⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 optex.cpp

📁 《windows 核心编程》的书中的源代码。希望对学习windows编程有帮助。
💻 CPP
字号:
/******************************************************************************
Module:  Optex.cpp
Notices: Copyright (c) 2000 Jeffrey Richter
******************************************************************************/


#include "..\CmnHdr.h"     /* See Appendix A. */
#include "Optex.h"


///////////////////////////////////////////////////////////////////////////////


// 0=multi-CPU, 1=single-CPU, -1=not set yet
BOOL COptex::sm_fUniprocessorHost = -1;


///////////////////////////////////////////////////////////////////////////////


PSTR COptex::ConstructObjectName(PSTR pszResult, 
   PCSTR pszPrefix, BOOL fUnicode, PVOID pszName) {

   pszResult[0] = 0;
   if (pszName == NULL) 
      return(NULL);

   wsprintfA(pszResult, fUnicode ? "%s%S" : "%s%s", pszPrefix, pszName);
   return(pszResult);
}


///////////////////////////////////////////////////////////////////////////////


void COptex::CommonConstructor(DWORD dwSpinCount, 
   BOOL fUnicode, PVOID pszName) {

   if (sm_fUniprocessorHost == -1) {
      // This is the 1st object constructed, get the number of CPUs
      SYSTEM_INFO sinf;
      GetSystemInfo(&sinf);
      sm_fUniprocessorHost = (sinf.dwNumberOfProcessors == 1);
   }


   m_hevt = m_hfm = NULL;
   m_psi  = NULL;

   if (pszName == NULL) {  // Creating a single-process optex

      m_hevt = CreateEventA(NULL, FALSE, FALSE, NULL);
      chASSERT(m_hevt != NULL);

      m_psi = new SHAREDINFO;
      chASSERT(m_psi != NULL);
      ZeroMemory(m_psi, sizeof(*m_psi));

   } else {                // Creating a cross-process optex

      // Always use ANSI so that this works on Win9x and Windows 2000
      char szResult[100];
      ConstructObjectName(szResult, "Optex_Event_", fUnicode, pszName);
      m_hevt = CreateEventA(NULL, FALSE, FALSE, szResult);
      chASSERT(m_hevt != NULL);

      ConstructObjectName(szResult, "Optex_MMF_", fUnicode, pszName);
      m_hfm = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, 
         PAGE_READWRITE, 0, sizeof(*m_psi), szResult);
      chASSERT(m_hfm != NULL);

      m_psi = (PSHAREDINFO) MapViewOfFile(m_hfm, 
         FILE_MAP_WRITE, 0, 0, 0);
      chASSERT(m_psi != NULL);

      // Note: SHAREDINFO's m_lLockCount, m_dwThreadId, and m_lRecurseCount
      // members need to be initialized to 0. Fortunately, a new pagefile 
      // MMF sets all of its data to 0 when created. This saves use from 
      // some thread synchronization work.
   }

   SetSpinCount(dwSpinCount);
}


///////////////////////////////////////////////////////////////////////////////


COptex::~COptex() {

#ifdef _DEBUG
   if (IsSingleProcessOptex() && (m_psi->m_dwThreadId != 0)) {
      // A single-process optex shouldn't be destroyed if any thread owns it
      DebugBreak();
   }

   if (!IsSingleProcessOptex() && 
      (m_psi->m_dwThreadId == GetCurrentThreadId())) {

      // A cross-process optex shouldn't be destroyed if our thread owns it
      DebugBreak();
   }
#endif

   CloseHandle(m_hevt);

   if (IsSingleProcessOptex()) {
      delete m_psi;
   } else {
      UnmapViewOfFile(m_psi);
      CloseHandle(m_hfm);
   }
}


///////////////////////////////////////////////////////////////////////////////


void COptex::SetSpinCount(DWORD dwSpinCount) {

   // No spinning on single CPU machines
   if (!sm_fUniprocessorHost)
      InterlockedExchangePointer((PVOID*) &m_psi->m_dwSpinCount, 
        (PVOID) (DWORD_PTR) dwSpinCount);
}


///////////////////////////////////////////////////////////////////////////////


void COptex::Enter() {

   // Spin, trying to get the optex
   if (TryEnter()) 
      return;  // We got it, return

   // We couldn't get the optex, wait for it.
   DWORD dwThreadId = GetCurrentThreadId();

   if (InterlockedIncrement(&m_psi->m_lLockCount) == 1) {

      // Optex is unowned, let this thread own it once
      m_psi->m_dwThreadId = dwThreadId;
      m_psi->m_lRecurseCount = 1;

   } else {

      if (m_psi->m_dwThreadId == dwThreadId) {

         // If optex is owned by this thread, own it again
         m_psi->m_lRecurseCount++;

      } else {

         // Optex is owned by another thread, wait for it
         WaitForSingleObject(m_hevt, INFINITE);

         // Optex is unowned, let this thread own it once
         m_psi->m_dwThreadId = dwThreadId;
         m_psi->m_lRecurseCount = 1;
      }
   }
}


///////////////////////////////////////////////////////////////////////////////


BOOL COptex::TryEnter() {

   DWORD dwThreadId = GetCurrentThreadId();

   BOOL fThisThreadOwnsTheOptex = FALSE;     // Assume a thread owns the optex
   DWORD dwSpinCount = m_psi->m_dwSpinCount; // How many times to spin

   do {
      // If lock count = 0, optex is unowned, we can own it
      fThisThreadOwnsTheOptex = (0 == 
         InterlockedCompareExchange(&m_psi->m_lLockCount, 1, 0)); 

      if (fThisThreadOwnsTheOptex) {

         // Optex is unowned, let this thread own it once
         m_psi->m_dwThreadId = dwThreadId;
         m_psi->m_lRecurseCount = 1;

      } else {

         if (m_psi->m_dwThreadId == dwThreadId) {

            // If optex is owned by this thread, own it again
            InterlockedIncrement(&m_psi->m_lLockCount);
            m_psi->m_lRecurseCount++;
            fThisThreadOwnsTheOptex = TRUE;
         }
      }

   } while (!fThisThreadOwnsTheOptex && (dwSpinCount-- > 0));

   // Return whether or not this thread owns the optex
   return(fThisThreadOwnsTheOptex);
}


///////////////////////////////////////////////////////////////////////////////


void COptex::Leave() {

#ifdef _DEBUG
   // Only the owning thread can leave the optex
   if (m_psi->m_dwThreadId != GetCurrentThreadId()) 
      DebugBreak();
#endif

   // Reduce this thread's ownership of the optex
   if (--m_psi->m_lRecurseCount > 0) {

      // We still own the optex
      InterlockedDecrement(&m_psi->m_lLockCount);

   } else {

      // We don't own the optex anymore
      m_psi->m_dwThreadId = 0;

      if (InterlockedDecrement(&m_psi->m_lLockCount) > 0) {

         // Other threads are waiting, the auto-reset event wakes one of them
         SetEvent(m_hevt);
      }
   }
}


//////////////////////////////// End of File //////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -