-/*
- * Timer.h
- *
- * Created on: Aug 10, 2012
- * Author: holy
- */
-
#ifndef APP_TIMER_H_
#define APP_TIMER_H_
namespace app {
+/// Stores timing information.
+/// For use by app::Timer.
template<class Time>
struct TimerData {
- TimerData() : time(0), target(0), refCount(0), justHit(false) { }
- TimerData(Time target) : time(0), target(target), refCount(0), justHit(false) { }
+ TimerData() : time(0), target(0), refCount(0), justHit(false), repeat(false) { }
+ TimerData(Time target, bool repeat) : time(0), target(target), refCount(0), justHit(false), repeat(repeat) { }
Time time;
Time target;
int refCount;
bool justHit;
+ bool repeat;
};
+/// Timer handle.
+/// How the various information returned by the const member functions is to be
+/// interpreted highly depends on how the timer was created (by app::Timers).
template<class Time>
class Timer {
}
public:
- bool Running() const {
+ /// Check if the timer was started (and not cleared) yet.
+ bool Started() const {
return data;
}
+ /// Check if the timer has reached its target time (only sensible for
+ /// countdown timers).
bool Finished() const {
- return data ? data->time >= data->target : false;
+ return data && data->target != Time() && !data->repeat && data->time >= data->target;
}
+ /// Check if the timer was started and has not finished yet (in case it's a
+ /// countdown).
+ bool Running() const {
+ return data && !Finished();
+ }
+ /// Get the elapsed time since the timer started.
Time Elapsed() const {
return data ? data->time : Time();
}
+ /// Get the time remaining for countdowns.
Time Remaining() const {
return data ? (data->target - data->time) : Time();
}
+ /// Time from start to hit.
+ Time TargetTime() const {
+ return data ? data->target : Time();
+ }
+ /// Get the elapsed time since the timer started or last hit.
+ Time IterationElapsed() const {
+ return data ? data->time % data->target : Time();
+ }
+ /// Get the remaining time in this iteration.
+ Time IterationRemaining() const {
+ return TargetTime() - IterationElapsed();
+ }
+ /// Get the iteration index for interval timers.
int Iteration() const {
- return (data && data->target > 0) ? std::floor(data->time / data->target) : 0;
+ return (data && data->target > Time()) ? std::floor(data->time / data->target) : Time();
}
+ /// Check if the timer reached its interval or countdown goal this iteration.
bool JustHit() const {
return data && data->justHit;
}
+ /// Unset the timer (does not stop other handles for a shared timer).
+ void Clear() {
+ if (data) {
+ --data->refCount;
+ data = 0;
+ }
+ }
+ /// Reset the timer, do not stop it if it's running.
void Reset() {
- if (data) data->time = 0;
+ if (data) data->time = Time();
}
+ /// Restart the timer.
+ /// Only works if the timer was started at least once.
void Restart() {
if (data) {
- if (data->target > 0 && data->justHit) {
+ if (data->target > Time() && data->justHit) {
data->time -= data->target;
} else {
- data->time = 0;
+ data->time = Time();
}
}
}
};
+/// Tracker for timers, responsible for creating and updating them.
template<class Time>
class Timers {
Timers() { }
public:
+ /// Move all timers forward by delta.
void Update(Time delta) {
for (typename std::list<TimerData<Time> >::iterator i(data.begin()), end(data.end()); i != end;) {
if (i->target > 0) {
Time intervalTime(i->time);
- while (intervalTime > i->target) intervalTime -= i->target;
+ if (i->repeat) while (intervalTime > i->target) intervalTime -= i->target;
i->justHit = intervalTime < i->target && intervalTime + delta >= i->target;
}
i->time += delta;
}
}
}
+ /// Start a timer that counts elapsed time until stopped manually.
Timer<Time> StartTimer() {
data.push_back(TimerData<Time>());
return Timer<Time>(&data.back());
}
+ /// Start a countdown that hits (JustHit() returing true) when duration
+ /// elapsed.
Timer<Time> StartCountdown(Time duration) {
- data.push_back(TimerData<Time>(duration));
+ data.push_back(TimerData<Time>(duration, false));
return Timer<Time>(&data.back());
}
+ /// Start an interval timer that hits (JustHit() returning true) each time
+ /// duration has passed.
Timer<Time> StartInterval(Time duration) {
- data.push_back(TimerData<Time>(duration));
+ data.push_back(TimerData<Time>(duration, true));
return Timer<Time>(&data.back());
}
}
-#endif /* APP_TIMER_H_ */
+#endif