diff options
author | Thomas Haller <thaller@redhat.com> | 2020-04-23 14:23:23 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2020-04-24 13:58:46 +0200 |
commit | cd5157a0c38adb20eb290a145888703b3d09dd4f (patch) | |
tree | 993a391fe97cdbb15329ad3add115145d625c54d /shared | |
parent | 93b634f1a23c43dd71c3b7668ae738c3ab6c970e (diff) | |
download | NetworkManager-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.c | 103 | ||||
-rw-r--r-- | shared/nm-glib-aux/nm-shared-utils.h | 13 |
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); /*****************************************************************************/ |