This commit merges the glib-threads branch into the main
[platform/upstream/glib.git] / gtimer.c
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 Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library 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  * MT safe
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include "glib.h"
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif /* HAVE_UNISTD_H */
32 #ifndef NATIVE_WIN32
33 #include <sys/time.h>
34 #endif /* NATIVE_WIN32 */
35
36 #ifdef NATIVE_WIN32
37 #include <windows.h>
38 #endif /* NATIVE_WIN32 */
39
40 typedef struct _GRealTimer GRealTimer;
41
42 struct _GRealTimer
43 {
44 #ifdef NATIVE_WIN32
45   DWORD start;
46   DWORD end;
47 #else /* !NATIVE_WIN32 */
48   struct timeval start;
49   struct timeval end;
50 #endif /* !NATIVE_WIN32 */
51
52   guint active : 1;
53 };
54
55 GTimer*
56 g_timer_new (void)
57 {
58   GRealTimer *timer;
59
60   timer = g_new (GRealTimer, 1);
61   timer->active = TRUE;
62
63 #ifdef NATIVE_WIN32
64   timer->start = GetTickCount ();
65 #else /* !NATIVE_WIN32 */
66   gettimeofday (&timer->start, NULL);
67 #endif /* !NATIVE_WIN32 */
68
69   return ((GTimer*) timer);
70 }
71
72 void
73 g_timer_destroy (GTimer *timer)
74 {
75   g_assert (timer != NULL);
76
77   g_free (timer);
78 }
79
80 void
81 g_timer_start (GTimer *timer)
82 {
83   GRealTimer *rtimer;
84
85   g_assert (timer != NULL);
86
87   rtimer = (GRealTimer*) timer;
88   rtimer->active = TRUE;
89
90 #ifdef NATIVE_WIN32
91   rtimer->start = GetTickCount ();
92 #else /* !NATIVE_WIN32 */
93   gettimeofday (&rtimer->start, NULL);
94 #endif /* !NATIVE_WIN32 */
95 }
96
97 void
98 g_timer_stop (GTimer *timer)
99 {
100   GRealTimer *rtimer;
101
102   g_assert (timer != NULL);
103
104   rtimer = (GRealTimer*) timer;
105   rtimer->active = FALSE;
106
107 #ifdef NATIVE_WIN32
108   rtimer->end = GetTickCount ();
109 #else /* !NATIVE_WIN32 */
110   gettimeofday (&rtimer->end, NULL);
111 #endif /* !NATIVE_WIN32 */
112 }
113
114 void
115 g_timer_reset (GTimer *timer)
116 {
117   GRealTimer *rtimer;
118
119   g_assert (timer != NULL);
120
121   rtimer = (GRealTimer*) timer;
122
123 #ifdef NATIVE_WIN32
124    rtimer->start = GetTickCount ();
125 #else /* !NATIVE_WIN32 */
126   gettimeofday (&rtimer->start, NULL);
127 #endif /* !NATIVE_WIN32 */
128 }
129
130 gdouble
131 g_timer_elapsed (GTimer *timer,
132                  gulong *microseconds)
133 {
134   GRealTimer *rtimer;
135   gdouble total;
136 #ifndef NATIVE_WIN32
137   struct timeval elapsed;
138 #endif /* NATIVE_WIN32 */
139
140   g_return_val_if_fail (timer != NULL, 0);
141
142   rtimer = (GRealTimer*) timer;
143
144 #ifdef NATIVE_WIN32
145   if (rtimer->active)
146     rtimer->end = GetTickCount ();
147
148   /* Check for wraparound, which happens every 49.7 days.
149    * No, Win95 machines probably are never running for that long,
150    * but NT machines are.
151    */
152   if (rtimer->end < rtimer->start)
153     total = (UINT_MAX - (rtimer->start - rtimer->end)) / 1000.0;
154   else
155     total = (rtimer->end - rtimer->start) / 1000.0;
156
157   if (microseconds)
158     {
159       if (rtimer->end < rtimer->start)
160         *microseconds =
161           ((UINT_MAX - (rtimer->start - rtimer->end)) % 1000) * 1000;
162       else
163         *microseconds =
164           ((rtimer->end - rtimer->start) % 1000) * 1000;
165     }
166 #else /* !NATIVE_WIN32 */
167   if (rtimer->active)
168     gettimeofday (&rtimer->end, NULL);
169
170   if (rtimer->start.tv_usec > rtimer->end.tv_usec)
171     {
172       rtimer->end.tv_usec += 1000000;
173       rtimer->end.tv_sec--;
174     }
175
176   elapsed.tv_usec = rtimer->end.tv_usec - rtimer->start.tv_usec;
177   elapsed.tv_sec = rtimer->end.tv_sec - rtimer->start.tv_sec;
178
179   total = elapsed.tv_sec + ((gdouble) elapsed.tv_usec / 1e6);
180
181   if (microseconds)
182     *microseconds = elapsed.tv_usec;
183 #endif /* !NATIVE_WIN32 */
184
185   return total;
186 }