- 
            
                
            
            
                
                    
                        Pl
                    
                
            
            
                
                    
                        chevron_right
                    
                
            
            
Christian Hergert: Integrating Libdex and GAsyncResult
news.movim.eu / PlanetGnome • 2 September • 2 minutes
 
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 Dex.Promise 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));
}
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 clean up legacy code.
For these cases use Dex.AsyncResult . It is designed to feel familiar to those that have used GTask .
   
    Dex.AsyncResult.new()
   
   allows taking the typical
   
    cancellable
   
   ,
   
    callback
   
   , and
   
    user_data
   
   parameters similar to
   
    GTask
   
   .
  
   Then call
   
    Dex.AsyncResult.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 propgate API such as Dex.AsyncResult.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
   
    Dex.Block
   
   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.
  
This article can be found in the documentation at Integrating GAsyncResult .