From 28a4fff7ec63000238c7e20ff965238027922c47 Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Fri, 13 Aug 2010 23:34:44 -0400 Subject: [PATCH] Add examples for GAsyncInitiable and GSimpleAsyncResult Bug 602417 --- gio/gasyncinitable.c | 94 +++++++++++++++++++++++++++++++++++ gio/gsimpleasyncresult.c | 104 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 197 insertions(+), 1 deletion(-) diff --git a/gio/gasyncinitable.c b/gio/gasyncinitable.c index aa13fe578..2e8a16a2c 100644 --- a/gio/gasyncinitable.c +++ b/gio/gasyncinitable.c @@ -45,6 +45,100 @@ * directly, or indirectly via a foo_thing_new_async() wrapper. This will call * g_async_initable_init_async() under the cover, calling back with %NULL and * a set %GError on failure. + * + * A typical implementation might look something like this: + * + * |[ + * enum { + * NOT_INITIALIZED, + * INITIALIZING, + * INITIALIZED + * }; + * + * static void + * _foo_ready_cb (Foo *self) + * { + * GList *l; + * + * self->priv->state = INITIALIZED; + * + * for (l = self->priv->init_results; l != NULL; l = l->next) + * { + * GSimpleAsyncResult *simple = l->data; + * + * if (!self->priv->success) + * g_simple_async_result_set_error (simple, ...); + * + * g_simple_async_result_complete (simple); + * g_object_unref (simple); + * } + * + * g_list_free (self->priv->init_results); + * self->priv->init_results = NULL; + * } + * + * static void + * foo_init_async (GAsyncInitable *initable, + * int io_priority, + * GCancellable *cancellable, + * GAsyncReadyCallback callback, + * gpointer user_data) + * { + * Foo *self = FOO (initable); + * GSimpleAsyncResult *simple; + * + * simple = g_simple_async_result_new (G_OBJECT (initable) + * callback, + * user_data, + * foo_init_async); + * + * switch (self->priv->state) + * { + * case NOT_INITIALIZED: + * _foo_get_ready (self); + * self->priv->init_results = g_list_append (self->priv->init_results, + * simple); + * self->priv->state = INITIALIZING; + * break; + * case INITIALIZING: + * self->priv->init_results = g_list_append (self->priv->init_results, + * simple); + * break; + * case INITIALIZED: + * if (!self->priv->success) + * g_simple_async_result_set_error (simple, ...); + * + * g_simple_async_result_complete_in_idle (simple); + * g_object_unref (simple); + * break; + * } + * } + * + * static gboolean + * foo_init_finish (GAsyncInitable *initable, + * GAsyncResult *result, + * GError **error) + * { + * g_return_val_if_fail (g_simple_async_result_is_valid (result, + * G_OBJECT (initable), foo_init_async), FALSE); + * + * if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), + * error)) + * return FALSE; + * + * return TRUE; + * } + * + * static void + * foo_async_initable_iface_init (gpointer g_iface, + * gpointer data) + * { + * GAsyncInitableIface *iface = g_iface; + * + * iface->init_async = foo_init_async; + * iface->init_finish = foo_init_finish; + * } + * ]| */ static void g_async_initable_real_init_async (GAsyncInitable *initable, diff --git a/gio/gsimpleasyncresult.c b/gio/gsimpleasyncresult.c index eb4711853..b76a54e7d 100644 --- a/gio/gsimpleasyncresult.c +++ b/gio/gsimpleasyncresult.c @@ -109,7 +109,109 @@ * g_simple_async_result_get_op_res_gssize() are * provided, getting the operation's result as a gpointer, gboolean, and * gssize, respectively. - **/ + * + * For the details of the requirements implementations must respect, see + * #GAsyncResult. A typical implementation of an asynchronous operation + * using GSimpleAsyncResult looks something like this: + * + * |[ + * static void + * baked_cb (Cake *cake, + * gpointer user_data) + * { + * /* In this example, this callback is not given a reference to the cake, so + * * the GSimpleAsyncResult has to take a reference to it. + * */ + * GSimpleAsyncResult *result = user_data; + * + * if (cake == NULL) + * g_simple_async_result_set_error (result, + * BAKER_ERRORS, + * BAKER_ERROR_NO_FLOUR, + * "Go to the supermarket"); + * else + * g_simple_async_result_set_op_res_gpointer (result, + * g_object_ref (cake), + * g_object_unref); + * + * + * /* In this example, we assume that baked_cb is called as a callback from + * * the mainloop, so it's safe to complete the operation synchronously here. + * * If, however, _baker_prepare_cake () might call its callback without + * * first returning to the mainloop — inadvisable, but some APIs do so — + * * we would need to use g_simple_async_result_complete_in_idle(). + * */ + * g_simple_async_result_complete (result); + * g_object_unref (result); + * } + * + * void + * baker_bake_cake_async (Baker *self, + * guint radius, + * GAsyncReadyCallback callback, + * gpointer user_data) + * { + * GSimpleAsyncResult *simple; + * Cake *cake; + * + * if (radius < 3) + * { + * g_simple_async_report_error_in_idle (G_OBJECT (self), + * callback, + * user_data, + * BAKER_ERRORS, + * BAKER_ERROR_TOO_SMALL, + * "%ucm radius cakes are silly", + * radius); + * return; + * } + * + * simple = g_simple_async_result_new (G_OBJECT (self), + * callback, + * user_data, + * baker_bake_cake_async); + * cake = _baker_get_cached_cake (self, radius); + * + * if (cake != NULL) + * { + * g_simple_async_result_set_op_res_gpointer (simple, + * g_object_ref (cake), + * g_object_unref); + * g_simple_async_result_complete_in_idle (simple); + * g_object_unref (simple); + * /* Drop the reference returned by _baker_get_cached_cake(); the + * * GSimpleAsyncResult has taken its own reference. + * */ + * g_object_unref (cake); + * return; + * } + * + * _baker_prepare_cake (self, radius, baked_cb, user_data); + * } + * + * Cake * + * baker_bake_cake_finish (Baker *self, + * GAsyncResult *result, + * GError **error) + * { + * GSimpleAsyncResult *simple; + * Cake *cake; + * + * g_return_val_if_fail (g_simple_async_result_is_valid (result, + * G_OBJECT (self), + * baker_bake_cake_async), + * NULL); + * + * simple = (GSimpleAsyncResult *) result; + * + * if (g_simple_async_result_propagate_error (simple, error)) + * return NULL; + * + * cake = CAKE (g_simple_async_result_get_op_res_gpointer (simple)); + * return g_object_ref (cake); + * } + * ]| + */ static void g_simple_async_result_async_result_iface_init (GAsyncResultIface *iface);