使用interlocked模仿CriticalSection 抄> 我加了注释

来源:互联网 发布:投诉淘宝卖家有啥后果 编辑:程序博客网 时间:2024/04/29 11:35

#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));
 }
}

原创粉丝点击