#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include #include // ============================================================================ // BoundedTaskQueue Test // ============================================================================ // Procedure: test_wsq_owner template void bounded_tsq_owner() { tf::BoundedTaskQueue queue; constexpr size_t N = (1 << LogSize) - 1; std::vector data; for(size_t k=0; k(); } TEST_CASE("BoundedTaskQueue.Owner.LogSize=3" * doctest::timeout(300)) { bounded_tsq_owner<3>(); } TEST_CASE("BoundedTaskQueue.Owner.LogSize=4" * doctest::timeout(300)) { bounded_tsq_owner<4>(); } TEST_CASE("BoundedTaskQueue.Owner.LogSize=5" * doctest::timeout(300)) { bounded_tsq_owner<5>(); } TEST_CASE("BoundedTaskQueue.Owner.LogSize=6" * doctest::timeout(300)) { bounded_tsq_owner<6>(); } TEST_CASE("BoundedTaskQueue.Owner.LogSize=7" * doctest::timeout(300)) { bounded_tsq_owner<7>(); } TEST_CASE("BoundedTaskQueue.Owner.LogSize=8" * doctest::timeout(300)) { bounded_tsq_owner<8>(); } TEST_CASE("BoundedTaskQueue.Owner.LogSize=9" * doctest::timeout(300)) { bounded_tsq_owner<9>(); } TEST_CASE("BoundedTaskQueue.Owner.LogSize=10" * doctest::timeout(300)) { bounded_tsq_owner<10>(); } // ============================================================================ // UnboundedTaskQueue Test // ============================================================================ // Procedure: unbounded_tsq_owner void unbounded_tsq_owner() { for(size_t N=1; N<=777777; N=N*2+1) { tf::UnboundedTaskQueue queue; std::vector gold(N); REQUIRE(queue.empty()); // push and pop for(size_t i=0; i queue; std::vector gold; std::atomic consumed; // 1, 4, 13, 40, 121, 364, 1093, 3280, 9841, 29524, 88573 for(size_t N=1; N<=88573; N=N*3+1) { REQUIRE(queue.empty()); gold.resize(N); consumed = 0; for(size_t i=0; i threads; std::vector> stolens(M); for(size_t i=0; i items; while(consumed != N) { auto ptr = queue.pop(); if(ptr != nullptr) { items.push_back(ptr); consumed.fetch_add(1, std::memory_order_relaxed); } } REQUIRE(queue.steal() == nullptr); REQUIRE(queue.pop() == nullptr); REQUIRE(queue.empty()); // join thieves for(auto& thread : threads) thread.join(); // merge items for(size_t i=0; i queue; std::vector gold; std::atomic consumed; // 1, 4, 13, 40, 121, 364, 1093, 3280, 9841, 29524, 88573, 265720 for(size_t N=1; N<=265720; N=N*3+1) { REQUIRE(queue.empty()); gold.resize(N); consumed = 0; for(size_t i=0; i threads; std::vector> stolens(M); for(size_t i=0; i items; while(consumed != N) { auto ptr = queue.pop(); if(ptr != nullptr) { items.push_back(ptr); consumed.fetch_add(1, std::memory_order_relaxed); } } REQUIRE(queue.steal() == nullptr); REQUIRE(queue.pop() == nullptr); REQUIRE(queue.empty()); // join thieves for(auto& thread : threads) thread.join(); // merge items for(size_t i=0; i void mpmc_basics() { tf::MPMC mpmc; size_t N = (1< data(N+1, -1); REQUIRE(mpmc.capacity() == N); REQUIRE(mpmc.empty() == true); REQUIRE(mpmc.try_dequeue() == std::nullopt); for(size_t i=0; i(); } TEST_CASE("BoundedMPMC.Basics.LogSize=2") { mpmc_basics(); } TEST_CASE("BoundedMPMC.Basics.LogSize=3") { mpmc_basics(); } TEST_CASE("BoundedMPMC.Basics.LogSize=4") { mpmc_basics(); } TEST_CASE("BoundedMPMC.Basics.LogSize=5") { mpmc_basics(); } TEST_CASE("BoundedMPMC.Basics.LogSize=6") { mpmc_basics(); } TEST_CASE("BoundedMPMC.Basics.LogSize=7") { mpmc_basics(); } TEST_CASE("BoundedMPMC.Basics.LogSize=8") { mpmc_basics(); } TEST_CASE("BoundedMPMC.Basics.LogSize=9") { mpmc_basics(); } TEST_CASE("BoundedMPMC.Basics.LogSize=10") { mpmc_basics(); } // mpmc template void mpmc(unsigned num_producers, unsigned num_consumers) { const uint64_t N = 65536; std::atomic pcnt(0), ccnt(0), ans(0); std::vector threads; tf::MPMC mpmc; for(unsigned i=0; i= N) { break; } mpmc.enqueue(v); } }); } for(auto & thread : threads) { thread.join(); } REQUIRE(ans.load() == (((N-1)*N) >> 1)); } TEST_CASE("BoundedMPMC.1C1P") { mpmc(1, 1); mpmc(1, 1); } TEST_CASE("BoundedMPMC.1C2P") { mpmc(1, 2); mpmc(1, 2); } TEST_CASE("BoundedMPMC.1C3P") { mpmc(1, 3); mpmc(1, 3); } TEST_CASE("BoundedMPMC.1C4P") { mpmc(1, 4); mpmc(1, 4); } TEST_CASE("BoundedMPMC.2C1P") { mpmc(2, 1); mpmc(2, 1); } TEST_CASE("BoundedMPMC.2C2P") { mpmc(2, 2); mpmc(2, 2); } TEST_CASE("BoundedMPMC.2C3P") { mpmc(2, 3); mpmc(2, 3); } TEST_CASE("BoundedMPMC.2C4P") { mpmc(2, 4); mpmc(2, 4); } TEST_CASE("BoundedMPMC.3C1P") { mpmc(3, 1); mpmc(3, 1); } TEST_CASE("BoundedMPMC.3C2P") { mpmc(3, 2); mpmc(3, 2); } TEST_CASE("BoundedMPMC.3C3P") { mpmc(3, 3); mpmc(3, 3); } TEST_CASE("BoundedMPMC.3C4P") { mpmc(3, 4); mpmc(3, 4); } TEST_CASE("BoundedMPMC.4C1P") { mpmc(4, 1); mpmc(4, 1); } TEST_CASE("BoundedMPMC.4C2P") { mpmc(4, 2); mpmc(4, 2); } TEST_CASE("BoundedMPMC.4C3P") { mpmc(4, 3); mpmc(4, 3); } TEST_CASE("BoundedMPMC.4C4P") { mpmc(4, 4); mpmc(4, 4); }