public void RestoreLock(ref LockCookie lockCookie)
{
// Validate cookie
int threadID = GetCurrentThreadID();
if (lockCookie._threadID != threadID)
{
throw GetInvalidLockCookieException();
}
if (_writerID == threadID || ThreadLocalLockEntry.GetCurrent(_lockID) != null)
{
throw new SynchronizationLockException(SR.ReaderWriterLock_RestoreLockWithOwnedLocks);
}
LockCookieFlags flags = lockCookie._flags;
if ((flags & LockCookieFlags.Invalid) != 0)
{
throw GetInvalidLockCookieException();
}
do
{
if ((flags & LockCookieFlags.OwnedNone) != 0)
{
break;
}
// Check for the no contention case
if ((flags & LockCookieFlags.OwnedWriter) != 0)
{
if (Interlocked.CompareExchange(ref _state, LockStates.Writer, 0) == 0)
{
// Restore writer nesting level
_writerID = threadID;
_writerLevel = lockCookie._writerLevel;
++_writerSeqNum;
break;
}
}
else if ((flags & LockCookieFlags.OwnedReader) != 0)
{
// This thread should not already be a reader else bad things can happen
ThreadLocalLockEntry threadLocalLockEntry = ThreadLocalLockEntry.GetOrCreateCurrent(_lockID);
Debug.Assert(threadLocalLockEntry.IsFree);
int knownState = _state;
if (knownState < LockStates.ReadersMask &&
Interlocked.CompareExchange(ref _state, knownState + LockStates.Reader, knownState) == knownState)
{
// Restore reader nesting level
threadLocalLockEntry._readerLevel = lockCookie._readerLevel;
break;
}
}
// We are aware of the contention on the lock and the thread will most probably block to acquire the lock
RecoverLock(ref lockCookie, flags);
} while (false);
lockCookie._flags = LockCookieFlags.Invalid;
}