HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_ThreadedAlgorithm.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UT_ThreadedAlgorithm.h ( SIM Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __UT_ThreadedAlgorithm__
12 #define __UT_ThreadedAlgorithm__
13 
14 #include "UT_API.h"
15 #include "UT_Functor.h"
16 #include "UT_Lock.h"
17 
18 #include <SYS/SYS_AtomicInt.h>
19 #include <SYS/SYS_Types.h>
20 
21 
22 class UT_JobInfo;
23 
24 
25 ///
26 /// UT_ThreadedAlgorithm takes care of all the thread administration that a
27 /// threaded algorithm requires.
28 ///
29 /// Its features are:
30 /// 1) it executes work in the main thread as well
31 /// 2) it assumes that the work can be divided into N parts and sends off
32 /// exactly N calls to threadfunc() (jobs). (N depends on the # of
33 /// installed processors and the maxthreads parm).
34 ///
35 /// Your callback function is called with several
36 /// useful parameters:
37 ///
38 /// void * data - the userdata pointer you provide to run()
39 /// int jobindex - there are N jobs, this is which job you're running
40 /// (0 to N-1).
41 /// int maxindex - the total number of jobs farmed (N)
42 /// UT_Lock &lock - a lock that you can use to lock other jobs out while
43 /// you work on something non-threadsafe. Accepts NULL.
44 ///
45 /// If your machine is a single proc, this will work exactly as a call to
46 /// threadfunc().
47 ///
48 /// In addition to the traditional threadfunc() callback, you can pass
49 /// in a UT_Functor1 which takes a UT_JobInfo parameter to specify the
50 /// job to be performed (see below). In this case, you may be better off
51 /// with the THREADED_METHOD macros detailed later.
52 ///
54 {
55 public:
56  UT_ThreadedAlgorithm(int maxthreads = -1);
58 
59  /// Starts the jobs, and waits until all are finished. This can be called
60  /// multiple times. The optional lock parm allows you to use your own
61  /// lock; if not specified, this class's lock will be used.
62  void run(void (*threadfunc)(void *, int, int, UT_Lock &),
63  void *userdata,
64  UT_Lock *lock = 0);
65 
66  /// Starts the jobs and waits until all are finished.
67  /// Since this uses a functor, you are expected to use BindFirst
68  /// to hide any user data you may have
69  /// While a return type is specified, it is not used. This is because
70  /// compiler bugs prohibit a Functor2 that returns null.
71  void run(UT_Functor1<int, const UT_JobInfo &> functor,
72  UT_Lock *lock = 0);
73 
74 private:
75  UT_Lock *myLock;
76  int myThreadCount;
77  bool myIsRoot;
78  static SYS_AtomicInt32 ourThreadedAlgorithmInUse;
79 };
80 
81 ///
82 /// Defines the work required for each invocation of *Partial
83 /// to complete.
84 ///
86 {
87 public:
88  UT_JobInfo(int jobidx, int numjobs, UT_Lock *lock, SYS_AtomicInt32 *aint = 0)
89  {
90  myJob = jobidx;
91  myNumJobs = numjobs;
92  myLock = lock;
93  myTask = aint;
94  myLocalTask = 0;
95  }
96 
97  /// The number of jobs is the total number of threads
98  /// that is running and job() is your thread #, starting at 0
99  /// and going up to numJobs()-1
100  int job() const { return myJob; }
101  int numJobs() const { return myNumJobs; }
102 
103  /// These control a shared AtomicInt32 so you can split
104  /// tasks among jobs using load balancing. The total number
105  /// is in this case up to you to detect.
106  /// The JobIds will start with 0 and each call will get a unique
107  /// higher number.
108  /// Example:
109  /// for (i = info.nextTask(); i < maxtask; i = info.nextTask())
110  int32 nextTask() const;
111 
112  /// Resets the task list. You are responsible for creating
113  /// a barrier to ensure that all the other threads have
114  /// hit the end of the tasks!
115  /// This is *not* required for your first loop as you will
116  /// already start at task 0.
117  void resetTasks() const;
118 
119  /// Given "units" work, report which units you are responsible
120  /// for with this JobInfo. The resulting interval is [start, end),
121  /// Appropriate for loop:
122  /// for (info.divideWork(total, i, end); i < end; i++)
123  void divideWork(int units, int &start, int &end) const;
124  void divideWork(exint units, exint &start, exint &end) const;
125 
126  /// lock and unlock a lock shared by all the jobs. This lock
127  /// is special cased to a no-op in the threadless case to avoid
128  /// overhead.
129  void lock() const
130  {
131  if (myLock)
132  myLock->lock();
133  }
134  void unlock() const
135  {
136  if (myLock)
137  myLock->unlock();
138  }
139 
140 protected:
141  int myJob, myNumJobs;
144  mutable int myLocalTask;
145 };
146 
148 {
149 public:
151  : myLock(lock)
152  { lock.lock(); }
153 
154  ~UT_AutoJobInfoLock() { myLock.unlock(); }
155 
156 private:
157  const UT_JobInfo &myLock;
158 };
159 
160 ///
161 /// @file
162 /// This macro is equivalent to
163 /// @code
164 /// for (i = 0; i < n; i++)
165 /// @endcode
166 ///
167 /// It will, however break it into BLOCK sized chunks for each thread,
168 /// allowing for load balancing
169 /// NB: Because it relies on the info.nextTask() starting at zero, you
170 /// can only loop once in this manner.
171 /// NB: This is a double loop, so break; does not work as you expect.
172 /// NB: The iterator, i, does not have to be defined.
173 /// An example of use:
174 ///
175 /// @code
176 /// FOR_INFOTASKS(info, i, n, 100)
177 /// {
178 /// // Process task i.
179 /// }
180 /// @endcode
181 ///
182 /// If you want opInterrupt() triggered for every block completed,
183 ///
184 /// @code
185 /// FOR_INFOTASKS_BOSS(info, i, n, 100, boss)
186 /// {
187 /// // Process task i.
188 /// }
189 /// @endcode
190 ///
191 #define FOR_INFOTASKS(info, i, n, blocksize) \
192 for (int task = info.nextTask() * blocksize; task < n; task = info.nextTask() * blocksize) \
193  for (int i = task, lcl_final = SYSmin(task+blocksize, (int)n); i < lcl_final; i++)
194 
195 #define FOR_INFOTASKS_BOSS(info, i, n, blocksize, boss) \
196 for (int task = info.nextTask() * blocksize; task < n && !boss->opInterrupt(); task = info.nextTask() * blocksize) \
197  for (int i = task, lcl_final = SYSmin(task+blocksize, (int)n); i < lcl_final; i++)
198 
199 
200 ///
201 /// @file
202 /// These macros automatically create all the wrapper functions
203 /// required to set up a multithreaded function call that can
204 /// be invoked transparently.
205 ///
206 /// An example of use:
207 /// @code
208 /// class Foobar
209 /// {
210 /// ...
211 /// THREADED_METHOD2(Foobar, gdp->points().entries() > 100,
212 /// translate,
213 /// GU_Detail *, gdp,
214 /// const UT_Vector3 &, delta)
215 ///
216 /// void translatePartial(GU_Detail *gdp, const UT_Vector3 &delta,
217 /// const UT_JobInfo &info);
218 /// ...
219 /// }
220 ///
221 /// void
222 /// Foobar::translatePartial(GU_Detail *gdp, const UT_Vector3 &delta,
223 /// const UT_JobInfo &info)
224 /// {
225 /// int i, n;
226 ///
227 /// for (info.divideWork(gdp->points().entries, i, n); i < n; i++)
228 /// {
229 /// gdp->points()(i).getPos() += delta;
230 /// }
231 /// }
232 /// @endcode
233 ///
234 /// The suffix number is the number of parameters the function
235 /// should take - THREADED_METHOD#(). The parameters to the macro are:
236 ///
237 /// @code
238 /// THREADED_METHOD#(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, ...);
239 /// @endcode
240 ///
241 /// The DOMULTI is a boolean value (which may be a function returning
242 /// such) which determines if multithreading should be performed.
243 /// This lets you disable the multithreading for small batches.
244 /// Note it executes inside of METHOD, so has access to the parameters
245 /// in the CLASS. For threaded methods with parameters, you need to
246 /// specify both the PARMTYPE and the PARMNAME for each parameter.
247 ///
248 /// The user must both prototype & implement a
249 /// @code
250 /// void functionPartial(parameterlist, const &UT_JobInfo)
251 /// @endcode
252 /// which does all the real work (see above).
253 ///
254 /// Automatically created by the THREADED_METHOD macro are:
255 /// @code
256 /// void function(parameterlist) <- what users can invoke
257 /// void functionNoThread(parameterlist) <- unthreaded version
258 /// int functionInvokeParital(...) <- marshalling function.
259 /// @endcode
260 ///
261 
262 #define THREADED_METHOD_INTERNAL(ISCONST, CLASSNAME, DOMULTI, METHOD) \
263 void METHOD ## NoThread() ISCONST \
264 { \
265  METHOD ## Partial(UT_JobInfo(0, 1, 0)); \
266 } \
267 \
268 void METHOD() ISCONST \
269 { \
270  if (!(DOMULTI)) \
271  { \
272  METHOD ## NoThread(); \
273  return; \
274  } \
275  \
276  auto functor = [&](const UT_JobInfo &info) \
277  { METHOD ## Partial(info); return 0; }; \
278  UT_ThreadedAlgorithm alg; \
279  alg.run(functor); \
280 } \
281 /**/
282 
283 #define THREADED_METHOD1_INTERNAL(ISCONST, CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1) \
284 void METHOD ## NoThread(PARMTYPE1 PARMNAME1) ISCONST \
285 { \
286  METHOD ## Partial(PARMNAME1, UT_JobInfo(0, 1, 0)); \
287 } \
288 \
289 void METHOD(PARMTYPE1 PARMNAME1) ISCONST \
290 { \
291  if (!(DOMULTI)) \
292  { \
293  METHOD ## NoThread(PARMNAME1); \
294  return; \
295  } \
296  \
297  auto functor = [&](const UT_JobInfo &info) \
298  { METHOD ## Partial(PARMNAME1, info); return 0; }; \
299  UT_ThreadedAlgorithm alg; \
300  alg.run(functor); \
301 } \
302 /**/
303 
304 #define THREADED_METHOD2_INTERNAL(ISCONST, CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2) \
305 void METHOD ## NoThread(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2) ISCONST \
306 { \
307  METHOD ## Partial(PARMNAME1, PARMNAME2, UT_JobInfo(0, 1, 0)); \
308 } \
309 \
310 void METHOD(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2) ISCONST \
311 { \
312  if (!(DOMULTI)) \
313  { \
314  METHOD ## NoThread(PARMNAME1, PARMNAME2); \
315  return; \
316  } \
317  \
318  auto functor = [&](const UT_JobInfo &info) \
319  { METHOD ## Partial(PARMNAME1, PARMNAME2, info); return 0; }; \
320  UT_ThreadedAlgorithm alg; \
321  alg.run(functor); \
322 } \
323 /**/
324 
325 #define THREADED_METHOD3_INTERNAL(ISCONST, CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3) \
326 void METHOD ## NoThread(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3) ISCONST \
327 { \
328  METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, UT_JobInfo(0, 1, 0)); \
329 } \
330 \
331 void METHOD(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3) ISCONST \
332 { \
333  if (!(DOMULTI)) \
334  { \
335  METHOD ## NoThread(PARMNAME1, PARMNAME2, PARMNAME3); \
336  return; \
337  } \
338  \
339  auto functor = [&](const UT_JobInfo &info) \
340  { METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, info); return 0; }; \
341  UT_ThreadedAlgorithm alg; \
342  alg.run(functor); \
343 } \
344 /**/
345 
346 #define THREADED_METHOD4_INTERNAL(ISCONST, CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4) \
347 void METHOD ## NoThread(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4) ISCONST \
348 { \
349  METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, UT_JobInfo(0, 1, 0)); \
350 } \
351 \
352 void METHOD(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4) ISCONST \
353 { \
354  if (!(DOMULTI)) \
355  { \
356  METHOD ## NoThread(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4); \
357  return; \
358  } \
359  \
360  auto functor = [&](const UT_JobInfo &info) \
361  { METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, info); return 0; }; \
362  UT_ThreadedAlgorithm alg; \
363  alg.run(functor); \
364 } \
365 /**/
366 
367 #define THREADED_METHOD5_INTERNAL(ISCONST, CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5) \
368 void METHOD ## NoThread(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5) ISCONST \
369 { \
370  METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, UT_JobInfo(0, 1, 0)); \
371 } \
372 \
373 void METHOD(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5) ISCONST \
374 { \
375  if (!(DOMULTI)) \
376  { \
377  METHOD ## NoThread(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5); \
378  return; \
379  } \
380  \
381  auto functor = [&](const UT_JobInfo &info) \
382  { METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, info); return 0; }; \
383  UT_ThreadedAlgorithm alg; \
384  alg.run(functor); \
385 } \
386 /**/
387 
388 #define THREADED_METHOD6_INTERNAL(ISCONST, CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6) \
389 void METHOD ## NoThread(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5, PARMTYPE6 PARMNAME6) ISCONST \
390 { \
391  METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, UT_JobInfo(0, 1, 0)); \
392 } \
393 \
394 void METHOD(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5, PARMTYPE6 PARMNAME6) ISCONST \
395 { \
396  if (!(DOMULTI)) \
397  { \
398  METHOD ## NoThread(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6); \
399  return; \
400  } \
401  \
402  auto functor = [&](const UT_JobInfo &info) \
403  { METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, info); return 0; }; \
404  UT_ThreadedAlgorithm alg; \
405  alg.run(functor); \
406 } \
407 /**/
408 
409 #define THREADED_METHOD7_INTERNAL(ISCONST, CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6, PARMTYPE7, PARMNAME7) \
410 void METHOD ## NoThread(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5, PARMTYPE6 PARMNAME6, PARMTYPE7 PARMNAME7) ISCONST \
411 { \
412  METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7, UT_JobInfo(0, 1, 0)); \
413 } \
414 \
415 void METHOD(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5, PARMTYPE6 PARMNAME6, PARMTYPE7 PARMNAME7) ISCONST \
416 { \
417  if (!(DOMULTI)) \
418  { \
419  METHOD ## NoThread(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7); \
420  return; \
421  } \
422  \
423  auto functor = [&](const UT_JobInfo &info) \
424  { METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7, info); return 0; }; \
425  UT_ThreadedAlgorithm alg; \
426  alg.run(functor); \
427 } \
428 /**/
429 
430 #define THREADED_METHOD8_INTERNAL(ISCONST, CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6, PARMTYPE7, PARMNAME7, PARMTYPE8, PARMNAME8) \
431 void METHOD ## NoThread(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5, PARMTYPE6 PARMNAME6, PARMTYPE7 PARMNAME7, PARMTYPE8 PARMNAME8) ISCONST \
432 { \
433  METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7, PARMNAME8, UT_JobInfo(0, 1, 0)); \
434 } \
435 \
436 void METHOD(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5, PARMTYPE6 PARMNAME6, PARMTYPE7 PARMNAME7, PARMTYPE8 PARMNAME8) ISCONST \
437 { \
438  if (!(DOMULTI)) \
439  { \
440  METHOD ## NoThread(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7, PARMNAME8); \
441  return; \
442  } \
443  \
444  auto functor = [&](const UT_JobInfo &info) \
445  { METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7, PARMNAME8, info); return 0; }; \
446  UT_ThreadedAlgorithm alg; \
447  alg.run(functor); \
448 } \
449 /**/
450 
451 #define THREADED_METHOD9_INTERNAL(ISCONST, CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6, PARMTYPE7, PARMNAME7, PARMTYPE8, PARMNAME8, PARMTYPE9, PARMNAME9) \
452 void METHOD ## NoThread(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5, PARMTYPE6 PARMNAME6, PARMTYPE7 PARMNAME7, PARMTYPE8 PARMNAME8, PARMTYPE9 PARMNAME9) ISCONST \
453 { \
454  METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7, PARMNAME8, PARMNAME9, UT_JobInfo(0, 1, 0)); \
455 } \
456 \
457 void METHOD(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5, PARMTYPE6 PARMNAME6, PARMTYPE7 PARMNAME7, PARMTYPE8 PARMNAME8, PARMTYPE9 PARMNAME9) ISCONST \
458 { \
459  if (!(DOMULTI)) \
460  { \
461  METHOD ## NoThread(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7, PARMNAME8, PARMNAME9); \
462  return; \
463  } \
464  \
465  auto functor = [&](const UT_JobInfo &info) \
466  { METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7, PARMNAME8, PARMNAME9, info); return 0; }; \
467  UT_ThreadedAlgorithm alg; \
468  alg.run(functor); \
469 } \
470 /**/
471 
472 #define THREADED_METHOD10_INTERNAL(ISCONST, CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6, PARMTYPE7, PARMNAME7, PARMTYPE8, PARMNAME8, PARMTYPE9, PARMNAME9, PARMTYPE10, PARMNAME10) \
473 void METHOD ## NoThread(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5, PARMTYPE6 PARMNAME6, PARMTYPE7 PARMNAME7, PARMTYPE8 PARMNAME8, PARMTYPE9 PARMNAME9, PARMTYPE10 PARMNAME10) ISCONST \
474 { \
475  METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7, PARMNAME8, PARMNAME9, PARMNAME10, UT_JobInfo(0, 1, 0)); \
476 } \
477 \
478 void METHOD(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5, PARMTYPE6 PARMNAME6, PARMTYPE7 PARMNAME7, PARMTYPE8 PARMNAME8, PARMTYPE9 PARMNAME9, PARMTYPE10 PARMNAME10) ISCONST \
479 { \
480  if (!(DOMULTI)) \
481  { \
482  METHOD ## NoThread(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7, PARMNAME8, PARMNAME9, PARMNAME10); \
483  return; \
484  } \
485  \
486  auto functor = [&](const UT_JobInfo &info) \
487  { METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7, PARMNAME8, PARMNAME9, PARMNAME10, info); return 0; }; \
488  UT_ThreadedAlgorithm alg; \
489  alg.run(functor); \
490 } \
491 /**/
492 
493 #define THREADED_METHOD(CLASSNAME, DOMULTI, METHOD) \
494  THREADED_METHOD_INTERNAL( , CLASSNAME, DOMULTI, METHOD)
495 #define THREADED_METHOD_CONST(CLASSNAME, DOMULTI, METHOD) \
496  THREADED_METHOD_INTERNAL(const , CLASSNAME, DOMULTI, METHOD)
497 
498 #define THREADED_METHOD1(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1) \
499  THREADED_METHOD1_INTERNAL( , CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1)
500 #define THREADED_METHOD1_CONST(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1) \
501  THREADED_METHOD1_INTERNAL(const , CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1)
502 
503 #define THREADED_METHOD2(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2) \
504  THREADED_METHOD2_INTERNAL( , CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2)
505 #define THREADED_METHOD2_CONST(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2) \
506  THREADED_METHOD2_INTERNAL(const , CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2)
507 
508 #define THREADED_METHOD3(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3) \
509  THREADED_METHOD3_INTERNAL( , CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3)
510 #define THREADED_METHOD3_CONST(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3) \
511  THREADED_METHOD3_INTERNAL(const , CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3)
512 
513 #define THREADED_METHOD4(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4) \
514  THREADED_METHOD4_INTERNAL( , CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4)
515 #define THREADED_METHOD4_CONST(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4) \
516  THREADED_METHOD4_INTERNAL(const , CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4)
517 
518 #define THREADED_METHOD5(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5) \
519  THREADED_METHOD5_INTERNAL( , CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5)
520 #define THREADED_METHOD5_CONST(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5) \
521  THREADED_METHOD5_INTERNAL(const , CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5)
522 
523 #define THREADED_METHOD6(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6) \
524  THREADED_METHOD6_INTERNAL( , CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6)
525 #define THREADED_METHOD6_CONST(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6) \
526  THREADED_METHOD6_INTERNAL(const , CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6)
527 
528 #define THREADED_METHOD7(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6, PARMTYPE7, PARMNAME7) \
529  THREADED_METHOD7_INTERNAL( , CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6, PARMTYPE7, PARMNAME7)
530 #define THREADED_METHOD7_CONST(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6, PARMTYPE7, PARMNAME7) \
531  THREADED_METHOD7_INTERNAL(const , CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6, PARMTYPE7, PARMNAME7)
532 
533 #define THREADED_METHOD8(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6, PARMTYPE7, PARMNAME7, PARMTYPE8, PARMNAME8) \
534  THREADED_METHOD8_INTERNAL( , CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6, PARMTYPE7, PARMNAME7, PARMTYPE8, PARMNAME8)
535 #define THREADED_METHOD8_CONST(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6, PARMTYPE7, PARMNAME7, PARMTYPE8, PARMNAME8) \
536  THREADED_METHOD8_INTERNAL(const , CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6, PARMTYPE7, PARMNAME7, PARMTYPE8, PARMNAME8)
537 
538 #define THREADED_METHOD9(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6, PARMTYPE7, PARMNAME7, PARMTYPE8, PARMNAME8, PARMTYPE9, PARMNAME9) \
539  THREADED_METHOD9_INTERNAL( , CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6, PARMTYPE7, PARMNAME7, PARMTYPE8, PARMNAME8, PARMTYPE9, PARMNAME9)
540 #define THREADED_METHOD9_CONST(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6, PARMTYPE7, PARMNAME7, PARMTYPE8, PARMNAME8, PARMTYPE9, PARMNAME9) \
541  THREADED_METHOD9_INTERNAL(const , CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6, PARMTYPE7, PARMNAME7, PARMTYPE8, PARMNAME8, PARMTYPE9, PARMNAME9)
542 
543 #define THREADED_METHOD10(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6, PARMTYPE7, PARMNAME7, PARMTYPE8, PARMNAME8, PARMTYPE9, PARMNAME9, PARMTYPE10, PARMNAME10) \
544  THREADED_METHOD10_INTERNAL( , CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6, PARMTYPE7, PARMNAME7, PARMTYPE8, PARMNAME8, PARMTYPE9, PARMNAME9, PARMTYPE10, PARMNAME10)
545 #define THREADED_METHOD10_CONST(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6, PARMTYPE7, PARMNAME7, PARMTYPE8, PARMNAME8, PARMTYPE9, PARMNAME9, PARMTYPE10, PARMNAME10) \
546  THREADED_METHOD10_INTERNAL(const , CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6, PARMTYPE7, PARMNAME7, PARMTYPE8, PARMNAME8, PARMTYPE9, PARMNAME9, PARMTYPE10, PARMNAME10)
547 
548 #endif
UT_JobInfo(int jobidx, int numjobs, UT_Lock *lock, SYS_AtomicInt32 *aint=0)
#define UT_API
Definition: UT_API.h:13
UT_AutoJobInfoLock(const UT_JobInfo &lock)
int64 exint
Definition: SYS_Types.h:120
GLuint GLuint end
Definition: glew.h:1253
int int32
Definition: SYS_Types.h:39
GLuint start
Definition: glew.h:1253
void lock() const
int numJobs() const
void unlock() const
SYS_AtomicInt32 * myTask
GLfloat units
Definition: glew.h:10289
int job() const