[evolution-data-server] EBookBackendClass: Add a 'use_serial_dispatch_queue' option.



commit 0def22dd549d807dac6e4faac0996f788e90ae74
Author: Matthew Barnes <mbarnes redhat com>
Date:   Tue Apr 2 12:42:34 2013 -0400

    EBookBackendClass: Add a 'use_serial_dispatch_queue' option.
    
    EBookBackend subclasses can set this to TRUE to use a serial dispatch
    queue, instead of a concurrent dispatch queue.  A serial dispatch queue
    executes one method at a time in the order in which methods were called.
    This is generally slower than a concurrent dispatch queue, but can help
    EBookBackend subclasses avoid thread-safety issues.

 addressbook/libedata-book/e-book-backend.c |   44 ++++++++++++++++++++++-----
 addressbook/libedata-book/e-book-backend.h |    7 ++++
 2 files changed, 43 insertions(+), 8 deletions(-)
---
diff --git a/addressbook/libedata-book/e-book-backend.c b/addressbook/libedata-book/e-book-backend.c
index eed1b5a..ab33708 100644
--- a/addressbook/libedata-book/e-book-backend.c
+++ b/addressbook/libedata-book/e-book-backend.c
@@ -144,6 +144,10 @@ book_backend_push_operation (EBookBackend *backend,
        if (G_IS_CANCELLABLE (cancellable))
                node->cancellable = g_object_ref (cancellable);
 
+       /* All operations block when using a serial dispatch queue. */
+       if (E_BOOK_BACKEND_GET_CLASS (backend)->use_serial_dispatch_queue)
+               node->blocking_operation = TRUE;
+
        g_queue_push_tail (&backend->priv->pending_operations, node);
 
        g_mutex_unlock (&backend->priv->operation_lock);
@@ -210,6 +214,23 @@ book_backend_dispatch_next_operation (EBookBackend *backend)
        return TRUE;
 }
 
+static void
+book_backend_unblock_operations (EBookBackend *backend,
+                                 GSimpleAsyncResult *simple)
+{
+       /* If the GSimpleAsyncResult was blocking the dispatch queue,
+        * unblock the dispatch queue.  Then dispatch as many waiting
+        * operations as we can. */
+
+       g_mutex_lock (&backend->priv->operation_lock);
+       if (backend->priv->blocked == simple)
+               g_clear_object (&backend->priv->blocked);
+       g_mutex_unlock (&backend->priv->operation_lock);
+
+       while (book_backend_dispatch_next_operation (backend))
+               ;
+}
+
 static guint32
 book_backend_stash_operation (EBookBackend *backend,
                               GSimpleAsyncResult *simple)
@@ -907,14 +928,7 @@ e_book_backend_open_finish (EBookBackend *backend,
 
        simple = G_SIMPLE_ASYNC_RESULT (result);
 
-       /* This operation blocks, so we need to let waiting operations
-        * through.  (FIXME Centralize this for any blocking operation.) */
-       g_mutex_lock (&backend->priv->operation_lock);
-       if (backend->priv->blocked == simple)
-               g_clear_object (&backend->priv->blocked);
-       g_mutex_unlock (&backend->priv->operation_lock);
-       while (book_backend_dispatch_next_operation (backend))
-               ;
+       book_backend_unblock_operations (backend, simple);
 
        /* Assume success unless a GError is set. */
        return !g_simple_async_result_propagate_error (simple, error);
@@ -1082,6 +1096,8 @@ e_book_backend_refresh_finish (EBookBackend *backend,
 
        simple = G_SIMPLE_ASYNC_RESULT (result);
 
+       book_backend_unblock_operations (backend, simple);
+
        /* Assume success unless a GError is set. */
        return !g_simple_async_result_propagate_error (simple, error);
 }
@@ -1273,6 +1289,8 @@ e_book_backend_create_contacts_finish (EBookBackend *backend,
        simple = G_SIMPLE_ASYNC_RESULT (result);
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
+       book_backend_unblock_operations (backend, simple);
+
        if (g_simple_async_result_propagate_error (simple, error))
                return FALSE;
 
@@ -1459,6 +1477,8 @@ e_book_backend_modify_contacts_finish (EBookBackend *backend,
        simple = G_SIMPLE_ASYNC_RESULT (result);
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
+       book_backend_unblock_operations (backend, simple);
+
        if (g_simple_async_result_propagate_error (simple, error))
                return FALSE;
 
@@ -1647,6 +1667,8 @@ e_book_backend_remove_contacts_finish (EBookBackend *backend,
        simple = G_SIMPLE_ASYNC_RESULT (result);
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
+       book_backend_unblock_operations (backend, simple);
+
        if (g_simple_async_result_propagate_error (simple, error))
                return FALSE;
 
@@ -1837,6 +1859,8 @@ e_book_backend_get_contact_finish (EBookBackend *backend,
        simple = G_SIMPLE_ASYNC_RESULT (result);
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
+       book_backend_unblock_operations (backend, simple);
+
        if (g_simple_async_result_propagate_error (simple, error))
                return NULL;
 
@@ -2032,6 +2056,8 @@ e_book_backend_get_contact_list_finish (EBookBackend *backend,
        simple = G_SIMPLE_ASYNC_RESULT (result);
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
+       book_backend_unblock_operations (backend, simple);
+
        if (g_simple_async_result_propagate_error (simple, error))
                return FALSE;
 
@@ -2224,6 +2250,8 @@ e_book_backend_get_contact_list_uids_finish (EBookBackend *backend,
        simple = G_SIMPLE_ASYNC_RESULT (result);
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
+       book_backend_unblock_operations (backend, simple);
+
        if (g_simple_async_result_propagate_error (simple, error))
                return FALSE;
 
diff --git a/addressbook/libedata-book/e-book-backend.h b/addressbook/libedata-book/e-book-backend.h
index bd9e3c9..8a6796a 100644
--- a/addressbook/libedata-book/e-book-backend.h
+++ b/addressbook/libedata-book/e-book-backend.h
@@ -101,6 +101,13 @@ struct _EBookBackend {
 struct _EBookBackendClass {
        EBackendClass parent_class;
 
+       /* Set this to TRUE to use a serial dispatch queue, instead
+        * of a concurrent dispatch queue.  A serial dispatch queue
+        * executes one method at a time in the order in which they
+        * were called.  This is generally slower than a concurrent
+        * dispatch queue, but helps avoid thread-safety issues. */
+       gboolean use_serial_dispatch_queue;
+
        /* Virtual methods */
        gchar *         (*get_backend_property) (EBookBackend *backend,
                                                 const gchar *prop_name);


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