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.

270 lines
6.6 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) 1995 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 INLINE_EXPORT_SPEC 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. LeaveCriticalSection(&csWriter);
  145. status = -1;
  146. } else {
  147. status = 0;
  148. }
  149. }
  150. }
  151. if (status == 0)
  152. cWriteRecursion++;
  153. return status;
  154. }
  155. void UnlockWriteMode() // Relinquish write access to the resource
  156. {
  157. if (!(--cWriteRecursion))
  158. {
  159. if (hResource)
  160. SetEvent(hResource);
  161. }
  162. LeaveCriticalSection(&csWriter);
  163. }
  164. };
  165. //////////////////////////////////////////////////////////////////////
  166. // Following class is just a utility class - users don't need to
  167. // necessarily use this class for obtaining read-write lock functionalities.
  168. //////////////////////////////////////////////////////////////////////
  169. // CScopeRWLock - This can be used to lock the given CReadWriteLock
  170. // object for the rest of the scope. The user just
  171. // needs to define this object in the scope by passing
  172. // a pointer to the CReadWriteLock object in the constructor.
  173. // When this CScopeRWLock object goes out of scope the
  174. // CReadWriteLock object will automatically be unlocked.
  175. // This is provided just for user convenience so that the
  176. // user can choose to avoid remembering to unlock the object
  177. // before every possible return/break path of the scope.
  178. // Use the RWLOCK_READ_MODE or RWLOCK_WRITE_MODE in the constructor
  179. // to indicate which type of access is requested.
  180. // Assumption:- CReadWriteLock object used here is expected to
  181. // be valid at lease until the end of the scope.
  182. class INLINE_EXPORT_SPEC CScopeRWLock
  183. {
  184. CReadWriteLock *m_prwLock;
  185. LPCRITICAL_SECTION m_pcs;
  186. RWLOCK_MODE m_rwMode;
  187. public:
  188. CScopeRWLock(CReadWriteLock * prwLock, RWLOCK_MODE rwMode)
  189. {
  190. m_prwLock = prwLock;
  191. m_pcs = NULL;
  192. m_rwMode = rwMode;
  193. if (m_prwLock)
  194. {
  195. if (m_rwMode == RWLOCK_READ_MODE)
  196. m_prwLock->LockReadMode();
  197. else if (m_rwMode == RWLOCK_WRITE_MODE)
  198. m_prwLock->LockWriteMode();
  199. }
  200. }
  201. CScopeRWLock(LPCRITICAL_SECTION pcsLock)
  202. {
  203. m_pcs = pcsLock;
  204. m_prwLock = NULL;
  205. if (m_pcs)
  206. EnterCriticalSection(m_pcs);
  207. }
  208. ~CScopeRWLock()
  209. {
  210. if (m_prwLock)
  211. {
  212. if (m_rwMode == RWLOCK_READ_MODE)
  213. m_prwLock->UnlockReadMode();
  214. else if (m_rwMode == RWLOCK_WRITE_MODE)
  215. m_prwLock->UnlockWriteMode();
  216. }
  217. if (m_pcs)
  218. {
  219. LeaveCriticalSection(m_pcs);
  220. }
  221. }
  222. };
  223. #endif // _RWLOCK_H_
  224. #endif // #if __cplusplus