aspnetcore/src/AspNetCoreModuleV2/IISLib/rwlock.h

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;