#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include #include // -------------------------------------------------------- // Testcase: Semaphores // -------------------------------------------------------- TEST_CASE("Semaphore") { tf::Semaphore semaphore1; REQUIRE(semaphore1.count() == 0); tf::Semaphore semaphore2(100); REQUIRE(semaphore2.count() == 100); for(int i=0; i<200; i++) { if(i<100) { REQUIRE(semaphore2.try_acquire() == true); } else { REQUIRE(semaphore2.try_acquire() == false); } } REQUIRE(semaphore2.count() == 0); for(int i=0; i<200; i++) { semaphore2.release(2); REQUIRE(semaphore2.count() == 2*(i+1)); } REQUIRE(tf::try_acquire(semaphore1, semaphore2) == false); tf::release(semaphore1, semaphore2); REQUIRE(semaphore1.count() == 1); REQUIRE(tf::try_acquire(semaphore1, semaphore2) == true); } // -------------------------------------------------------- // Testcase: CriticalSection // -------------------------------------------------------- void critical_section(unsigned W) { tf::Taskflow taskflow; tf::Executor executor(W); tf::Semaphore semaphore(1); // We don't do large N as acquire will trigger recursive // corun_until which can become too deep to process int N = 50; int counter = 0; for(int i=0; i semaphores(S); for(auto& semaphore : semaphores) { REQUIRE(semaphore.count() == 0); semaphore.reset(1); REQUIRE(semaphore.count() == 1); } int counter(0); for(size_t i=0; i semaphores; tf::Semaphore& AB = semaphores.emplace_back(1); tf::Semaphore& AC = semaphores.emplace_back(1); tf::Semaphore& BC = semaphores.emplace_back(1); auto beg = semaphores.begin(); auto end = semaphores.end(); int counter(0); REQUIRE(&(*beg) == &AB); REQUIRE(&(*std::next(beg, 1)) == &AC); REQUIRE(&(*std::next(beg, 2)) == &BC); taskflow.emplace([&](tf::Runtime& rt){ rt.acquire(beg, std::next(beg, 2)); counter++; rt.release(beg, std::next(beg, 2)); }); taskflow.emplace([&](tf::Runtime& rt){ rt.acquire(std::next(beg, 1), end); counter++; rt.release(std::next(beg, 1), end); }); taskflow.emplace([&](tf::Runtime& rt){ rt.acquire(BC, AB); counter++; rt.release(BC, AB); }); executor.run(taskflow).wait(); REQUIRE(counter == 3); for(size_t i=0; i<10; i++) { executor.run_n(taskflow, 10); } executor.wait_for_all(); REQUIRE(counter == 303); } TEST_CASE("RagnedDeadlock1.1thread") { ranged_deadlock_1(1); } TEST_CASE("RangedDeadlock1.2threads") { ranged_deadlock_1(2); } TEST_CASE("RangedDeadlock1.3threads") { ranged_deadlock_1(3); } TEST_CASE("RangedDeadlock1.4threads") { ranged_deadlock_1(4); } // ---------------------------------------------------------------------------- // Multiple Taskflows // ---------------------------------------------------------------------------- void semaphore_by_multiple_tasks(unsigned W) { tf::Executor executor(W); tf::Taskflow taskflow1, taskflow2, taskflow3, taskflow4; tf::Semaphore s(1); int counter {0}; size_t N = 50; for(size_t i=0; i