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 } }