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.
 
 
 
 
 
 

338 lines
6.9 KiB

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
lock.h
Abstract:
Portable synronization primitive class ( between Win9x and NT)
Win9x does not
Author:
Vlad Sadovsky (vlads) 02-Jan-1997
Environment:
User Mode - Win32
Revision History:
02-Jan-1997 VladS created
--*/
# ifndef _LOCK_H_
# define _LOCK_H_
/************************************************************
* Include Headers
************************************************************/
# ifdef _cplusplus
extern "C" {
# endif // _cplusplus
# ifdef _cplusplus
}; // extern "C"
# endif // _cplusplus
#ifndef DBG_REQUIRE
#define DBG_REQUIRE REQUIRE
#endif
#ifndef RTL_RESOURCE
//
// Shared resource function definitions. It is declared in NTRTL , but not in windows SDK header files
//
typedef struct _RTL_RESOURCE {
//
// The following field controls entering and exiting the critical
// section for the resource
//
RTL_CRITICAL_SECTION CriticalSection;
//
// The following four fields indicate the number of both shared or
// exclusive waiters
//
HANDLE SharedSemaphore;
ULONG NumberOfWaitingShared;
HANDLE ExclusiveSemaphore;
ULONG NumberOfWaitingExclusive;
//
// The following indicates the current state of the resource
//
// <0 the resource is acquired for exclusive access with the
// absolute value indicating the number of recursive accesses
// to the resource
//
// 0 the resource is available
//
// >0 the resource is acquired for shared access with the
// value indicating the number of shared accesses to the resource
//
LONG NumberOfActive;
HANDLE ExclusiveOwnerThread;
ULONG Flags; // See RTL_RESOURCE_FLAG_ equates below.
PVOID DebugInfo;
} RTL_RESOURCE, *PRTL_RESOURCE;
#define RTL_RESOURCE_FLAG_LONG_TERM ((ULONG) 0x00000001)
#endif // RTL_RESOURCE
/************************************************************
* Type Definitions
************************************************************/
# ifdef _cplusplus
extern "C" {
# endif // _cplusplus
BOOL
InitializeResource(
IN PRTL_RESOURCE Resource
);
BOOL
AcquireResourceShared(
IN PRTL_RESOURCE Resource,
IN BOOL Wait
);
BOOL
AcquireResourceExclusive(
IN PRTL_RESOURCE Resource,
IN BOOL Wait
);
BOOL
ReleaseResource(
IN PRTL_RESOURCE Resource
);
BOOL
ConvertSharedToExclusive(
IN PRTL_RESOURCE Resource
);
BOOL
ConvertExclusiveToShared(
IN PRTL_RESOURCE Resource
);
VOID
DeleteResource (
IN PRTL_RESOURCE Resource
);
# ifdef _cplusplus
}; // extern "C"
# endif // _cplusplus
///////////////////////////////////////////////////////////////////////
//
// Simple RTL_RESOURCE Wrapper class
//
//////////////////////////////////////////////////////////////////////
enum SYNC_LOCK_TYPE
{
SYNC_LOCK_READ = 0, // Take the lock for read only
SYNC_LOCK_WRITE // Take the lock for write
};
enum SYNC_CONV_TYPE
{
SYNC_CONV_READ = 0, // Convert the lock from write to read
SYNC_CONV_WRITE // Convert the lock from read to write
};
class SYNC_RESOURCE
{
friend class TAKE_SYNC_RESOURCE;
public:
SYNC_RESOURCE()
{ InitializeResource( &_rtlres ); }
~SYNC_RESOURCE()
{ DeleteResource( &_rtlres ); }
void Lock( enum SYNC_LOCK_TYPE type )
{ if ( type == SYNC_LOCK_READ ) {
DBG_REQUIRE( AcquireResourceShared( &_rtlres, TRUE ) );
} else {
DBG_REQUIRE( AcquireResourceExclusive( &_rtlres, TRUE ));
}
}
void Convert( enum SYNC_CONV_TYPE type )
{ if ( type == SYNC_CONV_READ ) {
DBG_REQUIRE( ConvertExclusiveToShared( &_rtlres ));
} else {
DBG_REQUIRE( ConvertSharedToExclusive( &_rtlres ));
}
}
void Unlock( VOID )
{ DBG_REQUIRE( ReleaseResource( &_rtlres )); }
private:
RTL_RESOURCE _rtlres;
};
///////////////////////////////////////////////////////////////////
// Instantiate one of these classes in a block of code
// when you want that block of code to be protected
// against re-entrancy.
// The Take() and Release() functions should rarely be necessary,
// and must be used in matched pairs with Release() called first.
///////////////////////////////////////////////////////////////////
class TAKE_SYNC_RESOURCE
{
private:
SYNC_RESOURCE& _syncres;
public:
void Take(void) { _syncres.Lock(SYNC_LOCK_WRITE); }
void Release(void) { _syncres.Unlock(); }
TAKE_SYNC_RESOURCE(SYNC_RESOURCE& syncres) : _syncres(syncres) { Take(); }
~TAKE_SYNC_RESOURCE() { Release(); }
};
//
// Auto critical section clss
//
class CRIT_SECT
{
public:
BOOL Lock()
{
if (m_bInitialized) {
EnterCriticalSection(&m_sec);
return TRUE;
}
return FALSE;
}
void Unlock()
{
LeaveCriticalSection(&m_sec);
}
CRIT_SECT()
{
m_bInitialized = FALSE;
__try {
#ifdef UNICODE
if(InitializeCriticalSectionAndSpinCount(&m_sec, MINLONG)) {
#else
InitializeCriticalSection(&m_sec); {
#endif
m_bInitialized = TRUE;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
}
}
~CRIT_SECT()
{
if (m_bInitialized) {
DeleteCriticalSection(&m_sec);
m_bInitialized = FALSE;
}
}
BOOL IsInitialized() {return m_bInitialized;}
CRITICAL_SECTION m_sec;
BOOL m_bInitialized;
};
class TAKE_CRIT_SECT
{
private:
CRIT_SECT& _syncres;
BOOL m_bLocked;
public:
inline TAKE_CRIT_SECT(CRIT_SECT& syncres) : _syncres(syncres), m_bLocked(FALSE) { m_bLocked = _syncres.Lock(); }
inline ~TAKE_CRIT_SECT() { if (m_bLocked) {_syncres.Unlock(); m_bLocked = FALSE;}; }
};
//
// Auto mutex class
//
class MUTEX_OBJ
{
private:
HANDLE m_hMutex;
public:
BOOL inline IsValid(VOID) {return (m_hMutex!=INVALID_HANDLE_VALUE);}
void Lock() { ::WaitForSingleObject(m_hMutex, INFINITE); }
void Unlock() { ::ReleaseMutex(m_hMutex); }
MUTEX_OBJ(LPCTSTR pszName) {
m_hMutex = ::CreateMutex(NULL,
FALSE,
pszName
);
}
~MUTEX_OBJ() {CloseHandle(m_hMutex);m_hMutex = INVALID_HANDLE_VALUE;}
};
class TAKE_MUTEX
{
private:
HANDLE const m_hMutex;
public:
void Take(void) { ::WaitForSingleObject(m_hMutex, INFINITE); }
void Release(void) { ::ReleaseMutex(m_hMutex); }
TAKE_MUTEX(HANDLE hMutex) : m_hMutex(hMutex) { Take(); }
~TAKE_MUTEX() { Release(); }
};
class TAKE_MUTEX_OBJ
{
private:
MUTEX_OBJ& _syncres;
public:
inline TAKE_MUTEX_OBJ(MUTEX_OBJ& syncres) : _syncres(syncres) { _syncres.Lock(); }
inline ~TAKE_MUTEX_OBJ() { _syncres.Unlock(); }
};
# endif // _LOCK_H_