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.
360 lines
7.7 KiB
360 lines
7.7 KiB
/*++
|
|
|
|
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
|