// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using System.Collections.Generic; using System.Reactive.Disposables; namespace System.Reactive.Concurrency { /// /// Base class for historical schedulers, which are virtual time schedulers that use DateTimeOffset for absolute time and TimeSpan for relative time. /// public abstract class HistoricalSchedulerBase : VirtualTimeSchedulerBase { /// /// Creates a new historical scheduler with the minimum value of DateTimeOffset as the initial clock value. /// protected HistoricalSchedulerBase() : base(DateTimeOffset.MinValue, Comparer.Default) { } /// /// Creates a new historical scheduler with the specified initial clock value. /// /// Initial clock value. protected HistoricalSchedulerBase(DateTimeOffset initialClock) : base(initialClock, Comparer.Default) { } /// /// Creates a new historical scheduler with the specified initial clock value and absolute time comparer. /// /// Initial value for the clock. /// Comparer to determine causality of events based on absolute time. protected HistoricalSchedulerBase(DateTimeOffset initialClock, IComparer comparer) : base(initialClock, comparer) { } /// /// Adds a relative time value to an absolute time value. /// /// Absolute time value. /// Relative time value to add. /// The resulting absolute time sum value. protected override DateTimeOffset Add(DateTimeOffset absolute, TimeSpan relative) { return absolute.Add(relative); } /// /// Converts the absolute time value to a DateTimeOffset value. /// /// Absolute time value to convert. /// The corresponding DateTimeOffset value. protected override DateTimeOffset ToDateTimeOffset(DateTimeOffset absolute) { return absolute; } /// /// Converts the TimeSpan value to a relative time value. /// /// TimeSpan value to convert. /// The corresponding relative time value. protected override TimeSpan ToRelative(TimeSpan timeSpan) { return timeSpan; } } /// /// Provides a virtual time scheduler that uses DateTimeOffset for absolute time and TimeSpan for relative time. /// public class HistoricalScheduler : HistoricalSchedulerBase { private readonly SchedulerQueue queue = new SchedulerQueue(); /// /// Creates a new historical scheduler with the minimum value of DateTimeOffset as the initial clock value. /// public HistoricalScheduler() : base() { } /// /// Creates a new historical scheduler with the specified initial clock value. /// /// Initial value for the clock. public HistoricalScheduler(DateTimeOffset initialClock) : base(initialClock) { } /// /// Creates a new historical scheduler with the specified initial clock value. /// /// Initial value for the clock. /// Comparer to determine causality of events based on absolute time. /// is null. public HistoricalScheduler(DateTimeOffset initialClock, IComparer comparer) : base(initialClock, comparer) { } /// /// Gets the next scheduled item to be executed. /// /// The next scheduled item. protected override IScheduledItem GetNext() { while (queue.Count > 0) { var next = queue.Peek(); if (next.IsCanceled) queue.Dequeue(); else return next; } return null; } /// /// Schedules an action to be executed at dueTime. /// /// The type of the state passed to the scheduled action. /// State passed to the action to be executed. /// Action to be executed. /// Absolute time at which to execute the action. /// The disposable object used to cancel the scheduled action (best effort). /// is null. public override IDisposable ScheduleAbsolute(TState state, DateTimeOffset dueTime, Func action) { if (action == null) throw new ArgumentNullException("action"); var si = default(ScheduledItem); var run = new Func((scheduler, state1) => { queue.Remove(si); return action(scheduler, state1); }); si = new ScheduledItem(this, state, run, dueTime, Comparer); queue.Enqueue(si); return Disposable.Create(si.Cancel); } } }