#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include #include // increments a counter only on destruction struct CountOnDestruction { CountOnDestruction(const CountOnDestruction& rhs) : counter {rhs.counter} { rhs.counter = nullptr; } CountOnDestruction(CountOnDestruction&& rhs) : counter{rhs.counter} { rhs.counter = nullptr; } CountOnDestruction(std::atomic& c) : counter {&c} {} ~CountOnDestruction() { if(counter) { //std::cout << "destroying\n"; counter->fetch_add(1, std::memory_order_relaxed); } } mutable std::atomic* counter {nullptr}; }; // ---------------------------------------------------------------------------- // test move constructor // ---------------------------------------------------------------------------- TEST_CASE("moved_run") { int N = 10000; std::atomic counter {0}; tf::Taskflow taskflow; auto make_taskflow = [&](){ for(int i=0; i counter {0}; auto make_taskflow = [&counter](tf::Taskflow& taskflow, int N){ for(int i=0; i counter {0}; auto make_taskflow = [&counter](tf::Taskflow& taskflow, int N){ for(int i=0; i threads; for(int i=0; i<64; i++) { threads.emplace_back([&](){ tf::Taskflow taskflow; make_taskflow(taskflow, N); executor.run(std::move(taskflow)); }); } for(auto& thread : threads) thread.join(); executor.wait_for_all(); } REQUIRE(counter == 64*N*2); counter = 0; { tf::Executor executor; std::vector threads; for(int i=0; i<32; i++) { threads.emplace_back([&](){ tf::Taskflow taskflow1; make_taskflow(taskflow1, N); tf::Taskflow taskflow2(std::move(taskflow1)); executor.run(std::move(taskflow1), [&](){ counter++; }); executor.run(std::move(taskflow2), [&](){ counter++; }); executor.run(std::move(taskflow1), [&](){ counter++; }); executor.run(std::move(taskflow2), [&](){ counter++; }); }); } for(auto& thread : threads) thread.join(); executor.wait_for_all(); } REQUIRE(counter == 32*(N*2 + 4)); }