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.

220 lines
5.5 KiB

  1. #include <unicode.h>
  2. #include <windows.h>
  3. #include "SafeCS.h"
  4. //+-----------------------------------------------------------------------
  5. //
  6. // Microsoft Windows
  7. //
  8. // Copyright (c) Microsoft Corporation 2000
  9. //
  10. // File: SafeCS.cpp
  11. //
  12. // Contents: CSafeAutoCriticalSection implementation
  13. // CSafeLock implementation
  14. //
  15. //------------------------------------------------------------------------
  16. //+--------------------------------------------------------------------------
  17. //
  18. // Class: CSafeAutoCriticalSection
  19. //
  20. // Purpose: Wrapper for initializing critical-sections.
  21. //
  22. // Interface: Lock - locks the critical section
  23. // Unlock - unlocks the critical section
  24. // Constructor - initializes the critical section
  25. // Detructor - uninitializes the critical section
  26. //
  27. // Notes: This provides a convenient way to ensure that you're
  28. // you wrap InitializeCriticalSection and
  29. // UnInitializeCriticalSection in try catches which is useful
  30. // in low-mem conditions
  31. //
  32. //---------------------------------------------------------------------------
  33. //+--------------------------------------------------------------------------
  34. // Default constructor - Initializes the critical section and sets the state
  35. // flag to initialized
  36. //+--------------------------------------------------------------------------
  37. CSafeAutoCriticalSection::CSafeAutoCriticalSection()
  38. {
  39. m_lState = STATE_UNINITIALIZED;
  40. m_dwError = ERROR_SUCCESS;
  41. __try
  42. {
  43. LONG lPreviousState;
  44. // try to set state flag
  45. lPreviousState = InterlockedCompareExchange(&m_lState,
  46. STATE_INITIALIZED,
  47. STATE_UNINITIALIZED);
  48. // if this critical section was not initialized
  49. if(STATE_UNINITIALIZED == lPreviousState)
  50. {
  51. //
  52. // Note we can call InitializeCriticalSectionAndSpinCount here
  53. // and thereby eliminate the need for a try catch in
  54. // EnterCriticalSection. But the docs say that
  55. // InitializeCriticalSectionAndSpinCount is valid on NT4.0 SP3
  56. // onwards and we need to run on plain NT4.0 - hence we call
  57. // InitializeCriticalSection
  58. //
  59. InitializeCriticalSection(&m_cs);
  60. }
  61. }
  62. __except(EXCEPTION_EXECUTE_HANDLER)
  63. {
  64. m_dwError = _exception_code();
  65. }
  66. // failed to initialize - need to reset
  67. if(ERROR_SUCCESS != m_dwError)
  68. {
  69. m_lState = STATE_UNINITIALIZED;
  70. }
  71. }
  72. //+--------------------------------------------------------------------------
  73. // Destructor
  74. //+--------------------------------------------------------------------------
  75. CSafeAutoCriticalSection::~CSafeAutoCriticalSection()
  76. {
  77. LONG lPreviousState;
  78. // try to reset the the state to uninitialized
  79. lPreviousState = InterlockedCompareExchange(&m_lState,
  80. STATE_UNINITIALIZED,
  81. STATE_INITIALIZED);
  82. // if the object was initialized delete the critical section
  83. if(STATE_INITIALIZED == lPreviousState)
  84. {
  85. DeleteCriticalSection(&m_cs);
  86. }
  87. }
  88. //+--------------------------------------------------------------------------
  89. // Enters critical section, if needed initializes critical section
  90. // before entering
  91. //
  92. // Returns
  93. // DWORD - ERROR_SUCCESS if everything is fine
  94. // ERROR_OUTOFMEMORY if failed to create or enter critical section
  95. //+--------------------------------------------------------------------------
  96. DWORD CSafeAutoCriticalSection::Lock()
  97. {
  98. DWORD dwError = ERROR_SUCCESS;
  99. if(!IsInitialized())
  100. {
  101. return m_dwError;
  102. }
  103. __try
  104. {
  105. EnterCriticalSection(&m_cs);
  106. }
  107. __except(EXCEPTION_EXECUTE_HANDLER)
  108. {
  109. dwError = _exception_code();
  110. }
  111. return dwError;
  112. }
  113. //+--------------------------------------------------------------------------
  114. // Leaves critical section
  115. //+--------------------------------------------------------------------------
  116. DWORD CSafeAutoCriticalSection::Unlock()
  117. {
  118. if(!IsInitialized())
  119. {
  120. return m_dwError;
  121. }
  122. LeaveCriticalSection(&m_cs);
  123. return ERROR_SUCCESS;
  124. }
  125. //+--------------------------------------------------------------------------
  126. //
  127. // Class: CSafeLock
  128. //
  129. // Purpose: Auto-unlocking critical-section services
  130. //
  131. // Interface: Lock - locks the critical section
  132. // Unlock - unlocks the critical section
  133. // Constructor - locks the critical section (unless told
  134. // otherwise)
  135. // Detructor - unlocks the critical section if its locked
  136. //
  137. // Notes: This provides a convenient way to ensure that you're
  138. // unlocking a CSemExclusive, which is useful if your routine
  139. // can be left via several returns and/or via exceptions....
  140. //
  141. //---------------------------------------------------------------------------
  142. CSafeLock::CSafeLock(CSafeAutoCriticalSection* val) :
  143. m_pSem(val),
  144. m_locked(FALSE)
  145. {
  146. }
  147. CSafeLock::CSafeLock(CSafeAutoCriticalSection& val) :
  148. m_pSem(&val),
  149. m_locked(FALSE)
  150. {
  151. }
  152. CSafeLock::~CSafeLock()
  153. {
  154. if (m_locked)
  155. {
  156. m_pSem->Unlock();
  157. }
  158. }
  159. DWORD CSafeLock::Lock()
  160. {
  161. DWORD dwError = ERROR_SUCCESS;
  162. if(!m_locked)
  163. {
  164. dwError = m_pSem->Lock();
  165. if(ERROR_SUCCESS == dwError)
  166. {
  167. m_locked = TRUE;
  168. }
  169. }
  170. return dwError;
  171. }
  172. DWORD CSafeLock::Unlock()
  173. {
  174. DWORD dwError = ERROR_SUCCESS;
  175. if(m_locked)
  176. {
  177. dwError = m_pSem->Unlock();
  178. m_locked = FALSE;
  179. }
  180. return dwError;
  181. }