Dex – 1: Integrating GAsyncResult
Description: Reference for Dex-1: Integrating GAsyncResult

#### Integrating GAsyncResult

Historically if you wanted to do asynchronous work in GObject-based applications you would use `GAsyncReadyCallback` and `GAsyncResult`.

There are two ways to integrate with this form of asynchronous API. In one direction, you can consume this historical API and provide the result as a `DexFuture`. In the other direction, you can provide this API in your application or library but implement it behind the scenes with `DexFuture`.

# Converting GAsyncResult to Futures

A typical case to integrate, at least initially, is to extract the result of a `GAsyncResult` and propagate it to a future.

One way to do that is with a `DexPromise` which will resolve or reject from your async callback.

    static void
    my_callback (GObject      *object,
                 GAsyncResult *result,
                 gpointer      user_data)
    {
      g_autoptr(DexPromise) promise = user_data;
      g_autoptr(GError) error = NULL;

      if (thing_finish (THING (object), result, &error))
        dex_promise_resolve_boolean (promise, TRUE);
      else
        dex_promise_reject (promise, g_steal_pointer (&error));
    }

    static DexFuture *
    my_wrapper (Thing *thing)
    {
      DexPromise *promise = dex_promise_new_cancellable ();

      thing_async (thing,
                   dex_promise_get_cancellable (promise),
                   my_callback,
                   dex_ref (promise));

      return DEX_FUTURE (promise);
    }

# Implementing AsyncResult with Futures

In some cases you may not want to “leak” into your API that you are using `DexFuture`. For example, you may want to only expose a traditional GIO API or maybe even rewriting legacy code.

For these cases use `DexAsyncResult`. It is designed to feel familiar to those that have used `GTask`.

`dex_async_result_new()` allows taking the typical `cancellable`, `callback`, and `user_data` parameters similar to `GTask`.

Then call `dex_async_result_await()` providing the future that will resolve or reject with error. One completed, the users provided `callback` will be executed within the active scheduler at time of creation.

From your finish function, call the appropriate propagate API such as `dex_async_result_propagate_int()`.

    void
    thing_async (Thing               *thing,
                 GCancellable        *cancellable,
                 GAsyncReadyCallback  callback,
                 gpointer             user_data)
    {
      g_autoptr(DexAsyncResult) result = NULL;

      result = dex_async_result_new (thing, cancellable, callback, user_data);
      dex_async_result_await (result, dex_future_new_true ());
    }

    gboolean
    thing_finish (Thing         *thing,
                  GAsyncResult  *result,
                  GError       **error)
    {
      return dex_async_result_propagate_boolean (DEX_ASYNC_RESULT (result), error);
    }

# Safety Notes

One thing that Libdex handles better than `GTask` is ensuring that your `user_data` is destroyed on the proper thread. The design of `DexBlock` was done in such a way that both the result and `user_data` are passed back to the owning thread at the same time. This ensures that your `user_data` will never be finalized on the wrong thread.