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
7.3 KiB
338 lines
7.3 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_
|