source: trunk/third/glib2/glib/gtimer.c @ 20721

Revision 20721, 6.8 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20720, which included commits to RCS files with non-trunk default branches.
Line 
1/* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library 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 GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20/*
21 * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
22 * file for a list of people on the GLib Team.  See the ChangeLog
23 * files for a list of changes.  These files are distributed with
24 * GLib at ftp://ftp.gtk.org/pub/gtk/.
25 */
26
27/*
28 * MT safe
29 */
30
31#include "config.h"
32#include "glibconfig.h"
33
34#ifdef HAVE_UNISTD_H
35#include <unistd.h>
36#endif /* HAVE_UNISTD_H */
37
38#ifndef G_OS_WIN32
39#include <sys/time.h>
40#include <time.h>
41#include <errno.h>
42#endif /* G_OS_WIN32 */
43
44#ifdef G_OS_WIN32
45#include <windows.h>
46#endif /* G_OS_WIN32 */
47
48#include "glib.h"
49
50
51struct _GTimer
52{
53#ifdef G_OS_WIN32
54  DWORD start;
55  DWORD end;
56#else /* !G_OS_WIN32 */
57  struct timeval start;
58  struct timeval end;
59#endif /* !G_OS_WIN32 */
60
61  guint active : 1;
62};
63
64#ifdef G_OS_WIN32
65#  define GETTIME(v) \
66     v = GetTickCount ()
67#else /* !G_OS_WIN32 */
68#  define GETTIME(v) \
69     gettimeofday (&v, NULL)
70#endif /* !G_OS_WIN32 */
71
72GTimer*
73g_timer_new (void)
74{
75  GTimer *timer;
76
77  timer = g_new (GTimer, 1);
78  timer->active = TRUE;
79
80  GETTIME (timer->start);
81
82  return timer;
83}
84
85void
86g_timer_destroy (GTimer *timer)
87{
88  g_return_if_fail (timer != NULL);
89
90  g_free (timer);
91}
92
93void
94g_timer_start (GTimer *timer)
95{
96  g_return_if_fail (timer != NULL);
97
98  timer->active = TRUE;
99
100  GETTIME (timer->start);
101}
102
103void
104g_timer_stop (GTimer *timer)
105{
106  g_return_if_fail (timer != NULL);
107
108  timer->active = FALSE;
109
110  GETTIME(timer->end);
111}
112
113void
114g_timer_reset (GTimer *timer)
115{
116  g_return_if_fail (timer != NULL);
117
118  GETTIME (timer->start);
119}
120
121void
122g_timer_continue (GTimer *timer)
123{
124#ifdef G_OS_WIN32
125  DWORD elapsed;
126#else
127  struct timeval elapsed;
128#endif /* G_OS_WIN32 */
129
130  g_return_if_fail (timer != NULL);
131  g_return_if_fail (timer->active == FALSE);
132
133  /* Get elapsed time and reset timer start time
134   *  to the current time minus the previously
135   *  elapsed interval.
136   */
137
138#ifdef G_OS_WIN32
139
140  elapsed = timer->end - timer->start;
141
142  GETTIME (timer->start);
143
144  timer->start -= elapsed;
145
146#else /* !G_OS_WIN32 */
147
148  if (timer->start.tv_usec > timer->end.tv_usec)
149    {
150      timer->end.tv_usec += G_USEC_PER_SEC;
151      timer->end.tv_sec--;
152    }
153
154  elapsed.tv_usec = timer->end.tv_usec - timer->start.tv_usec;
155  elapsed.tv_sec = timer->end.tv_sec - timer->start.tv_sec;
156
157  GETTIME (timer->start);
158
159  if (timer->start.tv_usec < elapsed.tv_usec)
160    {
161      timer->start.tv_usec += G_USEC_PER_SEC;
162      timer->start.tv_sec--;
163    }
164
165  timer->start.tv_usec -= elapsed.tv_usec;
166  timer->start.tv_sec -= elapsed.tv_sec;
167
168#endif /* !G_OS_WIN32 */
169
170  timer->active = TRUE;
171}
172
173gdouble
174g_timer_elapsed (GTimer *timer,
175                 gulong *microseconds)
176{
177  gdouble total;
178#ifndef G_OS_WIN32
179  struct timeval elapsed;
180#endif /* G_OS_WIN32 */
181
182  g_return_val_if_fail (timer != NULL, 0);
183
184#ifdef G_OS_WIN32
185  if (timer->active)
186    timer->end = GetTickCount ();
187
188  /* Check for wraparound, which happens every 49.7 days. */
189  if (timer->end < timer->start)
190    total = (UINT_MAX - (timer->start - timer->end - 1)) / 1000.0;
191  else
192    total = (timer->end - timer->start) / 1000.0;
193
194  if (microseconds)
195    {
196      if (timer->end < timer->start)
197        *microseconds =
198          ((UINT_MAX - (timer->start - timer->end - 1)) % 1000) * 1000;
199      else
200        *microseconds =
201          ((timer->end - timer->start) % 1000) * 1000;
202    }
203#else /* !G_OS_WIN32 */
204  if (timer->active)
205    gettimeofday (&timer->end, NULL);
206
207  if (timer->start.tv_usec > timer->end.tv_usec)
208    {
209      timer->end.tv_usec += G_USEC_PER_SEC;
210      timer->end.tv_sec--;
211    }
212
213  elapsed.tv_usec = timer->end.tv_usec - timer->start.tv_usec;
214  elapsed.tv_sec = timer->end.tv_sec - timer->start.tv_sec;
215
216  total = elapsed.tv_sec + ((gdouble) elapsed.tv_usec / 1e6);
217  if (total < 0)
218    {
219      total = 0;
220
221      if (microseconds)
222        *microseconds = 0;
223    }
224  else if (microseconds)
225    *microseconds = elapsed.tv_usec;
226
227#endif /* !G_OS_WIN32 */
228
229  return total;
230}
231
232void
233g_usleep (gulong microseconds)
234{
235#ifdef G_OS_WIN32
236  Sleep (microseconds / 1000);
237#else /* !G_OS_WIN32 */
238# ifdef HAVE_NANOSLEEP
239  struct timespec request, remaining;
240  request.tv_sec = microseconds / G_USEC_PER_SEC;
241  request.tv_nsec = 1000 * (microseconds % G_USEC_PER_SEC);
242  while (nanosleep (&request, &remaining) == EINTR)
243    request = remaining;
244# else /* !HAVE_NANOSLEEP */
245  if (g_thread_supported ())
246    {
247      static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
248      static GCond* cond = NULL;
249      GTimeVal end_time;
250     
251      g_get_current_time (&end_time);
252      if (microseconds > G_MAXLONG)
253        {
254          microseconds -= G_MAXLONG;
255          g_time_val_add (&end_time, G_MAXLONG);
256        }
257      g_time_val_add (&end_time, microseconds);
258
259      g_static_mutex_lock (&mutex);
260     
261      if (!cond)
262        cond = g_cond_new ();
263     
264      while (g_cond_timed_wait (cond, g_static_mutex_get_mutex (&mutex),
265                                &end_time))
266        /* do nothing */;
267     
268      g_static_mutex_unlock (&mutex);
269    }
270  else
271    {
272      struct timeval tv;
273      tv.tv_sec = microseconds / G_USEC_PER_SEC;
274      tv.tv_usec = microseconds % G_USEC_PER_SEC;
275      select(0, NULL, NULL, NULL, &tv);
276    }
277# endif /* !HAVE_NANOSLEEP */
278#endif /* !G_OS_WIN32 */
279}
280
281/**
282 * g_time_val_add:
283 * @time_: a #GTimeVal
284 * @microseconds: number of microseconds to add to @time
285 *
286 * Adds the given number of microseconds to @time_. @microseconds can
287 * also be negative to decrease the value of @time_.
288 **/
289void
290g_time_val_add (GTimeVal *time_, glong microseconds)
291{
292  g_return_if_fail (time_->tv_usec >= 0 && time_->tv_usec < G_USEC_PER_SEC);
293
294  if (microseconds >= 0)
295    {
296      time_->tv_usec += microseconds % G_USEC_PER_SEC;
297      time_->tv_sec += microseconds / G_USEC_PER_SEC;
298      if (time_->tv_usec >= G_USEC_PER_SEC)
299       {
300         time_->tv_usec -= G_USEC_PER_SEC;
301         time_->tv_sec++;
302       }
303    }
304  else
305    {
306      microseconds *= -1;
307      time_->tv_usec -= microseconds % G_USEC_PER_SEC;
308      time_->tv_sec -= microseconds / G_USEC_PER_SEC;
309      if (time_->tv_usec < 0)
310       {
311         time_->tv_usec += G_USEC_PER_SEC;
312         time_->tv_sec--;
313       }     
314    }
315}
Note: See TracBrowser for help on using the repository browser.