diff --git a/src/tests.cc b/src/tests.cc index 6d98c51..094c4bc 100644 --- a/src/tests.cc +++ b/src/tests.cc @@ -11,6 +11,7 @@ #include #include +#include //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -32,7 +33,7 @@ void stress() { std::thread producers[PRODUCERS]; for(unsigned i = 0; i < PRODUCERS; ++i) - producers[i] = std::thread([&q, &barrier]() { + producers[i] = std::thread([&q, &barrier, N=N]() { barrier.wait(); for(unsigned n = N; n; --n) q.push(n); @@ -105,6 +106,55 @@ void test_unique_ptr_int(Q& q) { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template +struct test_stateful_allocator : std::allocator { + State state; + test_stateful_allocator() = delete; + + // disambiguate constructor with std::nullptr_t + // std::in_place available since C++17 + test_stateful_allocator(std::nullptr_t, const State& s) noexcept + : state(s) {} + + test_stateful_allocator(const test_stateful_allocator& other) noexcept + : std::allocator(other), state(other.state) {} + + template + test_stateful_allocator(const test_stateful_allocator& other) noexcept + : state(other.state) {} + + test_stateful_allocator& operator=(const test_stateful_allocator& other) noexcept { + state = other.state; + return *this; + } + + ~test_stateful_allocator() noexcept = default; + + template + struct rebind { + using other = test_stateful_allocator; + }; +}; + +// Required by boost-test +template +std::ostream& operator<<(std::ostream& os, const test_stateful_allocator& allocator) { + return os << allocator.state; +} + +template +bool operator==(const test_stateful_allocator& lhs, const test_stateful_allocator& rhs) { + return lhs.state == rhs.state; +} + +template +bool operator!=(const test_stateful_allocator& lhs, const test_stateful_allocator& rhs) { + return !(lhs.state == rhs.state); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + } // namespace //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -137,6 +187,28 @@ BOOST_AUTO_TEST_CASE(move_only_b2) { test_unique_ptr_int(q); } +BOOST_AUTO_TEST_CASE(allocator_constructor_only_b) { + using allocator_type = test_stateful_allocator; + const auto allocator = allocator_type(nullptr, "Capybara"); + + AtomicQueueB q(2, allocator); + + BOOST_CHECK_EQUAL(q.get_allocator(), allocator); + auto q2 = std::move(q); + BOOST_CHECK_EQUAL(q2.get_allocator(), allocator); +} + +BOOST_AUTO_TEST_CASE(allocator_constructor_only_b2) { + using allocator_type = test_stateful_allocator, std::string>; + const auto allocator = allocator_type(nullptr, "Fox"); + + AtomicQueueB2, allocator_type> q(2, allocator); + + BOOST_CHECK_EQUAL(q.get_allocator(), allocator); + auto q2 = std::move(q); + BOOST_CHECK_EQUAL(q2.get_allocator(), allocator); +} + BOOST_AUTO_TEST_CASE(move_constructor_assignment) { AtomicQueueB2> q(2); auto q2 = std::move(q); @@ -194,4 +266,4 @@ BOOST_AUTO_TEST_CASE(power_of_2) { static_assert(round_up_to_power_of_2(0x40000000u + 1) == 0x80000000u, ""); } -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file