summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-12-06 13:18:59 +0100
committerThomas Haller <thaller@redhat.com>2019-12-10 07:53:25 +0100
commit691af7d32522ed89a555ca1a5919c626b0c2c2a6 (patch)
tree47974348fb9522b57f83c1a00e6d280605ce94f1
parent2532deadfcc85d8e5755b67487a3d7196ca86151 (diff)
downloadNetworkManager-691af7d32522ed89a555ca1a5919c626b0c2c2a6.tar.gz
shared: add nmc_client_new_waitsync() and nmc_client_new_async*() helpers
Benefits: - nmc_client_new_async*() allows to set properties on the NMClient instance before calling g_async_initable_init_async(). It also allows to subscribe to any signals (like NM_CLIENT_DEVICE_ADDED) before actually iterating the GMainContext. This is a sensible and supported thing to do! - nmc_client_new_waitsync() iterates the GMainContext until the (async) initialization is complete. That is different from synchronous nm_client_new(), which does not iterate the caller's GMainContext, and hence needs an internal context to ensure the order of events is honored. - nmc_client_new_waitsync() always returns the NMClient instance, even if initialization fails. That is useful if you need the nm_client_get_context_busy_watcher() instance to ensure all pending messages are completed.
-rw-r--r--shared/nm-libnm-aux/nm-libnm-aux.c116
-rw-r--r--shared/nm-libnm-aux/nm-libnm-aux.h18
2 files changed, 134 insertions, 0 deletions
diff --git a/shared/nm-libnm-aux/nm-libnm-aux.c b/shared/nm-libnm-aux/nm-libnm-aux.c
index 2a6b6b22e2..83b6f71b6b 100644
--- a/shared/nm-libnm-aux/nm-libnm-aux.c
+++ b/shared/nm-libnm-aux/nm-libnm-aux.c
@@ -3,3 +3,119 @@
#include "nm-default.h"
#include "nm-libnm-aux.h"
+
+/*****************************************************************************/
+
+NMClient *
+nmc_client_new_async_valist (GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ const char *first_property_name,
+ va_list ap)
+{
+ NMClient *nmc;
+
+ nmc = NM_CLIENT (g_object_new_valist (NM_TYPE_CLIENT, first_property_name, ap));
+ g_async_initable_init_async (G_ASYNC_INITABLE (nmc),
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ callback,
+ user_data);
+ return nmc;
+}
+
+NMClient *
+nmc_client_new_async (GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ const char *first_property_name,
+ ...)
+{
+ NMClient *nmc;
+ va_list ap;
+
+ va_start (ap, first_property_name);
+ nmc = nmc_client_new_async_valist (cancellable,
+ callback,
+ user_data,
+ first_property_name,
+ ap);
+ va_end (ap);
+ return nmc;
+}
+
+/*****************************************************************************/
+
+typedef struct {
+ GMainLoop *main_loop;
+ NMClient *nmc;
+ GError *error;
+} ClientCreateData;
+
+static void
+_nmc_client_new_waitsync_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ClientCreateData *data = user_data;
+
+ g_async_initable_init_finish (G_ASYNC_INITABLE (source_object),
+ result,
+ &data->error);
+ g_main_loop_quit (data->main_loop);
+}
+
+/**
+ * nmc_client_new:
+ * @cancellable: the cancellable to abort the creation.
+ * @out_nmc: (out): (transfer full): if give, transfers a reference
+ * to the NMClient instance. Note that this never fails to create
+ * the NMClient GObject, but depending on the return value,
+ * the instance was successfully initialized or not.
+ * @error: the error if creation fails.
+ * @first_property_name: the name of the first property
+ * @...: the value of the first property, followed optionally by more
+ * name/value pairs, followed by %NULL
+ *
+ * Returns: %TRUE, if the client was successfully initalized.
+ *
+ * This uses nm_client_new_async() to create a NMClient instance,
+ * but it iterates the current GMainContext until the client is
+ * ready. As such, it waits for the client creation to complete
+ * (like sync nm_client_new()) but it iterates the caller's GMainContext
+ * (unlike sync nm_client_new()). This is often preferable, because
+ * sync nm_client_new() needs to create an additional internal GMainContext
+ * that it can iterate instead. That has a performance overhead that
+ * is often unnecessary.
+ */
+gboolean
+nmc_client_new_waitsync (GCancellable *cancellable,
+ NMClient **out_nmc,
+ GError **error,
+ const char *first_property_name,
+ ...)
+{
+ gs_unref_object NMClient *nmc = NULL;
+ nm_auto_unref_gmainloop GMainLoop *main_loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE);
+ ClientCreateData data = {
+ .main_loop = main_loop,
+ };
+ va_list ap;
+
+ va_start (ap, first_property_name);
+ nmc = nmc_client_new_async_valist (cancellable,
+ _nmc_client_new_waitsync_cb,
+ &data,
+ first_property_name,
+ ap);
+ va_end (ap);
+
+ g_main_loop_run (main_loop);
+
+ NM_SET_OUT (out_nmc, g_steal_pointer (&nmc));
+ if (data.error) {
+ g_propagate_error (error, data.error);
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/shared/nm-libnm-aux/nm-libnm-aux.h b/shared/nm-libnm-aux/nm-libnm-aux.h
index 66bf05b69b..a0aff19f28 100644
--- a/shared/nm-libnm-aux/nm-libnm-aux.h
+++ b/shared/nm-libnm-aux/nm-libnm-aux.h
@@ -3,4 +3,22 @@
#ifndef __NM_LIBNM_AUX_H__
#define __NM_LIBNM_AUX_H__
+NMClient *nmc_client_new_async_valist (GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ const char *first_property_name,
+ va_list ap);
+
+NMClient *nmc_client_new_async (GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ const char *first_property_name,
+ ...);
+
+gboolean nmc_client_new_waitsync (GCancellable *cancellable,
+ NMClient **out_nmc,
+ GError **error,
+ const char *first_property_name,
+ ...);
+
#endif /* __NM_LIBNM_AUX_H__ */