using System; using System.Linq; using System.Threading; namespace Cosmos.IL2CPU { /// /// provides an easier interface to . It wraps Acquire/Release pairs using an IDisposable /// implementation, and automatically upgrades reader locks, if neccessary. /// public sealed class ReaderWriterLocker { private readonly ReaderWriterLockSlim mLock = new ReaderWriterLockSlim(); /// /// Returns whether or not a writer lock is currently held. /// public bool WriterLockHeld { get { return mLock.IsWriteLockHeld; } } /// /// Returns whether or not a lock is currently held. /// public bool ReaderLockHeld { get { return mLock.IsReadLockHeld || mLock.IsWriteLockHeld; } } /// /// Acquires a reader lock, if there's currently no lock held. /// /// A implementation, which releases the reader lock on disposal, or null if there was /// already a reader lock held. public IDisposable AcquireReaderLock() { if( mLock.IsReadLockHeld || mLock.IsWriteLockHeld ) { return null; } mLock.EnterReadLock(); return new ReadUnlocker( mLock ); } /// /// Acquires a writer lock, if there's currently no lock held. /// /// A implementation, which restores the lock state on disposal, or null if there was /// already a reader lock held. public IDisposable AcquireWriterLock() { if( mLock.IsWriteLockHeld ) { return null; } if( mLock.IsReadLockHeld ) { return new UpgradedReadLock( mLock ); } mLock.EnterWriteLock(); return new WriteUnlocker( mLock ); } private sealed class ReadUnlocker : IDisposable { private readonly ReaderWriterLockSlim mLock; public ReadUnlocker( ReaderWriterLockSlim theLock ) { mLock = theLock; } public void Dispose() { mLock.ExitReadLock(); } } private sealed class UpgradedReadLock : IDisposable { private readonly ReaderWriterLockSlim mLock; public UpgradedReadLock( ReaderWriterLockSlim aLock ) { mLock = aLock; aLock.ExitReadLock(); aLock.EnterWriteLock(); } public void Dispose() { mLock.ExitWriteLock(); mLock.EnterReadLock(); } } private sealed class WriteUnlocker : IDisposable { private readonly ReaderWriterLockSlim mLock; public WriteUnlocker( ReaderWriterLockSlim theLock ) { mLock = theLock; } public void Dispose() { mLock.ExitWriteLock(); } } } }