using System; using System.Threading; using System.Diagnostics; namespace Implab.Parallels { /// /// Implements a lightweight mechanism to aquire a shared or an exclusive lock. /// public class SharedLock { readonly object m_lock = new object(); int m_locks; bool m_exclusive; public bool LockExclusive(int timeout) { lock (m_lock) { if (m_locks > 0 && !Monitor.Wait(m_lock, timeout)) return false; m_exclusive = true; m_locks = 1; } } public void LockExclusive() { LockExclusive(-1); } public bool LockShared(int timeout) { lock (m_lock) { if (!m_exclusive) { m_locks++; return true; } if (m_lock == 0) { m_exclusive = false; m_locks = 1; return true; } if (Monitor.Wait(m_lock, timeout)) { Debug.Assert(m_locks == 0); m_locks = 1; m_exclusive = false; return true; } return false; } } public void LockShared() { LockShared(-1); } public void ReleaseShared() { lock (m_lock) { if (m_exclusive || m_locks <= 0) throw new InvalidOperationException(); m_locks--; if (m_locks == 0) Monitor.PulseAll(m_lock); } } public void ReleaseExclusive() { lock (m_lock) { if (!m_exclusive && m_locks != 1) throw new InvalidOperationException(); m_locks = 0; Monitor.PulseAll(m_lock); } } } }