📄 utsem.h
字号:
/* ----------------------------------------------------------------------------
Microsoft D.T.C (Distributed Transaction Coordinator)
(c) 1995 Microsoft Corporation. All Rights Reserved
@doc
@module UTSem.H |
SYNCHRO - C++ class to provide synchronization object encapsulation
This implementation of the SYNCHRO class provides multi-read XOR single-write
(a.k.a. shared vs. exclusive) lock capabilities, with protection against
writer starvation. Code origianly borrowed from
(c) 1994 by Daniel S. Glasser and then modified for our needs.
@devnote None
@rev 3 | 1st-Aug-1996 | GaganC | Added the spin lock code and class
@rev 2 | 31-May-1996 | GaganC | Removed the special code for x86
@rev 1 | 18th Jan, 96 | GaganC | Special cased UTGuard for X86
@rev 0 | 4th Feb,95 | GaganC | Created
---------------------------------------------------------------------------- */
#ifndef __UTSEM_H__
#define __UTSEM_H__
// -------------------------------------------------------------
// INCLUDES
// -------------------------------------------------------------
#include "UTAssert.H"
// -------------------------------------------------------------
// CONSTANTS AND TYPES
// -------------------------------------------------------------
typedef enum {SLC_WRITE, SLC_READWRITE, SLC_READWRITEPROMOTE}
SYNCH_LOCK_CAPS;
typedef enum {SLT_READ, SLT_READPROMOTE, SLT_WRITE}
SYNCH_LOCK_TYPE;
const int NUM_SYNCH_LOCK_TYPES = SLT_WRITE + 1;
// -------------------------------------------------------------
// FORWARDS
// -------------------------------------------------------------
class CSemExclusive;
class CSemExclusiveSL;
class UTGuard;
class UTSemReadWrite;
class UTSemCheapReadWrite;
// -------------------------------------------------------------
// GLOBAL HELPER FUNCTIONS
// -------------------------------------------------------------
/* ----------------------------------------------------------------------------
@func Description:<nl>
Guarantees isolated increments of *pl.<nl><nl>
Usage:<nl>
Use instead of InterlockedIncrement for Win16/Win32 portability.<nl><nl>
@rev 0 | 3/21/95 | Rcraig | Created.
---------------------------------------------------------------------------- */
inline LONG SafeIncrement ( LPLONG pl )
{
return (InterlockedIncrement (pl));
} // SafeIncrement
/* ----------------------------------------------------------------------------
@func Description:<nl>
Win16/Win32 abstraction wrapper:
Guarantees isolated decrements of *pl.<nl><nl>
Usage:<nl>
Use instead of InterlockedDecrement for Win16/Win32 portability.<nl><nl>
@rev 0 | 3/21/95 | Rcraig | Created.
---------------------------------------------------------------------------- */
inline LONG SafeDecrement ( LPLONG pl )
{
return (InterlockedDecrement (pl));
} // SafeDecrement
/* ----------------------------------------------------------------------------
@class UTGuard
This object represents a guard that can be acquired or released. The
advantage with useing this instead of a critical section is that this
is non blocking. If AcquireGuard fails, it will return false and will not
block.
@rev 0 | 4th Feb,95 | GaganC | Created
---------------------------------------------------------------------------- */
class UTGuard
{
private:
long m_lVal;
public:
//@cmember Constructor
UTGuard (void);
//@cmember Destructor
~UTGuard (void);
//@cmember Acquires the guard
BOOL AcquireGuard (void);
//@cmember Releases the guard
void ReleaseGuard (void);
//@cmember Initializes the Guard
void Init (void);
} ; //End class UTGuard
//-----------------------------------------------------------------------------
//
// IMPLEMENTATION of class UTGuard
//
//-----------------------------------------------------------------------------
/* ----------------------------------------------------------------------------
@mfunc
---------------------------------------------------------------------------- */
inline UTGuard::UTGuard ( void )
{
m_lVal = 0;
}
/* ----------------------------------------------------------------------------
@mfunc
---------------------------------------------------------------------------- */
inline UTGuard::~UTGuard ( void )
{
//Do nothing
}
/* ----------------------------------------------------------------------------
@mfunc
---------------------------------------------------------------------------- */
inline BOOL UTGuard::AcquireGuard (void)
{
long lVal;
lVal = InterlockedExchange (&m_lVal, 1);
return (lVal == 0);
}
/* ----------------------------------------------------------------------------
@mfunc
---------------------------------------------------------------------------- */
inline void UTGuard::ReleaseGuard (void)
{
m_lVal = 0;
}
/* ----------------------------------------------------------------------------
@mfunc
---------------------------------------------------------------------------- */
void inline UTGuard::Init ( void )
{
m_lVal = 0;
}
/* ----------------------------------------------------------------------------
@class UTSemReadWrite
@rev 0 | 4th Feb,95 | GaganC | Created
---------------------------------------------------------------------------- */
class UTSemReadWrite
{
private:
CRITICAL_SECTION csExclusive; // Critical section object to synchronize writers
CRITICAL_SECTION csReader; // Critical section object to synchronize readers
HANDLE hevReadDone; // Manual-reset event to notify writers of
//reader completion
int cReaders; // Count of current readers
BOOL fInitSucceeded; // TRUE if the constructor function succeeded
public:
UTSemReadWrite(void); // Constructor
~UTSemReadWrite(void); // Destructor
// This implementation supports Read and Write locks
SYNCH_LOCK_CAPS GetCaps(void) { return SLC_READWRITE; };
// This object is valid if it was initialized
BOOL IsValid(void) { return fInitSucceeded; }
BOOL Lock(SYNCH_LOCK_TYPE); // Lock the object
BOOL UnLock(SYNCH_LOCK_TYPE); // Unlock the object
};
//-----------------------------------------------------------------------------
//
// IMPLEMENTATION of class UTSemReadWrite
//
//-----------------------------------------------------------------------------
/* ----------------------------------------------------------------------------
@mfunc
SYNCHRO class - Constructor
Create the event, initialize the critical section objects and reader count,
and return.
---------------------------------------------------------------------------- */
inline UTSemReadWrite::UTSemReadWrite(void)
{
// Create the manual-reset event (the only init that can fail)
hevReadDone = CreateEvent(NULL, TRUE, TRUE, NULL);
fInitSucceeded = hevReadDone != NULL;
// If we created the event, proceed with the risk-free initialization
if (fInitSucceeded)
{
cReaders = 0;
InitializeCriticalSection(&csExclusive);
InitializeCriticalSection(&csReader);
}
return;
}
/* ----------------------------------------------------------------------------
@mfunc
SYNCHRO class - Destructor
Free the event, delete the critical section objects, and return.
---------------------------------------------------------------------------- */
inline UTSemReadWrite::~UTSemReadWrite(void)
{
if (IsValid())
{
CloseHandle(hevReadDone);
DeleteCriticalSection(&csExclusive);
DeleteCriticalSection(&csReader);
}
return;
}
/* ----------------------------------------------------------------------------
@mfunc
SYNCHRO class - Lock member function
---------------------------------------------------------------------------- */
inline BOOL UTSemReadWrite::Lock(SYNCH_LOCK_TYPE lt)
{
// Verify that the object is valid
if (! IsValid())
return FALSE;
// Verify that the specified lock type is supported by this implementation
if (lt == SLT_READPROMOTE)
return FALSE;
// Claim the read lock or write lock as specified
if (lt == SLT_READ)
{
// Claim the <csExclusive> critical section. This call blocks if there's
// an active writer or if there's a writer waiting for active readers to
// complete.
EnterCriticalSection(&csExclusive);
// Claim access to the reader count. If this blocks, it's only for the
// briefest moment, while other threads go through to increment or
// decrement the reader count.
EnterCriticalSection(&csReader);
// Increment the reader count. If this is the first reader, we reset the
// hevReadDone event so that the next writer blocks.
if (cReaders++ == 0)
ResetEvent(hevReadDone);
// Release access to the reader count
LeaveCriticalSection(&csReader);
// Release access to the <csExclusive> critical section. This enables
// other readers to come through and the next writer to wait for active
// readers to complete (which in turn prevents new readers from entering).
LeaveCriticalSection(&csExclusive);
}
else
{
// Verify that since this isn't the read lock, that it's the write lock
Assert(lt == SLT_WRITE);
// Claim the <csExclusive> critical section. This not only prevents other
// threads from claiming the write lock, but also prevents any new threads
// from claiming the read lock.
EnterCriticalSection(&csExclusive);
// Wait for the active readers to release their read locks.
return WaitForSingleObject(hevReadDone, INFINITE) == WAIT_OBJECT_0;
}
return TRUE;
} //End Lock
/* ----------------------------------------------------------------------------
@mfunc
SYNCHRO class - Unlock member function
---------------------------------------------------------------------------- */
inline BOOL UTSemReadWrite::UnLock(SYNCH_LOCK_TYPE lt)
{
// Verify that the object is valid
if (! IsValid())
return FALSE;
// Verify that the specified lock type is supported by this implementation
if (lt == SLT_READPROMOTE)
return FALSE;
// Release the read lock or write lock as specified
if (lt == SLT_READ)
{
// Claim access to the reader count. If this blocks, it's only for the
// briefest moment, while other threads go through to increment or
// decrement the reader count.
EnterCriticalSection(&csReader);
// Decrement the reader count. If this is the last reader, set
// <hevReadDone>, which allows the first waiting writer to proceed.
if (--cReaders == 0)
SetEvent(hevReadDone);
// Release access to the reader count
LeaveCriticalSection(&csReader);
}
else
{
// Verify that since this isn't the read lock, that it's the write lock
Assert(lt == SLT_WRITE);
// Make <csExclusive> available to one other writer or to the first reader
LeaveCriticalSection(&csExclusive);
}
return TRUE;
} //End Unlock
/* ----------------------------------------------------------------------------
@class UTSemCheapReadWrite
@rev 0 | 5/1/97 | Shaiwals | Created using UTSemReadWrite, reader
| | | access to the lock is cheaper if
| | | there is already a reader present
---------------------------------------------------------------------------- */
class UTSemCheapReadWrite
{
private:
CRITICAL_SECTION csExclusive; // Critical section object to provide core locking
CRITICAL_SECTION csReader; // Critical section object to synchronize readers
CRITICAL_SECTION csWriter; // Critical section object to synchronize writers
HANDLE hevReadDone; // Manual-reset event to notify writers of
// reader completion
HANDLE hevReaderPresent; // Readers are currently present
HANDLE hevWriterPresent; // Writers are currently present
long cReaders; // Count of current readers
long cWriters; // Count of writers waiting
BOOL fInitSucceeded; // TRUE if the constructor function succeeded
BOOL m_fReader; // Flag to signal that readers presence has
// been notifed
public:
UTSemCheapReadWrite(void); // Constructor
~UTSemCheapReadWrite(void); // Destructor
// This implementation supports Read and Write locks
SYNCH_LOCK_CAPS GetCaps(void) { return SLC_READWRITE; };
// This object is valid if it was initialized
BOOL IsValid(void) { return fInitSucceeded; }
BOOL Lock(SYNCH_LOCK_TYPE); // Lock the object
BOOL UnLock(SYNCH_LOCK_TYPE); // Unlock the object
};
//-----------------------------------------------------------------------------
//
// IMPLEMENTATION of class UTSemCheapReadWrite
//
//-----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -