PageRenderTime 264ms CodeModel.GetById 121ms app.highlight 4ms RepoModel.GetById 137ms app.codeStats 0ms

/Rhino.Etl.Core/Enumerables/ThreadSafeEnumerator.cs

http://github.com/ayende/rhino-etl
C# | 128 lines | 65 code | 14 blank | 49 comment | 7 complexity | b698c7e96fac6c471917748c5fbb2a58 MD5 | raw file
  1namespace Rhino.Etl.Core.Enumerables
  2{
  3    using System;
  4    using System.Collections;
  5    using System.Collections.Generic;
  6    using System.Threading;
  7
  8    /// <summary>
  9    /// This enumerator allows to safely move items between threads. It takes
 10    /// care of all the syncronization.
 11    /// </summary>
 12    /// <typeparam name="T"></typeparam>
 13    public class ThreadSafeEnumerator<T> : IEnumerable<T>, IEnumerator<T>
 14    {
 15        private bool active = true;
 16        private readonly Queue<T> cached = new Queue<T>();
 17        private T current;
 18
 19        /// <summary>
 20        /// Returns an enumerator that iterates through the collection.
 21        /// </summary>
 22        /// <returns>
 23        /// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
 24        /// </returns>
 25        public IEnumerator<T> GetEnumerator()
 26        {
 27            return this;
 28        }
 29
 30        /// <summary>
 31        /// Returns an enumerator that iterates through a collection.
 32        /// </summary>
 33        /// <returns>
 34        /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
 35        /// </returns>
 36        IEnumerator IEnumerable.GetEnumerator()
 37        {
 38            return ((IEnumerable<T>)this).GetEnumerator();
 39        }
 40
 41        /// <summary>
 42        /// Gets the element in the collection at the current position of the enumerator.
 43        /// </summary>
 44        /// <value></value>
 45        /// <returns>The element in the collection at the current position of the enumerator.</returns>
 46        public T Current
 47        {
 48            get { return current; }
 49        }
 50
 51        /// <summary>
 52        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
 53        /// </summary>
 54        public void Dispose()
 55        {
 56            cached.Clear();
 57        }
 58
 59        /// <summary>
 60        /// Advances the enumerator to the next element of the collection.
 61        /// </summary>
 62        /// <returns>
 63        /// true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection.
 64        /// </returns>
 65        /// <exception cref="T:System.InvalidOperationException">The collection was modified after the enumerator was created. </exception>
 66        public bool MoveNext()
 67        {
 68            lock (cached)
 69            {
 70                while (cached.Count == 0 && active)
 71                    Monitor.Wait(cached);
 72
 73                if (active == false && cached.Count == 0)
 74                    return false;
 75
 76                current = cached.Dequeue();
 77
 78                return true;
 79            }
 80        }
 81
 82        /// <summary>
 83        /// Sets the enumerator to its initial position, which is before the first element in the collection.
 84        /// </summary>
 85        /// <exception cref="T:System.InvalidOperationException">The collection was modified after the enumerator was created. </exception>
 86        public void Reset()
 87        {
 88            throw new NotSupportedException();
 89        }
 90
 91        /// <summary>
 92        /// Gets the element in the collection at the current position of the enumerator.
 93        /// </summary>
 94        /// <value></value>
 95        /// <returns>The element in the collection at the current position of the enumerator.</returns>
 96        object IEnumerator.Current
 97        {
 98            get { return Current; }
 99        }
100
101        /// <summary>
102        /// Adds the item to the items this is enumerating on.
103        /// Will immediately release a waiting thread that can start working on itl
104        /// </summary>
105        /// <param name="item">The item.</param>
106        public void AddItem(T item)
107        {
108            lock (cached)
109            {
110                cached.Enqueue(item);
111                Monitor.Pulse(cached);
112            }
113        }
114
115        /// <summary>
116        /// Marks this instance as finished, so it will stop iterating
117        /// </summary>
118        public void MarkAsFinished()
119        {
120            lock (cached)
121            {
122                active = false;
123                Monitor.Pulse(cached);
124            }
125
126        }
127    }
128}