ScheduledItem.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
  2. using System.Collections.Generic;
  3. using System.Reactive.Disposables;
  4. namespace System.Reactive.Concurrency
  5. {
  6. /// <summary>
  7. /// Abstract base class for scheduled work items.
  8. /// </summary>
  9. /// <typeparam name="TAbsolute">Absolute time representation type.</typeparam>
  10. public abstract class ScheduledItem<TAbsolute> : IScheduledItem<TAbsolute>, IComparable<ScheduledItem<TAbsolute>>
  11. where TAbsolute : IComparable<TAbsolute>
  12. {
  13. private readonly SingleAssignmentDisposable _disposable = new SingleAssignmentDisposable();
  14. private readonly TAbsolute _dueTime;
  15. private readonly IComparer<TAbsolute> _comparer;
  16. /// <summary>
  17. /// Creates a new scheduled work item to run at the specified time.
  18. /// </summary>
  19. /// <param name="dueTime">Absolute time at which the work item has to be executed.</param>
  20. /// <param name="comparer">Comparer used to compare work items based on their scheduled time.</param>
  21. /// <exception cref="ArgumentNullException"><paramref name="comparer"/> is null.</exception>
  22. protected ScheduledItem(TAbsolute dueTime, IComparer<TAbsolute> comparer)
  23. {
  24. if (comparer == null)
  25. throw new ArgumentNullException("comparer");
  26. _dueTime = dueTime;
  27. _comparer = comparer;
  28. }
  29. /// <summary>
  30. /// Gets the absolute time at which the item is due for invocation.
  31. /// </summary>
  32. public TAbsolute DueTime
  33. {
  34. get { return _dueTime; }
  35. }
  36. /// <summary>
  37. /// Invokes the work item.
  38. /// </summary>
  39. public void Invoke()
  40. {
  41. if (!_disposable.IsDisposed)
  42. _disposable.Disposable = InvokeCore();
  43. }
  44. /// <summary>
  45. /// Implement this method to perform the work item invocation, returning a disposable object for deep cancellation.
  46. /// </summary>
  47. /// <returns>Disposable object used to cancel the work item and/or derived work items.</returns>
  48. protected abstract IDisposable InvokeCore();
  49. #region Inequality
  50. /// <summary>
  51. /// Compares the work item with another work item based on absolute time values.
  52. /// </summary>
  53. /// <param name="other">Work item to compare the current work item to.</param>
  54. /// <returns>Relative ordering between this and the specified work item.</returns>
  55. /// <remarks>The inequality operators are overloaded to provide results consistent with the IComparable implementation. Equality operators implement traditional reference equality semantics.</remarks>
  56. public int CompareTo(ScheduledItem<TAbsolute> other)
  57. {
  58. // MSDN: By definition, any object compares greater than null, and two null references compare equal to each other.
  59. if (object.ReferenceEquals(other, null))
  60. return 1;
  61. return _comparer.Compare(DueTime, other.DueTime);
  62. }
  63. /// <summary>
  64. /// Determines whether one specified ScheduledItem&lt;TAbsolute&gt; object is due before a second specified ScheduledItem&lt;TAbsolute&gt; object.
  65. /// </summary>
  66. /// <param name="left">The first object to compare.</param>
  67. /// <param name="right">The second object to compare.</param>
  68. /// <returns>true if the DueTime value of left is earlier than the DueTime value of right; otherwise, false.</returns>
  69. /// <remarks>This operator provides results consistent with the IComparable implementation.</remarks>
  70. public static bool operator <(ScheduledItem<TAbsolute> left, ScheduledItem<TAbsolute> right)
  71. {
  72. return Comparer<ScheduledItem<TAbsolute>>.Default.Compare(left, right) < 0;
  73. }
  74. /// <summary>
  75. /// 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.
  76. /// </summary>
  77. /// <param name="left">The first object to compare.</param>
  78. /// <param name="right">The second object to compare.</param>
  79. /// <returns>true if the DueTime value of left is earlier than or simultaneous with the DueTime value of right; otherwise, false.</returns>
  80. /// <remarks>This operator provides results consistent with the IComparable implementation.</remarks>
  81. public static bool operator <=(ScheduledItem<TAbsolute> left, ScheduledItem<TAbsolute> right)
  82. {
  83. return Comparer<ScheduledItem<TAbsolute>>.Default.Compare(left, right) <= 0;
  84. }
  85. /// <summary>
  86. /// Determines whether one specified ScheduledItem&lt;TAbsolute&gt; object is due after a second specified ScheduledItem&lt;TAbsolute&gt; object.
  87. /// </summary>
  88. /// <param name="left">The first object to compare.</param>
  89. /// <param name="right">The second object to compare.</param>
  90. /// <returns>true if the DueTime value of left is later than the DueTime value of right; otherwise, false.</returns>
  91. /// <remarks>This operator provides results consistent with the IComparable implementation.</remarks>
  92. public static bool operator >(ScheduledItem<TAbsolute> left, ScheduledItem<TAbsolute> right)
  93. {
  94. return Comparer<ScheduledItem<TAbsolute>>.Default.Compare(left, right) > 0;
  95. }
  96. /// <summary>
  97. /// 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.
  98. /// </summary>
  99. /// <param name="left">The first object to compare.</param>
  100. /// <param name="right">The second object to compare.</param>
  101. /// <returns>true if the DueTime value of left is later than or simultaneous with the DueTime value of right; otherwise, false.</returns>
  102. /// <remarks>This operator provides results consistent with the IComparable implementation.</remarks>
  103. public static bool operator >=(ScheduledItem<TAbsolute> left, ScheduledItem<TAbsolute> right)
  104. {
  105. return Comparer<ScheduledItem<TAbsolute>>.Default.Compare(left, right) >= 0;
  106. }
  107. #endregion
  108. #region Equality
  109. /// <summary>
  110. /// Determines whether two specified ScheduledItem&lt;TAbsolute, TValue&gt; objects are equal.
  111. /// </summary>
  112. /// <param name="left">The first object to compare.</param>
  113. /// <param name="right">The second object to compare.</param>
  114. /// <returns>true if both ScheduledItem&lt;TAbsolute, TValue&gt; are equal; otherwise, false.</returns>
  115. /// <remarks>This operator does not provide results consistent with the IComparable implementation. Instead, it implements reference equality.</remarks>
  116. public static bool operator ==(ScheduledItem<TAbsolute> left, ScheduledItem<TAbsolute> right)
  117. {
  118. return object.ReferenceEquals(left, right);
  119. }
  120. /// <summary>
  121. /// Determines whether two specified ScheduledItem&lt;TAbsolute, TValue&gt; objects are inequal.
  122. /// </summary>
  123. /// <param name="left">The first object to compare.</param>
  124. /// <param name="right">The second object to compare.</param>
  125. /// <returns>true if both ScheduledItem&lt;TAbsolute, TValue&gt; are inequal; otherwise, false.</returns>
  126. /// <remarks>This operator does not provide results consistent with the IComparable implementation. Instead, it implements reference equality.</remarks>
  127. public static bool operator !=(ScheduledItem<TAbsolute> left, ScheduledItem<TAbsolute> right)
  128. {
  129. return !(left == right);
  130. }
  131. /// <summary>
  132. /// Determines whether a ScheduledItem&lt;TAbsolute&gt; object is equal to the specified object.
  133. /// </summary>
  134. /// <param name="obj">The object to compare to the current ScheduledItem&lt;TAbsolute&gt; object.</param>
  135. /// <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>
  136. public override bool Equals(object obj)
  137. {
  138. return object.ReferenceEquals(this, obj);
  139. }
  140. /// <summary>
  141. /// Returns the hash code for the current ScheduledItem&lt;TAbsolute&gt; object.
  142. /// </summary>
  143. /// <returns>A 32-bit signed integer hash code.</returns>
  144. public override int GetHashCode()
  145. {
  146. return base.GetHashCode();
  147. }
  148. #endregion
  149. /// <summary>
  150. /// Cancels the work item by disposing the resource returned by InvokeCore as soon as possible.
  151. /// </summary>
  152. public void Cancel()
  153. {
  154. _disposable.Dispose();
  155. }
  156. /// <summary>
  157. /// Gets whether the work item has received a cancellation request.
  158. /// </summary>
  159. public bool IsCanceled
  160. {
  161. get { return _disposable.IsDisposed; }
  162. }
  163. }
  164. /// <summary>
  165. /// Represents a scheduled work item based on the materialization of an IScheduler.Schedule method call.
  166. /// </summary>
  167. /// <typeparam name="TAbsolute">Absolute time representation type.</typeparam>
  168. /// <typeparam name="TValue">Type of the state passed to the scheduled action.</typeparam>
  169. public sealed class ScheduledItem<TAbsolute, TValue> : ScheduledItem<TAbsolute>
  170. where TAbsolute : IComparable<TAbsolute>
  171. {
  172. private readonly IScheduler _scheduler;
  173. private readonly TValue _state;
  174. private readonly Func<IScheduler, TValue, IDisposable> _action;
  175. /// <summary>
  176. /// Creates a materialized work item.
  177. /// </summary>
  178. /// <param name="scheduler">Recursive scheduler to invoke the scheduled action with.</param>
  179. /// <param name="state">State to pass to the scheduled action.</param>
  180. /// <param name="action">Scheduled action.</param>
  181. /// <param name="dueTime">Time at which to run the scheduled action.</param>
  182. /// <param name="comparer">Comparer used to compare work items based on their scheduled time.</param>
  183. /// <exception cref="ArgumentNullException"><paramref name="scheduler"/> or <paramref name="action"/> or <paramref name="comparer"/> is null.</exception>
  184. public ScheduledItem(IScheduler scheduler, TValue state, Func<IScheduler, TValue, IDisposable> action, TAbsolute dueTime, IComparer<TAbsolute> comparer)
  185. : base(dueTime, comparer)
  186. {
  187. if (scheduler == null)
  188. throw new ArgumentNullException("scheduler");
  189. if (action == null)
  190. throw new ArgumentNullException("action");
  191. _scheduler = scheduler;
  192. _state = state;
  193. _action = action;
  194. }
  195. /// <summary>
  196. /// Creates a materialized work item.
  197. /// </summary>
  198. /// <param name="scheduler">Recursive scheduler to invoke the scheduled action with.</param>
  199. /// <param name="state">State to pass to the scheduled action.</param>
  200. /// <param name="action">Scheduled action.</param>
  201. /// <param name="dueTime">Time at which to run the scheduled action.</param>
  202. /// <exception cref="ArgumentNullException"><paramref name="scheduler"/> or <paramref name="action"/> is null.</exception>
  203. public ScheduledItem(IScheduler scheduler, TValue state, Func<IScheduler, TValue, IDisposable> action, TAbsolute dueTime)
  204. : this(scheduler, state, action, dueTime, Comparer<TAbsolute>.Default)
  205. {
  206. }
  207. /// <summary>
  208. /// Invokes the scheduled action with the supplied recursive scheduler and state.
  209. /// </summary>
  210. /// <returns>Cancellation resource returned by the scheduled action.</returns>
  211. protected override IDisposable InvokeCore()
  212. {
  213. return _action(_scheduler, _state);
  214. }
  215. }
  216. }