Source code of Windows XP (NT5)
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.
|
|
// CResGuard
// CSysGlobalType
// CSysGlobalScalar
// CInterlockedType
// CInverseSemaphore
#ifndef __SYSGLOB_H__
#define __SYSGLOB_H__
#include <assert.h>
// Instances of this class will be accessed by mutiple threads. So,
// all members of this class (except the constructor and destructor)
// must be thread-safe.
class CResGuard { private: HANDLE m_hMutex; long m_lGrdCnt; // # of C calls
public:
CResGuard(void * pObjectAddr) { TCHAR szObjectName[32]; wsprintf(szObjectName, TEXT("CResGuard :: %08X"), (DWORD) pObjectAddr); m_lGrdCnt = 0; m_hMutex = CreateMutex(NULL, FALSE, szObjectName); assert(m_hMutex); } ~CResGuard() { CloseHandle(m_hMutex); }
// IsGuarded is used for debugging
BOOL IsGuarded() const { return(m_lGrdCnt > 0); }
public: class CGuard { private:
CResGuard& m_rg;
public:
CGuard(CResGuard& rg) : m_rg(rg) { m_rg.Guard(); };
~CGuard() { m_rg.Unguard(); }
};
private:
void Guard() { assert(WAIT_OBJECT_0 == WaitForSingleObject(m_hMutex, INFINITE)); m_lGrdCnt++; } void Unguard() { m_lGrdCnt--; ReleaseMutex(m_hMutex); }
// Guard/Unguard can only be accessed by the nested CGuard class.
friend class CResGuard::CGuard; };
// Instances of this class will be accessed by mutiple threads. So,
// all members of this class (except the constructor and destructor)
// must be thread-safe.
template <class TYPE> class CInterlockedType { private:
TYPE * m_pTVal;
protected: mutable CResGuard m_rg;
public:
// Public member functions
// Note: Constructors & destructors are always thread safe
CInterlockedType(TYPE * const pTVal) : m_rg( pTVal ) { m_pTVal = pTVal; }
virtual ~CInterlockedType() { }
// Cast operator to make writing code that uses
// thread-safe data type easier
operator TYPE() const { CResGuard::CGuard x(m_rg); return(GetVal()); }
protected: // Protected function to be called by derived class
TYPE& GetVal() { assert(m_rg.IsGuarded()); return(*m_pTVal); }
const TYPE& GetVal() const { assert(m_rg.IsGuarded()); return(*m_pTVal); }
TYPE SetVal(const TYPE& TNewVal) { assert(m_rg.IsGuarded()); TYPE& TVal = GetVal(); if (TVal != TNewVal) { TYPE TPrevVal = TVal; TVal = TNewVal; OnValChanged(TNewVal, TPrevVal); } return(TVal); }
protected: // Overridable functions
virtual void OnValChanged(const TYPE& TNewVal, const TYPE& TPrevVal) const { // Nothing to do here
}
};
// Instances of this class will be accessed by mutiple threads. So,
// all members of this class (except the constructor and destructor)
// must be thread-safe.
template <class TYPE> class CSysGlobalScalar : protected CInterlockedType<TYPE> { public: CSysGlobalScalar(TYPE * pTVal) : CInterlockedType<TYPE>(pTVal) { }
~CSysGlobalScalar() { }
// C++ does not allow operator cast to be inherited.
operator TYPE() const { return(CInterlockedType<TYPE>::operator TYPE()); }
TYPE operator=(TYPE TVal) { CResGuard::CGuard x(m_rg); return(SetVal(TVal)); }
TYPE operator++(int) // Postfix increment operator
{ CResGuard::CGuard x(m_rg); TYPE TPrevVal = GetVal(); SetVal(TPrevVal + 1); return(TPrevVal); // Return value BEFORE increment
}
TYPE operator--(int) // Postfix decrement operator.
{ CResGuard::CGuard x(m_rg); TYPE TPrevVal = GetVal(); SetVal(TPrevVal - 1); return(TPrevVal); // Return value BEFORE decrement
}
TYPE operator += (TYPE op) { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() + op)); }
TYPE operator++() { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() + 1)); }
TYPE operator -= (TYPE op) { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() - op)); }
TYPE operator--() { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() - 1)); }
TYPE operator *= (TYPE op) { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() * op)); }
TYPE operator /= (TYPE op) { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() / op)); }
TYPE operator %= (TYPE op) { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() % op)); }
TYPE operator ^= (TYPE op) { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() ^ op)); }
TYPE operator &= (TYPE op) { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() & op)); }
TYPE operator |= (TYPE op) { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() | op)); }
TYPE operator <<=(TYPE op) { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() << op)); }
TYPE operator >>=(TYPE op) { CResGuard::CGuard x(m_rg); return(SetVal(GetVal() >> op)); } };
// CSysGlobalHandle
//
// Same as CSysGlobalScalar, but without all the operators that would
// work on only scalars
template <class TYPE> class CSysGlobalHandle : protected CInterlockedType<TYPE> { public: CSysGlobalHandle(TYPE * pTVal) : CInterlockedType<TYPE>(pTVal) { }
~CSysGlobalHandle() { }
// C++ does not allow operator cast to be inherited.
operator TYPE() const { return(CInterlockedType<TYPE>::operator TYPE()); }
TYPE operator=(TYPE TVal) { CResGuard::CGuard x(m_rg); return(SetVal(TVal)); }
};
// Instances of this class will be accessed by mutiple threads. So,
// all members of this class (except the constructor and destructor)
// must be thread-safe.
template <class TYPE> class CInverseSemaphore : public CSysGlobalScalar<TYPE> { public:
CInverseSemaphore(TYPE * pTVal, BOOL fManualReset = TRUE) : CSysGlobalScalar<TYPE>(pTVal) { // The event should be signaled if TVal is 0
m_hevtZero = CreateEvent(NULL, fManualReset, (*pTVal == 0), NULL);
// The event should be signaled if TVal is NOT 0
m_hevtNotZero = CreateEvent(NULL, fManualReset, (*pTVal != 0), NULL); }
~CInverseSemaphore() { CloseHandle(m_hevtZero); CloseHandle(m_hevtNotZero); }
// C++ does not allow operator= to be inherited.
TYPE operator=(TYPE x) { return(CSysGlobalScalar<TYPE>::operator=(x)); }
// Return handle to event signaled when value is zero
operator HANDLE() const { return(m_hevtZero); }
// Return handle to event signaled when value is not zero
HANDLE GetNotZeroHandle() const { return(m_hevtNotZero); }
// C++ does not allow operator cast to be inherited.
operator TYPE() const { return(CSysGlobalScalar<TYPE>::operator TYPE()); }
protected: void OnValChanged(const TYPE& TNewVal, const TYPE& TPrevVal) const { // For best performance, avoid jumping to
// kernel mode if we don't have to
if ((TNewVal == 0) && (TPrevVal != 0)) { SetEvent(m_hevtZero); ResetEvent(m_hevtNotZero); } if ((TNewVal != 0) && (TPrevVal == 0)) { ResetEvent(m_hevtZero); SetEvent(m_hevtNotZero); } }
private: HANDLE m_hevtZero; // Signaled when data value is 0
HANDLE m_hevtNotZero; // Signaled when data value is not 0
};
#endif // __SYSGLOB_H__
|