+/*
+ * Timer.h
+ *
+ * Created on: Aug 10, 2012
+ * Author: holy
+ */
+
+#ifndef APP_TIMER_H_
+#define APP_TIMER_H_
+
+#include <algorithm>
+#include <list>
+
+namespace app {
+
+template<class Time>
+struct TimerData {
+
+ TimerData() : time(0), target(0), refCount(0) { }
+ TimerData(Time target) : time(0), target(target), refCount(0) { }
+
+ Time time;
+ Time target;
+ int refCount;
+
+};
+
+
+template<class Time>
+class Timer {
+
+public:
+ Timer() : data(0) { }
+ ~Timer() { if (data) --data->refCount; }
+ Timer(TimerData<Time> *data) : data(data) { ++data->refCount; }
+ Timer(const Timer<Time> &other)
+ : data(other.data) { if (data) ++(data->refCount); }
+ Timer<Time> &operator =(const Timer<Time> &other) {
+ Timer<Time> temp(other);
+ Swap(temp);
+ return *this;
+ }
+ void Swap(Timer<Time> &other) {
+ std::swap(data, other.data);
+ }
+
+public:
+ bool Running() const {
+ return data;
+ }
+ bool Finished() const {
+ return data ? data->time >= data->target : false;
+ }
+ Time Elapsed() const {
+ return data ? data->time : Time();
+ }
+ Time Remaining() const {
+ return data ? (data->target - data->time) : Time();
+ }
+
+private:
+ TimerData<Time> *data;
+
+};
+
+
+template<class Time>
+class Timers {
+
+public:
+ Timers() { }
+
+public:
+ void Update(Time delta) {
+ for (typename std::list<TimerData<Time> >::iterator i(data.begin()), end(data.end()); i != end;) {
+ i->time += delta;
+ if (i->refCount <= 0) {
+ i = data.erase(i);
+ } else {
+ ++i;
+ }
+ }
+ }
+ Timer<Time> StartTimer() {
+ data.push_back(TimerData<Time>());
+ return Timer<Time>(&data.back());
+ }
+ Timer<Time> StartCountdown(Time duration) {
+ data.push_back(TimerData<Time>(duration));
+ return Timer<Time>(&data.back());
+ }
+
+private:
+ std::list<TimerData<Time> > data;
+
+};
+
+}
+
+#endif /* APP_TIMER_H_ */