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.

661 lines
19 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. extern "C"
  23. {
  24. #include <windows.h>
  25. };
  26. #include <except.hxx>
  27. // This is temporary. To be moved to the appropriate error file
  28. // BUGBUG: use NT error codes. Conversion is expensive! (BartoszM)
  29. enum SEMRESULT
  30. {
  31. SEMSUCCESS = 0,
  32. SEMTIMEOUT,
  33. SEMNOBLOCK,
  34. SEMERROR
  35. };
  36. enum SEMSTATE
  37. {
  38. SEMSHARED,
  39. SEMSHAREDOWNED
  40. };
  41. // BUGBUG: inlcude winbase.h or some such
  42. // infinite timeout when requesting a semaphore
  43. #if !defined INFINITE
  44. #define INFINITE 0xFFFFFFFF
  45. #endif
  46. //+---------------------------------------------------------------------------
  47. //
  48. // Class: CMutexSem (mxs)
  49. //
  50. // Purpose: Mutex Semaphore services
  51. //
  52. // Interface: Init - initializer (two-step)
  53. // Request - acquire semaphore
  54. // Release - release semaphore
  55. //
  56. // History: 14-Jun-91 AlexT Created.
  57. // 30-oct-91 SethuR 32 bit implementation
  58. //
  59. // Notes: This class wraps a mutex semaphore. Mutex semaphores protect
  60. // access to resources by only allowing one client through at a
  61. // time. The client Requests the semaphore before accessing the
  62. // resource and Releases the semaphore when it is done. The
  63. // same client can Request the semaphore multiple times (a nest
  64. // count is maintained).
  65. // The mutex semaphore is a wrapper around a critical section
  66. // which does not support a timeout mechanism. Therefore the
  67. // usage of any value other than INFINITE is discouraged. It
  68. // is provided merely for compatibility.
  69. //
  70. //----------------------------------------------------------------------------
  71. class CMutexSem
  72. {
  73. public:
  74. CMutexSem();
  75. inline BOOL Init();
  76. ~CMutexSem();
  77. SEMRESULT Request(DWORD dwMilliseconds = INFINITE);
  78. void Release();
  79. private:
  80. CRITICAL_SECTION _cs;
  81. };
  82. //+---------------------------------------------------------------------------
  83. //
  84. // Class: CLock (lck)
  85. //
  86. // Purpose: Lock using a Mutex Semaphore
  87. //
  88. // History: 02-Oct-91 BartoszM Created.
  89. //
  90. // Notes: Simple lock object to be created on the stack.
  91. // The constructor acquires the semaphor, the destructor
  92. // (called when lock is going out of scope) releases it.
  93. //
  94. //----------------------------------------------------------------------------
  95. class CLock INHERIT_UNWIND_IF_CAIRO
  96. {
  97. EXPORTDEF DECLARE_UNWIND
  98. public:
  99. CLock ( CMutexSem& mxs );
  100. ~CLock ();
  101. private:
  102. CMutexSem& _mxs;
  103. };
  104. //+---------------------------------------------------------------------------
  105. //
  106. // Class: CEventSem (evs)
  107. //
  108. // Purpose: Event Semaphore services
  109. //
  110. // Interface: Wait - wait for semaphore to be signalled
  111. // Set - set signalled state
  112. // Reset - clear signalled state
  113. // Pulse - set and clear semaphore
  114. //
  115. // History: 21-Jun-91 AlexT Created.
  116. // 27-Feb-92 BartoszM Use exceptions for errors
  117. //
  118. // Notes: Used for communication between consumers and producers.
  119. // Consumer threads block by calling Wait. A producer
  120. // calls Set waking up all the consumers who go ahead
  121. // and consume until there's nothing left. They call
  122. // Reset, release whatever lock protected the resources,
  123. // and call Wait. There has to be a separate lock
  124. // to protect the shared resources.
  125. // Remember: call Reset under lock.
  126. // don't call Wait under lock.
  127. //
  128. //----------------------------------------------------------------------------
  129. class CEventSem
  130. {
  131. public:
  132. inline CEventSem( BOOL fInitState=FALSE, const LPSECURITY_ATTRIBUTES lpsa=NULL );
  133. inline CEventSem( HANDLE hEvent );
  134. inline ~CEventSem();
  135. inline ULONG Wait(DWORD dwMilliseconds = INFINITE,
  136. BOOL fAlertable = FALSE );
  137. inline void Set();
  138. inline void Reset();
  139. inline void Pulse();
  140. inline const HANDLE GetHandle() const { return _hEvent; }
  141. private:
  142. HANDLE _hEvent;
  143. };
  144. #if 0
  145. // BUGBUG: This class is superceded by CResource, in resource.hxx and
  146. // resource.cxx. It should be deleted by July 21, 1993
  147. // WadeR, July 8, 1883
  148. //+---------------------------------------------------------------------------
  149. //
  150. // Class: CShareSem (shs)
  151. //
  152. // Purpose: Shared Semaphore services
  153. //
  154. // Interface: RequestExclusive - acquire exclusive ownership
  155. // RequestShared - acquire shared access
  156. // RequestSharedOwned - acquire ownership, allowing shared access
  157. // Release - release semaphore
  158. // Upgrade - upgrade from SharedOwned to Exclusive
  159. // Downgrade - downgrade to SharedOwned or Shared
  160. //
  161. // History: 21-Jun-91 AlexT Created.
  162. //
  163. // Notes: Shared semaphores allow multiple readers/single writers
  164. // access to resources. Readers bracket their use of a resource
  165. // with calls to RequestShared and Release. Writers bracket
  166. // their use of a resource with calls to RequestExclusive and
  167. // Release.
  168. //
  169. // RequestSharedOwned gives a client ownership of the semaphore
  170. // but still allows other Readers to share the semaphore. At
  171. // some later point, the owning client can call Upgrade to get
  172. // Exclusive access to the semaphore. This is useful when a
  173. // client needs to examine a data structure before modifying it,
  174. // as it allows other clients to continue viewing the data
  175. // until the owning client actually needs to modify it.
  176. //
  177. // Downgrade allows a client to release ownership of a semaphore
  178. // without releasing access to it.
  179. //
  180. // For now, this just uses a mutex semaphore.
  181. //
  182. // BUGBUG -- Ownership related methods needs to be implemented.
  183. //
  184. //----------------------------------------------------------------------------
  185. class CShareSem
  186. {
  187. public:
  188. CShareSem();
  189. BOOL Init();
  190. ~CShareSem();
  191. SEMRESULT RequestExclusive(DWORD dwMilliseconds);
  192. SEMRESULT RequestShared(DWORD dwMilliseconds);
  193. SEMRESULT RequestSharedOwned(DWORD dwMilliseconds);
  194. void Release();
  195. SEMRESULT Upgrade(DWORD dwMilliseconds);
  196. SEMRESULT Downgrade(SEMSTATE fl);
  197. private:
  198. // Ownership related methods....
  199. BOOL ClaimOwnership();
  200. BOOL ReleaseOwnership();
  201. // Private methods to facilitate code sharing
  202. void EnableReaders();
  203. CMutexSem _cmtx;
  204. CEventSem _evsReaders;
  205. CEventSem _evsWriters;
  206. BOOL _fWrite;
  207. ULONG _cReaders;
  208. ULONG _cWaitingReaders;
  209. ULONG _cWaitingWriters;
  210. };
  211. //+---------------------------------------------------------------------------
  212. //
  213. // Class: CShareSemObject
  214. //
  215. // Purpose: The Semaphore Object -- the constructor accquires the
  216. // semaphore and the destructor releases it.
  217. //
  218. // Interface:
  219. //
  220. // History: 05-July-91 SethuR Created.
  221. //
  222. //
  223. //----------------------------------------------------------------------------
  224. class CShareSemObject INHERIT_UNWIND_IF_CAIRO
  225. {
  226. DECLARE_UNWIND
  227. public:
  228. inline CShareSemObject(CShareSem& shs);
  229. inline ~CShareSemObject();
  230. inline void RequestExclusive(DWORD dw);
  231. inline void RequestShared(DWORD dw);
  232. inline void RequestSharedOwned(DWORD dw);
  233. inline SEMRESULT Upgrade(DWORD dw);
  234. inline void Downgrade(SEMSTATE ss);
  235. private:
  236. CShareSem* _pshs;
  237. BOOL _fAccquired;
  238. };
  239. //+---------------------------------------------------------------------------
  240. //
  241. // Member: CShareSemObject::CShareSemObject, public
  242. //
  243. // Synopsis: Constructor
  244. //
  245. // Arguments: [shs] -- shared semaphore
  246. //
  247. // History: 29-Aug-91 SethuR Created.
  248. //
  249. //----------------------------------------------------------------------------
  250. inline CShareSemObject::CShareSemObject(CShareSem& shs)
  251. {
  252. _pshs = &shs;
  253. _fAccquired = FALSE;
  254. END_CONSTRUCTION(CShareSemObject)
  255. }
  256. //+---------------------------------------------------------------------------
  257. //
  258. // Member: CShareSemObject::RequestExclusive, public
  259. //
  260. // Synopsis: Get Exclusive acess
  261. //
  262. // Arguments: [dwMilliseconds] -- Timeout value
  263. //
  264. // History: 29-Aug-91 SethuR Created.
  265. //
  266. //----------------------------------------------------------------------------
  267. inline void CShareSemObject::RequestExclusive(DWORD dw)
  268. {
  269. if (_pshs->RequestExclusive(dw) == SEMSUCCESS)
  270. _fAccquired = TRUE;
  271. else
  272. THROW (CException(Win4ErrSemaphoreInvalid));
  273. }
  274. //+---------------------------------------------------------------------------
  275. //
  276. // Member: CShareSemObject::RequestShared, public
  277. //
  278. // Synopsis: Get allow shared access
  279. //
  280. // Arguments: [dwMilliseconds] -- Timeout value
  281. //
  282. // History: 29-Aug-91 SethuR Created.
  283. //
  284. //----------------------------------------------------------------------------
  285. inline void CShareSemObject::RequestShared(DWORD dw)
  286. {
  287. if (_pshs->RequestSharedOwned(dw) == SEMSUCCESS)
  288. _fAccquired = TRUE;
  289. else
  290. THROW (CException(Win4ErrSemaphoreInvalid));
  291. }
  292. //+---------------------------------------------------------------------------
  293. //
  294. // Member: CShareSemObject::RequestSharedOwned, public
  295. //
  296. // Synopsis: Get ownership but allow shared access
  297. //
  298. // Arguments: [dwMilliseconds] -- Timeout value
  299. //
  300. // History: 29-Aug-91 SethuR Created.
  301. //
  302. //----------------------------------------------------------------------------
  303. inline void CShareSemObject::RequestSharedOwned(DWORD dw)
  304. {
  305. if (_pshs->RequestSharedOwned(dw) == SEMSUCCESS)
  306. _fAccquired = TRUE;
  307. else
  308. THROW (CException(Win4ErrSemaphoreInvalid));
  309. }
  310. //+---------------------------------------------------------------------------
  311. //
  312. // Member: CShareSemObject::~CShareSemObject, public
  313. //
  314. // Synopsis: Destructor -- Releases the semaphore if accquired
  315. //
  316. // History: 27-Aug-91 AlexT Created.
  317. //
  318. //----------------------------------------------------------------------------
  319. inline CShareSemObject::~CShareSemObject()
  320. {
  321. if (_fAccquired)
  322. _pshs->Release();
  323. }
  324. //+---------------------------------------------------------------------------
  325. //
  326. // Member: CShareSemObject::Upgrade, public
  327. //
  328. // Synopsis: Get exclusive access (must have ownership already)
  329. //
  330. // Arguments: [dwMilliseconds] -- Timeout value
  331. //
  332. // History: 21-Jun-91 AlexT Created.
  333. //
  334. //----------------------------------------------------------------------------
  335. inline SEMRESULT CShareSemObject::Upgrade(DWORD dw)
  336. {
  337. if (_fAccquired)
  338. return _pshs->Upgrade(dw);
  339. THROW (CException(Win4ErrSemaphoreInvalid));
  340. return SEMTIMEOUT; // BUGBUG -- This is to satisfy compiler limitation
  341. }
  342. //+---------------------------------------------------------------------------
  343. //
  344. // Member: CShareSemObject::Downgrade, public
  345. //
  346. // Synopsis: Release exclusive access (but keep access)
  347. //
  348. // Arguments: [fl] -- SEMSHARED or SEMSHAREDOWNED
  349. //
  350. // History: 21-Jun-91 AlexT Created.
  351. //
  352. //----------------------------------------------------------------------------
  353. inline void CShareSemObject::Downgrade(SEMSTATE ss)
  354. {
  355. if (_fAccquired)
  356. _pshs->Downgrade(ss);
  357. else
  358. THROW (CException(Win4ErrSemaphoreInvalid));
  359. return;
  360. }
  361. #endif // 0 BUGBUG
  362. //+---------------------------------------------------------------------------
  363. //
  364. // Member: CMutexSem::CMutexSem, public
  365. //
  366. // Synopsis: Mutex semaphore constructor
  367. //
  368. // Effects: Initializes the semaphores data
  369. //
  370. // History: 14-Jun-91 AlexT Created.
  371. //
  372. //----------------------------------------------------------------------------
  373. inline CMutexSem::CMutexSem()
  374. {
  375. Init();
  376. }
  377. inline CMutexSem::Init()
  378. {
  379. InitializeCriticalSection(&_cs);
  380. return TRUE;
  381. };
  382. //+---------------------------------------------------------------------------
  383. //
  384. // Member: CMutexSem::~CMutexSem, public
  385. //
  386. // Synopsis: Mutex semaphore destructor
  387. //
  388. // Effects: Releases semaphore data
  389. //
  390. // History: 14-Jun-91 AlexT Created.
  391. //
  392. //----------------------------------------------------------------------------
  393. inline CMutexSem::~CMutexSem()
  394. {
  395. DeleteCriticalSection(&_cs);
  396. }
  397. //+---------------------------------------------------------------------------
  398. //
  399. // Member: CMutexSem::Request, public
  400. //
  401. // Synopsis: Acquire semaphore
  402. //
  403. // Effects: Asserts correct owner
  404. //
  405. // Arguments: [dwMilliseconds] -- Timeout value
  406. //
  407. // History: 14-Jun-91 AlexT Created.
  408. //
  409. // Notes: Uses GetCurrentTask to establish the semaphore owner, but
  410. // written to work even if GetCurrentTask fails.
  411. //
  412. //----------------------------------------------------------------------------
  413. inline SEMRESULT CMutexSem::Request(DWORD dwMilliseconds)
  414. {
  415. dwMilliseconds;
  416. EnterCriticalSection(&_cs);
  417. return(SEMSUCCESS);
  418. }
  419. //+---------------------------------------------------------------------------
  420. //
  421. // Member: CMutexSem::Release, public
  422. //
  423. // Synopsis: Release semaphore
  424. //
  425. // Effects: Asserts correct owner
  426. //
  427. // History: 14-Jun-91 AlexT Created.
  428. //
  429. // Notes: Uses GetCurrentTask to establish the semaphore owner, but
  430. // written to work even if GetCurrentTask fails.
  431. //
  432. //----------------------------------------------------------------------------
  433. inline void CMutexSem::Release()
  434. {
  435. LeaveCriticalSection(&_cs);
  436. }
  437. //+---------------------------------------------------------------------------
  438. //
  439. // Member: CLock::CLock
  440. //
  441. // Synopsis: Acquire semaphore
  442. //
  443. // History: 02-Oct-91 BartoszM Created.
  444. //
  445. //----------------------------------------------------------------------------
  446. inline CLock::CLock ( CMutexSem& mxs )
  447. : _mxs ( mxs )
  448. {
  449. _mxs.Request ( INFINITE );
  450. END_CONSTRUCTION (CLock);
  451. }
  452. //+---------------------------------------------------------------------------
  453. //
  454. // Member: CLock::~CLock
  455. //
  456. // Synopsis: Release semaphore
  457. //
  458. // History: 02-Oct-91 BartoszM Created.
  459. //
  460. //----------------------------------------------------------------------------
  461. inline CLock::~CLock ()
  462. {
  463. _mxs.Release();
  464. }
  465. //+---------------------------------------------------------------------------
  466. //
  467. // Member: CEventSem::CEventSem
  468. //
  469. // Synopsis: Creates an event
  470. //
  471. // Arguments: [bInitState] -- TRUE: signaled state, FALSE non-signaled
  472. // [lpsa] -- security attributes
  473. //
  474. // History: 27-Feb-92 BartoszM Created
  475. //
  476. //----------------------------------------------------------------------------
  477. inline CEventSem::CEventSem ( BOOL bInitState, const LPSECURITY_ATTRIBUTES lpsa )
  478. {
  479. _hEvent = CreateEvent ( lpsa, TRUE, bInitState, 0 );
  480. if ( _hEvent == 0 )
  481. {
  482. THROW ( CSystemException ( GetLastError() ));
  483. }
  484. }
  485. //+---------------------------------------------------------------------------
  486. //
  487. // Member: CEventSem::CEventSem
  488. //
  489. // Synopsis: Opens an event
  490. //
  491. // Arguments: [hEvent] -- handle of event to open
  492. // [bInitState] -- TRUE: signaled state, FALSE non-signaled
  493. //
  494. // History: 02-Jul-94 DwightKr Created
  495. //
  496. //----------------------------------------------------------------------------
  497. inline CEventSem::CEventSem ( HANDLE hEvent ) : _hEvent( hEvent )
  498. {
  499. }
  500. //+---------------------------------------------------------------------------
  501. //
  502. // Member: CEventSem::~CEventSem
  503. //
  504. // Synopsis: Releases event
  505. //
  506. // History: 27-Feb-92 BartoszM Created
  507. //
  508. //----------------------------------------------------------------------------
  509. inline CEventSem::~CEventSem ()
  510. {
  511. if ( !CloseHandle ( _hEvent ) )
  512. {
  513. THROW ( CSystemException ( GetLastError() ));
  514. }
  515. }
  516. //+---------------------------------------------------------------------------
  517. //
  518. // Member: CEventSem::Set
  519. //
  520. // Synopsis: Set the state to signaled. Wake up waiting threads.
  521. // For manual events the state remains set
  522. // until Reset is called
  523. //
  524. // History: 27-Feb-92 BartoszM Created
  525. //
  526. //----------------------------------------------------------------------------
  527. inline void CEventSem::Set()
  528. {
  529. if ( !SetEvent ( _hEvent ) )
  530. {
  531. THROW ( CSystemException ( GetLastError() ));
  532. }
  533. }
  534. //+---------------------------------------------------------------------------
  535. //
  536. // Member: CEventSem::Reset
  537. //
  538. // Synopsis: Reset the state to non-signaled. Threads will block.
  539. //
  540. // History: 27-Feb-92 BartoszM Created
  541. //
  542. //----------------------------------------------------------------------------
  543. inline void CEventSem::Reset()
  544. {
  545. if ( !ResetEvent ( _hEvent ) )
  546. {
  547. THROW ( CSystemException ( GetLastError() ));
  548. }
  549. }
  550. //+---------------------------------------------------------------------------
  551. //
  552. // Member: CEventSem::Wait
  553. //
  554. // Synopsis: Block until event set
  555. //
  556. // History: 27-Feb-92 BartoszM Created
  557. //
  558. //----------------------------------------------------------------------------
  559. inline ULONG CEventSem::Wait( DWORD msec, BOOL fAlertable )
  560. {
  561. DWORD res = WaitForSingleObjectEx ( _hEvent, msec, fAlertable );
  562. if ( res < 0 )
  563. {
  564. THROW ( CSystemException ( GetLastError() ));
  565. }
  566. return(res);
  567. }
  568. //+---------------------------------------------------------------------------
  569. //
  570. // Member: CEventSem::Pulse
  571. //
  572. // Synopsis: Set the state to signaled. Wake up waiting threads.
  573. //
  574. // History: 27-Feb-92 BartoszM Created
  575. //
  576. //----------------------------------------------------------------------------
  577. inline void CEventSem::Pulse()
  578. {
  579. if ( !PulseEvent ( _hEvent ) )
  580. {
  581. THROW ( CSystemException ( GetLastError() ));
  582. }
  583. }
  584. #endif /* __SEM32_HXX__ */