mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-13 15:56:23 +01:00
GSource: new API g_source_set_ready_time()
Add an API to mark a GSource to automatically become ready at the specified monotonic time. https://bugzilla.gnome.org/show_bug.cgi?id=657729
This commit is contained in:
parent
6d25e34998
commit
768574635d
@ -528,6 +528,8 @@ g_source_get_context
|
||||
g_source_set_callback
|
||||
GSourceFunc
|
||||
g_source_set_callback_indirect
|
||||
g_source_set_ready_time
|
||||
g_source_get_ready_time
|
||||
g_source_add_poll
|
||||
g_source_remove_poll
|
||||
g_source_add_child_source
|
||||
|
@ -638,6 +638,7 @@ g_source_get_current_time
|
||||
g_source_get_id
|
||||
g_source_get_name
|
||||
g_source_get_priority
|
||||
g_source_get_ready_time
|
||||
g_source_new
|
||||
g_source_ref
|
||||
g_source_remove
|
||||
@ -653,6 +654,7 @@ g_source_set_name
|
||||
g_source_set_name_by_id
|
||||
g_source_is_destroyed
|
||||
g_source_set_priority
|
||||
g_source_set_ready_time
|
||||
g_source_unref
|
||||
g_idle_add
|
||||
g_idle_add_full
|
||||
|
109
glib/gmain.c
109
glib/gmain.c
@ -317,6 +317,8 @@ struct _GSourcePrivate
|
||||
{
|
||||
GSList *child_sources;
|
||||
GSource *parent_source;
|
||||
|
||||
gint64 ready_time;
|
||||
};
|
||||
|
||||
typedef struct _GSourceIter
|
||||
@ -853,6 +855,8 @@ g_source_new (GSourceFuncs *source_funcs,
|
||||
|
||||
source->flags = G_HOOK_FLAG_ACTIVE;
|
||||
|
||||
source->priv->ready_time = -1;
|
||||
|
||||
/* NULL/0 initialization for all other fields */
|
||||
|
||||
return source;
|
||||
@ -1697,6 +1701,73 @@ g_source_get_priority (GSource *source)
|
||||
return source->priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_source_set_ready_time:
|
||||
* @source: a #GSource
|
||||
* @ready_time: the monotonic time at which the source will be ready,
|
||||
* 0 for "immediately", -1 for "never"
|
||||
*
|
||||
* Sets a #GSource to be dispatched when the given monotonic time is
|
||||
* reached (or passed). If the monotonic time is in the past (as it
|
||||
* always will be if @ready_time is 0) then the source will be
|
||||
* dispatched immediately.
|
||||
*
|
||||
* If @ready_time is -1 then the source is never woken up on the basis
|
||||
* of the passage of time.
|
||||
*
|
||||
* Dispatching the source does not reset the ready time. You should do
|
||||
* so yourself, from the source dispatch function.
|
||||
*
|
||||
* Since: 2.36
|
||||
**/
|
||||
void
|
||||
g_source_set_ready_time (GSource *source,
|
||||
gint64 ready_time)
|
||||
{
|
||||
GMainContext *context;
|
||||
|
||||
g_return_if_fail (source != NULL);
|
||||
g_return_if_fail (source->ref_count > 0);
|
||||
|
||||
if (source->priv->ready_time == ready_time)
|
||||
return;
|
||||
|
||||
context = source->context;
|
||||
|
||||
if (context)
|
||||
LOCK_CONTEXT (context);
|
||||
|
||||
source->priv->ready_time = ready_time;
|
||||
|
||||
if (context)
|
||||
{
|
||||
/* Quite likely that we need to change the timeout on the poll */
|
||||
if (!SOURCE_BLOCKED (source))
|
||||
g_wakeup_signal (context->wakeup);
|
||||
UNLOCK_CONTEXT (context);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* g_source_get_ready_time:
|
||||
* @source: a #GSource
|
||||
*
|
||||
* Gets the "ready time" of @source, as set by
|
||||
* g_source_set_ready_time().
|
||||
*
|
||||
* Any time before the current monotonic time (including 0) is an
|
||||
* indication that the source will fire immediately.
|
||||
*
|
||||
* Returns: the monotonic ready time, -1 for "never"
|
||||
**/
|
||||
gint64
|
||||
g_source_get_ready_time (GSource *source)
|
||||
{
|
||||
g_return_val_if_fail (source != NULL, -1);
|
||||
|
||||
return source->priv->ready_time;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_source_set_can_recurse:
|
||||
* @source: a #GSource
|
||||
@ -3066,6 +3137,31 @@ g_main_context_prepare (GMainContext *context,
|
||||
result = FALSE;
|
||||
}
|
||||
|
||||
if (result == FALSE && source->priv->ready_time != -1)
|
||||
{
|
||||
if (!context->time_is_fresh)
|
||||
{
|
||||
context->time = g_get_monotonic_time ();
|
||||
context->time_is_fresh = TRUE;
|
||||
}
|
||||
|
||||
if (source->priv->ready_time <= context->time)
|
||||
{
|
||||
source_timeout = 0;
|
||||
result = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gint timeout;
|
||||
|
||||
/* rounding down will lead to spinning, so always round up */
|
||||
timeout = (source->priv->ready_time - context->time + 999) / 1000;
|
||||
|
||||
if (source_timeout < 0 || timeout < source_timeout)
|
||||
source_timeout = timeout;
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
GSource *ready_source = source;
|
||||
@ -3243,6 +3339,7 @@ g_main_context_check (GMainContext *context,
|
||||
|
||||
if (check)
|
||||
{
|
||||
/* If the check function is set, call it. */
|
||||
context->in_check_or_prepare++;
|
||||
UNLOCK_CONTEXT (context);
|
||||
|
||||
@ -3254,6 +3351,18 @@ g_main_context_check (GMainContext *context,
|
||||
else
|
||||
result = FALSE;
|
||||
|
||||
if (result == FALSE && source->priv->ready_time != -1)
|
||||
{
|
||||
if (!context->time_is_fresh)
|
||||
{
|
||||
context->time = g_get_monotonic_time ();
|
||||
context->time_is_fresh = TRUE;
|
||||
}
|
||||
|
||||
if (source->priv->ready_time <= context->time)
|
||||
result = TRUE;
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
GSource *ready_source = source;
|
||||
|
@ -88,7 +88,9 @@ typedef struct _GSourceCallbackFuncs GSourceCallbackFuncs;
|
||||
* be -1 if all sources returned -1, or it will be the minimum of all the
|
||||
* @timeout_ values returned which were >= 0. Since 2.36 this may
|
||||
* be %NULL, in which case the effect is as if the function always
|
||||
* returns %FALSE with a timeout of -1.
|
||||
* returns %FALSE with a timeout of -1. If @prepare returns a
|
||||
* timeout and the source also has a 'ready time' set then the
|
||||
* nearer of the two will be used.
|
||||
* @check: Called after all the file descriptors are polled. The source
|
||||
* should return %TRUE if it is ready to be dispatched. Note that some
|
||||
* time may have passed since the previous prepare function was called,
|
||||
@ -462,6 +464,11 @@ GLIB_AVAILABLE_IN_ALL
|
||||
void g_source_set_name_by_id (guint tag,
|
||||
const char *name);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_36
|
||||
void g_source_set_ready_time (GSource *source,
|
||||
gint64 ready_time);
|
||||
GLIB_AVAILABLE_IN_2_36
|
||||
gint64 g_source_get_ready_time (GSource *source);
|
||||
|
||||
/* Used to implement g_source_connect_closure and internally*/
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
|
Loading…
Reference in New Issue
Block a user