/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

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