📄 rwlock.cpp
字号:
#include "stdafx.h"
#include "rwlock.h"
//#include "log.h"
//#include "exception.h"
//#include "LockStatusStack.h"
#if !defined(NEWLOCK) && !defined(OLDLOCK)
CRWLock::CRWLock()
{
//guard(CRWLock::CRWLock());
readerCount = 0;
dataLock = CreateMeteredSection(1, 1, NULL);
//_ASSERTE(dataLock);
InitializeCriticalSection(&mutex);
//unguard;
}
CRWLock::~CRWLock()
{
//guard(CRWLock::~CRWLock());
CloseMeteredSection(dataLock);
DeleteCriticalSection(&mutex);
//unguard;
}
void CRWLock::ReadLock()
{
//guard(void CRWLock::ReadLock());
//LOCK_LOG(L"RW ReadLock", (DWORD)this);
EnterCriticalSection(&mutex);
if (++readerCount == 1) {
if (EnterMeteredSection(dataLock, INFINITE) != WAIT_OBJECT_0) {
//Log.Add(LOG_ERROR, L"ReadLock failed on dataLock");
}
}
LeaveCriticalSection(&mutex);
//unguard;
}
void CRWLock::ReadUnlock()
{
//guard(void CRWLock::ReadUnlock());
//UNLOCK_LOG(L"RW ReadUnlock", (DWORD)this);
LONG prevCount;
EnterCriticalSection(&mutex);
if (--readerCount == 0) {
LeaveMeteredSection(dataLock, 1, &prevCount);
}
LeaveCriticalSection(&mutex);
//unguard;
}
void CRWLock::WriteLock()
{
//guard(void CRWLock::WriteLock());
//LOCK_LOG(L"RW WriteLock", (DWORD)this);
EnterMeteredSection(dataLock, INFINITE);
//unguard;
}
bool CRWLock::WriteTryLock()
{
//guard(bool CRWLock::WriteTryLock());
return EnterMeteredSection(dataLock, 0) == WAIT_OBJECT_0;
//unguard;
}
void CRWLock::WriteUnlock()
{
//guard(void CRWLock::WriteUnlock());
//UNLOCK_LOG(L"RW WriteUnlock", (DWORD)this);
LONG prevCount;
LeaveMeteredSection(dataLock, 1, &prevCount);
if (prevCount != 0) {
//Log.Add(LOG_ERROR, L"WriteUnlock semaphore was not locked");
}
//unguard;
}
#elif defined(OLDLOCK)
CRWLock::CRWLock()
{
//guard(CRWLock::CRWLock());
readerCount = 0;
dataLock = CreateSemaphore(NULL, 1, 1, NULL);
//_ASSERTE(dataLock);
InitializeCriticalSection(&mutex);
//unguard;
}
CRWLock::~CRWLock()
{
//guard(CRWLock::~CRWLock());
CloseHandle(dataLock);
DeleteCriticalSection(&mutex);
//unguard;
}
void CRWLock::ReadLock()
{
//guard(void CRWLock::ReadLock());
EnterCriticalSection(&mutex);
if (++readerCount == 1) {
if (WaitForSingleObject(dataLock, INFINITE) != WAIT_OBJECT_0) {
//Log.Add(LOG_ERROR, L"ReadLock failed on dataLock");
}
}
LeaveCriticalSection(&mutex);
//unguard;
}
void CRWLock::ReadUnlock()
{
//guard(void CRWLock::ReadUnlock());
LONG prevCount;
EnterCriticalSection(&mutex);
if (--readerCount == 0) {
ReleaseSemaphore(dataLock, 1, &prevCount);
}
LeaveCriticalSection(&mutex);
//unguard;
}
void CRWLock::WriteLock()
{
//guard(void CRWLock::WriteLock());
WaitForSingleObject(dataLock, INFINITE);
//unguard;
}
bool CRWLock::WriteTryLock()
{
//guard(bool CRWLock::WriteTryLock());
return WaitForSingleObject(dataLock, 0) == WAIT_OBJECT_0;
//unguard;
}
void CRWLock::WriteUnlock()
{
//guard(void CRWLock::WriteUnlock());
LONG prevCount;
ReleaseSemaphore(dataLock, 1, &prevCount);
if (prevCount != 0) {
//Log.Add(LOG_ERROR, L"WriteUnlock semaphore was not locked");
}
//unguard;
}
#else
CRWLock::CRWLock()
{
//guard(CRWLock::CRWLock() );
m_nLock = 0;
m_nRead = 0;
m_nWrite = 0;
#ifdef USE_SPINLOCK
m_hREvent = CreateEvent(NULL, FALSE, FALSE, NULL);
m_hWEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
m_lock = 0;
#else
m_hREvent = 0;
m_hWEvent = 0;
InitializeCriticalSectionAndSpinCount(&m_lock, 4000);
#endif
//unguard;
}
CRWLock::~CRWLock()
{
//guard(CRWLock::~CRWLock() );
//EASSERT(m_nLock == 0);
//EASSERT(m_nRead == 0);
//EASSERT(m_nWrite == 0);
#ifdef USE_SPINLOCK
CloseHandle(m_hREvent);
CloseHandle(m_hWEvent);
#else
if(m_hREvent)
CloseHandle(m_hREvent);
if (m_hWEvent)
CloseHandle(m_hWEvent);
DeleteCriticalSection(&m_lock);
#endif
unguard;
}
#ifdef USE_SPINLOCK
void CRWLock::Wait(/*int mode*/)
{
//guard(void CRWLock::Wait(/*int mode*/));
int count;
/*
if (mode == 0)
goto step3;
// step 1
count = 200;
while (--count >= 0) {
if (InterlockedExchange(&m_lock, 1) == 0)
goto step2;
if (InterlockedExchange(&m_lock, 1) == 0)
goto step2;
}
goto step3;
// step 2
while (--count >= 0) {
if (InterlockedExchange(&m_lock, 1) == 0) {
step2:
if (mode > 0 && m_nLock >= 0 || m_nLock == 0)
return;
InterlockedExchange(&m_lock, 0);
}
else {
break;
}
}
// I did test using GetThreadTimes
// CRWLock::Wait * 100,000 = 156250
// CriticalSection Spin count * 10,000,000 = 937,500
// WaitEvent & SetEvent * 100,000 = 10,000,000
// So, I decide to choose 200
// step3
step3:
*/
count = 4000;
while (--count >= 0) {
if (InterlockedExchange(&m_lock, 1) == 0)
return;
__asm { rep nop} // pause
}
count = 4000;
while (--count >= 0) {
SwitchToThread(); //Sleep(0);
if (InterlockedExchange(&m_lock, 1) == 0)
return;
}
for ( ; ; ) {
Sleep(1000);
if (InterlockedExchange(&m_lock, 1) == 0)
return;
}
//unguard;
}
#endif
void CRWLock::ReadLock()
{
//guard(void CRWLock::ReadLock());
Enter();
if (m_nLock == 0 && m_nWrite || m_nLock < 0) {
// check m_nWrite in order to prevent excessive task switching
do {
if (m_nWrite >= 0) {
m_nWrite += 0x80000000; // set sign bit
#ifndef USE_SPINLOCK
if (!m_hWEvent) {
m_hWEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
//EASSERT(m_hWEvent);
}
#endif
Leave();
WaitForSingleObject(m_hWEvent, INFINITE);
Enter();
m_nWrite -= 0x80000000; // clear sign bit
}
else {
m_nRead++;
#ifndef USE_SPINLOCK
if (!m_hREvent) {
m_hREvent = CreateEvent(NULL, FALSE, FALSE, NULL);
//EASSERT(m_hREvent);
}
#endif
Leave();
WaitForSingleObject(m_hREvent, INFINITE);
Enter();
m_nRead--;
}
} while (m_nLock < 0);
m_nLock++;
if (m_nRead) {
Leave();
SetEvent(m_hREvent);
}
else
Leave();
}
else {
m_nLock++;
Leave();
}
//unguard;
}
void CRWLock::ReadUnlock()
{
//guard(void CRWLock::ReadUnlock() );
Enter();
//EASSERT(m_nLock > 0);
if (--m_nLock == 0 && m_nWrite) {
Leave();
SetEvent(m_hWEvent);
}
else
Leave();
}
void CRWLock::WriteLock()
{
Enter();
if (m_nLock || m_nWrite) {
// check m_nWrite in order to prevent excessive task switching
m_nWrite++;
#ifndef USE_SPINLOCK
if (!m_hWEvent) {
m_hWEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
//EASSERT(m_hWEvent);
}
#endif
do {
Leave();
WaitForSingleObject(m_hWEvent, INFINITE);
Enter();
} while (m_nLock);
// I think this loop is unnecessary because m_nLock should be zero,
// but empirically that is not true.
// Anyway, using loop is safer.
m_nWrite--;
}
m_nLock = -1;
Leave();
//unguard;
}
bool CRWLock::WriteTryLock()
{
//guard(bool CRWLock::WriteTryLock());
Enter();
if (m_nLock) {
Leave();
return false;
}
m_nLock = -1;
Leave();
return true;
}
void CRWLock::WriteUnlock()
{
Enter();
//EASSERT(m_nLock < 0);
m_nLock = 0;
if (m_nWrite) {
Leave();
SetEvent(m_hWEvent);
}
else
Leave();
//unguard;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -