summary refs log tree commit diff
path: root/shared/nm-glib-aux
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
parent1e5977b62f896e844b548c3007ace9e1dfa7f9ed (diff)
New upstream version 1.24.0 upstream/1.24.0
Diffstat (limited to 'shared/nm-glib-aux')
-rw-r--r--shared/nm-glib-aux/nm-glib.h8
-rw-r--r--shared/nm-glib-aux/nm-hash-utils.c11
-rw-r--r--shared/nm-glib-aux/nm-hash-utils.h3
-rw-r--r--shared/nm-glib-aux/nm-shared-utils.c121
-rw-r--r--shared/nm-glib-aux/nm-shared-utils.h23
5 files changed, 134 insertions, 32 deletions
diff --git a/shared/nm-glib-aux/nm-glib.h b/shared/nm-glib-aux/nm-glib.h
index 4ecba9ff..7a5b8edd 100644
--- a/shared/nm-glib-aux/nm-glib.h
+++ b/shared/nm-glib-aux/nm-glib.h
@@ -622,4 +622,12 @@ g_hash_table_steal_extended (GHashTable    *hash_table,
 
 /*****************************************************************************/
 
+__attribute__((__deprecated__("Don't use g_cancellable_reset(). Create a new cancellable instead.")))
+void _nm_g_cancellable_reset (GCancellable *cancellable);
+
+#undef g_cancellable_reset
+#define g_cancellable_reset(cancellable) _nm_g_cancellable_reset(cancellable)
+
+/*****************************************************************************/
+
 #endif  /* __NM_GLIB_H__ */
diff --git a/shared/nm-glib-aux/nm-hash-utils.c b/shared/nm-glib-aux/nm-hash-utils.c
index 0a701d06..232c62c0 100644
--- a/shared/nm-glib-aux/nm-hash-utils.c
+++ b/shared/nm-glib-aux/nm-hash-utils.c
@@ -265,6 +265,17 @@ nm_ppdirect_equal (gconstpointer a, gconstpointer b)
 /*****************************************************************************/
 
 guint
+nm_gbytes_hash (gconstpointer p)
+{
+	GBytes *ptr = (GBytes *) p;
+	gconstpointer arr;
+	gsize len;
+
+	arr = g_bytes_get_data (ptr, &len);
+	return nm_hash_mem (792701303u, arr, len);
+}
+
+guint
 nm_pgbytes_hash (gconstpointer p)
 {
 	GBytes *const*ptr = p;
diff --git a/shared/nm-glib-aux/nm-hash-utils.h b/shared/nm-glib-aux/nm-hash-utils.h
index 9f2e9766..be69bfa8 100644
--- a/shared/nm-glib-aux/nm-hash-utils.h
+++ b/shared/nm-glib-aux/nm-hash-utils.h
@@ -315,6 +315,9 @@ gboolean nm_ppdirect_equal (gconstpointer a, gconstpointer b);
 
 /*****************************************************************************/
 
+guint nm_gbytes_hash (gconstpointer p);
+#define nm_gbytes_equal g_bytes_equal
+
 guint nm_pgbytes_hash (gconstpointer p);
 gboolean nm_pgbytes_equal (gconstpointer a, gconstpointer b);
 
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);
 }
 
 /*****************************************************************************/
diff --git a/shared/nm-glib-aux/nm-shared-utils.h b/shared/nm-glib-aux/nm-shared-utils.h
index 537b402b..d5990c2d 100644
--- a/shared/nm-glib-aux/nm-shared-utils.h
+++ b/shared/nm-glib-aux/nm-shared-utils.h
@@ -280,6 +280,14 @@ gboolean nm_utils_ipaddr_is_normalized (int addr_family,
             return (_a < _b) ? -1 : 1; \
     } G_STMT_END
 
+/* In the general case, direct pointer comparison is undefined behavior in C.
+ * Avoid that by casting pointers to void* and then to uintptr_t. This comparison
+ * is not really meaningful, except that it provides some kind of stable sort order
+ * between pointers (that can otherwise not be compared). */
+#define NM_CMP_DIRECT_PTR(a, b) \
+	NM_CMP_DIRECT ((uintptr_t) ((void *) (a)), \
+	               (uintptr_t) ((void *) (b)))
+
 #define NM_CMP_DIRECT_MEMCMP(a, b, size) \
     NM_CMP_RETURN (memcmp ((a), (b), (size)))
 
@@ -381,6 +389,8 @@ nm_utils_is_separator (const char c)
 
 /*****************************************************************************/
 
+GBytes *nm_gbytes_get_empty (void);
+
 static inline gboolean
 nm_gbytes_equal0 (GBytes *a, GBytes *b)
 {
@@ -1621,12 +1631,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);
 
 /*****************************************************************************/