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.

269 lines
6.5 KiB

  1. /*--------------------------------------------------------
  2. rwlock.h
  3. CReadWriteLock class provides functions that allow
  4. threads to lock any resource in two different
  5. modes (read-mode and write-mode).
  6. The class will allow multiple reader threads to access
  7. the resource simultaneously, but will make sure that
  8. a writer thread doesn't access the resource when
  9. reader threads or a writer thread is currently accessing
  10. the resource. The class also assures fairness in access
  11. i.e. the access will be regulated by a first-come-first-in
  12. policy.
  13. Note:- ALL the functions in the class are INLINE functions.
  14. So, this header can be directly used in the source.
  15. Copyright (C) 1997-98 Microsoft Corporation
  16. All rights reserved.
  17. Authors:
  18. rsraghav R.S. Raghavan
  19. History:
  20. 04-20-95 rsraghav Created.
  21. -------------------------------------------------------*/
  22. #ifdef __cplusplus // this file should be include only if this is
  23. // is included in a c++ source file.
  24. #ifndef _RWLOCK_H_
  25. #define _RWLOCK_H_
  26. #if defined(DEBUG) && defined(INLINE)
  27. #undef THIS_FILE
  28. static char BASED_CODE RWLOCK_H[] = "rwlock.h";
  29. #define THIS_FILE RWLOCK_H
  30. #endif
  31. #include <windows.h>
  32. #define INLINE_EXPORT_SPEC __declspec( dllexport)
  33. typedef enum {RWLOCK_READ_MODE, RWLOCK_WRITE_MODE} RWLOCK_MODE;
  34. //////////////////////////////////////////////////////////////////////
  35. // CReadWriteLock - Class that can be used to regulate read-write
  36. // access to resource, where multiple readers are
  37. // allowed simultaneously, but writers are excluded
  38. // from each other and from the readers.
  39. class CReadWriteLock
  40. {
  41. HANDLE hResource;
  42. CRITICAL_SECTION csReader;
  43. CRITICAL_SECTION csWriter;
  44. DWORD cReaders;
  45. DWORD cWriteRecursion;
  46. public:
  47. CReadWriteLock() // object constructor
  48. {
  49. cReaders =0;
  50. cWriteRecursion = 0;
  51. hResource = CreateEvent(NULL, FALSE, TRUE, NULL); // no manual reset & initial state is signalled
  52. InitializeCriticalSection(&csReader);
  53. InitializeCriticalSection(&csWriter);
  54. }
  55. ~CReadWriteLock() // object destructor
  56. {
  57. if (hResource)
  58. CloseHandle(hResource);
  59. DeleteCriticalSection(&csReader);
  60. DeleteCriticalSection(&csWriter);
  61. }
  62. CReadWriteLock *PrwLock()
  63. {
  64. return this;
  65. }
  66. BOOL FInit()
  67. {
  68. return (BOOL)hResource;
  69. }
  70. void LockReadMode() // Get read access to the resource
  71. {
  72. EnterCriticalSection(&csWriter);
  73. LeaveCriticalSection(&csWriter);
  74. EnterCriticalSection(&csReader);
  75. if (!cReaders)
  76. {
  77. if (hResource)
  78. WaitForSingleObject(hResource, INFINITE);
  79. }
  80. cReaders++;
  81. LeaveCriticalSection(&csReader);
  82. }
  83. int LockReadModeEx(int iTimeOut) // Get read access to the resource w/ Timeout
  84. {
  85. int status = 0;
  86. EnterCriticalSection(&csWriter);
  87. LeaveCriticalSection(&csWriter);
  88. EnterCriticalSection(&csReader);
  89. if (!cReaders)
  90. {
  91. if (hResource) {
  92. status = WaitForSingleObject(hResource, iTimeOut);
  93. if (status == WAIT_TIMEOUT)
  94. {
  95. status = -1;
  96. } else {
  97. status = 0;
  98. }
  99. }
  100. }
  101. cReaders++;
  102. LeaveCriticalSection(&csReader);
  103. return status;
  104. }
  105. void UnlockReadMode() // Relinquish read access to the resource
  106. {
  107. EnterCriticalSection(&csReader);
  108. if (!(--cReaders))
  109. {
  110. if (hResource)
  111. SetEvent(hResource);
  112. }
  113. LeaveCriticalSection(&csReader);
  114. }
  115. void LockCSUnderRead()
  116. {
  117. EnterCriticalSection(&csReader);
  118. }
  119. void UnlockCSUnderRead()
  120. {
  121. LeaveCriticalSection(&csReader);
  122. }
  123. void LockWriteMode() // Get write access to the resource
  124. {
  125. EnterCriticalSection(&csWriter);
  126. if (!cWriteRecursion)
  127. {
  128. if (hResource)
  129. WaitForSingleObject(hResource, INFINITE);
  130. }
  131. cWriteRecursion++;
  132. }
  133. int LockWriteModeEx(int iTimeOut) // Get write access to the resource
  134. {
  135. int status = 0;
  136. EnterCriticalSection(&csWriter);
  137. if (!cWriteRecursion)
  138. {
  139. if (hResource)
  140. {
  141. status = WaitForSingleObject(hResource, iTimeOut);
  142. if (status == WAIT_TIMEOUT)
  143. {
  144. status = -1;
  145. } else {
  146. status = 0;
  147. }
  148. }
  149. }
  150. if (status == 0)
  151. cWriteRecursion++;
  152. return status;
  153. }
  154. void UnlockWriteMode() // Relinquish write access to the resource
  155. {
  156. if (!(--cWriteRecursion))
  157. {
  158. if (hResource)
  159. SetEvent(hResource);
  160. }
  161. LeaveCriticalSection(&csWriter);
  162. }
  163. };
  164. //////////////////////////////////////////////////////////////////////
  165. // Following class is just a utility class - users don't need to
  166. // necessarily use this class for obtaining read-write lock functionalities.
  167. //////////////////////////////////////////////////////////////////////
  168. // CScopeRWLock - This can be used to lock the given CReadWriteLock
  169. // object for the rest of the scope. The user just
  170. // needs to define this object in the scope by passing
  171. // a pointer to the CReadWriteLock object in the constructor.
  172. // When this CScopeRWLock object goes out of scope the
  173. // CReadWriteLock object will automatically be unlocked.
  174. // This is provided just for user convenience so that the
  175. // user can choose to avoid remembering to unlock the object
  176. // before every possible return/break path of the scope.
  177. // Use the RWLOCK_READ_MODE or RWLOCK_WRITE_MODE in the constructor
  178. // to indicate which type of access is requested.
  179. // Assumption:- CReadWriteLock object used here is expected to
  180. // be valid at lease until the end of the scope.
  181. class CScopeRWLock
  182. {
  183. CReadWriteLock *m_prwLock;
  184. LPCRITICAL_SECTION m_pcs;
  185. RWLOCK_MODE m_rwMode;
  186. public:
  187. CScopeRWLock(CReadWriteLock * prwLock, RWLOCK_MODE rwMode)
  188. {
  189. m_prwLock = prwLock;
  190. m_pcs = NULL;
  191. m_rwMode = rwMode;
  192. if (m_prwLock)
  193. {
  194. if (m_rwMode == RWLOCK_READ_MODE)
  195. m_prwLock->LockReadMode();
  196. else if (m_rwMode == RWLOCK_WRITE_MODE)
  197. m_prwLock->LockWriteMode();
  198. }
  199. }
  200. CScopeRWLock(LPCRITICAL_SECTION pcsLock)
  201. {
  202. m_pcs = pcsLock;
  203. m_prwLock = NULL;
  204. if (m_pcs)
  205. EnterCriticalSection(m_pcs);
  206. }
  207. ~CScopeRWLock()
  208. {
  209. if (m_prwLock)
  210. {
  211. if (m_rwMode == RWLOCK_READ_MODE)
  212. m_prwLock->UnlockReadMode();
  213. else if (m_rwMode == RWLOCK_WRITE_MODE)
  214. m_prwLock->UnlockWriteMode();
  215. }
  216. if (m_pcs)
  217. {
  218. LeaveCriticalSection(m_pcs);
  219. }
  220. }
  221. };
  222. #endif // _RWLOCK_H_
  223. #endif // #if __cplusplus