changeset 113:468d156e434e v2-1

working on linked list
author cin
date Wed, 10 Dec 2014 01:29:53 +0100
parents 38d6a4db35d7
children c19cee55e85e
files Implab/Implab.csproj Implab/Parallels/MTLinkedList.cs Implab/Parallels/MTLinkedListNode.cs
diffstat 3 files changed, 152 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/Implab/Implab.csproj	Wed Nov 19 13:34:09 2014 +0300
+++ b/Implab/Implab.csproj	Wed Dec 10 01:29:53 2014 +0100
@@ -150,6 +150,8 @@
     <Compile Include="PromiseEventType.cs" />
     <Compile Include="Parallels\MTCustomQueue.cs" />
     <Compile Include="Parallels\MTCustomQueueNode.cs" />
+    <Compile Include="Parallels\MTLinkedList.cs" />
+    <Compile Include="Parallels\MTLinkedListNode.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ItemGroup />
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab/Parallels/MTLinkedList.cs	Wed Dec 10 01:29:53 2014 +0100
@@ -0,0 +1,140 @@
+using System;
+using System.Threading;
+
+namespace Implab.Parallels {
+    public class MTLinkedList<TNode> where TNode : MTLinkedListNode<TNode> {
+        TNode m_first;
+        TNode m_last;
+
+        public void InsertAfter( TNode pos, TNode node) {
+            Safe.ArgumentNotNull(node, "node");
+            if (!Attach(node))
+                throw new InvalidOperationException("The specified node already attached to a list");
+
+            TNode next;
+
+            while (true) {
+                // insert first if pos == null
+                next = pos == null ? m_first : pos.next;
+                node.prev = pos;
+                node.next = next;
+                if (next == m_first) {
+                    if (next != Interlocked.CompareExchange(ref m_first, node, next))
+                        continue;
+                    // race
+                } else {
+                    if (next != Interlocked.CompareExchange(ref pos.next, node, next))
+                        continue;
+                    // race
+                }
+                break;
+            }
+
+            while (true) {
+                if (next == null) {
+                    if (pos != Interlocked.CompareExchange(ref m_last, node, pos))
+                        continue;
+                } else {
+                    if (pos != Interlocked.CompareExchange(ref next.prev, node, pos))
+                        continue;
+                }
+                break;
+            }
+        }
+
+        public void InsertBefore( TNode pos, TNode node) {
+            Safe.ArgumentNotNull(node, "node");
+
+            if (!Attach(node))
+                return;
+
+            TNode prev;
+
+            while (true) {
+                // insert first if pos == null
+                prev = pos == null ? m_last : pos.prev;
+                node.next = pos;
+                node.prev = prev;
+                if (prev == m_last) {
+                    if (prev != Interlocked.CompareExchange(ref m_last, node, prev))
+                        continue;
+                    // race
+                } else {
+                    if (prev != Interlocked.CompareExchange(ref pos.prev, node, prev))
+                        continue;
+                    // race
+                }
+                break;
+            }
+
+            while (true) {
+                if (prev == null) {
+                    if (pos != Interlocked.CompareExchange(ref m_first, node, pos))
+                        continue;
+                } else {
+                    if (pos != Interlocked.CompareExchange(ref prev.next, node, pos))
+                        continue;
+                }
+                break;
+            }
+        }
+
+        bool Detach(TNode node) {
+            MTLinkedList<TNode> parent;
+
+            do {
+                parent = node.parentList;
+                if (parent == null || parent != this)
+                    return false;
+            } while(parent != Interlocked.CompareExchange(ref node.parentList, null, parent));
+        }
+
+        bool Attach(TNode node) {
+            MTLinkedList<TNode> parent;
+
+            do {
+                parent = node.parentList;
+                if (parent != null)
+                    return false;
+            } while(parent != Interlocked.CompareExchange(ref node.parentList, this, parent));
+        }
+
+        public void Remove(TNode node) {
+            Safe.ArgumentNotNull(node, "node");
+
+            if (!Detach(node))
+                return;
+
+            TNode prev;
+            TNode next;
+
+            while (true) {
+                prev = node.prev;
+                next = node.next;
+
+                if (prev == null) {
+                    if (node != Interlocked.CompareExchange(ref m_first, next, node))
+                        continue;
+                } else {
+                    if (node != Interlocked.CompareExchange(ref prev.next, next, node))
+                        continue;
+                }
+
+                break;
+            }
+
+            while (true) {
+                if (next == null) {
+                    if (node != Interlocked.CompareExchange(ref m_last, prev, node))
+                        continue;
+                } else {
+                    if (node != Interlocked.CompareExchange(ref next.prev, prev, node))
+                        continue;
+                }
+                break;
+            }
+        }
+
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab/Parallels/MTLinkedListNode.cs	Wed Dec 10 01:29:53 2014 +0100
@@ -0,0 +1,10 @@
+using System;
+
+namespace Implab.Parallels {
+    public class MTLinkedListNode<TNode> where T : MTLinkedListNode<TNode> {
+        public MTLinkedList<TNode> parentList;  
+        public TNode next;
+        public TNode prev;
+    }
+}
+