0b35142ddb36d9a29250b32a71f538387b9d0c4b
[blender.git] / intern / cycles / util / util_progress.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_PROGRESS_H__
18 #define __UTIL_PROGRESS_H__
19
20 /* Progress
21  *
22  * Simple class to communicate progress status messages, timing information,
23  * update notifications from a job running in another thread. All methods
24  * except for the constructor/destructor are thread safe. */
25
26 #include "util_function.h"
27 #include "util_string.h"
28 #include "util_time.h"
29 #include "util_thread.h"
30
31 CCL_NAMESPACE_BEGIN
32
33 class Progress {
34 public:
35         Progress()
36         {
37                 tile = 0;
38                 sample = 0;
39                 start_time = time_dt();
40                 total_time = 0.0f;
41                 render_time = 0.0f;
42                 tile_time = 0.0f;
43                 status = "Initializing";
44                 substatus = "";
45                 sync_status = "";
46                 sync_substatus = "";
47                 update_cb = function_null;
48                 cancel = false;
49                 cancel_message = "";
50                 error = false;
51                 error_message = "";
52                 cancel_cb = function_null;
53         }
54
55         Progress(Progress& progress)
56         {
57                 *this = progress;
58         }
59
60         Progress& operator=(Progress& progress)
61         {
62                 thread_scoped_lock lock(progress.progress_mutex);
63
64                 progress.get_status(status, substatus);
65                 progress.get_tile(tile, total_time, render_time, tile_time);
66
67                 sample = progress.get_sample();
68
69                 return *this;
70         }
71
72         void reset()
73         {
74                 tile = 0;
75                 sample = 0;
76                 start_time = time_dt();
77                 render_start_time = time_dt();
78                 total_time = 0.0f;
79                 render_time = 0.0f;
80                 tile_time = 0.0f;
81                 status = "Initializing";
82                 substatus = "";
83                 sync_status = "";
84                 sync_substatus = "";
85                 cancel = false;
86                 cancel_message = "";
87                 error = false;
88                 error_message = "";
89         }
90
91         /* cancel */
92         void set_cancel(const string& cancel_message_)
93         {
94                 thread_scoped_lock lock(progress_mutex);
95                 cancel_message = cancel_message_;
96                 cancel = true;
97         }
98
99         bool get_cancel()
100         {
101                 if(!cancel && cancel_cb)
102                         cancel_cb();
103
104                 return cancel;
105         }
106
107         string get_cancel_message()
108         {
109                 thread_scoped_lock lock(progress_mutex);
110                 return cancel_message;
111         }
112
113         void set_cancel_callback(function<void(void)> function)
114         {
115                 cancel_cb = function;
116         }
117
118         /* error */
119         void set_error(const string& error_message_)
120         {
121                 thread_scoped_lock lock(progress_mutex);
122                 error_message = error_message_;
123                 error = true;
124                 /* If error happens we also stop rendering. */
125                 cancel_message = error_message_;
126                 cancel = true;
127         }
128
129         bool get_error()
130         {
131                 return error;
132         }
133
134         string get_error_message()
135         {
136                 thread_scoped_lock lock(progress_mutex);
137                 return error_message;
138         }
139
140         /* tile and timing information */
141
142         void set_start_time(double start_time_)
143         {
144                 thread_scoped_lock lock(progress_mutex);
145
146                 start_time = start_time_;
147         }
148
149         void set_render_start_time(double render_start_time_)
150         {
151                 thread_scoped_lock lock(progress_mutex);
152
153                 render_start_time = render_start_time_;
154         }
155
156         void set_tile(int tile_, double tile_time_)
157         {
158                 thread_scoped_lock lock(progress_mutex);
159
160                 tile = tile_;
161                 total_time = time_dt() - start_time;
162                 render_time = time_dt() - render_start_time;
163                 tile_time = tile_time_;
164         }
165
166         void get_tile(int& tile_, double& total_time_, double& render_time_, double& tile_time_)
167         {
168                 thread_scoped_lock lock(progress_mutex);
169
170                 tile_ = tile;
171                 total_time_ = (total_time > 0.0)? total_time: 0.0;
172                 render_time_ = (render_time > 0.0)? render_time: 0.0;
173                 tile_time_ = tile_time;
174         }
175
176         void get_time(double& total_time_, double& render_time_)
177         {
178                 total_time_ = (total_time > 0.0)? total_time: 0.0;
179                 render_time_ = (render_time > 0.0)? render_time: 0.0;
180         }
181
182         void reset_sample()
183         {
184                 thread_scoped_lock lock(progress_mutex);
185
186                 sample = 0;
187         }
188
189         void increment_sample()
190         {
191                 thread_scoped_lock lock(progress_mutex);
192
193                 sample++;
194         }
195
196         void increment_sample_update()
197         {
198                 increment_sample();
199                 set_update();
200         }
201
202         int get_sample()
203         {
204                 return sample;
205         }
206
207         /* status messages */
208
209         void set_status(const string& status_, const string& substatus_ = "")
210         {
211                 {
212                         thread_scoped_lock lock(progress_mutex);
213                         status = status_;
214                         substatus = substatus_;
215                         total_time = time_dt() - start_time;
216                         render_time = time_dt() - render_start_time;
217                 }
218
219                 set_update();
220         }
221
222         void set_substatus(const string& substatus_)
223         {
224                 {
225                         thread_scoped_lock lock(progress_mutex);
226                         substatus = substatus_;
227                         total_time = time_dt() - start_time;
228                         render_time = time_dt() - render_start_time;
229                 }
230
231                 set_update();
232         }
233
234         void set_sync_status(const string& status_, const string& substatus_ = "")
235         {
236                 {
237                         thread_scoped_lock lock(progress_mutex);
238                         sync_status = status_;
239                         sync_substatus = substatus_;
240                         total_time = time_dt() - start_time;
241                         render_time = time_dt() - render_start_time;
242                 }
243
244                 set_update();
245
246         }
247
248         void set_sync_substatus(const string& substatus_)
249         {
250                 {
251                         thread_scoped_lock lock(progress_mutex);
252                         sync_substatus = substatus_;
253                         total_time = time_dt() - start_time;
254                         render_time = time_dt() - render_start_time;
255                 }
256
257                 set_update();
258         }
259
260         void get_status(string& status_, string& substatus_)
261         {
262                 thread_scoped_lock lock(progress_mutex);
263
264                 if(sync_status != "") {
265                         status_ = sync_status;
266                         substatus_ = sync_substatus;
267                 }
268                 else {
269                         status_ = status;
270                         substatus_ = substatus;
271                 }
272         }
273
274         /* callback */
275
276         void set_update()
277         {
278                 if(update_cb) {
279                         thread_scoped_lock lock(update_mutex);
280                         update_cb();
281                 }
282         }
283
284         void set_update_callback(function<void(void)> function)
285         {
286                 update_cb = function;
287         }
288
289 protected:
290         thread_mutex progress_mutex;
291         thread_mutex update_mutex;
292         function<void(void)> update_cb;
293         function<void(void)> cancel_cb;
294
295         int tile;    /* counter for rendered tiles */
296         int sample;  /* counter of rendered samples, global for all tiles */
297
298         double start_time, render_start_time;
299         double total_time, render_time;
300         double tile_time;
301
302         string status;
303         string substatus;
304
305         string sync_status;
306         string sync_substatus;
307
308         volatile bool cancel;
309         string cancel_message;
310
311         volatile bool error;
312         string error_message;
313 };
314
315 CCL_NAMESPACE_END
316
317 #endif /* __UTIL_PROGRESS_H__ */
318