Blame src/libnm-client-aux-extern/nm-libnm-aux.c

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