|
@@ -191,52 +191,48 @@ namespace System.Reactive.Concurrency
|
|
|
if (action == null)
|
|
|
throw new ArgumentNullException(nameof(action));
|
|
|
|
|
|
- var start = _stopwatch.Elapsed;
|
|
|
- var next = start + period;
|
|
|
-
|
|
|
- var state1 = state;
|
|
|
+ return new PeriodicallyScheduledWorkItem<TState>(this, state, period, action);
|
|
|
+ }
|
|
|
|
|
|
- var td = new TernaryDisposable();
|
|
|
+ private sealed class PeriodicallyScheduledWorkItem<TState> : IDisposable
|
|
|
+ {
|
|
|
+ private readonly TimeSpan _period;
|
|
|
+ private readonly Func<TState, TState> _action;
|
|
|
+ private readonly EventLoopScheduler _scheduler;
|
|
|
+ private readonly AsyncLock _gate = new AsyncLock();
|
|
|
|
|
|
- var gate = new AsyncLock();
|
|
|
- td.Extra = gate;
|
|
|
+ private TState _state;
|
|
|
+ private TimeSpan _next;
|
|
|
+ private IDisposable _task;
|
|
|
|
|
|
- var tick = default(Func<IScheduler, object, IDisposable>);
|
|
|
- tick = (self_, _) =>
|
|
|
+ public PeriodicallyScheduledWorkItem(EventLoopScheduler scheduler, TState state, TimeSpan period, Func<TState, TState> action)
|
|
|
{
|
|
|
- next += period;
|
|
|
+ _state = state;
|
|
|
+ _period = period;
|
|
|
+ _action = action;
|
|
|
+ _scheduler = scheduler;
|
|
|
+ _next = scheduler._stopwatch.Elapsed + period;
|
|
|
|
|
|
- td.Next = self_.Schedule(null, next - _stopwatch.Elapsed, tick);
|
|
|
-
|
|
|
- gate.Wait(() =>
|
|
|
- {
|
|
|
- state1 = action(state1);
|
|
|
- });
|
|
|
-
|
|
|
- return Disposable.Empty;
|
|
|
- };
|
|
|
+ Disposable.TrySetSingle(ref _task, scheduler.Schedule(this, _next - scheduler._stopwatch.Elapsed, (_, s) => s.Tick(_)));
|
|
|
+ }
|
|
|
|
|
|
- td.First = Schedule(null, next - _stopwatch.Elapsed, tick);
|
|
|
+ private IDisposable Tick(IScheduler self)
|
|
|
+ {
|
|
|
+ _next += _period;
|
|
|
|
|
|
- return td;
|
|
|
- }
|
|
|
+ Disposable.TrySetMultiple(ref _task, self.Schedule(this, _next - _scheduler._stopwatch.Elapsed, (_, s) => s.Tick(_)));
|
|
|
|
|
|
- private sealed class TernaryDisposable : IDisposable
|
|
|
- {
|
|
|
- private IDisposable _task;
|
|
|
- private IDisposable _extra;
|
|
|
+ _gate.Wait(
|
|
|
+ this,
|
|
|
+ closureWorkItem => closureWorkItem._state = closureWorkItem._action(closureWorkItem._state));
|
|
|
|
|
|
- // If Next was called before this assignment is executed, it won't overwrite
|
|
|
- // a more fresh IDisposable task
|
|
|
- public IDisposable First { set { Disposable.TrySetSingle(ref _task, value); } }
|
|
|
- // It is fine to overwrite the first or previous IDisposable task
|
|
|
- public IDisposable Next { set { Disposable.TrySetMultiple(ref _task, value); } }
|
|
|
- public IDisposable Extra { set { Disposable.SetSingle(ref _extra, value); } }
|
|
|
+ return Disposable.Empty;
|
|
|
+ }
|
|
|
|
|
|
public void Dispose()
|
|
|
{
|
|
|
Disposable.TryDispose(ref _task);
|
|
|
- Disposable.TryDispose(ref _extra);
|
|
|
+ _gate.Dispose();
|
|
|
}
|
|
|
}
|
|
|
|