using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CarFire
{
///
/// A simple timer class. I'm not sure why .NET or at least
/// XNA doesn't already have one of these.
///
public class Timer : IComparable> where T : IComparable
{
#region Public Properties
///
/// Get and set the expiration time. If the time is already set
/// and the timer is registered, you cannot push the expiration time
/// further back, but you can decrease it.
///
public T Time
{
get
{
return mTime;
}
set
{
if (mTime.CompareTo(value) > 0)
{
mTime = value;
gTimers.Promote(this);
}
}
}
///
/// Get the current absolute time, accurate up until
/// the last time Timer.FireAll was called.
///
public static T Now { get { return gNow; } }
///
/// Get and set the events that will be called when the
/// timer expires.
///
public event ExpiredEventHandler Expired;
///
/// Get and set a user contextual object.
///
public object Context;
#endregion
#region Public Types
///
/// The type for an event handler for timers that expire.
///
/// The timer that expired.
public delegate void ExpiredEventHandler(Timer timer);
#endregion
#region Public Methods
///
/// Construct a timer with an absolute time (in seconds)
/// when the timer should expire.
///
/// Absolute time, in seconds.
public Timer(T time)
{
mTime = time;
gTimers.Add(this);
}
///
/// Construct a timer with an absolute time (in seconds)
/// when the timer should expire, and an event handler.
///
/// Absolute time, in seconds.
/// An event handler.
public Timer(T time, ExpiredEventHandler expired)
{
mTime = time;
Expired += expired;
gTimers.Add(this);
}
///
/// Construct a timer with an absolute time (in seconds)
/// when the timer should expire, and a contextual object.
///
/// Absolute time, in seconds.
/// A user contextual object.
public Timer(T time, object context)
{
mTime = time;
Context = context;
gTimers.Add(this);
}
///
/// Construct a timer with an absolute time (in seconds)
/// when the timer should expire, an event handler, and a
/// contextual object.
///
/// Absolute time, in seconds.
/// An event handler.
/// A user contextual object.
public Timer(T time, ExpiredEventHandler expired, object context)
{
mTime = time;
Expired += expired;
Context = context;
gTimers.Add(this);
}
///
/// Fire all outstanding timers which should be expired
/// before a certain time.
///
/// Absolute time, in seconds.
public static void FireExpired(T time)
{
gNow = time;
while (gTimers.Count > 0)
{
Timer timer = gTimers.Peek();
if (timer.Time.CompareTo(Now) <= 0)
{
if (timer.Expired != null) timer.Expired(timer);
if (timer.Time.CompareTo(Now) <= 0) gTimers.GetNext();
}
else
{
break;
}
}
}
///
/// Unregister all registered timers without firing any events.
///
public static void Clear()
{
gTimers.Clear();
}
///
/// Compare a timer with another, based on the expiration
/// times of both timers.
///
/// The timer to compare against.
/// A negative value if this timer is less than the
/// other, a positive value if this timer is greater than the
/// other, or zero if they are the same.
public int CompareTo(Timer other)
{
return Time.CompareTo(other.Time);
}
#endregion
#region Private Variables
T mTime;
static IPriorityQueue> gTimers = new BinaryHeap>(10);
static T gNow;
#endregion
}
}