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.

271 lines
4.7 KiB

  1. #ifndef __LOCKS_H__
  2. #define __LOCKS_H__
  3. #include <windows.h>
  4. #include <dothrow.h>
  5. # pragma once
  6. const bool THROW_LOCK = true;
  7. const bool NOTHROW_LOCK = false;
  8. class CriticalSection
  9. {
  10. public:
  11. CriticalSection (bool can_throw , DWORD count = 0 );
  12. // Initialize the CRITICAL_SECTION.
  13. ~CriticalSection (void);
  14. // Implicitly destroy the CRITICAL_SECTION.
  15. bool close (void);
  16. // dummy call
  17. bool acquire (void);
  18. // Acquire lock ownership ( block if necessary).
  19. bool tryacquire (void);
  20. // Conditionally acquire lock ( non blocking ). Returns
  21. // false on failure
  22. bool release (void);
  23. // Release lock
  24. bool acquire_read (void);
  25. bool acquire_write (void);
  26. bool tryacquire_read (void);
  27. bool tryacquire_write (void);
  28. bool valid() const { return initialized_;}
  29. const CRITICAL_SECTION &lock (void) const;
  30. // Return the underlying mutex.
  31. void dump( void ) const ;
  32. private:
  33. CRITICAL_SECTION lock_;
  34. bool initialized_;
  35. bool can_throw_;
  36. void raise_exception();
  37. private:
  38. // = Prevent assignment and initialization.
  39. void operator= (CriticalSection &);
  40. CriticalSection (const CriticalSection &);
  41. };
  42. template <class Lock>
  43. bool SleepAndLock( Lock& lock, int timeout )
  44. {
  45. if (lock.valid())
  46. for (;!lock.locked();)
  47. {
  48. Sleep(timeout);
  49. lock.acquire();
  50. }
  51. return lock.locked();
  52. }
  53. inline
  54. CriticalSection::CriticalSection (bool can_throw,DWORD count):initialized_(false),can_throw_(can_throw)
  55. {
  56. __try
  57. {
  58. if(!count)
  59. InitializeCriticalSection(&lock_);
  60. else
  61. #ifdef _WIN32_WINNT
  62. #if _WIN32_WINNT > 0x0400
  63. InitializeCriticalSectionAndSpinCount(&lock_,count);
  64. #else
  65. InitializeCriticalSection(&lock_);
  66. #endif
  67. #else
  68. InitializeCriticalSection(&lock_);
  69. #endif
  70. initialized_ = true;
  71. }
  72. __except(GetExceptionCode() == STATUS_NO_MEMORY)
  73. {
  74. }
  75. if (initialized_ != true)
  76. raise_exception();
  77. };
  78. inline
  79. CriticalSection::~CriticalSection ()
  80. {
  81. if (initialized_)
  82. DeleteCriticalSection(&lock_);
  83. }
  84. inline void
  85. CriticalSection::raise_exception()
  86. {
  87. if (can_throw_)
  88. throw CX_MemoryException();
  89. };
  90. inline bool
  91. CriticalSection::acquire(void)
  92. {
  93. return acquire_write();
  94. };
  95. inline bool
  96. CriticalSection::acquire_read(void)
  97. {
  98. return acquire_write();
  99. };
  100. #ifndef STATUS_POSSIBLE_DEADLOCK
  101. #define STATUS_POSSIBLE_DEADLOCK (0xC0000194L)
  102. #endif
  103. inline bool
  104. CriticalSection::acquire_write(void)
  105. {
  106. if (initialized_)
  107. {
  108. bool bBreak = false;
  109. __try
  110. {
  111. EnterCriticalSection(&lock_);
  112. return true;
  113. }
  114. __except((GetExceptionCode() == STATUS_NO_MEMORY)?
  115. EXCEPTION_EXECUTE_HANDLER:
  116. ((bBreak = (GetExceptionCode() == STATUS_POSSIBLE_DEADLOCK))?
  117. EXCEPTION_EXECUTE_HANDLER:
  118. EXCEPTION_CONTINUE_SEARCH))
  119. {
  120. if (bBreak)
  121. DebugBreak();
  122. }
  123. }
  124. return false;
  125. };
  126. inline bool
  127. CriticalSection::release(void)
  128. {
  129. if (initialized_)
  130. {
  131. LeaveCriticalSection(&lock_);
  132. return true;
  133. }
  134. return false;
  135. }
  136. inline bool
  137. CriticalSection::tryacquire()
  138. {
  139. return tryacquire_write();
  140. };
  141. inline bool
  142. CriticalSection::tryacquire_read()
  143. {
  144. return tryacquire_write();
  145. };
  146. inline bool
  147. CriticalSection::tryacquire_write()
  148. {
  149. __try
  150. {
  151. #ifdef _WIN32_WINNT
  152. #if _WIN32_WINNT > 0x0400
  153. return TRUE == TryEnterCriticalSection(&lock_);
  154. #else
  155. return false;
  156. #endif
  157. #else
  158. return false;
  159. #endif
  160. }
  161. __except(GetExceptionCode() == STATUS_NO_MEMORY)
  162. {
  163. };
  164. return false;
  165. };
  166. inline bool
  167. CriticalSection::close()
  168. {
  169. return false;
  170. };
  171. #ifdef _WIN32_WINNT
  172. #if _WIN32_WINNT > 0x0400
  173. class ReaderWriter
  174. {
  175. struct RTL_RESOURCE {
  176. struct RTL_RESOURCE_DEBUG;
  177. RTL_CRITICAL_SECTION CriticalSection;
  178. HANDLE SharedSemaphore;
  179. ULONG NumberOfWaitingShared;
  180. HANDLE ExclusiveSemaphore;
  181. ULONG NumberOfWaitingExclusive;
  182. LONG NumberOfActive;
  183. HANDLE ExclusiveOwnerThread;
  184. ULONG Flags; // See RTL_RESOURCE_FLAG_ equates below.
  185. RTL_RESOURCE_DEBUG* DebugInfo;
  186. };
  187. public:
  188. ReaderWriter (bool can_throw);
  189. ~ReaderWriter (void);
  190. bool close (void);
  191. bool acquire (void);
  192. bool tryacquire (void);
  193. bool release (void);
  194. // Release lock
  195. bool acquire_read (void);
  196. bool acquire_write (void);
  197. bool tryacquire_read (void);
  198. bool tryacquire_write (void);
  199. void upgrade();
  200. void downgrade();
  201. bool valid() const { return initialized_;}
  202. const ReaderWriter &lock (void) const;
  203. // Return the underlying mutex.
  204. void dump( void ) const;
  205. private:
  206. RTL_RESOURCE lock_;
  207. bool initialized_;
  208. bool can_throw_;
  209. void raise_exception();
  210. private:
  211. // = Prevent assignment and initialization.
  212. void operator= (ReaderWriter &);
  213. ReaderWriter (const ReaderWriter &);
  214. };
  215. inline void
  216. ReaderWriter::raise_exception()
  217. {
  218. if (can_throw_)
  219. throw CX_MemoryException();
  220. };
  221. #endif
  222. #endif
  223. #endif