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 * Modified by the GLib Team and others 1997-1999.  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#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34
35#include "glib.h"
36#ifdef HAVE_UNISTD_H
37#include <unistd.h>
38#endif /* HAVE_UNISTD_H */
39#ifndef NATIVE_WIN32
40#include <sys/time.h>
41#endif /* NATIVE_WIN32 */
42
43#ifdef NATIVE_WIN32
44#include <windows.h>
45#endif /* NATIVE_WIN32 */
46
47typedef struct _GRealTimer GRealTimer;
48
49struct _GRealTimer
50{
51#ifdef NATIVE_WIN32
52  DWORD start;
53  DWORD end;
54#else /* !NATIVE_WIN32 */
55  struct timeval start;
56  struct timeval end;
57#endif /* !NATIVE_WIN32 */
58
59  guint active : 1;
60};
61
62GTimer*
63g_timer_new (void)
64{
65  GRealTimer *timer;
66
67  timer = g_new (GRealTimer, 1);
68  timer->active = TRUE;
69
70#ifdef NATIVE_WIN32
71  timer->start = GetTickCount ();
72#else /* !NATIVE_WIN32 */
73  gettimeofday (&timer->start, NULL);
74#endif /* !NATIVE_WIN32 */
75
76  return ((GTimer*) timer);
77}
78
79void
80g_timer_destroy (GTimer *timer)
81{
82  g_return_if_fail (timer != NULL);
83
84  g_free (timer);
85}
86
87void
88g_timer_start (GTimer *timer)
89{
90  GRealTimer *rtimer;
91
92  g_return_if_fail (timer != NULL);
93
94  rtimer = (GRealTimer*) timer;
95  rtimer->active = TRUE;
96
97#ifdef NATIVE_WIN32
98  rtimer->start = GetTickCount ();
99#else /* !NATIVE_WIN32 */
100  gettimeofday (&rtimer->start, NULL);
101#endif /* !NATIVE_WIN32 */
102}
103
104void
105g_timer_stop (GTimer *timer)
106{
107  GRealTimer *rtimer;
108
109  g_return_if_fail (timer != NULL);
110
111  rtimer = (GRealTimer*) timer;
112  rtimer->active = FALSE;
113
114#ifdef NATIVE_WIN32
115  rtimer->end = GetTickCount ();
116#else /* !NATIVE_WIN32 */
117  gettimeofday (&rtimer->end, NULL);
118#endif /* !NATIVE_WIN32 */
119}
120
121void
122g_timer_reset (GTimer *timer)
123{
124  GRealTimer *rtimer;
125
126  g_return_if_fail (timer != NULL);
127
128  rtimer = (GRealTimer*) timer;
129
130#ifdef NATIVE_WIN32
131   rtimer->start = GetTickCount ();
132#else /* !NATIVE_WIN32 */
133  gettimeofday (&rtimer->start, NULL);
134#endif /* !NATIVE_WIN32 */
135}
136
137gdouble
138g_timer_elapsed (GTimer *timer,
139		 gulong *microseconds)
140{
141  GRealTimer *rtimer;
142  gdouble total;
143#ifndef NATIVE_WIN32
144  struct timeval elapsed;
145#endif /* NATIVE_WIN32 */
146
147  g_return_val_if_fail (timer != NULL, 0);
148
149  rtimer = (GRealTimer*) timer;
150
151#ifdef NATIVE_WIN32
152  if (rtimer->active)
153    rtimer->end = GetTickCount ();
154
155  /* Check for wraparound, which happens every 49.7 days.
156   * No, Win95 machines probably are never running for that long,
157   * but NT machines are.
158   */
159  if (rtimer->end < rtimer->start)
160    total = (UINT_MAX - (rtimer->start - rtimer->end)) / 1000.0;
161  else
162    total = (rtimer->end - rtimer->start) / 1000.0;
163
164  if (microseconds)
165    {
166      if (rtimer->end < rtimer->start)
167	*microseconds =
168	  ((UINT_MAX - (rtimer->start - rtimer->end)) % 1000) * 1000;
169      else
170	*microseconds =
171	  ((rtimer->end - rtimer->start) % 1000) * 1000;
172    }
173#else /* !NATIVE_WIN32 */
174  if (rtimer->active)
175    gettimeofday (&rtimer->end, NULL);
176
177  if (rtimer->start.tv_usec > rtimer->end.tv_usec)
178    {
179      rtimer->end.tv_usec += 1000000;
180      rtimer->end.tv_sec--;
181    }
182
183  elapsed.tv_usec = rtimer->end.tv_usec - rtimer->start.tv_usec;
184  elapsed.tv_sec = rtimer->end.tv_sec - rtimer->start.tv_sec;
185
186  total = elapsed.tv_sec + ((gdouble) elapsed.tv_usec / 1e6);
187  if (total < 0)
188    {
189      total = 0;
190
191      if (microseconds)
192	*microseconds = 0;
193    }
194  else
195    if (microseconds)
196      *microseconds = elapsed.tv_usec;
197
198#endif /* !NATIVE_WIN32 */
199
200  return total;
201}
202