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

Revision 18159, 5.7 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18158, 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
121gdouble
122g_timer_elapsed (GTimer *timer,
123                 gulong *microseconds)
124{
125  gdouble total;
126#ifndef G_OS_WIN32
127  struct timeval elapsed;
128#endif /* G_OS_WIN32 */
129
130  g_return_val_if_fail (timer != NULL, 0);
131
132#ifdef G_OS_WIN32
133  if (timer->active)
134    timer->end = GetTickCount ();
135
136  /* Check for wraparound, which happens every 49.7 days. */
137  if (timer->end < timer->start)
138    total = (UINT_MAX - (timer->start - timer->end - 1)) / 1000.0;
139  else
140    total = (timer->end - timer->start) / 1000.0;
141
142  if (microseconds)
143    {
144      if (timer->end < timer->start)
145        *microseconds =
146          ((UINT_MAX - (timer->start - timer->end - 1)) % 1000) * 1000;
147      else
148        *microseconds =
149          ((timer->end - timer->start) % 1000) * 1000;
150    }
151#else /* !G_OS_WIN32 */
152  if (timer->active)
153    gettimeofday (&timer->end, NULL);
154
155  if (timer->start.tv_usec > timer->end.tv_usec)
156    {
157      timer->end.tv_usec += G_USEC_PER_SEC;
158      timer->end.tv_sec--;
159    }
160
161  elapsed.tv_usec = timer->end.tv_usec - timer->start.tv_usec;
162  elapsed.tv_sec = timer->end.tv_sec - timer->start.tv_sec;
163
164  total = elapsed.tv_sec + ((gdouble) elapsed.tv_usec / 1e6);
165  if (total < 0)
166    {
167      total = 0;
168
169      if (microseconds)
170        *microseconds = 0;
171    }
172  else if (microseconds)
173    *microseconds = elapsed.tv_usec;
174
175#endif /* !G_OS_WIN32 */
176
177  return total;
178}
179
180void
181g_usleep (gulong microseconds)
182{
183#ifdef G_OS_WIN32
184  Sleep (microseconds / 1000);
185#else /* !G_OS_WIN32 */
186# ifdef HAVE_NANOSLEEP
187  struct timespec request, remaining;
188  request.tv_sec = microseconds / G_USEC_PER_SEC;
189  request.tv_nsec = 1000 * (microseconds % G_USEC_PER_SEC);
190  while (nanosleep (&request, &remaining) == EINTR)
191    request = remaining;
192# else /* !HAVE_NANOSLEEP */
193  if (g_thread_supported ())
194    {
195      static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
196      static GCond* cond = NULL;
197      GTimeVal end_time;
198     
199      g_get_current_time (&end_time);
200      if (microseconds > G_MAXLONG)
201        {
202          microseconds -= G_MAXLONG;
203          g_time_val_add (&end_time, G_MAXLONG);
204        }
205      g_time_val_add (&end_time, microseconds);
206
207      g_static_mutex_lock (&mutex);
208     
209      if (!cond)
210        cond = g_cond_new ();
211     
212      while (g_cond_timed_wait (cond, g_static_mutex_get_mutex (&mutex),
213                                &end_time))
214        /* do nothing */;
215     
216      g_static_mutex_unlock (&mutex);
217    }
218  else
219    {
220      struct timeval tv;
221      tv.tv_sec = microseconds / G_USEC_PER_SEC;
222      tv.tv_usec = microseconds % G_USEC_PER_SEC;
223      select(0, NULL, NULL, NULL, &tv);
224    }
225# endif /* !HAVE_NANOSLEEP */
226#endif /* !G_OS_WIN32 */
227}
228
229/**
230 * g_time_val_add:
231 * @time_: a #GTimeVal
232 * @microseconds: number of microseconds to add to @time
233 *
234 * Adds the given number of microseconds to @time_. @microseconds can
235 * also be negative to decrease the value of @time_.
236 **/
237void
238g_time_val_add (GTimeVal *time_, glong microseconds)
239{
240  g_return_if_fail (time_->tv_usec >= 0 && time_->tv_usec < G_USEC_PER_SEC);
241
242  if (microseconds >= 0)
243    {
244      time_->tv_usec += microseconds % G_USEC_PER_SEC;
245      time_->tv_sec += microseconds / G_USEC_PER_SEC;
246      if (time_->tv_usec >= G_USEC_PER_SEC)
247       {
248         time_->tv_usec -= G_USEC_PER_SEC;
249         time_->tv_sec++;
250       }
251    }
252  else
253    {
254      microseconds *= -1;
255      time_->tv_usec -= microseconds % G_USEC_PER_SEC;
256      time_->tv_sec -= microseconds / G_USEC_PER_SEC;
257      if (time_->tv_usec < 0)
258       {
259         time_->tv_usec += G_USEC_PER_SEC;
260         time_->tv_sec--;
261       }     
262    }
263}
Note: See TracBrowser for help on using the repository browser.