167 lines
3.3 KiB
C++
167 lines
3.3 KiB
C++
// RWSync.cpp -- Implementation of class CRWSync
|
|
|
|
#include "stdafx.h"
|
|
#include "RWSYNC.h"
|
|
|
|
CRWSync::CRWSync()
|
|
{
|
|
m_cWritersWaiting = 0;
|
|
m_cReadersActive = 0;
|
|
m_cReadersWaiting = 0;
|
|
m_fState = INACTIVE;
|
|
|
|
InitializeCriticalSection(&m_cs);
|
|
|
|
m_hEvWriters = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
m_hEvReaders = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
|
|
ASSERT(m_hEvWriters);
|
|
ASSERT(m_hEvReaders);
|
|
}
|
|
|
|
|
|
CRWSync::~CRWSync()
|
|
{
|
|
m_fState |= SHUTTING_DOWN;
|
|
|
|
HoldForWriting(TRUE);
|
|
|
|
ASSERT(m_fState == (SHUTTING_DOWN | WRITER_ACTIVE));
|
|
|
|
ASSERT(m_cWritersWaiting == 0);
|
|
ASSERT(m_cReadersActive == 0);
|
|
ASSERT(m_cReadersWaiting == 0);
|
|
|
|
CloseHandle(m_hEvWriters);
|
|
CloseHandle(m_hEvReaders);
|
|
|
|
DeleteCriticalSection(&m_cs);
|
|
}
|
|
|
|
ULONG CRWSync::HoldForWriting(BOOL fForced)
|
|
{
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
if ((m_fState & SHUTTING_DOWN) && !fForced)
|
|
{
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return(SHUTDOWN);
|
|
}
|
|
|
|
ResetEvent(m_hEvReaders);
|
|
|
|
if (m_fState & (READER_ACTIVE | WRITER_ACTIVE))
|
|
{
|
|
m_cWritersWaiting++;
|
|
|
|
m_fState |= WRITER_WAITING;
|
|
|
|
while (m_fState & (READER_ACTIVE | WRITER_ACTIVE))
|
|
{
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
DWORD dwResult= WaitForSingleObject(m_hEvWriters, INFINITE);
|
|
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
if ((m_fState & SHUTTING_DOWN) && !fForced)
|
|
{
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return(SHUTDOWN);
|
|
}
|
|
|
|
ASSERT( dwResult != WAIT_OBJECT_0
|
|
|| !(m_fState & (READER_ACTIVE | WRITER_ACTIVE))
|
|
);
|
|
}
|
|
|
|
if (!--m_cWritersWaiting) m_fState &= ~WRITER_WAITING;
|
|
}
|
|
|
|
m_fState |= WRITER_ACTIVE;
|
|
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return STARTED;
|
|
}
|
|
|
|
ULONG CRWSync::BeginRead()
|
|
{
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
if (m_fState & SHUTTING_DOWN)
|
|
{
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return(SHUTDOWN);
|
|
}
|
|
|
|
if (m_fState & (WRITER_ACTIVE))
|
|
{
|
|
m_cReadersWaiting++;
|
|
|
|
m_fState |= READER_WAITING;
|
|
|
|
while (m_fState & (WRITER_ACTIVE))
|
|
{
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
DWORD dwResult= WaitForSingleObject(m_hEvReaders, INFINITE);
|
|
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
if (m_fState & SHUTTING_DOWN)
|
|
{
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return(SHUTDOWN);
|
|
}
|
|
|
|
ASSERT( dwResult != WAIT_OBJECT_0
|
|
|| !(m_fState & (READER_ACTIVE | WRITER_ACTIVE))
|
|
);
|
|
}
|
|
|
|
if (!--m_cReadersWaiting) m_fState &= ~READER_WAITING;
|
|
}
|
|
|
|
m_fState |= READER_ACTIVE;
|
|
|
|
m_cReadersActive++;
|
|
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return STARTED;
|
|
}
|
|
|
|
void CRWSync:: EndRead()
|
|
{
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
if (!--m_cReadersActive)
|
|
{
|
|
m_fState &= ~READER_ACTIVE;
|
|
|
|
if (m_fState & WRITER_WAITING) SetEvent(m_hEvWriters);
|
|
else
|
|
if (m_fState & READER_WAITING) SetEvent(m_hEvReaders);
|
|
}
|
|
|
|
LeaveCriticalSection(&m_cs);
|
|
}
|
|
|
|
void CRWSync:: EndWrite()
|
|
{
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
m_fState &= ~WRITER_ACTIVE;
|
|
|
|
if (m_fState & WRITER_WAITING) SetEvent(m_hEvWriters);
|
|
else
|
|
if (m_fState & READER_WAITING) SetEvent(m_hEvReaders);
|
|
|
|
LeaveCriticalSection(&m_cs);
|
|
}
|