[glib] Switch GTimeSpec users to int64 microseconds
- From: Ryan Lortie <ryanl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] Switch GTimeSpec users to int64 microseconds
- Date: Wed, 3 Nov 2010 02:39:47 +0000 (UTC)
commit c3a0d32ef1413f942890796aa20f7b1a54254eff
Author: Ryan Lortie <desrt desrt ca>
Date: Mon Nov 1 15:46:35 2010 -0400
Switch GTimeSpec users to int64 microseconds
glib is trying to move toward using microseconds-in-gint64 as its
universal time format.
No real API breaks here since GTimeSpec is new this unstable release
series.
gio/gperiodic.c | 33 ++---------
gio/gperiodic.h | 2 +-
gio/gsocket.c | 35 +++++------
glib/gmain.c | 183 +++++++++++++++++++++++--------------------------------
glib/gmain.h | 7 +-
5 files changed, 101 insertions(+), 159 deletions(-)
---
diff --git a/gio/gperiodic.c b/gio/gperiodic.c
index 1e96f60..31a8bf2 100644
--- a/gio/gperiodic.c
+++ b/gio/gperiodic.c
@@ -113,17 +113,7 @@ static guint g_periodic_repair;
static guint64
g_periodic_get_microticks (GPeriodic *periodic)
{
- guint64 microticks;
- GTimeSpec timespec;
-
- g_source_get_time (periodic->source, ×pec);
-
- microticks = timespec.tv_sec;
- microticks *= 1000000;
- microticks += timespec.tv_nsec / 1000;
- microticks *= periodic->hz;
-
- return microticks;
+ return g_source_get_time (periodic->source) * periodic->hz;
}
static void
@@ -397,7 +387,7 @@ g_periodic_block (GPeriodic *periodic)
/**
* g_periodic_unblock:
* @periodic: a #GPeriodic clock
- * @unblock_time: the unblock time, or %NULL
+ * @unblock_time: the unblock time
*
* Reverses the effect of a previous call to g_periodic_block().
*
@@ -406,8 +396,7 @@ g_periodic_block (GPeriodic *periodic)
* damaged.
*
* @unblock_time is the monotonic time, as per g_get_monotonic_time(),
- * at which the event causing the unblock occured. If it is %NULL then
- * g_get_monotonic_time() is called internally.
+ * at which the event causing the unblock occured.
*
* This function may not be called from handlers of any signal emitted
* by @periodic.
@@ -416,7 +405,7 @@ g_periodic_block (GPeriodic *periodic)
**/
void
g_periodic_unblock (GPeriodic *periodic,
- const GTimeSpec *unblock_time)
+ gint64 unblock_time)
{
g_return_if_fail (G_IS_PERIODIC (periodic));
g_return_if_fail (!periodic->in_repair);
@@ -425,19 +414,7 @@ g_periodic_unblock (GPeriodic *periodic,
if (--periodic->blocked)
{
- GTimeSpec now;
-
- if (unblock_time == NULL)
- {
- g_get_monotonic_time (&now);
- unblock_time = &now;
- }
-
- periodic->last_run = unblock_time->tv_sec;
- periodic->last_run *= 1000000;
- periodic->last_run += unblock_time->tv_nsec / 1000;
- periodic->last_run *= periodic->hz;
-
+ periodic->last_run = unblock_time * periodic->hz;
g_periodic_run (periodic);
}
}
diff --git a/gio/gperiodic.h b/gio/gperiodic.h
index 636de3a..b48f60e 100644
--- a/gio/gperiodic.h
+++ b/gio/gperiodic.h
@@ -58,7 +58,7 @@ void g_periodic_remove (GPeriod
void g_periodic_block (GPeriodic *periodic);
void g_periodic_unblock (GPeriodic *periodic,
- const GTimeSpec *unblock_time);
+ gint64 unblock_time);
void g_periodic_damaged (GPeriodic *periodic,
GPeriodicRepairFunc callback,
diff --git a/gio/gsocket.c b/gio/gsocket.c
index 637dcd4..ad0d940 100644
--- a/gio/gsocket.c
+++ b/gio/gsocket.c
@@ -2411,7 +2411,7 @@ typedef struct {
GIOCondition condition;
GCancellable *cancellable;
GPollFD cancel_pollfd;
- GTimeSpec timeout_time;
+ gint64 timeout_time;
} GSocketSource;
static gboolean
@@ -2423,19 +2423,20 @@ socket_source_prepare (GSource *source,
if (g_cancellable_is_cancelled (socket_source->cancellable))
return TRUE;
- if (socket_source->timeout_time.tv_sec)
+ if (socket_source->timeout_time)
{
- GTimeSpec now;
+ gint64 now;
- g_source_get_time (source, &now);
- *timeout = ((socket_source->timeout_time.tv_sec - now.tv_sec) * 1000 +
- (socket_source->timeout_time.tv_nsec - now.tv_nsec) / 1000000);
+ now = g_source_get_time (source);
+ /* Round up to ensure that we don't try again too early */
+ *timeout = (socket_source->timeout_time - now + 999) / 1000;
if (*timeout < 0)
- {
- socket_source->socket->priv->timed_out = TRUE;
- socket_source->pollfd.revents = socket_source->condition & (G_IO_IN | G_IO_OUT);
- return TRUE;
- }
+ {
+ socket_source->socket->priv->timed_out = TRUE;
+ socket_source->pollfd.revents = socket_source->condition & (G_IO_IN | G_IO_OUT);
+ *timeout = 0;
+ return TRUE;
+ }
}
else
*timeout = -1;
@@ -2546,15 +2547,11 @@ socket_source_new (GSocket *socket,
g_source_add_poll (source, &socket_source->pollfd);
if (socket->priv->timeout)
- {
- g_get_monotonic_time (&socket_source->timeout_time);
- socket_source->timeout_time.tv_sec += socket->priv->timeout;
- }
+ socket_source->timeout_time = g_get_monotonic_time () +
+ socket->priv->timeout * 1000000;
+
else
- {
- socket_source->timeout_time.tv_sec = 0;
- socket_source->timeout_time.tv_nsec = 0;
- }
+ socket_source->timeout_time = 0;
return source;
}
diff --git a/glib/gmain.c b/glib/gmain.c
index b0f352b..3194c37 100644
--- a/glib/gmain.c
+++ b/glib/gmain.c
@@ -264,7 +264,7 @@ struct _GMainContext
GPollFunc poll_func;
- GTimeSpec time;
+ gint64 time;
gboolean time_is_fresh;
GTimeVal current_time;
gboolean current_time_is_fresh;
@@ -288,7 +288,7 @@ struct _GMainLoop
struct _GTimeoutSource
{
GSource source;
- GTimeSpec expiration;
+ gint64 expiration;
guint interval;
gboolean seconds;
};
@@ -1825,7 +1825,6 @@ g_get_current_time (GTimeVal *result)
/**
* g_get_monotonic_time:
- * @result: #GTimeSpec structure in which to store the time
*
* Queries the system monotonic time, if available.
*
@@ -1839,13 +1838,13 @@ g_get_current_time (GTimeVal *result)
* the wall clock time is updated as infrequently as 64 times a second
* (which is approximately every 16ms).
*
+ * Returns: the monotonic time, in microseconds
+ *
* Since: 2.28
**/
-void
-g_get_monotonic_time (GTimeSpec *result)
+gint64
+g_get_monotonic_time (void)
{
- g_return_if_fail (result != NULL);
-
#ifdef HAVE_CLOCK_GETTIME
/* librt clock_gettime() is our first choice */
{
@@ -1871,8 +1870,30 @@ g_get_monotonic_time (GTimeSpec *result)
#endif
clock_gettime (clockid, &ts);
- result->tv_sec = ts.tv_sec;
- result->tv_nsec = ts.tv_nsec;
+
+ /* In theory monotonic time can have any epoch.
+ *
+ * glib presently assumes the following:
+ *
+ * 1) The epoch comes some time after the birth of Jesus of Nazareth, but
+ * not more than 10000 years later.
+ *
+ * 2) The current time also falls sometime within this range.
+ *
+ * These two reasonable assumptions leave us with a maximum deviation from
+ * the epoch of 10000 years, or 315569520000000000 seconds.
+ *
+ * If we restrict ourselves to this range then the number of microseconds
+ * will always fit well inside the constraints of a int64 (by a factor of
+ * about 29).
+ *
+ * If you actually hit the following assertion, probably you should file a
+ * bug against your operating system for being excessively silly.
+ **/
+ g_assert (G_GINT64_CONSTANT (-315569520000000000) < ts.tv_sec &&
+ ts.tv_sec < G_GINT64_CONSTANT (315569520000000000));
+
+ return (((gint64) ts.tv_sec) * 1000000) + (ts.tv_nsec / 1000);
}
#else
/* It may look like we are discarding accuracy on Windows (since its
@@ -1884,8 +1905,8 @@ g_get_monotonic_time (GTimeSpec *result)
GTimeVal tv;
g_get_current_time (&tv);
- result->tv_sec = tv.tv_sec;
- result->tv_nsec = tv.tv_usec * 1000;
+
+ return (((gint64) tv.tv_sec) * 1000000) + tv.tv_usec;
}
#endif
}
@@ -3395,7 +3416,6 @@ g_source_get_current_time (GSource *source,
/**
* g_source_get_time:
* @source: a #GSource
- * @timespec: #GTimeSpec structure in which to store the time
*
* Gets the time to be used when checking this source. The advantage of
* calling this function over calling g_get_monotonic_time() directly is
@@ -3405,31 +3425,35 @@ g_source_get_current_time (GSource *source,
* The time here is the system monotonic time, if available, or some
* other reasonable alternative otherwise. See g_get_monotonic_time().
*
+ * Returns: the monotonic time in microseconds
+ *
* Since: 2.28
**/
-void
-g_source_get_time (GSource *source,
- GTimeSpec *timespec)
+gint64
+g_source_get_time (GSource *source)
{
GMainContext *context;
-
- g_return_if_fail (source->context != NULL);
-
+ gint64 result;
+
+ g_return_val_if_fail (source->context != NULL, 0);
+
context = source->context;
LOCK_CONTEXT (context);
if (!context->time_is_fresh)
{
- g_get_monotonic_time (&context->time);
+ context->time = g_get_monotonic_time ();
context->time_is_fresh = TRUE;
}
-
- *timespec = context->time;
-
+
+ result = context->time;
+
UNLOCK_CONTEXT (context);
+
+ return result;
}
-
+
/**
* g_main_context_set_poll_func:
* @context: a #GMainContext
@@ -3561,18 +3585,10 @@ g_main_context_is_owner (GMainContext *context)
static void
g_timeout_set_expiration (GTimeoutSource *timeout_source,
- GTimeSpec *current_time)
+ gint64 current_time)
{
- guint seconds = timeout_source->interval / 1000;
- guint msecs = timeout_source->interval - seconds * 1000;
+ timeout_source->expiration = current_time + timeout_source->interval * 1000;
- timeout_source->expiration.tv_sec = current_time->tv_sec + seconds;
- timeout_source->expiration.tv_nsec = current_time->tv_nsec + msecs * 1000000;
- if (timeout_source->expiration.tv_nsec >= 1000000000)
- {
- timeout_source->expiration.tv_nsec -= 1000000000;
- timeout_source->expiration.tv_sec++;
- }
if (timeout_source->seconds)
{
static gint timer_perturb = -1;
@@ -3599,104 +3615,62 @@ g_timeout_set_expiration (GTimeoutSource *timeout_source,
* always only *increase* the expiration time by adding a full
* second in the case that the microsecond portion decreases.
*/
- if (timer_perturb * 1000 < timeout_source->expiration.tv_nsec)
- timeout_source->expiration.tv_sec++;
+ if (timer_perturb < timeout_source->expiration % 1000000)
+ timeout_source->expiration += 1000000;
- timeout_source->expiration.tv_nsec = timer_perturb * 1000;
+ timeout_source->expiration =
+ ((timeout_source->expiration / 1000000) * 1000000) + timer_perturb;
}
}
static gboolean
g_timeout_prepare (GSource *source,
- gint *timeout)
+ gint *timeout)
{
- glong sec;
- glong msec;
- GTimeSpec now;
-
- GTimeoutSource *timeout_source = (GTimeoutSource *)source;
-
- g_source_get_time (source, &now);
-
- sec = timeout_source->expiration.tv_sec - now.tv_sec;
- msec = (timeout_source->expiration.tv_nsec - now.tv_nsec) / 1000000;
+ GTimeoutSource *timeout_source = (GTimeoutSource *) source;
+ gint64 now = g_source_get_time (source);
- /* We do the following in a rather convoluted fashion to deal with
- * the fact that we don't have an integral type big enough to hold
- * the difference of two timevals in millseconds.
- */
- if (sec < 0 || (sec == 0 && msec < 0))
- msec = 0;
- else
+ if (now < timeout_source->expiration)
{
- glong interval_sec = timeout_source->interval / 1000;
- glong interval_msec = timeout_source->interval % 1000;
-
- if (msec < 0)
- {
- msec += 1000;
- sec -= 1;
- }
-
- if (sec > interval_sec ||
- (sec == interval_sec && msec > interval_msec))
- {
- /* The system time has been set backwards, so we
- * reset the expiration time to now + timeout_source->interval;
- * this at least avoids hanging for long periods of time.
- */
- g_timeout_set_expiration (timeout_source, &now);
- msec = MIN (G_MAXINT, timeout_source->interval);
- }
- else
- {
- msec = MIN (G_MAXINT, (guint)msec + 1000 * (guint)sec);
- }
+ /* Round up to ensure that we don't try again too early */
+ *timeout = (timeout_source->expiration - now + 999) / 1000;
+ return FALSE;
}
- *timeout = (gint)msec;
-
- return msec == 0;
+ *timeout = 0;
+ return TRUE;
}
static gboolean
g_timeout_check (GSource *source)
{
- GTimeSpec now;
- GTimeoutSource *timeout_source = (GTimeoutSource *)source;
+ GTimeoutSource *timeout_source = (GTimeoutSource *) source;
+ gint64 now = g_source_get_time (source);
- g_source_get_time (source, &now);
-
- return ((timeout_source->expiration.tv_sec < now.tv_sec) ||
- ((timeout_source->expiration.tv_sec == now.tv_sec) &&
- (timeout_source->expiration.tv_nsec <= now.tv_nsec)));
+ return timeout_source->expiration <= now;
}
static gboolean
g_timeout_dispatch (GSource *source,
- GSourceFunc callback,
- gpointer user_data)
+ GSourceFunc callback,
+ gpointer user_data)
{
GTimeoutSource *timeout_source = (GTimeoutSource *)source;
+ gboolean again;
if (!callback)
{
g_warning ("Timeout source dispatched without callback\n"
- "You must call g_source_set_callback().");
+ "You must call g_source_set_callback().");
return FALSE;
}
-
- if (callback (user_data))
- {
- GTimeSpec now;
- g_source_get_time (source, &now);
- g_timeout_set_expiration (timeout_source, &now);
+ again = callback (user_data);
- return TRUE;
- }
- else
- return FALSE;
+ if (again)
+ g_timeout_set_expiration (timeout_source, g_source_get_time (source));
+
+ return again;
}
/**
@@ -3716,13 +3690,10 @@ g_timeout_source_new (guint interval)
{
GSource *source = g_source_new (&g_timeout_funcs, sizeof (GTimeoutSource));
GTimeoutSource *timeout_source = (GTimeoutSource *)source;
- GTimeSpec now;
timeout_source->interval = interval;
+ g_timeout_set_expiration (timeout_source, g_get_monotonic_time ());
- g_get_monotonic_time (&now);
- g_timeout_set_expiration (timeout_source, &now);
-
return source;
}
@@ -3748,13 +3719,11 @@ g_timeout_source_new_seconds (guint interval)
{
GSource *source = g_source_new (&g_timeout_funcs, sizeof (GTimeoutSource));
GTimeoutSource *timeout_source = (GTimeoutSource *)source;
- GTimeSpec now;
timeout_source->interval = 1000 * interval;
timeout_source->seconds = TRUE;
- g_get_monotonic_time (&now);
- g_timeout_set_expiration (timeout_source, &now);
+ g_timeout_set_expiration (timeout_source, g_get_monotonic_time ());
return source;
}
diff --git a/glib/gmain.h b/glib/gmain.h
index 73c888d..c87a762 100644
--- a/glib/gmain.h
+++ b/glib/gmain.h
@@ -367,8 +367,7 @@ void g_source_remove_poll (GSource *source,
void g_source_get_current_time (GSource *source,
GTimeVal *timeval);
#endif
-void g_source_get_time (GSource *source,
- GTimeSpec *timespec);
+gint64 g_source_get_time (GSource *source);
/* void g_source_connect_closure (GSource *source,
GClosure *closure);
@@ -383,8 +382,8 @@ GSource *g_timeout_source_new_seconds (guint interval);
/* Miscellaneous functions
*/
-void g_get_current_time (GTimeVal *result);
-void g_get_monotonic_time (GTimeSpec *result);
+void g_get_current_time (GTimeVal *result);
+gint64 g_get_monotonic_time (void);
/* ============== Compat main loop stuff ================== */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]