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);
+            }
+        }
+
+    }
+}
+