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