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



commit 8a56d5e838982824015d9e08b2f9863fc5b2b6b9
Author: Matthew Barnes <mbarnes redhat com>
Date:   Tue Apr 2 14:25:48 2013 -0400

    ECalBackendClass: Add a 'use_serial_dispatch_queue' option.
    
    ECalBackend 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
    ECalBackend subclasses avoid thread-safety issues.

 calendar/libedata-cal/e-cal-backend.c |   56 ++++++++++++++++++++++++++++-----
 calendar/libedata-cal/e-cal-backend.h |    7 ++++
 2 files changed, 55 insertions(+), 8 deletions(-)
---
diff --git a/calendar/libedata-cal/e-cal-backend.c b/calendar/libedata-cal/e-cal-backend.c
index 5087a53..fa56745 100644
--- a/calendar/libedata-cal/e-cal-backend.c
+++ b/calendar/libedata-cal/e-cal-backend.c
@@ -202,6 +202,10 @@ cal_backend_push_operation (ECalBackend *backend,
        if (G_IS_CANCELLABLE (cancellable))
                node->cancellable = g_object_ref (cancellable);
 
+       /* All operations block when using a serial dispatch queue. */
+       if (E_CAL_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);
@@ -268,6 +272,23 @@ cal_backend_dispatch_next_operation (ECalBackend *backend)
        return TRUE;
 }
 
+static void
+cal_backend_unblock_operations (ECalBackend *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 (cal_backend_dispatch_next_operation (backend))
+               ;
+}
+
 static guint32
 cal_backend_stash_operation (ECalBackend *backend,
                              GSimpleAsyncResult *simple)
@@ -1405,14 +1426,7 @@ e_cal_backend_open_finish (ECalBackend *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 (cal_backend_dispatch_next_operation (backend))
-               ;
+       cal_backend_unblock_operations (backend, simple);
 
        /* Assume success unless a GError is set. */
        return !g_simple_async_result_propagate_error (simple, error);
@@ -1580,6 +1594,8 @@ e_cal_backend_refresh_finish (ECalBackend *backend,
 
        simple = G_SIMPLE_ASYNC_RESULT (result);
 
+       cal_backend_unblock_operations (backend, simple);
+
        /* Assume success unless a GError is set. */
        return !g_simple_async_result_propagate_error (simple, error);
 }
@@ -1763,6 +1779,8 @@ e_cal_backend_get_object_finish (ECalBackend *backend,
        simple = G_SIMPLE_ASYNC_RESULT (result);
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
+       cal_backend_unblock_operations (backend, simple);
+
        if (g_simple_async_result_propagate_error (simple, error))
                return FALSE;
 
@@ -1956,6 +1974,8 @@ e_cal_backend_get_object_list_finish (ECalBackend *backend,
        simple = G_SIMPLE_ASYNC_RESULT (result);
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
+       cal_backend_unblock_operations (backend, simple);
+
        if (g_simple_async_result_propagate_error (simple, error))
                return FALSE;
 
@@ -2154,6 +2174,8 @@ e_cal_backend_get_free_busy_finish (ECalBackend *backend,
 
        simple = G_SIMPLE_ASYNC_RESULT (result);
 
+       cal_backend_unblock_operations (backend, simple);
+
        /* Assume success unless a GError is set. */
        return !g_simple_async_result_propagate_error (simple, error);
 }
@@ -2349,6 +2371,8 @@ e_cal_backend_create_objects_finish (ECalBackend *backend,
        simple = G_SIMPLE_ASYNC_RESULT (result);
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
+       cal_backend_unblock_operations (backend, simple);
+
        if (g_simple_async_result_propagate_error (simple, error))
                return FALSE;
 
@@ -2568,6 +2592,8 @@ e_cal_backend_modify_objects_finish (ECalBackend *backend,
        simple = G_SIMPLE_ASYNC_RESULT (result);
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
+       cal_backend_unblock_operations (backend, simple);
+
        if (g_simple_async_result_propagate_error (simple, error))
                return FALSE;
 
@@ -2794,6 +2820,8 @@ e_cal_backend_remove_objects_finish (ECalBackend *backend,
        simple = G_SIMPLE_ASYNC_RESULT (result);
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
+       cal_backend_unblock_operations (backend, simple);
+
        if (g_simple_async_result_propagate_error (simple, error))
                return FALSE;
 
@@ -3014,6 +3042,8 @@ e_cal_backend_receive_objects_finish (ECalBackend *backend,
 
        simple = G_SIMPLE_ASYNC_RESULT (result);
 
+       cal_backend_unblock_operations (backend, simple);
+
        /* Assume success unless a GError is set. */
        return !g_simple_async_result_propagate_error (simple, error);
 }
@@ -3202,6 +3232,8 @@ e_cal_backend_send_objects_finish (ECalBackend *backend,
        simple = G_SIMPLE_ASYNC_RESULT (result);
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
+       cal_backend_unblock_operations (backend, simple);
+
        if (g_simple_async_result_propagate_error (simple, error))
                return NULL;
 
@@ -3401,6 +3433,8 @@ e_cal_backend_get_attachment_uris_finish (ECalBackend *backend,
        simple = G_SIMPLE_ASYNC_RESULT (result);
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
+       cal_backend_unblock_operations (backend, simple);
+
        if (g_simple_async_result_propagate_error (simple, error))
                return FALSE;
 
@@ -3598,6 +3632,8 @@ e_cal_backend_discard_alarm_finish (ECalBackend *backend,
 
        simple = G_SIMPLE_ASYNC_RESULT (result);
 
+       cal_backend_unblock_operations (backend, simple);
+
        /* Assume success unless a GError is set. */
        return !g_simple_async_result_propagate_error (simple, error);
 }
@@ -3772,6 +3808,8 @@ e_cal_backend_get_timezone_finish (ECalBackend *backend,
        simple = G_SIMPLE_ASYNC_RESULT (result);
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
+       cal_backend_unblock_operations (backend, simple);
+
        if (g_simple_async_result_propagate_error (simple, error))
                return FALSE;
 
@@ -3947,6 +3985,8 @@ e_cal_backend_add_timezone_finish (ECalBackend *backend,
 
        simple = G_SIMPLE_ASYNC_RESULT (result);
 
+       cal_backend_unblock_operations (backend, simple);
+
        /* Assume success unless a GError is set. */
        return !g_simple_async_result_propagate_error (simple, error);
 }
diff --git a/calendar/libedata-cal/e-cal-backend.h b/calendar/libedata-cal/e-cal-backend.h
index 304d27f..5e8dc2f 100644
--- a/calendar/libedata-cal/e-cal-backend.h
+++ b/calendar/libedata-cal/e-cal-backend.h
@@ -110,6 +110,13 @@ struct _ECalBackend {
 struct _ECalBackendClass {
        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) (ECalBackend *backend,
                                                 const gchar *prop_name);


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