Blender  V2.93
util_task.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "util/util_task.h"
18 #include "util/util_foreach.h"
19 #include "util/util_logging.h"
20 #include "util/util_system.h"
21 #include "util/util_time.h"
22 
24 
25 /* Task Pool */
26 
27 TaskPool::TaskPool() : start_time(time_dt()), num_tasks_pushed(0)
28 {
29 }
30 
32 {
33  cancel();
34 }
35 
37 {
38  tbb_group.run(std::move(task));
40 }
41 
43 {
44  tbb_group.wait();
45 
46  if (stats != NULL) {
47  stats->time_total = time_dt() - start_time;
49  }
50 
51  num_tasks_pushed = 0;
52 }
53 
55 {
56  if (num_tasks_pushed > 0) {
57  tbb_group.cancel();
58  tbb_group.wait();
59  num_tasks_pushed = 0;
60  }
61 }
62 
64 {
65  return tbb::is_current_task_group_canceling();
66 }
67 
68 /* Task Scheduler */
69 
71 int TaskScheduler::users = 0;
73 tbb::global_control *TaskScheduler::global_control = nullptr;
74 
75 void TaskScheduler::init(int num_threads)
76 {
78  /* Multiple cycles instances can use this task scheduler, sharing the same
79  * threads, so we keep track of the number of users. */
80  ++users;
81  if (users != 1) {
82  return;
83  }
84  if (num_threads > 0) {
85  /* Automatic number of threads. */
86  VLOG(1) << "Overriding number of TBB threads to " << num_threads << ".";
87  global_control = new tbb::global_control(tbb::global_control::max_allowed_parallelism,
88  num_threads);
90  }
91  else {
93  }
94 }
95 
97 {
99  users--;
100  if (users == 0) {
101  delete global_control;
102  global_control = nullptr;
103  active_num_threads = 0;
104  }
105 }
106 
108 {
109  assert(users == 0);
110 }
111 
113 {
114  return active_num_threads;
115 }
116 
117 /* Dedicated Task Pool */
118 
120 {
121  do_cancel = false;
122  do_exit = false;
123  num = 0;
124 
126 }
127 
129 {
130  wait();
131 
132  do_exit = true;
133  queue_cond.notify_all();
134 
135  worker_thread->join();
136  delete worker_thread;
137 }
138 
140 {
141  num_increase();
142 
143  /* add task to queue */
144  queue_mutex.lock();
145  if (front)
146  queue.emplace_front(std::move(task));
147  else
148  queue.emplace_back(std::move(task));
149 
150  queue_cond.notify_one();
151  queue_mutex.unlock();
152 }
153 
155 {
156  thread_scoped_lock num_lock(num_mutex);
157 
158  while (num)
159  num_cond.wait(num_lock);
160 }
161 
163 {
164  do_cancel = true;
165 
166  clear();
167  wait();
168 
169  do_cancel = false;
170 }
171 
173 {
174  return do_cancel;
175 }
176 
178 {
179  thread_scoped_lock num_lock(num_mutex);
180  num -= done;
181 
182  assert(num >= 0);
183  if (num == 0)
184  num_cond.notify_all();
185 }
186 
188 {
189  thread_scoped_lock num_lock(num_mutex);
190  num++;
191  num_cond.notify_all();
192 }
193 
195 {
196  thread_scoped_lock queue_lock(queue_mutex);
197 
198  while (queue.empty() && !do_exit)
199  queue_cond.wait(queue_lock);
200 
201  if (queue.empty()) {
202  assert(do_exit);
203  return false;
204  }
205 
206  task = queue.front();
207  queue.pop_front();
208 
209  return true;
210 }
211 
213 {
215 
216  /* keep popping off tasks */
217  while (thread_wait_pop(task)) {
218  /* run task */
219  task();
220 
221  /* delete task */
222  task = nullptr;
223 
224  /* notify task was done */
225  num_decrease(1);
226  }
227 }
228 
230 {
231  thread_scoped_lock queue_lock(queue_mutex);
232 
233  /* erase all tasks from the queue */
234  int done = queue.size();
235  queue.clear();
236 
237  queue_lock.unlock();
238 
239  /* notify done */
240  num_decrease(done);
241 }
242 
244 {
245  string report = "";
246  report += string_printf("Total time: %f\n", time_total);
247  report += string_printf("Tasks handled: %d\n", num_tasks_handled);
248  return report;
249 }
250 
thread_condition_variable num_cond
Definition: util_task.h:133
thread_mutex queue_mutex
Definition: util_task.h:136
thread_mutex num_mutex
Definition: util_task.h:132
void num_decrease(int done)
Definition: util_task.cpp:177
void push(TaskRunFunction &&run, bool front=false)
Definition: util_task.cpp:139
thread * worker_thread
Definition: util_task.h:143
thread_condition_variable queue_cond
Definition: util_task.h:137
list< TaskRunFunction > queue
Definition: util_task.h:135
bool thread_wait_pop(TaskRunFunction &task)
Definition: util_task.cpp:194
static void free_memory()
Definition: util_task.cpp:107
static void exit()
Definition: util_task.cpp:96
static int num_threads()
Definition: util_task.cpp:112
static void init(int num_threads=0)
Definition: util_task.cpp:75
static thread_mutex mutex
Definition: util_task.h:95
static int users
Definition: util_task.h:96
static int active_num_threads
Definition: util_task.h:97
bool join()
Definition: util_thread.cpp:56
#define function_bind
#define CCL_NAMESPACE_END
struct blender::compositor::@172::@174 task
string full_report() const
Definition: util_task.cpp:243
double time_total
Definition: util_task.h:45
void push(TaskRunFunction &&task)
Definition: util_task.cpp:36
static bool canceled()
Definition: util_task.cpp:63
int num_tasks_pushed
Definition: util_task.h:75
tbb::task_group tbb_group
Definition: util_task.h:67
double start_time
Definition: util_task.h:72
void cancel()
Definition: util_task.cpp:54
void wait_work(Summary *stats=NULL)
Definition: util_task.cpp:42
#define VLOG(severity)
Definition: util_logging.h:50
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition: util_string.cpp:32
int system_cpu_thread_count()
Definition: util_system.cpp:75
function< void(void)> TaskRunFunction
Definition: util_task.h:29
std::unique_lock< std::mutex > thread_scoped_lock
Definition: util_thread.h:41
CCL_NAMESPACE_BEGIN typedef std::mutex thread_mutex
Definition: util_thread.h:40
CCL_NAMESPACE_BEGIN double time_dt()
Definition: util_time.cpp:48