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