📄 optex.cpp
字号:
/******************************************************************************Module name: Optex.cppWritten by: Jeffrey RichterPurpose: Implements the COptex (optimized mutex) synchronization object******************************************************************************///#include "CmnHdr.h"#include "StdAfx.h"#include "Optex.h"//////////////////////////// Assert/Verify Macros /////////////////////////////#define chFAIL(szMSG) { \ MessageBox(GetActiveWindow(), szMSG, \ __TEXT("Assertion Failed"), MB_OK | MB_ICONERROR); \ DebugBreak(); \ }// Put up an assertion failure message box.#define chASSERTFAIL(file,line,expr) { \ TCHAR sz[128]; \ wsprintf(sz, __TEXT("File %hs, line %d : %hs"), file, line, expr); \ chFAIL(sz); \ }// Put up a message box if an assertion fails in a debug build.#ifdef _DEBUG#define chASSERT(x) if (!(x)) chASSERTFAIL(__FILE__, __LINE__, #x)#else#define chASSERT(x)#endif// Assert in debug builds, but don't remove the code in retail builds.#ifdef _DEBUG#define chVERIFY(x) chASSERT(x)#else#define chVERIFY(x) (x)#endif///////////////////////////////////////////////////////////////////////////////BOOL COptex::CommonConstructor(PVOID pszName, BOOL fUnicode, DWORD dwSpinCount) { m_hevt = m_hfm = NULL; m_pSharedInfo = NULL; SYSTEM_INFO sinf; GetSystemInfo(&sinf); m_fUniprocessorHost = (sinf.dwNumberOfProcessors == 1); char szNameA[100]; if (fUnicode) { // Convert Unicode name to ANSI wsprintfA(szNameA, "%S", pszName); pszName = (PVOID) szNameA; } char sz[100]; wsprintfA(sz, "JMR_Optex_Event_%s", pszName); m_hevt = CreateEventA(NULL, FALSE, FALSE, sz); chASSERT(m_hevt != NULL); if (m_hevt != NULL) { wsprintfA(sz, "JMR_Optex_MMF_%s", pszName); m_hfm = CreateFileMappingA((HANDLE) 0xFFFFFFFF, NULL, PAGE_READWRITE, 0, sizeof(*m_pSharedInfo), sz); chASSERT(m_hfm != NULL); if (m_hfm != NULL) { m_pSharedInfo = (PSHAREDINFO) MapViewOfFile(m_hfm, FILE_MAP_WRITE, 0, 0, 0); // 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. if (m_pSharedInfo != NULL) SetSpinCount(dwSpinCount); } } return((m_hevt != NULL) && (m_hfm != NULL) && (m_pSharedInfo != NULL));}///////////////////////////////////////////////////////////////////////////////COptex::~COptex() {#ifdef _DEBUG if (m_pSharedInfo->m_dwThreadId == GetCurrentThreadId()) DebugBreak();#endif UnmapViewOfFile(m_pSharedInfo); CloseHandle(m_hfm); CloseHandle(m_hevt);}///////////////////////////////////////////////////////////////////////////////void COptex::SetSpinCount(DWORD dwSpinCount) { if (!m_fUniprocessorHost) InterlockedExchange((LPLONG) &m_pSharedInfo->m_dwSpinCount, dwSpinCount);}///////////////////////////////////////////////////////////////////////////////void COptex::Enter() { // Spin, trying to get the Optex if (TryEnter()) return; DWORD dwThreadId = GetCurrentThreadId(); // The calling thread's ID if (InterlockedIncrement(&m_pSharedInfo->m_lLockCount) == 1) { // Optex is unowned, let this thread own it once InterlockedExchange((LPLONG) &m_pSharedInfo->m_dwThreadId, dwThreadId); m_pSharedInfo->m_lRecurseCount = 1; } else { // Optex is owned by a thread if (m_pSharedInfo->m_dwThreadId == dwThreadId) { // Optex is owned by this thread, own it again m_pSharedInfo->m_lRecurseCount++; } else { // Optex is owned by another thread // Wait for the owning thread to release the Optex WaitForSingleObject(m_hevt, INFINITE); // We got ownership of the Optex InterlockedExchange((LPLONG) &m_pSharedInfo->m_dwThreadId, dwThreadId); // We own it now m_pSharedInfo->m_lRecurseCount = 1; // We own it once } }}///////////////////////////////////////////////////////////////////////////////BOOL COptex::TryEnter() { DWORD dwThreadId = GetCurrentThreadId(); // The calling thread's ID // If the lock count is zero, the Optex is unowned and // this thread can become the owner of it now. BOOL fThisThreadOwnsTheOptex = FALSE; DWORD dwSpinCount = m_pSharedInfo->m_dwSpinCount; do { // If you get a compiler error here, make sure that the include-file for the SDK // has a higher priority than the include-files for MSVC98! It looks like the // declaration for this function has changed. fThisThreadOwnsTheOptex = (0 == (DWORD) InterlockedCompareExchange((LPLONG) &m_pSharedInfo->m_lLockCount, (LONG) 1, (LONG) 0)); if (fThisThreadOwnsTheOptex) { // We now own the Optex InterlockedExchange((LPLONG) &m_pSharedInfo->m_dwThreadId, dwThreadId); // We own it m_pSharedInfo->m_lRecurseCount = 1; // We own it once } else { // Some thread owns the Optex if (m_pSharedInfo->m_dwThreadId == dwThreadId) { // We already own the Optex InterlockedIncrement(&m_pSharedInfo->m_lLockCount); m_pSharedInfo->m_lRecurseCount++; // We own it again fThisThreadOwnsTheOptex = TRUE; // Return that we own the Optex } } } while (!fThisThreadOwnsTheOptex && (dwSpinCount-- > 0)); // Return whether or not this thread owns the Optex return(fThisThreadOwnsTheOptex);}///////////////////////////////////////////////////////////////////////////////void COptex::Leave() {#ifdef _DEBUG if (m_pSharedInfo->m_dwThreadId != GetCurrentThreadId()) DebugBreak();#endif if (--m_pSharedInfo->m_lRecurseCount > 0) { // We still own the Optex InterlockedDecrement(&m_pSharedInfo->m_lLockCount); } else { // We don't own the Optex InterlockedExchange((LPLONG) &m_pSharedInfo->m_dwThreadId, 0); if (InterlockedDecrement(&m_pSharedInfo->m_lLockCount) > 0) { // Other threads are waiting, wake one of them SetEvent(m_hevt); } }}///////////////////////////////// End of File /////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -