ThreadPoolScheduler.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. #if !UNITY_METRO
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Text;
  6. using UniRx.InternalUtil;
  7. namespace UniRx
  8. {
  9. public static partial class Scheduler
  10. {
  11. public static readonly IScheduler ThreadPool = new ThreadPoolScheduler();
  12. class ThreadPoolScheduler : IScheduler, ISchedulerPeriodic
  13. {
  14. public ThreadPoolScheduler()
  15. {
  16. }
  17. public DateTimeOffset Now
  18. {
  19. get { return Scheduler.Now; }
  20. }
  21. public IDisposable Schedule(Action action)
  22. {
  23. var d = new BooleanDisposable();
  24. System.Threading.ThreadPool.QueueUserWorkItem(_ =>
  25. {
  26. if (!d.IsDisposed)
  27. {
  28. action();
  29. }
  30. });
  31. return d;
  32. }
  33. public IDisposable Schedule(DateTimeOffset dueTime, Action action)
  34. {
  35. return Schedule(dueTime - Now, action);
  36. }
  37. public IDisposable Schedule(TimeSpan dueTime, Action action)
  38. {
  39. return new Timer(dueTime, action);
  40. }
  41. public IDisposable SchedulePeriodic(TimeSpan period, Action action)
  42. {
  43. return new PeriodicTimer(period, action);
  44. }
  45. public void ScheduleQueueing<T>(ICancelable cancel, T state, Action<T> action)
  46. {
  47. System.Threading.ThreadPool.QueueUserWorkItem(callBackState =>
  48. {
  49. if (!cancel.IsDisposed)
  50. {
  51. action((T)callBackState);
  52. }
  53. }, state);
  54. }
  55. // timer was borrwed from Rx Official
  56. sealed class Timer : IDisposable
  57. {
  58. static readonly HashSet<System.Threading.Timer> s_timers = new HashSet<System.Threading.Timer>();
  59. private readonly SingleAssignmentDisposable _disposable;
  60. private Action _action;
  61. private System.Threading.Timer _timer;
  62. private bool _hasAdded;
  63. private bool _hasRemoved;
  64. public Timer(TimeSpan dueTime, Action action)
  65. {
  66. _disposable = new SingleAssignmentDisposable();
  67. _disposable.Disposable = Disposable.Create(Unroot);
  68. _action = action;
  69. _timer = new System.Threading.Timer(Tick, null, dueTime, TimeSpan.FromMilliseconds(System.Threading.Timeout.Infinite));
  70. lock (s_timers)
  71. {
  72. if (!_hasRemoved)
  73. {
  74. s_timers.Add(_timer);
  75. _hasAdded = true;
  76. }
  77. }
  78. }
  79. private void Tick(object state)
  80. {
  81. try
  82. {
  83. if (!_disposable.IsDisposed)
  84. {
  85. _action();
  86. }
  87. }
  88. finally
  89. {
  90. Unroot();
  91. }
  92. }
  93. private void Unroot()
  94. {
  95. _action = Stubs.Nop;
  96. var timer = default(System.Threading.Timer);
  97. lock (s_timers)
  98. {
  99. if (!_hasRemoved)
  100. {
  101. timer = _timer;
  102. _timer = null;
  103. if (_hasAdded && timer != null)
  104. s_timers.Remove(timer);
  105. _hasRemoved = true;
  106. }
  107. }
  108. if (timer != null)
  109. timer.Dispose();
  110. }
  111. public void Dispose()
  112. {
  113. _disposable.Dispose();
  114. }
  115. }
  116. sealed class PeriodicTimer : IDisposable
  117. {
  118. static readonly HashSet<System.Threading.Timer> s_timers = new HashSet<System.Threading.Timer>();
  119. private Action _action;
  120. private System.Threading.Timer _timer;
  121. private readonly AsyncLock _gate;
  122. public PeriodicTimer(TimeSpan period, Action action)
  123. {
  124. this._action = action;
  125. this._timer = new System.Threading.Timer(Tick, null, period, period);
  126. this._gate = new AsyncLock();
  127. lock (s_timers)
  128. {
  129. s_timers.Add(_timer);
  130. }
  131. }
  132. private void Tick(object state)
  133. {
  134. _gate.Wait(() =>
  135. {
  136. _action();
  137. });
  138. }
  139. public void Dispose()
  140. {
  141. var timer = default(System.Threading.Timer);
  142. lock (s_timers)
  143. {
  144. timer = _timer;
  145. _timer = null;
  146. if (timer != null)
  147. s_timers.Remove(timer);
  148. }
  149. if (timer != null)
  150. {
  151. timer.Dispose();
  152. _action = Stubs.Nop;
  153. }
  154. }
  155. }
  156. }
  157. }
  158. }
  159. #endif