# HG changeset patch # User cin # Date 2014-10-31 14:34:54 # Node ID b11c7e9d93bcd49a34061f078c3318eee8bb4257 # Parent daffa72a1cec3507401e2294a6912902c20e351d added enumerable interface to MTQueue diff --git a/Implab/Parallels/MTQueue.cs b/Implab/Parallels/MTQueue.cs --- a/Implab/Parallels/MTQueue.cs +++ b/Implab/Parallels/MTQueue.cs @@ -1,7 +1,10 @@ using System.Threading; +using System.Collections.Generic; +using System; +using System.Collections; namespace Implab.Parallels { - public class MTQueue { + public class MTQueue : IEnumerable { class Node { public Node(T value) { this.value = value; @@ -19,6 +22,8 @@ namespace Implab.Parallels { 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 @@ namespace Implab.Parallels { value = first.value; return true; } + + #region IEnumerable implementation + + class Enumerator : IEnumerator { + 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 GetEnumerator() { + return new Enumerator(m_first); + } + + #endregion + + #region IEnumerable implementation + + IEnumerator IEnumerable.GetEnumerator() { + return GetEnumerator(); + } + + #endregion } }