# HG changeset patch
# User cin
# Date 2015-01-29 15:31:06
# Node ID 471f596b26037cfda5566b4b505fcd2ba38b452d
# Parent  6241bff0cd64e284346ea70c208272528be53d54
Added SharedLock to synchronization routines
diff --git a/Implab/Implab.csproj b/Implab/Implab.csproj
--- a/Implab/Implab.csproj
+++ b/Implab/Implab.csproj
@@ -143,8 +143,6 @@
     
     
     
-    
-    
     
     
     
@@ -156,6 +154,7 @@
     
     
     
+    
   
   
   
diff --git a/Implab/Parallels/AsyncQueue.cs b/Implab/Parallels/AsyncQueue.cs
--- a/Implab/Parallels/AsyncQueue.cs
+++ b/Implab/Parallels/AsyncQueue.cs
@@ -495,11 +495,11 @@ namespace Implab.Parallels {
             #region ICollection implementation
 
             public void Add(T item) {
-                throw new InvalidOperationException();
+                throw new NotSupportedException();
             }
 
             public void Clear() {
-                throw new InvalidOperationException();
+                throw new NotSupportedException();
             }
 
             public bool Contains(T item) {
@@ -511,7 +511,7 @@ namespace Implab.Parallels {
             }
 
             public bool Remove(T item) {
-                throw new NotImplementedException();
+                throw new NotSupportedException();
             }
 
             public int Count {
diff --git a/Implab/Parallels/MTCustomQueue.cs b/Implab/Parallels/MTCustomQueue.cs
deleted file mode 100644
--- a/Implab/Parallels/MTCustomQueue.cs
+++ /dev/null
@@ -1,135 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Threading;
-using System.Collections;
-
-namespace Implab.Parallels {
-    public class MTCustomQueue : IEnumerable where TNode : MTCustomQueueNode {
-        TNode m_first;
-        TNode m_last;
-
-        public void Enqueue(TNode next) {
-            Thread.MemoryBarrier();
-
-            var last = m_last;
-
-            // Interlocaked.CompareExchange implies Thread.MemoryBarrier();
-            // to ensure that the next node is completely constructed
-            while (last != Interlocked.CompareExchange(ref m_last, next, last))
-                last = m_last;
-
-            if (last != null)
-                last.next = next;
-            else
-                m_first = next;
-        }
-
-        public bool TryDequeue(out TNode node) {
-            TNode first;
-            TNode next;
-            node = null;
-
-            Thread.MemoryBarrier();
-            do {
-                first = m_first;
-                if (first == null)
-                    return false;
-                next = first.next;
-                if (next == null) {
-                    // this is the last element,
-                    // then try to update the tail
-                    if (first != Interlocked.CompareExchange(ref m_last, null, first)) {
-                        // this is the race condition
-                        if (m_last == null)
-                            // the queue is empty
-                            return false;
-                        // tail has been changed, we need to restart
-                        continue; 
-                    }
-
-                    // tail succesfully updated and first.next will never be changed
-                    // other readers will fail due to inconsistency m_last != m_fist && m_first.next == null
-                    // however the parallel writer may update the m_first since the m_last is null
-
-                    // so we need to fix inconsistency by setting m_first to null or if it has been
-                    // updated by the writer already then we should just to give up
-                    Interlocked.CompareExchange(ref m_first, null, first);
-                    break;
-
-                }
-                if (first == Interlocked.CompareExchange(ref m_first, next, first))
-                    // head succesfully updated
-                    break;
-            } while (true);
-
-            node = first;
-            return true;
-        }
-
-        #region IEnumerable implementation
-
-        class Enumerator : IEnumerator {
-            TNode m_current;
-            TNode m_first;
-
-            public Enumerator(TNode first) {
-                m_first = first;
-            }
-
-            #region IEnumerator implementation
-
-            public bool MoveNext() {
-                m_current = m_current == null ? m_first : m_current.next;
-                return m_current != null;
-            }
-
-            public void Reset() {
-                m_current = null;
-            }
-
-            object IEnumerator.Current {
-                get {
-                    if (m_current == null)
-                        throw new InvalidOperationException();
-                    return m_current;
-                }
-            }
-
-            #endregion
-
-            #region IDisposable implementation
-
-            public void Dispose() {
-            }
-
-            #endregion
-
-            #region IEnumerator implementation
-
-            public TNode Current {
-                get {
-                    if (m_current == null)
-                        throw new InvalidOperationException();
-                    return m_current;
-                }
-            }
-
-            #endregion
-        }
-
-        public IEnumerator GetEnumerator() {
-            return new Enumerator(m_first);
-        }
-
-        #endregion
-
-        #region IEnumerable implementation
-
-        IEnumerator IEnumerable.GetEnumerator() {
-            return GetEnumerator();
-        }
-
-        #endregion
-    }
-}
-
diff --git a/Implab/Parallels/MTCustomQueueNode.cs b/Implab/Parallels/MTCustomQueueNode.cs
deleted file mode 100644
--- a/Implab/Parallels/MTCustomQueueNode.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Implab.Parallels {
-    public class MTCustomQueueNode where TNode : MTCustomQueueNode {
-        public TNode next;
-    }
-}
-
diff --git a/Implab/Parallels/SharedLock.cs b/Implab/Parallels/SharedLock.cs
new file mode 100644
--- /dev/null
+++ b/Implab/Parallels/SharedLock.cs
@@ -0,0 +1,75 @@
+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);
+            }
+        }
+
+    }
+}
+
diff --git a/Implab/Parallels/Signal.cs b/Implab/Parallels/Signal.cs
--- a/Implab/Parallels/Signal.cs
+++ b/Implab/Parallels/Signal.cs
@@ -3,7 +3,7 @@ using System.Threading;
 
 namespace Implab.Parallels {
     /// 
-    /// Implements simple signalling logic using .
+    /// Implements a simple signalling logic using .
     /// 
     public class Signal {
         readonly object m_lock = new object();
diff --git a/Implab/Parallels/WorkerPool.cs b/Implab/Parallels/WorkerPool.cs
--- a/Implab/Parallels/WorkerPool.cs
+++ b/Implab/Parallels/WorkerPool.cs
@@ -7,7 +7,7 @@ namespace Implab.Parallels {
     public class WorkerPool : DispatchPool {
 
         AsyncQueue m_queue = new AsyncQueue();
-        int m_queueLength = 0;
+        int m_queueLength;
         readonly int m_threshold = 1;
 
         public WorkerPool(int minThreads, int maxThreads, int threshold)
@@ -40,7 +40,7 @@ namespace Implab.Parallels {
 
             var lop = TraceContext.Instance.CurrentOperation;
 
-            EnqueueTask(delegate() {
+            EnqueueTask(delegate {
                 TraceContext.Instance.EnterLogicalOperation(lop, false);
                 try {
                     promise.Resolve(task());