#include "StdAfx.h"
#include "FastReadWriteLock.h"

//	書き込み要求フラグ
#define	WRITE_REQUEST_FLAG	0x40000000	

//	最大同時書き込み数
#define	MAX_READER_COUNT	0x20000000


CFastReadWriteLock::CFastReadWriteLock(void)
{
	m_writerMutex.Create(FALSE);
	m_readerEvent.Create(TRUE, TRUE);
	m_readerZeroEvent.Create(FALSE, FALSE);
	m_readerCountWriteRequest = 0;
}

CFastReadWriteLock::~CFastReadWriteLock(void)
{
	//	全て開放してるか？
	ASSERT(m_readerCountWriteRequest.GetCounter() == 0);
}


/////////////////////////////////////////////////////////////////////////////////////
//	制御
/////////////////////////////////////////////////////////////////////////////////////
/*!
	読み込み要求
*/
void CFastReadWriteLock::ReadLock()
{
	//	最大数確認
	ASSERT(m_readerCountWriteRequest.GetCounter() < MAX_READER_COUNT);

	//	書き込み要求あり?
	while(m_readerCountWriteRequest.IncCounter() & WRITE_REQUEST_FLAG)
	{
		//	カウンタを戻す
		if(m_readerCountWriteRequest.DecCounter() == WRITE_REQUEST_FLAG)
			::SetEvent(m_readerZeroEvent);

		//	書き込み終了まで待つ
		WaitForSingleObject(m_readerEvent, INFINITE);
	}
}

/*!
	読み込み開放
*/
void CFastReadWriteLock::ReadUnlock()
{
	//	呼びすぎ？
	ASSERT(m_readerCountWriteRequest.GetCounter() > 0);

	//	カウンタを戻す
	if(m_readerCountWriteRequest.DecCounter() == WRITE_REQUEST_FLAG)
		::SetEvent(m_readerZeroEvent);
}


/*!
	書き込み要求
*/
void CFastReadWriteLock::WriteLock()
{
	//	書き込み排他制御
	WaitForSingleObject(m_writerMutex, INFINITE);

	//	リーダー待機イベントリセット
	::ResetEvent(m_readerEvent);

	//	リーダー停止フラグを立てる
	if(m_readerCountWriteRequest.AddCounter(WRITE_REQUEST_FLAG) != 0)
	{
		//	読み出し終了まで待つ
		WaitForSingleObject(m_readerZeroEvent, INFINITE);
	}
}

/*!
	書き込み開放
*/
void CFastReadWriteLock::WriteUnlock()
{
	//	呼びすぎ？
	ASSERT(m_readerCountWriteRequest.GetCounter() >= WRITE_REQUEST_FLAG);

	//	フラグ解除
	m_readerCountWriteRequest.AddCounter(-WRITE_REQUEST_FLAG);

	//	リーダー待機イベントセット
	::SetEvent(m_readerEvent);

	//	買い込み排他開放
	::ReleaseMutex(m_writerMutex);
}

