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.

320 lines
6.2 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. SYNC.H
  5. Abstract:
  6. Synchronization
  7. History:
  8. --*/
  9. #ifndef __WBEM_CRITSEC__H_
  10. #define __WBEM_CRITSEC__H_
  11. #include "corepol.h"
  12. #include <corex.h>
  13. class POLARITY CCritSec : public CRITICAL_SECTION
  14. {
  15. public:
  16. CCritSec()
  17. {
  18. __try
  19. {
  20. InitializeCriticalSection(this);
  21. }
  22. __except( GetExceptionCode() == STATUS_NO_MEMORY )
  23. {
  24. throw CX_MemoryException();
  25. }
  26. }
  27. ~CCritSec()
  28. {
  29. DeleteCriticalSection(this);
  30. }
  31. void Enter()
  32. {
  33. __try
  34. {
  35. EnterCriticalSection(this);
  36. }
  37. __except( GetExceptionCode() == STATUS_NO_MEMORY )
  38. {
  39. throw CX_MemoryException();
  40. }
  41. }
  42. void Leave()
  43. {
  44. LeaveCriticalSection(this);
  45. }
  46. };
  47. class POLARITY CTryCritSec
  48. {
  49. protected:
  50. CCritSec m_cs;
  51. CCritSec m_csControl;
  52. long m_lCount;
  53. public:
  54. CTryCritSec() : m_lCount(0){}
  55. void Enter()
  56. {
  57. EnterCriticalSection(&m_csControl);
  58. m_lCount++;
  59. LeaveCriticalSection(&m_csControl);
  60. EnterCriticalSection(&m_cs);
  61. }
  62. void Leave()
  63. {
  64. LeaveCriticalSection(&m_cs);
  65. EnterCriticalSection(&m_csControl);
  66. m_lCount--;
  67. LeaveCriticalSection(&m_csControl);
  68. }
  69. BOOL TryEnter()
  70. {
  71. EnterCriticalSection(&m_csControl);
  72. if(m_lCount > 0)
  73. {
  74. LeaveCriticalSection(&m_csControl);
  75. return FALSE;
  76. }
  77. else
  78. {
  79. EnterCriticalSection(&m_cs);
  80. m_lCount++;
  81. LeaveCriticalSection(&m_csControl);
  82. return TRUE;
  83. }
  84. }
  85. };
  86. class POLARITY CInCritSec
  87. {
  88. protected:
  89. CRITICAL_SECTION* m_pcs;
  90. public:
  91. CInCritSec(CRITICAL_SECTION* pcs) : m_pcs(pcs)
  92. {
  93. __try
  94. {
  95. EnterCriticalSection(m_pcs);
  96. }
  97. __except( GetExceptionCode() == STATUS_NO_MEMORY )
  98. {
  99. throw CX_MemoryException();
  100. }
  101. }
  102. inline ~CInCritSec()
  103. {
  104. LeaveCriticalSection(m_pcs);
  105. }
  106. };
  107. class POLARITY CInTryCritSec
  108. {
  109. protected:
  110. CTryCritSec* m_ptcs;
  111. public:
  112. CInTryCritSec(CTryCritSec* ptcs) : m_ptcs(ptcs)
  113. {
  114. m_ptcs->Enter();
  115. }
  116. ~CInTryCritSec()
  117. {
  118. m_ptcs->Leave();
  119. }
  120. };
  121. // Allows user to manually leave critical section, checks if inside before leaving
  122. class POLARITY CCheckedInCritSec
  123. {
  124. protected:
  125. CRITICAL_SECTION* m_pcs;
  126. BOOL m_fInside;
  127. public:
  128. CCheckedInCritSec(CRITICAL_SECTION* pcs) : m_pcs(pcs), m_fInside( FALSE )
  129. {
  130. EnterCriticalSection(m_pcs);
  131. m_fInside = TRUE;
  132. }
  133. ~CCheckedInCritSec()
  134. {
  135. Leave();
  136. }
  137. void Enter( void )
  138. {
  139. if ( !m_fInside )
  140. {
  141. EnterCriticalSection(m_pcs);
  142. m_fInside = TRUE;
  143. }
  144. }
  145. void Leave( void )
  146. {
  147. if ( m_fInside )
  148. {
  149. m_fInside = FALSE;
  150. LeaveCriticalSection(m_pcs);
  151. }
  152. }
  153. BOOL IsEntered( void )
  154. { return m_fInside; }
  155. };
  156. //
  157. // This class implements a light-weight exclusive lock. Critical sections are
  158. // not very good for this because they:
  159. // 1) Do not allow lock/unlock to occur on different threads
  160. // 2) Do not admit timeouts
  161. //
  162. // On the flip side, this guy is intentionally non-reentrant.
  163. // TBD: efficiency
  164. //
  165. class POLARITY CSimpleLock
  166. {
  167. protected:
  168. HANDLE m_hEvent;
  169. DWORD m_dwOwningThread;
  170. long m_lWaiting;
  171. bool m_bLocked;
  172. CCritSec m_cs;
  173. public:
  174. CSimpleLock();
  175. ~CSimpleLock();
  176. DWORD Enter(DWORD dwTimeout = INFINITE);
  177. void Leave();
  178. };
  179. class POLARITY CHaltable
  180. {
  181. public:
  182. CHaltable();
  183. virtual ~CHaltable();
  184. HRESULT Halt();
  185. HRESULT Resume();
  186. HRESULT ResumeAll();
  187. HRESULT WaitForResumption();
  188. BOOL IsHalted();
  189. bool isValid();
  190. private:
  191. CCritSec m_csHalt;
  192. HANDLE m_hReady;
  193. DWORD m_dwHaltCount;
  194. long m_lJustResumed;
  195. };
  196. inline bool
  197. CHaltable::isValid()
  198. { return m_hReady != NULL; };
  199. // This class is designed to provide the behavior of a critical section,
  200. // but without any of that pesky Kernel code. In some circumstances, we
  201. // need to lock resources across multiple threads (i.e. we lock on one
  202. // thread and unlock on another). If we do this using a critical section,
  203. // this appears to work, but in checked builds, we end up throwing an
  204. // exception. Since we actually need to do this (for example using NextAsync
  205. // in IEnumWbemClassObject) this class can be used to perform the
  206. // operation, but without causing exceptions in checked builds.
  207. // Please note that code that is going to do this MUST ensure that we don't
  208. // get crossing Enter/Leave operations (in other words, it's responsible for
  209. // synchronizing the Enter and Leave operations.) Please note that this
  210. // is a dangerous thing to do, so be VERY careful if you are using this
  211. // code for that purpose.
  212. class POLARITY CWbemCriticalSection
  213. {
  214. private:
  215. long m_lLock;
  216. long m_lRecursionCount;
  217. DWORD m_dwThreadId;
  218. HANDLE m_hEvent;
  219. public:
  220. CWbemCriticalSection();
  221. ~CWbemCriticalSection();
  222. BOOL Enter( DWORD dwTimeout = INFINITE );
  223. void Leave( void );
  224. DWORD GetOwningThreadId( void )
  225. { return m_dwThreadId; }
  226. long GetLockCount( void )
  227. { return m_lLock; }
  228. long GetRecursionCount( void )
  229. { return m_lRecursionCount; }
  230. };
  231. class POLARITY CEnterWbemCriticalSection
  232. {
  233. CWbemCriticalSection* m_pcs;
  234. BOOL m_fInside;
  235. public:
  236. CEnterWbemCriticalSection( CWbemCriticalSection* pcs, DWORD dwTimeout = INFINITE )
  237. : m_pcs( pcs ), m_fInside( FALSE )
  238. {
  239. if ( m_pcs )
  240. {
  241. m_fInside = m_pcs->Enter( dwTimeout );
  242. }
  243. }
  244. ~CEnterWbemCriticalSection( void )
  245. {
  246. if ( m_fInside )
  247. {
  248. m_pcs->Leave();
  249. }
  250. }
  251. BOOL IsEntered( void )
  252. { return m_fInside; }
  253. };
  254. class POLARITY CScopeLock
  255. {
  256. private:
  257. long* m_plVal;
  258. public:
  259. CScopeLock( long* plVal ) : m_plVal( plVal )
  260. { if ( NULL != m_plVal ) InterlockedIncrement( m_plVal ); }
  261. ~CScopeLock()
  262. { if ( NULL != m_plVal ) InterlockedDecrement( m_plVal ); }
  263. };
  264. #endif