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.

410 lines
11 KiB

  1. ///+---------------------------------------------------------------------------
  2. //
  3. // File: Sem.Hxx
  4. //
  5. // Contents: Semaphore classes
  6. //
  7. // Classes: CMutexSem - Mutex semaphore class
  8. // CShareSem - Multiple Reader, Single Writer class
  9. // CEventSem - Event semaphore
  10. //
  11. // History: 21-Jun-91 AlexT Created.
  12. //
  13. // Notes: No 32-bit implementation exists yet for these classes, it
  14. // will be provided when we have a 32-bit development
  15. // environment. In the meantime, the 16-bit implementations
  16. // provided here can be used to ensure your code not blocking
  17. // while you hold a semaphore.
  18. //
  19. //----------------------------------------------------------------------------
  20. #ifndef __SEM32_HXX__
  21. #define __SEM32_HXX__
  22. #include <windows.h>
  23. #include <except.hxx>
  24. // This is temporary. To be moved to the appropriate error file
  25. enum SEMRESULT
  26. {
  27. SEMSUCCESS = 0,
  28. SEMTIMEOUT,
  29. SEMNOBLOCK,
  30. SEMERROR
  31. };
  32. enum SEMSTATE
  33. {
  34. SEMSHARED,
  35. SEMSHAREDOWNED
  36. };
  37. // infinite timeout when requesting a semaphore
  38. #if !defined INFINITE
  39. #define INFINITE 0xFFFFFFFF
  40. #endif
  41. //+---------------------------------------------------------------------------
  42. //
  43. // Class: CMutexSem (mxs)
  44. //
  45. // Purpose: Mutex Semaphore services
  46. //
  47. // Interface: Init - initializer (two-step)
  48. // Request - acquire semaphore
  49. // Release - release semaphore
  50. //
  51. // History: 14-Jun-91 AlexT Created.
  52. // 30-oct-91 SethuR 32 bit implementation
  53. //
  54. // Notes: This class wraps a mutex semaphore. Mutex semaphores protect
  55. // access to resources by only allowing one client through at a
  56. // time. The client Requests the semaphore before accessing the
  57. // resource and Releases the semaphore when it is done. The
  58. // same client can Request the semaphore multiple times (a nest
  59. // count is maintained).
  60. // The mutex semaphore is a wrapper around a critical section
  61. // which does not support a timeout mechanism. Therefore the
  62. // usage of any value other than INFINITE is discouraged. It
  63. // is provided merely for compatibility.
  64. //
  65. //----------------------------------------------------------------------------
  66. class CMutexSem
  67. {
  68. public:
  69. CMutexSem();
  70. inline BOOL Init();
  71. ~CMutexSem();
  72. SEMRESULT Request(DWORD dwMilliseconds = INFINITE);
  73. void Release();
  74. private:
  75. CRITICAL_SECTION _cs;
  76. };
  77. //+---------------------------------------------------------------------------
  78. //
  79. // Class: CLock (lck)
  80. //
  81. // Purpose: Lock using a Mutex Semaphore
  82. //
  83. // History: 02-Oct-91 BartoszM Created.
  84. //
  85. // Notes: Simple lock object to be created on the stack.
  86. // The constructor acquires the semaphor, the destructor
  87. // (called when lock is going out of scope) releases it.
  88. //
  89. //----------------------------------------------------------------------------
  90. class CLock INHERIT_UNWIND_IF_CAIRO
  91. {
  92. EXPORTDEF DECLARE_UNWIND
  93. public:
  94. CLock ( CMutexSem& mxs );
  95. ~CLock ();
  96. private:
  97. CMutexSem& _mxs;
  98. };
  99. //+---------------------------------------------------------------------------
  100. //
  101. // Class: CEventSem (evs)
  102. //
  103. // Purpose: Event Semaphore services
  104. //
  105. // Interface: Wait - wait for semaphore to be signalled
  106. // Set - set signalled state
  107. // Reset - clear signalled state
  108. // Pulse - set and clear semaphore
  109. //
  110. // History: 21-Jun-91 AlexT Created.
  111. // 27-Feb-92 BartoszM Use exceptions for errors
  112. //
  113. // Notes: Used for communication between consumers and producers.
  114. // Consumer threads block by calling Wait. A producer
  115. // calls Set waking up all the consumers who go ahead
  116. // and consume until there's nothing left. They call
  117. // Reset, release whatever lock protected the resources,
  118. // and call Wait. There has to be a separate lock
  119. // to protect the shared resources.
  120. // Remember: call Reset under lock.
  121. // don't call Wait under lock.
  122. //
  123. //----------------------------------------------------------------------------
  124. class CEventSem
  125. {
  126. public:
  127. inline CEventSem( BOOL fInitState=FALSE, const LPSECURITY_ATTRIBUTES lpsa=NULL );
  128. inline CEventSem( HANDLE hEvent );
  129. inline ~CEventSem();
  130. inline ULONG Wait(DWORD dwMilliseconds = INFINITE,
  131. BOOL fAlertable = FALSE );
  132. inline void Set();
  133. inline void Reset();
  134. inline void Pulse();
  135. inline const HANDLE GetHandle() const { return _hEvent; }
  136. private:
  137. HANDLE _hEvent;
  138. };
  139. //+---------------------------------------------------------------------------
  140. //
  141. // Member: CMutexSem::CMutexSem, public
  142. //
  143. // Synopsis: Mutex semaphore constructor
  144. //
  145. // Effects: Initializes the semaphores data
  146. //
  147. // History: 14-Jun-91 AlexT Created.
  148. //
  149. //----------------------------------------------------------------------------
  150. inline CMutexSem::CMutexSem()
  151. {
  152. Init();
  153. }
  154. inline CMutexSem::Init()
  155. {
  156. InitializeCriticalSection(&_cs);
  157. return TRUE;
  158. };
  159. //+---------------------------------------------------------------------------
  160. //
  161. // Member: CMutexSem::~CMutexSem, public
  162. //
  163. // Synopsis: Mutex semaphore destructor
  164. //
  165. // Effects: Releases semaphore data
  166. //
  167. // History: 14-Jun-91 AlexT Created.
  168. //
  169. //----------------------------------------------------------------------------
  170. inline CMutexSem::~CMutexSem()
  171. {
  172. DeleteCriticalSection(&_cs);
  173. }
  174. //+---------------------------------------------------------------------------
  175. //
  176. // Member: CMutexSem::Request, public
  177. //
  178. // Synopsis: Acquire semaphore
  179. //
  180. // Effects: Asserts correct owner
  181. //
  182. // Arguments: [dwMilliseconds] -- Timeout value
  183. //
  184. // History: 14-Jun-91 AlexT Created.
  185. //
  186. // Notes: Uses GetCurrentTask to establish the semaphore owner, but
  187. // written to work even if GetCurrentTask fails.
  188. //
  189. //----------------------------------------------------------------------------
  190. inline SEMRESULT CMutexSem::Request(DWORD dwMilliseconds)
  191. {
  192. dwMilliseconds;
  193. EnterCriticalSection(&_cs);
  194. return(SEMSUCCESS);
  195. }
  196. //+---------------------------------------------------------------------------
  197. //
  198. // Member: CMutexSem::Release, public
  199. //
  200. // Synopsis: Release semaphore
  201. //
  202. // Effects: Asserts correct owner
  203. //
  204. // History: 14-Jun-91 AlexT Created.
  205. //
  206. // Notes: Uses GetCurrentTask to establish the semaphore owner, but
  207. // written to work even if GetCurrentTask fails.
  208. //
  209. //----------------------------------------------------------------------------
  210. inline void CMutexSem::Release()
  211. {
  212. LeaveCriticalSection(&_cs);
  213. }
  214. //+---------------------------------------------------------------------------
  215. //
  216. // Member: CLock::CLock
  217. //
  218. // Synopsis: Acquire semaphore
  219. //
  220. // History: 02-Oct-91 BartoszM Created.
  221. //
  222. //----------------------------------------------------------------------------
  223. inline CLock::CLock ( CMutexSem& mxs )
  224. : _mxs ( mxs )
  225. {
  226. _mxs.Request ( INFINITE );
  227. END_CONSTRUCTION (CLock);
  228. }
  229. //+---------------------------------------------------------------------------
  230. //
  231. // Member: CLock::~CLock
  232. //
  233. // Synopsis: Release semaphore
  234. //
  235. // History: 02-Oct-91 BartoszM Created.
  236. //
  237. //----------------------------------------------------------------------------
  238. inline CLock::~CLock ()
  239. {
  240. _mxs.Release();
  241. }
  242. //+---------------------------------------------------------------------------
  243. //
  244. // Member: CEventSem::CEventSem
  245. //
  246. // Synopsis: Creates an event
  247. //
  248. // Arguments: [bInitState] -- TRUE: signaled state, FALSE non-signaled
  249. // [lpsa] -- security attributes
  250. //
  251. // History: 27-Feb-92 BartoszM Created
  252. //
  253. //----------------------------------------------------------------------------
  254. inline CEventSem::CEventSem ( BOOL bInitState, const LPSECURITY_ATTRIBUTES lpsa )
  255. {
  256. _hEvent = CreateEvent ( lpsa, TRUE, bInitState, 0 );
  257. if ( _hEvent == 0 )
  258. {
  259. THROW ( CSystemException ( GetLastError() ));
  260. }
  261. }
  262. //+---------------------------------------------------------------------------
  263. //
  264. // Member: CEventSem::CEventSem
  265. //
  266. // Synopsis: Opens an event
  267. //
  268. // Arguments: [hEvent] -- handle of event to open
  269. // [bInitState] -- TRUE: signaled state, FALSE non-signaled
  270. //
  271. // History: 02-Jul-94 DwightKr Created
  272. //
  273. //----------------------------------------------------------------------------
  274. inline CEventSem::CEventSem ( HANDLE hEvent ) : _hEvent( hEvent )
  275. {
  276. }
  277. //+---------------------------------------------------------------------------
  278. //
  279. // Member: CEventSem::~CEventSem
  280. //
  281. // Synopsis: Releases event
  282. //
  283. // History: 27-Feb-92 BartoszM Created
  284. //
  285. //----------------------------------------------------------------------------
  286. inline CEventSem::~CEventSem ()
  287. {
  288. if ( !CloseHandle ( _hEvent ) )
  289. {
  290. THROW ( CSystemException ( GetLastError() ));
  291. }
  292. }
  293. //+---------------------------------------------------------------------------
  294. //
  295. // Member: CEventSem::Set
  296. //
  297. // Synopsis: Set the state to signaled. Wake up waiting threads.
  298. // For manual events the state remains set
  299. // until Reset is called
  300. //
  301. // History: 27-Feb-92 BartoszM Created
  302. //
  303. //----------------------------------------------------------------------------
  304. inline void CEventSem::Set()
  305. {
  306. if ( !SetEvent ( _hEvent ) )
  307. {
  308. THROW ( CSystemException ( GetLastError() ));
  309. }
  310. }
  311. //+---------------------------------------------------------------------------
  312. //
  313. // Member: CEventSem::Reset
  314. //
  315. // Synopsis: Reset the state to non-signaled. Threads will block.
  316. //
  317. // History: 27-Feb-92 BartoszM Created
  318. //
  319. //----------------------------------------------------------------------------
  320. inline void CEventSem::Reset()
  321. {
  322. if ( !ResetEvent ( _hEvent ) )
  323. {
  324. THROW ( CSystemException ( GetLastError() ));
  325. }
  326. }
  327. //+---------------------------------------------------------------------------
  328. //
  329. // Member: CEventSem::Wait
  330. //
  331. // Synopsis: Block until event set
  332. //
  333. // History: 27-Feb-92 BartoszM Created
  334. //
  335. //----------------------------------------------------------------------------
  336. inline ULONG CEventSem::Wait( DWORD msec, BOOL fAlertable )
  337. {
  338. DWORD res = WaitForSingleObjectEx ( _hEvent, msec, fAlertable );
  339. if ( res == (DWORD)0xffffffff )
  340. {
  341. THROW ( CSystemException ( GetLastError() ));
  342. }
  343. return(res);
  344. }
  345. //+---------------------------------------------------------------------------
  346. //
  347. // Member: CEventSem::Pulse
  348. //
  349. // Synopsis: Set the state to signaled. Wake up waiting threads.
  350. //
  351. // History: 27-Feb-92 BartoszM Created
  352. //
  353. //----------------------------------------------------------------------------
  354. inline void CEventSem::Pulse()
  355. {
  356. if ( !PulseEvent ( _hEvent ) )
  357. {
  358. THROW ( CSystemException ( GetLastError() ));
  359. }
  360. }
  361. #endif /* __SEM32_HXX__ */