windows-nt/Source/XPSP1/NT/ds/security/passport/include/rwlock.h
2020-09-26 16:20:57 +08:00

130 lines
3.2 KiB
C++

// this lock only works for a single write, and multiple read, concurrent
// multiple exclusive lock isn't a supported scenario
//
// (1) ClaimExclusiveLock() and ClaimShareLock() is mutually exclusive because
// the reverse order of increments and checking
//
// (2) As soon as Exclusive is set, all new Share lock will be blocked
//
//
#ifndef _CReadWriteLock_H_
#define _CReadWriteLock_H_
class CReadWriteLock
{
long lExclusive;
long lTotalUsers;
long lReadInQueue;
HANDLE hWriteReadyEvent, hReadReadyEvent;
public:
CReadWriteLock()
{
hWriteReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
hReadReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
};
~CReadWriteLock()
{
CloseHandle(hWriteReadyEvent);
CloseHandle(hReadReadyEvent);
}
bool IsInit()
{
return NULL != hWriteReadyEvent && NULL != hReadReadyEvent;
}
bool CReadWriteLock::ClaimExclusiveLock()
{
ResetEvent(hWriteReadyEvent);
ResetEvent(hReadReadyEvent);
InterlockedIncrement( &lExclusive );
InterlockedIncrement( &lTotalUsers );
if (lTotalUsers > 1)
{
if (lReadInQueue > 0) // in case no body is in the read queue
{
// wait until all the reads to finish
if (WAIT_OBJECT_0 != WaitForSingleObject(hWriteReadyEvent, INFINITE))
return false;
}
}
return true;
}
void CReadWriteLock::ReleaseExclusiveLock( )
{
InterlockedDecrement( &lTotalUsers );
InterlockedDecrement( &lExclusive );
SetEvent(hReadReadyEvent);
}
bool CReadWriteLock::ClaimShareLock( )
{
InterlockedIncrement( &lTotalUsers );
if (CReadWriteLock::lExclusive > 0)
{
if (WAIT_OBJECT_0 != WaitForSingleObject(hReadReadyEvent, INFINITE))
return false;
}
InterlockedIncrement ( &lReadInQueue );
return true;
}
void CReadWriteLock::ReleaseShareLock( )
{
if (0 == InterlockedDecrement ( &lReadInQueue ))
{
if (CReadWriteLock::lExclusive > 0)
SetEvent(hWriteReadyEvent);
}
InterlockedDecrement( &lTotalUsers );
}
};
//
// this class extends CReadWriteLock to allow multiple write threads
// -- additional overhead of entering/leaving critical section
//
class CReadWriteLockEx : public CReadWriteLock
{
public:
bool ClaimExclusiveLock()
{
// Request ownership of the critical section.
EnterCriticalSection(&CriticalSection);
return CReadWriteLock::ClaimExclusiveLock();
};
void ReleaseExclusiveLock( )
{
CReadWriteLock::ReleaseExclusiveLock();
// Release ownership of the critical section.
LeaveCriticalSection(&CriticalSection);
};
public:
// constructor and desctructor
CReadWriteLockEx()
{
// Initialize the critical section.
InitializeCriticalSection(&CriticalSection);
};
virtual ~CReadWriteLockEx()
{
// Release resources used by the critical section object.
DeleteCriticalSection(&CriticalSection);
};
protected:
// data members
CRITICAL_SECTION CriticalSection;
};
#endif