|
|
///+---------------------------------------------------------------------------
//
// File: Sem.Hxx
//
// Contents: Semaphore classes
//
// Classes: CMutexSem - Mutex semaphore class
// CShareSem - Multiple Reader, Single Writer class
// CEventSem - Event semaphore
//
// History: 21-Jun-91 AlexT Created.
//
// Notes: No 32-bit implementation exists yet for these classes, it
// will be provided when we have a 32-bit development
// environment. In the meantime, the 16-bit implementations
// provided here can be used to ensure your code not blocking
// while you hold a semaphore.
//
//----------------------------------------------------------------------------
#ifndef __SEM32_HXX__
#define __SEM32_HXX__
#include <windows.h>
#include <except.hxx>
// This is temporary. To be moved to the appropriate error file
enum SEMRESULT { SEMSUCCESS = 0, SEMTIMEOUT, SEMNOBLOCK, SEMERROR };
enum SEMSTATE { SEMSHARED, SEMSHAREDOWNED };
// infinite timeout when requesting a semaphore
#if !defined INFINITE
#define INFINITE 0xFFFFFFFF
#endif
//+---------------------------------------------------------------------------
//
// Class: CMutexSem (mxs)
//
// Purpose: Mutex Semaphore services
//
// Interface: Init - initializer (two-step)
// Request - acquire semaphore
// Release - release semaphore
//
// History: 14-Jun-91 AlexT Created.
// 30-oct-91 SethuR 32 bit implementation
//
// Notes: This class wraps a mutex semaphore. Mutex semaphores protect
// access to resources by only allowing one client through at a
// time. The client Requests the semaphore before accessing the
// resource and Releases the semaphore when it is done. The
// same client can Request the semaphore multiple times (a nest
// count is maintained).
// The mutex semaphore is a wrapper around a critical section
// which does not support a timeout mechanism. Therefore the
// usage of any value other than INFINITE is discouraged. It
// is provided merely for compatibility.
//
//----------------------------------------------------------------------------
class CMutexSem { public: CMutexSem(); inline BOOL Init(); ~CMutexSem();
SEMRESULT Request(DWORD dwMilliseconds = INFINITE); void Release();
private: CRITICAL_SECTION _cs; };
//+---------------------------------------------------------------------------
//
// Class: CLock (lck)
//
// Purpose: Lock using a Mutex Semaphore
//
// History: 02-Oct-91 BartoszM Created.
//
// Notes: Simple lock object to be created on the stack.
// The constructor acquires the semaphor, the destructor
// (called when lock is going out of scope) releases it.
//
//----------------------------------------------------------------------------
class CLock INHERIT_UNWIND_IF_CAIRO { EXPORTDEF DECLARE_UNWIND
public: CLock ( CMutexSem& mxs ); ~CLock (); private: CMutexSem& _mxs; };
//+---------------------------------------------------------------------------
//
// Class: CEventSem (evs)
//
// Purpose: Event Semaphore services
//
// Interface: Wait - wait for semaphore to be signalled
// Set - set signalled state
// Reset - clear signalled state
// Pulse - set and clear semaphore
//
// History: 21-Jun-91 AlexT Created.
// 27-Feb-92 BartoszM Use exceptions for errors
//
// Notes: Used for communication between consumers and producers.
// Consumer threads block by calling Wait. A producer
// calls Set waking up all the consumers who go ahead
// and consume until there's nothing left. They call
// Reset, release whatever lock protected the resources,
// and call Wait. There has to be a separate lock
// to protect the shared resources.
// Remember: call Reset under lock.
// don't call Wait under lock.
//
//----------------------------------------------------------------------------
class CEventSem { public: inline CEventSem( BOOL fInitState=FALSE, const LPSECURITY_ATTRIBUTES lpsa=NULL ); inline CEventSem( HANDLE hEvent ); inline ~CEventSem();
inline ULONG Wait(DWORD dwMilliseconds = INFINITE, BOOL fAlertable = FALSE ); inline void Set(); inline void Reset(); inline void Pulse(); inline const HANDLE GetHandle() const { return _hEvent; }
private: HANDLE _hEvent; };
//+---------------------------------------------------------------------------
//
// Member: CMutexSem::CMutexSem, public
//
// Synopsis: Mutex semaphore constructor
//
// Effects: Initializes the semaphores data
//
// History: 14-Jun-91 AlexT Created.
//
//----------------------------------------------------------------------------
inline CMutexSem::CMutexSem() { Init(); }
inline CMutexSem::Init() { InitializeCriticalSection(&_cs); return TRUE; };
//+---------------------------------------------------------------------------
//
// Member: CMutexSem::~CMutexSem, public
//
// Synopsis: Mutex semaphore destructor
//
// Effects: Releases semaphore data
//
// History: 14-Jun-91 AlexT Created.
//
//----------------------------------------------------------------------------
inline CMutexSem::~CMutexSem() { DeleteCriticalSection(&_cs); }
//+---------------------------------------------------------------------------
//
// Member: CMutexSem::Request, public
//
// Synopsis: Acquire semaphore
//
// Effects: Asserts correct owner
//
// Arguments: [dwMilliseconds] -- Timeout value
//
// History: 14-Jun-91 AlexT Created.
//
// Notes: Uses GetCurrentTask to establish the semaphore owner, but
// written to work even if GetCurrentTask fails.
//
//----------------------------------------------------------------------------
inline SEMRESULT CMutexSem::Request(DWORD dwMilliseconds) { dwMilliseconds;
EnterCriticalSection(&_cs); return(SEMSUCCESS); }
//+---------------------------------------------------------------------------
//
// Member: CMutexSem::Release, public
//
// Synopsis: Release semaphore
//
// Effects: Asserts correct owner
//
// History: 14-Jun-91 AlexT Created.
//
// Notes: Uses GetCurrentTask to establish the semaphore owner, but
// written to work even if GetCurrentTask fails.
//
//----------------------------------------------------------------------------
inline void CMutexSem::Release() { LeaveCriticalSection(&_cs); }
//+---------------------------------------------------------------------------
//
// Member: CLock::CLock
//
// Synopsis: Acquire semaphore
//
// History: 02-Oct-91 BartoszM Created.
//
//----------------------------------------------------------------------------
inline CLock::CLock ( CMutexSem& mxs ) : _mxs ( mxs ) { _mxs.Request ( INFINITE ); END_CONSTRUCTION (CLock); }
//+---------------------------------------------------------------------------
//
// Member: CLock::~CLock
//
// Synopsis: Release semaphore
//
// History: 02-Oct-91 BartoszM Created.
//
//----------------------------------------------------------------------------
inline CLock::~CLock () { _mxs.Release(); }
//+---------------------------------------------------------------------------
//
// Member: CEventSem::CEventSem
//
// Synopsis: Creates an event
//
// Arguments: [bInitState] -- TRUE: signaled state, FALSE non-signaled
// [lpsa] -- security attributes
//
// History: 27-Feb-92 BartoszM Created
//
//----------------------------------------------------------------------------
inline CEventSem::CEventSem ( BOOL bInitState, const LPSECURITY_ATTRIBUTES lpsa ) { _hEvent = CreateEvent ( lpsa, TRUE, bInitState, 0 ); if ( _hEvent == 0 ) { THROW ( CSystemException ( GetLastError() )); } }
//+---------------------------------------------------------------------------
//
// Member: CEventSem::CEventSem
//
// Synopsis: Opens an event
//
// Arguments: [hEvent] -- handle of event to open
// [bInitState] -- TRUE: signaled state, FALSE non-signaled
//
// History: 02-Jul-94 DwightKr Created
//
//----------------------------------------------------------------------------
inline CEventSem::CEventSem ( HANDLE hEvent ) : _hEvent( hEvent ) { }
//+---------------------------------------------------------------------------
//
// Member: CEventSem::~CEventSem
//
// Synopsis: Releases event
//
// History: 27-Feb-92 BartoszM Created
//
//----------------------------------------------------------------------------
inline CEventSem::~CEventSem () { if ( !CloseHandle ( _hEvent ) ) { THROW ( CSystemException ( GetLastError() )); } }
//+---------------------------------------------------------------------------
//
// Member: CEventSem::Set
//
// Synopsis: Set the state to signaled. Wake up waiting threads.
// For manual events the state remains set
// until Reset is called
//
// History: 27-Feb-92 BartoszM Created
//
//----------------------------------------------------------------------------
inline void CEventSem::Set() { if ( !SetEvent ( _hEvent ) ) { THROW ( CSystemException ( GetLastError() )); } }
//+---------------------------------------------------------------------------
//
// Member: CEventSem::Reset
//
// Synopsis: Reset the state to non-signaled. Threads will block.
//
// History: 27-Feb-92 BartoszM Created
//
//----------------------------------------------------------------------------
inline void CEventSem::Reset() { if ( !ResetEvent ( _hEvent ) ) { THROW ( CSystemException ( GetLastError() )); } }
//+---------------------------------------------------------------------------
//
// Member: CEventSem::Wait
//
// Synopsis: Block until event set
//
// History: 27-Feb-92 BartoszM Created
//
//----------------------------------------------------------------------------
inline ULONG CEventSem::Wait( DWORD msec, BOOL fAlertable ) { DWORD res = WaitForSingleObjectEx ( _hEvent, msec, fAlertable );
if ( res == (DWORD)0xffffffff ) { THROW ( CSystemException ( GetLastError() )); } return(res); }
//+---------------------------------------------------------------------------
//
// Member: CEventSem::Pulse
//
// Synopsis: Set the state to signaled. Wake up waiting threads.
//
// History: 27-Feb-92 BartoszM Created
//
//----------------------------------------------------------------------------
inline void CEventSem::Pulse() { if ( !PulseEvent ( _hEvent ) ) { THROW ( CSystemException ( GetLastError() )); } }
#endif /* __SEM32_HXX__ */
|