class CRWGuard ...{ public: CRWGuard(); virtual~CRWGuard(); void WaitToRead(); void WaitToWrite(); void Done(); protected: CRITICAL_SECTION m_cs; //关键代码段实现内部同步 int m_nActive; //活动数 int m_nWaitingReaders; //读者排队数 int m_nWaitingWriters; //作者排队数 HANDLE m_hsemWriters; //作者信标 HANDLE m_hsemReaders; //读者信标 };
CRWGuard::CRWGuard() ...{ // Initially no readers want access, no writers want access, and // no threads are accessing the resource m_nWaitingReaders = m_nWaitingWriters = m_nActive =0; m_hsemReaders = CreateSemaphore(NULL, 0, 10, NULL); m_hsemWriters = CreateSemaphore(NULL, 0, 10, NULL); InitializeCriticalSection(&m_cs); } CRWGuard::~CRWGuard() ...{ m_nWaitingReaders = m_nWaitingWriters = m_nActive =0; DeleteCriticalSection(&m_cs); CloseHandle(m_hsemReaders); CloseHandle(m_hsemWriters); } //等待读取 void CRWGuard::WaitToRead() ...{ EnterCriticalSection(&m_cs); // Are there writers waiting or is a writer writing? BOOL fResourceWritePending = (m_nWaitingWriters || (m_nActive <0)); if (fResourceWritePending) ...{ // 增加等待读者数 m_nWaitingReaders++; }else...{ // This reader can read, increment the count of active readers m_nActive++; } // Allow other threads to attempt reading/writing LeaveCriticalSection(&m_cs); if (fResourceWritePending) ...{ // This thread must wait WaitForSingleObject(m_hsemReaders, INFINITE); } } //等待写入 void CRWGuard::WaitToWrite() ...{ EnterCriticalSection(&m_cs); // Are there any threads accessing the resource? BOOL fResourceOwned = (m_nActive !=0); if (fResourceOwned) ...{ // 增加等待作者数 m_nWaitingWriters++; }else...{ // This writer can write, decrement the count of active writers m_nActive =-1; } // Allow other threads to attempt reading/writing LeaveCriticalSection(&m_cs); if (fResourceOwned) ...{ // 等待 WaitForSingleObject(m_hsemWriters, INFINITE); } } void CRWGuard::Done() ...{ // Ensure exclusive access to the member variables EnterCriticalSection(&m_cs); if (m_nActive >0) ...{ // Readers have control so a reader must be done m_nActive--; }else...{ // Writers have control so a writer must be done m_nActive++; } HANDLE hsem = NULL; // Assume no threads are waiting LONG lCount =1; // Assume only 1 waiter wakes; always true for writers if (m_nActive ==0) ...{ // NOTE: 若作者总尝试写入,读者可能饥饿 // 作者或读者谁优先,视乎判断顺序. 若有多读者,建议作者优先 if (m_nWaitingWriters >0) ...{ //作者优先 // Writers are waiting and they take priority over readers m_nActive =-1; // A writer will get access m_nWaitingWriters--; // One less writer will be waiting hsem = m_hsemWriters; // Writers wait on this semaphore // NOTE: The semaphore will release only 1 writer thread }elseif (m_nWaitingReaders >0) ...{ // Readers are waiting and no writers are waiting m_nActive = m_nWaitingReaders; // All readers will get access m_nWaitingReaders =0; // No readers will be waiting hsem = m_hsemReaders; // Readers wait on this semaphore lCount = m_nActive; // Semaphore releases all readers }else...{ // There are no threads waiting at all; no semaphore gets released } } // Allow other threads to attempt reading/writing LeaveCriticalSection(&m_cs); if (hsem != NULL) ...{ // Some threads are to be released ReleaseSemaphore(hsem, lCount, NULL); } }