GTimeout: simplify math for 'seconds' case

The code was designed to deal with any granularity of timer and due to
the use of GTimeVal/GTimeSpec, the math for this gets extremely
confusing.

From a practical standpoint, we only ever have a granularity of seconds.

Take advantage of that fact in the code and vastly simplify the math.
This commit is contained in:
Ryan Lortie 2010-11-01 13:31:37 -04:00
parent b6854efdb9
commit d9f5ab56c3

View File

@ -290,7 +290,7 @@ struct _GTimeoutSource
GSource source; GSource source;
GTimeSpec expiration; GTimeSpec expiration;
guint interval; guint interval;
guint granularity; gboolean seconds;
}; };
struct _GChildWatchSource struct _GChildWatchSource
@ -393,8 +393,6 @@ static gint child_watch_wake_up_pipe[2] = {0, 0};
G_LOCK_DEFINE_STATIC (main_context_list); G_LOCK_DEFINE_STATIC (main_context_list);
static GSList *main_context_list = NULL; static GSList *main_context_list = NULL;
static gint timer_perturb = -1;
GSourceFuncs g_timeout_funcs = GSourceFuncs g_timeout_funcs =
{ {
g_timeout_prepare, g_timeout_prepare,
@ -3575,54 +3573,36 @@ g_timeout_set_expiration (GTimeoutSource *timeout_source,
timeout_source->expiration.tv_nsec -= 1000000000; timeout_source->expiration.tv_nsec -= 1000000000;
timeout_source->expiration.tv_sec++; timeout_source->expiration.tv_sec++;
} }
if (timer_perturb==-1) if (timeout_source->seconds)
{ {
/* static gint timer_perturb = -1;
* we want a per machine/session unique 'random' value; try the dbus
* address first, that has a UUID in it. If there is no dbus, use the
* hostname for hashing.
*/
const char *session_bus_address = g_getenv ("DBUS_SESSION_BUS_ADDRESS");
if (!session_bus_address)
session_bus_address = g_getenv ("HOSTNAME");
if (session_bus_address)
timer_perturb = ABS ((gint) g_str_hash (session_bus_address));
else
timer_perturb = 0;
}
if (timeout_source->granularity)
{
gint remainder;
gint gran; /* in nsecs */
gint perturb;
gran = timeout_source->granularity * 1000000; if (timer_perturb == -1)
perturb = timer_perturb % gran;
/*
* We want to give each machine a per machine pertubation;
* shift time back first, and forward later after the rounding
*/
timeout_source->expiration.tv_nsec -= perturb;
if (timeout_source->expiration.tv_nsec < 0)
{ {
timeout_source->expiration.tv_nsec += 1000000000; /*
timeout_source->expiration.tv_sec--; * we want a per machine/session unique 'random' value; try the dbus
* address first, that has a UUID in it. If there is no dbus, use the
* hostname for hashing.
*/
const char *session_bus_address = g_getenv ("DBUS_SESSION_BUS_ADDRESS");
if (!session_bus_address)
session_bus_address = g_getenv ("HOSTNAME");
if (session_bus_address)
timer_perturb = ABS ((gint) g_str_hash (session_bus_address)) % 1000000;
else
timer_perturb = 0;
} }
remainder = timeout_source->expiration.tv_nsec % gran; /* We want the microseconds part of the timeout to land on the
if (remainder >= gran/4) /* round up */ * 'timer_perturb' mark, but we need to make sure we don't try to
timeout_source->expiration.tv_nsec += gran; * set the timeout in the past. We do this by ensuring that we
timeout_source->expiration.tv_nsec -= remainder; * always only *increase* the expiration time by adding a full
/* shift back */ * second in the case that the microsecond portion decreases.
timeout_source->expiration.tv_nsec += perturb; */
if (timer_perturb * 1000 < timeout_source->expiration.tv_nsec)
timeout_source->expiration.tv_sec++;
/* the rounding may have overflown tv_nsec */ timeout_source->expiration.tv_nsec = timer_perturb * 1000;
while (timeout_source->expiration.tv_nsec > 1000000000)
{
timeout_source->expiration.tv_nsec -= 1000000000;
timeout_source->expiration.tv_sec++;
}
} }
} }
@ -3770,8 +3750,8 @@ g_timeout_source_new_seconds (guint interval)
GTimeoutSource *timeout_source = (GTimeoutSource *)source; GTimeoutSource *timeout_source = (GTimeoutSource *)source;
GTimeSpec now; GTimeSpec now;
timeout_source->interval = 1000*interval; timeout_source->interval = 1000 * interval;
timeout_source->granularity = 1000; timeout_source->seconds = TRUE;
g_get_monotonic_time (&now); g_get_monotonic_time (&now);
g_timeout_set_expiration (timeout_source, &now); g_timeout_set_expiration (timeout_source, &now);