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()12 Timer::Timer()
13 {
14 	timeout.tv_sec=0;
15 	timeout.tv_usec=0;
16 
17 	timer_list.insert(this);
18 }
19 
~Timer()20 Timer::~Timer()
21 {
22 	timer_list.erase(this);
23 }
24 
setTimer(int nSeconds)25 void Timer::setTimer(int nSeconds)
26 {
27 	gettimeofday(&timeout, NULL);
28 	timeout.tv_sec += nSeconds;
29 }
30 
setTimer(struct timeval tv)31 void 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()45 struct 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)54 struct 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)88 struct 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()170 void Timer::alarm()
171 {
172 }
173