| 21 | #include "fl/system/engine_events.h" |
| 22 | |
| 23 | FL_TEST_FILE(FL_FILEPATH) { |
| 24 | |
| 25 | using namespace fl; |
| 26 | using fl::task::CoroutineConfig; |
| 27 | using fl::task::run; |
| 28 | using fl::task::Scheduler; |
| 29 | |
| 30 | // ============================================================ |
| 31 | // Level 1: Binary semaphore tests |
| 32 | // ============================================================ |
| 33 | |
| 34 | FL_TEST_CASE("coroutine - binary semaphore basic signal") { |
| 35 | fl::binary_semaphore sem(0); |
| 36 | FL_CHECK_FALSE(sem.try_acquire()); |
| 37 | sem.release(); |
| 38 | FL_CHECK(sem.try_acquire()); |
| 39 | FL_CHECK_FALSE(sem.try_acquire()); |
| 40 | } |
| 41 | |
| 42 | FL_TEST_CASE("coroutine - binary semaphore thread handoff") { |
| 43 | fl::binary_semaphore sem(0); |
| 44 | fl::atomic<bool> thread_ran(false); |
| 45 | |
| 46 | fl::thread t([&]() { |
| 47 | sem.acquire(); |
| 48 | thread_ran.store(true); |
| 49 | }); |
| 50 | |
| 51 | fl::this_thread::sleep_for(fl::chrono::milliseconds(10)); // ok sleep for |
| 52 | FL_CHECK_FALSE(thread_ran.load()); |
| 53 | |
| 54 | sem.release(); |
| 55 | t.join(); |
| 56 | FL_CHECK(thread_ran.load()); |
| 57 | } |
| 58 | |
| 59 | FL_TEST_CASE("coroutine - counting semaphore two-phase handoff") { |
| 60 | fl::counting_semaphore<2> sem(0); |
| 61 | fl::atomic<int> phase(0); |
| 62 | |
| 63 | fl::thread t([&]() { |
| 64 | phase.store(1); |
| 65 | sem.release(); // Signal "started" |
| 66 | |
| 67 | // Simulate work |
| 68 | fl::this_thread::sleep_for(fl::chrono::milliseconds(5)); // ok sleep for |
| 69 | |
| 70 | phase.store(2); |
| 71 | sem.release(); // Signal "done" |
| 72 | }); |
| 73 | |
| 74 | sem.acquire(); // Wait for "started" |
| 75 | FL_CHECK_EQ(phase.load(), 1); |
| 76 | |
| 77 | sem.acquire(); // Wait for "done" |
| 78 | FL_CHECK_EQ(phase.load(), 2); |
| 79 | |
| 80 | t.join(); |
nothing calls this directly
no test coverage detected