#include <windows.h>
#include <process.h>
struct SHAREINFO
{
DWORD dwSpinCount; //循环查询的次数
volatile LONG nLockCount; //任何线程调用Entry的次数
DWORD dwThreadID; //表明当前使用濒界区的线程ID
int nRecurseCount; //本线程调用Entry的次数
};
class TestCriticalSection
{
public:
TestCriticalSection();
~TestCriticalSection();
public:
BOOL CreatetCritical(DWORD dwSpinCount, const wchar_t *pEventName);
void DestroyCritical();
void SetSpinCount(DWORD dwSpinCount);
BOOL TryEntry();
void Entry();
void Leave();
private:
DWORD m_dwSpinCount;
HANDLE m_hEvent;
SHAREINFO *m_pShareInfo;
BOOL m_bInit;
};
TestCriticalSection::TestCriticalSection()
:m_dwSpinCount(4000)
,m_hEvent(NULL)
,m_pShareInfo(NULL)
,m_bInit(FALSE)
{
}
TestCriticalSection::~TestCriticalSection()
{
DestroyCritical();
}
BOOL TestCriticalSection::CreatetCritical(DWORD dwSpinCount, const wchar_t *pEventName)
{
DestroyCritical();
m_hEvent = CreateEventW(NULL, FALSE, FALSE, pEventName);
m_pShareInfo = new SHAREINFO;
memset(m_pShareInfo, 0, sizeof(SHAREINFO));
m_bInit = TRUE;
m_dwSpinCount = dwSpinCount;
return TRUE;
}
void TestCriticalSection::DestroyCritical()
{
if (m_hEvent)
CloseHandle(m_hEvent);
m_hEvent = NULL;
if (m_pShareInfo)
delete[] m_pShareInfo;
m_pShareInfo = NULL;
m_bInit = FALSE;
}
void TestCriticalSection::SetSpinCount(DWORD dwSpinCount)
{
m_dwSpinCount = dwSpinCount;
}
//使用InterlockedCompareExchange循环查询m_dwSpinCount次, 看是否能查到
//m_pShareInfo->nLockCount 等于 0
BOOL TestCriticalSection::TryEntry()
{
if (!m_bInit)
return FALSE;
BOOL bOwnCriticalSection = FALSE;
DWORD dwSpinCount = m_dwSpinCount;
DWORD dwCurrentThreadId = GetCurrentThreadId();
while (!bOwnCriticalSection && (dwSpinCount--) > 0)
{
bOwnCriticalSection =
(0 == InterlockedCompareExchange(&(m_pShareInfo->nLockCount), 1, 0) );
//等到了m_pShareInfo->nLockCount == 0
if (bOwnCriticalSection)
{
m_pShareInfo->dwThreadID = dwCurrentThreadId;
m_pShareInfo->nRecurseCount = 1;
ResetEvent(m_hEvent);
}
else
{
if (m_pShareInfo->dwThreadID == dwCurrentThreadId)
{
InterlockedIncrement(&(m_pShareInfo->nLockCount));
m_pShareInfo->nRecurseCount++;
}
}
}
return bOwnCriticalSection;
}
void TestCriticalSection::Entry()
{
if (TryEntry())
return;
DWORD dwThreadId = GetCurrentThreadId();
if (InterlockedIncrement(&(m_pShareInfo->nLockCount)) == 1)
{
m_pShareInfo->dwThreadID = dwThreadId;
m_pShareInfo->nRecurseCount = 1;
ResetEvent(m_hEvent);
}
else
{
//使用事件来等待,进入了内核区
WaitForSingleObject(m_hEvent, -1);
m_pShareInfo->dwThreadID = dwThreadId;
m_pShareInfo->nRecurseCount = 1;
}
}
void TestCriticalSection::Leave()
{
if (!m_bInit)
return;
if (--(m_pShareInfo->nRecurseCount) > 0)
{
InterlockedDecrement(&(m_pShareInfo->nLockCount));
}
else
{
//表明线程调用N次Entry,最后一次调用Leave()
m_pShareInfo->dwThreadID = 0;
SetEvent(m_hEvent);
InterlockedDecrement(&(m_pShareInfo->nLockCount));
}
}