public void Dispose() { // release lock switch (_status) { case ReadWriteLockStatus.Write: { var oldCounter = Concurrency.Atomic( ref _lockable._counter, counter => counter.SetWriterCount(counter.WriterCount() - 1).SetReaderCount(counter.ReaderCount())); Debug.Assert(oldCounter.WriterCount() > 0); if (oldCounter.WriterCount() > 0) { #if READWRITELOCK_TRACE Debug.Print("{0} #{1} release WriteLock", GetHashCode(), Thread.CurrentThread.ManagedThreadId); #endif _lockable._writeThreadID = 0; } else throw new InvalidOperationException("No write lock is held"); _status = ReadWriteLockStatus.None; } break; case ReadWriteLockStatus.Read: { var oldCounter = Concurrency.Atomic( ref _lockable._counter, counter => counter.SetReaderCount(counter.ReaderCount() - 1).SetWriterCount(counter.WriterCount())); if (oldCounter.ReaderCount() > 0) { #if READWRITELOCK_TRACE Debug.Print("{0} #{1} release ReadLock", GetHashCode(), Thread.CurrentThread.ManagedThreadId); #endif } else throw new InvalidOperationException("No read lock is held"); } break; default: throw new InvalidOperationException("No lock is held"); } GC.SuppressFinalize(this); }
public void Downgrade() { // update status switch (_status) { case ReadWriteLockStatus.Read: // already downgraded return; case ReadWriteLockStatus.None: throw new InvalidOperationException("Cannot downgrade lock that has been released"); } // switch write lock to read lock _lockable._writeThreadID = 0; Concurrency.Atomic(ref _lockable._counter, counter => 0.SetReaderCount(counter.ReaderCount() + 1).SetWriterCount(counter.WriterCount() - 1)); _status = ReadWriteLockStatus.Read; }
internal Lock(ReadWriteLockable lockable, ReadWriteLockStatus status) { _lockable = lockable; _status = status; }