ScheduledItem.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. // this code is borrowed from RxOfficial(rx.codeplex.com) and modified
  2. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
  3. using System;
  4. using System.Collections.Generic;
  5. namespace UniRx.InternalUtil
  6. {
  7. /// <summary>
  8. /// Abstract base class for scheduled work items.
  9. /// </summary>
  10. internal class ScheduledItem : IComparable<ScheduledItem>
  11. {
  12. private readonly BooleanDisposable _disposable = new BooleanDisposable();
  13. private readonly TimeSpan _dueTime;
  14. private readonly Action _action;
  15. /// <summary>
  16. /// Creates a new scheduled work item to run at the specified time.
  17. /// </summary>
  18. /// <param name="dueTime">Absolute time at which the work item has to be executed.</param>
  19. public ScheduledItem(Action action, TimeSpan dueTime)
  20. {
  21. _dueTime = dueTime;
  22. _action = action;
  23. }
  24. /// <summary>
  25. /// Gets the absolute time at which the item is due for invocation.
  26. /// </summary>
  27. public TimeSpan DueTime
  28. {
  29. get { return _dueTime; }
  30. }
  31. /// <summary>
  32. /// Invokes the work item.
  33. /// </summary>
  34. public void Invoke()
  35. {
  36. if (!_disposable.IsDisposed)
  37. {
  38. _action();
  39. }
  40. }
  41. #region Inequality
  42. /// <summary>
  43. /// Compares the work item with another work item based on absolute time values.
  44. /// </summary>
  45. /// <param name="other">Work item to compare the current work item to.</param>
  46. /// <returns>Relative ordering between this and the specified work item.</returns>
  47. /// <remarks>The inequality operators are overloaded to provide results consistent with the IComparable implementation. Equality operators implement traditional reference equality semantics.</remarks>
  48. public int CompareTo(ScheduledItem other)
  49. {
  50. // MSDN: By definition, any object compares greater than null, and two null references compare equal to each other.
  51. if (object.ReferenceEquals(other, null))
  52. return 1;
  53. return DueTime.CompareTo(other.DueTime);
  54. }
  55. /// <summary>
  56. /// Determines whether one specified ScheduledItem&lt;TAbsolute&gt; object is due before a second specified ScheduledItem&lt;TAbsolute&gt; object.
  57. /// </summary>
  58. /// <param name="left">The first object to compare.</param>
  59. /// <param name="right">The second object to compare.</param>
  60. /// <returns>true if the DueTime value of left is earlier than the DueTime value of right; otherwise, false.</returns>
  61. /// <remarks>This operator provides results consistent with the IComparable implementation.</remarks>
  62. public static bool operator <(ScheduledItem left, ScheduledItem right)
  63. {
  64. return left.CompareTo(right) < 0;
  65. }
  66. /// <summary>
  67. /// Determines whether one specified ScheduledItem&lt;TAbsolute&gt; object is due before or at the same of a second specified ScheduledItem&lt;TAbsolute&gt; object.
  68. /// </summary>
  69. /// <param name="left">The first object to compare.</param>
  70. /// <param name="right">The second object to compare.</param>
  71. /// <returns>true if the DueTime value of left is earlier than or simultaneous with the DueTime value of right; otherwise, false.</returns>
  72. /// <remarks>This operator provides results consistent with the IComparable implementation.</remarks>
  73. public static bool operator <=(ScheduledItem left, ScheduledItem right)
  74. {
  75. return left.CompareTo(right) <= 0;
  76. }
  77. /// <summary>
  78. /// Determines whether one specified ScheduledItem&lt;TAbsolute&gt; object is due after a second specified ScheduledItem&lt;TAbsolute&gt; object.
  79. /// </summary>
  80. /// <param name="left">The first object to compare.</param>
  81. /// <param name="right">The second object to compare.</param>
  82. /// <returns>true if the DueTime value of left is later than the DueTime value of right; otherwise, false.</returns>
  83. /// <remarks>This operator provides results consistent with the IComparable implementation.</remarks>
  84. public static bool operator >(ScheduledItem left, ScheduledItem right)
  85. {
  86. return left.CompareTo(right) > 0;
  87. }
  88. /// <summary>
  89. /// Determines whether one specified ScheduledItem&lt;TAbsolute&gt; object is due after or at the same time of a second specified ScheduledItem&lt;TAbsolute&gt; object.
  90. /// </summary>
  91. /// <param name="left">The first object to compare.</param>
  92. /// <param name="right">The second object to compare.</param>
  93. /// <returns>true if the DueTime value of left is later than or simultaneous with the DueTime value of right; otherwise, false.</returns>
  94. /// <remarks>This operator provides results consistent with the IComparable implementation.</remarks>
  95. public static bool operator >=(ScheduledItem left, ScheduledItem right)
  96. {
  97. return left.CompareTo(right) >= 0;
  98. }
  99. #endregion
  100. #region Equality
  101. /// <summary>
  102. /// Determines whether two specified ScheduledItem&lt;TAbsolute, TValue&gt; objects are equal.
  103. /// </summary>
  104. /// <param name="left">The first object to compare.</param>
  105. /// <param name="right">The second object to compare.</param>
  106. /// <returns>true if both ScheduledItem&lt;TAbsolute, TValue&gt; are equal; otherwise, false.</returns>
  107. /// <remarks>This operator does not provide results consistent with the IComparable implementation. Instead, it implements reference equality.</remarks>
  108. public static bool operator ==(ScheduledItem left, ScheduledItem right)
  109. {
  110. return object.ReferenceEquals(left, right);
  111. }
  112. /// <summary>
  113. /// Determines whether two specified ScheduledItem&lt;TAbsolute, TValue&gt; objects are inequal.
  114. /// </summary>
  115. /// <param name="left">The first object to compare.</param>
  116. /// <param name="right">The second object to compare.</param>
  117. /// <returns>true if both ScheduledItem&lt;TAbsolute, TValue&gt; are inequal; otherwise, false.</returns>
  118. /// <remarks>This operator does not provide results consistent with the IComparable implementation. Instead, it implements reference equality.</remarks>
  119. public static bool operator !=(ScheduledItem left, ScheduledItem right)
  120. {
  121. return !(left == right);
  122. }
  123. /// <summary>
  124. /// Determines whether a ScheduledItem&lt;TAbsolute&gt; object is equal to the specified object.
  125. /// </summary>
  126. /// <param name="obj">The object to compare to the current ScheduledItem&lt;TAbsolute&gt; object.</param>
  127. /// <returns>true if the obj parameter is a ScheduledItem&lt;TAbsolute&gt; object and is equal to the current ScheduledItem&lt;TAbsolute&gt; object; otherwise, false.</returns>
  128. public override bool Equals(object obj)
  129. {
  130. return object.ReferenceEquals(this, obj);
  131. }
  132. /// <summary>
  133. /// Returns the hash code for the current ScheduledItem&lt;TAbsolute&gt; object.
  134. /// </summary>
  135. /// <returns>A 32-bit signed integer hash code.</returns>
  136. public override int GetHashCode()
  137. {
  138. return base.GetHashCode();
  139. }
  140. #endregion
  141. public IDisposable Cancellation
  142. {
  143. get
  144. {
  145. return _disposable;
  146. }
  147. }
  148. /// <summary>
  149. /// Gets whether the work item has received a cancellation request.
  150. /// </summary>
  151. public bool IsCanceled
  152. {
  153. get { return _disposable.IsDisposed; }
  154. }
  155. }
  156. /// <summary>
  157. /// Efficient scheduler queue that maintains scheduled items sorted by absolute time.
  158. /// </summary>
  159. /// <remarks>This type is not thread safe; users should ensure proper synchronization.</remarks>
  160. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix", Justification = "But it *is* a queue!")]
  161. internal class SchedulerQueue
  162. {
  163. private readonly PriorityQueue<ScheduledItem> _queue;
  164. /// <summary>
  165. /// Creates a new scheduler queue with a default initial capacity.
  166. /// </summary>
  167. public SchedulerQueue()
  168. : this(1024)
  169. {
  170. }
  171. /// <summary>
  172. /// Creats a new scheduler queue with the specified initial capacity.
  173. /// </summary>
  174. /// <param name="capacity">Initial capacity of the scheduler queue.</param>
  175. /// <exception cref="ArgumentOutOfRangeException"><paramref name="capacity"/> is less than zero.</exception>
  176. public SchedulerQueue(int capacity)
  177. {
  178. if (capacity < 0)
  179. throw new ArgumentOutOfRangeException("capacity");
  180. _queue = new PriorityQueue<ScheduledItem>(capacity);
  181. }
  182. /// <summary>
  183. /// Gets the number of scheduled items in the scheduler queue.
  184. /// </summary>
  185. public int Count
  186. {
  187. get
  188. {
  189. return _queue.Count;
  190. }
  191. }
  192. /// <summary>
  193. /// Enqueues the specified work item to be scheduled.
  194. /// </summary>
  195. /// <param name="scheduledItem">Work item to be scheduled.</param>
  196. public void Enqueue(ScheduledItem scheduledItem)
  197. {
  198. _queue.Enqueue(scheduledItem);
  199. }
  200. /// <summary>
  201. /// Removes the specified work item from the scheduler queue.
  202. /// </summary>
  203. /// <param name="scheduledItem">Work item to be removed from the scheduler queue.</param>
  204. /// <returns>true if the item was found; false otherwise.</returns>
  205. public bool Remove(ScheduledItem scheduledItem)
  206. {
  207. return _queue.Remove(scheduledItem);
  208. }
  209. /// <summary>
  210. /// Dequeues the next work item from the scheduler queue.
  211. /// </summary>
  212. /// <returns>Next work item in the scheduler queue (removed).</returns>
  213. public ScheduledItem Dequeue()
  214. {
  215. return _queue.Dequeue();
  216. }
  217. /// <summary>
  218. /// Peeks the next work item in the scheduler queue.
  219. /// </summary>
  220. /// <returns>Next work item in the scheduler queue (not removed).</returns>
  221. public ScheduledItem Peek()
  222. {
  223. return _queue.Peek();
  224. }
  225. }
  226. }