00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef __GZ_THREAD_H__
00023 #define __GZ_THREAD_H__
00024
00033 #include "gzBasicTypes.h"
00034 #include "gzMemory.h"
00035 #include "gzMutex.h"
00036 #include "gzReference.h"
00037 #include "gzStackInfo.h"
00038
00040 const gzULong GZ_SLEEP_SECOND=1000;
00041
00043 const gzULong GZ_SLEEP_INFINITE=0xFFFFFFFFUL;
00044
00045 #if defined GZ_WINDOWS
00046
00047 #if !defined GZ_WINCE
00048
00049 #include <process.h>
00050
00051 typedef gzUInt gzThreadReturnValue;
00052
00053 typedef struct
00054 {
00055 gzUInt info;
00056 HANDLE handle;
00057 } gzThreadInfo;
00058 #else
00059
00060 typedef gzULong gzThreadReturnValue;
00061
00062 typedef struct
00063 {
00064 gzULong info;
00065 HANDLE handle;
00066 HANDLE thread;
00067
00068 } gzThreadInfo;
00069 #endif
00070
00071 #elif defined GZ_UNIX
00072
00073
00074
00075 #include <unistd.h>
00076
00077 typedef struct
00078 {
00079 pthread_t info;
00080
00081 } gzThreadInfo;
00082
00083 typedef gzVoid * gzThreadReturnValue;
00084
00085 #endif
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00123 enum gzThreadPriority { GZ_THREAD_PRIO_LOWEST, GZ_THREAD_PRIO_LOW, GZ_THREAD_PRIO_NORMAL, GZ_THREAD_PRIO_HIGH, GZ_THREAD_PRIO_HIGHEST };
00124
00125 const gzULong GZ_THREADSLOTS=10000;
00126
00127 class GZ_BASE_EXPORT gzThread : public gzMemoryCheck ,
00128 public gzProgramExecution
00129 {
00130 public:
00131
00132 gzThread(gzThreadPriority prio=GZ_THREAD_PRIO_NORMAL);
00133
00134 virtual ~gzThread();
00135
00136 virtual gzVoid stop(gzBool waitForStop=FALSE);
00137
00138 virtual gzBool run();
00139
00140
00141
00142 gzBool isRunning();
00143
00144 gzBool isStopping();
00145
00146 gzVoid tickAlive();
00147
00148 gzVoid setTickLimit(gzDouble tickLimit);
00149
00150 gzDouble getTickLimit();
00151
00152 gzVoid setThreadPriority(gzThreadPriority prio);
00153
00154 gzVoid kill();
00155
00156 gzVoid setAutoDelete(gzBool deleteAfterTermination);
00157
00158 gzThreadInfo getThreadInfo() const;
00159
00160
00161
00162
00163 static gzVoid gzDelayFunction( gzULong milliseconds , gzEvent *event=NULL);
00164 static gzVoid gzMicroDelayFunction( gzULong microseconds);
00165
00166 static gzULong getThreadID();
00167 static gzULong getThreadEnum(gzULong threadID=0);
00168
00169 protected:
00170
00171 friend gzThreadReturnValue GZ_CALLBACK sprocess(gzVoid *pek);
00172
00173 virtual gzVoid process();
00174
00175 virtual gzVoid onProgramExecution();
00176
00177 gzVoid wrapproc();
00178
00179 gzVoid tickAlive_unsafe();
00180 gzBool isRunning_unsafe();
00181 gzBool isStopping_unsafe();
00182
00183 gzMutex m_mutex;
00184
00185 gzBool m_stop:1;
00186
00187 gzBool m_run:1;
00188
00189 gzBool m_autoDelete:1;
00190
00191 gzThreadInfo m_pInfo;
00192
00193 gzDouble m_tickAliveTime;
00194
00195 gzDouble m_tickLimit;
00196
00197 gzThreadPriority m_priority;
00198
00199 };
00200
00201 #define gzSleep gzThread::gzDelayFunction
00202
00203 #define gzMicroSleep gzThread::gzMicroDelayFunction
00204
00205 typedef enum { GZ_TICK_ACCUM , GZ_TICK_SKIP } gzTickPolicy;
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 class gzThreadTicker
00223 {
00224 public:
00225
00226 GZ_BASE_EXPORT gzThreadTicker(gzULong pool,gzThreadPriority prio=GZ_THREAD_PRIO_NORMAL);
00227
00228 GZ_BASE_EXPORT virtual ~gzThreadTicker();
00229
00230 GZ_BASE_EXPORT virtual gzVoid onInitialize(){}
00231
00232 GZ_BASE_EXPORT virtual gzVoid onTerminate(){}
00233
00234 GZ_BASE_EXPORT virtual gzVoid onTick(){}
00235
00236 GZ_BASE_EXPORT gzVoid setTickInterval(gzDouble interval);
00237
00238 GZ_BASE_EXPORT gzVoid setTickPolicy(gzTickPolicy policy);
00239
00241 GZ_BASE_EXPORT gzBool triggerTick(gzDouble waitDelay=0);
00242
00243 GZ_BASE_EXPORT gzVoid disableThreadTicker();
00244
00245 GZ_BASE_EXPORT gzVoid enableThreadTicker();
00246
00247 GZ_BASE_EXPORT gzVoid deleteThreadTicker();
00248
00249 GZ_BASE_EXPORT gzBool isEnabled();
00250
00251 GZ_BASE_EXPORT gzULong getPoolID();
00252
00253 GZ_PROPERTY_EXPORT_( gzULong , MinPoolSleepTicks ,GZ_BASE_EXPORT);
00254
00255 private:
00256
00257 friend class gzThreadPoolTicker;
00258
00259 gzDouble m_interval;
00260
00261 gzDouble m_nextTick;
00262
00263 gzDouble m_oneShot;
00264
00265 gzULong m_poolID;
00266
00267 gzTickPolicy m_policy;
00268
00269 gzThreadPriority m_priority;
00270
00271 gzMutex m_lock;
00272
00273 gzMutex m_trigger;
00274
00275 gzBool m_enabled;
00276 };
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 class gzThreadPoolTicker : public gzReference , public gzThread
00293 {
00294 public:
00295
00296 GZ_BASE_EXPORT virtual ~gzThreadPoolTicker();
00297
00298 GZ_BASE_EXPORT virtual gzBool useDeepCopy();
00299
00300 GZ_BASE_EXPORT static gzVoid guiTick();
00301
00302 private:
00303
00304 friend class gzThreadTicker;
00305
00306 GZ_BASE_EXPORT gzThreadPoolTicker(gzULong pool,gzThreadPriority prio);
00307
00308 gzVoid addSubscriber(gzThreadTicker *subscriber);
00309
00310 gzVoid removeSubscriber(gzThreadTicker *subscriber);
00311
00312 gzBool checkSubscriptions(gzULong &minSleepTicks);
00313
00314 gzVoid checkMinTickDelay();
00315
00316 virtual gzVoid process();
00317
00318 gzBool processWork();
00319
00320
00321
00322 gzULong m_poolID;
00323
00324 gzList<gzThreadTicker> m_subscribers;
00325
00326 gzList<gzThreadTicker> m_addSubscribers;
00327
00328 gzList<gzThreadTicker> m_removeSubscribers;
00329
00330 gzList<gzThreadTicker> m_deleteSubscribers;
00331
00332 gzMutex m_addSubscriberLock;
00333
00334 gzMutex m_removeSubscriberLock;
00335
00336 gzMutex m_deleteSubscriberLock;
00337
00338 gzDouble m_minTickDelay;
00339
00340 gzEvent m_event;
00341
00342 static gzRefPointer<gzThreadPoolTicker> getThreadPoolTicker(gzULong pool,gzThreadPriority prio=GZ_THREAD_PRIO_NORMAL);
00343
00344 static gzMemCheck<gzMutex> s_threadPoolLock;
00345
00346 static gzRefList<gzThreadPoolTicker> s_threadPool;
00347 };
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363 template <class T> class gzThreadData
00364 {
00365 public:
00366
00367 gzThreadData(gzUByte indexCount=1);
00368
00369 virtual ~gzThreadData();
00370
00371 operator T &();
00372
00373 T & operator[](gzUByte index);
00374
00375 T & get() { return operator T&(); }
00376
00377 gzVoid set(const T & data);
00378
00379 private:
00380
00381 template <class T2> class _localData : public gzReference
00382 {
00383 public:
00384
00385 _localData(gzUByte indexCount):data(indexCount),index(0)
00386 {
00387 }
00388
00389 virtual ~_localData()
00390 {
00391 }
00392
00393 gzArray<T2> data;
00394 gzUByte index;
00395 };
00396
00397 gzULong m_currentThreadID;
00398
00399 gzRefPointer<_localData<T> > m_currentData;
00400
00401 gzRefDict<gzValueCompareInterface,_localData<T> > m_dict;
00402
00403 gzMutex m_locker;
00404
00405 gzUByte m_indexCount;
00406 };
00407
00408 template <class T> inline gzThreadData<T>::gzThreadData(gzUByte indexCount):
00409 m_currentThreadID(0),
00410 m_locker(FALSE),
00411 m_indexCount(indexCount)
00412 {
00413 }
00414
00415 template <class T> gzThreadData<T>::~gzThreadData()
00416 {
00417 m_locker.waitLock();
00418
00419 m_dict.clear();
00420 m_currentData=0;
00421
00422 m_locker.unLock();
00423 }
00424
00425
00426 template <class T> inline gzVoid gzThreadData<T>::set(const T & data)
00427 {
00428 operator T&()=data;
00429 }
00430
00431 template <class T> inline gzThreadData<T>::operator T &()
00432 {
00433 GZ_BODYGUARD(m_locker);
00434
00435 gzULong threadID=gzThread::getThreadID();
00436
00437 if(m_currentThreadID!=threadID)
00438 {
00439 _localData<T> *refData=m_dict.find(threadID);
00440
00441 if(!refData)
00442 {
00443 refData=new _localData<T>(m_indexCount);
00444 m_dict.enter(threadID,refData);
00445 }
00446
00447 m_currentThreadID=threadID;
00448 m_currentData=refData;
00449 }
00450
00451 T & retval = m_currentData->data[m_currentData->index];
00452
00453 m_currentData->index=(m_currentData->index+1)%m_indexCount;
00454
00455 return retval;
00456 }
00457
00458 template <class T> inline T & gzThreadData<T>::operator [](gzUByte index)
00459 {
00460 GZ_BODYGUARD(m_locker);
00461
00462 gzULong threadID=gzThread::getThreadID();
00463
00464 if(m_currentThreadID!=threadID)
00465 {
00466 _localData<T> *refData=m_dict.find(threadID);
00467
00468 if(!refData)
00469 {
00470 refData=new _localData<T>(m_indexCount);
00471 m_dict.enter(threadID,refData);
00472 }
00473
00474 m_currentThreadID=threadID;
00475 m_currentData=refData;
00476 }
00477
00478 if(index<m_indexCount)
00479 return m_currentData->data[index];
00480
00481 throwFatalTemplateError("gzThreadData [] index out of bounds");
00482 }
00483
00484 #endif //__GZ_THREAD_H__
00485
00486