Skip to content

Draft: gdbus-codegen: Support dex future proxy method calls and dex fiber skeleton method invocation

Adds support for dex in the gdbus codegen. The changes are limited to the codegen, don't add a dependency on libdex, and are only in effect when --c-generate-futures is passed.

This adds two things in particular:

  • Dbus proxys get a new variant of calling methods: ${interface}_call_${method}_future which returns a DexFuture that resolves or rejects at some point
  • Dbus skeleton interfaces get a new variant of handling method calls: if the new fiber_${method} vfunc is set, method calls get dispatched in a DexFiber instead of the signal/vfunc

To see how this can be used, and the boilerplate it replaces, see https://gitlab.gnome.org/swick/gdbus-libdex-codegen-test.

The gist of it:

static DexFuture *
do_some_dbus_stuff (G_GNUC_UNUSED gpointer user_data)
{
  g_autoptr(GDBusConnection) connection = NULL;
  g_autoptr(DbusSystemd1Manager) manager = NULL;
  g_autoptr(DbusSystemd1ManagerGetDefaultTargetResult) default_target = NULL;
  g_autoptr(GError) error = NULL;

  connection = dex_await_object (dex_bus_get (G_BUS_TYPE_SESSION), &error);
  if (!connection)
    return dex_future_new_for_error (g_steal_pointer (&error));

  manager = dex_await_object (dbus_systemd1_manager_proxy_new_future (connection,
                                                                     G_DBUS_PROXY_FLAGS_NONE,
                                                                     "org.example.test",
                                                                     "/org/example/test"),
                              &error);
  if (!manager)
    return dex_future_new_for_error (g_steal_pointer (&error));

  default_target = dex_await_boxed (dbus_systemd1_manager_call_get_default_target_future (manager),
                                    &error);
  if (!default_target)
    return dex_future_new_for_error (g_steal_pointer (&error));

  return dex_future_new_for_string (default_target->name);
}
struct _Systemd1Manager
{
  DbusSystemd1ManagerSkeleton parent_instance;
};

struct Systemd1ManagerClass
{
  DbusSystemd1ManagerSkeletonClass parent_class;
};

static void dbus_systemd1_manager_iface_init (DbusSystemd1ManagerIface *iface);

#define SYSTEMD1_TYPE_MANAGER (systemd1_manager_get_type ())
G_DECLARE_FINAL_TYPE (Systemd1Manager,
                      systemd1_manager,
                      Systemd1, MANAGER,
                      DbusSystemd1ManagerSkeleton)

G_DEFINE_TYPE_WITH_CODE (Systemd1Manager,
                         systemd1_manager,
                         DBUS_SYSTEMD1_TYPE_MANAGER_SKELETON,
                         G_IMPLEMENT_INTERFACE (DBUS_SYSTEMD1_TYPE_MANAGER,
                                                dbus_systemd1_manager_iface_init));

static GMainLoop *main_loop;

static gboolean
handle_get_default_target (DbusSystemd1Manager   *object,
                           GDBusMethodInvocation *invocation)
{
  dex_await (dex_timeout_new_seconds (1), NULL);
  dbus_systemd1_manager_complete_get_default_target (object,
                                                     invocation,
                                                     "test.target");
  return G_DBUS_METHOD_INVOCATION_HANDLED;
}

static void
dbus_systemd1_manager_iface_init (DbusSystemd1ManagerIface *iface)
{
  iface->method_invocations_in_fiber = TRUE;
  iface->handle_get_default_target = handle_get_default_target;
}

static void
systemd1_manager_init (Systemd1Manager *manager)
{
}

static void
systemd1_manager_class_init (Systemd1ManagerClass *klass)
{
}

ToDo before un-drafting:

  • fix the failing codegen test
  • run some test with --c-generate-futures to ensure no regressions
  • add some tests with libdex

Enhancements:

  • cancel fibers on dispose
Edited by Sebastian Wick

Merge request reports

Loading