Mercurial > pub > ImplabNet
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; + } +} +