#include "pls/internal/helpers/profiler.h" #include "pls/internal/scheduling/scheduler.h" #include "pls/internal/scheduling/task.h" #include "pls/internal/scheduling/thread_state.h" namespace pls { namespace internal { namespace scheduling { task::task() : finished_construction_{false}, ref_count_{0}, parent_{nullptr}, deque_state_{0} {} void *task::allocate_memory(long size) { if (finished_construction_) { PLS_ERROR("Must not allocate dynamic task memory after it's construction.") } return thread_state::get()->task_stack_->push_bytes(size); } void task::execute() { PROFILE_WORK_BLOCK("execute task") auto last_executing = thread_state::get()->current_task_; thread_state::get()->current_task_ = this; execute_internal(); PROFILE_END_BLOCK wait_for_all(); thread_state::get()->current_task_ = last_executing; if (parent_ != nullptr) { parent_->ref_count_--; } } void task::wait_for_all() { auto scheduler = thread_state::get()->scheduler_; while (ref_count_ > 0) { if (!scheduler->try_execute_local()) { scheduler->try_execute_stolen(); } } thread_state::get()->deque_.release_memory_until(deque_state_); } } } }