#include #include #include "pls/pls.h" using namespace pls::internal::scheduling; using namespace pls::internal::scheduling::lock_free; constexpr int MAX_NUM_TASKS = 32; constexpr int MAX_STACK_SIZE = 1024 * 8; TEST_CASE("scheduler correctly initializes", "[internal/scheduling/scheduler]") { const unsigned num_tasks = 16; const unsigned num_threads = 4; pls::scheduler scheduler{num_threads, num_tasks, 4096, false}; SECTION("task chains are valid") { for (unsigned i = 0; i < num_threads; i++) { task_manager &manager = scheduler.task_manager_for(i); for (unsigned j = 0; j < num_tasks; j++) { REQUIRE(manager.get_task(j)->depth_ == j); REQUIRE(manager.get_task(j)->thread_id_ == i); if (j < num_tasks - 1) { REQUIRE(manager.get_task(j)->next_ == manager.get_task(j + 1)); } if (j > 0) { REQUIRE(manager.get_task(j)->prev_ == manager.get_task(j - 1)); } } } } } TEST_CASE("tasks distributed over workers (do not block)", "[internal/scheduling/scheduler.h]") { scheduler scheduler{3, MAX_NUM_TASKS, MAX_STACK_SIZE}; std::atomic num_run{0}; scheduler.perform_work([&] { scheduler::spawn([&] { num_run++; while (num_run < 3); }); scheduler::spawn([&] { while (num_run < 1); num_run++; while (num_run < 3); }); scheduler::spawn([&] { while (num_run < 2); num_run++; }); scheduler::sync(); }); REQUIRE(num_run == 3); } unsigned fib_serial(unsigned n) { if (n <= 1) { return n; } return fib_serial(n - 1) + fib_serial(n - 2); } unsigned fib_pls(unsigned n) { if (n <= 1) { return n; } unsigned a, b; pls::invoke( [&a, n] { a = fib_pls(n - 1); }, [&b, n] { b = fib_pls(n - 2); } ); return a + b; } TEST_CASE("simple fib", "[internal/scheduling/scheduler]") { scheduler scheduler{3, MAX_NUM_TASKS, MAX_STACK_SIZE}; scheduler.perform_work([&] { REQUIRE(fib_serial(28) == fib_pls(28)); }); }