Blender  V3.3
task_graph.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
9 #include "MEM_guardedalloc.h"
10 
11 #include "BLI_task.h"
12 
13 #include <memory>
14 #include <vector>
15 
16 #ifdef WITH_TBB
17 # include <tbb/flow_graph.h>
18 #endif
19 
20 /* Task Graph */
21 struct TaskGraph {
22 #ifdef WITH_TBB
23  tbb::flow::graph tbb_graph;
24 #endif
25  std::vector<std::unique_ptr<TaskNode>> nodes;
26 
27 #ifdef WITH_CXX_GUARDEDALLOC
28  MEM_CXX_CLASS_ALLOC_FUNCS("task_graph:TaskGraph")
29 #endif
30 };
31 
32 /* TaskNode - a node in the task graph. */
33 struct TaskNode {
34  /* TBB Node. */
35 #ifdef WITH_TBB
36  tbb::flow::continue_node<tbb::flow::continue_msg> tbb_node;
37 #endif
38  /* Successors to execute after this task, for serial execution fallback. */
39  std::vector<TaskNode *> successors;
40 
41  /* User function to be executed with given task data. */
43  void *task_data;
44  /* Optional callback to free task data along with the graph. If task data
45  * is shared between nodes, only a single task node should free the data. */
47 
48  TaskNode(TaskGraph *task_graph,
50  void *task_data,
52  :
53 #ifdef WITH_TBB
54  tbb_node(task_graph->tbb_graph,
55  tbb::flow::unlimited,
56  [&](const tbb::flow::continue_msg input) { run(input); }),
57 #endif
61  {
62 #ifndef WITH_TBB
63  UNUSED_VARS(task_graph);
64 #endif
65  }
66 
67  TaskNode(const TaskNode &other) = delete;
68  TaskNode &operator=(const TaskNode &other) = delete;
69 
71  {
72  if (task_data && free_func) {
74  }
75  }
76 
77 #ifdef WITH_TBB
78  tbb::flow::continue_msg run(const tbb::flow::continue_msg UNUSED(input))
79  {
81  return tbb::flow::continue_msg();
82  }
83 #endif
84 
85  void run_serial()
86  {
88  for (TaskNode *successor : successors) {
89  successor->run_serial();
90  }
91  }
92 
93 #ifdef WITH_CXX_GUARDEDALLOC
94  MEM_CXX_CLASS_ALLOC_FUNCS("task_graph:TaskNode")
95 #endif
96 };
97 
99 {
100  return new TaskGraph();
101 }
102 
104 {
105  delete task_graph;
106 }
107 
109 {
110 #ifdef WITH_TBB
111  task_graph->tbb_graph.wait_for_all();
112 #else
113  UNUSED_VARS(task_graph);
114 #endif
115 }
116 
117 struct TaskNode *BLI_task_graph_node_create(struct TaskGraph *task_graph,
119  void *user_data,
121 {
122  TaskNode *task_node = new TaskNode(task_graph, run, user_data, free_func);
123  task_graph->nodes.push_back(std::unique_ptr<TaskNode>(task_node));
124  return task_node;
125 }
126 
128 {
129 #ifdef WITH_TBB
130  if (BLI_task_scheduler_num_threads() > 1) {
131  return task_node->tbb_node.try_put(tbb::flow::continue_msg());
132  }
133 #endif
134 
135  task_node->run_serial();
136  return true;
137 }
138 
139 void BLI_task_graph_edge_create(struct TaskNode *from_node, struct TaskNode *to_node)
140 {
141 #ifdef WITH_TBB
142  if (BLI_task_scheduler_num_threads() > 1) {
143  tbb::flow::make_edge(from_node->tbb_node, to_node->tbb_node);
144  return;
145  }
146 #endif
147 
148  from_node->successors.push_back(to_node);
149 }
int BLI_task_scheduler_num_threads(void)
void(* TaskGraphNodeFreeFunction)(void *task_data)
Definition: BLI_task.h:388
void(* TaskGraphNodeRunFunction)(void *__restrict task_data)
Definition: BLI_task.h:387
#define UNUSED_VARS(...)
#define UNUSED(x)
Read Guarded memory(de)allocation.
Depsgraph * graph
void * user_data
ccl_global KernelShaderEvalInput * input
static PyObject * free_func(PyObject *, PyObject *value)
Definition: python.cpp:220
std::vector< std::unique_ptr< TaskNode > > nodes
Definition: task_graph.cc:25
TaskNode(TaskGraph *task_graph, TaskGraphNodeRunFunction run_func, void *task_data, TaskGraphNodeFreeFunction free_func)
Definition: task_graph.cc:48
TaskNode(const TaskNode &other)=delete
std::vector< TaskNode * > successors
Definition: task_graph.cc:39
TaskGraphNodeFreeFunction free_func
Definition: task_graph.cc:46
TaskNode & operator=(const TaskNode &other)=delete
void run_serial()
Definition: task_graph.cc:85
TaskGraphNodeRunFunction run_func
Definition: task_graph.cc:42
void * task_data
Definition: task_graph.cc:43
TaskGraph * BLI_task_graph_create()
Definition: task_graph.cc:98
void BLI_task_graph_edge_create(struct TaskNode *from_node, struct TaskNode *to_node)
Definition: task_graph.cc:139
bool BLI_task_graph_node_push_work(struct TaskNode *task_node)
Definition: task_graph.cc:127
void BLI_task_graph_work_and_wait(TaskGraph *task_graph)
Definition: task_graph.cc:108
struct TaskNode * BLI_task_graph_node_create(struct TaskGraph *task_graph, TaskGraphNodeRunFunction run, void *user_data, TaskGraphNodeFreeFunction free_func)
Definition: task_graph.cc:117
void BLI_task_graph_free(TaskGraph *task_graph)
Definition: task_graph.cc:103