add BLI_strcpy_rlen, replace strcat, which was used in misleading way.
[blender.git] / intern / cycles / util / util_progress.h
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 #ifndef __UTIL_PROGRESS_H__
20 #define __UTIL_PROGRESS_H__
21
22 /* Progress
23  *
24  * Simple class to communicate progress status messages, timing information,
25  * update notifications from a job running in another thread. All methods
26  * except for the constructor/destructor are thread safe. */
27
28 #include "util_function.h"
29 #include "util_string.h"
30 #include "util_time.h"
31 #include "util_thread.h"
32
33 CCL_NAMESPACE_BEGIN
34
35 class Progress {
36 public:
37         Progress()
38         {
39                 tile = 0;
40                 sample = 0;
41                 start_time = time_dt();
42                 total_time = 0.0f;
43                 tile_time = 0.0f;
44                 status = "Initializing";
45                 substatus = "";
46                 sync_status = "";
47                 sync_substatus = "";
48                 update_cb = NULL;
49                 cancel = false;
50                 cancel_message = "";
51                 cancel_cb = NULL;
52         }
53
54         Progress(Progress& progress)
55         {
56                 *this = progress;
57         }
58
59         Progress& operator=(Progress& progress)
60         {
61                 thread_scoped_lock lock(progress.progress_mutex);
62
63                 progress.get_status(status, substatus);
64                 progress.get_tile(tile, total_time, tile_time);
65
66                 sample = progress.get_sample();
67
68                 return *this;
69         }
70
71         void reset()
72         {
73                 tile = 0;
74                 sample = 0;
75                 start_time = time_dt();
76                 total_time = 0.0f;
77                 tile_time = 0.0f;
78                 status = "Initializing";
79                 substatus = "";
80                 sync_status = "";
81                 sync_substatus = "";
82                 cancel = false;
83                 cancel_message = "";
84         }
85
86         /* cancel */
87         void set_cancel(const string& cancel_message_)
88         {
89                 thread_scoped_lock lock(progress_mutex);
90                 cancel_message = cancel_message_;
91                 cancel = true;
92         }
93
94         bool get_cancel()
95         {
96                 if(!cancel && cancel_cb)
97                         cancel_cb();
98
99                 return cancel;
100         }
101
102         string get_cancel_message()
103         {
104                 thread_scoped_lock lock(progress_mutex);
105                 return cancel_message;
106         }
107
108         void set_cancel_callback(boost::function<void(void)> function)
109         {
110                 cancel_cb = function;
111         }
112
113         /* tile and timing information */
114
115         void set_start_time(double start_time_)
116         {
117                 thread_scoped_lock lock(progress_mutex);
118
119                 start_time = start_time_;
120         }
121
122         void set_tile(int tile_, double tile_time_)
123         {
124                 thread_scoped_lock lock(progress_mutex);
125
126                 tile = tile_;
127                 total_time = time_dt() - start_time;
128                 tile_time = tile_time_;
129         }
130
131         void get_tile(int& tile_, double& total_time_, double& tile_time_)
132         {
133                 thread_scoped_lock lock(progress_mutex);
134
135                 tile_ = tile;
136                 total_time_ = (total_time > 0.0)? total_time: 0.0;
137                 tile_time_ = tile_time;
138         }
139
140         void reset_sample()
141         {
142                 thread_scoped_lock lock(progress_mutex);
143
144                 sample = 0;
145         }
146
147         void increment_sample()
148         {
149                 thread_scoped_lock lock(progress_mutex);
150
151                 sample++;
152         }
153
154         int get_sample()
155         {
156                 return sample;
157         }
158
159         /* status messages */
160
161         void set_status(const string& status_, const string& substatus_ = "")
162         {
163                 {
164                         thread_scoped_lock lock(progress_mutex);
165                         status = status_;
166                         substatus = substatus_;
167                         total_time = time_dt() - start_time;
168                 }
169
170                 set_update();
171         }
172
173         void set_substatus(const string& substatus_)
174         {
175                 {
176                         thread_scoped_lock lock(progress_mutex);
177                         substatus = substatus_;
178                         total_time = time_dt() - start_time;
179                 }
180
181                 set_update();
182         }
183
184         void set_sync_status(const string& status_, const string& substatus_ = "")
185         {
186                 {
187                         thread_scoped_lock lock(progress_mutex);
188                         sync_status = status_;
189                         sync_substatus = substatus_;
190                         total_time = time_dt() - start_time;
191                 }
192
193                 set_update();
194
195         }
196
197         void set_sync_substatus(const string& substatus_)
198         {
199                 {
200                         thread_scoped_lock lock(progress_mutex);
201                         sync_substatus = substatus_;
202                         total_time = time_dt() - start_time;
203                 }
204
205                 set_update();
206         }
207
208         void get_status(string& status_, string& substatus_)
209         {
210                 thread_scoped_lock lock(progress_mutex);
211
212                 if(sync_status != "") {
213                         status_ = sync_status;
214                         substatus_ = sync_substatus;
215                 }
216                 else {
217                         status_ = status;
218                         substatus_ = substatus;
219                 }
220         }
221
222         /* callback */
223
224         void set_update()
225         {
226                 if(update_cb) {
227                         thread_scoped_lock lock(update_mutex);
228                         update_cb();
229                 }
230         }
231
232         void set_update_callback(boost::function<void(void)> function)
233         {
234                 update_cb = function;
235         }
236
237 protected:
238         thread_mutex progress_mutex;
239         thread_mutex update_mutex;
240         boost::function<void(void)> update_cb;
241         boost::function<void(void)> cancel_cb;
242
243         int tile;    /* counter for rendered tiles */
244         int sample;  /* counter of rendered samples, global for all tiles */
245
246         double start_time;
247         double total_time;
248         double tile_time;
249
250         string status;
251         string substatus;
252
253         string sync_status;
254         string sync_substatus;
255
256         volatile bool cancel;
257         string cancel_message;
258 };
259
260 CCL_NAMESPACE_END
261
262 #endif /* __UTIL_PROGRESS_H__ */
263