home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2006 March / Gamestar_82_2006-03_dvd.iso / DVDStar / Editace / quake4_sdkv10.exe / source / idlib / threads / AutoCrit.h
C/C++ Source or Header  |  2005-11-14  |  4KB  |  223 lines

  1. #ifndef __AUTOCRIT_H__
  2. #define __AUTOCRIT_H__
  3.  
  4. #ifdef RV_USE_CRITICALSECTION
  5. // This class eliminates the need to figure out where to call InitializeCriticalSection
  6. // and DeleteCriticalSection.  It makes critical sections into a meaningful class.  More
  7. // importantly, now when they are created as statics, they are already initialized, so
  8. // the AutoCrit doesn't have to worry about checking to see if they've been initialized yet
  9. class CriticalSection
  10. {
  11. public:
  12.     ID_INLINE CriticalSection() 
  13.     { 
  14.         InitializeCriticalSection(&mCrit); 
  15.     }
  16.     ID_INLINE ~CriticalSection() 
  17.     { 
  18.         DeleteCriticalSection(&mCrit); 
  19.     }
  20.  
  21.     ID_INLINE void Enter() 
  22.     { 
  23.         while(!Try())
  24.         {
  25.             Sleep(0);    // give another thread a chance to run to try to eliminate deadlock
  26.         }
  27.     }
  28.     ID_INLINE void Leave() 
  29.     { 
  30.         LeaveCriticalSection(&mCrit); 
  31.     }
  32.  
  33.     ID_INLINE bool Try()
  34.     {
  35.         return TryEnterCriticalSection(&mCrit) != 0;
  36.     }
  37.  
  38. private:
  39.     CRITICAL_SECTION mCrit;
  40. };
  41. #endif
  42.  
  43. #ifdef RV_USE_AUTOCRIT
  44. // Enters a critical section unique to the type of object t on construction
  45. // Exits that critical section on destruction.  Effectively synchronizes calls
  46. // to ANY instance of type t
  47. template <typename t>
  48. class AutoCrit
  49. {
  50. public:
  51.     ID_INLINE AutoCrit() 
  52.     { 
  53.         sCrit.Enter();
  54.     }
  55.     ID_INLINE ~AutoCrit() 
  56.     { 
  57.         sCrit.Leave();
  58.     }
  59. private:
  60.     static CriticalSection sCrit;
  61. };
  62.  
  63. template<typename t>
  64. CriticalSection AutoCrit<t>::sCrit;
  65.  
  66. template <typename t>
  67. class ConditionalAutoCrit
  68. {
  69. public:
  70.     ID_INLINE ConditionalAutoCrit()
  71.     {
  72.         if(sThreading)
  73.         {
  74.             sCrit.Enter();
  75.             mMustLeave = true;
  76.         }
  77.         else
  78.         {
  79.             mMustLeave = false;
  80.         }
  81.     }
  82.     ID_INLINE ~ConditionalAutoCrit()
  83.     {
  84.         if(mMustLeave)
  85.         {
  86.             sCrit.Leave();
  87.         }
  88.     }
  89.  
  90.     static ID_INLINE SetThreading(bool threading)
  91.     {
  92.         // not threadsafe...must be called BEFORE entering and AFTER leaving a threaded section, not during
  93.         sThreading = threading;
  94.     }
  95.  
  96.     static ID_INLINE bool IsThreading()
  97.     {
  98.         return sThreading;
  99.     }
  100.  
  101. private:
  102.     static bool                sThreading;
  103.     static CriticalSection    sCrit;
  104.     bool                        mMustLeave;
  105. };
  106.  
  107. template<typename t>
  108. CriticalSection ConditionalAutoCrit<t>::sCrit;
  109.  
  110. template<typename t>
  111. bool ConditionalAutoCrit<t>::sThreading=false;
  112.  
  113. #else
  114. // these compile out completely in release and removes the need
  115. // for ifdefs all over the code
  116. template <typename t>
  117. class AutoCrit
  118. {
  119. public:
  120.     AutoCrit() { }
  121.     ~AutoCrit() { }
  122. };
  123.  
  124. template <typename t>
  125. class ConditionalAutoCrit
  126. {
  127. public:
  128.     ConditionalAutoCrit() { }
  129.     ~ConditionalAutoCrit() { }
  130. };
  131. #endif
  132.  
  133. #ifdef RV_USE_AUTOINSTANCECRIT
  134.  
  135. class CritInfo
  136. {
  137. public:
  138.     ID_INLINE CritInfo() { refCount = 0; }
  139.     int refCount;
  140.     CriticalSection crit;
  141. };
  142.  
  143.  
  144. // Enters a critical section unique to the specific instance of an object of type t on construction
  145. // Exits that critical section on destruction.  This is templated instead of using void * in order
  146. // to reduce search time when entering and leaving.  Effectively synchronizes on a single instance
  147. // of an object.  This would allow containers for example to not be synchronized to other containers
  148. // of the same type.
  149. template<typename t>
  150. class AutoInstanceCrit
  151. {
  152. public:
  153.  
  154.     ID_INLINE AutoInstanceCrit(t *ptr)
  155.     {
  156.         CritInfo *critPtr = NULL;
  157.         //AutoCrit<AutoInstanceCrit<t> > crit;            // protect access to the map
  158.         critSect.Enter();
  159.         mPtr = ptr;
  160.         int i = sPtrs.FindIndex(mPtr);
  161.  
  162.         if(i == -1)    // not found
  163.         {
  164.             i = sPtrs.Num();
  165.             sPtrs.Append(mPtr);
  166.             sInfos.Append(CritInfo());
  167.         }
  168.         critPtr = &(sInfos[i]);
  169.         critPtr->refCount++;
  170.         critSect.Leave();
  171.  
  172.         critPtr->crit.Enter();
  173.     }
  174.  
  175.     ID_INLINE ~AutoInstanceCrit() 
  176.     { 
  177.         CritInfo *critPtr = NULL;
  178.         {
  179.             //AutoCrit<AutoInstanceCrit<t> > crit;            // protect access to the map
  180.             critSect.Enter();
  181.             int i = sPtrs.FindIndex(mPtr);
  182.             assert(i != -1);
  183.             critPtr = &(sInfos[i]);
  184.             critPtr->refCount--;                                // decrement refcount
  185.             critSect.Leave();
  186.         }
  187.         critPtr->crit.Leave();
  188.         /*
  189.         if(critPtr->refCount == 0)
  190.         {
  191.             sPtrs.RemoveIndex(i);
  192.             sInfos.RemoveIndex(i);
  193.         }*/
  194.     }
  195.  
  196. private:
  197.     t *mPtr;        // the pointer we're protecting
  198.     static CriticalSection critSect;
  199.     static idList<t *> sPtrs;
  200.     static idList<CritInfo> sInfos;
  201. };
  202. template<typename t>
  203. idList<t *> AutoInstanceCrit<t>::sPtrs;
  204.  
  205. template<typename t>
  206. idList<CritInfo> AutoInstanceCrit<t>::sInfos;
  207.  
  208. template<typename t>
  209. CriticalSection AutoInstanceCrit<t>::critSect;
  210.  
  211. #else
  212. // this compiles out completely in release and removes the need
  213. // for ifdefs all over the code
  214. template <typename t>
  215. class AutoInstanceCrit
  216. {
  217. public:
  218.     ID_INLINE AutoInstanceCrit(t *ptr) { }
  219. };
  220. #endif
  221.  
  222. #endif
  223.