/*++ 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 // // 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