annotate Implab/Parallels/MTQueue.cs @ 94:a43745f81f10 v2

minor fixes
author cin
date Thu, 23 Oct 2014 17:50:09 +0400
parents dc4942d09e74
children b11c7e9d93bc
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
93
dc4942d09e74 improved tracing
cin
parents: 80
diff changeset
1 using System.Threading;
14
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
2
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
3 namespace Implab.Parallels {
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
4 public class MTQueue<T> {
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
5 class Node {
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
6 public Node(T value) {
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
7 this.value = value;
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
8 }
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
9 public readonly T value;
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
10 public Node next;
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
11 }
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
12
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
13 Node m_first;
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
14 Node m_last;
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
15
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
16 public void Enqueue(T value) {
80
4f20870d0816 added memory barriers
cin
parents: 71
diff changeset
17 Thread.MemoryBarrier();
4f20870d0816 added memory barriers
cin
parents: 71
diff changeset
18
14
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
19 var last = m_last;
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
20 var next = new Node(value);
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
21
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
22 while (last != Interlocked.CompareExchange(ref m_last, next, last))
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
23 last = m_last;
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
24
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
25 if (last != null)
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
26 last.next = next;
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
27 else
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
28 m_first = next;
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
29 }
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
30
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
31 public bool TryDequeue(out T value) {
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
32 Node first;
93
dc4942d09e74 improved tracing
cin
parents: 80
diff changeset
33 Node next;
14
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
34 value = default(T);
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
35
80
4f20870d0816 added memory barriers
cin
parents: 71
diff changeset
36 Thread.MemoryBarrier();
14
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
37 do {
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
38 first = m_first;
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
39 if (first == null)
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
40 return false;
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
41 next = first.next;
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
42 if (next == null) {
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
43 // this is the last element,
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 14
diff changeset
44 // then try to update the tail
14
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
45 if (first != Interlocked.CompareExchange(ref m_last, null, first)) {
71
1714fd8678ef code cleanup
cin
parents: 24
diff changeset
46 // this is the race condition
14
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
47 if (m_last == null)
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 14
diff changeset
48 // the queue is empty
14
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
49 return false;
71
1714fd8678ef code cleanup
cin
parents: 24
diff changeset
50 // tail has been changed, we need to restart
14
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
51 continue;
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
52 }
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
53
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
54 // tail succesfully updated and first.next will never be changed
71
1714fd8678ef code cleanup
cin
parents: 24
diff changeset
55 // other readers will fail due to inconsistency m_last != m_fist && m_first.next == null
1714fd8678ef code cleanup
cin
parents: 24
diff changeset
56 // however the parallel writer may update the m_first since the m_last is null
14
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
57
71
1714fd8678ef code cleanup
cin
parents: 24
diff changeset
58 // so we need to fix inconsistency by setting m_first to null or if it has been
1714fd8678ef code cleanup
cin
parents: 24
diff changeset
59 // updated by the writer already then we should just to give up
14
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
60 Interlocked.CompareExchange(ref m_first, null, first);
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
61 break;
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
62
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
63 }
93
dc4942d09e74 improved tracing
cin
parents: 80
diff changeset
64 if (first == Interlocked.CompareExchange(ref m_first, next, first))
dc4942d09e74 improved tracing
cin
parents: 80
diff changeset
65 // head succesfully updated
dc4942d09e74 improved tracing
cin
parents: 80
diff changeset
66 break;
14
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
67 } while (true);
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
68
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
69 value = first.value;
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
70 return true;
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
71 }
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
72 }
e943453e5039 Implemented interllocked queue
cin
parents:
diff changeset
73 }