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.

338 lines
6.9 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. lock.h
  5. Abstract:
  6. Portable synronization primitive class ( between Win9x and NT)
  7. Win9x does not
  8. Author:
  9. Vlad Sadovsky (vlads) 02-Jan-1997
  10. Environment:
  11. User Mode - Win32
  12. Revision History:
  13. 02-Jan-1997 VladS created
  14. --*/
  15. # ifndef _LOCK_H_
  16. # define _LOCK_H_
  17. /************************************************************
  18. * Include Headers
  19. ************************************************************/
  20. # ifdef _cplusplus
  21. extern "C" {
  22. # endif // _cplusplus
  23. # ifdef _cplusplus
  24. }; // extern "C"
  25. # endif // _cplusplus
  26. #ifndef DBG_REQUIRE
  27. #define DBG_REQUIRE REQUIRE
  28. #endif
  29. #ifndef RTL_RESOURCE
  30. //
  31. // Shared resource function definitions. It is declared in NTRTL , but not in windows SDK header files
  32. //
  33. typedef struct _RTL_RESOURCE {
  34. //
  35. // The following field controls entering and exiting the critical
  36. // section for the resource
  37. //
  38. RTL_CRITICAL_SECTION CriticalSection;
  39. //
  40. // The following four fields indicate the number of both shared or
  41. // exclusive waiters
  42. //
  43. HANDLE SharedSemaphore;
  44. ULONG NumberOfWaitingShared;
  45. HANDLE ExclusiveSemaphore;
  46. ULONG NumberOfWaitingExclusive;
  47. //
  48. // The following indicates the current state of the resource
  49. //
  50. // <0 the resource is acquired for exclusive access with the
  51. // absolute value indicating the number of recursive accesses
  52. // to the resource
  53. //
  54. // 0 the resource is available
  55. //
  56. // >0 the resource is acquired for shared access with the
  57. // value indicating the number of shared accesses to the resource
  58. //
  59. LONG NumberOfActive;
  60. HANDLE ExclusiveOwnerThread;
  61. ULONG Flags; // See RTL_RESOURCE_FLAG_ equates below.
  62. PVOID DebugInfo;
  63. } RTL_RESOURCE, *PRTL_RESOURCE;
  64. #define RTL_RESOURCE_FLAG_LONG_TERM ((ULONG) 0x00000001)
  65. #endif // RTL_RESOURCE
  66. /************************************************************
  67. * Type Definitions
  68. ************************************************************/
  69. # ifdef _cplusplus
  70. extern "C" {
  71. # endif // _cplusplus
  72. BOOL
  73. InitializeResource(
  74. IN PRTL_RESOURCE Resource
  75. );
  76. BOOL
  77. AcquireResourceShared(
  78. IN PRTL_RESOURCE Resource,
  79. IN BOOL Wait
  80. );
  81. BOOL
  82. AcquireResourceExclusive(
  83. IN PRTL_RESOURCE Resource,
  84. IN BOOL Wait
  85. );
  86. BOOL
  87. ReleaseResource(
  88. IN PRTL_RESOURCE Resource
  89. );
  90. BOOL
  91. ConvertSharedToExclusive(
  92. IN PRTL_RESOURCE Resource
  93. );
  94. BOOL
  95. ConvertExclusiveToShared(
  96. IN PRTL_RESOURCE Resource
  97. );
  98. VOID
  99. DeleteResource (
  100. IN PRTL_RESOURCE Resource
  101. );
  102. # ifdef _cplusplus
  103. }; // extern "C"
  104. # endif // _cplusplus
  105. ///////////////////////////////////////////////////////////////////////
  106. //
  107. // Simple RTL_RESOURCE Wrapper class
  108. //
  109. //////////////////////////////////////////////////////////////////////
  110. enum SYNC_LOCK_TYPE
  111. {
  112. SYNC_LOCK_READ = 0, // Take the lock for read only
  113. SYNC_LOCK_WRITE // Take the lock for write
  114. };
  115. enum SYNC_CONV_TYPE
  116. {
  117. SYNC_CONV_READ = 0, // Convert the lock from write to read
  118. SYNC_CONV_WRITE // Convert the lock from read to write
  119. };
  120. class SYNC_RESOURCE
  121. {
  122. friend class TAKE_SYNC_RESOURCE;
  123. public:
  124. SYNC_RESOURCE()
  125. { InitializeResource( &_rtlres ); }
  126. ~SYNC_RESOURCE()
  127. { DeleteResource( &_rtlres ); }
  128. void Lock( enum SYNC_LOCK_TYPE type )
  129. { if ( type == SYNC_LOCK_READ ) {
  130. DBG_REQUIRE( AcquireResourceShared( &_rtlres, TRUE ) );
  131. } else {
  132. DBG_REQUIRE( AcquireResourceExclusive( &_rtlres, TRUE ));
  133. }
  134. }
  135. void Convert( enum SYNC_CONV_TYPE type )
  136. { if ( type == SYNC_CONV_READ ) {
  137. DBG_REQUIRE( ConvertExclusiveToShared( &_rtlres ));
  138. } else {
  139. DBG_REQUIRE( ConvertSharedToExclusive( &_rtlres ));
  140. }
  141. }
  142. void Unlock( VOID )
  143. { DBG_REQUIRE( ReleaseResource( &_rtlres )); }
  144. private:
  145. RTL_RESOURCE _rtlres;
  146. };
  147. ///////////////////////////////////////////////////////////////////
  148. // Instantiate one of these classes in a block of code
  149. // when you want that block of code to be protected
  150. // against re-entrancy.
  151. // The Take() and Release() functions should rarely be necessary,
  152. // and must be used in matched pairs with Release() called first.
  153. ///////////////////////////////////////////////////////////////////
  154. class TAKE_SYNC_RESOURCE
  155. {
  156. private:
  157. SYNC_RESOURCE& _syncres;
  158. public:
  159. void Take(void) { _syncres.Lock(SYNC_LOCK_WRITE); }
  160. void Release(void) { _syncres.Unlock(); }
  161. TAKE_SYNC_RESOURCE(SYNC_RESOURCE& syncres) : _syncres(syncres) { Take(); }
  162. ~TAKE_SYNC_RESOURCE() { Release(); }
  163. };
  164. //
  165. // Auto critical section clss
  166. //
  167. class CRIT_SECT
  168. {
  169. public:
  170. BOOL Lock()
  171. {
  172. if (m_bInitialized) {
  173. EnterCriticalSection(&m_sec);
  174. return TRUE;
  175. }
  176. return FALSE;
  177. }
  178. void Unlock()
  179. {
  180. LeaveCriticalSection(&m_sec);
  181. }
  182. CRIT_SECT()
  183. {
  184. m_bInitialized = FALSE;
  185. __try {
  186. #ifdef UNICODE
  187. if(InitializeCriticalSectionAndSpinCount(&m_sec, MINLONG)) {
  188. #else
  189. InitializeCriticalSection(&m_sec); {
  190. #endif
  191. m_bInitialized = TRUE;
  192. }
  193. }
  194. __except (EXCEPTION_EXECUTE_HANDLER) {
  195. }
  196. }
  197. ~CRIT_SECT()
  198. {
  199. if (m_bInitialized) {
  200. DeleteCriticalSection(&m_sec);
  201. m_bInitialized = FALSE;
  202. }
  203. }
  204. BOOL IsInitialized() {return m_bInitialized;}
  205. CRITICAL_SECTION m_sec;
  206. BOOL m_bInitialized;
  207. };
  208. class TAKE_CRIT_SECT
  209. {
  210. private:
  211. CRIT_SECT& _syncres;
  212. BOOL m_bLocked;
  213. public:
  214. inline TAKE_CRIT_SECT(CRIT_SECT& syncres) : _syncres(syncres), m_bLocked(FALSE) { m_bLocked = _syncres.Lock(); }
  215. inline ~TAKE_CRIT_SECT() { if (m_bLocked) {_syncres.Unlock(); m_bLocked = FALSE;}; }
  216. };
  217. //
  218. // Auto mutex class
  219. //
  220. class MUTEX_OBJ
  221. {
  222. private:
  223. HANDLE m_hMutex;
  224. public:
  225. BOOL inline IsValid(VOID) {return (m_hMutex!=INVALID_HANDLE_VALUE);}
  226. void Lock() { ::WaitForSingleObject(m_hMutex, INFINITE); }
  227. void Unlock() { ::ReleaseMutex(m_hMutex); }
  228. MUTEX_OBJ(LPCTSTR pszName) {
  229. m_hMutex = ::CreateMutex(NULL,
  230. FALSE,
  231. pszName
  232. );
  233. }
  234. ~MUTEX_OBJ() {CloseHandle(m_hMutex);m_hMutex = INVALID_HANDLE_VALUE;}
  235. };
  236. class TAKE_MUTEX
  237. {
  238. private:
  239. HANDLE const m_hMutex;
  240. public:
  241. void Take(void) { ::WaitForSingleObject(m_hMutex, INFINITE); }
  242. void Release(void) { ::ReleaseMutex(m_hMutex); }
  243. TAKE_MUTEX(HANDLE hMutex) : m_hMutex(hMutex) { Take(); }
  244. ~TAKE_MUTEX() { Release(); }
  245. };
  246. class TAKE_MUTEX_OBJ
  247. {
  248. private:
  249. MUTEX_OBJ& _syncres;
  250. public:
  251. inline TAKE_MUTEX_OBJ(MUTEX_OBJ& syncres) : _syncres(syncres) { _syncres.Lock(); }
  252. inline ~TAKE_MUTEX_OBJ() { _syncres.Unlock(); }
  253. };
  254. # endif // _LOCK_H_