Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

356 lines
7.8 KiB

  1. // CResGuard
  2. // CSysGlobalType
  3. // CSysGlobalScalar
  4. // CInterlockedType
  5. // CInverseSemaphore
  6. #ifndef __SYSGLOB_H__
  7. #define __SYSGLOB_H__
  8. #include <assert.h>
  9. // Instances of this class will be accessed by mutiple threads. So,
  10. // all members of this class (except the constructor and destructor)
  11. // must be thread-safe.
  12. class CResGuard
  13. {
  14. private:
  15. HANDLE m_hMutex;
  16. long m_lGrdCnt; // # of C calls
  17. public:
  18. CResGuard(void * pObjectAddr)
  19. {
  20. TCHAR szObjectName[32];
  21. wsprintf(szObjectName, TEXT("CResGuard :: %08X"), (DWORD) pObjectAddr);
  22. m_lGrdCnt = 0;
  23. m_hMutex = CreateMutex(NULL, FALSE, szObjectName);
  24. assert(m_hMutex);
  25. }
  26. ~CResGuard()
  27. {
  28. CloseHandle(m_hMutex);
  29. }
  30. // IsGuarded is used for debugging
  31. BOOL IsGuarded() const
  32. {
  33. return(m_lGrdCnt > 0);
  34. }
  35. public:
  36. class CGuard
  37. {
  38. private:
  39. CResGuard& m_rg;
  40. public:
  41. CGuard(CResGuard& rg) : m_rg(rg)
  42. {
  43. m_rg.Guard();
  44. };
  45. ~CGuard()
  46. {
  47. m_rg.Unguard();
  48. }
  49. };
  50. private:
  51. void Guard()
  52. {
  53. assert(WAIT_OBJECT_0 == WaitForSingleObject(m_hMutex, INFINITE));
  54. m_lGrdCnt++;
  55. }
  56. void Unguard()
  57. {
  58. m_lGrdCnt--;
  59. ReleaseMutex(m_hMutex);
  60. }
  61. // Guard/Unguard can only be accessed by the nested CGuard class.
  62. friend class CResGuard::CGuard;
  63. };
  64. // Instances of this class will be accessed by mutiple threads. So,
  65. // all members of this class (except the constructor and destructor)
  66. // must be thread-safe.
  67. template <class TYPE>
  68. class CInterlockedType
  69. {
  70. private:
  71. TYPE * m_pTVal;
  72. protected:
  73. mutable CResGuard m_rg;
  74. public:
  75. // Public member functions
  76. // Note: Constructors & destructors are always thread safe
  77. CInterlockedType(TYPE * const pTVal) : m_rg( pTVal )
  78. {
  79. m_pTVal = pTVal;
  80. }
  81. virtual ~CInterlockedType()
  82. {
  83. }
  84. // Cast operator to make writing code that uses
  85. // thread-safe data type easier
  86. operator TYPE() const
  87. {
  88. CResGuard::CGuard x(m_rg);
  89. return(GetVal());
  90. }
  91. protected: // Protected function to be called by derived class
  92. TYPE& GetVal()
  93. {
  94. assert(m_rg.IsGuarded());
  95. return(*m_pTVal);
  96. }
  97. const TYPE& GetVal() const
  98. {
  99. assert(m_rg.IsGuarded());
  100. return(*m_pTVal);
  101. }
  102. TYPE SetVal(const TYPE& TNewVal)
  103. {
  104. assert(m_rg.IsGuarded());
  105. TYPE& TVal = GetVal();
  106. if (TVal != TNewVal)
  107. {
  108. TYPE TPrevVal = TVal;
  109. TVal = TNewVal;
  110. OnValChanged(TNewVal, TPrevVal);
  111. }
  112. return(TVal);
  113. }
  114. protected: // Overridable functions
  115. virtual void OnValChanged(const TYPE& TNewVal, const TYPE& TPrevVal) const
  116. {
  117. // Nothing to do here
  118. }
  119. };
  120. // Instances of this class will be accessed by mutiple threads. So,
  121. // all members of this class (except the constructor and destructor)
  122. // must be thread-safe.
  123. template <class TYPE>
  124. class CSysGlobalScalar : protected CInterlockedType<TYPE>
  125. {
  126. public:
  127. CSysGlobalScalar(TYPE * pTVal) : CInterlockedType<TYPE>(pTVal)
  128. {
  129. }
  130. ~CSysGlobalScalar()
  131. {
  132. }
  133. // C++ does not allow operator cast to be inherited.
  134. operator TYPE() const
  135. {
  136. return(CInterlockedType<TYPE>::operator TYPE());
  137. }
  138. TYPE operator=(TYPE TVal)
  139. {
  140. CResGuard::CGuard x(m_rg);
  141. return(SetVal(TVal));
  142. }
  143. TYPE operator++(int) // Postfix increment operator
  144. {
  145. CResGuard::CGuard x(m_rg);
  146. TYPE TPrevVal = GetVal();
  147. SetVal(TPrevVal + 1);
  148. return(TPrevVal); // Return value BEFORE increment
  149. }
  150. TYPE operator--(int) // Postfix decrement operator.
  151. {
  152. CResGuard::CGuard x(m_rg);
  153. TYPE TPrevVal = GetVal();
  154. SetVal(TPrevVal - 1);
  155. return(TPrevVal); // Return value BEFORE decrement
  156. }
  157. TYPE operator += (TYPE op)
  158. { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() + op)); }
  159. TYPE operator++()
  160. { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() + 1)); }
  161. TYPE operator -= (TYPE op)
  162. { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() - op)); }
  163. TYPE operator--()
  164. { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() - 1)); }
  165. TYPE operator *= (TYPE op)
  166. { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() * op)); }
  167. TYPE operator /= (TYPE op)
  168. { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() / op)); }
  169. TYPE operator %= (TYPE op)
  170. { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() % op)); }
  171. TYPE operator ^= (TYPE op)
  172. { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() ^ op)); }
  173. TYPE operator &= (TYPE op)
  174. { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() & op)); }
  175. TYPE operator |= (TYPE op)
  176. { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() | op)); }
  177. TYPE operator <<=(TYPE op)
  178. { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() << op)); }
  179. TYPE operator >>=(TYPE op)
  180. { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() >> op)); }
  181. };
  182. // CSysGlobalHandle
  183. //
  184. // Same as CSysGlobalScalar, but without all the operators that would
  185. // work on only scalars
  186. template <class TYPE>
  187. class CSysGlobalHandle : protected CInterlockedType<TYPE>
  188. {
  189. public:
  190. CSysGlobalHandle(TYPE * pTVal) : CInterlockedType<TYPE>(pTVal)
  191. {
  192. }
  193. ~CSysGlobalHandle()
  194. {
  195. }
  196. // C++ does not allow operator cast to be inherited.
  197. operator TYPE() const
  198. {
  199. return(CInterlockedType<TYPE>::operator TYPE());
  200. }
  201. TYPE operator=(TYPE TVal)
  202. {
  203. CResGuard::CGuard x(m_rg);
  204. return(SetVal(TVal));
  205. }
  206. };
  207. // Instances of this class will be accessed by mutiple threads. So,
  208. // all members of this class (except the constructor and destructor)
  209. // must be thread-safe.
  210. template <class TYPE> class CInverseSemaphore :
  211. public CSysGlobalScalar<TYPE>
  212. {
  213. public:
  214. CInverseSemaphore(TYPE * pTVal, BOOL fManualReset = TRUE) : CSysGlobalScalar<TYPE>(pTVal)
  215. {
  216. // The event should be signaled if TVal is 0
  217. m_hevtZero = CreateEvent(NULL, fManualReset, (*pTVal == 0), NULL);
  218. // The event should be signaled if TVal is NOT 0
  219. m_hevtNotZero = CreateEvent(NULL, fManualReset, (*pTVal != 0), NULL);
  220. }
  221. ~CInverseSemaphore()
  222. {
  223. CloseHandle(m_hevtZero);
  224. CloseHandle(m_hevtNotZero);
  225. }
  226. // C++ does not allow operator= to be inherited.
  227. TYPE operator=(TYPE x)
  228. {
  229. return(CSysGlobalScalar<TYPE>::operator=(x));
  230. }
  231. // Return handle to event signaled when value is zero
  232. operator HANDLE() const
  233. {
  234. return(m_hevtZero);
  235. }
  236. // Return handle to event signaled when value is not zero
  237. HANDLE GetNotZeroHandle() const
  238. {
  239. return(m_hevtNotZero);
  240. }
  241. // C++ does not allow operator cast to be inherited.
  242. operator TYPE() const
  243. {
  244. return(CSysGlobalScalar<TYPE>::operator TYPE());
  245. }
  246. protected:
  247. void OnValChanged(const TYPE& TNewVal, const TYPE& TPrevVal) const
  248. {
  249. // For best performance, avoid jumping to
  250. // kernel mode if we don't have to
  251. if ((TNewVal == 0) && (TPrevVal != 0))
  252. {
  253. SetEvent(m_hevtZero);
  254. ResetEvent(m_hevtNotZero);
  255. }
  256. if ((TNewVal != 0) && (TPrevVal == 0))
  257. {
  258. ResetEvent(m_hevtZero);
  259. SetEvent(m_hevtNotZero);
  260. }
  261. }
  262. private:
  263. HANDLE m_hevtZero; // Signaled when data value is 0
  264. HANDLE m_hevtNotZero; // Signaled when data value is not 0
  265. };
  266. #endif // __SYSGLOB_H__