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.

333 lines
8.0 KiB

  1. #ifndef _INC_CSCVIEW_THDSYNC_H
  2. #define _INC_CSCVIEW_THDSYNC_H
  3. ///////////////////////////////////////////////////////////////////////////////
  4. /* File: thdsync.h
  5. Description: Contains classes for managing thread synchronization in
  6. Win32 programs. Most of the work is to provide automatic unlocking
  7. of synchronization primities on object destruction. The work on
  8. monitors and condition variables is strongly patterned after
  9. work in "Multithreaded Programming with Windows NT" by Pham and Garg.
  10. Revision History:
  11. Date Description Programmer
  12. -------- --------------------------------------------------- ----------
  13. 09/22/97 Initial creation. BrianAu
  14. */
  15. ///////////////////////////////////////////////////////////////////////////////
  16. #ifndef _WINDOWS_
  17. # include <windows.h>
  18. #endif
  19. #ifndef _INC_DSKQUOTA_DEBUG_H
  20. # include "debug.h"
  21. #endif
  22. class CCriticalSection
  23. {
  24. public:
  25. CCriticalSection(void)
  26. { InitializeCriticalSection(&m_cs); }
  27. ~CCriticalSection(void)
  28. { DeleteCriticalSection(&m_cs); }
  29. void Enter(void)
  30. { EnterCriticalSection(&m_cs); }
  31. void Leave(void)
  32. { LeaveCriticalSection(&m_cs); }
  33. operator CRITICAL_SECTION& ()
  34. { return m_cs; }
  35. private:
  36. CRITICAL_SECTION m_cs;
  37. //
  38. // Prevent copy.
  39. //
  40. CCriticalSection(const CCriticalSection& rhs);
  41. CCriticalSection& operator = (const CCriticalSection& rhs);
  42. };
  43. class CWin32SyncObj
  44. {
  45. public:
  46. explicit CWin32SyncObj(HANDLE handle)
  47. : m_handle(handle) { }
  48. virtual ~CWin32SyncObj(void)
  49. { if (NULL != m_handle) CloseHandle(m_handle); }
  50. HANDLE Handle(void)
  51. { return m_handle; }
  52. protected:
  53. HANDLE m_handle;
  54. };
  55. class CSemaphore : public CWin32SyncObj
  56. {
  57. public:
  58. explicit CSemaphore(DWORD dwInitialCount = 0, DWORD dwMaxCount = 1);
  59. ~CSemaphore(void) { };
  60. DWORD Wait(DWORD dwTimeout = INFINITE)
  61. { return WaitForSingleObject(m_handle, dwTimeout); }
  62. void Release(DWORD dwReleaseCount = 1)
  63. { ReleaseSemaphore(m_handle, dwReleaseCount, NULL); }
  64. private:
  65. //
  66. // Prevent copy.
  67. //
  68. CSemaphore(const CSemaphore& rhs);
  69. CSemaphore& operator = (const CSemaphore& rhs);
  70. };
  71. class CSemaphoreList
  72. {
  73. public:
  74. CSemaphoreList(void)
  75. : m_pFirst(NULL),
  76. m_pLast(NULL) { }
  77. ~CSemaphoreList(void);
  78. void Append(CSemaphore *pSem);
  79. void Prepend(CSemaphore *pSem);
  80. CSemaphore *Head(void);
  81. bool bEmpty(void)
  82. { return (NULL == m_pFirst); }
  83. void Dump(void);
  84. private:
  85. class Item
  86. {
  87. public:
  88. Item(CSemaphore *pSem, Item *pNext = NULL)
  89. : m_pSem(pSem), m_pNext(pNext) { }
  90. CSemaphore *m_pSem;
  91. Item *m_pNext;
  92. };
  93. Item *m_pFirst;
  94. Item *m_pLast;
  95. };
  96. class CMutex : public CWin32SyncObj
  97. {
  98. public:
  99. explicit CMutex(BOOL InitialOwner = FALSE);
  100. ~CMutex(void) { };
  101. DWORD Wait(DWORD dwTimeout = INFINITE)
  102. { return WaitForSingleObject(m_handle, dwTimeout); }
  103. void Release(void)
  104. { ReleaseMutex(m_handle); }
  105. private:
  106. //
  107. // Prevent copy.
  108. //
  109. CMutex(const CMutex& rhs);
  110. CMutex& operator = (const CMutex& rhs);
  111. };
  112. class CEvent : public CWin32SyncObj
  113. {
  114. public:
  115. explicit CEvent(BOOL bManualReset, BOOL bInitialState);
  116. ~CEvent(void) { };
  117. BOOL Set(void)
  118. { return SetEvent(m_handle); }
  119. BOOL Reset(void)
  120. { return ResetEvent(m_handle); }
  121. private:
  122. //
  123. // Prevent copy.
  124. //
  125. CEvent(const CEvent& rhs);
  126. CEvent& operator = (const CEvent& rhs);
  127. };
  128. class CMonitor
  129. {
  130. public:
  131. CMonitor(void) { }
  132. ~CMonitor(void) { }
  133. virtual void Lock(void)
  134. { m_Mutex.Wait(); }
  135. virtual void Release(void)
  136. { m_Mutex.Release(); }
  137. protected:
  138. CMutex m_Mutex;
  139. };
  140. class CConditionSU; // fwd decl for use in CMonitorSU.
  141. //
  142. // "Signal-Urgent" monitor.
  143. // Signalling threads are guaranteed to run immediately after the signaled
  144. // thread exits the monitor.
  145. //
  146. class CMonitorSU : public CMonitor
  147. {
  148. public:
  149. CMonitorSU(void)
  150. : m_cUrgentSemCount(0) { }
  151. ~CMonitorSU(void) { }
  152. virtual void Release(void);
  153. protected:
  154. int m_cUrgentSemCount;
  155. CSemaphoreList m_UrgentSemList;
  156. friend class CConditionSU;
  157. };
  158. //
  159. // "Signal-Return" condition variable.
  160. // Thread that is signaled is guaranteed to own the mutex lock following
  161. // receipt of the signal.
  162. //
  163. class CConditionSR
  164. {
  165. public:
  166. explicit CConditionSR(CMonitor& monitor)
  167. : m_Monitor(monitor),
  168. m_cSemCount(0) { }
  169. virtual ~CConditionSR(void) { }
  170. virtual void Wait(void);
  171. virtual void Signal(void);
  172. protected:
  173. CMonitor& m_Monitor;
  174. CSemaphore m_Sem;
  175. int m_cSemCount;
  176. };
  177. //
  178. // "Signal-Urgent" condition variable.
  179. // A signaling thread is guaranteed to run first when the
  180. // signaled thread exits the monitor.
  181. //
  182. class CConditionSU
  183. {
  184. public:
  185. explicit CConditionSU(CMonitorSU& monitor)
  186. : m_Monitor(monitor),
  187. m_cSemCount(0) { }
  188. virtual ~CConditionSU(void) { }
  189. virtual void Wait(void);
  190. virtual void Signal(void);
  191. protected:
  192. CMonitorSU& m_Monitor;
  193. CSemaphoreList m_SemList;
  194. int m_cSemCount;
  195. };
  196. //
  197. // An "auto lock" object based on a Win32 critical section.
  198. // The constructor automatically calls EnterCriticalSection for the
  199. // specified critical section. The destructor automatically calls
  200. // LeaveCriticalSection. Note that the critical section object may
  201. // be specified as a Win32 CRITICAL_SECTION or a CCriticalSection object.
  202. // If using a CRITICAL_SECTION object, initialization and deletion of
  203. // the CRITICALS_SECTION is the responsibility of the caller.
  204. //
  205. class AutoLockCs
  206. {
  207. public:
  208. explicit AutoLockCs(CRITICAL_SECTION& cs)
  209. : m_cLock(0),
  210. m_pCS(&cs) { Lock(); }
  211. void Lock(void)
  212. { DBGASSERT((0 <= m_cLock)); EnterCriticalSection(m_pCS); m_cLock++; }
  213. void Release(void)
  214. { m_cLock--; LeaveCriticalSection(m_pCS); }
  215. ~AutoLockCs(void) { if (0 < m_cLock) Release(); }
  216. private:
  217. CRITICAL_SECTION *m_pCS;
  218. int m_cLock;
  219. };
  220. //
  221. // An "auto lock" object based on a Win32 Mutex object.
  222. // The constructor automatically calls WaitForSingleObject for the
  223. // specified mutex. The destructor automatically calls
  224. // ReleaseMutex.
  225. //
  226. class AutoLockMutex
  227. {
  228. public:
  229. //
  230. // Attaches to an already-owned mutex to ensure release.
  231. //
  232. explicit AutoLockMutex(HANDLE hMutex)
  233. : m_hMutex(hMutex) { }
  234. explicit AutoLockMutex(CMutex& mutex)
  235. : m_hMutex(mutex.Handle()) { }
  236. AutoLockMutex(HANDLE hMutex, DWORD dwTimeout)
  237. : m_hMutex(hMutex) { Wait(dwTimeout); }
  238. AutoLockMutex(CMutex& mutex, DWORD dwTimeout)
  239. : m_hMutex(mutex.Handle()) { Wait(dwTimeout); }
  240. ~AutoLockMutex(void) { ReleaseMutex(m_hMutex); }
  241. private:
  242. HANDLE m_hMutex;
  243. void Wait(DWORD dwTimeout = INFINITE);
  244. };
  245. //
  246. // Automatically locks a monitor on creation and releases the
  247. // lock on destruction. Helps exception-safety of monitor functions.
  248. //
  249. class AutoLockMonitor
  250. {
  251. public:
  252. explicit AutoLockMonitor(CMonitor& monitor)
  253. : m_Monitor(monitor)
  254. { m_Monitor.Lock(); }
  255. ~AutoLockMonitor(void)
  256. { m_Monitor.Release(); }
  257. private:
  258. CMonitor& m_Monitor;
  259. };
  260. #endif // _INC_CSCVIEW_THDSYNC_H