#include "ReadersWriterLock.h"

VOID InitializeRWLock(LPRWLOCK lpRwl)
{
	lpRwl->cReaders = 0;
	lpRwl->hDoRead = CreateEvent(NULL, TRUE, FALSE, NULL);
	lpRwl->hDoWrite = CreateEvent(NULL, TRUE, TRUE, NULL);
	InitializeCriticalSection(&lpRwl->cs);
}

VOID WriterEnter(LPRWLOCK lpRwl)
{
	ResetEvent(lpRwl->hDoRead);
	WaitForSingleObject(lpRwl->hDoWrite, INFINITE);
}

VOID WriterLeave(LPRWLOCK lpRwl)
{
	SetEvent(lpRwl->hDoRead);
}

VOID ReaderEnter(LPRWLOCK lpRwl)
{
	WaitForSingleObject(lpRwl->hDoRead, INFINITE);	

#ifdef RWL_USE_INTERLOCKED	
	if(InterlockedIncrement(&(lpRwl->cReaders)) == 1)
		ResetEvent(lpRwl->hDoWrite);
#else
	EnterCriticalSection(&lpRwl->cs);
	if(lpRwl->cReaders == 0)
		ResetEvent(lpRwl->hDoWrite);
	lpRwl->cReaders ++;
	LeaveCriticalSection(&lpRwl->cs);
#endif	
}

VOID ReaderLeave(LPRWLOCK lpRwl)
{
#ifdef RWL_USE_INTERLOCKED	
	if(InterlockedDecrement(&(lpRwl->cReaders)) == 0)
		SetEvent(lpRwl->hDoWrite);
#else
	EnterCriticalSection(&lpRwl->cs);	
	lpRwl->cReaders --;
	if(lpRwl->cReaders == 0)
		SetEvent(lpRwl->hDoWrite);
	LeaveCriticalSection(&lpRwl->cs);
#endif
}

VOID DeleteRWLock(LPRWLOCK lpRwl)
{
	CloseHandle(lpRwl->hDoRead);
	CloseHandle(lpRwl->hDoWrite);
	DeleteCriticalSection(&lpRwl->cs);
}