Mercurial > pub > ImplabNet
diff Implab/Parallels/MTQueue.cs @ 97:b11c7e9d93bc v2
added enumerable interface to MTQueue
author | cin |
---|---|
date | Fri, 31 Oct 2014 17:34:54 +0300 |
parents | dc4942d09e74 |
children | 4c945d94b9ab |
line wrap: on
line diff
--- a/Implab/Parallels/MTQueue.cs Thu Oct 30 10:06:16 2014 +0300 +++ b/Implab/Parallels/MTQueue.cs Fri Oct 31 17:34:54 2014 +0300 @@ -1,7 +1,10 @@ using System.Threading; +using System.Collections.Generic; +using System; +using System.Collections; namespace Implab.Parallels { - public class MTQueue<T> { + public class MTQueue<T> : IEnumerable<T> { class Node { public Node(T value) { this.value = value; @@ -19,6 +22,8 @@ var last = m_last; var next = new Node(value); + // Interlocaked.CompareExchange implies Thread.MemoryBarrier(); + // to ensure that the next node is completely constructed while (last != Interlocked.CompareExchange(ref m_last, next, last)) last = m_last; @@ -69,5 +74,70 @@ value = first.value; return true; } + + #region IEnumerable implementation + + class Enumerator : IEnumerator<T> { + Node m_current; + Node m_first; + + public Enumerator(Node first) { + m_first = first; + } + + #region IEnumerator implementation + + public bool MoveNext() { + m_current = m_current == null ? m_first : m_current.next; + return m_current != null; + } + + public void Reset() { + m_current = null; + } + + public object IEnumerator.Current { + get { + if (m_current == null) + throw new InvalidOperationException(); + return m_current.value; + } + } + + #endregion + + #region IDisposable implementation + + public void Dispose() { + } + + #endregion + + #region IEnumerator implementation + + public T Current { + get { + if (m_current == null) + throw new InvalidOperationException(); + return m_current.value; + } + } + + #endregion + } + + public IEnumerator<T> GetEnumerator() { + return new Enumerator(m_first); + } + + #endregion + + #region IEnumerable implementation + + IEnumerator IEnumerable.GetEnumerator() { + return GetEnumerator(); + } + + #endregion } }