static void
add_connection_cb(NMClient *client,
GAsyncResult *result,
gpointer user_data)
{
/* This callback will be invoked in the same thread as
* nm_client_add_and_activate_connection_async(), once
* the task completes.
*/
}
/* Calling this function gathers the arguments into a
* task object and passes it to a task thread. When
* the task completes, the callback you passed is
* invoked in _this_ thread's main context.
*/
nm_client_add_and_activate_connection_async(client,
connection,
device,
NULL,
NULL,
(GAsyncReadyCallback) add_connection_cb,
&uuid)
The GLib main context runs a function and when it completes, control is returned to the main context, which then runs the next function. This allows for a sort of cooperateive-scheduling, either by delegating blocking work to another thread, or by deferring with an event source as created by e.g. g_timeout_add()
or g_idle_add()
.
Asynchronous functions work in GIO by gathering task data (i.e. the function arguments) into a GTask
object, including a reference to the current GMainContext
and the callback you provided. When the task completes, it schedules the callback (i.e add_connection_cb()
) to be invoked in the original main context using some event source.
Using a GMainLoop
to iterate the main context until the task completes, is in fact a common way to make asynchronous-only methods into synchronous ones. Without seeing more of your code, what you probably want to do is pass your self
object (maybe that’s a GtkWidget
) as the user_data
argument. Then your callback will look something like:
static void
add_connection_cb(NMClient *client,
GAsyncResult *result,
GtkWidget *self)
{
g_autoptr (NMActiveConnection) conn = NULL;
g_autoptr (GError) error = NULL;
conn = nm_client_add_and_activate_connection_finish (client,
result,
&error);
if (error != NULL)
{
g_warning ("%s(): %s", G_STRFUNC, error->message);
return;
}
/* The operation succeeded, so do something with the object
* and add some notification to the GUI.
*/
g_set_object (&self->conn, conn);
gtk_label_set_label (self->status_label, "Succeeded!");
}