cmake-template
Loading...
Searching...
No Matches
exkit.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <atomic>
4#include <deque>
5
6#include <memory>
7#include <unordered_map>
8
9#include "exkit/scheduler.hpp"
10#include "exkit/task.hpp"
11
12class Exkit {
13public:
25 Exkit(IScheduler &scheduler);
26
35 void run();
36
49 template <typename DependentType, typename... DependencyTypes>
51
65 template <typename FunctionType>
66 auto task(FunctionType&& function);
67
84 template <typename FunctionType, typename... ResultTypes>
85 auto task(FunctionType&& function, TaskHandle<ResultTypes>&... dependencies);
86
87private:
98 void _execute_task(ITask* task, std::unordered_map<ITask*, std::atomic<int>>& remaining);
99
111 void _register_dependency(ITask* dependent, ITask* dependency);
112
113private:
114 std::deque<std::unique_ptr<ITask>> _tasks;
115 std::atomic<bool> _is_running;
116 IScheduler& _scheduler;
117};
118
119// ------------------------- Implementation of template methods -------------------------
120
121template <typename DependentType, typename... DependencyTypes>
123 if (_is_running.load()) {
124 throw std::runtime_error("Cannot add dependencies while Exkit is running.");
125 }
126
127 (_register_dependency(dependent._task, dependencies._task), ...);
128}
129
130template <typename FunctionType>
131auto Exkit::task(FunctionType&& function) {
132 if (_is_running.load()) {
133 throw std::runtime_error("Cannot add tasks while Exkit is running.");
134 }
135
136 using ResultType = std::invoke_result_t<FunctionType>;
137
138 auto task = std::make_unique<Task<ResultType>>(std::forward<FunctionType>(function));
139 auto handle = TaskHandle<ResultType>(task.get());
140
141 _tasks.push_back(std::move(task));
142 return handle;
143}
144
145template <typename FunctionType, typename... ResultTypes>
146auto Exkit::task(FunctionType&& function, TaskHandle<ResultTypes>&... dependencies) {
147 if (_is_running.load()) {
148 throw std::runtime_error("Cannot add tasks while Exkit is running.");
149 }
150
151 using Args = decltype(dependency_values(std::declval<TaskHandle<ResultTypes>&>()...));
152 using ResultType = decltype(std::apply(std::declval<FunctionType>(), std::declval<Args>()));
153
154 auto wrapper = [function = std::forward<FunctionType>(function), dependencies...]() {
155 return std::apply(function, dependency_values(dependencies...));
156 };
157
158 auto task = std::make_unique<Task<ResultType>>(std::move(wrapper));
159 (_register_dependency(task.get(), dependencies._task), ...);
160
161 auto handle = TaskHandle<ResultType>(task.get());
162 _tasks.push_back(std::move(task));
163
164 return handle;
165}
Definition: exkit.hpp:12
Exkit(IScheduler &scheduler)
Construct a new Exkit object.
void run()
Executes all the registered tasks while respecting their dependencies.
void add_dependency(TaskHandle< DependentType > &dependent, TaskHandle< DependencyTypes > &... dependencies)
Adds a dependency between a dependent task and one or more dependency tasks.
Definition: exkit.hpp:122
auto task(FunctionType &&function)
Creates a new task with the given function.
Definition: exkit.hpp:131
Definition: scheduler.hpp:5
Definition: task.hpp:7
Definition: task.hpp:62
auto dependency_values(TaskHandle< ResultTypes > const &... deps)
Definition: task.hpp:103