public bool TryEnterWriteLock (int millisecondsTimeout)
{
if (millisecondsTimeout < Timeout.Infinite)
throw new ArgumentOutOfRangeException ("millisecondsTimeout");
if (read_locks == null)
throw new ObjectDisposedException (null);
if (IsWriteLockHeld)
throw new LockRecursionException ();
EnterMyLock ();
LockDetails ld = GetReadLockDetails (Thread.CurrentThread.ManagedThreadId, false);
if (ld != null && ld.ReadLocks > 0) {
ExitMyLock ();
throw new LockRecursionException ("Write lock cannot be acquired while read lock is held");
}
while (true){
// There is no contention, we are done
if (owners == 0){
// Indicate that we have a writer
owners = -1;
write_thread = Thread.CurrentThread;
break;
}
// If we are the thread that took the Upgradable read lock
if (owners == 1 && upgradable_thread == Thread.CurrentThread){
owners = -1;
write_thread = Thread.CurrentThread;
break;
}
// If the request is to probe.
if (millisecondsTimeout == 0){
ExitMyLock ();
return false;
}
// We need to wait, figure out what kind of waiting.
if (upgradable_thread == Thread.CurrentThread){
// We are the upgradable thread, register our interest.
if (upgradeEvent == null){
LazyCreateEvent (ref upgradeEvent, false);
// since we left the lock, start over.
continue;
}
if (numUpgradeWaiters > 0){
ExitMyLock ();
throw new ApplicationException ("Upgrading lock to writer lock already in process, deadlock");
}
if (!WaitOnEvent (upgradeEvent, ref numUpgradeWaiters, millisecondsTimeout))
return false;
} else {
if (writeEvent == null){
LazyCreateEvent (ref writeEvent, true);
// since we left the lock, retry
continue;
}
if (!WaitOnEvent (writeEvent, ref numWriteWaiters, millisecondsTimeout))
return false;
}
}
Debug.Assert (owners == -1, "Owners is not -1");
ExitMyLock ();
return true;
}