util_task.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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. #ifndef __UTIL_TASK_H__
  17. #define __UTIL_TASK_H__
  18. #include "util/util_list.h"
  19. #include "util/util_string.h"
  20. #include "util/util_thread.h"
  21. #include "util/util_vector.h"
  22. CCL_NAMESPACE_BEGIN
  23. class Task;
  24. class TaskPool;
  25. class TaskScheduler;
  26. /* Notes on Thread ID
  27. *
  28. * Thread ID argument reports the 0-based ID of a working thread from which
  29. * the run() callback is being invoked. Thread ID of 0 denotes the thread from
  30. * which wait_work() was called.
  31. *
  32. * DO NOT use this ID to control execution flaw, use it only for things like
  33. * emulating TLS which does not affect on scheduling. Don't use this ID to make
  34. * any decisions.
  35. *
  36. * It is to be noted here that dedicated task pool will always report thread ID
  37. * of 0.
  38. */
  39. typedef function<void(int thread_id)> TaskRunFunction;
  40. /* Task
  41. *
  42. * Base class for tasks to be executed in threads. */
  43. class Task {
  44. public:
  45. Task(){};
  46. explicit Task(const TaskRunFunction &run_) : run(run_)
  47. {
  48. }
  49. virtual ~Task()
  50. {
  51. }
  52. TaskRunFunction run;
  53. };
  54. /* Task Pool
  55. *
  56. * Pool of tasks that will be executed by the central TaskScheduler.For each
  57. * pool, we can wait for all tasks to be done, or cancel them before they are
  58. * done.
  59. *
  60. * The run callback that actually executes the task may be created like this:
  61. * function_bind(&MyClass::task_execute, this, _1, _2) */
  62. class TaskPool {
  63. public:
  64. struct Summary {
  65. /* Time spent to handle all tasks. */
  66. double time_total;
  67. /* Number of all tasks handled by this pool. */
  68. int num_tasks_handled;
  69. /* A full multiline description of the state of the pool after
  70. * all work is done.
  71. */
  72. string full_report() const;
  73. };
  74. TaskPool();
  75. ~TaskPool();
  76. void push(Task *task, bool front = false);
  77. void push(const TaskRunFunction &run, bool front = false);
  78. void wait_work(Summary *stats = NULL); /* work and wait until all tasks are done */
  79. void cancel(); /* cancel all tasks, keep worker threads running */
  80. void stop(); /* stop all worker threads */
  81. bool finished(); /* check if all work has been completed */
  82. bool canceled(); /* for worker threads, test if canceled */
  83. protected:
  84. friend class TaskScheduler;
  85. void num_decrease(int done);
  86. void num_increase();
  87. thread_mutex num_mutex;
  88. thread_condition_variable num_cond;
  89. int num;
  90. bool do_cancel;
  91. /* ** Statistics ** */
  92. /* Time time stamp of first task pushed. */
  93. double start_time;
  94. /* Number of all tasks handled by this pool. */
  95. int num_tasks_handled;
  96. };
  97. /* Task Scheduler
  98. *
  99. * Central scheduler that holds running threads ready to execute tasks. A singe
  100. * queue holds the task from all pools. */
  101. class TaskScheduler {
  102. public:
  103. static void init(int num_threads = 0);
  104. static void exit();
  105. static void free_memory();
  106. /* number of threads that can work on task */
  107. static int num_threads()
  108. {
  109. return threads.size();
  110. }
  111. /* test if any session is using the scheduler */
  112. static bool active()
  113. {
  114. return users != 0;
  115. }
  116. protected:
  117. friend class TaskPool;
  118. struct Entry {
  119. Task *task;
  120. TaskPool *pool;
  121. };
  122. static thread_mutex mutex;
  123. static int users;
  124. static vector<thread *> threads;
  125. static bool do_exit;
  126. static list<Entry> queue;
  127. static thread_mutex queue_mutex;
  128. static thread_condition_variable queue_cond;
  129. static void thread_run(int thread_id);
  130. static bool thread_wait_pop(Entry &entry);
  131. static void push(Entry &entry, bool front);
  132. static void clear(TaskPool *pool);
  133. };
  134. /* Dedicated Task Pool
  135. *
  136. * Like a TaskPool, but will launch one dedicated thread to execute all tasks.
  137. *
  138. * The run callback that actually executes the task may be created like this:
  139. * function_bind(&MyClass::task_execute, this, _1, _2) */
  140. class DedicatedTaskPool {
  141. public:
  142. DedicatedTaskPool();
  143. ~DedicatedTaskPool();
  144. void push(Task *task, bool front = false);
  145. void push(const TaskRunFunction &run, bool front = false);
  146. void wait(); /* wait until all tasks are done */
  147. void cancel(); /* cancel all tasks, keep worker thread running */
  148. void stop(); /* stop worker thread */
  149. bool canceled(); /* for worker thread, test if canceled */
  150. protected:
  151. void num_decrease(int done);
  152. void num_increase();
  153. void thread_run();
  154. bool thread_wait_pop(Task *&entry);
  155. void clear();
  156. thread_mutex num_mutex;
  157. thread_condition_variable num_cond;
  158. list<Task *> queue;
  159. thread_mutex queue_mutex;
  160. thread_condition_variable queue_cond;
  161. int num;
  162. bool do_cancel;
  163. bool do_exit;
  164. thread *worker_thread;
  165. };
  166. CCL_NAMESPACE_END
  167. #endif