blob: d967b7bd1f2330b19bc03b0be7018160b8a5a8f0 [file] [log] [blame]
Emeric Vigier2f625822012-08-06 11:09:52 -04001// Copyright (C) 1999-2005 Open Source Telecom Corporation.
2// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
3//
4// This program is free software; you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation; either version 2 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17//
18// As a special exception, you may use this file as part of a free software
19// library without restriction. Specifically, if other files instantiate
20// templates or use macros or inline functions from this file, or you compile
21// this file and link it with other files to produce an executable, this
22// file does not by itself cause the resulting executable to be covered by
23// the GNU General Public License. This exception does not however
24// invalidate any other reasons why the executable file might be covered by
25// the GNU General Public License.
26//
27// This exception applies only to the code released under the name GNU
28// Common C++. If you copy code from other releases into a copy of GNU
29// Common C++, as the General Public License permits, the exception does
30// not apply to the code that you add in this way. To avoid misleading
31// anyone as to the status of such modified files, you must delete
32// this exception notice from them.
33//
34// If you write modifications of your own for GNU Common C++, it is your choice
35// whether to permit this exception to apply to your modifications.
36// If you do not wish that, delete this exception notice.
37//
38
39#include <cc++/config.h>
40#include <cc++/export.h>
41#include <cc++/thread.h>
42#include "private.h"
43
44#ifdef CCXX_NAMESPACES
45namespace ost {
46#endif
47
48#ifndef WIN32
49
50#ifdef HAVE_HIRES_TIMER
51TimerPort::TimerPort()
52{
53 struct timespec ts;
54 active = false;
55
56#if defined(CLOCK_MONOTONIC) && defined(USE_MONOTONIC_TIMER)
57 ::clock_gettime(CLOCK_MONOTONIC, &ts);
58#else
59 ::clock_gettime(CLOCK_REALTIME, &ts);
60#endif
61 timer.tv_sec = ts.tv_sec;
62 timer.tv_usec = ts.tv_nsec / 1000;
63}
64#else
65TimerPort::TimerPort()
66{
67 active = false;
68 SysTime::getTimeOfDay(&timer);
69}
70#endif
71
72void TimerPort::setTimer(timeout_t timeout)
73{
74#ifdef HAVE_HIRES_TIMER
75 struct timespec ts;
76#if defined(CLOCK_MONOTONIC) && defined(USE_MONOTONIC_TIMER)
77 ::clock_gettime(CLOCK_MONOTONIC, &ts);
78#else
79 ::clock_gettime(CLOCK_REALTIME, &ts);
80#endif
81 timer.tv_sec = ts.tv_sec;
82 timer.tv_usec = ts.tv_nsec / 1000l;
83#else
84 SysTime::getTimeOfDay(&timer);
85#endif
86 active = false;
87 if(timeout)
88 incTimer(timeout);
89}
90
91void TimerPort::incTimer(timeout_t timeout)
92{
93 int secs = timeout / 1000;
94 int usecs = (timeout % 1000) * 1000;
95
96 timer.tv_usec += usecs;
97 if(timer.tv_usec > 1000000l) {
98 ++timer.tv_sec;
99 timer.tv_usec %= 1000000l;
100 }
101 timer.tv_sec += secs;
102 active = true;
103}
104
105void TimerPort::decTimer(timeout_t timeout)
106{
107 int secs = timeout / 1000;
108 int usecs = (timeout % 1000) * 1000;
109
110 if(timer.tv_usec < usecs) {
111 --timer.tv_sec;
112 timer.tv_usec = 1000000l + timer.tv_usec - usecs;
113 }
114 else
115 timer.tv_usec -= usecs;
116
117 timer.tv_sec -= secs;
118 active = true;
119}
120
121#ifdef HAVE_HIRES_TIMER
122void TimerPort::sleepTimer(void)
123{
124 struct timespec ts;
125 ts.tv_sec = timer.tv_sec;
126 ts.tv_nsec = timer.tv_usec * 1000l;
127
128#if defined(CLOCK_MONOTONIC) && defined(USE_MONOTONIC_TIMER)
129 ::clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, NULL);
130#else
131 ::clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &ts, NULL);
132#endif
133}
134#else
135void TimerPort::sleepTimer(void)
136{
137 timeout_t remaining = getTimer();
138 if(remaining && remaining != TIMEOUT_INF)
139 Thread::sleep(remaining);
140}
141#endif
142
143void TimerPort::endTimer(void)
144{
145 active = false;
146}
147
148timeout_t TimerPort::getTimer(void) const
149{
150#ifdef HAVE_HIRES_TIMER
151 struct timespec now;
152#else
153 struct timeval now;
154#endif
155 long diff;
156
157 if(!active)
158 return TIMEOUT_INF;
159
160#ifdef HAVE_HIRES_TIMER
161#if defined(CLOCK_MONOTONIC) && defined(USE_MONOTONIC_TIMER)
162 ::clock_gettime(CLOCK_MONOTONIC, &now);
163#else
164 ::clock_gettime(CLOCK_REALTIME, &now);
165#endif
166 diff = (timer.tv_sec - now.tv_sec) * 1000l;
167 diff += (timer.tv_usec - (now.tv_nsec / 1000)) / 1000l;
168#else
169 SysTime::getTimeOfDay(&now);
170 diff = (timer.tv_sec - now.tv_sec) * 1000l;
171 diff += (timer.tv_usec - now.tv_usec) / 1000l;
172#endif
173
174 if(diff < 0)
175 return 0l;
176
177 return diff;
178}
179
180timeout_t TimerPort::getElapsed(void) const
181{
182#ifdef HAVE_HIRES_TIMER
183 struct timespec now;
184#else
185 struct timeval now;
186#endif
187 long diff;
188
189 if(!active)
190 return TIMEOUT_INF;
191
192#ifdef HAVE_HIRES_TIMER
193#if defined(CLOCK_MONOTONIC) && defined(USE_MONOTONIC_TIMER)
194 ::clock_gettime(CLOCK_MONOTONIC, &now);
195#else
196 ::clock_gettime(CLOCK_REALTIME, &now);
197#endif
198 diff = (now.tv_sec - timer.tv_sec) * 1000l;
199 diff += ((now.tv_nsec / 1000l) - timer.tv_usec) / 1000l;
200#else
201 SysTime::getTimeOfDay(&now);
202 diff = (now.tv_sec -timer.tv_sec) * 1000l;
203 diff += (now.tv_usec - timer.tv_usec) / 1000l;
204#endif
205 if(diff < 0)
206 return 0;
207 return diff;
208}
209#else // WIN32
210TimerPort::TimerPort()
211{
212 active = false;
213 timer = GetTickCount();
214}
215
216void TimerPort::setTimer(timeout_t timeout)
217{
218 timer = GetTickCount();
219 active = false;
220 if(timeout)
221 incTimer(timeout);
222}
223
224void TimerPort::incTimer(timeout_t timeout)
225{
226 timer += timeout;
227 active = true;
228}
229
230void TimerPort::decTimer(timeout_t timeout)
231{
232 timer -= timeout;
233 active = true;
234}
235
236void TimerPort::sleepTimer(void)
237{
238 timeout_t remaining = getTimer();
239 if(remaining && remaining != TIMEOUT_INF)
240 Thread::sleep(remaining);
241}
242
243void TimerPort::endTimer(void)
244{
245 active = false;
246}
247
248timeout_t TimerPort::getTimer(void) const
249{
250 DWORD now;
251 long diff;
252
253 if(!active)
254 return TIMEOUT_INF;
255
256 now = GetTickCount();
257 diff = timer - now;
258
259 if(diff < 0)
260 return 0l;
261
262 return diff;
263}
264
265timeout_t TimerPort::getElapsed(void) const
266{
267 DWORD now;
268 long diff;
269
270 if(!active)
271 return TIMEOUT_INF;
272
273 now = GetTickCount();
274 diff = now - timer;
275
276 if(diff < 0)
277 return 0l;
278
279 return diff;
280}
281#endif
282
283#ifdef CCXX_NAMESPACES
284}
285#endif
286
287/** EMACS **
288 * Local variables:
289 * mode: c++
290 * c-basic-offset: 4
291 * End:
292 */