⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rwlock.cpp

📁 概述:数据的纵向收集
💻 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 + -