summaryrefslogtreecommitdiffstats
path: root/curses/timer.C
diff options
context:
space:
mode:
Diffstat (limited to 'curses/timer.C')
-rw-r--r--curses/timer.C172
1 files changed, 172 insertions, 0 deletions
diff --git a/curses/timer.C b/curses/timer.C
new file mode 100644
index 0000000..8097f37
--- /dev/null
+++ b/curses/timer.C
@@ -0,0 +1,172 @@
+/*
+** Copyright 2002, Double Precision Inc.
+**
+** See COPYING for distribution information.
+*/
+
+#include "curses_config.h"
+#include "timer.H"
+
+std::set<Timer *> Timer::timer_list;
+
+Timer::Timer()
+{
+ timeout.tv_sec=0;
+ timeout.tv_usec=0;
+
+ timer_list.insert(this);
+}
+
+Timer::~Timer()
+{
+ timer_list.erase(this);
+}
+
+void Timer::setTimer(int nSeconds)
+{
+ gettimeofday(&timeout, NULL);
+ timeout.tv_sec += nSeconds;
+}
+
+void Timer::setTimer(struct timeval tv)
+{
+ gettimeofday(&timeout, NULL);
+ timeout.tv_sec += tv.tv_sec;
+
+ timeout.tv_usec += tv.tv_usec;
+
+ if (timeout.tv_usec >= 1000000)
+ {
+ ++timeout.tv_sec;
+ timeout.tv_usec %= 1000000;
+ }
+}
+
+struct timeval Timer::getTimer() const
+{
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+
+ return getTimer(tv);
+}
+
+struct timeval Timer::getTimer(const struct timeval &tv) const
+{
+ struct timeval t;
+
+ t.tv_sec=0;
+ t.tv_usec=0;
+
+ if (timeout.tv_sec == 0 && timeout.tv_usec == 0)
+ return t;
+
+ if (tv.tv_sec > timeout.tv_sec)
+ return t;
+
+ if (tv.tv_sec == timeout.tv_sec &&
+ tv.tv_usec >= timeout.tv_usec)
+ return t;
+
+ t=timeout;
+
+ t.tv_sec -= tv.tv_sec;
+ t.tv_usec -= tv.tv_usec;
+
+ if (t.tv_usec < 0)
+ {
+ t.tv_usec += 1000000;
+ t.tv_sec--;
+ }
+
+ return t;
+}
+
+#define DEBUG 1
+#undef DEBUG
+
+struct timeval Timer::getNextTimeout(bool &alarmCalledFlag)
+{
+ struct timeval now;
+
+ gettimeofday(&now, NULL);
+
+ bool alarmed;
+
+ bool wasAlarmed=false;
+
+ struct timeval s;
+
+ alarmCalledFlag=false;
+
+ do
+ {
+#if DEBUG
+ cerr << "In getNextTimeout:" << endl;
+#endif
+
+ alarmed=false;
+
+ std::set<Timer *>::iterator b=timer_list.begin(),
+ e=timer_list.end();
+
+ s.tv_sec=0;
+ s.tv_usec=0;
+
+ while (b != e)
+ {
+ Timer *t= *b++;
+
+ if (t->timeout.tv_sec == 0 &&
+ t->timeout.tv_usec == 0)
+ continue;
+
+ struct timeval v=t->getTimer(now);
+
+#if DEBUG
+ cerr << "Timer " << t << ": " << v.tv_sec
+ << "." << v.tv_usec << endl;
+#endif
+
+ if (v.tv_sec == 0 && v.tv_usec == 0)
+ {
+#if DEBUG
+ cerr << "ALARM: " <<
+ (wasAlarmed ? "ignored":"handled")
+ << endl;
+#endif
+ if (wasAlarmed)
+ {
+ // We can get here if an alarm
+ // went off, and the alarm handler
+ // reset the alarm to 0 seconds again.
+ // We'll get it on the next go-round
+
+ s=v;
+ break; // Kick the alarm next time
+ }
+ t->timeout=v;
+ t->alarm();
+ alarmCalledFlag=true;
+ alarmed=true;
+ }
+ else if ((s.tv_sec == 0 && s.tv_usec == 0) ||
+ v.tv_sec < s.tv_sec ||
+ (v.tv_sec == s.tv_sec
+ && v.tv_usec < s.tv_usec))
+ s=v;
+ }
+
+ wasAlarmed=alarmed;
+
+ } while (alarmed);
+
+#if DEBUG
+ cerr << "getNextTimeout: " << s.tv_sec << "." << s.tv_usec << endl;
+#endif
+ return s;
+}
+
+void Timer::alarm()
+{
+}