234 lines
4.2 KiB
C
234 lines
4.2 KiB
C
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1997.
|
||
|
//
|
||
|
// File: critsect.h
|
||
|
//
|
||
|
// Contents: critical section helper class
|
||
|
//
|
||
|
// Classes: CCriticalSection
|
||
|
// CLockHandler
|
||
|
// CLock
|
||
|
//
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
// History: 13-Nov-97 rogerg Created.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
|
||
|
#ifndef _CRITSECT_
|
||
|
#define _CRITSECT_
|
||
|
|
||
|
#include "widewrap.h"
|
||
|
|
||
|
class CLock;
|
||
|
|
||
|
class CCriticalSection
|
||
|
{
|
||
|
DWORD cRefs;
|
||
|
CRITICAL_SECTION *m_pcsect;
|
||
|
DWORD m_dwThreadID;
|
||
|
|
||
|
public:
|
||
|
inline CCriticalSection(CRITICAL_SECTION *pcsect,DWORD dwThreadID)
|
||
|
{
|
||
|
m_pcsect = pcsect;
|
||
|
cRefs = 0;
|
||
|
m_dwThreadID = dwThreadID;
|
||
|
};
|
||
|
|
||
|
|
||
|
inline ~CCriticalSection()
|
||
|
{
|
||
|
AssertSz(0 == cRefs,"UnReleased Critical Section");
|
||
|
Assert(m_dwThreadID == GetCurrentThreadId());
|
||
|
|
||
|
while(cRefs--) // unwind any left over cRefs
|
||
|
{
|
||
|
LeaveCriticalSection(m_pcsect);
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
inline void Enter()
|
||
|
{
|
||
|
EnterCriticalSection(m_pcsect);
|
||
|
|
||
|
Assert(m_dwThreadID == GetCurrentThreadId());
|
||
|
++cRefs;
|
||
|
|
||
|
Assert(1 == cRefs); // we don't allow nested calls.
|
||
|
};
|
||
|
|
||
|
inline void Leave()
|
||
|
{
|
||
|
Assert(m_dwThreadID == GetCurrentThreadId());
|
||
|
Assert(0 < cRefs);
|
||
|
|
||
|
if (0 >= cRefs)
|
||
|
return;
|
||
|
|
||
|
--cRefs;
|
||
|
Assert(0 == cRefs);
|
||
|
|
||
|
LeaveCriticalSection(m_pcsect);
|
||
|
};
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
class CLockHandler {
|
||
|
|
||
|
public:
|
||
|
CLockHandler();
|
||
|
~CLockHandler();
|
||
|
|
||
|
void Lock(DWORD dwThreadId);
|
||
|
void UnLock();
|
||
|
inline DWORD GetLockThreadId() { return m_dwLockThreadId; };
|
||
|
|
||
|
private:
|
||
|
CRITICAL_SECTION m_CriticalSection; // critical section for the queue.
|
||
|
DWORD m_dwLockThreadId; // thread that has the lock.
|
||
|
|
||
|
friend CLock;
|
||
|
};
|
||
|
|
||
|
|
||
|
// helper class for making sure locks on the queue are released.
|
||
|
class CLock
|
||
|
{
|
||
|
DWORD cRefs;
|
||
|
CLockHandler *m_pLockHandler;
|
||
|
DWORD m_dwThreadID;
|
||
|
|
||
|
public:
|
||
|
inline CLock(CLockHandler *pLockHandler)
|
||
|
{
|
||
|
m_pLockHandler = pLockHandler;
|
||
|
cRefs = 0;
|
||
|
m_dwThreadID = GetCurrentThreadId();
|
||
|
};
|
||
|
|
||
|
|
||
|
inline ~CLock()
|
||
|
{
|
||
|
AssertSz(0 == cRefs,"UnReleased Lock");
|
||
|
Assert(m_dwThreadID == GetCurrentThreadId());
|
||
|
|
||
|
while(cRefs--) // unwind any left over cRefs
|
||
|
{
|
||
|
m_pLockHandler->UnLock();
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
inline void Enter()
|
||
|
{
|
||
|
Assert(m_dwThreadID == GetCurrentThreadId());
|
||
|
|
||
|
++cRefs;
|
||
|
Assert(1 == cRefs); // we don't allow nested calls.
|
||
|
m_pLockHandler->Lock(m_dwThreadID);
|
||
|
};
|
||
|
|
||
|
inline void Leave()
|
||
|
{
|
||
|
Assert(m_dwThreadID == GetCurrentThreadId());
|
||
|
Assert(0 < cRefs);
|
||
|
|
||
|
if (0 >= cRefs)
|
||
|
return;
|
||
|
|
||
|
--cRefs;
|
||
|
Assert(0 == cRefs);
|
||
|
m_pLockHandler->UnLock();
|
||
|
|
||
|
};
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
#define ASSERT_LOCKHELD(pLockHandler) Assert(pLockHandler->GetLockThreadId() == GetCurrentThreadId());
|
||
|
#define ASSERT_LOCKNOTHELD(pLockHandler) Assert(pLockHandler->GetLockThreadId() == 0);
|
||
|
|
||
|
// helper class for Mutex locking
|
||
|
|
||
|
class CMutex
|
||
|
{
|
||
|
HANDLE m_hMutex;
|
||
|
BOOL m_fHasLock;
|
||
|
BOOL m_fReleasedLock;
|
||
|
|
||
|
public:
|
||
|
inline CMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes,BOOL bInitialOwner,LPCTSTR lpName)
|
||
|
{
|
||
|
m_hMutex = CreateMutex(lpMutexAttributes,bInitialOwner,lpName);
|
||
|
|
||
|
// on failure routines go on just don't take the lock
|
||
|
|
||
|
m_fHasLock = FALSE;
|
||
|
m_fReleasedLock = FALSE;
|
||
|
};
|
||
|
|
||
|
|
||
|
inline ~CMutex()
|
||
|
{
|
||
|
AssertSz(!m_fHasLock,"UnReleased Mutex ");
|
||
|
|
||
|
// if failed to release mutex release now.
|
||
|
if (m_hMutex && m_fHasLock)
|
||
|
{
|
||
|
ReleaseMutex(m_hMutex);
|
||
|
}
|
||
|
if (m_hMutex)
|
||
|
{
|
||
|
CloseHandle(m_hMutex);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
inline void Enter(DWORD dwMilliseconds = INFINITE)
|
||
|
{
|
||
|
AssertSz(!m_fHasLock,"Tried to take Lock Twice");
|
||
|
AssertSz(!m_fReleasedLock,"Tried to take lock After Released Mutex");
|
||
|
|
||
|
if (!m_fHasLock && m_hMutex)
|
||
|
{
|
||
|
if (WAIT_OBJECT_0 ==WaitForSingleObject( m_hMutex, dwMilliseconds ))
|
||
|
{
|
||
|
m_fHasLock = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
inline void Leave()
|
||
|
{
|
||
|
Assert(m_fHasLock);
|
||
|
|
||
|
if (m_fHasLock && m_hMutex)
|
||
|
{
|
||
|
ReleaseMutex(m_hMutex);
|
||
|
}
|
||
|
|
||
|
if (m_hMutex)
|
||
|
{
|
||
|
CloseHandle(m_hMutex);
|
||
|
}
|
||
|
m_hMutex = NULL;
|
||
|
m_fHasLock = FALSE;
|
||
|
m_fReleasedLock = TRUE;
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
#endif // _CRITSECT_
|