Mercurial > pub > ImplabNet
diff Implab/Parallels/SimpleAsyncQueue.cs @ 242:cbe10ac0731e v3
Working on promises
author | cin |
---|---|
date | Wed, 24 Jan 2018 03:03:21 +0300 |
parents | d6fe09f5592c |
children |
line wrap: on
line diff
--- a/Implab/Parallels/SimpleAsyncQueue.cs Tue Jan 23 19:39:21 2018 +0300 +++ b/Implab/Parallels/SimpleAsyncQueue.cs Wed Jan 24 03:03:21 2018 +0300 @@ -15,12 +15,12 @@ // the reader and the writer are mainteined completely independent, // the reader can read next item when m_first.next is not null - // the writer creates the a new node, moves m_last to this node and + // the writer creates a new node, moves m_last to this node and // only after that restores the reference from the previous node - // making available the reader to read the new node. + // making the reader be able to read the new node. - Node m_first; // position on the node which is already read - Node m_last; // position on the node which is already written + volatile Node m_first; // position on the node which is already read + volatile Node m_last; // position on the node which is already written public SimpleAsyncQueue() { m_first = m_last = new Node(default(T)); @@ -35,29 +35,38 @@ // release-fence last.next = next; - + } public bool TryDequeue(out T value) { - Node first; - Node next; + Node first = m_first; ; + Node next = first.next; ; + + if (next == null) { + value = default(T); + return false; + } + + var first2 = Interlocked.CompareExchange(ref m_first, next, first); + + if (first != first2) { + // head is updated by someone else - Thread.MemoryBarrier(); // ensure m_first is fresh - SpinWait spin = new SpinWait(); - do { - first = m_first; - // aquire-fence - next = first.next; - if (next == null) { - value = default(T); - return false; - } - - if (first == Interlocked.CompareExchange(ref m_first, next, first)) - // head succesfully updated - break; - spin.SpinOnce(); - } while (true); + SpinWait spin = new SpinWait(); + do { + first = first2; + next = first.next; + if (next == null) { + value = default(T); + return false; + } + + first2 = Interlocked.CompareExchange(ref m_first, next, first); + if (first == first2) + break; + spin.SpinOnce(); + } while (true); + } value = next.value; return true;