/**********************************************************************/ /** Microsoft Windows NT **/ /** Copyright(c) Microsoft Corp., 1993 **/ /**********************************************************************/ /* critsec.hxx Critical Section object FILE HISTORY: JonN 02-Aug-1993 created JonN 10-Aug-1993 CODE REVIEW: DavidHov Added Shared Critical Section support */ #ifndef _CRITSEC_HXX_ #define _CRITSEC_HXX_ class WIN32_CRITICAL; class WIN32_CRITICAL_LOCK; /**********************************************************\ NAME: WIN32_CRITICAL (critsec) SYNOPSIS: Wrapper for NT critical section object. INTERFACE: (public) WIN32_CRITICAL(): constructor ~WIN32_CRITICAL(): destructor Enter(): Enter critical section. Any other thread attempting to enter this critical section will be blocked until this thread calls Leave(). The same thread may enter more than once at a time (but see NOTES below). Leave(): Leave critical section. InitShared(): Initializes pointer to shared critical section. EnterShared(): Enters shared critical section. LeaveShared(): Leaves critical section. PARENT: none NOTES: Note that this is not a BASE child, construction never fails. If compiled DEBUG, the destructor will assert if we destruct without all threads first leaving this critical section. If compiled TRACE, we will get a warning if we Enter() the critical section more than once, or if we Leave() but some process is still in the critical section. This can be OK since a thread is allowed to be in a critical section more than once. The easiest and safest way to use a WIN32_CRITICAL is with a WIN32_CRITICAL_LOCK (see below). You must first call WIN32_CRITICAL_LOCK::InitShared() and have it return TRUE before using EnterShared() or LeaveShared(). CODEWORK: InitShared() should not create the critical section, instead that should be delayed until it is needed. HISTORY: JonN 02-Aug-1993 Created JonN 10-Aug-1993 Added Shared Critical Section support \**********************************************************/ class WIN32_CRITICAL { private: CRITICAL_SECTION _NTCritSection; INT _cUseCount_Debug; static WIN32_CRITICAL * _pstatic_critsec; public: WIN32_CRITICAL(); ~WIN32_CRITICAL(); // These should generally only be called via WIN32_CRITICAL_LOCK VOID Enter(); VOID Leave(); static BOOL InitShared(); static WIN32_CRITICAL & QueryShared() { ASSERT( _pstatic_critsec != NULL ); return (*_pstatic_critsec); } static VOID EnterShared() { QueryShared().Enter(); } static VOID LeaveShared() { QueryShared().Leave(); } } ; /**********************************************************\ NAME: WIN32_CRITICAL_LOCK (critseclock) WIN32_SHARED_LOCK (critsecshared) SYNOPSIS: Holds a critical section while instantiated INTERFACE: (public) WIN32_CRITICAL_ENTRY(): constructor, enters critical section ~WIN32_CRITICAL_ENTRY(): destructor, leaves critical section PARENT: none NOTES: Note that this is not a BASE child, construction never fails. This is the easiest way to use a WIN32_CRITICAL. The critical section is locked as long as the WIN32_CRITICAL_LOCK is in scope. If you declare a WIN32_CRITICAL_LOCK on the stack (and not just a pointer to one), you don't have to worry about forgetting to unlock the critical section as long as you exit the function normally. The WIN32_SHARED_LOCK variant uses the shared critical section built into WIN32_CRITICAL_LOCK. You must first call WIN32_CRITICAL_LOCK::InitShared() and have it return TRUE before instantiating an object of this type. HISTORY: JonN 02-Aug-1993 Created \**********************************************************/ class WIN32_CRITICAL_LOCK { private: WIN32_CRITICAL & _critsec; public: WIN32_CRITICAL_LOCK( WIN32_CRITICAL & critsec ); ~WIN32_CRITICAL_LOCK(); } ; class WIN32_SHARED_LOCK : public WIN32_CRITICAL_LOCK { public: WIN32_SHARED_LOCK() : WIN32_CRITICAL_LOCK( WIN32_CRITICAL::QueryShared() ) {} ~WIN32_SHARED_LOCK() {} } ; #endif // _CRITSEC_HXX_