summaryrefslogtreecommitdiff
path: root/shared
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-04-23 14:23:23 +0200
committerThomas Haller <thaller@redhat.com>2020-04-24 13:58:46 +0200
commitcd5157a0c38adb20eb290a145888703b3d09dd4f (patch)
tree993a391fe97cdbb15329ad3add115145d625c54d /shared
parent93b634f1a23c43dd71c3b7668ae738c3ab6c970e (diff)
downloadNetworkManager-cd5157a0c38adb20eb290a145888703b3d09dd4f.tar.gz
shared: add nm_utils_invoke_on_timeout()
Add nm_utils_invoke_on_timeout() beside nm_utils_invoke_on_idle(). They are fundamentally similar, except one schedules an idle handler and the other a timeout. Also, use the current g_main_context_get_thread_default() as context instead of the singleton instance. That is a change in behavior, but the only caller of nm_utils_invoke_on_idle() is the daemon, which doesn't use different main contexts. Anyway, to avoid anybody being tripped up by this also change the order of arguments. It anyway seems nicer to first pass the cancellable, and the callback and user data as last arguments. It's more in line with glib's asynchronous methods. Also, in the unlikely case that the cancellable is already cancelled from the start, always schedule an idle action to complete fast.
Diffstat (limited to 'shared')
-rw-r--r--shared/nm-glib-aux/nm-shared-utils.c103
-rw-r--r--shared/nm-glib-aux/nm-shared-utils.h13
2 files changed, 84 insertions, 32 deletions
diff --git a/shared/nm-glib-aux/nm-shared-utils.c b/shared/nm-glib-aux/nm-shared-utils.c
index c06399dda8..61e3e26716 100644
--- a/shared/nm-glib-aux/nm-shared-utils.c
+++ b/shared/nm-glib-aux/nm-shared-utils.c
@@ -3655,9 +3655,9 @@ _nm_utils_user_data_unpack (gpointer user_data, int nargs, ...)
typedef struct {
gpointer callback_user_data;
GCancellable *cancellable;
+ GSource *source;
NMUtilsInvokeOnIdleCallback callback;
gulong cancelled_id;
- guint idle_id;
} InvokeOnIdleData;
static gboolean
@@ -3665,12 +3665,13 @@ _nm_utils_invoke_on_idle_cb_idle (gpointer user_data)
{
InvokeOnIdleData *data = user_data;
- data->idle_id = 0;
nm_clear_g_signal_handler (data->cancellable, &data->cancelled_id);
data->callback (data->callback_user_data, data->cancellable);
+
nm_g_object_unref (data->cancellable);
- g_slice_free (InvokeOnIdleData, data);
+ g_source_destroy (data->source);
+ nm_g_slice_free (data);
return G_SOURCE_REMOVE;
}
@@ -3680,41 +3681,87 @@ _nm_utils_invoke_on_idle_cb_cancelled (GCancellable *cancellable,
{
/* on cancellation, we invoke the callback synchronously. */
nm_clear_g_signal_handler (data->cancellable, &data->cancelled_id);
- nm_clear_g_source (&data->idle_id);
+ nm_clear_g_source_inst (&data->source);
data->callback (data->callback_user_data, data->cancellable);
nm_g_object_unref (data->cancellable);
- g_slice_free (InvokeOnIdleData, data);
+ nm_g_slice_free (data);
}
-void
-nm_utils_invoke_on_idle (NMUtilsInvokeOnIdleCallback callback,
- gpointer callback_user_data,
- GCancellable *cancellable)
+static void
+_nm_utils_invoke_on_idle_start (gboolean use_timeout,
+ guint timeout_msec,
+ GCancellable *cancellable,
+ NMUtilsInvokeOnIdleCallback callback,
+ gpointer callback_user_data)
{
InvokeOnIdleData *data;
+ GSource *source;
g_return_if_fail (callback);
data = g_slice_new (InvokeOnIdleData);
- data->callback = callback;
- data->callback_user_data = callback_user_data;
- data->cancellable = nm_g_object_ref (cancellable);
- if ( cancellable
- && !g_cancellable_is_cancelled (cancellable)) {
- /* if we are passed a non-cancelled cancellable, we register to the "cancelled"
- * signal an invoke the callback synchronously (from the signal handler).
- *
- * We don't do that,
- * - if the cancellable is already cancelled (because we don't want to invoke
- * the callback synchronously from the caller).
- * - if we have no cancellable at hand. */
- data->cancelled_id = g_signal_connect (cancellable,
- "cancelled",
- G_CALLBACK (_nm_utils_invoke_on_idle_cb_cancelled),
- data);
- } else
- data->cancelled_id = 0;
- data->idle_id = g_idle_add (_nm_utils_invoke_on_idle_cb_idle, data);
+ *data = (InvokeOnIdleData) {
+ .callback = callback,
+ .callback_user_data = callback_user_data,
+ .cancellable = nm_g_object_ref (cancellable),
+ .cancelled_id = 0,
+ };
+
+ if (cancellable) {
+ if (g_cancellable_is_cancelled (cancellable)) {
+ /* the cancellable is already cancelled. We ignore the timeout
+ * and always schedule an idle action. */
+ use_timeout = FALSE;
+ } else {
+ /* if we are passed a non-cancelled cancellable, we register to the "cancelled"
+ * signal an invoke the callback synchronously (from the signal handler).
+ *
+ * We don't do that,
+ * - if the cancellable is already cancelled (because we don't want to invoke
+ * the callback synchronously from the caller).
+ * - if we have no cancellable at hand. */
+ data->cancelled_id = g_signal_connect (cancellable,
+ "cancelled",
+ G_CALLBACK (_nm_utils_invoke_on_idle_cb_cancelled),
+ data);
+ }
+ }
+
+ if (use_timeout) {
+ source = nm_g_timeout_source_new (timeout_msec,
+ G_PRIORITY_DEFAULT,
+ _nm_utils_invoke_on_idle_cb_idle,
+ data,
+ NULL);
+ } else {
+ source = nm_g_idle_source_new (G_PRIORITY_DEFAULT,
+ _nm_utils_invoke_on_idle_cb_idle,
+ data,
+ NULL);
+ }
+
+ /* use the current thread default context. */
+ g_source_attach (source,
+ g_main_context_get_thread_default ());
+
+ data->source = source;
+}
+
+void
+nm_utils_invoke_on_idle (GCancellable *cancellable,
+ NMUtilsInvokeOnIdleCallback callback,
+ gpointer callback_user_data)
+{
+ _nm_utils_invoke_on_idle_start (FALSE, 0, cancellable, callback, callback_user_data);
+}
+
+void
+nm_utils_invoke_on_timeout (guint timeout_msec,
+ GCancellable *cancellable,
+ NMUtilsInvokeOnIdleCallback callback,
+ gpointer callback_user_data)
+{
+ _nm_utils_invoke_on_idle_start (TRUE, timeout_msec, cancellable, callback, callback_user_data);
}
/*****************************************************************************/
diff --git a/shared/nm-glib-aux/nm-shared-utils.h b/shared/nm-glib-aux/nm-shared-utils.h
index 38b100416d..9200f80fdf 100644
--- a/shared/nm-glib-aux/nm-shared-utils.h
+++ b/shared/nm-glib-aux/nm-shared-utils.h
@@ -1629,12 +1629,17 @@ void _nm_utils_user_data_unpack (gpointer user_data, int nargs, ...);
/*****************************************************************************/
-typedef void (*NMUtilsInvokeOnIdleCallback) (gpointer callback_user_data,
+typedef void (*NMUtilsInvokeOnIdleCallback) (gpointer user_data,
GCancellable *cancellable);
-void nm_utils_invoke_on_idle (NMUtilsInvokeOnIdleCallback callback,
- gpointer callback_user_data,
- GCancellable *cancellable);
+void nm_utils_invoke_on_idle (GCancellable *cancellable,
+ NMUtilsInvokeOnIdleCallback callback,
+ gpointer callback_user_data);
+
+void nm_utils_invoke_on_timeout (guint timeout_msec,
+ GCancellable *cancellable,
+ NMUtilsInvokeOnIdleCallback callback,
+ gpointer callback_user_data);
/*****************************************************************************/