155 lines
3.8 KiB
C++
155 lines
3.8 KiB
C++
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1999-2000 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// SpinLock.h
|
|
//
|
|
// Description:
|
|
// Spin Lock implementation.
|
|
//
|
|
// Maintained By:
|
|
// Geoffrey Pease (GPease) 27-NOV-1999
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#pragma once
|
|
|
|
// CSpinLock
|
|
class
|
|
CSpinLock
|
|
{
|
|
private: // Data
|
|
LONG * m_plLock; // pointer to the lock
|
|
LONG m_lSpinCount; // counts the number of sleeps
|
|
LONG m_lTimeout; // count until acquire lock fails
|
|
#if DBG==1
|
|
BOOL m_fAcquired; // DEBUG: internal state of the lock
|
|
BOOL m_fAcquiredOnce; // DEBUG: lock was acquired at least once.
|
|
#endif
|
|
|
|
public: // Methods
|
|
explicit
|
|
CSpinLock( LONG * plLock, LONG lTimeout ) :
|
|
m_plLock( plLock ),
|
|
m_lTimeout( lTimeout )
|
|
{
|
|
Assert( m_lTimeout >= 0 || m_lTimeout == INFINITE );
|
|
#if DBG==1
|
|
m_fAcquired = FALSE;
|
|
m_fAcquiredOnce = FALSE;
|
|
#endif
|
|
};
|
|
|
|
//
|
|
~CSpinLock()
|
|
{
|
|
#if DBG==1
|
|
AssertMsg( m_fAcquired == FALSE, "Lock was not released!" );
|
|
AssertMsg( m_fAcquiredOnce != FALSE, "Lock was never acquired. Why was I needed?" );
|
|
#endif
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HRESULT
|
|
// AcquireLock( void )
|
|
//
|
|
// Description:
|
|
// Acquires the spin lock. Does not return until the lock is
|
|
// acquired.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Values:
|
|
// S_OK - Sucess.
|
|
// HRESULT_FROM_WIN32( ERROR_LOCK_FAILED ) - Lock failed.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
AcquireLock( void )
|
|
{
|
|
HRESULT hr;
|
|
LONG l = TRUE;
|
|
|
|
#if DBG==1
|
|
AssertMsg( m_fAcquired == FALSE, "Trying to acquire a lock that it already own. Thread is going to freeze up." );
|
|
m_fAcquiredOnce = TRUE;
|
|
#endif
|
|
|
|
m_lSpinCount = 0;
|
|
|
|
for(;;)
|
|
{
|
|
l = InterlockedCompareExchange( m_plLock, TRUE, FALSE );
|
|
if ( l == FALSE )
|
|
{
|
|
//
|
|
// Lock acquired.
|
|
//
|
|
hr = S_OK;
|
|
break;
|
|
} // if: got lock
|
|
else
|
|
{
|
|
m_lSpinCount++;
|
|
if ( m_lSpinCount > m_lTimeout )
|
|
{
|
|
AssertMsg( m_lSpinCount >= 0, "This lock doesn't seem to have been released properly." );
|
|
if ( m_lTimeout != INFINITE )
|
|
{
|
|
hr = THR( HRESULT_FROM_WIN32( ERROR_LOCK_FAILED ) );
|
|
break;
|
|
|
|
} // if: not infinite
|
|
|
|
} // if: count exceeded
|
|
|
|
//
|
|
// Put a breakpoint here if you think that someone is double
|
|
// locking.
|
|
//
|
|
Sleep( 1 );
|
|
|
|
} // if: lock not acquired
|
|
|
|
} // for: forever
|
|
|
|
#if DBG==1
|
|
m_fAcquired = TRUE;
|
|
#endif
|
|
return hr;
|
|
}; // AcquireLock( )
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HRESULT
|
|
// ReleaseLock( void )
|
|
//
|
|
// Description:
|
|
// Releases the spin lock. Return immediately.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Values:
|
|
// S_OK - Success.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
ReleaseLock( void )
|
|
{
|
|
#if DBG==1
|
|
AssertMsg( m_fAcquired == TRUE, "Releasing a lock that was not owned." );
|
|
#endif
|
|
*m_plLock = FALSE;
|
|
#if DBG==1
|
|
m_fAcquired = FALSE;
|
|
#endif
|
|
return S_OK;
|
|
}; // ReleaseLock( )
|
|
|
|
}; // class CSpinLock
|
|
|