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 ReaderWriterLock mLock = new ReaderWriterLock(); /// /// Returns whether or not a writer lock is currently held. /// public bool WriterLockHeld { get { return mLock.IsWriterLockHeld; } } /// /// Returns whether or not a lock is currently held. /// public bool ReaderLockHeld { get { return mLock.IsReaderLockHeld || mLock.IsWriterLockHeld; } } /// /// 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.IsReaderLockHeld || mLock.IsWriterLockHeld) { return null; } mLock.AcquireReaderLock(-1); 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.IsWriterLockHeld) { return null; } if (mLock.IsReaderLockHeld) { return new UpgradedReadLock(mLock); } mLock.AcquireWriterLock(-1); return new WriteUnlocker(mLock); } private sealed class ReadUnlocker : IDisposable { private readonly ReaderWriterLock mLock; public ReadUnlocker(ReaderWriterLock theLock) { mLock = theLock; } public void Dispose() { mLock.ReleaseReaderLock(); } } private sealed class UpgradedReadLock : IDisposable { private readonly ReaderWriterLock mLock; public UpgradedReadLock(ReaderWriterLock aLock) { mLock = aLock; aLock.ReleaseReaderLock(); aLock.AcquireWriterLock(-1); } public void Dispose() { mLock.ReleaseWriterLock(); mLock.AcquireReaderLock(-1); } } private sealed class WriteUnlocker : IDisposable { private readonly ReaderWriterLock mLock; public WriteUnlocker(ReaderWriterLock theLock) { mLock = theLock; } public void Dispose() { mLock.ReleaseWriterLock(); } } } }