annotate Implab/Parallels/MTLinkedList.cs @ 113:468d156e434e v2-1

working on linked list
author cin
date Wed, 10 Dec 2014 01:29:53 +0100
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
113
468d156e434e working on linked list
cin
parents:
diff changeset
1 using System;
468d156e434e working on linked list
cin
parents:
diff changeset
2 using System.Threading;
468d156e434e working on linked list
cin
parents:
diff changeset
3
468d156e434e working on linked list
cin
parents:
diff changeset
4 namespace Implab.Parallels {
468d156e434e working on linked list
cin
parents:
diff changeset
5 public class MTLinkedList<TNode> where TNode : MTLinkedListNode<TNode> {
468d156e434e working on linked list
cin
parents:
diff changeset
6 TNode m_first;
468d156e434e working on linked list
cin
parents:
diff changeset
7 TNode m_last;
468d156e434e working on linked list
cin
parents:
diff changeset
8
468d156e434e working on linked list
cin
parents:
diff changeset
9 public void InsertAfter( TNode pos, TNode node) {
468d156e434e working on linked list
cin
parents:
diff changeset
10 Safe.ArgumentNotNull(node, "node");
468d156e434e working on linked list
cin
parents:
diff changeset
11 if (!Attach(node))
468d156e434e working on linked list
cin
parents:
diff changeset
12 throw new InvalidOperationException("The specified node already attached to a list");
468d156e434e working on linked list
cin
parents:
diff changeset
13
468d156e434e working on linked list
cin
parents:
diff changeset
14 TNode next;
468d156e434e working on linked list
cin
parents:
diff changeset
15
468d156e434e working on linked list
cin
parents:
diff changeset
16 while (true) {
468d156e434e working on linked list
cin
parents:
diff changeset
17 // insert first if pos == null
468d156e434e working on linked list
cin
parents:
diff changeset
18 next = pos == null ? m_first : pos.next;
468d156e434e working on linked list
cin
parents:
diff changeset
19 node.prev = pos;
468d156e434e working on linked list
cin
parents:
diff changeset
20 node.next = next;
468d156e434e working on linked list
cin
parents:
diff changeset
21 if (next == m_first) {
468d156e434e working on linked list
cin
parents:
diff changeset
22 if (next != Interlocked.CompareExchange(ref m_first, node, next))
468d156e434e working on linked list
cin
parents:
diff changeset
23 continue;
468d156e434e working on linked list
cin
parents:
diff changeset
24 // race
468d156e434e working on linked list
cin
parents:
diff changeset
25 } else {
468d156e434e working on linked list
cin
parents:
diff changeset
26 if (next != Interlocked.CompareExchange(ref pos.next, node, next))
468d156e434e working on linked list
cin
parents:
diff changeset
27 continue;
468d156e434e working on linked list
cin
parents:
diff changeset
28 // race
468d156e434e working on linked list
cin
parents:
diff changeset
29 }
468d156e434e working on linked list
cin
parents:
diff changeset
30 break;
468d156e434e working on linked list
cin
parents:
diff changeset
31 }
468d156e434e working on linked list
cin
parents:
diff changeset
32
468d156e434e working on linked list
cin
parents:
diff changeset
33 while (true) {
468d156e434e working on linked list
cin
parents:
diff changeset
34 if (next == null) {
468d156e434e working on linked list
cin
parents:
diff changeset
35 if (pos != Interlocked.CompareExchange(ref m_last, node, pos))
468d156e434e working on linked list
cin
parents:
diff changeset
36 continue;
468d156e434e working on linked list
cin
parents:
diff changeset
37 } else {
468d156e434e working on linked list
cin
parents:
diff changeset
38 if (pos != Interlocked.CompareExchange(ref next.prev, node, pos))
468d156e434e working on linked list
cin
parents:
diff changeset
39 continue;
468d156e434e working on linked list
cin
parents:
diff changeset
40 }
468d156e434e working on linked list
cin
parents:
diff changeset
41 break;
468d156e434e working on linked list
cin
parents:
diff changeset
42 }
468d156e434e working on linked list
cin
parents:
diff changeset
43 }
468d156e434e working on linked list
cin
parents:
diff changeset
44
468d156e434e working on linked list
cin
parents:
diff changeset
45 public void InsertBefore( TNode pos, TNode node) {
468d156e434e working on linked list
cin
parents:
diff changeset
46 Safe.ArgumentNotNull(node, "node");
468d156e434e working on linked list
cin
parents:
diff changeset
47
468d156e434e working on linked list
cin
parents:
diff changeset
48 if (!Attach(node))
468d156e434e working on linked list
cin
parents:
diff changeset
49 return;
468d156e434e working on linked list
cin
parents:
diff changeset
50
468d156e434e working on linked list
cin
parents:
diff changeset
51 TNode prev;
468d156e434e working on linked list
cin
parents:
diff changeset
52
468d156e434e working on linked list
cin
parents:
diff changeset
53 while (true) {
468d156e434e working on linked list
cin
parents:
diff changeset
54 // insert first if pos == null
468d156e434e working on linked list
cin
parents:
diff changeset
55 prev = pos == null ? m_last : pos.prev;
468d156e434e working on linked list
cin
parents:
diff changeset
56 node.next = pos;
468d156e434e working on linked list
cin
parents:
diff changeset
57 node.prev = prev;
468d156e434e working on linked list
cin
parents:
diff changeset
58 if (prev == m_last) {
468d156e434e working on linked list
cin
parents:
diff changeset
59 if (prev != Interlocked.CompareExchange(ref m_last, node, prev))
468d156e434e working on linked list
cin
parents:
diff changeset
60 continue;
468d156e434e working on linked list
cin
parents:
diff changeset
61 // race
468d156e434e working on linked list
cin
parents:
diff changeset
62 } else {
468d156e434e working on linked list
cin
parents:
diff changeset
63 if (prev != Interlocked.CompareExchange(ref pos.prev, node, prev))
468d156e434e working on linked list
cin
parents:
diff changeset
64 continue;
468d156e434e working on linked list
cin
parents:
diff changeset
65 // race
468d156e434e working on linked list
cin
parents:
diff changeset
66 }
468d156e434e working on linked list
cin
parents:
diff changeset
67 break;
468d156e434e working on linked list
cin
parents:
diff changeset
68 }
468d156e434e working on linked list
cin
parents:
diff changeset
69
468d156e434e working on linked list
cin
parents:
diff changeset
70 while (true) {
468d156e434e working on linked list
cin
parents:
diff changeset
71 if (prev == null) {
468d156e434e working on linked list
cin
parents:
diff changeset
72 if (pos != Interlocked.CompareExchange(ref m_first, node, pos))
468d156e434e working on linked list
cin
parents:
diff changeset
73 continue;
468d156e434e working on linked list
cin
parents:
diff changeset
74 } else {
468d156e434e working on linked list
cin
parents:
diff changeset
75 if (pos != Interlocked.CompareExchange(ref prev.next, node, pos))
468d156e434e working on linked list
cin
parents:
diff changeset
76 continue;
468d156e434e working on linked list
cin
parents:
diff changeset
77 }
468d156e434e working on linked list
cin
parents:
diff changeset
78 break;
468d156e434e working on linked list
cin
parents:
diff changeset
79 }
468d156e434e working on linked list
cin
parents:
diff changeset
80 }
468d156e434e working on linked list
cin
parents:
diff changeset
81
468d156e434e working on linked list
cin
parents:
diff changeset
82 bool Detach(TNode node) {
468d156e434e working on linked list
cin
parents:
diff changeset
83 MTLinkedList<TNode> parent;
468d156e434e working on linked list
cin
parents:
diff changeset
84
468d156e434e working on linked list
cin
parents:
diff changeset
85 do {
468d156e434e working on linked list
cin
parents:
diff changeset
86 parent = node.parentList;
468d156e434e working on linked list
cin
parents:
diff changeset
87 if (parent == null || parent != this)
468d156e434e working on linked list
cin
parents:
diff changeset
88 return false;
468d156e434e working on linked list
cin
parents:
diff changeset
89 } while(parent != Interlocked.CompareExchange(ref node.parentList, null, parent));
468d156e434e working on linked list
cin
parents:
diff changeset
90 }
468d156e434e working on linked list
cin
parents:
diff changeset
91
468d156e434e working on linked list
cin
parents:
diff changeset
92 bool Attach(TNode node) {
468d156e434e working on linked list
cin
parents:
diff changeset
93 MTLinkedList<TNode> parent;
468d156e434e working on linked list
cin
parents:
diff changeset
94
468d156e434e working on linked list
cin
parents:
diff changeset
95 do {
468d156e434e working on linked list
cin
parents:
diff changeset
96 parent = node.parentList;
468d156e434e working on linked list
cin
parents:
diff changeset
97 if (parent != null)
468d156e434e working on linked list
cin
parents:
diff changeset
98 return false;
468d156e434e working on linked list
cin
parents:
diff changeset
99 } while(parent != Interlocked.CompareExchange(ref node.parentList, this, parent));
468d156e434e working on linked list
cin
parents:
diff changeset
100 }
468d156e434e working on linked list
cin
parents:
diff changeset
101
468d156e434e working on linked list
cin
parents:
diff changeset
102 public void Remove(TNode node) {
468d156e434e working on linked list
cin
parents:
diff changeset
103 Safe.ArgumentNotNull(node, "node");
468d156e434e working on linked list
cin
parents:
diff changeset
104
468d156e434e working on linked list
cin
parents:
diff changeset
105 if (!Detach(node))
468d156e434e working on linked list
cin
parents:
diff changeset
106 return;
468d156e434e working on linked list
cin
parents:
diff changeset
107
468d156e434e working on linked list
cin
parents:
diff changeset
108 TNode prev;
468d156e434e working on linked list
cin
parents:
diff changeset
109 TNode next;
468d156e434e working on linked list
cin
parents:
diff changeset
110
468d156e434e working on linked list
cin
parents:
diff changeset
111 while (true) {
468d156e434e working on linked list
cin
parents:
diff changeset
112 prev = node.prev;
468d156e434e working on linked list
cin
parents:
diff changeset
113 next = node.next;
468d156e434e working on linked list
cin
parents:
diff changeset
114
468d156e434e working on linked list
cin
parents:
diff changeset
115 if (prev == null) {
468d156e434e working on linked list
cin
parents:
diff changeset
116 if (node != Interlocked.CompareExchange(ref m_first, next, node))
468d156e434e working on linked list
cin
parents:
diff changeset
117 continue;
468d156e434e working on linked list
cin
parents:
diff changeset
118 } else {
468d156e434e working on linked list
cin
parents:
diff changeset
119 if (node != Interlocked.CompareExchange(ref prev.next, next, node))
468d156e434e working on linked list
cin
parents:
diff changeset
120 continue;
468d156e434e working on linked list
cin
parents:
diff changeset
121 }
468d156e434e working on linked list
cin
parents:
diff changeset
122
468d156e434e working on linked list
cin
parents:
diff changeset
123 break;
468d156e434e working on linked list
cin
parents:
diff changeset
124 }
468d156e434e working on linked list
cin
parents:
diff changeset
125
468d156e434e working on linked list
cin
parents:
diff changeset
126 while (true) {
468d156e434e working on linked list
cin
parents:
diff changeset
127 if (next == null) {
468d156e434e working on linked list
cin
parents:
diff changeset
128 if (node != Interlocked.CompareExchange(ref m_last, prev, node))
468d156e434e working on linked list
cin
parents:
diff changeset
129 continue;
468d156e434e working on linked list
cin
parents:
diff changeset
130 } else {
468d156e434e working on linked list
cin
parents:
diff changeset
131 if (node != Interlocked.CompareExchange(ref next.prev, prev, node))
468d156e434e working on linked list
cin
parents:
diff changeset
132 continue;
468d156e434e working on linked list
cin
parents:
diff changeset
133 }
468d156e434e working on linked list
cin
parents:
diff changeset
134 break;
468d156e434e working on linked list
cin
parents:
diff changeset
135 }
468d156e434e working on linked list
cin
parents:
diff changeset
136 }
468d156e434e working on linked list
cin
parents:
diff changeset
137
468d156e434e working on linked list
cin
parents:
diff changeset
138 }
468d156e434e working on linked list
cin
parents:
diff changeset
139 }
468d156e434e working on linked list
cin
parents:
diff changeset
140