抄WINDOW核心程式設計中的 多單寫多讀鎖,
#pragma once
#include <windows.h>
class CSWMRG
{
public:
CSWMRG(void);
~CSWMRG(void);
public:
void WaitToRead();
void WaitToWrite();
void Done();
private:
CRITICAL_SECTION m_cs;
HANDLE m_hsemReaders;
HANDLE m_hsemWriters;
int m_nWaitingReaders;
int m_nWaitingWriters;
int m_nActives;
};
#include "StdAfx.h"
#include "./swmrg.h"
CSWMRG::CSWMRG(void)
{
InitializeCriticalSection(&m_cs);
m_hsemReaders = CreateSemaphore(NULL, 0, 65535, NULL);
m_hsemWriters = CreateSemaphore(NULL, 0, 65535, NULL);
m_nWaitingReaders = 0;
m_nWaitingWriters = 0;
m_nActives = 0;
}
CSWMRG::~CSWMRG(void)
{
CloseHandle(m_hsemWriters);
CloseHandle(m_hsemReaders);
DeleteCriticalSection(&m_cs);
m_nWaitingReaders = 0;
m_nWaitingWriters = 0;
m_nActives = 0;
}
void CSWMRG::WaitToRead()
{
EnterCriticalSection(&m_cs);
//只需要判斷寫, 因為可以同時讀
BOOL bWriting = ((m_nActives < 0) || (m_nWaitingWriters > 0));
if (bWriting)
{
m_nWaitingReaders++;
}
else
{
m_nActives++;
}
LeaveCriticalSection(&m_cs);
if (bWriting)
{
WaitForSingleObject(m_hsemReaders, -1);
}
}
void CSWMRG::WaitToWrite()
{
EnterCriticalSection(&m_cs);
//只要有人正在讀或寫就不能寫
BOOL bBusy = (m_nActives != 0);
if (bBusy)
{
m_nWaitingWriters++;
}
else
{
m_nActives = -1;
}
LeaveCriticalSection(&m_cs);
if (bBusy)
{
WaitForSingleObject(&m_hsemWriters, -1);
}
}
void CSWMRG::Done()
{
EnterCriticalSection(&m_cs);
if (m_nActives > 0)
{
m_nActives--;
}
else
{
m_nActives++;
}
HANDLE hSem = NULL;
int nCount = 1;
if (m_nActives == 0)
{
if (m_nWaitingWriters > 0)
{
m_nActives = -1;
m_nWaitingWriters--;
hSem = m_hsemWriters;
}
else if (m_nWaitingReaders > 0)
{
//全部可讀
m_nActives = m_nWaitingReaders;
m_nWaitingReaders = 0;
hSem = m_hsemReaders;
nCount = m_nWaitingReaders;
}
}
LeaveCriticalSection(&m_cs);
if (hSem)
{
ReleaseSemaphore(hSem, nCount, NULL);
}
}
// CSWMRG.cpp : 定義控制檯應用程式的入口點。
//
#include "stdafx.h"
#include "SWMRG.h"
#include <process.h>
unsigned int __stdcall TestRead(void *pParam);
unsigned int __stdcall TestWrite(void *pParam);
CSWMRG g_swmrg;
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hThread[5];
wchar_t *pContent = new wchar_t[512];
memset(pContent, '/0', 512);
for (int i = 0; i < 3; i++)
{
hThread[i] = (HANDLE) _beginthreadex(NULL, 0,TestRead, pContent, 0, NULL);
}
for (int i = 3; i < 5; i++)
{
hThread[i] = (HANDLE) _beginthreadex(NULL, 0,TestWrite, pContent, 0, NULL);
}
WaitForMultipleObjects(5, hThread, TRUE, -1);
delete[] pContent;
for (int i = 0; i < 5; i++)
{
CloseHandle(hThread[i]);
}
wprintf(L"Game Over /r/n");
getchar();
return 0;
}
unsigned int __stdcall TestRead(void *pParam)
{
wchar_t *pContent = (wchar_t *) pParam;
if (NULL == pContent)
return -1;
for (int i = 0; i < 5; i++)
{
g_swmrg.WaitToRead();
wprintf(pContent);
Sleep(1000);
g_swmrg.Done();
Sleep(0);
}
return 1;
}
static int nThreadCount = 0;
unsigned int __stdcall TestWrite(void *pParam)
{
wchar_t *pContent = (wchar_t *) pParam;
if (NULL == pContent)
return -1;
int nThreadNum = nThreadCount;
nThreadCount++;
for (int i = 0; i < 3; i++)
{
g_swmrg.WaitToRead();
wsprintfW(pContent, L"hread = %d, Loop = %d/r/n", nThreadNum, i);
Sleep(1000);
g_swmrg.Done();
Sleep(0);
}
return 1;
}