// 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);
}
}
}