00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef __UT_Thread__
00028 #define __UT_Thread__
00029
00030 #include "UT_API.h"
00031 #include <stdlib.h>
00032 #include <SYS/SYS_Types.h>
00033 #include "UT_Assert.h"
00034 #include "UT_Defines.h"
00035
00036 #if defined(WIN32)
00037 typedef int ut_thread_id_t;
00038 #elif defined(USE_PTHREADS)
00039 #include <pthread.h>
00040 typedef pthread_t ut_thread_id_t;
00041 #else
00042 #error Unsupported Platform for UT_Thread
00043 #endif
00044
00045 #define UT_INVALID_THREAD_ID ((ut_thread_id_t)0)
00046
00047
00048 #define UT_THREAD_DEFAULT_STACK_SIZE (8U*1024U*1024U)
00049 #define UT_THREAD_SMALL_STACK_SIZE (1U*1024U*1024U)
00050
00051 typedef void *(*UTthreadFunc)(void*);
00052
00053
00054 class UT_TaskScope;
00055
00056 class UT_API UT_Thread
00057 {
00058 public:
00059
00060
00061 virtual ~UT_Thread();
00062
00063
00064
00065
00066 enum {
00067 ThreadIdle,
00068 ThreadRunning
00069 };
00070
00071
00072
00073
00074
00075
00076 enum {
00077 ThreadSingleRun,
00078 ThreadLowUsage,
00079 };
00080
00081 static UT_Thread *allocThread(int spin_mode);
00082
00083 static int getNumProcessors();
00084
00085
00086
00087
00088
00089 static void resetNumProcessors();
00090
00091
00092 #if defined(USE_PTHREADS)
00093 static ut_thread_id_t getMyThreadId() { return pthread_self(); }
00094 #else
00095 static ut_thread_id_t getMyThreadId();
00096 #endif
00097
00098 static ut_thread_id_t getMainThreadId();
00099 static int getMainSequentialThreadId();
00100 static inline int isMainThread()
00101 {
00102 return getMyThreadId() == getMainThreadId();
00103 }
00104
00105
00106
00107
00108
00109
00110
00111
00112 static int getMySequentialThreadIndex();
00113
00114
00115
00116
00117 static int getFirstSequentialThreadIndex() { return 1; }
00118
00119
00120
00121
00122
00123
00124 static void configureMaxThreads(int maxthreads = -1,
00125 int stacksize = -1);
00126
00127
00128
00129
00130 virtual bool startThread(UTthreadFunc func, void *data) = 0;
00131
00132
00133
00134 virtual void threadStarted();
00135
00136
00137
00138 virtual void threadEnded();
00139
00140
00141
00142
00143
00144
00145
00146 virtual int isResourceHog() const;
00147
00148
00149 virtual int getState();
00150 virtual int getSpinMode();
00151 virtual void waitForState(int desired) = 0;
00152 virtual void setSpinMode(int spin_mode);
00153
00154
00155 virtual void killThread() = 0;
00156
00157
00158
00159 virtual int niceThread(int priority) = 0;
00160 virtual int suspendThread() = 0;
00161 virtual int restartThread() = 0;
00162
00163 int isActive()
00164 { return waitThread(0); }
00165
00166 static void interval(int count, int thisSection, int numSections,
00167 int &start, int &len)
00168 {
00169 start = (int)(thisSection*count/(fpreal)numSections+0.5F);
00170 len = (int)((thisSection+1)*count/(fpreal)numSections+0.5F) -
00171 start;
00172 }
00173
00174 protected:
00175
00176
00177
00178
00179 virtual int waitThread(int block=1) = 0;
00180
00181
00182 virtual int isValid();
00183
00184
00185 void killIdle();
00186
00187 static void *threadWrapper(void *data);
00188
00189
00190 virtual void setState(int state) = 0;
00191
00192 volatile int myState;
00193 int mySpinMode;
00194 UTthreadFunc myCallback;
00195 void *myCBData;
00196
00197 const UT_TaskScope *myTaskScope;
00198
00199 UT_Thread(int spin_mode);
00200 };
00201
00202
00203
00204 class UT_API UT_NullThread : public UT_Thread
00205 {
00206 public:
00207 UT_NullThread();
00208 virtual ~UT_NullThread();
00209
00210 virtual bool startThread(UTthreadFunc func, void *data);
00211 virtual void killThread();
00212 virtual int waitThread(int block);
00213 virtual void waitForState(int );
00214
00215 virtual int niceThread(int priority);
00216 virtual int suspendThread();
00217 virtual int restartThread();
00218
00219 protected:
00220 virtual void setState(int state);
00221 };
00222
00223
00224 class UT_API UT_ThreadSet
00225 {
00226 public:
00227 UT_ThreadSet(int nthreads=-1, int null_thread_if_1_cpu = 0);
00228 ~UT_ThreadSet();
00229
00230 void setFunc(UTthreadFunc func)
00231 {
00232 myFunc = func;
00233 }
00234 void setUserData(void *user_data_array, size_t structlen)
00235 {
00236 myUserData = user_data_array;
00237 myUserDataInc = structlen;
00238 }
00239 void setUserData(void *user_data)
00240 {
00241 myUserData = user_data;
00242 myUserDataInc = 0;
00243 }
00244
00245 void reuse(int spin_mode);
00246 void go();
00247 int wait(int block=1);
00248
00249 int getNumThreads() const { return myThreadCount; }
00250 UT_Thread *getThread(int which);
00251 UT_Thread *operator[](int which)
00252 {
00253 UT_ASSERT_P(which < myThreadCount);
00254 return myThreads[which];
00255 }
00256
00257 protected:
00258 int myThreadCount;
00259 UT_Thread **myThreads;
00260 UTthreadFunc myFunc;
00261 void *myUserData;
00262 int64 myUserDataInc;
00263 };
00264
00265 class UT_API UT_ThreadFarm
00266 {
00267 public:
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 UT_ThreadFarm(int nthreads=-1);
00280 ~UT_ThreadFarm();
00281
00282
00283
00284
00285 UT_Thread *nextThread(int *thread_index =0,int block = 1);
00286
00287
00288
00289 int wait(int block = 1);
00290
00291 int getEntries() const { return myThreadCount; }
00292
00293 protected:
00294 int myThreadCount;
00295 UT_Thread **myThreads;
00296 };
00297
00298 static inline int
00299 UTgetSTID()
00300 {
00301 return UT_Thread::getMySequentialThreadIndex();
00302 }
00303
00304 #endif