Commit f8c1c1f9 authored by Matthias Clasen's avatar Matthias Clasen

Add functions for approximate timeouts

parent 4a7aeef1
2006-09-10 Matthias Clasen <mclasen@redhat.com> 2006-09-10 Matthias Clasen <mclasen@redhat.com>
* glib/glib.symbols:
* glib/gmain.[hc]: Add functions to create approximate
timeouts. (#353942, Arjan van de Ven)
* glib/gstdio.c (g_rename): Initialize save_errno. * glib/gstdio.c (g_rename): Initialize save_errno.
(#355206, Mike Edenfield) (#355206, Mike Edenfield)
......
2006-09-10 Matthias Clasen <mclasen@redhat.com>
* glib/glib-sections.txt: Add new functions
2006-08-28 Matthias Clasen <mclasen@redhat.com> 2006-08-28 Matthias Clasen <mclasen@redhat.com>
* glib/compiling.sgml: Add a note about G_DISABLE_DEPRECATED. * glib/compiling.sgml: Add a note about G_DISABLE_DEPRECATED.
......
...@@ -437,8 +437,10 @@ g_main_set_poll_func ...@@ -437,8 +437,10 @@ g_main_set_poll_func
<SUBSECTION> <SUBSECTION>
g_timeout_source_new g_timeout_source_new
g_timeout_source_new_seconds
g_timeout_add g_timeout_add
g_timeout_add_full g_timeout_add_full
g_timeout_add_seconds
<SUBSECTION> <SUBSECTION>
g_idle_source_new g_idle_source_new
......
...@@ -617,8 +617,10 @@ g_idle_add_full ...@@ -617,8 +617,10 @@ g_idle_add_full
g_idle_remove_by_data g_idle_remove_by_data
g_idle_source_new g_idle_source_new
g_timeout_add g_timeout_add
g_timeout_add_seconds
g_timeout_add_full g_timeout_add_full
g_timeout_source_new g_timeout_source_new
g_timeout_source_new_seconds
#endif #endif
#endif #endif
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <signal.h> #include <signal.h>
#include <sys/types.h> #include <sys/types.h>
#include <time.h> #include <time.h>
#include <stdlib.h>
#ifdef HAVE_SYS_TIME_H #ifdef HAVE_SYS_TIME_H
#include <sys/time.h> #include <sys/time.h>
#endif /* HAVE_SYS_TIME_H */ #endif /* HAVE_SYS_TIME_H */
...@@ -179,6 +180,7 @@ struct _GTimeoutSource ...@@ -179,6 +180,7 @@ struct _GTimeoutSource
GSource source; GSource source;
GTimeVal expiration; GTimeVal expiration;
guint interval; guint interval;
guint granularity;
}; };
struct _GChildWatchSource struct _GChildWatchSource
...@@ -281,6 +283,8 @@ static gint child_watch_wake_up_pipe[2] = {0, 0}; ...@@ -281,6 +283,8 @@ 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,
...@@ -3337,6 +3341,55 @@ g_timeout_set_expiration (GTimeoutSource *timeout_source, ...@@ -3337,6 +3341,55 @@ g_timeout_set_expiration (GTimeoutSource *timeout_source,
timeout_source->expiration.tv_usec -= 1000000; timeout_source->expiration.tv_usec -= 1000000;
timeout_source->expiration.tv_sec++; timeout_source->expiration.tv_sec++;
} }
if (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 = getenv("DBUS_SESSION_BUS_ADDRESS");
if (!session_bus_address)
session_bus_address = getenv("HOSTNAME");
if (session_bus_address)
timer_perturb = g_str_hash(session_bus_address);
else
timer_perturb = 0;
}
if (timeout_source->granularity)
{
gint remainder;
gint gran; /* in usecs */
gint perturb;
gran = timeout_source->granularity * 1000;
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_usec -= perturb;
if (timeout_source->expiration.tv_usec < 0)
{
timeout_source->expiration.tv_usec += 1000000;
timeout_source->expiration.tv_sec--;
}
remainder = timeout_source->expiration.tv_usec % gran;
if (remainder >= gran/4) /* round up */
timeout_source->expiration.tv_usec += gran;
timeout_source->expiration.tv_usec -= remainder;
/* shift back */
timeout_source->expiration.tv_usec += perturb;
/* the rounding may have overflown tv_usec */
while (timeout_source->expiration.tv_usec > 1000000)
{
timeout_source->expiration.tv_usec -= 1000000;
timeout_source->expiration.tv_sec++;
}
}
} }
static gboolean static gboolean
...@@ -3459,6 +3512,39 @@ g_timeout_source_new (guint interval) ...@@ -3459,6 +3512,39 @@ g_timeout_source_new (guint interval)
return source; return source;
} }
/**
* g_timeout_source_new_seconds:
* @interval: the timeout interval in seconds
*
* Creates a new timeout source.
*
* The source will not initially be associated with any #GMainContext
* and must be added to one with g_source_attach() before it will be
* executed.
* The scheduling granularity/accuracy of this timeout source will be
* in seconds.
*
* Return value: the newly-created timeout source
*
* Since: 2.14
**/
GSource *
g_timeout_source_new_seconds (guint interval)
{
GSource *source = g_source_new (&g_timeout_funcs, sizeof (GTimeoutSource));
GTimeoutSource *timeout_source = (GTimeoutSource *)source;
GTimeVal current_time;
timeout_source->interval = 1000*interval;
timeout_source->granularity = 1000;
g_get_current_time (&current_time);
g_timeout_set_expiration (timeout_source, &current_time);
return source;
}
/** /**
* g_timeout_add_full: * g_timeout_add_full:
* @priority: the priority of the idle source. Typically this will be in the * @priority: the priority of the idle source. Typically this will be in the
...@@ -3527,6 +3613,11 @@ g_timeout_add_full (gint priority, ...@@ -3527,6 +3613,11 @@ g_timeout_add_full (gint priority,
* timeout is recalculated based on the current time and the given interval * timeout is recalculated based on the current time and the given interval
* (it does not try to 'catch up' time lost in delays). * (it does not try to 'catch up' time lost in delays).
* *
* If you want to have a timer in the "seconds" range and do not care
* about the exact time of the first call of the timer, use the
* g_timeout_add_seconds() function; this function allows for more
* optimizations and more efficient system power usage.
*
* Return value: the ID (greater than 0) of the event source. * Return value: the ID (greater than 0) of the event source.
**/ **/
guint guint
...@@ -3538,6 +3629,62 @@ g_timeout_add (guint32 interval, ...@@ -3538,6 +3629,62 @@ g_timeout_add (guint32 interval,
interval, function, data, NULL); interval, function, data, NULL);
} }
/**
* g_timeout_add_seconds:
* @interval: the time between calls to the function, in seconds
* @function: function to call
* @data: data to pass to @function
*
* Sets a function to be called at regular intervals, with the default
* priority, #G_PRIORITY_DEFAULT. The function is called repeatedly
* until it returns %FALSE, at which point the timeout is automatically
* destroyed and the function will not be called again.
*
* Unlike g_timeout_add(), this function operates at whole second granularity.
* The initial starting point of the timer is determined by the implementation
* and the implementation is expected to group multiple timers together so that
* they fire all at the same time.
* To allow this grouping, the @interval to the first timer is rounded
* and can deviate up to one second from the specified interval.
* Subsequent timer iterations will generally run at the specified interval.
*
* Note that timeout functions may be delayed, due to the processing of other
* event sources. Thus they should not be relied on for precise timing.
* After each call to the timeout function, the time of the next
* timeout is recalculated based on the current time and the given @interval
*
* If you want timing more precise than whole seconds, use g_timeout_add()
* instead.
*
* The grouping of timers to fire at the same time results in a more power
* and CPU efficient behavior so if your timer is in multiples of seconds
* and you don't require the first timer exactly 1 second from now, the
* use of g_timeout_add_second() is prefered over g_timeout_add().
*
* Return value: the ID (greater than 0) of the event source.
*
* Since: 2.14
**/
guint
g_timeout_add_seconds (guint32 interval,
GSourceFunc function,
gpointer data)
{
GSource *source;
guint id;
g_return_val_if_fail (function != NULL, 0);
source = g_timeout_source_new_seconds (interval);
g_source_set_callback (source, function, data, NULL);
id = g_source_attach (source, NULL);
g_source_unref (source);
return id;
}
/* Child watch functions */ /* Child watch functions */
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
......
...@@ -256,6 +256,7 @@ void g_source_get_current_time (GSource *source, ...@@ -256,6 +256,7 @@ void g_source_get_current_time (GSource *source,
GSource *g_idle_source_new (void); GSource *g_idle_source_new (void);
GSource *g_child_watch_source_new (GPid pid); GSource *g_child_watch_source_new (GPid pid);
GSource *g_timeout_source_new (guint interval); GSource *g_timeout_source_new (guint interval);
GSource *g_timeout_source_new_seconds (guint interval);
/* Miscellaneous functions /* Miscellaneous functions
*/ */
...@@ -298,6 +299,9 @@ guint g_timeout_add_full (gint priority, ...@@ -298,6 +299,9 @@ guint g_timeout_add_full (gint priority,
guint g_timeout_add (guint interval, guint g_timeout_add (guint interval,
GSourceFunc function, GSourceFunc function,
gpointer data); gpointer data);
guint g_timeout_add_seconds (guint interval,
GSourceFunc function,
gpointer data);
guint g_child_watch_add_full (gint priority, guint g_child_watch_add_full (gint priority,
GPid pid, GPid pid,
GChildWatchFunc function, GChildWatchFunc function,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment