windows-nt/Source/XPSP1/NT/admin/wmi/wbem/winmgmt/wbemcomn/sync.h
2020-09-26 16:20:57 +08:00

321 lines
6.2 KiB
C++

/*++
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>
class POLARITY CCritSec : public CRITICAL_SECTION
{
public:
CCritSec()
{
__try
{
InitializeCriticalSection(this);
}
__except( GetExceptionCode() == STATUS_NO_MEMORY )
{
throw CX_MemoryException();
}
}
~CCritSec()
{
DeleteCriticalSection(this);
}
void Enter()
{
__try
{
EnterCriticalSection(this);
}
__except( GetExceptionCode() == STATUS_NO_MEMORY )
{
throw CX_MemoryException();
}
}
void Leave()
{
LeaveCriticalSection(this);
}
};
class POLARITY CTryCritSec
{
protected:
CCritSec m_cs;
CCritSec m_csControl;
long m_lCount;
public:
CTryCritSec() : m_lCount(0){}
void Enter()
{
EnterCriticalSection(&m_csControl);
m_lCount++;
LeaveCriticalSection(&m_csControl);
EnterCriticalSection(&m_cs);
}
void Leave()
{
LeaveCriticalSection(&m_cs);
EnterCriticalSection(&m_csControl);
m_lCount--;
LeaveCriticalSection(&m_csControl);
}
BOOL TryEnter()
{
EnterCriticalSection(&m_csControl);
if(m_lCount > 0)
{
LeaveCriticalSection(&m_csControl);
return FALSE;
}
else
{
EnterCriticalSection(&m_cs);
m_lCount++;
LeaveCriticalSection(&m_csControl);
return TRUE;
}
}
};
class POLARITY CInCritSec
{
protected:
CRITICAL_SECTION* m_pcs;
public:
CInCritSec(CRITICAL_SECTION* pcs) : m_pcs(pcs)
{
__try
{
EnterCriticalSection(m_pcs);
}
__except( GetExceptionCode() == STATUS_NO_MEMORY )
{
throw CX_MemoryException();
}
}
inline ~CInCritSec()
{
LeaveCriticalSection(m_pcs);
}
};
class POLARITY CInTryCritSec
{
protected:
CTryCritSec* m_ptcs;
public:
CInTryCritSec(CTryCritSec* ptcs) : m_ptcs(ptcs)
{
m_ptcs->Enter();
}
~CInTryCritSec()
{
m_ptcs->Leave();
}
};
// Allows user to manually leave critical section, checks if inside before leaving
class POLARITY CCheckedInCritSec
{
protected:
CRITICAL_SECTION* m_pcs;
BOOL m_fInside;
public:
CCheckedInCritSec(CRITICAL_SECTION* pcs) : m_pcs(pcs), m_fInside( FALSE )
{
EnterCriticalSection(m_pcs);
m_fInside = TRUE;
}
~CCheckedInCritSec()
{
Leave();
}
void Enter( void )
{
if ( !m_fInside )
{
EnterCriticalSection(m_pcs);
m_fInside = TRUE;
}
}
void Leave( void )
{
if ( m_fInside )
{
m_fInside = FALSE;
LeaveCriticalSection(m_pcs);
}
}
BOOL IsEntered( void )
{ return m_fInside; }
};
//
// This class implements a light-weight exclusive lock. Critical sections are
// not very good for this because they:
// 1) Do not allow lock/unlock to occur on different threads
// 2) Do not admit timeouts
//
// On the flip side, this guy is intentionally non-reentrant.
// TBD: efficiency
//
class POLARITY CSimpleLock
{
protected:
HANDLE m_hEvent;
DWORD m_dwOwningThread;
long m_lWaiting;
bool m_bLocked;
CCritSec m_cs;
public:
CSimpleLock();
~CSimpleLock();
DWORD Enter(DWORD dwTimeout = INFINITE);
void Leave();
};
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; }
};
class POLARITY CScopeLock
{
private:
long* m_plVal;
public:
CScopeLock( long* plVal ) : m_plVal( plVal )
{ if ( NULL != m_plVal ) InterlockedIncrement( m_plVal ); }
~CScopeLock()
{ if ( NULL != m_plVal ) InterlockedDecrement( m_plVal ); }
};
#endif