19 #include <unordered_map> 21 #include "containers.h" 29 template <
class TMemInterface >
class base_task;
30 template <
class TMemInterface >
class base_thread_pool;
35 template <
class task_type,
class TMemInterface >
struct base_sub_graph :
public TMemInterface
37 typedef std::vector< task_type *, stl_allocator< task_type *, TMemInterface > > task_vector;
59 template <
class TMemInterface >
class base_task_graph :
public TMemInterface
70 typedef std::unordered_map< string_type, task_type *, std::hash< string_type >, std::equal_to< string_type >,
72 task_name_to_task_map;
73 typedef std::vector< sub_graph_type *, stl_allocator< sub_graph_type *, TMemInterface > > sub_graph_vector;
74 typedef std::vector< task_type *, stl_allocator< task_type *, TMemInterface > > task_vector;
77 typedef std::function< void(task_type *, void *&) > traversal_function_type;
81 typedef base_task_queue_type
super;
84 bool push_back(
typename base_task< TMemInterface >::task_type * _new_task);
118 for (
auto &queue : task_queue)
128 for (
auto &queue : task_queue)
170 void setup(sub_graph_type *_sub_graph =
nullptr);
175 void load(string_type _file_name);
185 void set_task_thread_affinity(task_type *_task, uint64_t _mask);
191 void set_task_thread_exclusion(task_type *_task, uint64_t _mask);
197 void set_num_workers(task_type *_task, thread_num_t _num_workers);
203 void set_percentage_of_workers(task_type *_task,
float _percentage_workers);
207 void setup_tail_kickers();
218 void depth_first_visitor(task_type *_task, traversal_function_type _preorder_functor,
219 traversal_function_type _inorder_functor, traversal_function_type _post_order_functor,
220 traversal_function_type _tail_functor,
void *_param,
bool _bottom_up =
false);
231 void queue_task(task_type *_task, thread_num_t _num_threads_to_wake_up = 1);
237 task_type *dequeue_task(uint32_t _priority);
242 bool is_task_available();
249 bool link_task(task_type *_parent_task, task_type *_dependent_task);
257 bool find_head(task_vector &_head_list);
263 size_t size(task_list _task_list)
const;
267 task_memory_allocator_type task_memory_allocator;
288 template <
class TMemInterface >
294 template <
class TMemInterface >
297 return super::push_back(_new_task);
300 template <
class TMemInterface >
309 using namespace std::chrono_literals;
320 for (
auto task : *task_list)
324 task->transient.num_working = 0;
325 task->transient.task_time = 0ms;
326 task->transient.num_runned = 0;
328 for (
auto task : *task_list)
330 for (
auto dependent_task : task->persistent.dependent_tasks)
332 ++dependent_task->transient.start_gate;
339 auto found_at_least_one_head =
false;
342 uint64_t start_gate = task->
transient.start_gate.load();
345 _head_list.push_back(task);
346 found_at_least_one_head =
true;
349 return found_at_least_one_head;
366 using namespace std::placeholders;
381 std::set< task_type * > head_nodes_with_a_tail_node;
382 for (
auto tail_task : tail_tasks)
384 for (
auto kick_task : tail_task->kick_tasks)
386 auto result = head_nodes_with_a_tail_node.insert(kick_task);
387 assert(result.second);
400 sub_graph->tail_tasks.push_back(tail_task);
401 task_set sub_graph_set;
402 for (
auto kick_task : tail_task->persistent.kick_tasks)
404 sub_graph->head_tasks.push_back(kick_task);
405 void *param =
nullptr;
407 [](
task_type *node,
void *&_param, task_set *_sub_graph_set,
410 _sub_graph_set->insert(node);
413 _1, _2, &sub_graph_set, sub_graph),
414 nullptr,
nullptr,
nullptr, param);
416 copy(sub_graph_set.begin(), sub_graph_set.end(), back_inserter(sub_graph->task_list));
420 task_set ranked_tasks;
421 traversal_function_type ranking_func = [&](
task_type *nodeTask,
void *¶m) {
423 nodeTask->
persistent.
rank +=
reinterpret_cast< typename task_type::rank_type
>(param);
430 for (
auto bottomHeadTask : sub_graph->tail_tasks)
432 void *param =
nullptr;
448 sort(task->persistent.dependent_tasks.begin(), task->persistent.dependent_tasks.end(),
449 rank_sorter::compare);
455 void *param =
nullptr;
461 nullptr,
nullptr,
nullptr, param);
465 template <
class TMemInterface >
470 valid_thread_mask = valid_thread_mask - 1;
478 template <
class TMemInterface >
483 valid_thread_mask = valid_thread_mask - 1;
484 _mask = _mask & valid_thread_mask;
488 template <
class TMemInterface >
494 template <
class TMemInterface >
497 assert(_percentage_workers > .0f && _percentage_workers <= 1.0f);
503 using namespace std::placeholders;
507 void *param =
nullptr;
509 head_task,
nullptr,
nullptr,
nullptr,
511 [](
task_type *_tail_task,
void *&_param,
task_type *_head_task, task_vector *_tail_tasks) {
514 auto result = find(begin(*_tail_tasks), end(*_tail_tasks), _tail_task);
515 if (result == end(*_tail_tasks))
518 _tail_tasks->push_back(_tail_task);
526 template <
class TMemInterface >
528 traversal_function_type _pre_order_functor,
529 traversal_function_type _in_order_functor,
530 traversal_function_type _post_order_functor,
531 traversal_function_type _tail_functor,
void *_param,
534 if (_pre_order_functor)
535 _pre_order_functor(_task, _param);
541 _tail_functor(_task, _param);
546 depth_first_visitor(parent_task, _pre_order_functor, _in_order_functor, _post_order_functor,
547 _tail_functor, _param, _bottom_up);
548 if (_in_order_functor)
549 _in_order_functor(_task, _param);
557 _tail_functor(_task, _param);
562 depth_first_visitor(dependent_task, _pre_order_functor, _in_order_functor, _post_order_functor,
563 _tail_functor, _param, _bottom_up);
564 if (_in_order_functor)
565 _in_order_functor(_task, _param);
568 if (_post_order_functor)
569 _post_order_functor(_task, _param);
595 template <
class TMemInterface >
603 for (thread_num_t count = 0; count < requested_workers; ++count)
607 }
while (!
transient.task_queue[priority]->push_back(_task) && ++priority < task_type::num_priority);
608 assert(priority < task_type::num_priority);
614 template <
class TMemInterface >
619 transient.task_queue[_priority]->pop_front(next_task);
625 for (
auto queue :
transient.task_queue)
635 template <
class TMemInterface >
638 _parent_task->dependent_tasks.push_back(_dependent_task);
639 _dependent_task->parent_tasks.push_back(_parent_task);
void wake_up(thread_num_t _num_threads_to_wake_up=max_num_threads, uint64_t _thread_affinity_mask=std::numeric_limits< uint64_t >::max())
Wakes up.
Definition: threadpool.h:191
transient_container transient
The transient
Definition: task.h:259
task_vector kick_tasks
The kick tasks
Definition: task.h:174
void queue_task(task_type *_task, thread_num_t _num_threads_to_wake_up=1)
Queues the task.
Definition: taskgraph.h:596
persistent_container persistent
The persistent
Definition: taskgraph.h:273
void depth_first_visitor(task_type *_task, traversal_function_type _preorder_functor, traversal_function_type _inorder_functor, traversal_function_type _post_order_functor, traversal_function_type _tail_functor, void *_param, bool _bottom_up=false)
Depthes the first visitor.
Definition: taskgraph.h:527
void set_task_thread_exclusion(task_type *_task, uint64_t _mask)
Sets the task thread exclusion.
Definition: taskgraph.h:479
Class stl_allocator.
Definition: allocator.h:16
task_vector task_list
The task list
Definition: taskgraph.h:49
task_type * dequeue_task(uint32_t _priority)
Dequeues the task.
Definition: taskgraph.h:616
Struct debug_container
Definition: taskgraph.h:143
thread_pool & pool
The pool
Definition: taskgraph.h:285
bool link_task(task_type *_parent_task, task_type *_dependent_task)
Links the task.
Definition: taskgraph.h:636
~base_task_graph()
Finalizes an instance of the base_task_graph class.
Definition: taskgraph.h:572
void setup_tail_kickers()
Setups the tail kickers.
Definition: taskgraph.h:501
Struct base_sub_graph
Definition: task.h:38
Definition: allocator.h:17
task_vector task_list
The task list
Definition: taskgraph.h:152
Struct transient_container
Definition: taskgraph.h:110
void setup(sub_graph_type *_sub_graph=nullptr)
Setups the specified sub graph.
Definition: taskgraph.h:307
priority_selector task_priority
The task priority
Definition: task.h:162
transient_container transient
The transient
Definition: taskgraph.h:277
uint64_t thread_affinity
The thread affinity
Definition: task.h:186
transient_container(task_memory_allocator_type *allocator)
Initializes a new instance of the base_task_graph<TMemInterface>.transient_container struct...
Definition: taskgraph.h:116
sub_graph_type * sub_graph
The sub graph
Definition: task.h:178
std::atomic_int64_t start_gate
The start gate
Definition: task.h:118
sub_graph_vector sub_graphs
The sub graphs
Definition: taskgraph.h:104
task_vector tail_tasks
The tail tasks
Definition: taskgraph.h:100
thread_num_t num_threads
The number threads
Definition: threadpool.h:113
string_type task_name
The task name
Definition: task.h:94
virtual thread_num_t get_recommended_num_workers()
Gets the best number of workers for the task every frame
Definition: task.h:515
void set_num_workers(task_type *_task, thread_num_t _num_workers)
Sets the number workers.
Definition: taskgraph.h:489
void kick()
Kicks this instance.
Definition: taskgraph.h:586
Definition: lockfreequeue.h:20
Struct persistent_container
Definition: taskgraph.h:91
debug_container debug
The debug
Definition: taskgraph.h:281
task_vector head_tasks
The head tasks
Definition: taskgraph.h:41
Definition: lockfreequeue.h:235
task_vector head_tasks
The head tasks
Definition: taskgraph.h:96
void set_percentage_of_workers(task_type *_task, float _percentage_workers)
Sets the percentage of workers.
Definition: taskgraph.h:495
Class base_task.
Definition: task.h:44
Class base_task_graph.
Definition: task.h:35
debug_container debug
The debug
Definition: task.h:255
task_vector tail_tasks
The tail tasks
Definition: taskgraph.h:45
void set_task_thread_affinity(task_type *_task, uint64_t _mask)
Sets the task thread affinity.
Definition: taskgraph.h:466
task_vector parent_tasks
The parent tasks
Definition: task.h:166
void initialize()
Initializes this instance.
Definition: taskgraph.h:364
thread_num_t num_workers
User set number of workers to use to run this task
Definition: task.h:194
Class base_thread_pool.
Definition: task.h:36
rank_type rank
The rank
Definition: task.h:182
task_name_to_task_map task_name_to_task
The task name to task
Definition: taskgraph.h:148
Definition: taskgraph.h:79
~transient_container()
Finalizes an instance of the base_task_graph<TMemInterface>.transient_container class.
Definition: taskgraph.h:126
base_task_graph(thread_pool &_pool)
Initializes a new instance of the base_task_graph class.
Definition: taskgraph.h:301
bool is_task_available()
Determines whether [is task available].
Definition: taskgraph.h:623
task_vector dependent_tasks
The dependent tasks
Definition: task.h:170
persistent_container persistent
The persistent
Definition: task.h:263