Blender V5.0
task.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "util/task.h"
6
7#include "util/log.h"
8#include "util/time.h"
9
11
12/* Task Pool */
13
15
17{
18 cancel();
19}
20
22{
23 tbb_group.run(std::move(task));
25}
26
28{
29 tbb_group.wait();
30
31 if (stats != nullptr) {
32 stats->time_total = time_dt() - start_time;
34 }
35
37}
38
40{
41 if (num_tasks_pushed > 0) {
42 tbb_group.cancel();
43 tbb_group.wait();
45 }
46}
47
49{
50 return tbb::is_current_task_group_canceling();
51}
52
53/* Task Scheduler */
54
58unique_ptr<tbb::global_control> TaskScheduler::global_control;
59
60void TaskScheduler::init(const int num_threads)
61{
63 /* Multiple cycles instances can use this task scheduler, sharing the same
64 * threads, so we keep track of the number of users. */
65 ++users;
66 if (users != 1) {
67 return;
68 }
69 if (num_threads > 0) {
70 /* Automatic number of threads. */
71 LOG_INFO << "Overriding number of TBB threads to " << num_threads << ".";
72 global_control = make_unique<tbb::global_control>(tbb::global_control::max_allowed_parallelism,
73 num_threads);
74 active_num_threads = num_threads;
75 }
76 else {
77 active_num_threads = tbb::this_task_arena::max_concurrency();
78 }
79}
80
82{
84 users--;
85 if (users == 0) {
86 global_control.reset();
88 }
89}
90
92{
93 assert(users == 0);
94}
95
97{
99 return (users > 0) ? active_num_threads : tbb::this_task_arena::max_concurrency();
100}
101
102/* Dedicated Task Pool */
103
105{
106 do_cancel = false;
107 do_exit = false;
108 num = 0;
109
110 worker_thread = make_unique<thread>([this] { thread_run(); });
111}
112
114{
115 wait();
116
117 do_exit = true;
118 queue_cond.notify_all();
119
120 worker_thread->join();
121 worker_thread.reset();
122}
123
125{
126 num_increase();
127
128 /* add task to queue */
129 queue_mutex.lock();
130 if (front) {
131 queue.emplace_front(std::move(run));
132 }
133 else {
134 queue.emplace_back(std::move(run));
135 }
136
137 queue_cond.notify_one();
138 queue_mutex.unlock();
139}
140
142{
144
145 while (num) {
146 num_cond.wait(num_lock);
147 }
148}
149
151{
152 do_cancel = true;
153
154 clear();
155 wait();
156
157 do_cancel = false;
158}
159
161{
162 return do_cancel;
163}
164
166{
167 const thread_scoped_lock num_lock(num_mutex);
168 num -= done;
169
170 assert(num >= 0);
171 if (num == 0) {
172 num_cond.notify_all();
173 }
174}
175
177{
178 const thread_scoped_lock num_lock(num_mutex);
179 num++;
180 num_cond.notify_all();
181}
182
184{
186
187 while (queue.empty() && !do_exit) {
188 queue_cond.wait(queue_lock);
189 }
190
191 if (queue.empty()) {
193 return false;
194 }
195
196 task = queue.front();
197 queue.pop_front();
198
199 return true;
200}
201
203{
204 TaskRunFunction task;
205
206 /* keep popping off tasks */
207 while (thread_wait_pop(task)) {
208 /* run task */
209 task();
210
211 /* delete task */
212 task = nullptr;
213
214 /* notify task was done */
215 num_decrease(1);
216 }
217}
218
220{
222
223 /* erase all tasks from the queue */
224 const int done = queue.size();
225 queue.clear();
226
227 queue_lock.unlock();
228
229 /* notify done */
230 num_decrease(done);
231}
232
234{
235 string report;
236 report += string_printf("Total time: %f\n", time_total);
237 report += string_printf("Tasks handled: %d", num_tasks_handled);
238 return report;
239}
240
volatile int lock
thread_condition_variable num_cond
Definition task.h:119
void num_decrease(const int done)
Definition task.cpp:165
void thread_run()
Definition task.cpp:202
thread_mutex queue_mutex
Definition task.h:122
thread_mutex num_mutex
Definition task.h:118
unique_ptr< thread > worker_thread
Definition task.h:129
void push(TaskRunFunction &&run, bool front=false)
Definition task.cpp:124
thread_condition_variable queue_cond
Definition task.h:123
bool canceled()
Definition task.cpp:160
void num_increase()
Definition task.cpp:176
list< TaskRunFunction > queue
Definition task.h:121
bool thread_wait_pop(TaskRunFunction &task)
Definition task.cpp:183
static void free_memory()
Definition task.cpp:91
static void exit()
Definition task.cpp:81
static thread_mutex mutex
Definition task.h:82
static int users
Definition task.h:83
static int active_num_threads
Definition task.h:84
static int max_concurrency()
Definition task.cpp:96
static void init(const int num_threads=0)
Definition task.cpp:60
#define CCL_NAMESPACE_END
#define assert(assertion)
#define LOG_INFO
Definition log.h:106
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition string.cpp:23
string full_report() const
Definition task.cpp:233
int num_tasks_handled
Definition task.h:35
double time_total
Definition task.h:32
void push(TaskRunFunction &&task)
Definition task.cpp:21
static bool canceled()
Definition task.cpp:48
int num_tasks_pushed
Definition task.h:62
tbb::task_group tbb_group
Definition task.h:54
double start_time
Definition task.h:59
void wait_work(Summary *stats=nullptr)
Definition task.cpp:27
void cancel()
Definition task_pool.cc:290
TaskPool()
Definition task.cpp:14
std::function< void()> TaskRunFunction
Definition task.h:18
std::mutex thread_mutex
Definition thread.h:27
std::unique_lock< std::mutex > thread_scoped_lock
Definition thread.h:28
CCL_NAMESPACE_BEGIN double time_dt()
Definition time.cpp:47