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.

332 lines
7.5 KiB

  1. //////////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // CriticalSection.cpp
  4. //
  5. // Copyright (C) 1998, 1999 Microsoft Corporation. All rights reserved.
  6. //
  7. // Abstract :
  8. //
  9. // This is the implementation of CCriticalSection
  10. //
  11. // History :
  12. //
  13. // 05/06/1999 luish Created
  14. //
  15. //////////////////////////////////////////////////////////////////////////////////////////////
  16. #include <assert.h>
  17. #include "CriticalSection.h"
  18. #include "ExceptionHandler.h"
  19. #include "AppManDebug.h"
  20. //To flag as DBG_LOCK
  21. #ifdef DBG_MODULE
  22. #undef DBG_MODULE
  23. #endif
  24. #define DBG_MODULE DBG_LOCK
  25. //////////////////////////////////////////////////////////////////////////////////////////////
  26. //
  27. //////////////////////////////////////////////////////////////////////////////////////////////
  28. CCriticalSection::CCriticalSection(void)
  29. {
  30. FUNCTION("CCriticalSection::CCriticalSection (void)");
  31. m_lLockCount = 0;
  32. m_hAccessMutex = NULL;
  33. m_fCreator = FALSE;
  34. }
  35. //////////////////////////////////////////////////////////////////////////////////////////////
  36. //
  37. //////////////////////////////////////////////////////////////////////////////////////////////
  38. CCriticalSection::~CCriticalSection(void)
  39. {
  40. FUNCTION("CCriticalSection::~CCriticalSection (void)");
  41. Shutdown();
  42. }
  43. //////////////////////////////////////////////////////////////////////////////////////////////
  44. //
  45. //////////////////////////////////////////////////////////////////////////////////////////////
  46. STDMETHODIMP CCriticalSection::Initialize(void)
  47. {
  48. FUNCTION("CCriticalSection::Initialize ()");
  49. if (NULL != m_hAccessMutex)
  50. {
  51. Shutdown();
  52. }
  53. if (NULL == m_hAccessMutex)
  54. {
  55. m_lLockCount = 0;
  56. m_hAccessMutex = CreateMutex(NULL, FALSE, NULL);
  57. if (NULL == m_hAccessMutex)
  58. {
  59. THROW(E_UNEXPECTED);
  60. }
  61. m_fCreator = TRUE;
  62. }
  63. return S_OK;
  64. }
  65. //////////////////////////////////////////////////////////////////////////////////////////////
  66. //
  67. //////////////////////////////////////////////////////////////////////////////////////////////
  68. STDMETHODIMP CCriticalSection::Initialize(const BOOL fOwner)
  69. {
  70. FUNCTION("CCriticalSection::Initialize ()");
  71. if (NULL != m_hAccessMutex)
  72. {
  73. Shutdown();
  74. }
  75. if (NULL == m_hAccessMutex)
  76. {
  77. //
  78. // Please note that since this is not a named mutex object, we are guaranteed to create
  79. // it if the memory is available
  80. //
  81. m_lLockCount = 0;
  82. m_hAccessMutex = CreateMutex(NULL, fOwner, NULL);
  83. if (NULL == m_hAccessMutex)
  84. {
  85. THROW(E_UNEXPECTED);
  86. }
  87. m_fCreator = TRUE;
  88. if (fOwner)
  89. {
  90. InterlockedIncrement(&m_lLockCount);
  91. }
  92. }
  93. return S_OK;
  94. }
  95. //////////////////////////////////////////////////////////////////////////////////////////////
  96. //
  97. //////////////////////////////////////////////////////////////////////////////////////////////
  98. STDMETHODIMP CCriticalSection::Initialize(const BOOL fOwner, const CHAR * pName)
  99. {
  100. FUNCTION("CCriticalSection::Initialize ()");
  101. if (NULL != m_hAccessMutex)
  102. {
  103. Shutdown();
  104. }
  105. if (NULL == m_hAccessMutex)
  106. {
  107. m_lLockCount = 0;
  108. m_hAccessMutex = CreateMutex(NULL, fOwner, pName);
  109. if (NULL == m_hAccessMutex)
  110. {
  111. THROW(E_UNEXPECTED);
  112. }
  113. //
  114. // Use GetLastError() to define whether or not the call to CreateMutex() actually created
  115. // a new mutex object or simply returned the handle of an existing mutex object
  116. //
  117. if (ERROR_ALREADY_EXISTS == GetLastError())
  118. {
  119. m_fCreator = FALSE;
  120. }
  121. else
  122. {
  123. m_fCreator = TRUE;
  124. }
  125. //
  126. // Since it is possible for this named mutex to have been created prior, we must check
  127. // to see if we created it or simply copied it. If we copied it and TRUE == fOwner, then
  128. // we will not have ownership of the mutex and henceforth must call Enter() before
  129. // returning
  130. //
  131. if (fOwner)
  132. {
  133. if (!m_fCreator)
  134. {
  135. return Enter();
  136. }
  137. else
  138. {
  139. InterlockedIncrement(&m_lLockCount);
  140. }
  141. }
  142. }
  143. return S_OK;
  144. }
  145. //////////////////////////////////////////////////////////////////////////////////////////////
  146. //
  147. //////////////////////////////////////////////////////////////////////////////////////////////
  148. STDMETHODIMP CCriticalSection::Shutdown(void)
  149. {
  150. FUNCTION("CCriticalSection::Shutdown ()");
  151. //
  152. // If the m_hAccessMutex handle was successfully created, we need to make sure that
  153. // we release all lock instances associated with this object is we own the lock
  154. //
  155. if (NULL != m_hAccessMutex)
  156. {
  157. while (0 < m_lLockCount)
  158. {
  159. ReleaseMutex(m_hAccessMutex);
  160. m_lLockCount--;
  161. }
  162. CloseHandle(m_hAccessMutex);
  163. m_hAccessMutex = NULL;
  164. }
  165. m_lLockCount = 0;
  166. return S_OK;
  167. }
  168. //////////////////////////////////////////////////////////////////////////////////////////////
  169. //
  170. //////////////////////////////////////////////////////////////////////////////////////////////
  171. STDMETHODIMP CCriticalSection::IsInitialized(void)
  172. {
  173. FUNCTION("CCriticalSection::IsInitialized ()");
  174. if (NULL == m_hAccessMutex)
  175. {
  176. return S_FALSE;
  177. }
  178. return S_OK;
  179. }
  180. //////////////////////////////////////////////////////////////////////////////////////////////
  181. //
  182. //////////////////////////////////////////////////////////////////////////////////////////////
  183. STDMETHODIMP CCriticalSection::IsCreator(void)
  184. {
  185. FUNCTION("CCriticalSection::IsCreator ()");
  186. if (!m_fCreator)
  187. {
  188. return S_FALSE;
  189. }
  190. return S_OK;
  191. }
  192. //////////////////////////////////////////////////////////////////////////////////////////////
  193. //
  194. //////////////////////////////////////////////////////////////////////////////////////////////
  195. STDMETHODIMP_(DWORD) CCriticalSection::GetLockCount(void)
  196. {
  197. FUNCTION("CCriticalSection::GetLockCount ()");
  198. LONG lLockCount;
  199. lLockCount = InterlockedExchange(&m_lLockCount, m_lLockCount);
  200. if (0 > lLockCount)
  201. {
  202. THROW(E_UNEXPECTED);
  203. }
  204. return (DWORD) lLockCount;
  205. }
  206. //////////////////////////////////////////////////////////////////////////////////////////////
  207. //
  208. //////////////////////////////////////////////////////////////////////////////////////////////
  209. STDMETHODIMP CCriticalSection::Enter(void)
  210. {
  211. FUNCTION("CCriticalSection::Enter ()");
  212. if (NULL == m_hAccessMutex)
  213. {
  214. THROW(E_UNEXPECTED);
  215. }
  216. if (WAIT_TIMEOUT == WaitForSingleObject(m_hAccessMutex, TEN_SECONDS))
  217. {
  218. THROW(E_UNEXPECTED);
  219. }
  220. InterlockedIncrement(&m_lLockCount);
  221. return S_OK;
  222. }
  223. //////////////////////////////////////////////////////////////////////////////////////////////
  224. //
  225. //////////////////////////////////////////////////////////////////////////////////////////////
  226. STDMETHODIMP CCriticalSection::Enter(const DWORD dwWaitTime)
  227. {
  228. FUNCTION("CCriticalSection::Enter ()");
  229. if (NULL == m_hAccessMutex)
  230. {
  231. THROW(E_UNEXPECTED);
  232. }
  233. if (WAIT_TIMEOUT == WaitForSingleObject(m_hAccessMutex, dwWaitTime))
  234. {
  235. return S_FALSE;
  236. }
  237. InterlockedIncrement(&m_lLockCount);
  238. return S_OK;
  239. }
  240. //////////////////////////////////////////////////////////////////////////////////////////////
  241. //
  242. // NOTE : This function can never fail. It will always return CSECTION_S_OK
  243. //
  244. //////////////////////////////////////////////////////////////////////////////////////////////
  245. STDMETHODIMP CCriticalSection::Leave(void)
  246. {
  247. FUNCTION("CCriticalSection::Leave ()");
  248. if (NULL == m_hAccessMutex)
  249. {
  250. THROW(E_UNEXPECTED);
  251. }
  252. //
  253. // If the lock count is greater than 0, release the mutex and decrement the lock count
  254. //
  255. if (0 < GetLockCount())
  256. {
  257. InterlockedDecrement(&m_lLockCount);
  258. if (!ReleaseMutex(m_hAccessMutex))
  259. {
  260. THROW(E_UNEXPECTED);
  261. }
  262. return S_OK;
  263. }
  264. return S_FALSE;
  265. }