comparison Implab/Parallels/SimpleAsyncQueue.cs @ 242:cbe10ac0731e v3

Working on promises
author cin
date Wed, 24 Jan 2018 03:03:21 +0300
parents d6fe09f5592c
children
comparison
equal deleted inserted replaced
240:fa6cbf4d8841 242:cbe10ac0731e
13 public volatile Node next; 13 public volatile Node next;
14 } 14 }
15 15
16 // the reader and the writer are mainteined completely independent, 16 // the reader and the writer are mainteined completely independent,
17 // the reader can read next item when m_first.next is not null 17 // the reader can read next item when m_first.next is not null
18 // the writer creates the a new node, moves m_last to this node and 18 // the writer creates a new node, moves m_last to this node and
19 // only after that restores the reference from the previous node 19 // only after that restores the reference from the previous node
20 // making available the reader to read the new node. 20 // making the reader be able to read the new node.
21 21
22 Node m_first; // position on the node which is already read 22 volatile Node m_first; // position on the node which is already read
23 Node m_last; // position on the node which is already written 23 volatile Node m_last; // position on the node which is already written
24 24
25 public SimpleAsyncQueue() { 25 public SimpleAsyncQueue() {
26 m_first = m_last = new Node(default(T)); 26 m_first = m_last = new Node(default(T));
27 } 27 }
28 28
33 // to ensure that the next node is completely constructed 33 // to ensure that the next node is completely constructed
34 var last = Interlocked.Exchange(ref m_last, next); 34 var last = Interlocked.Exchange(ref m_last, next);
35 35
36 // release-fence 36 // release-fence
37 last.next = next; 37 last.next = next;
38 38
39 } 39 }
40 40
41 public bool TryDequeue(out T value) { 41 public bool TryDequeue(out T value) {
42 Node first; 42 Node first = m_first; ;
43 Node next; 43 Node next = first.next; ;
44 44
45 Thread.MemoryBarrier(); // ensure m_first is fresh 45 if (next == null) {
46 SpinWait spin = new SpinWait(); 46 value = default(T);
47 do { 47 return false;
48 first = m_first; 48 }
49 // aquire-fence 49
50 next = first.next; 50 var first2 = Interlocked.CompareExchange(ref m_first, next, first);
51 if (next == null) { 51
52 value = default(T); 52 if (first != first2) {
53 return false; 53 // head is updated by someone else
54 } 54
55 55 SpinWait spin = new SpinWait();
56 if (first == Interlocked.CompareExchange(ref m_first, next, first)) 56 do {
57 // head succesfully updated 57 first = first2;
58 break; 58 next = first.next;
59 spin.SpinOnce(); 59 if (next == null) {
60 } while (true); 60 value = default(T);
61 return false;
62 }
63
64 first2 = Interlocked.CompareExchange(ref m_first, next, first);
65 if (first == first2)
66 break;
67 spin.SpinOnce();
68 } while (true);
69 }
61 70
62 value = next.value; 71 value = next.value;
63 return true; 72 return true;
64 } 73 }
65 74