|
Packit Service |
a1bd4f |
/* SPDX-License-Identifier: LGPL-2.1+ */
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
#include "nm-default.h"
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
#include "nm-libnm-aux.h"
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
/*****************************************************************************/
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
NMClient *
|
|
Packit Service |
a1bd4f |
nmc_client_new_async_valist(GCancellable * cancellable,
|
|
Packit Service |
a1bd4f |
GAsyncReadyCallback callback,
|
|
Packit Service |
a1bd4f |
gpointer user_data,
|
|
Packit Service |
a1bd4f |
const char * first_property_name,
|
|
Packit Service |
a1bd4f |
va_list ap)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
NMClient *nmc;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
nmc = NM_CLIENT(g_object_new_valist(NM_TYPE_CLIENT, first_property_name, ap));
|
|
Packit Service |
a1bd4f |
g_async_initable_init_async(G_ASYNC_INITABLE(nmc),
|
|
Packit Service |
a1bd4f |
G_PRIORITY_DEFAULT,
|
|
Packit Service |
a1bd4f |
cancellable,
|
|
Packit Service |
a1bd4f |
callback,
|
|
Packit Service |
a1bd4f |
user_data);
|
|
Packit Service |
a1bd4f |
return nmc;
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
NMClient *
|
|
Packit Service |
a1bd4f |
nmc_client_new_async(GCancellable * cancellable,
|
|
Packit Service |
a1bd4f |
GAsyncReadyCallback callback,
|
|
Packit Service |
a1bd4f |
gpointer user_data,
|
|
Packit Service |
a1bd4f |
const char * first_property_name,
|
|
Packit Service |
a1bd4f |
...)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
NMClient *nmc;
|
|
Packit Service |
a1bd4f |
va_list ap;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
va_start(ap, first_property_name);
|
|
Packit Service |
a1bd4f |
nmc = nmc_client_new_async_valist(cancellable, callback, user_data, first_property_name, ap);
|
|
Packit Service |
a1bd4f |
va_end(ap);
|
|
Packit Service |
a1bd4f |
return nmc;
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
/*****************************************************************************/
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
typedef struct {
|
|
Packit Service |
a1bd4f |
GMainLoop *main_loop;
|
|
Packit Service |
a1bd4f |
NMClient * nmc;
|
|
Packit Service |
a1bd4f |
GError * error;
|
|
Packit |
5756e2 |
} ClientCreateData;
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static void
|
|
Packit Service |
a1bd4f |
_nmc_client_new_waitsync_cb(GObject *source_object, GAsyncResult *result, gpointer user_data)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
ClientCreateData *data = user_data;
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
g_async_initable_init_finish(G_ASYNC_INITABLE(source_object), result, &data->error);
|
|
Packit Service |
a1bd4f |
g_main_loop_quit(data->main_loop);
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
/**
|
|
Packit |
5756e2 |
* nmc_client_new:
|
|
Packit |
5756e2 |
* @cancellable: the cancellable to abort the creation.
|
|
Packit |
5756e2 |
* @out_nmc: (out): (transfer full): if give, transfers a reference
|
|
Packit |
5756e2 |
* to the NMClient instance. Note that this never fails to create
|
|
Packit |
5756e2 |
* the NMClient GObject, but depending on the return value,
|
|
Packit |
5756e2 |
* the instance was successfully initialized or not.
|
|
Packit |
5756e2 |
* @error: the error if creation fails.
|
|
Packit |
5756e2 |
* @first_property_name: the name of the first property
|
|
Packit |
5756e2 |
* @...: the value of the first property, followed optionally by more
|
|
Packit |
5756e2 |
* name/value pairs, followed by %NULL
|
|
Packit |
5756e2 |
*
|
|
Packit |
5756e2 |
* Returns: %TRUE, if the client was successfully initalized.
|
|
Packit |
5756e2 |
*
|
|
Packit |
5756e2 |
* This uses nm_client_new_async() to create a NMClient instance,
|
|
Packit |
5756e2 |
* but it iterates the current GMainContext until the client is
|
|
Packit |
5756e2 |
* ready. As such, it waits for the client creation to complete
|
|
Packit |
5756e2 |
* (like sync nm_client_new()) but it iterates the caller's GMainContext
|
|
Packit |
5756e2 |
* (unlike sync nm_client_new()). This is often preferable, because
|
|
Packit |
5756e2 |
* sync nm_client_new() needs to create an additional internal GMainContext
|
|
Packit |
5756e2 |
* that it can iterate instead. That has a performance overhead that
|
|
Packit |
5756e2 |
* is often unnecessary.
|
|
Packit |
5756e2 |
*/
|
|
Packit |
5756e2 |
gboolean
|
|
Packit Service |
a1bd4f |
nmc_client_new_waitsync(GCancellable *cancellable,
|
|
Packit Service |
a1bd4f |
NMClient ** out_nmc,
|
|
Packit Service |
a1bd4f |
GError ** error,
|
|
Packit Service |
a1bd4f |
const char * first_property_name,
|
|
Packit Service |
a1bd4f |
...)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
gs_unref_object NMClient *nmc = NULL;
|
|
Packit Service |
a1bd4f |
nm_auto_unref_gmainloop GMainLoop *main_loop =
|
|
Packit Service |
a1bd4f |
g_main_loop_new(g_main_context_get_thread_default(), FALSE);
|
|
Packit Service |
a1bd4f |
ClientCreateData data = {
|
|
Packit Service |
a1bd4f |
.main_loop = main_loop,
|
|
Packit Service |
a1bd4f |
};
|
|
Packit Service |
a1bd4f |
va_list ap;
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
#if NM_MORE_ASSERTS > 10
|
|
Packit Service |
a1bd4f |
/* The sync initialization of NMClient is generally a bad idea, because it
|
|
Packit Service |
a1bd4f |
* brings the overhead of an additional GMainContext. Anyway, since our own
|
|
Packit Service |
a1bd4f |
* code no longer uses that, we hardly test those code paths. But they should
|
|
Packit Service |
a1bd4f |
* work just the same. Randomly use instead the sync initialization in a debug
|
|
Packit Service |
a1bd4f |
* build... */
|
|
Packit Service |
a1bd4f |
if ((g_random_int() % 2) == 0) {
|
|
Packit Service |
a1bd4f |
gboolean success;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
va_start(ap, first_property_name);
|
|
Packit Service |
a1bd4f |
nmc = NM_CLIENT(g_object_new_valist(NM_TYPE_CLIENT, first_property_name, ap));
|
|
Packit Service |
a1bd4f |
va_end(ap);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
/* iterate the context at least once, just so that the behavior from POV of the
|
|
Packit Service |
a1bd4f |
* caller is roughly the same. */
|
|
Packit Service |
a1bd4f |
g_main_context_iteration(nm_client_get_main_context(nmc), FALSE);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
success = g_initable_init(G_INITABLE(nmc), cancellable, error);
|
|
Packit Service |
a1bd4f |
NM_SET_OUT(out_nmc, g_steal_pointer(&nmc));
|
|
Packit Service |
a1bd4f |
return success;
|
|
Packit Service |
a1bd4f |
}
|
|
Packit |
5756e2 |
#endif
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
va_start(ap, first_property_name);
|
|
Packit Service |
a1bd4f |
nmc = nmc_client_new_async_valist(cancellable,
|
|
Packit Service |
a1bd4f |
_nmc_client_new_waitsync_cb,
|
|
Packit Service |
a1bd4f |
&data,
|
|
Packit Service |
a1bd4f |
first_property_name,
|
|
Packit Service |
a1bd4f |
ap);
|
|
Packit Service |
a1bd4f |
va_end(ap);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
g_main_loop_run(main_loop);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
NM_SET_OUT(out_nmc, g_steal_pointer(&nmc));
|
|
Packit Service |
a1bd4f |
if (data.error) {
|
|
Packit Service |
a1bd4f |
g_propagate_error(error, data.error);
|
|
Packit Service |
a1bd4f |
return FALSE;
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
return TRUE;
|
|
Packit |
5756e2 |
}
|