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.
 
 
 
 
 
 

264 lines
7.1 KiB

#ifndef __SHARELOCK_H__
#define __SHARELOCK_H__
//////////////////////////////////////////////////////////////////////
//
// The standard include files.
//
// The standard include files setup a consistent environment
// for all of the modules in a program. The structure of each
// header file is as follows:
// 1. Standard include files.
// 2. Include files for inherited classes.
// 3. Constants exported from the class.
// 4. Data structures exported from the class.
// 5. Class specification.
// 6. Inline functions.
// Sections that are not required are omitted.
//
//////////////////////////////////////////////////////////////////////
// #include "Global.h"
// #include "NewEx.h"
// #include "Standard.h"
// #include "System.h"
#include <irtlmisc.h>
typedef int SBIT32;
//////////////////////////////////////////////////////////////////////
//
// Sharelock and Semaphore locking.
//
// This class provides a very conservative locking scheme.
// The assumption behind the code is that locks will be
// held for a very short time. A lock can be obtained in
// either exclusive mode or shared mode. If the lock is not
// available the caller waits by spinning or if that fails
// by sleeping.
//
//////////////////////////////////////////////////////////////////////
class IRTL_DLLEXP CSharelock
{
private:
// internally used constants
enum Internal
{
// The Windows NT kernel requires a maximum wakeup count when
// creating a semaphore.
m_MaxShareLockUsers = 256
};
//
// Private data.
//
volatile LONG m_lExclusive;
volatile LONG m_lTotalUsers;
SBIT32 m_lMaxSpins;
SBIT32 m_lMaxUsers;
HANDLE m_hSemaphore;
volatile LONG m_lWaiting;
#ifdef _DEBUG
//
// Counters for debugging builds.
//
volatile LONG m_lTotalExclusiveLocks;
volatile LONG m_lTotalShareLocks;
volatile LONG m_lTotalSleeps;
volatile LONG m_lTotalSpins;
volatile LONG m_lTotalTimeouts;
volatile LONG m_lTotalWaits;
#endif
public:
//
// Public functions.
//
CSharelock( SBIT32 lNewMaxSpins = 4096, SBIT32 lNewMaxUsers = 256 );
inline SBIT32 ActiveUsers( void ) { return (SBIT32) m_lTotalUsers; }
inline void ChangeExclusiveLockToSharedLock( void );
inline BOOLEAN ChangeSharedLockToExclusiveLock( SBIT32 lSleep = INFINITE );
inline BOOLEAN ClaimExclusiveLock( SBIT32 lSleep = INFINITE );
inline BOOLEAN ClaimShareLock( SBIT32 lSleep = INFINITE );
inline void ReleaseExclusiveLock( void );
inline void ReleaseShareLock( void );
BOOLEAN UpdateMaxSpins( SBIT32 lNewMaxSpins );
BOOLEAN UpdateMaxUsers( SBIT32 lNewMaxUsers );
~CSharelock( void );
private:
//
// Private functions.
//
BOOLEAN SleepWaitingForLock( SBIT32 lSleep );
BOOLEAN WaitForExclusiveLock( SBIT32 lSleep );
BOOLEAN WaitForShareLock( SBIT32 lSleep );
void WakeAllSleepers( void );
private:
//
// Disabled operations.
//
CSharelock( const CSharelock & Copy );
void operator=( const CSharelock & Copy );
};
/********************************************************************/
/* */
/* Change an exclusive lock to a shread lock. */
/* */
/* Downgrade the existing exclusive lock to a shared lock. */
/* */
/********************************************************************/
inline void CSharelock::ChangeExclusiveLockToSharedLock( void )
{
(void) InterlockedDecrement( (LPLONG) & m_lExclusive );
#ifdef _DEBUG
(void) InterlockedIncrement( (LPLONG) & m_lTotalShareLocks );
#endif
}
/********************************************************************/
/* */
/* Change a shared lock to an exclusive lock. */
/* */
/* Upgrade the existing shared lock to an exclusive lock. */
/* */
/********************************************************************/
inline BOOLEAN CSharelock::ChangeSharedLockToExclusiveLock( SBIT32 lSleep )
{
(void) InterlockedIncrement( (LPLONG) & m_lExclusive );
if ( m_lTotalUsers != 1 )
{
if ( ! WaitForExclusiveLock( lSleep ) )
{ return FALSE; }
}
#ifdef _DEBUG
(void) InterlockedIncrement( (LPLONG) & m_lTotalExclusiveLocks );
#endif
return TRUE;
}
//////////////////////////////////////////////////////////////////////
//
// Claim an exclusive lock.
//
// Claim an exclusive lock if available else wait or exit.
//
//////////////////////////////////////////////////////////////////////
inline BOOLEAN CSharelock::ClaimExclusiveLock( SBIT32 lSleep )
{
(void) InterlockedIncrement( (LPLONG) & m_lExclusive );
(void) InterlockedIncrement( (LPLONG) & m_lTotalUsers );
if ( m_lTotalUsers != 1 )
{
if ( ! WaitForExclusiveLock( lSleep ) )
{
return FALSE;
}
}
#ifdef _DEBUG
InterlockedIncrement( (LPLONG) & m_lTotalExclusiveLocks );
#endif
return TRUE;
}
//////////////////////////////////////////////////////////////////////
//
// Claim a shared lock.
//
// Claim a shared lock if available else wait or exit.
//
//////////////////////////////////////////////////////////////////////
inline BOOLEAN CSharelock::ClaimShareLock( SBIT32 lSleep )
{
(void) InterlockedIncrement( (LPLONG) & m_lTotalUsers );
if ( (m_lExclusive > 0) || (m_lTotalUsers > m_lMaxUsers) )
{
if ( ! WaitForShareLock( lSleep ) )
{
return FALSE;
}
}
#ifdef _DEBUG
InterlockedIncrement( (LPLONG) & m_lTotalShareLocks );
#endif
return TRUE;
}
//////////////////////////////////////////////////////////////////////
//
// Release an exclusive lock.
//
// Release an exclusive lock and if needed wakeup any sleepers.
//
//////////////////////////////////////////////////////////////////////
inline void CSharelock::ReleaseExclusiveLock( void )
{
(void) InterlockedDecrement( (LPLONG) & m_lTotalUsers );
(void) InterlockedDecrement( (LPLONG) & m_lExclusive );
if ( m_lWaiting > 0 )
{
WakeAllSleepers();
}
}
//////////////////////////////////////////////////////////////////////
//
// Release a shared lock.
//
// Release a shared lock and if needed wakeup any sleepers.
//
//////////////////////////////////////////////////////////////////////
inline void CSharelock::ReleaseShareLock( void )
{
(void) InterlockedDecrement( (LPLONG) & m_lTotalUsers );
if ( m_lWaiting > 0 )
{
WakeAllSleepers();
}
}
#endif // __SHARELOCK_H__