HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_Thread.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_Thread.h ( UT Library, C++)
7  *
8  * COMMENTS: Generic thread class.
9  * The owner of the thread can do things like:
10  *
11  * killThread() - Stop execution of thread
12  * waitThread() - Wait until thread finishes execution
13  * suspendThread() - Suspend execution of thread
14  * restartThread() - Restart a stopped thread
15  * niceThread() - Prioritize thread (0 low priority, 100 high)
16  *
17  * TODO: It might be nice to have a way to get the exit status of a thread.
18  */
19 
20 #ifndef __UT_Thread__
21 #define __UT_Thread__
22 
23 #include "UT_API.h"
24 #include "UT_Assert.h"
25 #include "UT_Defines.h"
26 
27 #include <SYS/SYS_Deprecated.h>
29 #include <SYS/SYS_Types.h>
30 
31 #include <stdlib.h>
32 
33 #if defined(WIN32)
34 # include <intrin.h>
35  typedef int ut_thread_id_t;
36 #elif defined(USE_PTHREADS)
37 # include <sched.h>
38 # include <pthread.h>
39  typedef pthread_t ut_thread_id_t;
40 #else
41  #error Unsupported Platform for UT_Thread
42 #endif
43 
44 #define UT_INVALID_THREAD_ID ((ut_thread_id_t)0)
45 
46 // some stack size defines
47 #define UT_THREAD_DEFAULT_STACK_SIZE (8U*1024U*1024U)
48 #define UT_THREAD_SMALL_STACK_SIZE (1U*1024U*1024U)
49 
50 typedef void *(*UTthreadFunc)(void*);
51 
52 // forward declarations
53 class UT_TaskScope;
54 
56 {
57 public:
58  // The destructor will wait until the thread is idle before it completes
59  // If you wish to kill the thread, call killThread() first.
60  virtual ~UT_Thread();
61 
62  // This enum specifies the current state for a persistent thread. The
63  // thread will typically be running or idle. If the thread is idle, it's
64  // behaviour will be determined by the SpinState.
65  enum State
66  {
68  ThreadRunning
69  };
70 
71  // // The thread status determines how the thread will behave once the
72  // callback function is completed:
73  // ThreadSingleRun - The thread cannot be restarted
74  // ThreadLowUsage - The thread will yeild cycles while idle
75  //
76  enum SpinMode
77  {
80  };
81 
82  static UT_Thread *allocThread(SpinMode spin_mode);
83 
84  static int getNumProcessors();
85 
86  /// This is only valid in debug builds
87  static int activeThreadCount();
88 
89  /// Reset the number of threads that is used by Houdini. This will reread
90  /// the HOUDINI_MAXTHREADS setting.
91  /// @note There should be no active tasks when this is called.
92  /// @note Only call this from the MAIN THREAD!
93  static void resetNumProcessors();
94 
95  // getMyThreadId() is inlined for speed if we're using pthreads.
96 #if defined(USE_PTHREADS)
97  static ut_thread_id_t getMyThreadId() { return pthread_self(); }
98 #else
99  static ut_thread_id_t getMyThreadId();
100 #endif
101 
102  static ut_thread_id_t getMainThreadId();
103  static int getMainSequentialThreadId();
104  static inline int isMainThread()
105  {
106  return getMyThreadId() == getMainThreadId();
107  }
108 
109  /// Returns true if the current thread is a UT_Thread.
110  /// Returns false if the current thread is either the main thread
111  /// or a TBB thread.
112  static bool isUTThreadCurrent();
113 
114  /// Returns true iff the current thread is allowed to create more tasks.
115  /// This is sometimes disabled, to avoid needing to create a UT_TaskArena
116  /// for small cases that won't get much benefit from threading.
117  /// This should be checked by anything using tbb::parallel_for,
118  /// tbb::parallel_invoke, or anything else creating TBB tasks.
119  static bool isThreadingEnabled();
120 
121  /// This is used to disable (false) threading for the current thread,
122  /// to avoid needing to create a UT_TaskArena for small cases that won't
123  /// get much benefit from threading. It returns if it was enabled before.
124  /// It is also used to re-enable (true) threading for the current thread.
125  static bool setThreadingEnabled(bool will_be_enabled);
126 
128  {
129  public:
131  : myPreviouslyEnabled(setThreadingEnabled(false))
132  {}
134  {
135  if (myPreviouslyEnabled)
136  setThreadingEnabled(true);
137  }
138  private:
139  const bool myPreviouslyEnabled;
140  };
141 
142  // CPU pauses the task for a given number of cycles
143  static inline void pause(uint cycles)
144  {
145  for(uint i = 0; i < cycles; i++)
146 #if defined(USE_PTHREADS)
147  __asm__ __volatile__("pause;");
148 #else
149  _mm_pause();
150 #endif
151  }
152  // Yields the task to the scheduler.
153 #if defined(USE_PTHREADS)
154  static inline void yield(bool higher_only=false)
155  {
156  if (higher_only)
157  {
158  ::sched_yield();
159  }
160  else
161  {
162  // Sleep for 100ns. That's 10,000,000 sleep
163  // cycles a second (in case you don't have a
164  // calculator :-)
165  struct timespec ts = {0,100};
166  ::nanosleep(&ts, 0);
167  }
168  }
169 #else
170  static void yield(bool higher_only=false);
171 #endif
172 
173  /// This function has been deprecated. Use SYS_SequentialThreadIndex::get()
174  /// or SYSgetSTID instead.
175  static int SYS_DEPRECATED(12.5) getMySequentialThreadIndex()
176  { return SYS_SequentialThreadIndex::get(); }
177 
178  /// Configure the global number of tasks used by the system and the default
179  /// stack size for threads. For the @c stacksize:
180  /// - A value of -1 leaves the stack size unchanged
181  /// - A value of 0 uses the stack size of the main thread
182  /// - A value larger than 0 will use that specific stack size
183  /// @note Only call this in the main thread when there are no tasks active.
184  /// @note This function is NOT thread-safe.
185  static void configureMaxThreads(int maxthreads = -1,
186  int stacksize = -1);
187 
188  /// Returns true if configureMaxThreads() has been called at least once
189  static bool isMaxThreadsConfigured();
190 
191  /// Return function pointer to terminate task scheduler that is activated
192  /// by configureMaxThreads(). This function should called prior to exit()
193  /// in order to avoid possible deadlocks when the process exits. Note that
194  /// multiple calls to the termination function are handled by only
195  /// terminating the first time. After that, no task scheduling is allowed.
196  using TerminateFunc = void (*)();
197  static TerminateFunc getTaskSchedulerExitCallback();
198 
199  // Start the thread running. If the thread is not in idle state, the
200  // thread will wait until it's in idle before starting. If the thread
201  // doesn't exist yet, it will be created.
202  virtual bool startThread(UTthreadFunc func, void *data,
203  int stacksize) = 0;
204 
205  // Use the global thread stack size set by configureMaxThreads()
206  bool startThread(UTthreadFunc func, void *data);
207 
208  // This method is called when the thread function is first entered.
209  // By default it does nothing but some sub-classes may need this.
210  virtual void threadStarted();
211 
212  // This method is called when the thread function is returned from.
213  // By default it sets the state to idle.
214  virtual void threadEnded();
215 
216 
217  // Some thread architectures have very expensive resources (i.e. sproc()
218  // threads). While these threads spin (are idle), they consume system
219  // resources. This method will let the user know whether the threads are
220  // resource hogs (so that if they spin for a long time, they could
221  // possibley be cleaned up).
222  virtual int isResourceHog() const;
223 
224  // For persistent threads (which get restarted)
225  virtual State getState();
226  virtual SpinMode getSpinMode();
227  virtual void waitForState(State desired) = 0;
228  virtual void setSpinMode(SpinMode spin_mode);
229 
230  // Terminate the thread process
231  virtual void killThread() = 0;
232 
233  // If it's possible to perform these tasks, the return code will be 1. If
234  // not, the return code will be 0. Not all
235  virtual int niceThread(int priority) = 0;
236  virtual int suspendThread() = 0;
237  virtual int restartThread() = 0;
238 
239  int isActive()
240  { return waitThread(0); }
241 
242  static void interval(int count, int thisSection, int numSections,
243  int &start, int &len)
244  {
245  start = (int)(thisSection*count/(fpreal)numSections+0.5F);
246  len = (int)((thisSection+1)*count/(fpreal)numSections+0.5F) -
247  start;
248  }
249 
250  /// NOTE: This level doesn't own any data apart from itself.
251  virtual int64 getMemoryUsage(bool inclusive) const = 0;
252 
253 protected:
254  // System dependent internal functions.
255  // waitThread() returns 1 if the thread is still active (i.e. exists) and
256  // should return 0 if the thread doesn't exist. If waitThread detects
257  // that the thread no longer exists, it should do appropriate cleanup.
258  virtual int waitThread(int block=1) = 0;
259 
260  // Quick check to see that the thread is really active
261  virtual int isValid();
262 
263  // This method can be used to kill an idle process.
264  void killIdle();
265 
266  static void *threadWrapper(void *data);
267 
268  // Internally used to change the state safely.
269  virtual void setState(State state) = 0;
270 
271  volatile State myState;
274  void *myCBData;
275 
277 
278  UT_Thread(SpinMode spin_mode);
279 };
280 
281 // For debugging, the following uses a single thread (i.e. is not
282 // multi-threaded)
284 {
285 public:
286  UT_NullThread();
287  virtual ~UT_NullThread();
288 
289  virtual bool startThread(UTthreadFunc func, void *data,
290  int stacksize);
291  virtual void killThread();
292  virtual int waitThread(int block);
293  virtual void waitForState(State);
294 
295  virtual int niceThread(int priority);
296  virtual int suspendThread();
297  virtual int restartThread();
298 
299  virtual int64 getMemoryUsage(bool inclusive) const
300  {
301  int64 mem = inclusive ? sizeof(*this) : 0;
302  // NOTE: We don't know how much memory Windows uses,
303  // so we can't count it.
304  return mem;
305  }
306 
307 protected:
308  virtual void setState(State state);
309 };
310 
311 
313 {
314 public:
315  UT_ThreadSet(int nthreads=-1, int null_thread_if_1_cpu = 0);
316  ~UT_ThreadSet();
317 
319  {
320  myFunc = func;
321  }
322  void setUserData(void *user_data_array, size_t structlen)
323  {
324  myUserData = user_data_array;
325  myUserDataInc = structlen;
326  }
327  void setUserData(void *user_data)
328  {
329  myUserData = user_data;
330  myUserDataInc = 0;
331  }
332 
333  void reuse(UT_Thread::SpinMode spin_mode);
334  void go();
335  int wait(int block=1);
336 
337  int getNumThreads() const { return myThreadCount; }
338  UT_Thread *getThread(int which);
339  UT_Thread *operator[](int which)
340  {
341  UT_ASSERT_P(which < myThreadCount);
342  return myThreads[which];
343  }
344 
345 protected:
349  void *myUserData;
351 };
352 
354 {
355 public:
357  {
358  NON_BLOCKING = 0, // Only assign thread if one is available
359  BLOCKING = 1, // Block until a thread is free.
360  DYNAMIC = 2 // If no threads are availble, create a new one.
361  };
362 
363  // similar to UT_ThreadSet, but a bit simpler. Called UT_ThreadFarm
364  // because it farms out the next available thread. You also don't need to
365  // match the number of data chunks to the number of threads.
366  // ie.
367  // farm = new UT_ThreadFarm(4);
368  // while(!done) {
369  // thread = farm->nextThread();
370  // thread->startThread(entrypoint, mydata);
371  // }
372  // farm->wait();
373 
374  UT_ThreadFarm(int nthreads=-1);
375  ~UT_ThreadFarm();
376 
377  // waits for the next available thread, (or returns null if none are
378  // available and block = 0). thread_index will contain the thread index
379  // if you pass it a non-null pointer.
380  UT_Thread *nextThread(int *thread_index =0,
381  AssignmentStyle style = BLOCKING);
382 
383  // waits until all threads are finished (or, returns 0 if not finished and
384  // block = 0).
385  int wait(int block = 1);
386 
387  // deletes threads in the thread farm. if kill=1 the threads are killed before
388  // cleanup, otherwise wait(1) is called.
389  void cleanup(int kill = 0);
390 
391  int getEntries() const { return myThreadCount; }
393  {
394  UT_ASSERT_P(index < myThreadCount);
395  return myThreads[index];
396  }
397 
398 protected:
399  void addThreads(int thread_count);
400 
403 };
404 
405 // Gradual backoff when there's thread contention.
407 {
408 public:
409  UT_ThreadBackoff() : myCycles(1) {}
410 
411  static const uint cycles_for_noop = 4;
412  static const uint cycles_for_pause = cycles_for_noop * 4;
413  static const uint cycles_for_yield_higher = cycles_for_pause * 2;
414  static const uint cycles_for_yield_all = cycles_for_yield_higher * 2;
415 
416  // Same thresholds as hboost::detail::yield(), but different behaviour
417  void wait()
418  {
419  if (myCycles > cycles_for_yield_all)
420  {
421  // Yield the thread completely, to any and all comers.
422  UT_Thread::yield(false);
423  return;
424  }
425 
426  if (myCycles <= cycles_for_noop)
427  {
428  // Noop.
429  }
430  else if (myCycles <= cycles_for_pause)
431  {
432  UT_Thread::pause(myCycles);
433  }
434  else if (myCycles <= cycles_for_yield_higher)
435  {
436  UT_Thread::yield(true);
437  }
438  myCycles += (myCycles+1)>>1;
439  }
440 
441  void reset()
442  {
443  myCycles = 1;
444  }
445 
446 private:
447  uint myCycles;
448 };
449 
450 // This function has been deprecated. Use SYSgetSTID instead.
451 static inline int SYS_DEPRECATED(12.5)
452 UTgetSTID()
453 {
455 }
456 
457 #endif
volatile State myState
Definition: UT_Thread.h:271
int getNumThreads() const
Definition: UT_Thread.h:337
void setUserData(void *user_data)
Definition: UT_Thread.h:327
#define SYS_DEPRECATED(__V__)
virtual int restartThread()=0
int myThreadCount
Definition: UT_Thread.h:346
GLuint start
Definition: glcorearb.h:474
void *(* UTthreadFunc)(void *)
Definition: UT_Thread.h:50
UTthreadFunc myCallback
Definition: UT_Thread.h:273
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
UT_Thread * operator[](int index)
Definition: UT_Thread.h:392
SpinMode mySpinMode
Definition: UT_Thread.h:272
void * myCBData
Definition: UT_Thread.h:274
#define UT_API
Definition: UT_API.h:13
png_uint_32 i
Definition: png.h:2877
UT_Thread * operator[](int which)
Definition: UT_Thread.h:339
int getEntries() const
Definition: UT_Thread.h:391
UT_Thread ** myThreads
Definition: UT_Thread.h:347
virtual int64 getMemoryUsage(bool inclusive) const
NOTE: This level doesn't own any data apart from itself.
Definition: UT_Thread.h:299
long long int64
Definition: SYS_Types.h:107
virtual void setState(State state)=0
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:125
int myThreadCount
Definition: UT_Thread.h:401
virtual void waitForState(State desired)=0
void setFunc(UTthreadFunc func)
Definition: UT_Thread.h:318
virtual bool startThread(UTthreadFunc func, void *data, int stacksize)=0
virtual void killThread()=0
GLboolean * data
Definition: glcorearb.h:130
int64 myUserDataInc
Definition: UT_Thread.h:350
const UT_TaskScope * myTaskScope
Definition: UT_Thread.h:276
unsigned int uint
Definition: SYS_Types.h:40
GLint GLsizei count
Definition: glcorearb.h:404
virtual int suspendThread()=0
double fpreal
Definition: SYS_Types.h:270
virtual int niceThread(int priority)=0
static int isMainThread()
Definition: UT_Thread.h:104
GLenum func
Definition: glcorearb.h:782
static void interval(int count, int thisSection, int numSections, int &start, int &len)
Definition: UT_Thread.h:242
typedef int
Definition: png.h:1175
UTthreadFunc myFunc
Definition: UT_Thread.h:348
GLuint index
Definition: glcorearb.h:785
UT_Thread ** myThreads
Definition: UT_Thread.h:402
static void pause(uint cycles)
Definition: UT_Thread.h:143
int isActive()
Definition: UT_Thread.h:239
static void yield(bool higher_only=false)
virtual int waitThread(int block=1)=0
void * myUserData
Definition: UT_Thread.h:349
void setUserData(void *user_data_array, size_t structlen)
Definition: UT_Thread.h:322