Mercurial > pub > ImplabNet
diff Implab/Parallels/SharedLock.cs @ 129:471f596b2603 v2
Added SharedLock to synchronization routines
author | cin |
---|---|
date | Thu, 29 Jan 2015 18:31:06 +0300 |
parents | |
children | 671f60cd0250 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Parallels/SharedLock.cs Thu Jan 29 18:31:06 2015 +0300 @@ -0,0 +1,75 @@ +using System; +using System.Threading; +using System.Diagnostics; + +namespace Implab.Parallels { + /// <summary> + /// Implements a lightweight mechanism to aquire a shared or an exclusive lock. + /// </summary> + 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); + } + } + + } +} +