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.

233 lines
4.2 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: critsect.h
  7. //
  8. // Contents: critical section helper class
  9. //
  10. // Classes: CCriticalSection
  11. // CLockHandler
  12. // CLock
  13. //
  14. //
  15. // Notes:
  16. //
  17. // History: 13-Nov-97 rogerg Created.
  18. //
  19. //--------------------------------------------------------------------------
  20. #ifndef _CRITSECT_
  21. #define _CRITSECT_
  22. #include "widewrap.h"
  23. class CLock;
  24. class CCriticalSection
  25. {
  26. DWORD cRefs;
  27. CRITICAL_SECTION *m_pcsect;
  28. DWORD m_dwThreadID;
  29. public:
  30. inline CCriticalSection(CRITICAL_SECTION *pcsect,DWORD dwThreadID)
  31. {
  32. m_pcsect = pcsect;
  33. cRefs = 0;
  34. m_dwThreadID = dwThreadID;
  35. };
  36. inline ~CCriticalSection()
  37. {
  38. AssertSz(0 == cRefs,"UnReleased Critical Section");
  39. Assert(m_dwThreadID == GetCurrentThreadId());
  40. while(cRefs--) // unwind any left over cRefs
  41. {
  42. LeaveCriticalSection(m_pcsect);
  43. }
  44. };
  45. inline void Enter()
  46. {
  47. EnterCriticalSection(m_pcsect);
  48. Assert(m_dwThreadID == GetCurrentThreadId());
  49. ++cRefs;
  50. Assert(1 == cRefs); // we don't allow nested calls.
  51. };
  52. inline void Leave()
  53. {
  54. Assert(m_dwThreadID == GetCurrentThreadId());
  55. Assert(0 < cRefs);
  56. if (0 >= cRefs)
  57. return;
  58. --cRefs;
  59. Assert(0 == cRefs);
  60. LeaveCriticalSection(m_pcsect);
  61. };
  62. };
  63. class CLockHandler {
  64. public:
  65. CLockHandler();
  66. ~CLockHandler();
  67. void Lock(DWORD dwThreadId);
  68. void UnLock();
  69. inline DWORD GetLockThreadId() { return m_dwLockThreadId; };
  70. private:
  71. CRITICAL_SECTION m_CriticalSection; // critical section for the queue.
  72. DWORD m_dwLockThreadId; // thread that has the lock.
  73. friend CLock;
  74. };
  75. // helper class for making sure locks on the queue are released.
  76. class CLock
  77. {
  78. DWORD cRefs;
  79. CLockHandler *m_pLockHandler;
  80. DWORD m_dwThreadID;
  81. public:
  82. inline CLock(CLockHandler *pLockHandler)
  83. {
  84. m_pLockHandler = pLockHandler;
  85. cRefs = 0;
  86. m_dwThreadID = GetCurrentThreadId();
  87. };
  88. inline ~CLock()
  89. {
  90. AssertSz(0 == cRefs,"UnReleased Lock");
  91. Assert(m_dwThreadID == GetCurrentThreadId());
  92. while(cRefs--) // unwind any left over cRefs
  93. {
  94. m_pLockHandler->UnLock();
  95. }
  96. };
  97. inline void Enter()
  98. {
  99. Assert(m_dwThreadID == GetCurrentThreadId());
  100. ++cRefs;
  101. Assert(1 == cRefs); // we don't allow nested calls.
  102. m_pLockHandler->Lock(m_dwThreadID);
  103. };
  104. inline void Leave()
  105. {
  106. Assert(m_dwThreadID == GetCurrentThreadId());
  107. Assert(0 < cRefs);
  108. if (0 >= cRefs)
  109. return;
  110. --cRefs;
  111. Assert(0 == cRefs);
  112. m_pLockHandler->UnLock();
  113. };
  114. };
  115. #define ASSERT_LOCKHELD(pLockHandler) Assert(pLockHandler->GetLockThreadId() == GetCurrentThreadId());
  116. #define ASSERT_LOCKNOTHELD(pLockHandler) Assert(pLockHandler->GetLockThreadId() == 0);
  117. // helper class for Mutex locking
  118. class CMutex
  119. {
  120. HANDLE m_hMutex;
  121. BOOL m_fHasLock;
  122. BOOL m_fReleasedLock;
  123. public:
  124. inline CMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes,BOOL bInitialOwner,LPCTSTR lpName)
  125. {
  126. m_hMutex = CreateMutex(lpMutexAttributes,bInitialOwner,lpName);
  127. // on failure routines go on just don't take the lock
  128. m_fHasLock = FALSE;
  129. m_fReleasedLock = FALSE;
  130. };
  131. inline ~CMutex()
  132. {
  133. AssertSz(!m_fHasLock,"UnReleased Mutex ");
  134. // if failed to release mutex release now.
  135. if (m_hMutex && m_fHasLock)
  136. {
  137. ReleaseMutex(m_hMutex);
  138. }
  139. if (m_hMutex)
  140. {
  141. CloseHandle(m_hMutex);
  142. }
  143. };
  144. inline void Enter(DWORD dwMilliseconds = INFINITE)
  145. {
  146. AssertSz(!m_fHasLock,"Tried to take Lock Twice");
  147. AssertSz(!m_fReleasedLock,"Tried to take lock After Released Mutex");
  148. if (!m_fHasLock && m_hMutex)
  149. {
  150. if (WAIT_OBJECT_0 ==WaitForSingleObject( m_hMutex, dwMilliseconds ))
  151. {
  152. m_fHasLock = TRUE;
  153. }
  154. }
  155. };
  156. inline void Leave()
  157. {
  158. Assert(m_fHasLock);
  159. if (m_fHasLock && m_hMutex)
  160. {
  161. ReleaseMutex(m_hMutex);
  162. }
  163. if (m_hMutex)
  164. {
  165. CloseHandle(m_hMutex);
  166. }
  167. m_hMutex = NULL;
  168. m_fHasLock = FALSE;
  169. m_fReleasedLock = TRUE;
  170. };
  171. };
  172. #endif // _CRITSECT_