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() ISCONST \
264 { \
265  if (!(DOMULTI)) \
266  { \
267  METHOD ## NoThread(); \
268  return; \
269  } \
270  \
271  auto functor = [&](const UT_JobInfo &info) \
272  { METHOD ## Partial(info); return 0; }; \
273  UT_ThreadedAlgorithm alg; \
274  alg.run(functor); \
275 } \
276 \
277 void METHOD ## NoThread() ISCONST \
278 { \
279  METHOD ## Partial(UT_JobInfo(0, 1, 0)); \
280 } \
281 /**/
282 
283 #define THREADED_METHOD1_INTERNAL(ISCONST, CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1) \
284 void METHOD(PARMTYPE1 PARMNAME1) ISCONST \
285 { \
286  if (!(DOMULTI)) \
287  { \
288  METHOD ## NoThread(PARMNAME1); \
289  return; \
290  } \
291  \
292  auto functor = [&](const UT_JobInfo &info) \
293  { METHOD ## Partial(PARMNAME1, info); return 0; }; \
294  UT_ThreadedAlgorithm alg; \
295  alg.run(functor); \
296 } \
297 \
298 void METHOD ## NoThread(PARMTYPE1 PARMNAME1) ISCONST \
299 { \
300  METHOD ## Partial(PARMNAME1, UT_JobInfo(0, 1, 0)); \
301 } \
302 /**/
303 
304 #define THREADED_METHOD2_INTERNAL(ISCONST, CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2) \
305 void METHOD(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2) ISCONST \
306 { \
307  if (!(DOMULTI)) \
308  { \
309  METHOD ## NoThread(PARMNAME1, PARMNAME2); \
310  return; \
311  } \
312  \
313  auto functor = [&](const UT_JobInfo &info) \
314  { METHOD ## Partial(PARMNAME1, PARMNAME2, info); return 0; }; \
315  UT_ThreadedAlgorithm alg; \
316  alg.run(functor); \
317 } \
318 \
319 void METHOD ## NoThread(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2) ISCONST \
320 { \
321  METHOD ## Partial(PARMNAME1, PARMNAME2, UT_JobInfo(0, 1, 0)); \
322 } \
323 /**/
324 
325 #define THREADED_METHOD3_INTERNAL(ISCONST, CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3) \
326 void METHOD(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3) ISCONST \
327 { \
328  if (!(DOMULTI)) \
329  { \
330  METHOD ## NoThread(PARMNAME1, PARMNAME2, PARMNAME3); \
331  return; \
332  } \
333  \
334  auto functor = [&](const UT_JobInfo &info) \
335  { METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, info); return 0; }; \
336  UT_ThreadedAlgorithm alg; \
337  alg.run(functor); \
338 } \
339 \
340 void METHOD ## NoThread(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3) ISCONST \
341 { \
342  METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, UT_JobInfo(0, 1, 0)); \
343 } \
344 /**/
345 
346 #define THREADED_METHOD4_INTERNAL(ISCONST, CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4) \
347 void METHOD(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4) ISCONST \
348 { \
349  if (!(DOMULTI)) \
350  { \
351  METHOD ## NoThread(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4); \
352  return; \
353  } \
354  \
355  auto functor = [&](const UT_JobInfo &info) \
356  { METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, info); return 0; }; \
357  UT_ThreadedAlgorithm alg; \
358  alg.run(functor); \
359 } \
360 \
361 void METHOD ## NoThread(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4) ISCONST \
362 { \
363  METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, UT_JobInfo(0, 1, 0)); \
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(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5) ISCONST \
369 { \
370  if (!(DOMULTI)) \
371  { \
372  METHOD ## NoThread(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5); \
373  return; \
374  } \
375  \
376  auto functor = [&](const UT_JobInfo &info) \
377  { METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, info); return 0; }; \
378  UT_ThreadedAlgorithm alg; \
379  alg.run(functor); \
380 } \
381 \
382 void METHOD ## NoThread(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5) ISCONST \
383 { \
384  METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, UT_JobInfo(0, 1, 0)); \
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(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5, PARMTYPE6 PARMNAME6) ISCONST \
390 { \
391  if (!(DOMULTI)) \
392  { \
393  METHOD ## NoThread(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6); \
394  return; \
395  } \
396  \
397  auto functor = [&](const UT_JobInfo &info) \
398  { METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, info); return 0; }; \
399  UT_ThreadedAlgorithm alg; \
400  alg.run(functor); \
401 } \
402 \
403 void METHOD ## NoThread(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5, PARMTYPE6 PARMNAME6) ISCONST \
404 { \
405  METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, UT_JobInfo(0, 1, 0)); \
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(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5, PARMTYPE6 PARMNAME6, PARMTYPE7 PARMNAME7) ISCONST \
411 { \
412  if (!(DOMULTI)) \
413  { \
414  METHOD ## NoThread(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7); \
415  return; \
416  } \
417  \
418  auto functor = [&](const UT_JobInfo &info) \
419  { METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7, info); return 0; }; \
420  UT_ThreadedAlgorithm alg; \
421  alg.run(functor); \
422 } \
423 \
424 void METHOD ## NoThread(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5, PARMTYPE6 PARMNAME6, PARMTYPE7 PARMNAME7) ISCONST \
425 { \
426  METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7, UT_JobInfo(0, 1, 0)); \
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(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5, PARMTYPE6 PARMNAME6, PARMTYPE7 PARMNAME7, PARMTYPE8 PARMNAME8) ISCONST \
432 { \
433  if (!(DOMULTI)) \
434  { \
435  METHOD ## NoThread(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7, PARMNAME8); \
436  return; \
437  } \
438  \
439  auto functor = [&](const UT_JobInfo &info) \
440  { METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7, PARMNAME8, info); return 0; }; \
441  UT_ThreadedAlgorithm alg; \
442  alg.run(functor); \
443 } \
444 \
445 void METHOD ## NoThread(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5, PARMTYPE6 PARMNAME6, PARMTYPE7 PARMNAME7, PARMTYPE8 PARMNAME8) ISCONST \
446 { \
447  METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7, PARMNAME8, UT_JobInfo(0, 1, 0)); \
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(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5, PARMTYPE6 PARMNAME6, PARMTYPE7 PARMNAME7, PARMTYPE8 PARMNAME8, PARMTYPE9 PARMNAME9) ISCONST \
453 { \
454  if (!(DOMULTI)) \
455  { \
456  METHOD ## NoThread(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7, PARMNAME8, PARMNAME9); \
457  return; \
458  } \
459  \
460  auto functor = [&](const UT_JobInfo &info) \
461  { METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7, PARMNAME8, PARMNAME9, info); return 0; }; \
462  UT_ThreadedAlgorithm alg; \
463  alg.run(functor); \
464 } \
465 \
466 void METHOD ## NoThread(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5, PARMTYPE6 PARMNAME6, PARMTYPE7 PARMNAME7, PARMTYPE8 PARMNAME8, PARMTYPE9 PARMNAME9) ISCONST \
467 { \
468  METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7, PARMNAME8, PARMNAME9, UT_JobInfo(0, 1, 0)); \
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(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5, PARMTYPE6 PARMNAME6, PARMTYPE7 PARMNAME7, PARMTYPE8 PARMNAME8, PARMTYPE9 PARMNAME9, PARMTYPE10 PARMNAME10) ISCONST \
474 { \
475  if (!(DOMULTI)) \
476  { \
477  METHOD ## NoThread(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7, PARMNAME8, PARMNAME9, PARMNAME10); \
478  return; \
479  } \
480  \
481  auto functor = [&](const UT_JobInfo &info) \
482  { METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7, PARMNAME8, PARMNAME9, PARMNAME10, info); return 0; }; \
483  UT_ThreadedAlgorithm alg; \
484  alg.run(functor); \
485 } \
486 \
487 void METHOD ## NoThread(PARMTYPE1 PARMNAME1, PARMTYPE2 PARMNAME2, PARMTYPE3 PARMNAME3, PARMTYPE4 PARMNAME4, PARMTYPE5 PARMNAME5, PARMTYPE6 PARMNAME6, PARMTYPE7 PARMNAME7, PARMTYPE8 PARMNAME8, PARMTYPE9 PARMNAME9, PARMTYPE10 PARMNAME10) ISCONST \
488 { \
489  METHOD ## Partial(PARMNAME1, PARMNAME2, PARMNAME3, PARMNAME4, PARMNAME5, PARMNAME6, PARMNAME7, PARMNAME8, PARMNAME9, PARMNAME10, UT_JobInfo(0, 1, 0)); \
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)
GLuint start
Definition: glcorearb.h:474
#define UT_API
Definition: UT_API.h:13
UT_AutoJobInfoLock(const UT_JobInfo &lock)
int64 exint
Definition: SYS_Types.h:116
GLuint GLuint end
Definition: glcorearb.h:474
GLfloat units
Definition: glcorearb.h:407
int int32
Definition: SYS_Types.h:35
void lock() const
int numJobs() const
void unlock() const
SYS_AtomicInt32 * myTask
int job() const