|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
reslock.cxx
Abstract:
Contains methods for RESOURCE_LOCK class
Contents: RESOURCE_LOCK::Acquire() RESOURCE_LOCK::Release()
Author:
Richard L Firth (rfirth) 18-Jun-1996
Revision History:
18-Jun-1996 rfirth Created
--*/
#include <wininetp.h>
//
// class members
//
#ifdef OLD_VERSION
BOOL RESOURCE_LOCK::Acquire( IN BOOL bExclusiveMode )
/*++
Routine Description:
Acquires the resource protected by this lock. Acquires for non-exclusive (read) or exclusive (write) ownership
Arguments:
bExclusiveMode - TRUE if we are acquiring the resource for exclusive (write) ownership
Return Value:
BOOL TRUE - resource is acquired
FALSE - failed to acquire resource (timeout?)
--*/
{ DEBUG_ENTER((DBG_RESLOCK, Bool, "RESOURCE_LOCK::Acquire", "%B", bExclusiveMode ));
INET_ASSERT(this != NULL); //INET_ASSERT(IsInitialized());
//INET_ASSERT(IsValid());
if (!IsInitialized()) {
DEBUG_LEAVE(FALSE);
return FALSE; }
BOOL acquired = TRUE;
//_CritSect.Lock();
if (bExclusiveMode) {
//
// acquired for exclusive ownership (write access). Set the owning
// thread id and wait for the last current reader to release. Note
// that if we're being re-entered, the Lock() has already
// done the work of checking the thread id and updating re-entrancy
// counts, so if its already not zero, we know it must be us
//
++_WriteCount; if (_ThreadId == 0) { _ThreadId = GetCurrentThreadId(); #if INET_DEBUG
INET_ASSERT(_ThreadId != _ThreadIdReader); #endif
acquired = Wait(_hWriteEvent); _CritSect.Lock(); } else {
INET_ASSERT(_ThreadId == GetCurrentThreadId());
} } else {
//
// don't allow re-entry if already held for exclusive access
//
INET_ASSERT(_ThreadId == 0);
//
// acquired for non-exclusive ownership (read access). Just increase
// the number of active readers. If this is the first then inhibit the
// writer
//
if (InterlockedIncrement(&_Readers) == 0) { #if INET_DEBUG
if (_ThreadIdReader == 0) { _ThreadIdReader = GetCurrentThreadId(); } #endif
ResetEvent(_hWriteEvent); }
//
// reader doesn't need to keep hold of critical section
//
//_CritSect.Unlock();
}
DEBUG_LEAVE(acquired);
return acquired; }
VOID RESOURCE_LOCK::Release( VOID )
/*++
Routine Description:
Releases a resource previously acquired by RESOURCE_LOCK::Acquire()
Arguments:
None.
Return Value:
None.
--*/
{ DEBUG_ENTER((DBG_RESLOCK, None, "RESOURCE_LOCK::Release", NULL ));
INET_ASSERT(this != NULL); //INET_ASSERT(IsInitialized());
//INET_ASSERT(IsValid());
if (!IsInitialized()) {
DEBUG_LEAVE(0);
return; }
if ((_ThreadId != 0) && (_ThreadId == GetCurrentThreadId())) {
INET_ASSERT(_WriteCount > 0);
if (--_WriteCount == 0) {
//
// we acquired _hWriteEvent; signal it to allow next writer to continue
//
SetEvent(_hWriteEvent);
//
// this resource no longer owned for exclusive access
//
_ThreadId = 0; } _CritSect.Unlock(); } else if (InterlockedDecrement(&_Readers) < 0) {
INET_ASSERT(_Readers >= -1);
//
// we are last currently active reader; allow waiting writer to continue
//
#if INET_DEBUG
if (_ThreadIdReader == GetCurrentThreadId()) { _ThreadIdReader = 0; } #endif
SetEvent(_hWriteEvent); }
DEBUG_LEAVE(0); }
#else
BOOL RESOURCE_LOCK::Acquire( IN BOOL bExclusiveMode ) { DEBUG_ENTER((DBG_RESLOCK, Bool, "RESOURCE_LOCK::Acquire", "%B", bExclusiveMode ));
BOOL fReturn = TRUE;
if (!IsInitialized()) {
fReturn = FALSE; goto quit; }
if (bExclusiveMode) { do {
DEBUG_PRINT(RESLOCK, INFO, ("Waiting on WriteEvent\n") );
if (_ThreadId != GetCurrentThreadId()) { Wait(_hWriteEvent); } if (!_CritSect.Lock()) { DEBUG_PRINT(RESLOCK, ERROR, ("Failed to obtain critsec lock after waiting on WriteEvent\n") ); fReturn = FALSE; break; }
INET_ASSERT((_ThreadId == 0) || (_ThreadId == GetCurrentThreadId()));
if ((_Readers == -1) && ((_ThreadId == 0) || (_ThreadId == GetCurrentThreadId()))) { _ThreadId = GetCurrentThreadId(); if (++_WriteCount == 1) { ResetEvent(_hWriteEvent); } break; }
DEBUG_PRINT(RESLOCK, INFO, ("trying again\n") );
_CritSect.Unlock(); } while ( 1 ); } else { if (_CritSect.Lock()) { if (++_Readers == 0) {
DEBUG_PRINT(RESLOCK, INFO, ("Resetting WriteEvent\n") );
ResetEvent(_hWriteEvent); } _CritSect.Unlock(); } else { DEBUG_PRINT(RESLOCK, ERROR, ("Failed to obtain critsec lock after waiting on WriteEvent\n") ); fReturn = FALSE; } }
quit: DEBUG_LEAVE(fReturn);
return fReturn; }
VOID RESOURCE_LOCK::Release( VOID ) { DEBUG_ENTER((DBG_RESLOCK, None, "RESOURCE_LOCK::Release", NULL ));
if (IsInitialized()) { if (_ThreadId == GetCurrentThreadId()) {
DEBUG_PRINT(RESLOCK, INFO, ("Clearing writer\n") );
if (--_WriteCount == 0) { _ThreadId = 0; SetEvent(_hWriteEvent); } _CritSect.Unlock(); } else { if (_CritSect.Lock()) { if (--_Readers == -1) {
DEBUG_PRINT(RESLOCK, INFO, ("Setting WriteEvent\n") );
SetEvent(_hWriteEvent); } _CritSect.Unlock(); } else { DEBUG_PRINT(RESLOCK, INFO, ("Couldn't set WriteEvent due to not enough memory\n") ); } } }
DEBUG_LEAVE(0); }
#endif // OLD_VERSION
|