193 lines
3.8 KiB
C++
193 lines
3.8 KiB
C++
// Copyright (c) .NET Foundation. All rights reserved.
|
|
// Licensed under the MIT License. See License.txt in the project root for license information.
|
|
|
|
#pragma once
|
|
|
|
#if (_WIN32_WINNT < 0x600)
|
|
|
|
//
|
|
// XP implementation.
|
|
//
|
|
class CWSDRWLock
|
|
{
|
|
public:
|
|
|
|
CWSDRWLock()
|
|
: m_bInited(FALSE)
|
|
{
|
|
}
|
|
|
|
~CWSDRWLock()
|
|
{
|
|
if (m_bInited)
|
|
{
|
|
DeleteCriticalSection(&m_rwLock.critsec);
|
|
CloseHandle(m_rwLock.ReadersDoneEvent);
|
|
}
|
|
}
|
|
|
|
BOOL QueryInited() const
|
|
{
|
|
return m_bInited;
|
|
}
|
|
|
|
HRESULT Init()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (FALSE == m_bInited)
|
|
{
|
|
m_rwLock.fWriterWaiting = FALSE;
|
|
m_rwLock.LockCount = 0;
|
|
if ( !InitializeCriticalSectionAndSpinCount( &m_rwLock.critsec, 0 ))
|
|
{
|
|
DWORD dwError = GetLastError();
|
|
hr = HRESULT_FROM_WIN32(dwError);
|
|
return hr;
|
|
}
|
|
|
|
m_rwLock.ReadersDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
if( NULL == m_rwLock.ReadersDoneEvent )
|
|
{
|
|
DWORD dwError = GetLastError();
|
|
hr = HRESULT_FROM_WIN32(dwError);
|
|
DeleteCriticalSection(&m_rwLock.critsec);
|
|
return hr;
|
|
}
|
|
m_bInited = TRUE;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
void SharedAcquire()
|
|
{
|
|
EnterCriticalSection(&m_rwLock.critsec);
|
|
InterlockedIncrement(&m_rwLock.LockCount);
|
|
LeaveCriticalSection(&m_rwLock.critsec);
|
|
}
|
|
|
|
void SharedRelease()
|
|
{
|
|
ReleaseRWLock();
|
|
}
|
|
|
|
void ExclusiveAcquire()
|
|
{
|
|
EnterCriticalSection( &m_rwLock.critsec );
|
|
|
|
m_rwLock.fWriterWaiting = TRUE;
|
|
|
|
// check if there are any readers active
|
|
if ( InterlockedExchangeAdd( &m_rwLock.LockCount, 0 ) > 0 )
|
|
{
|
|
//
|
|
// Wait for all the readers to get done..
|
|
//
|
|
WaitForSingleObject( m_rwLock.ReadersDoneEvent, INFINITE );
|
|
}
|
|
m_rwLock.LockCount = -1;
|
|
}
|
|
|
|
void ExclusiveRelease()
|
|
{
|
|
ReleaseRWLock();
|
|
}
|
|
|
|
private:
|
|
|
|
BOOL m_bInited;
|
|
|
|
typedef struct _RW_LOCK
|
|
{
|
|
BOOL fWriterWaiting; // Is a writer waiting on the lock?
|
|
LONG LockCount;
|
|
CRITICAL_SECTION critsec;
|
|
HANDLE ReadersDoneEvent;
|
|
} RW_LOCK, *PRW_LOCK;
|
|
|
|
RW_LOCK m_rwLock;
|
|
|
|
private:
|
|
|
|
void ReleaseRWLock()
|
|
{
|
|
LONG Count = InterlockedDecrement( &m_rwLock.LockCount );
|
|
|
|
if ( 0 <= Count )
|
|
{
|
|
// releasing a read lock
|
|
if (( m_rwLock.fWriterWaiting ) && ( 0 == Count ))
|
|
{
|
|
SetEvent( m_rwLock.ReadersDoneEvent );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Releasing a write lock
|
|
m_rwLock.LockCount = 0;
|
|
m_rwLock.fWriterWaiting = FALSE;
|
|
LeaveCriticalSection(&m_rwLock.critsec);
|
|
}
|
|
}
|
|
};
|
|
|
|
#else
|
|
|
|
//
|
|
// Implementation for Windows Vista or greater.
|
|
//
|
|
class CWSDRWLock
|
|
{
|
|
public:
|
|
|
|
CWSDRWLock()
|
|
{
|
|
InitializeSRWLock(&m_rwLock);
|
|
}
|
|
|
|
BOOL QueryInited()
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
HRESULT Init()
|
|
{
|
|
//
|
|
// Method defined to keep compatibility with CWSDRWLock class for XP.
|
|
//
|
|
return S_OK;
|
|
}
|
|
|
|
void SharedAcquire()
|
|
{
|
|
AcquireSRWLockShared(&m_rwLock);
|
|
}
|
|
|
|
void SharedRelease()
|
|
{
|
|
ReleaseSRWLockShared(&m_rwLock);
|
|
}
|
|
|
|
void ExclusiveAcquire()
|
|
{
|
|
AcquireSRWLockExclusive(&m_rwLock);
|
|
}
|
|
|
|
void ExclusiveRelease()
|
|
{
|
|
ReleaseSRWLockExclusive(&m_rwLock);
|
|
}
|
|
|
|
private:
|
|
|
|
SRWLOCK m_rwLock;
|
|
};
|
|
|
|
#endif
|
|
|
|
//
|
|
// Rename the lock class to a more clear name.
|
|
//
|
|
typedef CWSDRWLock READ_WRITE_LOCK; |