diff --git a/lib/pls/CMakeLists.txt b/lib/pls/CMakeLists.txt index b4a6b66..eca5449 100644 --- a/lib/pls/CMakeLists.txt +++ b/lib/pls/CMakeLists.txt @@ -8,10 +8,11 @@ add_library(pls STATIC src/internal/scheduling/scheduler.cpp include/pls/internal/scheduling/scheduler.h src/internal/scheduling/thread_state.cpp include/pls/internal/scheduling/thread_state.h src/internal/base/barrier.cpp include/pls/internal/base/barrier.h - src/internal/scheduling/root_task.cpp include/pls/internal/scheduling/root_task.h + src/internal/scheduling/root_task.cpp include/pls/internal/scheduling/root_task.h src/internal/base/aligned_stack.cpp include/pls/internal/base/aligned_stack.h include/pls/internal/base/system_details.h - src/internal/scheduling/run_on_n_threads_task.cpp include/pls/internal/scheduling/run_on_n_threads_task.h) + src/internal/scheduling/run_on_n_threads_task.cpp include/pls/internal/scheduling/run_on_n_threads_task.h + src/internal/scheduling/tbb_task.cpp include/pls/internal/scheduling/tbb_task.h) # Add everything in `./include` to be in the include path of this project target_include_directories(pls diff --git a/lib/pls/include/pls/internal/scheduling/tbb_task.h b/lib/pls/include/pls/internal/scheduling/tbb_task.h new file mode 100644 index 0000000..71c7187 --- /dev/null +++ b/lib/pls/include/pls/internal/scheduling/tbb_task.h @@ -0,0 +1,72 @@ + +#ifndef PLS_TBB_LIKE_TASK_H +#define PLS_TBB_LIKE_TASK_H + +#include "abstract_task.h" + +namespace pls { + namespace internal { + namespace scheduling { + class tbb_task; + class tbb_sub_task { + friend class tbb_task; + + std::atomic_uint32_t ref_count_; + tbb_sub_task* parent_; + tbb_task* tbb_task_; + + public: + explicit tbb_sub_task(tbb_sub_task* parent, tbb_task* tbb_task); + ~tbb_sub_task(); + void execute(); + + protected: + virtual void execute_internal() = 0; + // SubClass Implementations: + // Do Work + // |-- Spawn Sub Task + // |-- Spawn Sub task + // Do Work + // |-- Wait For All + // Do Work + // |-- Spawn Sub Task + + // Currently required to construct child... + // TODO: Allocate child with custom new(...) on stack + tbb_sub_task* parent() { return parent_; } + tbb_task* tbb_task() { return tbb_task_; } + + void wait_for_all(); + private: + tbb_sub_task* get_local_task(); + }; + + class tbb_task: public abstract_task { + friend class tbb_sub_task; + tbb_sub_task* root_task_; + // TODO: hold stuff for double ended sub-task queue + + explicit tbb_task(tbb_sub_task* root_task): + abstract_task{0, 0}, + root_task_{root_task} {}; + + void execute() override { + root_task_->execute(); + } + + bool internal_stealing(abstract_task* other_task) override { + auto cast_other_task = reinterpret_cast(other_task); + // TODO: Try to steal from the other sub-task queue + return false; + } + + bool split_task() override { + // TODO: Take an internal task and create a new tbb task from it + return false; + } + }; + } + } +} + +#endif //PLS_TBB_LIKE_TASK_H diff --git a/lib/pls/src/internal/scheduling/tbb_task.cpp b/lib/pls/src/internal/scheduling/tbb_task.cpp new file mode 100644 index 0000000..543e7b1 --- /dev/null +++ b/lib/pls/src/internal/scheduling/tbb_task.cpp @@ -0,0 +1,43 @@ +#include "pls/internal/scheduling/tbb_task.h" + +namespace pls { + namespace internal { + namespace scheduling { + tbb_sub_task::tbb_sub_task(tbb_sub_task *parent, class tbb_task *tbb_task): + ref_count_{0}, + parent_{parent}, + tbb_task_{tbb_task} { + parent->ref_count_++; + } + + tbb_sub_task::~tbb_sub_task() { + wait_for_all(); + } + + void tbb_sub_task::execute() { + execute_internal(); + wait_for_all(); + } + + tbb_sub_task* tbb_sub_task::get_local_task() { + // TODO: get a task from the bottom of our sub-task queue + } + + void tbb_sub_task::wait_for_all() { + while (ref_count_ > 0) { + tbb_sub_task* local_task = get_local_task(); + if (local_task != nullptr) { + local_task->execute(); + continue; + } else { + // Try to steal work. + // External steal will be executed explicitly + if (tbb_task_->steal_work()) { + // TODO: Internal Success, execute stolen task + } + } + } + } + } + } +}