1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| class CRWLock
{
LONG ReaderCount;
HANDLE WriterLock;
HANDLE WriteEvent;
HANDLE ReadEvent;
public:
enum RWLockType
{
Reader,
Writer
};
CRWLock()
{
WriterLock = CreateEvent(0, false, true, 0);
WriteEvent = CreateEvent(0, true, true, 0);
ReadEvent = CreateEvent(0, true, false, 0);
ReaderCount = -1;
}
~CRWLock()
{
CloseHandle(WriteEvent);
CloseHandle(WriterLock);
CloseHandle(ReadEvent);
}
DWORD Lock(RWLockType type, DWORD dwTimeOut = INFINITE)
{
// An arbitrary number of readers (all in the same process) can own the lock at any time,
// but no more than one writer can own it
DWORD dwRes;
if(type == Writer)
{
ResetEvent(WriteEvent);
if ((dwRes = WaitForSingleObject(WriterLock, dwTimeOut)) == WAIT_TIMEOUT)
return dwRes;
}
else
{
if ((dwRes = WaitForSingleObject(WriteEvent, dwTimeOut)) == WAIT_TIMEOUT)
return dwRes;
if(InterlockedIncrement(&ReaderCount) == 0)
{
if ((dwRes = WaitForSingleObject(WriterLock, dwTimeOut)) == WAIT_TIMEOUT)
return dwRes;
SetEvent(ReadEvent);
}
if ((dwRes = WaitForSingleObject(ReadEvent, dwTimeOut)) == WAIT_TIMEOUT)
return dwRes;
}
return dwRes;
}
void Unlock(RWLockType type)
{
if(type == Writer)
{
SetEvent(WriterLock);
SetEvent(WriteEvent);
}
else if(InterlockedDecrement(&ReaderCount) < 0)
{
ResetEvent(ReadEvent);
SetEvent(WriterLock);
}
}
};
class CAutoRWLock
{
public:
CAutoRWLock(CRWLock& l,CRWLock::RWLockType t, DWORD dwTimeOut = INFINITE)
:rwL(l),rwType(t)
{ rwL.Lock(rwType,dwTimeOut); }
virtual ~CAutoRWLock()
{ rwL.Unlock(rwType); }
protected:
CRWLock& rwL;
CRWLock::RWLockType rwType;
}; |
Partager