169 lines
3 KiB
C++
169 lines
3 KiB
C++
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1995 - 1999
|
|
|
|
Module Name:
|
|
|
|
Locks.cxx
|
|
|
|
Abstract:
|
|
|
|
Out of line methods for some of the syncronization classes
|
|
defined in locks.hxx.
|
|
|
|
Author:
|
|
|
|
Mario Goertzel [MarioGo]
|
|
|
|
Revision History:
|
|
|
|
MarioGo 03-14-95 Moved from misc.cxx.
|
|
MarioGo 01-27-96 Changed from busy (Sleep(0)) wait to event
|
|
|
|
--*/
|
|
|
|
#include "qmgrlibp.h"
|
|
#include <locks.hxx>
|
|
|
|
BOOL BITSInitializeCriticalSectionInternal( LPCRITICAL_SECTION lpCriticalSection )
|
|
{
|
|
__try
|
|
{
|
|
InitializeCriticalSection( lpCriticalSection ); // SEC: REVIEWED 2002-03-28
|
|
}
|
|
__except( ( GetExceptionCode() == STATUS_NO_MEMORY ) ?
|
|
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH )
|
|
{
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void BITSIntializeCriticalSection( LPCRITICAL_SECTION lpCriticalSection )
|
|
{
|
|
if (!BITSInitializeCriticalSectionInternal( lpCriticalSection ) )
|
|
throw ComError( E_OUTOFMEMORY );
|
|
}
|
|
|
|
//
|
|
// CShareLock methods
|
|
//
|
|
|
|
CSharedLock::CSharedLock()
|
|
{
|
|
exclusive_owner = 0;
|
|
writers = 0;
|
|
hevent = INVALID_HANDLE_VALUE; // Flag in the d'tor
|
|
|
|
BITSIntializeCriticalSection( &lock );
|
|
|
|
hevent = CreateEvent(0, FALSE, FALSE, 0); // SEC: REVIEWED 2002-03-28
|
|
if (0 == hevent)
|
|
{
|
|
DeleteCriticalSection(&lock);
|
|
throw ComError( E_OUTOFMEMORY );
|
|
}
|
|
}
|
|
|
|
CSharedLock::~CSharedLock()
|
|
{
|
|
if (hevent != INVALID_HANDLE_VALUE)
|
|
{
|
|
DeleteCriticalSection(&lock);
|
|
|
|
if (hevent) CloseHandle(hevent);
|
|
}
|
|
}
|
|
|
|
void
|
|
CSharedLock::LockShared()
|
|
{
|
|
readers++;
|
|
|
|
if (writers)
|
|
{
|
|
if ((readers--) == 0)
|
|
{
|
|
SetEvent(hevent);
|
|
}
|
|
|
|
EnterCriticalSection(&lock);
|
|
readers++;
|
|
LeaveCriticalSection(&lock);
|
|
}
|
|
|
|
exclusive_owner = 0;
|
|
}
|
|
|
|
void
|
|
CSharedLock::UnlockShared(void)
|
|
{
|
|
ASSERT((LONG)readers > 0);
|
|
ASSERT(exclusive_owner == 0);
|
|
|
|
if ( (readers--) == 0 && writers)
|
|
{
|
|
SetEvent(hevent);
|
|
}
|
|
}
|
|
|
|
void
|
|
CSharedLock::LockExclusive(void)
|
|
{
|
|
EnterCriticalSection(&lock);
|
|
|
|
writers++;
|
|
while(readers)
|
|
{
|
|
WaitForSingleObject(hevent, INFINITE);
|
|
}
|
|
ASSERT(writers);
|
|
exclusive_owner = GetCurrentThreadId();
|
|
}
|
|
|
|
void
|
|
CSharedLock::UnlockExclusive(void)
|
|
{
|
|
ASSERT(HeldExclusive());
|
|
ASSERT(writers);
|
|
writers--;
|
|
exclusive_owner = 0;
|
|
LeaveCriticalSection(&lock);
|
|
}
|
|
|
|
void
|
|
CSharedLock::Unlock()
|
|
{
|
|
// Either the lock is held exclusively by this thread or the thread
|
|
// has a shared lock. (or the caller has a bug).
|
|
|
|
if (HeldExclusive())
|
|
{
|
|
UnlockExclusive();
|
|
}
|
|
else
|
|
{
|
|
UnlockShared();
|
|
}
|
|
}
|
|
|
|
void
|
|
CSharedLock::ConvertToExclusive(void)
|
|
{
|
|
ASSERT((LONG)readers > 0);
|
|
ASSERT(exclusive_owner == 0);
|
|
|
|
if ( (readers--) == 0 && writers )
|
|
SetEvent(hevent);
|
|
|
|
EnterCriticalSection(&lock);
|
|
writers++;
|
|
while(readers)
|
|
{
|
|
WaitForSingleObject(hevent, INFINITE);
|
|
}
|
|
ASSERT(writers);
|
|
exclusive_owner = GetCurrentThreadId();
|
|
}
|
|
|