Asynchronous method/callback example?

I am attempting to use the libnm library to deactivate a connection asynchronously using the
nm_client_deactivate_connection_async method () in the NMClient class. It works fine using the deprecated nm_client_deactivate_connection () method, but when I try to use the asynchronous one, I am not seeing it working.

I’m wondering if I am passing some bad parameters or something? Even though I’m not getting any compiler errors, I’m not sure if I’m doing something wrong. I’m still quite fresh in GObject and C programming in general.

How should a proper GAsyncReadyCallback function look? How is this function properly passed to the nm_client_deactivate_connection_async () method? Can someone help me with a code example? Thanks.

Edit: I thought I’d include some of my current (non-working code):

static void
callback ()
{
  // This never gets called
  printf ("Hello from callback\n");
}

void
myobject_deactivate_connection (MyObject            *self,
                                NMActiveConnection  *connection)
{
  NMClient *client = nm_client_new (NULL, NULL);

  // This doesn't appear to do anything with the connection
  nm_client_deactivate_connection_async (client,
                                         connection,
                                         NULL,
                                         (GAsyncReadyCallback) callback,
                                         NULL);
}

The signature for GAsyncReadyCallback is declared in the documentation:

void
(*GAsyncReadyCallback) (GObject *source_object,
                        GAsyncResult *res,
                        gpointer user_data);

Typically, when casting the callback function, you would use the proper type of the source object:

static void
callback (NMClient     *client,
          GAsyncResult *res,
          MyObject     *self)
{
  GError *error = NULL;

  // Finish the operation
  if (!nm_client_deactivate_connection_finish (client, res, &error))
    g_warning ("Deactivating connection: %s", error->message);
  else
    g_debug ("Deactivated connection successfully");

  g_error_free (error);
}

void
myobject_deactivate_connection (MyObject            *self,
                                NMActiveConnection  *connection)
{
  NMClient *client = nm_client_new (NULL, NULL);

  // Start the operation
  nm_client_deactivate_connection_async (client,
                                         connection,
                                         NULL,
                                         (GAsyncReadyCallback) callback,
                                         self);
}

You seem to be leaking a reference to your NMClient here though.

1 Like

Thanks, Andy. I did see the GAsyncReadyCallback signature in the doc, but most importantly didn’t realize that it should be appropriate to use the inherited object and passed the self class as the pointer. Also good to see how the nm_client_deactivate_connection_finish () ties in.

I’ll make sure to take care of the NMClient leak too. Still getting used to not having garbage collection. :wink:

You’ve really cleared this up for me. Thanks again.

If you’re used to garbage collection and like those patterns, you can look into the autocleanups in GLib like g_autoptr():

static void
callback (NMClient     *client,
          GAsyncResult *res,
          MyObject     *self)
{
  g_autoptr (GError) error = NULL;

  if (!nm_client_deactivate_connection_finish (client, res, &error))
    g_warning ("Deactivating connection: %s", error->message);
}

void
myobject_deactivate_connection (MyObject            *self,
                                NMActiveConnection  *connection)
{
  // When myobject_deactivate() returns g_object_unref() will be
  // automatically called on `client`. Notice the omitted `*` here.
  g_autoptr (NMClient) client = NULL;

  client = nm_client_new (NULL, NULL);

  // When this function is called, it creates a GTask object that
  // holds a reference on `client` until the callback returns
  nm_client_deactivate_connection_async (client,
                                         connection,
                                         NULL,
                                         (GAsyncReadyCallback) callback,
                                         self);
}
1 Like

Thanks, I didn’t know about that. Looks handy. I’ll probably to try to get a better feel for manual memory management before I use any helper stuff like that though.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.