Blame libnm/nm-libnm-aux/nm-libnm-aux.c

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
}