Gizmo3D

gzThread.h

Go to the documentation of this file.
00001 // *****************************************************************************
00002 // File         : gzThread.h
00003 // Module       : gzBase
00004 // Description  : Class definition of Thread classes.
00005 // Author       : Anders Modén      
00006 // Product      : GizmoBase 2.1.1
00007 //      
00008 // Copyright © 2003- Saab Training Systems AB, Sweden       
00009 //          
00010 // NOTE:    GizmoBase is a platform abstraction utility layer for C++. It contains 
00011 //          design patterns and C++ solutions for the advanced programmer.
00012 //
00013 //
00014 // Revision History...                          
00015 //                                  
00016 // Who  Date    Description                     
00017 //                                  
00018 // AMO  981104  Created file    
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;        // Thread ID
00056             HANDLE handle;
00057         } gzThreadInfo;
00058 #else
00059 
00060 typedef gzULong  gzThreadReturnValue;
00061 
00062 typedef struct 
00063         {
00064             gzULong info;       // Thread ID
00065             HANDLE handle;
00066             HANDLE thread;
00067 
00068         } gzThreadInfo;
00069 #endif
00070 
00071 #elif defined GZ_UNIX
00072 
00073 // --------------------------------  UNIX ----------------------------------
00074 
00075 #include <unistd.h>
00076 
00077 typedef struct 
00078         {
00079             pthread_t info;     // Thread ID
00080 
00081         } gzThreadInfo;
00082 
00083 typedef gzVoid *        gzThreadReturnValue;
00084 
00085 #endif
00086 
00087 
00088 // ******************** class definitions ***************************************
00089 
00090 //******************************************************************************
00091 // Class    : gzThread
00092 //                                  
00093 // Purpose  : - 
00094 //                                  
00095 // Notes    : - 
00096 //                                  
00097 // Revision History...                          
00098 //                                  
00099 // Who  Date    Description                     
00100 //                                  
00101 // AMO  981104  Created 
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;     // Number of possible enums
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     // static utilities
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 // Class    : gzThreadTicker
00209 //                                  
00210 // Purpose  : To provide a uniform ticking mechanism in combination with thread 
00211 //            pool management.
00212 //                                  
00213 // Notes    : - 
00214 //                                  
00215 // Revision History...                          
00216 //                                  
00217 // Who  Date    Description                     
00218 //                                  
00219 // AMO  001012  Created 
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 // Class    : gzThreadPoolTicker
00280 //                                  
00281 // Purpose  : Provides the tick manager for a certain thread pool
00282 //                                  
00283 // Notes    : - 
00284 //                                  
00285 // Revision History...                          
00286 //                                  
00287 // Who  Date    Description                     
00288 //                                  
00289 // AMO  001012  Created 
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     // --------------- vars ------------------
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 // Class    : gzThreadData
00351 //                                  
00352 // Purpose  : To provide a thread local storage.- Each thread gets its own instance of data
00353 //                                  
00354 // Notes    : - 
00355 //                                  
00356 // Revision History...                          
00357 //                                  
00358 // Who  Date    Description                     
00359 //                                  
00360 // AMO  020525  Created 
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 

Documentation for Gizmo3D generated at Wed Feb 20 11:54:11 2008 by   Saab Training Systems AB, ¸ (c) 2003-and beyond