mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-09-27 17:52:58 +02: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:
@@ -528,6 +528,8 @@ g_source_get_context
|
|||||||
g_source_set_callback
|
g_source_set_callback
|
||||||
GSourceFunc
|
GSourceFunc
|
||||||
g_source_set_callback_indirect
|
g_source_set_callback_indirect
|
||||||
|
g_source_set_ready_time
|
||||||
|
g_source_get_ready_time
|
||||||
g_source_add_poll
|
g_source_add_poll
|
||||||
g_source_remove_poll
|
g_source_remove_poll
|
||||||
g_source_add_child_source
|
g_source_add_child_source
|
||||||
|
@@ -638,6 +638,7 @@ g_source_get_current_time
|
|||||||
g_source_get_id
|
g_source_get_id
|
||||||
g_source_get_name
|
g_source_get_name
|
||||||
g_source_get_priority
|
g_source_get_priority
|
||||||
|
g_source_get_ready_time
|
||||||
g_source_new
|
g_source_new
|
||||||
g_source_ref
|
g_source_ref
|
||||||
g_source_remove
|
g_source_remove
|
||||||
@@ -653,6 +654,7 @@ g_source_set_name
|
|||||||
g_source_set_name_by_id
|
g_source_set_name_by_id
|
||||||
g_source_is_destroyed
|
g_source_is_destroyed
|
||||||
g_source_set_priority
|
g_source_set_priority
|
||||||
|
g_source_set_ready_time
|
||||||
g_source_unref
|
g_source_unref
|
||||||
g_idle_add
|
g_idle_add
|
||||||
g_idle_add_full
|
g_idle_add_full
|
||||||
|
109
glib/gmain.c
109
glib/gmain.c
@@ -317,6 +317,8 @@ struct _GSourcePrivate
|
|||||||
{
|
{
|
||||||
GSList *child_sources;
|
GSList *child_sources;
|
||||||
GSource *parent_source;
|
GSource *parent_source;
|
||||||
|
|
||||||
|
gint64 ready_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _GSourceIter
|
typedef struct _GSourceIter
|
||||||
@@ -853,6 +855,8 @@ g_source_new (GSourceFuncs *source_funcs,
|
|||||||
|
|
||||||
source->flags = G_HOOK_FLAG_ACTIVE;
|
source->flags = G_HOOK_FLAG_ACTIVE;
|
||||||
|
|
||||||
|
source->priv->ready_time = -1;
|
||||||
|
|
||||||
/* NULL/0 initialization for all other fields */
|
/* NULL/0 initialization for all other fields */
|
||||||
|
|
||||||
return source;
|
return source;
|
||||||
@@ -1697,6 +1701,73 @@ g_source_get_priority (GSource *source)
|
|||||||
return source->priority;
|
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:
|
* g_source_set_can_recurse:
|
||||||
* @source: a #GSource
|
* @source: a #GSource
|
||||||
@@ -3066,6 +3137,31 @@ g_main_context_prepare (GMainContext *context,
|
|||||||
result = FALSE;
|
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)
|
if (result)
|
||||||
{
|
{
|
||||||
GSource *ready_source = source;
|
GSource *ready_source = source;
|
||||||
@@ -3243,6 +3339,7 @@ g_main_context_check (GMainContext *context,
|
|||||||
|
|
||||||
if (check)
|
if (check)
|
||||||
{
|
{
|
||||||
|
/* If the check function is set, call it. */
|
||||||
context->in_check_or_prepare++;
|
context->in_check_or_prepare++;
|
||||||
UNLOCK_CONTEXT (context);
|
UNLOCK_CONTEXT (context);
|
||||||
|
|
||||||
@@ -3254,6 +3351,18 @@ g_main_context_check (GMainContext *context,
|
|||||||
else
|
else
|
||||||
result = FALSE;
|
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)
|
if (result)
|
||||||
{
|
{
|
||||||
GSource *ready_source = source;
|
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
|
* 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
|
* @timeout_ values returned which were >= 0. Since 2.36 this may
|
||||||
* be %NULL, in which case the effect is as if the function always
|
* 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
|
* @check: Called after all the file descriptors are polled. The source
|
||||||
* should return %TRUE if it is ready to be dispatched. Note that some
|
* should return %TRUE if it is ready to be dispatched. Note that some
|
||||||
* time may have passed since the previous prepare function was called,
|
* 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,
|
void g_source_set_name_by_id (guint tag,
|
||||||
const char *name);
|
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*/
|
/* Used to implement g_source_connect_closure and internally*/
|
||||||
GLIB_AVAILABLE_IN_ALL
|
GLIB_AVAILABLE_IN_ALL
|
||||||
|
Reference in New Issue
Block a user