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