diff --git a/libcxx/test/std/containers/associative/map/map.cons/assign_initializer_list.pass.cpp b/libcxx/test/std/containers/associative/map/map.cons/assign_initializer_list.pass.cpp --- a/libcxx/test/std/containers/associative/map/map.cons/assign_initializer_list.pass.cpp +++ b/libcxx/test/std/containers/associative/map/map.cons/assign_initializer_list.pass.cpp @@ -21,6 +21,8 @@ #include "min_allocator.h" #include "test_allocator.h" +test_allocator_statistics alloc_stats; + void test_basic() { { typedef std::pair V; @@ -76,15 +78,15 @@ void duplicate_keys_test() { typedef std::map, test_allocator > > Map; { - LIBCPP_ASSERT(test_alloc_base::alloc_count == 0); - Map s = {{1, 0}, {2, 0}, {3, 0}}; - LIBCPP_ASSERT(test_alloc_base::alloc_count == 3); + LIBCPP_ASSERT(alloc_stats.alloc_count == 0); + Map s({{1, 0}, {2, 0}, {3, 0}}, std::less(), test_allocator >(&alloc_stats)); + LIBCPP_ASSERT(alloc_stats.alloc_count == 3); s = {{4, 0}, {4, 0}, {4, 0}, {4, 0}}; - LIBCPP_ASSERT(test_alloc_base::alloc_count == 1); + LIBCPP_ASSERT(alloc_stats.alloc_count == 1); assert(s.size() == 1); assert(s.begin()->first == 4); } - LIBCPP_ASSERT(test_alloc_base::alloc_count == 0); + LIBCPP_ASSERT(alloc_stats.alloc_count == 0); } int main(int, char**) diff --git a/libcxx/test/std/containers/associative/set/set.cons/assign_initializer_list.pass.cpp b/libcxx/test/std/containers/associative/set/set.cons/assign_initializer_list.pass.cpp --- a/libcxx/test/std/containers/associative/set/set.cons/assign_initializer_list.pass.cpp +++ b/libcxx/test/std/containers/associative/set/set.cons/assign_initializer_list.pass.cpp @@ -21,6 +21,8 @@ #include "min_allocator.h" #include "test_allocator.h" +test_allocator_statistics alloc_stats; + void basic_test() { { typedef std::set C; @@ -57,15 +59,15 @@ void duplicate_keys_test() { typedef std::set, test_allocator > Set; { - LIBCPP_ASSERT(test_alloc_base::alloc_count == 0); - Set s = {1, 2, 3}; - LIBCPP_ASSERT(test_alloc_base::alloc_count == 3); + LIBCPP_ASSERT(alloc_stats.alloc_count == 0); + Set s({1, 2, 3}, std::less(), test_allocator(&alloc_stats)); + LIBCPP_ASSERT(alloc_stats.alloc_count == 3); s = {4, 4, 4, 4, 4}; - LIBCPP_ASSERT(test_alloc_base::alloc_count == 1); + LIBCPP_ASSERT(alloc_stats.alloc_count == 1); assert(s.size() == 1); assert(*s.begin() == 4); } - LIBCPP_ASSERT(test_alloc_base::alloc_count == 0); + LIBCPP_ASSERT(alloc_stats.alloc_count == 0); } int main(int, char**) { diff --git a/libcxx/test/std/containers/container.requirements/container.requirements.general/allocator_move.pass.cpp b/libcxx/test/std/containers/container.requirements/container.requirements.general/allocator_move.pass.cpp --- a/libcxx/test/std/containers/container.requirements/container.requirements.general/allocator_move.pass.cpp +++ b/libcxx/test/std/containers/container.requirements/container.requirements.general/allocator_move.pass.cpp @@ -25,29 +25,31 @@ #include "test_macros.h" #include "test_allocator.h" +test_allocator_statistics alloc_stats; + template void test(int expected_num_allocs = 1) { { - test_alloc_base::clear(); + alloc_stats.clear(); using AllocT = typename C::allocator_type; - C v(AllocT(42, 101)); + C v(AllocT(42, 101, &alloc_stats)); - assert(test_alloc_base::count == expected_num_allocs); + assert(alloc_stats.count == expected_num_allocs); - const int num_stored_allocs = test_alloc_base::count; + const int num_stored_allocs = alloc_stats.count; { const AllocT& a = v.get_allocator(); - assert(test_alloc_base::count == 1 + num_stored_allocs); + assert(alloc_stats.count == 1 + num_stored_allocs); assert(a.get_data() == 42); assert(a.get_id() == 101); } - assert(test_alloc_base::count == num_stored_allocs); - test_alloc_base::clear_ctor_counters(); + assert(alloc_stats.count == num_stored_allocs); + alloc_stats.clear_ctor_counters(); C v2 = std::move(v); - assert(test_alloc_base::count == num_stored_allocs * 2); - assert(test_alloc_base::copied == 0); - assert(test_alloc_base::moved == num_stored_allocs); + assert(alloc_stats.count == num_stored_allocs * 2); + assert(alloc_stats.copied == 0); + assert(alloc_stats.moved == num_stored_allocs); { const AllocT& a = v.get_allocator(); assert(a.get_id() == test_alloc_base::moved_value); diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_back_exception_safety.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_back_exception_safety.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_back_exception_safety.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_back_exception_safety.pass.cpp @@ -16,6 +16,8 @@ #include "test_allocator.h" #include +test_allocator_statistics alloc_stats; + // Flag that makes the copy constructor for CMyClass throw an exception static bool gCopyConstructorShouldThow = false; @@ -87,10 +89,10 @@ { typedef std::deque > C; - C vec; - C vec2(vec); + C vec((test_allocator(&alloc_stats))); + C vec2(vec, test_allocator(&alloc_stats)); - C::allocator_type::throw_after = 1; + alloc_stats.throw_after = 1; try { vec.push_back(instance); assert(false); diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_front_exception_safety.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_front_exception_safety.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_front_exception_safety.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_front_exception_safety.pass.cpp @@ -16,6 +16,8 @@ #include "test_macros.h" #include "test_allocator.h" +test_allocator_statistics alloc_stats; + // Flag that makes the copy constructor for CMyClass throw an exception static bool gCopyConstructorShouldThow = false; @@ -87,10 +89,10 @@ { typedef std::deque > C; - C vec; - C vec2(vec); + C vec((test_allocator(&alloc_stats))); + C vec2(vec, test_allocator(&alloc_stats)); - C::allocator_type::throw_after = 1; + alloc_stats.throw_after = 1; try { vec.push_front(instance); assert(false); diff --git a/libcxx/test/std/containers/sequences/vector.bool/move.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/move.pass.cpp --- a/libcxx/test/std/containers/sequences/vector.bool/move.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/move.pass.cpp @@ -18,11 +18,13 @@ #include "test_allocator.h" #include "min_allocator.h" +test_allocator_statistics alloc_stats; + int main(int, char**) { { - std::vector > l(test_allocator(5)); - std::vector > lo(test_allocator(5)); + std::vector > l(test_allocator(5, &alloc_stats)); + std::vector > lo(test_allocator(5, &alloc_stats)); for (int i = 1; i <= 3; ++i) { l.push_back(true); @@ -60,24 +62,24 @@ assert(l2.get_allocator() == lo.get_allocator()); } { - test_alloc_base::clear(); + alloc_stats.clear(); using Vect = std::vector >; using AllocT = Vect::allocator_type; - Vect v(test_allocator(42, 101)); - assert(test_alloc_base::count == 1); + Vect v(test_allocator(42, 101, &alloc_stats)); + assert(alloc_stats.count == 1); { const AllocT& a = v.get_allocator(); - assert(test_alloc_base::count == 2); + assert(alloc_stats.count == 2); assert(a.get_data() == 42); assert(a.get_id() == 101); } - assert(test_alloc_base::count == 1); - test_alloc_base::clear_ctor_counters(); + assert(alloc_stats.count == 1); + alloc_stats.clear_ctor_counters(); Vect v2 = std::move(v); - assert(test_alloc_base::count == 2); - assert(test_alloc_base::copied == 0); - assert(test_alloc_base::moved == 1); + assert(alloc_stats.count == 2); + assert(alloc_stats.copied == 0); + assert(alloc_stats.moved == 1); { const AllocT& a = v.get_allocator(); assert(a.get_id() == test_alloc_base::moved_value); diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/move.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/move.pass.cpp --- a/libcxx/test/std/containers/sequences/vector/vector.cons/move.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/move.pass.cpp @@ -21,11 +21,13 @@ #include "min_allocator.h" #include "asan_testing.h" +test_allocator_statistics alloc_stats; + int main(int, char**) { { - std::vector > l(test_allocator(5)); - std::vector > lo(test_allocator(5)); + std::vector > l(test_allocator(5, &alloc_stats)); + std::vector > lo(test_allocator(5, &alloc_stats)); assert(is_contiguous_container_asan_correct(l)); assert(is_contiguous_container_asan_correct(lo)); for (int i = 1; i <= 3; ++i) @@ -100,24 +102,24 @@ assert(is_contiguous_container_asan_correct(c2)); } { - test_alloc_base::clear(); + alloc_stats.clear(); using Vect = std::vector >; - Vect v(test_allocator(42, 101)); - assert(test_alloc_base::count == 1); - assert(test_alloc_base::copied == 1); - assert(test_alloc_base::moved == 0); + Vect v(test_allocator(42, 101, &alloc_stats)); + assert(alloc_stats.count == 1); + assert(alloc_stats.copied == 1); + assert(alloc_stats.moved == 0); { const test_allocator& a = v.get_allocator(); assert(a.get_data() == 42); assert(a.get_id() == 101); } - assert(test_alloc_base::count == 1); - test_alloc_base::clear_ctor_counters(); + assert(alloc_stats.count == 1); + alloc_stats.clear_ctor_counters(); Vect v2 = std::move(v); - assert(test_alloc_base::count == 2); - assert(test_alloc_base::copied == 0); - assert(test_alloc_base::moved == 1); + assert(alloc_stats.count == 2); + assert(alloc_stats.copied == 0); + assert(alloc_stats.moved == 1); { const test_allocator& a = v.get_allocator(); assert(a.get_id() == test_alloc_base::moved_value); diff --git a/libcxx/test/std/re/re.results/re.results.const/move.pass.cpp b/libcxx/test/std/re/re.results/re.results.const/move.pass.cpp --- a/libcxx/test/std/re/re.results/re.results.const/move.pass.cpp +++ b/libcxx/test/std/re/re.results/re.results.const/move.pass.cpp @@ -19,6 +19,8 @@ #include "test_macros.h" #include "test_allocator.h" +test_allocator_statistics alloc_stats; + template void test(const Allocator& a) @@ -42,11 +44,11 @@ test(std::allocator >()); #endif - test (test_allocator >(3)); - assert(test_alloc_base::moved == 1); + test (test_allocator >(3, &alloc_stats)); + assert(alloc_stats.moved == 1); #ifndef TEST_HAS_NO_WIDE_CHARACTERS - test(test_allocator >(3)); - assert(test_alloc_base::moved == 2); + test(test_allocator >(3, &alloc_stats)); + assert(alloc_stats.moved == 2); #endif return 0; diff --git a/libcxx/test/std/strings/basic.string/string.capacity/capacity.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/capacity.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.capacity/capacity.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.capacity/capacity.pass.cpp @@ -18,11 +18,13 @@ #include "test_macros.h" +test_allocator_statistics alloc_stats; + template void test(S s) { - S::allocator_type::throw_after = 0; + alloc_stats.throw_after = 0; #ifndef TEST_HAS_NO_EXCEPTIONS try #endif @@ -37,14 +39,14 @@ assert(false); } #endif - S::allocator_type::throw_after = INT_MAX; + alloc_stats.throw_after = INT_MAX; } int main(int, char**) { { typedef std::basic_string, test_allocator > S; - S s; + S s((test_allocator(&alloc_stats))); test(s); s.assign(10, 'a'); s.erase(5); diff --git a/libcxx/test/std/strings/basic.string/string.cons/move_alloc.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/move_alloc.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.cons/move_alloc.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.cons/move_alloc.pass.cpp @@ -19,6 +19,7 @@ #include "test_allocator.h" #include "min_allocator.h" +test_allocator_statistics alloc_stats; template void @@ -44,12 +45,12 @@ #elif TEST_STD_VER >= 11 static_assert((noexcept(S()) == std::is_nothrow_move_constructible::value), "" ); #endif - test(S(), A(3)); - test(S("1"), A(5)); - test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A(7)); + test(S(), A(3, &alloc_stats)); + test(S("1"), A(5, &alloc_stats)); + test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A(7, &alloc_stats)); } - int alloc_count = test_alloc_base::alloc_count; + int alloc_count = alloc_stats.alloc_count; { typedef test_allocator A; typedef std::basic_string, A> S; @@ -58,10 +59,10 @@ #elif TEST_STD_VER >= 11 static_assert((noexcept(S()) == std::is_nothrow_move_constructible::value), "" ); #endif - S s1 ( "Twas brillig, and the slivy toves did gyre and gymbal in the wabe" ); - S s2 (std::move(s1), A(1)); + S s1 ( "Twas brillig, and the slivy toves did gyre and gymbal in the wabe", A(&alloc_stats)); + S s2 (std::move(s1), A(1, &alloc_stats)); } - assert ( test_alloc_base::alloc_count == alloc_count ); + assert ( alloc_stats.alloc_count == alloc_count ); { typedef min_allocator A; typedef std::basic_string, A> S; diff --git a/libcxx/test/std/thread/futures/futures.promise/alloc_ctor.pass.cpp b/libcxx/test/std/thread/futures/futures.promise/alloc_ctor.pass.cpp --- a/libcxx/test/std/thread/futures/futures.promise/alloc_ctor.pass.cpp +++ b/libcxx/test/std/thread/futures/futures.promise/alloc_ctor.pass.cpp @@ -23,33 +23,35 @@ #include "test_allocator.h" #include "min_allocator.h" +test_allocator_statistics alloc_stats; + int main(int, char**) { - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); { - std::promise p(std::allocator_arg, test_allocator(42)); - assert(test_alloc_base::alloc_count == 1); + std::promise p(std::allocator_arg, test_allocator(42, &alloc_stats)); + assert(alloc_stats.alloc_count == 1); std::future f = p.get_future(); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); { - std::promise p(std::allocator_arg, test_allocator(42)); - assert(test_alloc_base::alloc_count == 1); + std::promise p(std::allocator_arg, test_allocator(42, &alloc_stats)); + assert(alloc_stats.alloc_count == 1); std::future f = p.get_future(); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); { - std::promise p(std::allocator_arg, test_allocator(42)); - assert(test_alloc_base::alloc_count == 1); + std::promise p(std::allocator_arg, test_allocator(42, &alloc_stats)); + assert(alloc_stats.alloc_count == 1); std::future f = p.get_future(); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); // Test with a minimal allocator { std::promise p(std::allocator_arg, bare_allocator()); diff --git a/libcxx/test/std/thread/futures/futures.promise/move_assign.pass.cpp b/libcxx/test/std/thread/futures/futures.promise/move_assign.pass.cpp --- a/libcxx/test/std/thread/futures/futures.promise/move_assign.pass.cpp +++ b/libcxx/test/std/thread/futures/futures.promise/move_assign.pass.cpp @@ -21,17 +21,19 @@ #include "test_macros.h" #include "test_allocator.h" +test_allocator_statistics alloc_stats; + int main(int, char**) { - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); { - std::promise p0(std::allocator_arg, test_allocator()); - std::promise p(std::allocator_arg, test_allocator()); - assert(test_alloc_base::alloc_count == 2); + std::promise p0(std::allocator_arg, test_allocator(&alloc_stats)); + std::promise p(std::allocator_arg, test_allocator(&alloc_stats)); + assert(alloc_stats.alloc_count == 2); p = std::move(p0); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); std::future f = p.get_future(); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); #ifndef TEST_HAS_NO_EXCEPTIONS try @@ -44,17 +46,17 @@ assert(e.code() == make_error_code(std::future_errc::no_state)); } #endif - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); { - std::promise p0(std::allocator_arg, test_allocator()); - std::promise p(std::allocator_arg, test_allocator()); - assert(test_alloc_base::alloc_count == 2); + std::promise p0(std::allocator_arg, test_allocator(&alloc_stats)); + std::promise p(std::allocator_arg, test_allocator(&alloc_stats)); + assert(alloc_stats.alloc_count == 2); p = std::move(p0); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); std::future f = p.get_future(); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); #ifndef TEST_HAS_NO_EXCEPTIONS try @@ -67,17 +69,17 @@ assert(e.code() == make_error_code(std::future_errc::no_state)); } #endif - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); { - std::promise p0(std::allocator_arg, test_allocator()); - std::promise p(std::allocator_arg, test_allocator()); - assert(test_alloc_base::alloc_count == 2); + std::promise p0(std::allocator_arg, test_allocator(&alloc_stats)); + std::promise p(std::allocator_arg, test_allocator(&alloc_stats)); + assert(alloc_stats.alloc_count == 2); p = std::move(p0); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); std::future f = p.get_future(); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); #ifndef TEST_HAS_NO_EXCEPTIONS try @@ -90,9 +92,9 @@ assert(e.code() == make_error_code(std::future_errc::no_state)); } #endif - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); return 0; } diff --git a/libcxx/test/std/thread/futures/futures.promise/move_ctor.pass.cpp b/libcxx/test/std/thread/futures/futures.promise/move_ctor.pass.cpp --- a/libcxx/test/std/thread/futures/futures.promise/move_ctor.pass.cpp +++ b/libcxx/test/std/thread/futures/futures.promise/move_ctor.pass.cpp @@ -21,15 +21,17 @@ #include "test_macros.h" #include "test_allocator.h" +test_allocator_statistics alloc_stats; + int main(int, char**) { - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); { - std::promise p0(std::allocator_arg, test_allocator()); + std::promise p0(std::allocator_arg, test_allocator(&alloc_stats)); std::promise p(std::move(p0)); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); std::future f = p.get_future(); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); #ifndef TEST_HAS_NO_EXCEPTIONS try @@ -41,16 +43,16 @@ { assert(e.code() == make_error_code(std::future_errc::no_state)); } - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); #endif } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); { - std::promise p0(std::allocator_arg, test_allocator()); + std::promise p0(std::allocator_arg, test_allocator(&alloc_stats)); std::promise p(std::move(p0)); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); std::future f = p.get_future(); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); #ifndef TEST_HAS_NO_EXCEPTIONS try @@ -62,16 +64,16 @@ { assert(e.code() == make_error_code(std::future_errc::no_state)); } - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); #endif } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); { - std::promise p0(std::allocator_arg, test_allocator()); + std::promise p0(std::allocator_arg, test_allocator(&alloc_stats)); std::promise p(std::move(p0)); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); std::future f = p.get_future(); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); #ifndef TEST_HAS_NO_EXCEPTIONS try @@ -83,10 +85,10 @@ { assert(e.code() == make_error_code(std::future_errc::no_state)); } - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); #endif } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); return 0; } diff --git a/libcxx/test/std/thread/futures/futures.promise/swap.pass.cpp b/libcxx/test/std/thread/futures/futures.promise/swap.pass.cpp --- a/libcxx/test/std/thread/futures/futures.promise/swap.pass.cpp +++ b/libcxx/test/std/thread/futures/futures.promise/swap.pass.cpp @@ -23,65 +23,67 @@ #include "test_macros.h" #include "test_allocator.h" +test_allocator_statistics alloc_stats; + int main(int, char**) { - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); { - std::promise p0(std::allocator_arg, test_allocator()); - std::promise p(std::allocator_arg, test_allocator()); - assert(test_alloc_base::alloc_count == 2); + std::promise p0(std::allocator_arg, test_allocator(&alloc_stats)); + std::promise p(std::allocator_arg, test_allocator(&alloc_stats)); + assert(alloc_stats.alloc_count == 2); p.swap(p0); - assert(test_alloc_base::alloc_count == 2); + assert(alloc_stats.alloc_count == 2); std::future f = p.get_future(); - assert(test_alloc_base::alloc_count == 2); + assert(alloc_stats.alloc_count == 2); assert(f.valid()); f = p0.get_future(); assert(f.valid()); - assert(test_alloc_base::alloc_count == 2); + assert(alloc_stats.alloc_count == 2); } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); { - std::promise p0(std::allocator_arg, test_allocator()); - std::promise p(std::allocator_arg, test_allocator()); - assert(test_alloc_base::alloc_count == 2); + std::promise p0(std::allocator_arg, test_allocator(&alloc_stats)); + std::promise p(std::allocator_arg, test_allocator(&alloc_stats)); + assert(alloc_stats.alloc_count == 2); swap(p, p0); - assert(test_alloc_base::alloc_count == 2); + assert(alloc_stats.alloc_count == 2); std::future f = p.get_future(); - assert(test_alloc_base::alloc_count == 2); + assert(alloc_stats.alloc_count == 2); assert(f.valid()); f = p0.get_future(); assert(f.valid()); - assert(test_alloc_base::alloc_count == 2); + assert(alloc_stats.alloc_count == 2); } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); { - std::promise p0(std::allocator_arg, test_allocator()); + std::promise p0(std::allocator_arg, test_allocator(&alloc_stats)); std::promise p; - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); p.swap(p0); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); std::future f = p.get_future(); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); f = p0.get_future(); assert(f.valid()); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); { - std::promise p0(std::allocator_arg, test_allocator()); + std::promise p0(std::allocator_arg, test_allocator(&alloc_stats)); std::promise p; - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); swap(p, p0); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); std::future f = p.get_future(); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); f = p0.get_future(); assert(f.valid()); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); return 0; } diff --git a/libcxx/test/std/thread/futures/futures.shared_future/dtor.pass.cpp b/libcxx/test/std/thread/futures/futures.shared_future/dtor.pass.cpp --- a/libcxx/test/std/thread/futures/futures.shared_future/dtor.pass.cpp +++ b/libcxx/test/std/thread/futures/futures.shared_future/dtor.pass.cpp @@ -22,51 +22,53 @@ #include "test_macros.h" #include "test_allocator.h" +test_allocator_statistics alloc_stats; + int main(int, char**) { - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); { typedef int T; std::shared_future f; { - std::promise p(std::allocator_arg, test_allocator()); - assert(test_alloc_base::alloc_count == 1); + std::promise p(std::allocator_arg, test_allocator(&alloc_stats)); + assert(alloc_stats.alloc_count == 1); f = p.get_future(); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); } - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); { typedef int& T; std::shared_future f; { - std::promise p(std::allocator_arg, test_allocator()); - assert(test_alloc_base::alloc_count == 1); + std::promise p(std::allocator_arg, test_allocator(&alloc_stats)); + assert(alloc_stats.alloc_count == 1); f = p.get_future(); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); } - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); { typedef void T; std::shared_future f; { - std::promise p(std::allocator_arg, test_allocator()); - assert(test_alloc_base::alloc_count == 1); + std::promise p(std::allocator_arg, test_allocator(&alloc_stats)); + assert(alloc_stats.alloc_count == 1); f = p.get_future(); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); } - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); return 0; } diff --git a/libcxx/test/std/thread/futures/futures.task/futures.task.members/ctor_func_alloc.pass.cpp b/libcxx/test/std/thread/futures/futures.task/futures.task.members/ctor_func_alloc.pass.cpp --- a/libcxx/test/std/thread/futures/futures.task/futures.task.members/ctor_func_alloc.pass.cpp +++ b/libcxx/test/std/thread/futures/futures.task/futures.task.members/ctor_func_alloc.pass.cpp @@ -25,6 +25,8 @@ #include "test_allocator.h" #include "min_allocator.h" +test_allocator_statistics alloc_stats; + class A { long data_; @@ -49,8 +51,8 @@ { { std::packaged_task p(std::allocator_arg, - test_allocator(), A(5)); - assert(test_alloc_base::alloc_count > 0); + test_allocator(&alloc_stats), A(5)); + assert(alloc_stats.alloc_count > 0); assert(p.valid()); std::future f = p.get_future(); p(3, 'a'); @@ -58,14 +60,14 @@ assert(A::n_copies == 0); assert(A::n_moves > 0); } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); A::n_copies = 0; A::n_moves = 0; { A a(5); std::packaged_task p(std::allocator_arg, - test_allocator(), a); - assert(test_alloc_base::alloc_count > 0); + test_allocator(&alloc_stats), a); + assert(alloc_stats.alloc_count > 0); assert(p.valid()); std::future f = p.get_future(); p(3, 'a'); @@ -73,31 +75,31 @@ assert(A::n_copies > 0); assert(A::n_moves >= 0); } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); A::n_copies = 0; A::n_moves = 0; { A a(5); - std::packaged_task p(std::allocator_arg, test_allocator(), &func); - assert(test_alloc_base::alloc_count > 0); + std::packaged_task p(std::allocator_arg, test_allocator(&alloc_stats), &func); + assert(alloc_stats.alloc_count > 0); assert(p.valid()); std::future f = p.get_future(); p(4); assert(f.get() == 4); } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); A::n_copies = 0; A::n_moves = 0; { A a(5); - std::packaged_task p(std::allocator_arg, test_allocator(), func); - assert(test_alloc_base::alloc_count > 0); + std::packaged_task p(std::allocator_arg, test_allocator(&alloc_stats), func); + assert(alloc_stats.alloc_count > 0); assert(p.valid()); std::future f = p.get_future(); p(4); assert(f.get() == 4); } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); A::n_copies = 0; A::n_moves = 0; { diff --git a/libcxx/test/std/thread/futures/futures.unique_future/dtor.pass.cpp b/libcxx/test/std/thread/futures/futures.unique_future/dtor.pass.cpp --- a/libcxx/test/std/thread/futures/futures.unique_future/dtor.pass.cpp +++ b/libcxx/test/std/thread/futures/futures.unique_future/dtor.pass.cpp @@ -22,51 +22,53 @@ #include "test_macros.h" #include "test_allocator.h" +test_allocator_statistics alloc_stats; + int main(int, char**) { - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); { typedef int T; std::future f; { - std::promise p(std::allocator_arg, test_allocator()); - assert(test_alloc_base::alloc_count == 1); + std::promise p(std::allocator_arg, test_allocator(&alloc_stats)); + assert(alloc_stats.alloc_count == 1); f = p.get_future(); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); } - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); { typedef int& T; std::future f; { - std::promise p(std::allocator_arg, test_allocator()); - assert(test_alloc_base::alloc_count == 1); + std::promise p(std::allocator_arg, test_allocator(&alloc_stats)); + assert(alloc_stats.alloc_count == 1); f = p.get_future(); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); } - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); { typedef void T; std::future f; { - std::promise p(std::allocator_arg, test_allocator()); - assert(test_alloc_base::alloc_count == 1); + std::promise p(std::allocator_arg, test_allocator(&alloc_stats)); + assert(alloc_stats.alloc_count == 1); f = p.get_future(); - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); } - assert(test_alloc_base::alloc_count == 1); + assert(alloc_stats.alloc_count == 1); assert(f.valid()); } - assert(test_alloc_base::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); return 0; } diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp --- a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp @@ -25,6 +25,7 @@ #include "count_new.h" #include "../function_types.h" +test_allocator_statistics alloc_stats; #if TEST_STD_VER >= 11 struct RValueCallable { @@ -69,7 +70,7 @@ std::function f2(std::allocator_arg, alloc, target); // The allocator may not fit in the small object buffer, if we allocated // check it was done via the allocator. - assert(globalMemCounter.checkOutstandingNewEq(test_alloc_base::alloc_count)); + assert(globalMemCounter.checkOutstandingNewEq(alloc_stats.alloc_count)); assert(f2.template target()); assert(*f2.template target() == target); assert(f2.template target() == 0); @@ -86,7 +87,7 @@ TargetType target = &MemFunClass::foo; assert(globalMemCounter.checkOutstandingNewEq(0)); std::function f2(std::allocator_arg, alloc, target); - assert(globalMemCounter.checkOutstandingNewEq(test_alloc_base::alloc_count)); + assert(globalMemCounter.checkOutstandingNewEq(alloc_stats.alloc_count)); assert(f2.template target()); assert(*f2.template target() == target); assert(f2.template target() == 0); @@ -119,7 +120,7 @@ test_for_alloc(bare_alloc); } { - non_default_test_allocator non_default_alloc(42); + non_default_test_allocator non_default_alloc(42, &alloc_stats); test_for_alloc(non_default_alloc); } #if TEST_STD_VER >= 11 diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_allocator.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_allocator.pass.cpp --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_allocator.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_allocator.pass.cpp @@ -17,6 +17,8 @@ #include "test_allocator.h" #include "min_allocator.h" +test_allocator_statistics alloc_stats; + struct A { static int count; @@ -31,7 +33,7 @@ int main(int, char**) { { - std::shared_ptr p(nullptr, test_deleter(3), test_allocator(5)); + std::shared_ptr p(nullptr, test_deleter(3), test_allocator(5, &alloc_stats)); assert(A::count == 0); assert(p.use_count() == 1); assert(p.get() == 0); @@ -42,14 +44,14 @@ assert(d); assert(d->state() == 3); #endif - assert(test_allocator::count == 1); - assert(test_allocator::alloc_count == 1); + assert(alloc_stats.count == 1); + assert(alloc_stats.alloc_count == 1); } assert(A::count == 0); assert(test_deleter::count == 0); assert(test_deleter::dealloc_count == 1); - assert(test_allocator::count == 0); - assert(test_allocator::alloc_count == 0); + assert(alloc_stats.count == 0); + assert(alloc_stats.alloc_count == 0); test_deleter::dealloc_count = 0; // Test an allocator with a minimal interface { diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_allocator_throw.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_allocator_throw.pass.cpp --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_allocator_throw.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_allocator_throw.pass.cpp @@ -17,6 +17,8 @@ #include "deleter_types.h" #include "test_allocator.h" +test_allocator_statistics alloc_stats; + struct A { static int count; @@ -32,8 +34,8 @@ { try { - test_allocator::throw_after = 0; - std::shared_ptr p(nullptr, test_deleter(3), test_allocator(5)); + alloc_stats.throw_after = 0; + std::shared_ptr p(nullptr, test_deleter(3), test_allocator(5, &alloc_stats)); assert(false); } catch (std::bad_alloc&) @@ -41,8 +43,8 @@ assert(A::count == 0); assert(test_deleter::count == 0); assert(test_deleter::dealloc_count == 1); - assert(test_allocator::count == 0); - assert(test_allocator::alloc_count == 0); + assert(alloc_stats.count == 0); + assert(alloc_stats.alloc_count == 0); } return 0; diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator.pass.cpp --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator.pass.cpp @@ -17,6 +17,8 @@ #include "test_allocator.h" #include "min_allocator.h" +test_allocator_statistics alloc_stats; + struct A { static int count; @@ -64,7 +66,7 @@ { { A* ptr = new A; - std::shared_ptr p(ptr, test_deleter(3), test_allocator(5)); + std::shared_ptr p(ptr, test_deleter(3), test_allocator(5, &alloc_stats)); assert(A::count == 1); assert(p.use_count() == 1); assert(p.get() == ptr); @@ -75,14 +77,14 @@ assert(d); assert(d->state() == 3); #endif - assert(test_allocator::count == 1); - assert(test_allocator::alloc_count == 1); + assert(alloc_stats.count == 1); + assert(alloc_stats.alloc_count == 1); } assert(A::count == 0); assert(test_deleter::count == 0); assert(test_deleter::dealloc_count == 1); - assert(test_allocator::count == 0); - assert(test_allocator::alloc_count == 0); + assert(alloc_stats.count == 0); + assert(alloc_stats.alloc_count == 0); test_deleter::dealloc_count = 0; // Test an allocator with a minimal interface { diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator_throw.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator_throw.pass.cpp --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator_throw.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator_throw.pass.cpp @@ -17,6 +17,8 @@ #include "deleter_types.h" #include "test_allocator.h" +test_allocator_statistics alloc_stats; + struct A { static int count; @@ -33,17 +35,17 @@ A* ptr = new A; try { - test_allocator::throw_after = 0; - std::shared_ptr p(ptr, test_deleter(3), test_allocator(5)); + alloc_stats.throw_after = 0; + std::shared_ptr p(ptr, test_deleter(3), test_allocator(5, &alloc_stats)); assert(false); } catch (std::bad_alloc&) { - assert(A::count == 0); - assert(test_deleter::count == 0); + assert(alloc_stats.count == 0); + assert(alloc_stats.count == 0); assert(test_deleter::dealloc_count == 1); - assert(test_allocator::count == 0); - assert(test_allocator::alloc_count == 0); + assert(alloc_stats.count == 0); + assert(alloc_stats.alloc_count == 0); } return 0; diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp @@ -22,6 +22,7 @@ #include "min_allocator.h" int new_count = 0; +test_allocator_statistics alloc_stats; struct A { @@ -144,14 +145,14 @@ { int i = 67; char c = 'e'; - std::shared_ptr p = std::allocate_shared(test_allocator(54), i, c); - assert(test_allocator::alloc_count == 1); + std::shared_ptr p = std::allocate_shared(test_allocator(54, &alloc_stats), i, c); + assert(alloc_stats.alloc_count == 1); assert(A::count == 1); assert(p->get_int() == 67); assert(p->get_char() == 'e'); } assert(A::count == 0); - assert(test_allocator::alloc_count == 0); + assert(alloc_stats.alloc_count == 0); { int i = 67; char c = 'e'; diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.mod/reset_pointer_deleter_allocator.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.mod/reset_pointer_deleter_allocator.pass.cpp --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.mod/reset_pointer_deleter_allocator.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.mod/reset_pointer_deleter_allocator.pass.cpp @@ -18,6 +18,8 @@ #include "deleter_types.h" #include "test_allocator.h" +test_allocator_statistics alloc_stats; + struct B { static int count; @@ -46,7 +48,7 @@ { std::shared_ptr p(new B); A* ptr = new A; - p.reset(ptr, test_deleter(3), test_allocator(4)); + p.reset(ptr, test_deleter(3), test_allocator(4, &alloc_stats)); assert(A::count == 1); assert(B::count == 1); assert(p.use_count() == 1); @@ -58,18 +60,18 @@ assert(d); assert(d->state() == 3); #endif - assert(test_allocator::count == 1); - assert(test_allocator::alloc_count == 1); + assert(alloc_stats.count == 1); + assert(alloc_stats.alloc_count == 1); } assert(A::count == 0); assert(test_deleter::count == 0); assert(test_deleter::dealloc_count == 1); - assert(test_allocator::count == 0); - assert(test_allocator::alloc_count == 0); + assert(alloc_stats.count == 0); + assert(alloc_stats.alloc_count == 0); { std::shared_ptr p; A* ptr = new A; - p.reset(ptr, test_deleter(3), test_allocator(4)); + p.reset(ptr, test_deleter(3), test_allocator(4, &alloc_stats)); assert(A::count == 1); assert(B::count == 1); assert(p.use_count() == 1); @@ -81,14 +83,14 @@ assert(d); assert(d->state() == 3); #endif - assert(test_allocator::count == 1); - assert(test_allocator::alloc_count == 1); + assert(alloc_stats.count == 1); + assert(alloc_stats.alloc_count == 1); } assert(A::count == 0); assert(test_deleter::count == 0); assert(test_deleter::dealloc_count == 2); - assert(test_allocator::count == 0); - assert(test_allocator::alloc_count == 0); + assert(alloc_stats.count == 0); + assert(alloc_stats.alloc_count == 0); #if TEST_STD_VER > 14 { diff --git a/libcxx/test/support/test_allocator.h b/libcxx/test/support/test_allocator.h --- a/libcxx/test/support/test_allocator.h +++ b/libcxx/test/support/test_allocator.h @@ -26,23 +26,16 @@ return AT::max_size(a); } -class test_alloc_base { -protected: - static int time_to_throw; - -public: - static int throw_after; - static int count; - static int alloc_count; - static int copied; - static int moved; - static int converted; - - const static int destructed_value = -1; - const static int default_value = 0; - const static int moved_value = INT_MAX; - - static void clear() { +struct test_allocator_statistics { + int time_to_throw = 0; + int throw_after = INT_MAX; + int count = 0; + int alloc_count = 0; + int copied = 0; + int moved = 0; + int converted = 0; + + TEST_CONSTEXPR_CXX14 void clear() { assert(count == 0 && "clearing leaking allocator data?"); count = 0; time_to_throw = 0; @@ -51,25 +44,24 @@ clear_ctor_counters(); } - static void clear_ctor_counters() { + TEST_CONSTEXPR_CXX14 void clear_ctor_counters() { copied = 0; moved = 0; converted = 0; } }; -int test_alloc_base::count = 0; -int test_alloc_base::time_to_throw = 0; -int test_alloc_base::alloc_count = 0; -int test_alloc_base::throw_after = INT_MAX; -int test_alloc_base::copied = 0; -int test_alloc_base::moved = 0; -int test_alloc_base::converted = 0; +struct test_alloc_base { + TEST_CONSTEXPR static const int destructed_value = -1; + TEST_CONSTEXPR static const int moved_value = INT_MAX; +}; template -class test_allocator : public test_alloc_base { - int data_; // participates in equality - int id_; // unique identifier, doesn't participate in equality +class test_allocator { + int data_ = 0; // participates in equality + int id_ = 0; // unique identifier, doesn't participate in equality + test_allocator_statistics* stats_ = nullptr; + template friend class test_allocator; @@ -87,74 +79,113 @@ typedef test_allocator other; }; - test_allocator() TEST_NOEXCEPT : data_(0), id_(0) { ++count; } - explicit test_allocator(int i, int id = 0) TEST_NOEXCEPT : data_(i), id_(id) { ++count; } - test_allocator(const test_allocator& a) TEST_NOEXCEPT : data_(a.data_), id_(a.id_) { - ++count; - ++copied; - assert(a.data_ != destructed_value && a.id_ != destructed_value && "copying from destroyed allocator"); + TEST_CONSTEXPR test_allocator() TEST_NOEXCEPT = default; + + TEST_CONSTEXPR_CXX14 explicit test_allocator(test_allocator_statistics* stats) TEST_NOEXCEPT : stats_(stats) { + if (stats_ != nullptr) + ++stats_->count; + } + + TEST_CONSTEXPR explicit test_allocator(int data) TEST_NOEXCEPT : data_(data) {} + + TEST_CONSTEXPR_CXX14 explicit test_allocator(int data, test_allocator_statistics* stats) TEST_NOEXCEPT + : data_(data), stats_(stats) { + if (stats != nullptr) + ++stats_->count; + } + + TEST_CONSTEXPR explicit test_allocator(int data, int id) TEST_NOEXCEPT : data_(data), id_(id) {} + + TEST_CONSTEXPR_CXX14 explicit test_allocator(int data, int id, test_allocator_statistics* stats) TEST_NOEXCEPT + : data_(data), id_(id), stats_(stats) { + if (stats_ != nullptr) + ++stats_->count; } + + TEST_CONSTEXPR_CXX14 test_allocator(const test_allocator& a) TEST_NOEXCEPT + : data_(a.data_), id_(a.id_), stats_(a.stats_) { + assert(a.data_ != test_alloc_base::destructed_value && a.id_ != test_alloc_base::destructed_value && + "copying from destroyed allocator"); + if (stats_ != nullptr) { + ++stats_->count; + ++stats_->copied; + } + } + #if TEST_STD_VER >= 11 - test_allocator(test_allocator&& a) TEST_NOEXCEPT : data_(a.data_), id_(a.id_) { - ++count; - ++moved; - assert(a.data_ != destructed_value && a.id_ != destructed_value && "moving from destroyed allocator"); - a.data_ = moved_value; - a.id_ = moved_value; + TEST_CONSTEXPR_CXX14 test_allocator(test_allocator&& a) TEST_NOEXCEPT : data_(a.data_), id_(a.id_), stats_(a.stats_) { + if (stats_ != nullptr) { + ++stats_->count; + ++stats_->moved; + } + assert(a.data_ != test_alloc_base::destructed_value && a.id_ != test_alloc_base::destructed_value && + "moving from destroyed allocator"); + a.data_ = test_alloc_base::moved_value; + a.id_ = test_alloc_base::moved_value; } #endif + template - test_allocator(const test_allocator& a) TEST_NOEXCEPT : data_(a.data_), id_(a.id_) { - ++count; - ++converted; + TEST_CONSTEXPR_CXX14 test_allocator(const test_allocator& a) TEST_NOEXCEPT + : data_(a.data_), id_(a.id_), stats_(a.stats_) { + if (stats_ != nullptr) { + ++stats_->count; + ++stats_->converted; + } } - ~test_allocator() TEST_NOEXCEPT { - assert(data_ >= 0); - assert(id_ >= 0); - --count; - data_ = destructed_value; - id_ = destructed_value; + + TEST_CONSTEXPR_CXX20 ~test_allocator() TEST_NOEXCEPT { + assert(data_ != test_alloc_base::destructed_value); + assert(id_ != test_alloc_base::destructed_value); + if (stats_ != nullptr) + --stats_->count; + data_ = test_alloc_base::destructed_value; + id_ = test_alloc_base::destructed_value; } - pointer address(reference x) const { return &x; } - const_pointer address(const_reference x) const { return &x; } - pointer allocate(size_type n, const void* = 0) { - assert(data_ >= 0); - if (time_to_throw >= throw_after) { -#ifndef TEST_HAS_NO_EXCEPTIONS - throw std::bad_alloc(); -#else - std::terminate(); -#endif + + TEST_CONSTEXPR pointer address(reference x) const { return &x; } + TEST_CONSTEXPR const_pointer address(const_reference x) const { return &x; } + + TEST_CONSTEXPR_CXX14 pointer allocate(size_type n, const void* = 0) { + assert(data_ != test_alloc_base::destructed_value); + if (stats_ != nullptr) { + if (stats_->time_to_throw >= stats_->throw_after) + TEST_THROW(std::bad_alloc()); + ++stats_->time_to_throw; + ++stats_->alloc_count; } - ++time_to_throw; - ++alloc_count; - return (pointer)::operator new(n * sizeof(T)); + return std::allocator().allocate(n); } - void deallocate(pointer p, size_type) { - assert(data_ >= 0); - --alloc_count; - ::operator delete((void*)p); + + TEST_CONSTEXPR_CXX14 void deallocate(pointer p, size_type s) { + assert(data_ != test_alloc_base::destructed_value); + if (stats_ != nullptr) + --stats_->alloc_count; + std::allocator().deallocate(p, s); } - size_type max_size() const TEST_NOEXCEPT { return UINT_MAX / sizeof(T); } + + TEST_CONSTEXPR size_type max_size() const TEST_NOEXCEPT { return UINT_MAX / sizeof(T); } + #if TEST_STD_VER < 11 void construct(pointer p, const T& val) { ::new (static_cast(p)) T(val); } #else template - void construct(pointer p, U&& val) { + TEST_CONSTEXPR_CXX14 void construct(pointer p, U&& val) { ::new (static_cast(p)) T(std::forward(val)); } #endif - void destroy(pointer p) { p->~T(); } - friend bool operator==(const test_allocator& x, const test_allocator& y) { return x.data_ == y.data_; } - friend bool operator!=(const test_allocator& x, const test_allocator& y) { return !(x == y); } + TEST_CONSTEXPR_CXX14 void destroy(pointer p) { p->~T(); } + TEST_CONSTEXPR friend bool operator==(const test_allocator& x, const test_allocator& y) { return x.data_ == y.data_; } + TEST_CONSTEXPR friend bool operator!=(const test_allocator& x, const test_allocator& y) { return !(x == y); } - int get_data() const { return data_; } - int get_id() const { return id_; } + TEST_CONSTEXPR int get_data() const { return data_; } + TEST_CONSTEXPR int get_id() const { return id_; } }; template -class non_default_test_allocator : public test_alloc_base { - int data_; +class non_default_test_allocator { + int data_ = 0; + test_allocator_statistics* stats_ = nullptr; template friend class non_default_test_allocator; @@ -173,59 +204,71 @@ typedef non_default_test_allocator other; }; - // non_default_test_allocator() TEST_NOEXCEPT : data_(0) {++count;} - explicit non_default_test_allocator(int i) TEST_NOEXCEPT : data_(i) { ++count; } - non_default_test_allocator(const non_default_test_allocator& a) TEST_NOEXCEPT : data_(a.data_) { ++count; } + TEST_CONSTEXPR_CXX14 + explicit non_default_test_allocator(int i, test_allocator_statistics* stats = nullptr) TEST_NOEXCEPT + : data_(i), stats_(stats) { + if (stats_ != nullptr) { + ++stats_->count; + } + } + + TEST_CONSTEXPR_CXX14 + non_default_test_allocator(const non_default_test_allocator& a) TEST_NOEXCEPT : data_(a.data_), stats_(a.stats_) { + if (stats_ != nullptr) + ++stats_->count; + } + template - non_default_test_allocator(const non_default_test_allocator& a) TEST_NOEXCEPT : data_(a.data_) { - ++count; + TEST_CONSTEXPR_CXX14 non_default_test_allocator(const non_default_test_allocator& a) TEST_NOEXCEPT + : data_(a.data_), stats_(a.stats_) { + if (stats_ != nullptr) + ++stats_->count; } - ~non_default_test_allocator() TEST_NOEXCEPT { - assert(data_ >= 0); - --count; - data_ = -1; + + TEST_CONSTEXPR_CXX20 ~non_default_test_allocator() TEST_NOEXCEPT { + assert(data_ != test_alloc_base::destructed_value); + if (stats_ != nullptr) + --stats_->count; + data_ = test_alloc_base::destructed_value; } - pointer address(reference x) const { return &x; } - const_pointer address(const_reference x) const { return &x; } - pointer allocate(size_type n, const void* = 0) { - assert(data_ >= 0); - if (time_to_throw >= throw_after) { -#ifndef TEST_HAS_NO_EXCEPTIONS - throw std::bad_alloc(); -#else - std::terminate(); -#endif + + TEST_CONSTEXPR pointer address(reference x) const { return &x; } + TEST_CONSTEXPR const_pointer address(const_reference x) const { return &x; } + + TEST_CONSTEXPR_CXX20 pointer allocate(size_type n, const void* = nullptr) { + assert(data_ != test_alloc_base::destructed_value); + if (stats_ != nullptr) { + if (stats_->time_to_throw >= stats_->throw_after) + TEST_THROW(std::bad_alloc()); + ++stats_->time_to_throw; + ++stats_->alloc_count; } - ++time_to_throw; - ++alloc_count; - return (pointer)::operator new(n * sizeof(T)); - } - void deallocate(pointer p, size_type) { - assert(data_ >= 0); - --alloc_count; - ::operator delete((void*)p); + return std::allocator().allocate(n); } - size_type max_size() const TEST_NOEXCEPT { return UINT_MAX / sizeof(T); } -#if TEST_STD_VER < 11 - void construct(pointer p, const T& val) { ::new (static_cast(p)) T(val); } -#else - template - void construct(pointer p, U&& val) { - ::new (static_cast(p)) T(std::forward(val)); + + TEST_CONSTEXPR_CXX20 void deallocate(pointer p, size_type n) { + assert(data_ != test_alloc_base::destructed_value); + if (stats_ != nullptr) + --stats_->alloc_count; + std::allocator().deallocate(p, n); } -#endif - void destroy(pointer p) { p->~T(); } - friend bool operator==(const non_default_test_allocator& x, const non_default_test_allocator& y) { + TEST_CONSTEXPR size_type max_size() const TEST_NOEXCEPT { return UINT_MAX / sizeof(T); } + + TEST_CONSTEXPR friend bool operator==(const non_default_test_allocator& x, const non_default_test_allocator& y) { return x.data_ == y.data_; } - friend bool operator!=(const non_default_test_allocator& x, const non_default_test_allocator& y) { return !(x == y); } + + TEST_CONSTEXPR friend bool operator!=(const non_default_test_allocator& x, const non_default_test_allocator& y) { + return !(x == y); + } }; template <> -class test_allocator : public test_alloc_base { - int data_; - int id_; +class test_allocator { + int data_ = 0; + int id_ = 0; + test_allocator_statistics* stats_ = nullptr; template friend class test_allocator; @@ -242,26 +285,46 @@ typedef test_allocator other; }; - test_allocator() TEST_NOEXCEPT : data_(0), id_(0) {} - explicit test_allocator(int i, int id = 0) TEST_NOEXCEPT : data_(i), id_(id) {} - test_allocator(const test_allocator& a) TEST_NOEXCEPT : data_(a.data_), id_(a.id_) {} + TEST_CONSTEXPR test_allocator() TEST_NOEXCEPT = default; + + TEST_CONSTEXPR_CXX14 explicit test_allocator(test_allocator_statistics* stats) TEST_NOEXCEPT : stats_(stats) {} + + TEST_CONSTEXPR explicit test_allocator(int data) TEST_NOEXCEPT : data_(data) {} + + TEST_CONSTEXPR explicit test_allocator(int data, test_allocator_statistics* stats) TEST_NOEXCEPT + : data_(data), stats_(stats) + {} + + TEST_CONSTEXPR explicit test_allocator(int data, int id) : data_(data), id_(id) {} + + TEST_CONSTEXPR_CXX14 explicit test_allocator(int data, int id, test_allocator_statistics* stats) TEST_NOEXCEPT + : data_(data), id_(id), stats_(stats) + {} + + TEST_CONSTEXPR_CXX14 explicit test_allocator(const test_allocator& a) TEST_NOEXCEPT + : data_(a.data_), id_(a.id_), stats_(a.stats_) + {} + template - test_allocator(const test_allocator& a) TEST_NOEXCEPT : data_(a.data_), id_(a.id_) {} - ~test_allocator() TEST_NOEXCEPT { - data_ = -1; - id_ = -1; + TEST_CONSTEXPR_CXX14 test_allocator(const test_allocator& a) TEST_NOEXCEPT + : data_(a.data_), id_(a.id_), stats_(a.stats_) + {} + + TEST_CONSTEXPR_CXX20 ~test_allocator() TEST_NOEXCEPT { + data_ = test_alloc_base::destructed_value; + id_ = test_alloc_base::destructed_value; } - int get_id() const { return id_; } - int get_data() const { return data_; } + TEST_CONSTEXPR int get_id() const { return id_; } + TEST_CONSTEXPR int get_data() const { return data_; } - friend bool operator==(const test_allocator& x, const test_allocator& y) { return x.data_ == y.data_; } - friend bool operator!=(const test_allocator& x, const test_allocator& y) { return !(x == y); } + TEST_CONSTEXPR friend bool operator==(const test_allocator& x, const test_allocator& y) { return x.data_ == y.data_; } + TEST_CONSTEXPR friend bool operator!=(const test_allocator& x, const test_allocator& y) { return !(x == y); } }; template class other_allocator { - int data_; + int data_ = -1; template friend class other_allocator; @@ -269,17 +332,22 @@ public: typedef T value_type; - other_allocator() : data_(-1) {} - explicit other_allocator(int i) : data_(i) {} + TEST_CONSTEXPR_CXX14 other_allocator() {} + TEST_CONSTEXPR_CXX14 explicit other_allocator(int i) : data_(i) {} + template - other_allocator(const other_allocator& a) : data_(a.data_) {} - T* allocate(std::size_t n) { return (T*)::operator new(n * sizeof(T)); } - void deallocate(T* p, std::size_t) { ::operator delete((void*)p); } + TEST_CONSTEXPR_CXX14 other_allocator(const other_allocator& a) : data_(a.data_) {} - other_allocator select_on_container_copy_construction() const { return other_allocator(-2); } + TEST_CONSTEXPR_CXX20 T* allocate(std::size_t n) { return std::allocator().allocate(n); } + TEST_CONSTEXPR_CXX20 void deallocate(T* p, std::size_t s) { std::allocator().deallocate(p, s); } - friend bool operator==(const other_allocator& x, const other_allocator& y) { return x.data_ == y.data_; } - friend bool operator!=(const other_allocator& x, const other_allocator& y) { return !(x == y); } + TEST_CONSTEXPR_CXX14 other_allocator select_on_container_copy_construction() const { return other_allocator(-2); } + + TEST_CONSTEXPR_CXX14 friend bool operator==(const other_allocator& x, const other_allocator& y) { + return x.data_ == y.data_; + } + + TEST_CONSTEXPR_CXX14 friend bool operator!=(const other_allocator& x, const other_allocator& y) { return !(x == y); } typedef std::true_type propagate_on_container_copy_assignment; typedef std::true_type propagate_on_container_move_assignment; @@ -301,15 +369,15 @@ // All constructors must be passed the Tag type. // DefaultInsertable into vector>, - Tag_X(Ctor_Tag) {} + constexpr Tag_X(Ctor_Tag) {} // CopyInsertable into vector>, - Tag_X(Ctor_Tag, const Tag_X&) {} + constexpr Tag_X(Ctor_Tag, const Tag_X&) {} // MoveInsertable into vector>, and - Tag_X(Ctor_Tag, Tag_X&&) {} + constexpr Tag_X(Ctor_Tag, Tag_X&&) {} // EmplaceConstructible into vector> from args. template - Tag_X(Ctor_Tag, Args&&...) {} + constexpr Tag_X(Ctor_Tag, Args&&...) {} // not DefaultConstructible, CopyConstructible or MoveConstructible. Tag_X() = delete; @@ -317,15 +385,13 @@ Tag_X(Tag_X&&) = delete; // CopyAssignable. - Tag_X& operator=(const Tag_X&) { return *this; } + TEST_CONSTEXPR_CXX14 Tag_X& operator=(const Tag_X&) { return *this; }; // MoveAssignable. - Tag_X& operator=(Tag_X&&) { return *this; } + TEST_CONSTEXPR_CXX14 Tag_X& operator=(Tag_X&&) { return *this; }; private: - // Not Destructible. - ~Tag_X() {} - + ~Tag_X() = default; // Erasable from vector>. friend class TaggingAllocator; }; @@ -337,71 +403,109 @@ TaggingAllocator() = default; template - TaggingAllocator(const TaggingAllocator&) {} - - T* allocate(std::size_t n) { return std::allocator{}.allocate(n); } - - void deallocate(T* p, std::size_t n) { std::allocator{}.deallocate(p, n); } + constexpr TaggingAllocator(const TaggingAllocator&){}; template void construct(Tag_X* p, Args&&... args) { ::new ((void*)p) Tag_X(Ctor_Tag{}, std::forward(args)...); } - template - void construct(U* p, Args&&... args) { - ::new ((void*)p) U(std::forward(args)...); - } - - template + template void destroy(U* p) { p->~U(); } -}; - -template -bool operator==(const TaggingAllocator&, const TaggingAllocator&) { - return true; -} -template -bool operator!=(const TaggingAllocator&, const TaggingAllocator&) { - return false; -} + TEST_CONSTEXPR_CXX20 T* allocate(std::size_t n) { return std::allocator{}.allocate(n); } + TEST_CONSTEXPR_CXX20 void deallocate(T* p, std::size_t n) { std::allocator{}.deallocate(p, n); } +}; #endif template struct limited_alloc_handle { - std::size_t outstanding_; - void* last_alloc_; - - limited_alloc_handle() : outstanding_(0), last_alloc_(nullptr) {} + std::size_t outstanding_ = 0; + void* last_alloc_ = nullptr; template - T* allocate(std::size_t N) { + TEST_CONSTEXPR_CXX20 T* allocate(std::size_t N) { if (N + outstanding_ > MaxAllocs) TEST_THROW(std::bad_alloc()); - last_alloc_ = ::operator new(N * sizeof(T)); + last_alloc_ = std::allocator().allocate(N); outstanding_ += N; return static_cast(last_alloc_); } - void deallocate(void* ptr, std::size_t N) { + template + TEST_CONSTEXPR_CXX20 void deallocate(T* ptr, std::size_t N) { if (ptr == last_alloc_) { last_alloc_ = nullptr; assert(outstanding_ >= N); outstanding_ -= N; } - ::operator delete(ptr); + std::allocator().deallocate(ptr, N); } }; +namespace detail { +template +class thread_unsafe_shared_ptr { +public: + thread_unsafe_shared_ptr() = default; + + TEST_CONSTEXPR_CXX14 thread_unsafe_shared_ptr(const thread_unsafe_shared_ptr& other) : block(other.block) { + ++block->ref_count; + } + + TEST_CONSTEXPR_CXX20 ~thread_unsafe_shared_ptr() { + --block->ref_count; + if (block->ref_count != 0) + return; + typedef std::allocator_traits > allocator_traits; + std::allocator alloc; + allocator_traits::destroy(alloc, block); + allocator_traits::deallocate(alloc, block, 1); + } + + TEST_CONSTEXPR const T& operator*() const { return block->content; } + TEST_CONSTEXPR const T* operator->() const { return &block->content; } + TEST_CONSTEXPR_CXX14 T& operator*() { return block->content; } + TEST_CONSTEXPR_CXX14 T* operator->() { return &block->content; } + TEST_CONSTEXPR_CXX14 T* get() { return &block->content; } + TEST_CONSTEXPR const T* get() const { return &block->content; } + +private: + struct control_block { + template + TEST_CONSTEXPR control_block(Args... args) : content(std::forward(args)...) {} + size_t ref_count = 1; + T content; + }; + + control_block* block = nullptr; + + template + friend TEST_CONSTEXPR_CXX20 thread_unsafe_shared_ptr make_thread_unsafe_shared(Args...); +}; + +template +TEST_CONSTEXPR_CXX20 thread_unsafe_shared_ptr make_thread_unsafe_shared(Args... args) { + typedef typename thread_unsafe_shared_ptr::control_block control_block_type; + typedef std::allocator_traits > allocator_traits; + + thread_unsafe_shared_ptr ptr; + std::allocator alloc; + ptr.block = allocator_traits::allocate(alloc, 1); + allocator_traits::construct(alloc, ptr.block, std::forward(args)...); + + return ptr; +} +} // namespace detail + template class limited_allocator { template friend class limited_allocator; typedef limited_alloc_handle BuffT; - std::shared_ptr handle_; + detail::thread_unsafe_shared_ptr handle_; public: typedef T value_type; @@ -417,29 +521,28 @@ typedef limited_allocator other; }; - limited_allocator() : handle_(new BuffT) {} + TEST_CONSTEXPR_CXX20 limited_allocator() : handle_(detail::make_thread_unsafe_shared()) {} - limited_allocator(limited_allocator const& other) : handle_(other.handle_) {} + limited_allocator(limited_allocator const&) = default; template - explicit limited_allocator(limited_allocator const& other) : handle_(other.handle_) {} + TEST_CONSTEXPR explicit limited_allocator(limited_allocator const& other) : handle_(other.handle_) {} limited_allocator& operator=(const limited_allocator&) = delete; - pointer allocate(size_type n) { return handle_->template allocate(n); } - void deallocate(pointer p, size_type n) { handle_->deallocate(p, n); } - size_type max_size() const { return N; } - - BuffT* getHandle() const { return handle_.get(); } + TEST_CONSTEXPR_CXX20 pointer allocate(size_type n) { return handle_->template allocate(n); } + TEST_CONSTEXPR_CXX20 void deallocate(pointer p, size_type n) { handle_->template deallocate(p, n); } + TEST_CONSTEXPR size_type max_size() const { return N; } + TEST_CONSTEXPR BuffT* getHandle() const { return handle_.get(); } }; template -inline bool operator==(limited_allocator const& LHS, limited_allocator const& RHS) { +TEST_CONSTEXPR inline bool operator==(limited_allocator const& LHS, limited_allocator const& RHS) { return LHS.getHandle() == RHS.getHandle(); } template -inline bool operator!=(limited_allocator const& LHS, limited_allocator const& RHS) { +TEST_CONSTEXPR inline bool operator!=(limited_allocator const& LHS, limited_allocator const& RHS) { return !(LHS == RHS); }