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.

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