Leaked source code of windows server 2003
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.
 
 
 
 
 
 

578 lines
12 KiB

/*++
Copyright (C) Microsoft Corporation, 1996 - 1999
Module Name:
Locks
Abstract:
This module provides the definitions of common lock objects.
Author:
Doug Barlow (dbarlow) 10/24/1996
Environment:
Win32, C++ w/ exceptions
Notes:
?Notes?
--*/
#ifndef _LOCKS_H_
#define _LOCKS_H_
#ifdef DBG
#define REASONABLE_TIME 2 * 60 * 1000 // Two minutes
#else
#define REASONABLE_TIME INFINITE
#endif
extern DWORD
WaitForAnyObject(
DWORD dwTimeout,
...);
extern DWORD
WaitForAnObject(
HANDLE hWaitOn,
DWORD dwTimeout);
#ifdef DBG
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("WaitForEverObject")
inline void
WaitForEverObject(
HANDLE hWaitOn,
DWORD dwTimeout,
DEBUG_TEXT szReason,
LPCTSTR szObject = NULL)
{
DWORD dwSts;
while (ERROR_SUCCESS != (dwSts = WaitForAnObject(hWaitOn, dwTimeout)))
CalaisWarning(__SUBROUTINE__, szReason, dwSts, szObject);
}
inline void
WaitForEverObject(
HANDLE hWaitOn,
DWORD dwTimeout,
DEBUG_TEXT szReason,
DWORD dwObject)
{
DWORD dwSts;
TCHAR szNum[16];
wsprintf(szNum, TEXT("0x%08x"), dwObject);
while (ERROR_SUCCESS != (dwSts = WaitForAnObject(hWaitOn, dwTimeout)))
CalaisWarning(__SUBROUTINE__, szReason, dwSts, szNum);
}
#define WaitForever(hWaitOn, dwTimeout, szReason, szObject) \
WaitForEverObject(hWaitOn, dwTimeout, szReason, szObject)
#else
inline void
WaitForEverObject(
HANDLE hWaitOn)
{
while (ERROR_SUCCESS != WaitForAnObject(hWaitOn, INFINITE));
// Empty body
}
#define WaitForever(hWaitOn, dwTimeout, szReason, szObject) \
WaitForEverObject(hWaitOn)
#endif
//
// Critical Section Support.
//
// The following Classes and Macros aid in debugging Critical Section
// Conflicts.
//
//
//==============================================================================
//
// CCriticalSectionObject
//
class CCriticalSectionObject
{
public:
// Constructors & Destructor
CCriticalSectionObject(DWORD dwCsid = 0);
~CCriticalSectionObject();
// Properties
// Methods
virtual void Enter(DEBUG_TEXT szOwner, DEBUG_TEXT szComment);
virtual void Leave(void);
#ifdef DBG
LPCTSTR Description(void) const;
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CCriticalSectionObject::Owner")
LPCTSTR Owner(void) const
{ return (LPCTSTR)m_bfOwner.Access(); };
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CCriticalSectionObject::Comment")
LPCTSTR Comment(void) const
{ return (LPCTSTR)m_bfComment.Access(); };
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CCriticalSectionObject::IsOwnedByMe")
BOOL IsOwnedByMe(void) const
{ return (GetCurrentThreadId() == m_dwOwnerThread); };
#endif
// Operators
protected:
// Properties
CRITICAL_SECTION m_csLock;
#ifdef DBG
DWORD m_dwCsid;
CBuffer m_bfOwner;
CBuffer m_bfComment;
DWORD m_dwOwnerThread;
DWORD m_dwRecursion;
DWORD m_dwArrayEntry;
static CDynamicArray<CCriticalSectionObject *> *mg_prgCSObjects;
static CRITICAL_SECTION mg_csArrayLock;
#endif
// Methods
};
//
//==============================================================================
//
// COwnCriticalSection
//
class COwnCriticalSection
{
public:
// Constructors & Destructor
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("COwnCriticalSection::COwnCriticalSection")
COwnCriticalSection(
CCriticalSectionObject *pcs,
DEBUG_TEXT szSubroutine,
DEBUG_TEXT szComment)
{
m_pcsLock = pcs;
m_pcsLock->Enter(szSubroutine, szComment);
};
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("COwnCriticalSection::~COwnCriticalSection")
~COwnCriticalSection()
{
m_pcsLock->Leave();
};
// Properties
// Methods
// Operators
protected:
// Properties
CCriticalSectionObject *m_pcsLock;
// Methods
};
#define LockSection(cx, reason) \
COwnCriticalSection csLock(cx, __SUBROUTINE__, reason)
#ifndef DBG
//
//In-line the simple Critical Section calls.
//
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CCriticalSectionObject::CCriticalSectionObject")
inline
CCriticalSectionObject::CCriticalSectionObject(
DWORD dwCsid)
{
BOOL fInited = FALSE;
do
{
try
{
InitializeCriticalSection(&m_csLock);
fInitied = TRUE;
}
catch (...)
{
Sleep(1000); // Sleep for 1 second.
}
} while (!fInited);
}
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CCriticalSectionObject::~CCriticalSectionObject")
inline
CCriticalSectionObject::~CCriticalSectionObject()
{
DeleteCriticalSection(&m_csLock);
}
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CCriticalSectionObject::Enter")
inline void
CCriticalSectionObject::Enter(
DEBUG_TEXT szOwner,
DEBUG_TEXT szComment)
{
BOOL fEntered = FALSE;
do
{
try
{
EnterCriticalSection(&m_csLock);
fEntered = TRUE;
}
catch (...)
{
Sleep(1000); // Sleep for 1 second.
}
} while (!fEntered);
}
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CCriticalSectionObject::Leave")
inline void
CCriticalSectionObject::Leave(
void)
{
LeaveCriticalSection(&m_csLock);
}
#endif // !DBG
//
//==============================================================================
//
// CHandleObject
//
class CHandleObject
{
public:
// Constructors & Destructor
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CHandleObject::CHandleObject")
CHandleObject(DEBUG_TEXT szName)
#ifdef DBG
: m_bfName((LPCBYTE)szName, (lstrlen(szName) + 1) * sizeof(TCHAR))
#endif
{
m_hHandle = NULL;
m_dwError = ERROR_SUCCESS;
};
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CHandleObject::~CHandleObject")
~CHandleObject()
{
if (IsValid())
{
#ifdef _DEBUG
CalaisWarning(
__SUBROUTINE__,
DBGT("Unclosed handle '%1' -- fixing."),
(DEBUG_TEXT)m_bfName.Access());
#endif
Close();
}
};
// Properties
// Methods
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CHandleObject::IsValid")
BOOL IsValid(void) const
{
return (NULL != m_hHandle) && (INVALID_HANDLE_VALUE != m_hHandle);
};
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CHandleObject::Value")
HANDLE Value(void) const
{
#ifdef _DEBUG
if (!IsValid())
CalaisWarning(
__SUBROUTINE__,
DBGT("Accessing invalid '%1' handle value."),
(DEBUG_TEXT)m_bfName.Access());
#endif
return m_hHandle;
};
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CHandleObject::GetLastError")
DWORD GetLastError(void) const
{
return m_dwError;
};
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CHandleObject::Open")
HANDLE Open(HANDLE h)
{
if ((NULL == h) || (INVALID_HANDLE_VALUE == h))
{
m_dwError = ::GetLastError();
#ifdef _DEBUG
CalaisWarning(
__SUBROUTINE__,
DBGT("Attempt to assign invalid handle value to '%1'."),
(DEBUG_TEXT)m_bfName.Access());
#endif
}
else
m_dwError = ERROR_SUCCESS;
if (IsValid())
{
#ifdef _DEBUG
CalaisWarning(
__SUBROUTINE__,
DBGT("Overwriting handle '%1' -- fixing"),
(DEBUG_TEXT)m_bfName.Access());
#endif
Close();
}
m_hHandle = h;
return m_hHandle;
};
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CHandleObject::Close")
DWORD Close(void)
{
DWORD dwSts = ERROR_SUCCESS;
if (IsValid())
{
BOOL fSts;
fSts = CloseHandle(m_hHandle);
#ifdef DBG
if (!fSts)
{
dwSts = GetLastError();
CalaisWarning(
__SUBROUTINE__,
DBGT("Failed to close handle '%2': %1"),
dwSts,
(DEBUG_TEXT)m_bfName.Access());
}
#endif
m_hHandle = NULL;
}
#ifdef DBG
else
{
CalaisWarning(
__SUBROUTINE__,
DBGT("Attempt to re-close handle '%1'"),
(DEBUG_TEXT)m_bfName.Access());
}
#endif
return dwSts;
};
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CHandleObject::Relinquish")
HANDLE Relinquish(void)
{
HANDLE hTmp = m_hHandle;
#ifdef _DEBUG
if (!IsValid())
CalaisWarning(
__SUBROUTINE__,
DBGT("Relinquishing invalid '%1' handle"),
(DEBUG_TEXT)m_bfName.Access());
#endif
m_hHandle = NULL;
return hTmp;
};
// Operators
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CHandleObject::operator HANDLE")
operator HANDLE(void) const
{
ASSERT(IsValid());
return Value();
};
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CHandleObject::operator=")
HANDLE operator=(HANDLE h)
{
return Open(h);
};
protected:
// Properties
HANDLE m_hHandle;
DWORD m_dwError;
#ifdef DBG
CBuffer m_bfName;
#endif
// Methods
};
//
//==============================================================================
//
// CAccessLock
//
class CAccessLock
{
public:
// Constructors & Destructor
CAccessLock(DWORD dwTimeout = CALAIS_LOCK_TIMEOUT);
~CAccessLock();
#ifdef DBG
BOOL NotReadLocked(void);
BOOL IsReadLocked(void);
BOOL NotWriteLocked(void);
BOOL IsWriteLocked(void);
#endif
protected:
// Properties
CCriticalSectionObject m_csLock;
DWORD m_dwReadCount;
DWORD m_dwWriteCount;
DWORD m_dwTimeout;
CHandleObject m_hSignalNoReaders;
CHandleObject m_hSignalNoWriters;
DWORD m_dwOwner;
#ifdef DBG
CDynamicArray<VOID> m_rgdwReaders;
#endif
// Methods
void Wait(HANDLE hSignal);
void Signal(HANDLE hSignal);
void Unsignal(HANDLE hSignal);
void WaitOnReaders(void)
{
Wait(m_hSignalNoReaders);
};
void WaitOnWriters(void)
{
Wait(m_hSignalNoWriters);
};
void SignalNoReaders(void)
{
Signal(m_hSignalNoReaders);
};
void SignalNoWriters(void)
{
Signal(m_hSignalNoWriters);
};
void UnsignalNoReaders(void)
{
Signal(m_hSignalNoReaders);
};
void UnsignalNoWriters(void)
{
Unsignal(m_hSignalNoWriters);
};
friend class CLockRead;
friend class CLockWrite;
};
//
//==============================================================================
//
// CLockRead
//
class CLockRead
{
public:
// Constructors & Destructor
CLockRead(CAccessLock *pLock);
~CLockRead();
// Properties
// Methods
// Operators
protected:
// Properties
CAccessLock * m_pLock;
// Methods
};
//
//==============================================================================
//
// CLockWrite
//
class CLockWrite
{
public:
// Constructors & Destructor
CLockWrite(CAccessLock *pLock);
~CLockWrite();
// Properties
// Methods
// Operators
protected:
// Properties
CAccessLock *m_pLock;
// Methods
};
#endif // _LOCKS_H_