1 /* 2 ** Copyright 2002, Double Precision Inc. 3 ** 4 ** See COPYING for distribution information. 5 */ 6 7 #include "curses_config.h" 8 #include "timer.H" 9 10 std::set<Timer *> Timer::timer_list; 11 Timer()12Timer::Timer() 13 { 14 timeout.tv_sec=0; 15 timeout.tv_usec=0; 16 17 timer_list.insert(this); 18 } 19 ~Timer()20Timer::~Timer() 21 { 22 timer_list.erase(this); 23 } 24 setTimer(int nSeconds)25void Timer::setTimer(int nSeconds) 26 { 27 gettimeofday(&timeout, NULL); 28 timeout.tv_sec += nSeconds; 29 } 30 setTimer(struct timeval tv)31void Timer::setTimer(struct timeval tv) 32 { 33 gettimeofday(&timeout, NULL); 34 timeout.tv_sec += tv.tv_sec; 35 36 timeout.tv_usec += tv.tv_usec; 37 38 if (timeout.tv_usec >= 1000000) 39 { 40 ++timeout.tv_sec; 41 timeout.tv_usec %= 1000000; 42 } 43 } 44 getTimer()45struct timeval Timer::getTimer() const 46 { 47 struct timeval tv; 48 49 gettimeofday(&tv, NULL); 50 51 return getTimer(tv); 52 } 53 getTimer(const struct timeval & tv)54struct timeval Timer::getTimer(const struct timeval &tv) const 55 { 56 struct timeval t; 57 58 t.tv_sec=0; 59 t.tv_usec=0; 60 61 if (timeout.tv_sec == 0 && timeout.tv_usec == 0) 62 return t; 63 64 if (tv.tv_sec > timeout.tv_sec) 65 return t; 66 67 if (tv.tv_sec == timeout.tv_sec && 68 tv.tv_usec >= timeout.tv_usec) 69 return t; 70 71 t=timeout; 72 73 t.tv_sec -= tv.tv_sec; 74 t.tv_usec -= tv.tv_usec; 75 76 if (t.tv_usec < 0) 77 { 78 t.tv_usec += 1000000; 79 t.tv_sec--; 80 } 81 82 return t; 83 } 84 85 #define DEBUG 1 86 #undef DEBUG 87 getNextTimeout(bool & alarmCalledFlag)88struct timeval Timer::getNextTimeout(bool &alarmCalledFlag) 89 { 90 struct timeval now; 91 92 gettimeofday(&now, NULL); 93 94 bool alarmed; 95 96 bool wasAlarmed=false; 97 98 struct timeval s; 99 100 alarmCalledFlag=false; 101 102 do 103 { 104 #if DEBUG 105 cerr << "In getNextTimeout:" << endl; 106 #endif 107 108 alarmed=false; 109 110 std::set<Timer *>::iterator b=timer_list.begin(), 111 e=timer_list.end(); 112 113 s.tv_sec=0; 114 s.tv_usec=0; 115 116 while (b != e) 117 { 118 Timer *t= *b++; 119 120 if (t->timeout.tv_sec == 0 && 121 t->timeout.tv_usec == 0) 122 continue; 123 124 struct timeval v=t->getTimer(now); 125 126 #if DEBUG 127 cerr << "Timer " << t << ": " << v.tv_sec 128 << "." << v.tv_usec << endl; 129 #endif 130 131 if (v.tv_sec == 0 && v.tv_usec == 0) 132 { 133 #if DEBUG 134 cerr << "ALARM: " << 135 (wasAlarmed ? "ignored":"handled") 136 << endl; 137 #endif 138 if (wasAlarmed) 139 { 140 // We can get here if an alarm 141 // went off, and the alarm handler 142 // reset the alarm to 0 seconds again. 143 // We'll get it on the next go-round 144 145 s=v; 146 break; // Kick the alarm next time 147 } 148 t->timeout=v; 149 t->alarm(); 150 alarmCalledFlag=true; 151 alarmed=true; 152 } 153 else if ((s.tv_sec == 0 && s.tv_usec == 0) || 154 v.tv_sec < s.tv_sec || 155 (v.tv_sec == s.tv_sec 156 && v.tv_usec < s.tv_usec)) 157 s=v; 158 } 159 160 wasAlarmed=alarmed; 161 162 } while (alarmed); 163 164 #if DEBUG 165 cerr << "getNextTimeout: " << s.tv_sec << "." << s.tv_usec << endl; 166 #endif 167 return s; 168 } 169 alarm()170void Timer::alarm() 171 { 172 } 173