You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
255 lines
5.8 KiB
255 lines
5.8 KiB
/*++
|
|
|
|
Copyright (C) 1996-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
SYNC.H
|
|
|
|
Abstract:
|
|
|
|
Synchronization
|
|
|
|
History:
|
|
|
|
--*/
|
|
|
|
#ifndef __WBEM_CRITSEC__H_
|
|
#define __WBEM_CRITSEC__H_
|
|
|
|
#include "corepol.h"
|
|
#include <corex.h>
|
|
|
|
#ifndef STATUS_POSSIBLE_DEADLOCK
|
|
#define STATUS_POSSIBLE_DEADLOCK (0xC0000194L)
|
|
#endif /*STATUS_POSSIBLE_DEADLOCK */
|
|
|
|
DWORD POLARITY BreakOnDbgAndRenterLoop(void);
|
|
|
|
class POLARITY CCritSec : public CRITICAL_SECTION
|
|
{
|
|
public:
|
|
CCritSec()
|
|
{
|
|
#ifdef _WIN32_WINNT
|
|
#if _WIN32_WINNT > 0x0400
|
|
bool initialized = (InitializeCriticalSectionAndSpinCount(this,0))?true:false;
|
|
if (!initialized) throw CX_MemoryException();
|
|
#else
|
|
bool initialized = false;
|
|
__try
|
|
{
|
|
InitializeCriticalSection(this);
|
|
initialized = true;
|
|
}
|
|
__except(GetExceptionCode() == STATUS_NO_MEMORY)
|
|
{
|
|
}
|
|
if (!initialized) throw CX_MemoryException();
|
|
#endif
|
|
#else
|
|
bool initialized = false;
|
|
__try
|
|
{
|
|
InitializeCriticalSection(this);
|
|
initialized = true;
|
|
}
|
|
__except(GetExceptionCode() == STATUS_NO_MEMORY)
|
|
{
|
|
}
|
|
if (!initialized) throw CX_MemoryException();
|
|
#endif
|
|
}
|
|
|
|
~CCritSec()
|
|
{
|
|
DeleteCriticalSection(this);
|
|
}
|
|
|
|
void Enter()
|
|
{
|
|
__try {
|
|
EnterCriticalSection(this);
|
|
} __except((STATUS_POSSIBLE_DEADLOCK == GetExceptionCode())? BreakOnDbgAndRenterLoop():EXCEPTION_CONTINUE_SEARCH) {
|
|
}
|
|
}
|
|
|
|
void Leave()
|
|
{
|
|
LeaveCriticalSection(this);
|
|
}
|
|
};
|
|
|
|
|
|
class POLARITY CInCritSec
|
|
{
|
|
protected:
|
|
CRITICAL_SECTION* m_pcs;
|
|
public:
|
|
CInCritSec(CRITICAL_SECTION* pcs) : m_pcs(pcs)
|
|
{
|
|
__try {
|
|
EnterCriticalSection(m_pcs);
|
|
} __except((STATUS_POSSIBLE_DEADLOCK == GetExceptionCode())? BreakOnDbgAndRenterLoop():EXCEPTION_CONTINUE_SEARCH) {
|
|
}
|
|
}
|
|
inline ~CInCritSec()
|
|
{
|
|
LeaveCriticalSection(m_pcs);
|
|
}
|
|
};
|
|
|
|
|
|
// Allows user to manually leave critical section, checks if inside before leaving
|
|
class POLARITY CCheckedInCritSec
|
|
{
|
|
protected:
|
|
CCritSec* m_pcs;
|
|
BOOL m_fInside;
|
|
public:
|
|
CCheckedInCritSec(CCritSec* pcs) : m_pcs(pcs), m_fInside( FALSE )
|
|
{
|
|
m_pcs->Enter();
|
|
m_fInside = TRUE;
|
|
}
|
|
~CCheckedInCritSec()
|
|
{
|
|
Leave();
|
|
}
|
|
|
|
void Enter( void )
|
|
{
|
|
if ( !m_fInside )
|
|
{
|
|
m_pcs->Enter();
|
|
m_fInside = TRUE;
|
|
}
|
|
}
|
|
|
|
void Leave( void )
|
|
{
|
|
if ( m_fInside )
|
|
{
|
|
m_pcs->Leave();
|
|
m_fInside = FALSE;
|
|
}
|
|
}
|
|
|
|
BOOL IsEntered( void )
|
|
{ return m_fInside; }
|
|
};
|
|
|
|
|
|
//
|
|
// Local wrapper class. Does not initialize or clean up the critsec. Simply
|
|
// used as a wrapper for scoping so that AV and exception stack unwinding will
|
|
// cause the critsec to be exited properly once it is entered.
|
|
//
|
|
/////////////////////////////////////////////////////////
|
|
|
|
class CCritSecWrapper
|
|
{
|
|
BOOL m_bIn;
|
|
CCritSec *m_pcs;
|
|
public:
|
|
CCritSecWrapper(CCritSec *pcs) { m_pcs = pcs; m_bIn = FALSE; }
|
|
~CCritSecWrapper() { if (m_bIn) m_pcs->Leave(); }
|
|
void Enter() { m_pcs->Enter(); m_bIn = TRUE; }
|
|
void Leave() { m_pcs->Leave(); m_bIn = FALSE; }
|
|
};
|
|
|
|
|
|
class POLARITY CHaltable
|
|
{
|
|
public:
|
|
CHaltable();
|
|
virtual ~CHaltable();
|
|
HRESULT Halt();
|
|
HRESULT Resume();
|
|
HRESULT ResumeAll();
|
|
HRESULT WaitForResumption();
|
|
BOOL IsHalted();
|
|
bool isValid();
|
|
|
|
private:
|
|
CCritSec m_csHalt;
|
|
HANDLE m_hReady;
|
|
DWORD m_dwHaltCount;
|
|
long m_lJustResumed;
|
|
};
|
|
|
|
inline bool
|
|
CHaltable::isValid()
|
|
{ return m_hReady != NULL; };
|
|
|
|
// This class is designed to provide the behavior of a critical section,
|
|
// but without any of that pesky Kernel code. In some circumstances, we
|
|
// need to lock resources across multiple threads (i.e. we lock on one
|
|
// thread and unlock on another). If we do this using a critical section,
|
|
// this appears to work, but in checked builds, we end up throwing an
|
|
// exception. Since we actually need to do this (for example using NextAsync
|
|
// in IEnumWbemClassObject) this class can be used to perform the
|
|
// operation, but without causing exceptions in checked builds.
|
|
|
|
// Please note that code that is going to do this MUST ensure that we don't
|
|
// get crossing Enter/Leave operations (in other words, it's responsible for
|
|
// synchronizing the Enter and Leave operations.) Please note that this
|
|
// is a dangerous thing to do, so be VERY careful if you are using this
|
|
// code for that purpose.
|
|
|
|
class POLARITY CWbemCriticalSection
|
|
{
|
|
private:
|
|
|
|
long m_lLock;
|
|
long m_lRecursionCount;
|
|
DWORD m_dwThreadId;
|
|
HANDLE m_hEvent;
|
|
|
|
public:
|
|
|
|
CWbemCriticalSection();
|
|
~CWbemCriticalSection();
|
|
|
|
BOOL Enter( DWORD dwTimeout = INFINITE );
|
|
void Leave( void );
|
|
|
|
DWORD GetOwningThreadId( void )
|
|
{ return m_dwThreadId; }
|
|
|
|
long GetLockCount( void )
|
|
{ return m_lLock; }
|
|
|
|
long GetRecursionCount( void )
|
|
{ return m_lRecursionCount; }
|
|
|
|
};
|
|
|
|
class POLARITY CEnterWbemCriticalSection
|
|
{
|
|
CWbemCriticalSection* m_pcs;
|
|
BOOL m_fInside;
|
|
public:
|
|
|
|
CEnterWbemCriticalSection( CWbemCriticalSection* pcs, DWORD dwTimeout = INFINITE )
|
|
: m_pcs( pcs ), m_fInside( FALSE )
|
|
{
|
|
if ( m_pcs )
|
|
{
|
|
m_fInside = m_pcs->Enter( dwTimeout );
|
|
}
|
|
}
|
|
|
|
~CEnterWbemCriticalSection( void )
|
|
{
|
|
if ( m_fInside )
|
|
{
|
|
m_pcs->Leave();
|
|
}
|
|
}
|
|
|
|
BOOL IsEntered( void )
|
|
{ return m_fInside; }
|
|
};
|
|
|
|
#endif
|