[evolution-data-server] Add EAsyncClosure.



commit c14aa79d7616075ce8a16f297be20118deb19746
Author: Matthew Barnes <mbarnes redhat com>
Date:   Tue May 8 10:46:33 2012 -0400

    Add EAsyncClosure.
    
    EAsyncClosure provides a simple way to run an asynchronous function
    synchronously without blocking a running GMainLoop or using threads.
    
    Merging this API from the account-mgmt branch as it has proven stable
    and quite convenient.  I've seen this pattern in use throughout GIO,
    but to my knowledge it has never been formalized like this.

 .../libedataserver/libedataserver-sections.txt     |    5 +
 libedataserver/e-data-server-util.c                |  136 ++++++++++++++++++++
 libedataserver/e-data-server-util.h                |    9 ++
 3 files changed, 150 insertions(+), 0 deletions(-)
---
diff --git a/docs/reference/libedataserver/libedataserver-sections.txt b/docs/reference/libedataserver/libedataserver-sections.txt
index 92d07ac..9936e20 100644
--- a/docs/reference/libedataserver/libedataserver-sections.txt
+++ b/docs/reference/libedataserver/libedataserver-sections.txt
@@ -559,6 +559,11 @@ e_file_recursive_delete
 e_file_recursive_delete_finish
 e_binding_transform_enum_value_to_nick
 e_binding_transform_enum_nick_to_value
+EAsyncClosure
+e_async_closure_new
+e_async_closure_wait
+e_async_closure_free
+e_async_closure_callback
 e_util_get_prefix
 e_util_get_cp_prefix
 e_util_get_localedir
diff --git a/libedataserver/e-data-server-util.c b/libedataserver/e-data-server-util.c
index 91f196c..219637c 100644
--- a/libedataserver/e-data-server-util.c
+++ b/libedataserver/e-data-server-util.c
@@ -1219,6 +1219,142 @@ e_binding_transform_enum_nick_to_value (GBinding *binding,
 	return success;
 }
 
+/**
+ * EAsyncClosure:
+ *
+ * #EAsyncClosure provides a simple way to run an asynchronous function
+ * synchronously without blocking a running #GMainLoop or using threads.
+ *
+ * 1) Create an #EAsyncClosure with e_async_closure_new().
+ *
+ * 2) Call the asynchronous function passing e_async_closure_callback() as
+ *    the #GAsyncReadyCallback argument and the #EAsyncClosure as the data
+ *    argument.
+ *
+ * 3) Call e_async_closure_wait() and collect the #GAsyncResult.
+ *
+ * 4) Call the corresponding asynchronous "finish" function, passing the
+ *    #GAsyncResult returned by e_async_closure_wait().
+ *
+ * 5) If needed, repeat steps 2-4 for additional asynchronous functions
+ *    using the same #EAsyncClosure.
+ *
+ * 6) Finally, free the #EAsyncClosure with e_async_closure_free().
+ *
+ * Since: 3.6
+ **/
+struct _EAsyncClosure {
+	GMainLoop *loop;
+	GMainContext *context;
+	GAsyncResult *result;
+};
+
+/**
+ * e_async_closure_new:
+ *
+ * Creates a new #EAsyncClosure for use with asynchronous functions.
+ *
+ * Returns: a new #EAsyncClosure
+ *
+ * Since: 3.6
+ **/
+EAsyncClosure *
+e_async_closure_new (void)
+{
+	EAsyncClosure *closure;
+
+	closure = g_slice_new0 (EAsyncClosure);
+	closure->context = g_main_context_new ();
+	closure->loop = g_main_loop_new (closure->context, FALSE);
+
+	g_main_context_push_thread_default (closure->context);
+
+	return closure;
+}
+
+/**
+ * e_async_closure_wait:
+ * @closure: an #EAsyncClosure
+ *
+ * Call this function immediately after starting an asynchronous operation.
+ * The function waits for the asynchronous operation to complete and returns
+ * its #GAsyncResult to be passed to the operation's "finish" function.
+ *
+ * This function can be called repeatedly on the same #EAsyncClosure to
+ * easily string together multiple asynchronous operations.
+ *
+ * Returns: a #GAsyncResult
+ *
+ * Since: 3.6
+ **/
+GAsyncResult *
+e_async_closure_wait (EAsyncClosure *closure)
+{
+	g_return_val_if_fail (closure != NULL, NULL);
+
+	g_main_loop_run (closure->loop);
+
+	return closure->result;
+}
+
+/**
+ * e_async_closure_free:
+ * @closure: an #EAsyncClosure
+ *
+ * Frees the @closure and the resources it holds.
+ *
+ * Since: 3.6
+ **/
+void
+e_async_closure_free (EAsyncClosure *closure)
+{
+	g_return_if_fail (closure != NULL);
+
+	g_main_context_pop_thread_default (closure->context);
+
+	g_main_loop_unref (closure->loop);
+	g_main_context_unref (closure->context);
+
+	if (closure->result != NULL)
+		g_object_unref (closure->result);
+
+	g_slice_free (EAsyncClosure, closure);
+}
+
+/**
+ * e_async_closure_callback:
+ * @object: a #GObject
+ * @result: a #GAsyncResult
+ * @closure: an #EAsyncClosure
+ *
+ * Pass this function as the #GAsyncReadyCallback argument of an asynchronous
+ * function, and the #EAsyncClosure as the data argument.
+ *
+ * This causes e_async_closure_wait() to terminate and return @result.
+ *
+ * Since: 3.6
+ **/
+void
+e_async_closure_callback (GObject *object,
+                          GAsyncResult *result,
+                          gpointer closure)
+{
+	EAsyncClosure *real_closure;
+
+	g_return_if_fail (G_IS_OBJECT (object));
+	g_return_if_fail (G_IS_ASYNC_RESULT (result));
+	g_return_if_fail (closure != NULL);
+
+	real_closure = closure;
+
+	/* Replace any previous result. */
+	if (real_closure->result != NULL)
+		g_object_unref (real_closure->result);
+	real_closure->result = g_object_ref (result);
+
+	g_main_loop_quit (real_closure->loop);
+}
+
 #ifdef G_OS_WIN32
 
 #include <windows.h>
diff --git a/libedataserver/e-data-server-util.h b/libedataserver/e-data-server-util.h
index a137c6c..4deb2c9 100644
--- a/libedataserver/e-data-server-util.h
+++ b/libedataserver/e-data-server-util.h
@@ -95,6 +95,15 @@ gboolean	e_binding_transform_enum_nick_to_value
 						 GValue *target_value,
 						 gpointer not_used);
 
+typedef struct _EAsyncClosure EAsyncClosure;
+
+EAsyncClosure *	e_async_closure_new		(void);
+GAsyncResult *	e_async_closure_wait		(EAsyncClosure *closure);
+void		e_async_closure_free		(EAsyncClosure *closure);
+void		e_async_closure_callback	(GObject *object,
+						 GAsyncResult *result,
+						 gpointer closure);
+
 #ifdef G_OS_WIN32
 const gchar *	e_util_get_prefix		(void) G_GNUC_CONST;
 const gchar *	e_util_get_cp_prefix		(void) G_GNUC_CONST;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]