/* Check constructors/destructors are called in containers. */ #include #include #include #include #include #include #if __cplusplus >= 201103L #include #include #include #include #endif #include "target-flex-common.h" struct indirect_counter { typedef int counter_value_type; counter_value_type *_count_ptr; indirect_counter(counter_value_type *count_ptr) BL_NOEXCEPT : _count_ptr(count_ptr) { ++(*_count_ptr); } indirect_counter(const indirect_counter& other) BL_NOEXCEPT : _count_ptr(other._count_ptr) { ++(*_count_ptr); } /* Don't declare a move constructor, we want to copy no matter what. */ ~indirect_counter() { --(*_count_ptr); } }; bool operator==(indirect_counter const& lhs, indirect_counter const& rhs) BL_NOEXCEPT { return lhs._count_ptr == rhs._count_ptr; } bool operator<(indirect_counter const& lhs, indirect_counter const& rhs) BL_NOEXCEPT { return lhs._count_ptr < rhs._count_ptr; } #if __cplusplus >= 201103L template<> struct std::hash { std::size_t operator()(const indirect_counter& ic) const noexcept { return std::hash{}(ic._count_ptr); } }; #endif /* Not a container, just a sanity check really. */ bool automatic_lifetime_test() { bool ok; #pragma omp target map(from: ok) { bool inner_ok = true; int counter = 0; { indirect_counter c = indirect_counter(&counter); indirect_counter(static_cast(&counter)); } VERIFY (counter == 0); end: ok = inner_ok; } return ok; } bool vector_test() { bool ok; #pragma omp target map(from: ok) { bool inner_ok = true; int counter = 0; { std::vector vec(42, indirect_counter(&counter)); VERIFY (counter == 42); vec.resize(32, indirect_counter(&counter)); VERIFY (counter == 32); vec.push_back(indirect_counter(&counter)); VERIFY (counter == 33); vec.pop_back(); VERIFY (counter == 32); vec.pop_back(); VERIFY (counter == 31); vec.resize(100, indirect_counter(&counter)); VERIFY (counter == 100); } VERIFY (counter == 0); end: ok = inner_ok; } return ok; } bool deque_test() { bool ok; #pragma omp target map(from: ok) { bool inner_ok = true; int counter = 0; { std::deque vec(42, indirect_counter(&counter)); VERIFY (counter == 42); vec.resize(32, indirect_counter(&counter)); VERIFY (counter == 32); vec.push_back(indirect_counter(&counter)); VERIFY (counter == 33); vec.pop_back(); VERIFY (counter == 32); vec.pop_back(); VERIFY (counter == 31); vec.resize(100, indirect_counter(&counter)); VERIFY (counter == 100); } VERIFY (counter == 0); end: ok = inner_ok; } return ok; } bool list_test() { bool ok; #pragma omp target map(from: ok) { bool inner_ok = true; int counter = 0; { std::list list(42, indirect_counter(&counter)); VERIFY (counter == 42); list.resize(32, indirect_counter(&counter)); VERIFY (counter == 32); list.push_back(indirect_counter(&counter)); VERIFY (counter == 33); list.pop_back(); VERIFY (counter == 32); list.pop_back(); VERIFY (counter == 31); list.resize(100, indirect_counter(&counter)); VERIFY (counter == 100); } VERIFY (counter == 0); end: ok = inner_ok; } return ok; } bool map_test() { bool ok; #pragma omp target map(from: ok) { bool inner_ok = true; int counter = 0; { std::map map; map.insert(std::make_pair(1, indirect_counter(&counter))); VERIFY (counter == 1); map.insert(std::make_pair(1, indirect_counter(&counter))); VERIFY (counter == 1); map.insert(std::make_pair(2, indirect_counter(&counter))); VERIFY (counter == 2); } VERIFY (counter == 0); end: ok = inner_ok; } return ok; } bool set_test() { bool ok; #pragma omp target map(from: ok) { bool inner_ok = true; int counter0 = 0; int counter1 = 0; { std::set set; set.insert(indirect_counter(&counter0)); VERIFY (counter0 == 1); set.insert(indirect_counter(&counter0)); VERIFY (counter0 == 1); set.insert(indirect_counter(&counter1)); VERIFY (counter0 == 1 && counter1 == 1); } VERIFY (counter0 == 0 && counter1 == 0); end: ok = inner_ok; } return ok; } bool multimap_test() { bool ok; #pragma omp target map(from: ok) { bool inner_ok = true; int counter = 0; { std::multimap multimap; multimap.insert(std::make_pair(1, indirect_counter(&counter))); VERIFY (counter == 1); multimap.insert(std::make_pair(1, indirect_counter(&counter))); VERIFY (counter == 2); multimap.insert(std::make_pair(2, indirect_counter(&counter))); VERIFY (counter == 3); } VERIFY (counter == 0); end: ok = inner_ok; } return ok; } bool multiset_test() { bool ok; #pragma omp target map(from: ok) { bool inner_ok = true; int counter0 = 0; int counter1 = 0; { std::multiset multiset; multiset.insert(indirect_counter(&counter0)); VERIFY (counter0 == 1); multiset.insert(indirect_counter(&counter0)); VERIFY (counter0 == 2); multiset.insert(indirect_counter(&counter1)); VERIFY (counter0 == 2 && counter1 == 1); } VERIFY (counter0 == 0 && counter1 == 0); end: ok = inner_ok; } return ok; } #if __cplusplus >= 201103L bool array_test() { bool ok; #pragma omp target map(from: ok) { bool inner_ok = true; int counter = 0; { indirect_counter ic(&counter); std::array array{ic, ic, ic, ic, ic, ic, ic, ic, ic, ic}; VERIFY (counter == 11); } VERIFY (counter == 0); end: ok = inner_ok; } return ok; } bool forward_list_test() { bool ok; #pragma omp target map(from: ok) { bool inner_ok = true; int counter = 0; { std::forward_list forward_list(42, indirect_counter(&counter)); VERIFY (counter == 42); forward_list.resize(32, indirect_counter(&counter)); VERIFY (counter == 32); forward_list.push_front(indirect_counter(&counter)); VERIFY (counter == 33); forward_list.pop_front(); VERIFY (counter == 32); forward_list.pop_front(); VERIFY (counter == 31); forward_list.resize(100, indirect_counter(&counter)); VERIFY (counter == 100); } VERIFY (counter == 0); end: ok = inner_ok; } return ok; } bool unordered_map_test() { bool ok; #pragma omp target map(from: ok) { bool inner_ok = true; int counter = 0; { std::unordered_map unordered_map; unordered_map.insert({1, indirect_counter(&counter)}); VERIFY (counter == 1); unordered_map.insert({1, indirect_counter(&counter)}); VERIFY (counter == 1); unordered_map.insert({2, indirect_counter(&counter)}); VERIFY (counter == 2); } VERIFY (counter == 0); end: ok = inner_ok; } return ok; } bool unordered_set_test() { bool ok; #pragma omp target map(from: ok) { bool inner_ok = true; int counter0 = 0; int counter1 = 0; { std::unordered_set unordered_set; unordered_set.insert(indirect_counter(&counter0)); VERIFY (counter0 == 1); unordered_set.insert(indirect_counter(&counter0)); VERIFY (counter0 == 1); unordered_set.insert(indirect_counter(&counter1)); VERIFY (counter0 == 1 && counter1 == 1); } VERIFY (counter0 == 0 && counter1 == 0); end: ok = inner_ok; } return ok; } bool unordered_multimap_test() { bool ok; #pragma omp target map(from: ok) { bool inner_ok = true; int counter = 0; { std::unordered_multimap unordered_multimap; unordered_multimap.insert({1, indirect_counter(&counter)}); VERIFY (counter == 1); unordered_multimap.insert({1, indirect_counter(&counter)}); VERIFY (counter == 2); unordered_multimap.insert({2, indirect_counter(&counter)}); VERIFY (counter == 3); } VERIFY (counter == 0); end: ok = inner_ok; } return ok; } bool unordered_multiset_test() { bool ok; #pragma omp target map(from: ok) { bool inner_ok = true; int counter0 = 0; int counter1 = 0; { std::unordered_multiset unordered_multiset; unordered_multiset.insert(indirect_counter(&counter0)); VERIFY (counter0 == 1); unordered_multiset.insert(indirect_counter(&counter0)); VERIFY (counter0 == 2); unordered_multiset.insert(indirect_counter(&counter1)); VERIFY (counter0 == 2 && counter1 == 1); } VERIFY (counter0 == 0 && counter1 == 0); end: ok = inner_ok; } return ok; } #else bool array_test() { return true; } bool forward_list_test() { return true; } bool unordered_map_test() { return true; } bool unordered_set_test() { return true; } bool unordered_multimap_test() { return true; } bool unordered_multiset_test() { return true; } #endif int main() { const bool auto_res = automatic_lifetime_test(); const bool vec_res = vector_test(); const bool deque_res = deque_test(); const bool list_res = list_test(); const bool map_res = map_test(); const bool set_res = set_test(); const bool multimap_res = multimap_test(); const bool multiset_res = multiset_test(); const bool array_res = array_test(); const bool forward_list_res = forward_list_test(); const bool unordered_map_res = unordered_map_test(); const bool unordered_set_res = unordered_set_test(); const bool unordered_multimap_res = unordered_multimap_test(); const bool unordered_multiset_res = unordered_multiset_test(); std::printf("sanity check : %s\n", auto_res ? "PASS" : "FAIL"); std::printf("vector : %s\n", vec_res ? "PASS" : "FAIL"); std::printf("deque : %s\n", deque_res ? "PASS" : "FAIL"); std::printf("list : %s\n", list_res ? "PASS" : "FAIL"); std::printf("map : %s\n", map_res ? "PASS" : "FAIL"); std::printf("set : %s\n", set_res ? "PASS" : "FAIL"); std::printf("multimap : %s\n", multimap_res ? "PASS" : "FAIL"); std::printf("multiset : %s\n", multiset_res ? "PASS" : "FAIL"); std::printf("array : %s\n", array_res ? "PASS" : "FAIL"); std::printf("forward_list : %s\n", forward_list_res ? "PASS" : "FAIL"); std::printf("unordered_map : %s\n", unordered_map_res ? "PASS" : "FAIL"); std::printf("unordered_set : %s\n", unordered_set_res ? "PASS" : "FAIL"); std::printf("unordered_multimap: %s\n", unordered_multimap_res ? "PASS" : "FAIL"); std::printf("unordered_multiset: %s\n", unordered_multiset_res ? "PASS" : "FAIL"); const bool ok = auto_res && vec_res && deque_res && list_res && map_res && set_res && multimap_res && multiset_res && array_res && forward_list_res && unordered_map_res && unordered_set_res && unordered_multimap_res && unordered_multiset_res; return ok ? 0 : 1; }