about summary refs log tree commit diff
path: root/shared/nm-glib-aux/nm-shared-utils.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2020-05-08 21:40:53 +0200
committerMichael Biebl <biebl@debian.org>2020-05-08 21:40:53 +0200
commitd460892bbfece74fb6d3cd846bf6ef548290be41 (patch)
tree0474e5be0b5e5fac0d2f3a1e554382e8d1aa6397 /shared/nm-glib-aux/nm-shared-utils.c
parent1e5977b62f896e844b548c3007ace9e1dfa7f9ed (diff)
New upstream version 1.24.0 upstream/1.24.0
Diffstat (limited to 'shared/nm-glib-aux/nm-shared-utils.c')
-rw-r--r--shared/nm-glib-aux/nm-shared-utils.c121
1 files changed, 93 insertions, 28 deletions
diff --git a/shared/nm-glib-aux/nm-shared-utils.c b/shared/nm-glib-aux/nm-shared-utils.c
index c06399dd..5dd099a7 100644
--- a/shared/nm-glib-aux/nm-shared-utils.c
+++ b/shared/nm-glib-aux/nm-shared-utils.c
@@ -397,6 +397,24 @@ truncate:
 
 /*****************************************************************************/
 
+GBytes *
+nm_gbytes_get_empty (void)
+{
+	static GBytes *bytes = NULL;
+	GBytes *b;
+
+again:
+	b = g_atomic_pointer_get (&bytes);
+	if (G_UNLIKELY (!b)) {
+		b = g_bytes_new_static ("", 0);
+		if (!g_atomic_pointer_compare_and_exchange (&bytes, NULL, b)) {
+			g_bytes_unref (b);
+			goto again;
+		}
+	}
+	return b;
+}
+
 /**
  * nm_utils_gbytes_equals:
  * @bytes: (allow-none): a #GBytes array to compare. Note that
@@ -3655,9 +3673,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 +3683,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 +3699,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);
 }
 
 /*****************************************************************************/