Leaked source code of windows server 2003
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.

255 lines
5.8 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. #ifndef STATUS_POSSIBLE_DEADLOCK
  14. #define STATUS_POSSIBLE_DEADLOCK (0xC0000194L)
  15. #endif /*STATUS_POSSIBLE_DEADLOCK */
  16. DWORD POLARITY BreakOnDbgAndRenterLoop(void);
  17. class POLARITY CCritSec : public CRITICAL_SECTION
  18. {
  19. public:
  20. CCritSec()
  21. {
  22. #ifdef _WIN32_WINNT
  23. #if _WIN32_WINNT > 0x0400
  24. bool initialized = (InitializeCriticalSectionAndSpinCount(this,0))?true:false;
  25. if (!initialized) throw CX_MemoryException();
  26. #else
  27. bool initialized = false;
  28. __try
  29. {
  30. InitializeCriticalSection(this);
  31. initialized = true;
  32. }
  33. __except(GetExceptionCode() == STATUS_NO_MEMORY)
  34. {
  35. }
  36. if (!initialized) throw CX_MemoryException();
  37. #endif
  38. #else
  39. bool initialized = false;
  40. __try
  41. {
  42. InitializeCriticalSection(this);
  43. initialized = true;
  44. }
  45. __except(GetExceptionCode() == STATUS_NO_MEMORY)
  46. {
  47. }
  48. if (!initialized) throw CX_MemoryException();
  49. #endif
  50. }
  51. ~CCritSec()
  52. {
  53. DeleteCriticalSection(this);
  54. }
  55. void Enter()
  56. {
  57. __try {
  58. EnterCriticalSection(this);
  59. } __except((STATUS_POSSIBLE_DEADLOCK == GetExceptionCode())? BreakOnDbgAndRenterLoop():EXCEPTION_CONTINUE_SEARCH) {
  60. }
  61. }
  62. void Leave()
  63. {
  64. LeaveCriticalSection(this);
  65. }
  66. };
  67. class POLARITY CInCritSec
  68. {
  69. protected:
  70. CRITICAL_SECTION* m_pcs;
  71. public:
  72. CInCritSec(CRITICAL_SECTION* pcs) : m_pcs(pcs)
  73. {
  74. __try {
  75. EnterCriticalSection(m_pcs);
  76. } __except((STATUS_POSSIBLE_DEADLOCK == GetExceptionCode())? BreakOnDbgAndRenterLoop():EXCEPTION_CONTINUE_SEARCH) {
  77. }
  78. }
  79. inline ~CInCritSec()
  80. {
  81. LeaveCriticalSection(m_pcs);
  82. }
  83. };
  84. // Allows user to manually leave critical section, checks if inside before leaving
  85. class POLARITY CCheckedInCritSec
  86. {
  87. protected:
  88. CCritSec* m_pcs;
  89. BOOL m_fInside;
  90. public:
  91. CCheckedInCritSec(CCritSec* pcs) : m_pcs(pcs), m_fInside( FALSE )
  92. {
  93. m_pcs->Enter();
  94. m_fInside = TRUE;
  95. }
  96. ~CCheckedInCritSec()
  97. {
  98. Leave();
  99. }
  100. void Enter( void )
  101. {
  102. if ( !m_fInside )
  103. {
  104. m_pcs->Enter();
  105. m_fInside = TRUE;
  106. }
  107. }
  108. void Leave( void )
  109. {
  110. if ( m_fInside )
  111. {
  112. m_pcs->Leave();
  113. m_fInside = FALSE;
  114. }
  115. }
  116. BOOL IsEntered( void )
  117. { return m_fInside; }
  118. };
  119. //
  120. // Local wrapper class. Does not initialize or clean up the critsec. Simply
  121. // used as a wrapper for scoping so that AV and exception stack unwinding will
  122. // cause the critsec to be exited properly once it is entered.
  123. //
  124. /////////////////////////////////////////////////////////
  125. class CCritSecWrapper
  126. {
  127. BOOL m_bIn;
  128. CCritSec *m_pcs;
  129. public:
  130. CCritSecWrapper(CCritSec *pcs) { m_pcs = pcs; m_bIn = FALSE; }
  131. ~CCritSecWrapper() { if (m_bIn) m_pcs->Leave(); }
  132. void Enter() { m_pcs->Enter(); m_bIn = TRUE; }
  133. void Leave() { m_pcs->Leave(); m_bIn = FALSE; }
  134. };
  135. class POLARITY CHaltable
  136. {
  137. public:
  138. CHaltable();
  139. virtual ~CHaltable();
  140. HRESULT Halt();
  141. HRESULT Resume();
  142. HRESULT ResumeAll();
  143. HRESULT WaitForResumption();
  144. BOOL IsHalted();
  145. bool isValid();
  146. private:
  147. CCritSec m_csHalt;
  148. HANDLE m_hReady;
  149. DWORD m_dwHaltCount;
  150. long m_lJustResumed;
  151. };
  152. inline bool
  153. CHaltable::isValid()
  154. { return m_hReady != NULL; };
  155. // This class is designed to provide the behavior of a critical section,
  156. // but without any of that pesky Kernel code. In some circumstances, we
  157. // need to lock resources across multiple threads (i.e. we lock on one
  158. // thread and unlock on another). If we do this using a critical section,
  159. // this appears to work, but in checked builds, we end up throwing an
  160. // exception. Since we actually need to do this (for example using NextAsync
  161. // in IEnumWbemClassObject) this class can be used to perform the
  162. // operation, but without causing exceptions in checked builds.
  163. // Please note that code that is going to do this MUST ensure that we don't
  164. // get crossing Enter/Leave operations (in other words, it's responsible for
  165. // synchronizing the Enter and Leave operations.) Please note that this
  166. // is a dangerous thing to do, so be VERY careful if you are using this
  167. // code for that purpose.
  168. class POLARITY CWbemCriticalSection
  169. {
  170. private:
  171. long m_lLock;
  172. long m_lRecursionCount;
  173. DWORD m_dwThreadId;
  174. HANDLE m_hEvent;
  175. public:
  176. CWbemCriticalSection();
  177. ~CWbemCriticalSection();
  178. BOOL Enter( DWORD dwTimeout = INFINITE );
  179. void Leave( void );
  180. DWORD GetOwningThreadId( void )
  181. { return m_dwThreadId; }
  182. long GetLockCount( void )
  183. { return m_lLock; }
  184. long GetRecursionCount( void )
  185. { return m_lRecursionCount; }
  186. };
  187. class POLARITY CEnterWbemCriticalSection
  188. {
  189. CWbemCriticalSection* m_pcs;
  190. BOOL m_fInside;
  191. public:
  192. CEnterWbemCriticalSection( CWbemCriticalSection* pcs, DWORD dwTimeout = INFINITE )
  193. : m_pcs( pcs ), m_fInside( FALSE )
  194. {
  195. if ( m_pcs )
  196. {
  197. m_fInside = m_pcs->Enter( dwTimeout );
  198. }
  199. }
  200. ~CEnterWbemCriticalSection( void )
  201. {
  202. if ( m_fInside )
  203. {
  204. m_pcs->Leave();
  205. }
  206. }
  207. BOOL IsEntered( void )
  208. { return m_fInside; }
  209. };
  210. #endif