diff options
author | Thomas Haller <thaller@redhat.com> | 2019-12-06 13:18:59 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2019-12-10 09:17:17 +0100 |
commit | 9e10b4f699dbaa47b5773244157a3c9be1aa4eb4 (patch) | |
tree | 66040e2a09163703401bdde3903ee498cef2085c | |
parent | 3843e0c87d1351f8fb2ecfb37a7a33172988aa04 (diff) | |
download | NetworkManager-9e10b4f699dbaa47b5773244157a3c9be1aa4eb4.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.c | 116 | ||||
-rw-r--r-- | shared/nm-libnm-aux/nm-libnm-aux.h | 18 |
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__ */ |