Gizmo3D

gzMutex.h

Go to the documentation of this file.
00001 //*****************************************************************************
00002 // File         : gzMutex.h
00003 // Module       : gzBase
00004 // Description  : Class definition of mutex functionality
00005 // Author       : Anders Modén      
00006 // Product      : GizmoBase 2.1.1
00007 //      
00008 // Copyright © 2003- Saab Training System 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  980819  Created file    
00019 //
00020 //******************************************************************************
00021 #ifndef __GZ_MUTEX_H__
00022 #define __GZ_MUTEX_H__
00023 
00031 #include "gzBasicTypes.h"
00032 #include "gzDebug.h"
00033 #include "gzMemory.h"
00034 #include "gzReference.h"
00035 
00036 #if defined GZ_WINDOWS
00037 // --------------------------------  GZ_WINDOWS ----------------------------
00038 
00039     #include "windows.h"
00040     typedef CRITICAL_SECTION    gzSyncType;
00041     typedef HANDLE              gzEventHandle;
00042 
00043 #elif defined GZ_UNIX 
00044 // --------------------------------  UNIX ----------------------------------
00045 
00046     //#if defined GZ_MAC                // Can not yet handle recursive mutexes
00047     //  #define NON_RECURSIVE_MUTEX
00048     //#endif
00049 
00050     #include "pthread.h"
00051     #include "sys/errno.h"
00052     typedef pthread_mutex_t gzSyncType;
00053     typedef pthread_cond_t  gzEventHandle;
00054 
00055 
00056 #endif
00057 
00058 
00059 //******************************************************************************
00060 // Class    : gzMutex
00061 //                                  
00062 // Purpose  : Lock and Unlock utils for mutexes
00063 //                                  
00064 // Notes    : - 
00065 //                                  
00066 // Revision History...                          
00067 //                                  
00068 // Who  Date    Description                     
00069 //                                  
00070 // AMO  980819  Created 
00071 //                                  
00072 //******************************************************************************
00073 class  GZ_BASE_EXPORT gzMutex 
00074 {
00075 public:
00076         
00077     gzMutex(gzBool useThreadID=TRUE);
00078     gzMutex(const gzMutex &copy);
00079     gzMutex & operator=(const gzMutex &copy);
00080 
00081     virtual ~gzMutex();
00082 
00083     gzVoid  waitLock() const;
00084     gzBool  tryLock() const;
00085     gzVoid  unLock() const;
00086     gzBool  isLocked() const;
00087 
00088     gzULong getOwnerThreadID() const;
00089 
00090     gzULong getSpinLockCount() const;
00091 
00092 private:
00093 
00094     gzSyncType      m_lock;
00095 
00096 #ifdef NON_RECURSIVE_MUTEX
00097 
00098     gzSyncType      m_waiter;
00099 
00100 #endif
00101 
00102     gzULong         m_threadID;
00103 
00104     gzULong         m_spinLock;
00105 
00106     gzBool          m_useThreadID;
00107 };
00108 
00109 
00110 //******************************************************************************
00111 // Class    : gzGuard
00112 //                                  
00113 // Purpose  : Guards a primitive with a mutex
00114 //                                  
00115 // Notes    : - 
00116 //                                  
00117 // Revision History...                          
00118 //                                  
00119 // Who  Date    Description                     
00120 //                                  
00121 // AMO  981101  Created 
00122 //                                  
00123 //******************************************************************************
00124 template <class T> class gzGuard : public gzMutex
00125 {
00126 public:
00127     
00128     gzGuard(){};
00129 
00130     gzGuard(const T& data):m_data(data){};
00131 
00132     operator T&() { return (T &)m_data; }   
00133 
00134     T& operator=( const T& data ){ m_data=data; return m_data; }
00135 
00136 private:
00137 
00138     T m_data;
00139 };
00140 
00141 //******************************************************************************
00142 // Class    : gzClassGuard
00143 //                                  
00144 // Purpose  : Guards a class
00145 //                                  
00146 // Notes    : - 
00147 //                                  
00148 // Revision History...                          
00149 //                                  
00150 // Who  Date    Description                     
00151 //                                  
00152 // AMO  011101  Created 
00153 //                                  
00154 //******************************************************************************
00155 template <class T> class gzClassGuard : public T , public gzMutex
00156 {
00157 public:
00158     
00159     gzClassGuard(){};
00160 
00161     virtual ~gzClassGuard(){};
00162 
00163     gzClassGuard(const T& data):T(data){};
00164 };
00165 
00166 //******************************************************************************
00167 // Class    : gzBodyGuard
00168 //                                  
00169 // Purpose  : Auto guard. Use to protect methods
00170 //                                  
00171 // Notes    : -
00172 //                                  
00173 // Revision History...                          
00174 //                                  
00175 // Who  Date    Description                     
00176 //                                  
00177 // AMO  011101  Created 
00178 //                                  
00179 //******************************************************************************
00180 class GZ_BASE_EXPORT gzBodyGuard 
00181 {
00182 public:
00183     gzBodyGuard(const gzMutex &guard):m_guard(&guard)   { m_guard->waitLock(); }
00184 
00185     virtual ~gzBodyGuard()                              { m_guard->unLock(); }
00186 
00187 private:    // Do not allow copy or assignments
00188 
00189     gzBodyGuard( const gzBodyGuard &copy):m_guard(NULL){}
00190 
00191     gzBodyGuard & operator=(const gzBodyGuard &copy){ return *this; }
00192 
00193 private:
00194 
00195     const gzMutex *m_guard;
00196 };
00197 
00198 #define GZ_BODYGUARD    gzBodyGuard _guard_
00199 
00200 //******************************************************************************
00201 // Class    : gzThreadSafeReference
00202 //                                  
00203 // Purpose  : Thread safe reference class
00204 //                                  
00205 // Notes    : -
00206 //                                  
00207 // Revision History...                          
00208 //                                  
00209 // Who  Date    Description                     
00210 //                                  
00211 // AMO  030305  Created 
00212 //                                  
00213 //******************************************************************************
00214 class GZ_BASE_EXPORT gzThreadSafeReference : public gzReference 
00215 {
00216 public:
00217 
00218     virtual gzVoid  ref()
00219     {
00220         m_ThreadSafeRefLock.waitLock();
00221 
00222         gzReference::ref();
00223 
00224         m_ThreadSafeRefLock.unLock();
00225     }
00226 
00227     virtual gzVoid  unref()
00228     {
00229         m_ThreadSafeRefLock.waitLock();
00230 
00231         gzUInt retval(gzReference::unrefNoDelete());
00232 
00233         m_ThreadSafeRefLock.unLock();
00234 
00235         if(!retval)
00236             checkDelete();
00237     }
00238 
00239     virtual gzUInt  unrefNoDelete()
00240     {
00241         m_ThreadSafeRefLock.waitLock();
00242 
00243         gzUInt retval(gzReference::unrefNoDelete());
00244 
00245         m_ThreadSafeRefLock.unLock();
00246 
00247         return retval;
00248     }
00249 
00250     virtual gzBool  checkDelete()
00251     {
00252         m_ThreadSafeRefLock.waitLock();
00253 
00254         if(!_refCount)
00255         {
00256             m_ThreadSafeRefLock.unLock();
00257 
00258             delete this;
00259 
00260             return TRUE;
00261         }
00262 
00263         m_ThreadSafeRefLock.unLock();
00264 
00265         return FALSE;
00266     }
00267 
00268     virtual gzUInt  getRef() const
00269     {
00270         m_ThreadSafeRefLock.waitLock();
00271 
00272         gzUInt retval(gzReference::getRef());
00273 
00274         m_ThreadSafeRefLock.unLock();
00275 
00276         return retval;
00277     }
00278 
00279 protected:
00280 
00281     gzMutex m_ThreadSafeRefLock;
00282 };
00283 
00284 //******************************************************************************
00285 // Class    : gzEvent
00286 //                                  
00287 // Purpose  : A waitable event that can trigger thread execution.
00288 //                                  
00289 // Notes    : - 
00290 //                                  
00291 // Revision History...                          
00292 //                                  
00293 // Who  Date    Description                     
00294 //                                  
00295 // AMO  020402  Created 
00296 //                                  
00297 //******************************************************************************
00299 class GZ_BASE_EXPORT gzEvent : public gzThreadSafeReference
00300 {
00301 public:
00302 
00304     gzEvent();
00305 
00307     virtual ~gzEvent();
00308 
00310 
00313     gzVoid fire();
00314 
00315     gzEventHandle getHandle() const;
00316 
00318 
00322     gzBool wait(gzULong timeout);
00323 
00325 
00330     static gzBool wait(gzULong timeout , const gzArray<gzEvent> & events , gzBool waitForAllEvents=FALSE , gzULong *eventIndex=NULL);
00331 
00332 private:
00333 
00334     gzEventHandle   m_handle;
00335 };
00336 
00337 GZ_DECLARE_REFPTR(gzEvent);
00338 
00339 //******************************************************************************
00340 // Class    : gzSemaphore
00341 //                                  
00342 // Purpose  : -
00343 //                                  
00344 // Notes    : Used to allow muliple locks per value (mode)  
00345 //                                  
00346 // Revision History...                          
00347 //                                  
00348 // Who  Date    Description                     
00349 //                                  
00350 // AMO  981101  Created 
00351 //                                  
00352 //******************************************************************************
00353 class GZ_BASE_EXPORT gzSemaphore
00354 {
00355 public:
00356 
00357     gzSemaphore(gzULong currentValue=0,gzULong currentCount=0,gzULong maxCount=0);
00358 
00359     virtual ~gzSemaphore(){};
00360 
00361     gzBool waitLock(gzULong value) const;
00362     
00363     gzBool tryLock(gzULong value) const;
00364 
00365     gzULong setMaxLockCount(gzULong maxCount);
00366 
00367     gzVoid unLock() const;
00368 
00369     gzULong getOwnerValue() const;
00370 
00371     gzULong getSpinLockCount() const;
00372 
00373 private:
00374 
00375     gzULong m_maxCount;
00376     gzMutex m_locker;
00377     mutable gzULong m_currentValue;
00378     mutable gzULong m_counter;
00379     mutable gzEvent m_waiter;
00380 };
00381 
00382 #define GZ_SEMA_READ    (0)
00383 #define GZ_SEMA_WRITE   (gzThread::getThreadID())
00384 
00385 //******************************************************************************
00386 // Class    : gzRecycleData && gzRecycleDataExport
00387 //                                  
00388 // Purpose  : Recycle data storage for faster access
00389 //                                  
00390 // Notes    : -
00391 //                                  
00392 // Revision History...                          
00393 //                                  
00394 // Who  Date    Description                     
00395 //                                  
00396 // AMO  030305  Created 
00397 //                                  
00398 //******************************************************************************
00399 #define GZ_DECLARE_RECYCLE_DATA_EXPORT(moduleName,exportDef)    template <class T> class gzRecycleData_##moduleName\
00400 {                                                                                   \
00401 public:                                                                             \
00402                                                                                     \
00403     gzRecycleData_##moduleName()                                                    \
00404     {                                                                               \
00405         s_recycleDataLock.waitLock();                                               \
00406                                                                                     \
00407         if(s_recycleData.first())                                                   \
00408         {                                                                           \
00409             m_data=s_recycleData.first();                                           \
00410                                                                                     \
00411             s_recycleData.removeFirst();                                            \
00412                                                                                     \
00413             m_needNew=FALSE;                                                        \
00414                                                                                     \
00415         }                                                                           \
00416         else                                                                        \
00417         {                                                                           \
00418             m_data=new gzRefData<T>;                                                \
00419                                                                                     \
00420             m_needNew=TRUE;                                                         \
00421         }                                                                           \
00422                                                                                     \
00423         m_needInit=TRUE;                                                            \
00424                                                                                     \
00425         s_recycleDataLock.unLock();                                                 \
00426     }                                                                               \
00427                                                                                     \
00428     gzRecycleData_##moduleName(const T &copy)                                       \
00429     {                                                                               \
00430         s_recycleDataLock.waitLock();                                               \
00431                                                                                     \
00432         if(s_recycleData.first())                                                   \
00433         {                                                                           \
00434             m_data=s_recycleData.first();                                           \
00435                                                                                     \
00436             s_recycleData.removeFirst();                                            \
00437         }                                                                           \
00438         else                                                                        \
00439         {                                                                           \
00440             m_data=new gzRefData<T>;                                                \
00441         }                                                                           \
00442                                                                                     \
00443         m_needNew=FALSE;                                                            \
00444         m_needInit=FALSE;                                                           \
00445                                                                                     \
00446         *m_data.get()=copy;                                                         \
00447                                                                                     \
00448         s_recycleDataLock.unLock();                                                 \
00449     }                                                                               \
00450                                                                                     \
00451     virtual ~gzRecycleData_##moduleName()                                           \
00452     {                                                                               \
00453         s_recycleDataLock.waitLock();                                               \
00454                                                                                     \
00455         if(!m_needNew && s_enabled)                                                 \
00456             if(s_recycleData.entries()<s_maxStorageCount)                           \
00457                 s_recycleData.pre_insert(m_data);                                   \
00458                                                                                     \
00459         m_data=NULL;                                                                \
00460                                                                                     \
00461         s_recycleDataLock.unLock();                                                 \
00462     }                                                                               \
00463                                                                                     \
00464     /* User defined callbacks */                                                    \
00465     virtual gzVoid onNewItem(T & data)      const {};                               \
00466     virtual gzVoid onInitItem(T & data)     const {};                               \
00467                                                                                     \
00468     operator T &()                                                                  \
00469     {                                                                               \
00470         if(m_needInit)                                                              \
00471         {                                                                           \
00472             m_needInit=FALSE;                                                       \
00473                                                                                     \
00474             if(m_needNew)                                                           \
00475             {                                                                       \
00476                 m_needNew=FALSE;                                                    \
00477                 onNewItem(*m_data.get());                                           \
00478             }                                                                       \
00479             onInitItem(*m_data.get());                                              \
00480         }                                                                           \
00481                                                                                     \
00482         return (T &)*m_data.get();                                                  \
00483     }                                                                               \
00484                                                                                     \
00485     operator const T &() const                                                      \
00486     {                                                                               \
00487         if(m_needInit)                                                              \
00488         {                                                                           \
00489             m_needInit=FALSE;                                                       \
00490                                                                                     \
00491             if(m_needNew)                                                           \
00492             {                                                                       \
00493                 m_needNew=FALSE;                                                    \
00494                 onNewItem(*m_data.get());                                           \
00495             }                                                                       \
00496             onInitItem(*m_data.get());                                              \
00497         }                                                                           \
00498                                                                                     \
00499         return (T &)*m_data.get();                                                  \
00500     }                                                                               \
00501                                                                                     \
00502     T & getRecycledInstance()                                                       \
00503     {                                                                               \
00504         if(m_needInit)                                                              \
00505         {                                                                           \
00506             m_needInit=FALSE;                                                       \
00507                                                                                     \
00508             if(m_needNew)                                                           \
00509             {                                                                       \
00510                 m_needNew=FALSE;                                                    \
00511                 onNewItem(*m_data.get());                                           \
00512             }                                                                       \
00513             onInitItem(*m_data.get());                                              \
00514         }                                                                           \
00515                                                                                     \
00516         return (T &)*m_data.get();                                                  \
00517     }                                                                               \
00518                                                                                     \
00519     gzVoid init()                                                                   \
00520     {                                                                               \
00521         if(m_needInit)                                                              \
00522         {                                                                           \
00523             m_needInit=FALSE;                                                       \
00524                                                                                     \
00525             if(m_needNew)                                                           \
00526             {                                                                       \
00527                 m_needNew=FALSE;                                                    \
00528                 onNewItem(*m_data.get());                                           \
00529             }                                                                       \
00530             onInitItem(*m_data.get());                                              \
00531         }                                                                           \
00532     }                                                                               \
00533                                                                                     \
00534     static gzVoid clearRecycledData()                                               \
00535     {                                                                               \
00536         s_recycleDataLock.waitLock();                                               \
00537         s_recycleData.clear();                                                      \
00538         s_recycleDataLock.unLock();                                                 \
00539     }                                                                               \
00540                                                                                     \
00541     gzRecycleData_##moduleName &operator=(const gzRecycleData_##moduleName &data)   \
00542     {                                                                               \
00543         if(m_needInit)                                                              \
00544         {                                                                           \
00545             m_needInit=FALSE;                                                       \
00546                                                                                     \
00547             if(m_needNew)                                                           \
00548             {                                                                       \
00549                 m_needNew=FALSE;                                                    \
00550                 onNewItem(*m_data.get());                                           \
00551             }                                                                       \
00552             onInitItem(*m_data.get());                                              \
00553         }                                                                           \
00554                                                                                     \
00555         if(data.m_needInit)                                                         \
00556         {                                                                           \
00557             data.m_needInit=FALSE;                                                  \
00558                                                                                     \
00559             if(data.m_needNew)                                                      \
00560             {                                                                       \
00561                 data.m_needNew=FALSE;                                               \
00562                 data.onNewItem(*data.m_data.get());                                 \
00563             }                                                                       \
00564             data.onInitItem(*data.m_data.get());                                    \
00565         }                                                                           \
00566                                                                                     \
00567         ((T &)*m_data.get())=((T &)*data.m_data.get());                             \
00568                                                                                     \
00569         return *this;                                                               \
00570     }                                                                               \
00571                                                                                     \
00572     gzRecycleData_##moduleName(const gzRecycleData_##moduleName &data)              \
00573     {                                                                               \
00574         s_recycleDataLock.waitLock();                                               \
00575                                                                                     \
00576         if(s_recycleData.first())                                                   \
00577         {                                                                           \
00578             m_data=s_recycleData.first();                                           \
00579                                                                                     \
00580             s_recycleData.removeFirst();                                            \
00581                                                                                     \
00582         }                                                                           \
00583         else                                                                        \
00584         {                                                                           \
00585             m_data=new gzRefData<T>;                                                \
00586         }                                                                           \
00587                                                                                     \
00588         m_needInit=FALSE;                                                           \
00589         m_needNew=FALSE;                                                            \
00590                                                                                     \
00591         s_recycleDataLock.unLock();                                                 \
00592                                                                                     \
00593                                                                                     \
00594         if(data.m_needInit)                                                         \
00595         {                                                                           \
00596             data.m_needInit=FALSE;                                                  \
00597                                                                                     \
00598             if(data.m_needNew)                                                      \
00599             {                                                                       \
00600                 data.m_needNew=FALSE;                                               \
00601                 data.onNewItem(*data.m_data.get());                                 \
00602             }                                                                       \
00603             data.onInitItem(*data.m_data.get());                                    \
00604         }                                                                           \
00605                                                                                     \
00606         ((T &)*m_data.get())=((T &)*data.m_data.get());                             \
00607                                                                                     \
00608     }                                                                               \
00609                                                                                     \
00610     T& operator=(const T &data)                                                     \
00611     {                                                                               \
00612         if(m_needInit)                                                              \
00613         {                                                                           \
00614             m_needInit=FALSE;                                                       \
00615                                                                                     \
00616             if(m_needNew)                                                           \
00617             {                                                                       \
00618                 m_needNew=FALSE;                                                    \
00619                 onNewItem(*m_data.get());                                           \
00620             }                                                                       \
00621             onInitItem(*m_data.get());                                              \
00622         }                                                                           \
00623                                                                                     \
00624         ((T &)*m_data.get())=data;                                                  \
00625         return ((T &)*m_data.get());                                                \
00626     }                                                                               \
00627                                                                                     \
00628     T * operator ->() const                                                         \
00629     {                                                                               \
00630         if(m_needInit)                                                              \
00631         {                                                                           \
00632             m_needInit=FALSE;                                                       \
00633                                                                                     \
00634             if(m_needNew)                                                           \
00635             {                                                                       \
00636                 m_needNew=FALSE;                                                    \
00637                 onNewItem(*m_data.get());                                           \
00638             }                                                                       \
00639             onInitItem(*m_data.get());                                              \
00640         }                                                                           \
00641                                                                                     \
00642         return &((T &)*m_data.get());                                               \
00643     }                                                                               \
00644                                                                                     \
00645     static gzVoid setMaxStorageCount(gzULong count)                                 \
00646     {                                                                               \
00647         s_recycleDataLock.waitLock();                                               \
00648         s_maxStorageCount=count;                                                    \
00649         s_recycleDataLock.unLock();                                                 \
00650     }                                                                               \
00651                                                                                     \
00652     static gzVoid enable()                                                          \
00653     {                                                                               \
00654         s_recycleDataLock.waitLock();                                               \
00655         s_enabled=TRUE;                                                             \
00656         s_recycleDataLock.unLock();                                                 \
00657     }                                                                               \
00658                                                                                     \
00659     static gzVoid disable()                                                         \
00660     {                                                                               \
00661         s_recycleDataLock.waitLock();                                               \
00662         s_enabled=FALSE;                                                            \
00663         s_recycleData.clear();                                                      \
00664         s_recycleDataLock.unLock();                                                 \
00665     }                                                                               \
00666                                                                                     \
00667     static gzVoid reuseLinks(gzBool on)                                             \
00668     {                                                                               \
00669         s_recycleDataLock.waitLock();                                               \
00670         s_recycleData.reuseLinks(on);                                               \
00671         s_recycleDataLock.unLock();                                                 \
00672     }                                                                               \
00673                                                                                     \
00674 private:                                                                            \
00675                                                                                     \
00676     gzRefPointer<gzRefData<T> >     m_data;                                         \
00677                                                                                     \
00678                                                                                     \
00679     mutable gzBool                  m_needInit:1;                                   \
00680     mutable gzBool                  m_needNew:1;                                    \
00681                                                                                     \
00682                                                                                     \
00683     exportDef static    gzBool                      s_enabled;                      \
00684     exportDef static    gzULong                     s_maxStorageCount;              \
00685     exportDef static    gzMutex                     s_recycleDataLock;              \
00686     exportDef static    gzRefList<gzRefData<T> >    s_recycleData;                  \
00687                                                                                     \
00688 };
00689 
00690 #define GZ_DECLARE_RECYCLE_DATA_EXPORT_IMP(moduleName)  template <class T> gzMutex gzRecycleData_##moduleName<T>::s_recycleDataLock=gzMutex(FALSE); template <class T> gzRefList<gzRefData<T> > gzRecycleData_##moduleName<T>::s_recycleData=gzRefList<gzRefData<T> >(FALSE); template <class T> gzULong gzRecycleData_##moduleName<T>::s_maxStorageCount=0xfffffffful; template <class T> gzBool gzRecycleData_##moduleName<T>::s_enabled=TRUE;
00691 
00692 // Define the export naming module
00693 #define gzRecycleDataExport(moduleName) gzRecycleData_##moduleName
00694 
00695 // Define the standard gzBase gzRecycleData
00696 
00697 #define COMMON_EXPORT   // Empty definition
00698 
00699 GZ_DECLARE_RECYCLE_DATA_EXPORT(gzBase, COMMON_EXPORT);
00700 
00701 #define gzRecycleData gzRecycleDataExport(gzBase)
00702 #define GZ_DECLARE_RECYCLE_DATA_IMP GZ_DECLARE_RECYCLE_DATA_EXPORT_IMP(gzBase)
00703 
00704 #endif

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