/// <summary> /// Acquires the write lock if it is not held by another thread /// within the given waiting time and <see cref="System.Threading.Thread.Interrupt()"/> has not been called on the current thread /// </summary> /// <remarks> /// Acquires the write lock if neither the read nor write lock /// are held by another thread /// and returns immediately with the value <see lang="true"/>, /// setting the write lock hold count to one. If this lock has been /// set to use a fair ordering policy then an available lock /// <b>will not</b> be acquired if any other threads are /// waiting for the write lock. This is in contrast to the <see cref="Spring.Threading.Locks.WriterLock.TryLock()"/> /// If you want a timed <see cref="Spring.Threading.Locks.WriterLock.TryLock()"/> /// that does permit barging on a fair lock, then combine the /// timed and un-timed forms together: /// /// <code> /// if (lock.TryLock() || lock.tryLock(timeSpan) ) { ... } /// </code> /// /// <p/> /// If the current thread already holds this lock then the /// hold count is incremented by one and the method returns /// <see lang="true"/>. /// /// <p/> /// If the lock is held by another thread then the current /// thread becomes disabled for thread scheduling purposes and /// lies dormant until one of three things happens: /// /// <ul> /// <li>The write lock is acquired by the current thread</li> /// <li>Some other thread calls <see cref="System.Threading.Thread.Interrupt()"/> /// on the current thread</li> /// <li>The specified <see cref="System.TimeSpan"/> elapses</li> /// </ul> /// /// <p/> /// If the write lock is acquired then the value <see lang="true"/> is /// returned and the write lock hold count is set to one. /// /// <p/> /// If the current thread has <see cref="System.Threading.Thread.Interrupt()"/> called on it while acquiring /// the write lock, then a <see cref="System.Threading.ThreadInterruptedException"/> is thrown. /// /// <p/> /// If the specified <see cref="System.TimeSpan"/> elapses then the value /// <see lang="false"/> is returned. If the time is less than or /// equal to zero, the method will not wait at all. /// /// <p/> /// In this implementation, as this method is an explicit /// interruption point, preference is given to responding to /// the interrupt over normal or reentrant acquisition of the /// lock, and over reporting the elapse of the waiting time. /// /// </remarks> /// <param name="durationToWait">the time to wait for the write lock</param> /// <returns> <see lang="true"/> if the lock was free and was acquired /// by the current thread, or the write lock was already held by the /// current thread; and <see lang="false"/> if the waiting time /// elapsed before the lock could be acquired. /// </returns> /// /// <exception cref="System.Threading.ThreadInterruptedException">if the current thread is interrupted.</exception> public override bool TryLock(TimeSpan durationToWait) { ThreadInterruptedException ie = null; lock (this) { if (durationToWait.TotalMilliseconds <= 0) { return(ReentrantReadWriteLock.StartWrite()); } else if (ReentrantReadWriteLock.StartWriteFromNewWriter()) { return(true); } else { DateTime deadline = DateTime.Now.Add(durationToWait); for (;;) { try { Monitor.Wait(this, durationToWait); } catch (ThreadInterruptedException ex) { ReentrantReadWriteLock.CancelWaitingWriter(); Monitor.Pulse(this); ie = ex; break; } if (ReentrantReadWriteLock.StartWriteFromWaitingWriter()) { return(true); } else { if (deadline.Subtract(DateTime.Now).TotalMilliseconds <= 0) { ReentrantReadWriteLock.CancelWaitingWriter(); Monitor.Pulse(this); break; } } } } } ReentrantReadWriteLock.SignallerReaderLock.SignalWaiters(); if (ie != null) { throw ie; } else { return(false); } }
/// <summary> /// Acquires the write lock unless <see cref="System.Threading.Thread.Interrupt()"/> is called on the current thread /// </summary> /// <remarks> /// Acquires the write lock if neither the read nor write locks /// are held by another thread /// and returns immediately, setting the write lock hold count to /// one. /// /// <p/> /// If the current thread already holds this lock then the /// hold count is incremented by one and the method returns /// immediately. /// /// <p/> /// If the lock is held by another thread then the current /// thread becomes disabled for thread scheduling purposes and /// lies dormant until one of two things happens: /// /// <ul> /// <li>The write lock is acquired by the current thread.</li> /// <li>Some other thread calls <see cref="System.Threading.Thread.Interrupt()"/> on the current thread.</li> /// </ul> /// /// <p/> /// If the write lock is acquired by the current thread then the /// lock hold count is set to one. /// /// <p/> /// If the current thread: /// <ul> /// <li>has its interrupted status set on entry to this method</li> /// <li><see cref="System.Threading.Thread.Interrupt()"/> is called on the thread while acquiring the write lock.</li> /// </ul> /// /// then a <see cref="System.Threading.ThreadInterruptedException"/> is thrown and the current /// thread's interrupted status is cleared. /// /// <p/> /// In this implementation, as this method is an explicit /// interruption point, preference is given to responding to /// the interrupt over normal or reentrant acquisition of the /// lock. /// /// </remarks> /// <exception cref="System.Threading.ThreadInterruptedException">if the current thread is interrupted.</exception> public override IDisposable LockInterruptibly() { ThreadInterruptedException ie = null; lock (this) { if (!ReentrantReadWriteLock.StartWriteFromNewWriter()) { for (;;) { try { Monitor.Wait(this); if (ReentrantReadWriteLock.StartWriteFromWaitingWriter()) { return(this); } } catch (ThreadInterruptedException ex) { ReentrantReadWriteLock.CancelWaitingWriter(); Monitor.Pulse(this); ie = ex; break; } } } } if (ie != null) { // Fall through outside synch on interrupt. // On exception, we may need to signal readers. // It is not worth checking here whether it is strictly necessary. ReentrantReadWriteLock.SignallerReaderLock.SignalWaiters(); throw ie; } return(this); }