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