mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-06-19 10:08:38 +02:00
glib-aux: use g_cancellable_connection() in nm_utils_invoke_on_idle() and cleanup
Use g_cancellable_connect(). That approach better handles the case where the cancellable is already cancelled. Theoretically, we could extend that approach further and make it thread-safe, but in the current form is nm_utils_invoke_on_idle() not thread-safe. While at it, also cleanup duplicate code during completion.
This commit is contained in:
parent
b4c25f9131
commit
758fbd7aac
1 changed files with 31 additions and 26 deletions
|
|
@ -4293,11 +4293,9 @@ typedef struct {
|
|||
gulong cancelled_id;
|
||||
} InvokeOnIdleData;
|
||||
|
||||
static gboolean
|
||||
_nm_utils_invoke_on_idle_cb_idle(gpointer user_data)
|
||||
static void
|
||||
_nm_utils_invoke_on_idle_complete(InvokeOnIdleData *data)
|
||||
{
|
||||
InvokeOnIdleData *data = user_data;
|
||||
|
||||
nm_clear_g_signal_handler(data->cancellable, &data->cancelled_id);
|
||||
|
||||
data->callback(data->callback_user_data, data->cancellable);
|
||||
|
|
@ -4305,18 +4303,31 @@ _nm_utils_invoke_on_idle_cb_idle(gpointer user_data)
|
|||
nm_g_object_unref(data->cancellable);
|
||||
g_source_destroy(data->source);
|
||||
nm_g_slice_free(data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_nm_utils_invoke_on_idle_cb_idle(gpointer user_data)
|
||||
{
|
||||
_nm_utils_invoke_on_idle_complete(user_data);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
_nm_utils_invoke_on_idle_cb_cancelled(GCancellable *cancellable, InvokeOnIdleData *data)
|
||||
{
|
||||
/* on cancellation, we invoke the callback synchronously. */
|
||||
nm_clear_g_signal_handler(data->cancellable, &data->cancelled_id);
|
||||
nm_clear_g_source_inst(&data->source);
|
||||
data->callback(data->callback_user_data, data->cancellable);
|
||||
nm_g_object_unref(data->cancellable);
|
||||
nm_g_slice_free(data);
|
||||
if (data->cancelled_id == 0) {
|
||||
/* this can only happen during _nm_utils_invoke_on_idle_start(). Don't do anything,
|
||||
* we still schedule an idle action. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* On cancellation, we invoke the callback synchronously.
|
||||
*
|
||||
* Note that this is not thread-safe, meaning: you can only cancel the cancellable
|
||||
* while not iterating the GMainContext (that has the idle/timeout source attached).
|
||||
* Making this thread safe would be complicated, and it's simply not used by our
|
||||
* callers. */
|
||||
_nm_utils_invoke_on_idle_complete(data);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -4340,23 +4351,17 @@ _nm_utils_invoke_on_idle_start(gboolean use_timeout,
|
|||
};
|
||||
|
||||
if (cancellable) {
|
||||
if (g_cancellable_is_cancelled(cancellable)) {
|
||||
/* the cancellable is already cancelled. We ignore the timeout
|
||||
* and always schedule an idle action. */
|
||||
gulong cancelled_id;
|
||||
|
||||
cancelled_id = g_cancellable_connect(cancellable,
|
||||
G_CALLBACK(_nm_utils_invoke_on_idle_cb_cancelled),
|
||||
data,
|
||||
NULL);
|
||||
if (cancelled_id == 0) {
|
||||
/* the cancellable is already cancelled. We still 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);
|
||||
}
|
||||
} else
|
||||
data->cancelled_id = cancelled_id;
|
||||
}
|
||||
|
||||
if (use_timeout) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue