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 #ifndef __UTIL_TASK_H__ 18 #define __UTIL_TASK_H__ 19 20 #include "util/util_list.h" 21 #include "util/util_string.h" 22 #include "util/util_tbb.h" 23 #include "util/util_thread.h" 24 #include "util/util_vector.h" 25 26 CCL_NAMESPACE_BEGIN 27 28 class TaskPool; 29 class TaskScheduler; 30 31 typedef function<void(void)> TaskRunFunction; 32 33 /* Task Pool 34 * 35 * Pool of tasks that will be executed by the central TaskScheduler.For each 36 * pool, we can wait for all tasks to be done, or cancel them before they are 37 * done. 38 * 39 * TaskRunFunction may be created with std::bind or lambda expressions. */ 40 41 class TaskPool { 42 public: 43 struct Summary { 44 /* Time spent to handle all tasks. */ 45 double time_total; 46 47 /* Number of all tasks handled by this pool. */ 48 int num_tasks_handled; 49 50 /* A full multi-line description of the state of the pool after 51 * all work is done. 52 */ 53 string full_report() const; 54 }; 55 56 TaskPool(); 57 ~TaskPool(); 58 59 void push(TaskRunFunction &&task); 60 61 void wait_work(Summary *stats = NULL); /* work and wait until all tasks are done */ 62 void cancel(); /* cancel all tasks and wait until they are no longer executing */ 63 64 static bool canceled(); /* For worker threads, test if current task pool canceled. */ 65 66 protected: 67 tbb::task_group tbb_group; 68 69 /* ** Statistics ** */ 70 71 /* Time time stamp of first task pushed. */ 72 double start_time; 73 74 /* Number of all tasks pushed to the pool. Cleared after wait_work() and cancel(). */ 75 int num_tasks_pushed; 76 }; 77 78 /* Task Scheduler 79 * 80 * Central scheduler that holds running threads ready to execute tasks. A singe 81 * queue holds the task from all pools. */ 82 83 class TaskScheduler { 84 public: 85 static void init(int num_threads = 0); 86 static void exit(); 87 static void free_memory(); 88 89 /* Approximate number of threads that will work on task, which may be lower 90 * or higher than the actual number of threads. Use as little as possible and 91 * leave splitting up tasks to the scheduler.. */ 92 static int num_threads(); 93 94 protected: 95 static thread_mutex mutex; 96 static int users; 97 static int active_num_threads; 98 99 #ifdef WITH_TBB_GLOBAL_CONTROL 100 static tbb::global_control *global_control; 101 #endif 102 }; 103 104 /* Dedicated Task Pool 105 * 106 * Like a TaskPool, but will launch one dedicated thread to execute all tasks. 107 * 108 * The run callback that actually executes the task may be created like this: 109 * function_bind(&MyClass::task_execute, this, _1, _2) */ 110 111 class DedicatedTaskPool { 112 public: 113 DedicatedTaskPool(); 114 ~DedicatedTaskPool(); 115 116 void push(TaskRunFunction &&run, bool front = false); 117 118 void wait(); /* wait until all tasks are done */ 119 void cancel(); /* cancel all tasks, keep worker thread running */ 120 121 bool canceled(); /* for worker thread, test if canceled */ 122 123 protected: 124 void num_decrease(int done); 125 void num_increase(); 126 127 void thread_run(); 128 bool thread_wait_pop(TaskRunFunction &task); 129 130 void clear(); 131 132 thread_mutex num_mutex; 133 thread_condition_variable num_cond; 134 135 list<TaskRunFunction> queue; 136 thread_mutex queue_mutex; 137 thread_condition_variable queue_cond; 138 139 int num; 140 bool do_cancel; 141 bool do_exit; 142 143 thread *worker_thread; 144 }; 145 146 CCL_NAMESPACE_END 147 148 #endif 149