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