using System; using System.Linq; using System.Threading; namespace Indy.IL2CPU.Assembler { /// /// 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(LockRecursionPolicy.SupportsRecursion); /// /// 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(); } } } }