[evolution-data-server] CamelStore: Stop using the internal 'folder_lock'.



commit 4d7bc9968273305a375cdb3a4672da0905470b39
Author: Matthew Barnes <mbarnes redhat com>
Date:   Sun Dec 1 10:41:45 2013 -0500

    CamelStore: Stop using the internal 'folder_lock'.
    
    Use camel_service_queue_task() instead of locking an internal mutex.
    This ensures methods are run in the order they were called, and also
    makes cancellation of a waiting method immediate instead of blocking
    until it acquires the mutex it's competing for.
    
    This requires flip-flopping some synchronous and asynchronous functions,
    so that the synchronous function calls its asynchronous counterpart with
    help from CamelAsyncClosure.
    
    Removed functions:
    
      camel_store_lock()
      camel_store_unlock()

 camel/camel-store.c                     |  441 ++++++++++++++++---------------
 camel/camel-store.h                     |    2 -
 camel/camel-subscribable.c              |  160 +++++++-----
 docs/reference/camel/camel-sections.txt |    2 -
 4 files changed, 315 insertions(+), 290 deletions(-)
---
diff --git a/camel/camel-store.c b/camel/camel-store.c
index b74d0c7..3151c6a 100644
--- a/camel/camel-store.c
+++ b/camel/camel-store.c
@@ -34,6 +34,7 @@
 
 #include <glib/gi18n-lib.h>
 
+#include "camel-async-closure.h"
 #include "camel-db.h"
 #include "camel-debug.h"
 #include "camel-folder.h"
@@ -56,8 +57,6 @@ typedef struct _AsyncContext AsyncContext;
 typedef struct _SignalClosure SignalClosure;
 
 struct _CamelStorePrivate {
-       GRecMutex folder_lock;  /* for locking folder operations */
-
        GMutex signal_emission_lock;
        gboolean folder_info_stale_scheduled;
 };
@@ -340,8 +339,6 @@ store_finalize (GObject *object)
        if (store->folders != NULL)
                camel_object_bag_destroy (store->folders);
 
-       g_rec_mutex_clear (&store->priv->folder_lock);
-
        if (store->cdb_r != NULL) {
                camel_db_close (store->cdb_r);
                store->cdb_r = NULL;
@@ -668,8 +665,6 @@ camel_store_init (CamelStore *store)
                CAMEL_STORE_CAN_EDIT_FOLDERS;
 
        store->mode = CAMEL_STORE_READ | CAMEL_STORE_WRITE;
-
-       g_rec_mutex_init (&store->priv->folder_lock);
 }
 
 G_DEFINE_QUARK (camel-store-error-quark, camel_store_error)
@@ -1176,38 +1171,6 @@ camel_store_can_refresh_folder (CamelStore *store,
 }
 
 /**
- * camel_store_lock:
- * @store: a #CamelStore
- *
- * Locks @store. Unlock it with camel_store_unlock().
- *
- * Since: 2.32
- **/
-void
-camel_store_lock (CamelStore *store)
-{
-       g_return_if_fail (CAMEL_IS_STORE (store));
-
-       g_rec_mutex_lock (&store->priv->folder_lock);
-}
-
-/**
- * camel_store_unlock:
- * @store: a #CamelStore
- *
- * Unlocks @store, previously locked with camel_store_lock().
- *
- * Since: 2.32
- **/
-void
-camel_store_unlock (CamelStore *store)
-{
-       g_return_if_fail (CAMEL_IS_STORE (store));
-
-       g_rec_mutex_unlock (&store->priv->folder_lock);
-}
-
-/**
  * camel_store_get_folder_sync:
  * @store: a #CamelStore
  * @folder_name: name of the folder to get
@@ -2147,46 +2110,27 @@ camel_store_create_folder_sync (CamelStore *store,
                                 GCancellable *cancellable,
                                 GError **error)
 {
-       CamelStoreClass *class;
-       CamelFolderInfo *fi;
+       CamelAsyncClosure *closure;
+       GAsyncResult *result;
+       CamelFolderInfo *folder_info;
 
        g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
        g_return_val_if_fail (folder_name != NULL, NULL);
 
-       class = CAMEL_STORE_GET_CLASS (store);
-       g_return_val_if_fail (class->create_folder_sync != NULL, NULL);
+       closure = camel_async_closure_new ();
 
-       if ((parent_name == NULL || parent_name[0] == 0)
-           && (((store->flags & CAMEL_STORE_VTRASH) && strcmp (folder_name, CAMEL_VTRASH_NAME) == 0)
-               || ((store->flags & CAMEL_STORE_VJUNK) && strcmp (folder_name, CAMEL_VJUNK_NAME) == 0))) {
-               g_set_error (
-                       error, CAMEL_STORE_ERROR,
-                       CAMEL_STORE_ERROR_INVALID,
-                       _("Cannot create folder: %s: folder exists"),
-                       folder_name);
-               return NULL;
-       }
+       camel_store_create_folder (
+               store, parent_name, folder_name,
+               G_PRIORITY_DEFAULT, cancellable,
+               camel_async_closure_callback, closure);
 
-       camel_store_lock (store);
+       result = camel_async_closure_wait (closure);
 
-       /* Check for cancellation after locking. */
-       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
-               camel_store_unlock (store);
-               return NULL;
-       }
-
-       camel_operation_push_message (
-               cancellable, _("Creating folder '%s'"), folder_name);
-
-       fi = class->create_folder_sync (
-               store, parent_name, folder_name, cancellable, error);
-       CAMEL_CHECK_GERROR (store, create_folder_sync, fi != NULL, error);
+       folder_info = camel_store_create_folder_finish (store, result, error);
 
-       camel_operation_pop_message (cancellable);
+       camel_async_closure_free (closure);
 
-       camel_store_unlock (store);
-
-       return fi;
+       return folder_info;
 }
 
 /* Helper for camel_store_create_folder() */
@@ -2196,17 +2140,51 @@ store_create_folder_thread (GTask *task,
                             gpointer task_data,
                             GCancellable *cancellable)
 {
-       CamelFolderInfo *folder_info;
+       CamelStore *store;
+       CamelStoreClass *class;
        AsyncContext *async_context;
+       CamelFolderInfo *folder_info;
+       const gchar *parent_name;
+       const gchar *folder_name;
        GError *local_error = NULL;
 
+       store = CAMEL_STORE (source_object);
        async_context = (AsyncContext *) task_data;
 
-       folder_info = camel_store_create_folder_sync (
-               CAMEL_STORE (source_object),
-               async_context->folder_name_1,
-               async_context->folder_name_2,
-               cancellable, &local_error);
+       parent_name = async_context->folder_name_1;
+       folder_name = async_context->folder_name_2;
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_if_fail (class->create_folder_sync != NULL);
+
+       if (parent_name == NULL || *parent_name == '\0') {
+               gboolean reserved_vfolder_name;
+
+               reserved_vfolder_name =
+                       ((store->flags & CAMEL_STORE_VJUNK) &&
+                       g_str_equal (folder_name, CAMEL_VJUNK_NAME)) ||
+                       ((store->flags & CAMEL_STORE_VTRASH) &&
+                       g_str_equal (folder_name, CAMEL_VTRASH_NAME));
+
+               if (reserved_vfolder_name) {
+                       g_task_return_new_error (
+                               task, CAMEL_STORE_ERROR,
+                               CAMEL_STORE_ERROR_INVALID,
+                               _("Cannot create folder: %s: folder exists"),
+                               folder_name);
+                       return;
+               }
+       }
+
+       camel_operation_push_message (
+               cancellable, _("Creating folder '%s'"), folder_name);
+
+       folder_info = class->create_folder_sync (
+               store, parent_name, folder_name, cancellable, &local_error);
+       CAMEL_CHECK_LOCAL_GERROR (
+               store, create_folder_sync, folder_info != NULL, local_error);
+
+       camel_operation_pop_message (cancellable);
 
        if (local_error != NULL) {
                g_warn_if_fail (folder_info == NULL);
@@ -2246,11 +2224,14 @@ camel_store_create_folder (CamelStore *store,
                            gpointer user_data)
 {
        GTask *task;
+       CamelService *service;
        AsyncContext *async_context;
 
        g_return_if_fail (CAMEL_IS_STORE (store));
        g_return_if_fail (folder_name != NULL);
 
+       service = CAMEL_SERVICE (store);
+
        async_context = g_slice_new0 (AsyncContext);
        async_context->folder_name_1 = g_strdup (parent_name);
        async_context->folder_name_2 = g_strdup (folder_name);
@@ -2263,7 +2244,8 @@ camel_store_create_folder (CamelStore *store,
                task, async_context,
                (GDestroyNotify) async_context_free);
 
-       g_task_run_in_thread (task, store_create_folder_thread);
+       camel_service_queue_task (
+               service, task, store_create_folder_thread);
 
        g_object_unref (task);
 }
@@ -2316,52 +2298,25 @@ camel_store_delete_folder_sync (CamelStore *store,
                                 GCancellable *cancellable,
                                 GError **error)
 {
-       CamelStoreClass *class;
+       CamelAsyncClosure *closure;
+       GAsyncResult *result;
        gboolean success;
-       GError *local_error = NULL, **check_error = NULL;
 
        g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
        g_return_val_if_fail (folder_name != NULL, FALSE);
 
-       class = CAMEL_STORE_GET_CLASS (store);
-       g_return_val_if_fail (class->delete_folder_sync != NULL, FALSE);
-
-       /* TODO: should probably be a parameter/bit on the storeinfo */
-       if (((store->flags & CAMEL_STORE_VTRASH) && strcmp (folder_name, CAMEL_VTRASH_NAME) == 0)
-           || ((store->flags & CAMEL_STORE_VJUNK) && strcmp (folder_name, CAMEL_VJUNK_NAME) == 0)) {
-               g_set_error (
-                       error, CAMEL_STORE_ERROR,
-                       CAMEL_STORE_ERROR_NO_FOLDER,
-                       _("Cannot delete folder: %s: Invalid operation"),
-                       folder_name);
-               return FALSE;
-       }
-
-       camel_store_lock (store);
+       closure = camel_async_closure_new ();
 
-       /* Check for cancellation after locking. */
-       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
-               camel_store_unlock (store);
-               return FALSE;
-       }
+       camel_store_delete_folder (
+               store, folder_name,
+               G_PRIORITY_DEFAULT, cancellable,
+               camel_async_closure_callback, closure);
 
-       success = class->delete_folder_sync (
-               store, folder_name, cancellable, &local_error);
-       if (local_error)
-               check_error = &local_error;
-       CAMEL_CHECK_GERROR (store, delete_folder_sync, success, check_error);
+       result = camel_async_closure_wait (closure);
 
-       /* ignore 'no such table' errors */
-       if (local_error != NULL &&
-           g_ascii_strncasecmp (local_error->message, "no such table", 13) == 0)
-               g_clear_error (&local_error);
+       success = camel_store_delete_folder_finish (store, result, error);
 
-       if (local_error == NULL)
-               cs_delete_cached_folder (store, folder_name);
-       else
-               g_propagate_error (error, local_error);
-
-       camel_store_unlock (store);
+       camel_async_closure_free (closure);
 
        return success;
 }
@@ -2373,20 +2328,51 @@ store_delete_folder_thread (GTask *task,
                             gpointer task_data,
                             GCancellable *cancellable)
 {
-       gboolean success;
+       CamelStore *store;
+       CamelStoreClass *class;
        AsyncContext *async_context;
+       const gchar *folder_name;
+       gboolean reserved_vfolder_name;
+       gboolean success;
        GError *local_error = NULL;
 
+       store = CAMEL_STORE (source_object);
        async_context = (AsyncContext *) task_data;
 
-       success = camel_store_delete_folder_sync (
-               CAMEL_STORE (source_object),
-               async_context->folder_name_1,
-               cancellable, &local_error);
+       folder_name = async_context->folder_name_1;
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_if_fail (class->delete_folder_sync != NULL);
+
+       reserved_vfolder_name =
+               ((store->flags & CAMEL_STORE_VJUNK) &&
+               g_str_equal (folder_name, CAMEL_VJUNK_NAME)) ||
+               ((store->flags & CAMEL_STORE_VTRASH) &&
+               g_str_equal (folder_name, CAMEL_VTRASH_NAME));
+
+       if (reserved_vfolder_name) {
+               g_task_return_new_error (
+                       task, CAMEL_STORE_ERROR,
+                       CAMEL_STORE_ERROR_NO_FOLDER,
+                       _("Cannot delete folder: %s: Invalid operation"),
+                       folder_name);
+               return;
+       }
+
+       success = class->delete_folder_sync (
+               store, folder_name, cancellable, &local_error);
+       CAMEL_CHECK_LOCAL_GERROR (
+               store, delete_folder_sync, success, local_error);
+
+       /* ignore 'no such table' errors */
+       if (local_error != NULL &&
+           g_ascii_strncasecmp (local_error->message, "no such table", 13) == 0)
+               g_clear_error (&local_error);
 
        if (local_error != NULL) {
                g_task_return_error (task, local_error);
        } else {
+               cs_delete_cached_folder (store, folder_name);
                g_task_return_boolean (task, success);
        }
 }
@@ -2417,11 +2403,14 @@ camel_store_delete_folder (CamelStore *store,
                            gpointer user_data)
 {
        GTask *task;
+       CamelService *service;
        AsyncContext *async_context;
 
        g_return_if_fail (CAMEL_IS_STORE (store));
        g_return_if_fail (folder_name != NULL);
 
+       service = CAMEL_SERVICE (store);
+
        async_context = g_slice_new0 (AsyncContext);
        async_context->folder_name_1 = g_strdup (folder_name);
 
@@ -2433,7 +2422,8 @@ camel_store_delete_folder (CamelStore *store,
                task, async_context,
                (GDestroyNotify) async_context_free);
 
-       g_task_run_in_thread (task, store_delete_folder_thread);
+       camel_service_queue_task (
+               service, task, store_delete_folder_thread);
 
        g_object_unref (task);
 }
@@ -2481,151 +2471,164 @@ camel_store_delete_folder_finish (CamelStore *store,
  **/
 gboolean
 camel_store_rename_folder_sync (CamelStore *store,
-                                const gchar *old_namein,
+                                const gchar *old_name,
                                 const gchar *new_name,
                                 GCancellable *cancellable,
                                 GError **error)
 {
-       CamelStoreClass *class;
-       CamelFolder *folder;
-       gint i, oldlen, namelen;
-       GPtrArray *folders = NULL;
-       gchar *old_name;
+       CamelAsyncClosure *closure;
+       GAsyncResult *result;
        gboolean success;
 
        g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
-       g_return_val_if_fail (old_namein != NULL, FALSE);
+       g_return_val_if_fail (old_name != NULL, FALSE);
        g_return_val_if_fail (new_name != NULL, FALSE);
 
+       closure = camel_async_closure_new ();
+
+       camel_store_rename_folder (
+               store, old_name, new_name,
+               G_PRIORITY_DEFAULT, cancellable,
+               camel_async_closure_callback, closure);
+
+       result = camel_async_closure_wait (closure);
+
+       success = camel_store_rename_folder_finish (store, result, error);
+
+       camel_async_closure_free (closure);
+
+       return success;
+}
+
+/* Helper for camel_store_rename_folder() */
+static void
+store_rename_folder_thread (GTask *task,
+                            gpointer source_object,
+                            gpointer task_data,
+                            GCancellable *cancellable)
+{
+       CamelStore *store;
+       CamelStoreClass *class;
+       CamelFolder *folder;
+       GPtrArray *folders;
+       const gchar *old_name;
+       const gchar *new_name;
+       gboolean reserved_vfolder_name;
+       gboolean success;
+       gsize old_name_len;
+       guint ii;
+       AsyncContext *async_context;
+       GError *local_error = NULL;
+
+       store = CAMEL_STORE (source_object);
+       async_context = (AsyncContext *) task_data;
+
+       old_name = async_context->folder_name_1;
+       new_name = async_context->folder_name_2;
+
        class = CAMEL_STORE_GET_CLASS (store);
-       g_return_val_if_fail (class->rename_folder_sync != NULL, FALSE);
+       g_return_if_fail (class->rename_folder_sync != NULL);
+
+       if (g_str_equal (old_name, new_name)) {
+               g_task_return_boolean (task, TRUE);
+               return;
+       }
 
-       if (strcmp (old_namein, new_name) == 0)
-               return TRUE;
+       reserved_vfolder_name =
+               ((store->flags & CAMEL_STORE_VJUNK) &&
+               g_str_equal (old_name, CAMEL_VJUNK_NAME) == 0) ||
+               ((store->flags & CAMEL_STORE_VTRASH) &&
+               g_str_equal (old_name, CAMEL_VTRASH_NAME) == 0);
 
-       if (((store->flags & CAMEL_STORE_VTRASH) && strcmp (old_namein, CAMEL_VTRASH_NAME) == 0)
-           || ((store->flags & CAMEL_STORE_VJUNK) && strcmp (old_namein, CAMEL_VJUNK_NAME) == 0)) {
-               g_set_error (
-                       error, CAMEL_STORE_ERROR,
+       if (reserved_vfolder_name) {
+               g_task_return_new_error (
+                       task, CAMEL_STORE_ERROR,
                        CAMEL_STORE_ERROR_NO_FOLDER,
                        _("Cannot rename folder: %s: Invalid operation"),
-                       old_namein);
-               return FALSE;
+                       old_name);
+               return;
        }
 
-       /* need to save this, since old_namein might be folder->full_name, which could go away */
-       old_name = g_strdup (old_namein);
-       oldlen = strlen (old_name);
-
-       camel_store_lock (store);
-
-       /* Check for cancellation after locking. */
-       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
-               camel_store_unlock (store);
-               return FALSE;
-       }
+       old_name_len = strlen (old_name);
 
        /* If the folder is open (or any subfolders of the open folder)
         * We need to rename them atomically with renaming the actual
         * folder path. */
        folders = camel_object_bag_list (store->folders);
-       for (i = 0; folders && i < folders->len; i++) {
+       for (ii = 0; ii < folders->len; ii++) {
                const gchar *full_name;
+               gsize full_name_len;
 
-               folder = folders->pdata[i];
+               folder = folders->pdata[ii];
                full_name = camel_folder_get_full_name (folder);
+               full_name_len = strlen (full_name);
 
-               namelen = strlen (full_name);
-               if ((namelen == oldlen &&
+               if ((full_name_len == old_name_len &&
                     strcmp (full_name, old_name) == 0)
-                   || ((namelen > oldlen)
-                       && strncmp (full_name, old_name, oldlen) == 0
-                       && full_name[oldlen] == '/')) {
+                   || ((full_name_len > old_name_len)
+                       && strncmp (full_name, old_name, old_name_len) == 0
+                       && full_name[old_name_len] == '/')) {
                        camel_folder_lock (folder);
                } else {
-                       g_ptr_array_remove_index_fast (folders, i);
-                       i--;
+                       g_ptr_array_remove_index_fast (folders, ii);
+                       ii--;
                        g_object_unref (folder);
                }
        }
 
        /* Now try the real rename (will emit renamed signal) */
        success = class->rename_folder_sync (
-               store, old_name, new_name, cancellable, error);
-       CAMEL_CHECK_GERROR (store, rename_folder_sync, success, error);
+               store, old_name, new_name, cancellable, &local_error);
+       CAMEL_CHECK_LOCAL_GERROR (
+               store, rename_folder_sync, success, local_error);
 
        /* If it worked, update all open folders/unlock them */
-       if (folders) {
-               if (success) {
-                       CamelStoreGetFolderInfoFlags flags;
-                       CamelFolderInfo *folder_info;
+       if (success) {
+               CamelStoreGetFolderInfoFlags flags;
+               CamelFolderInfo *folder_info;
 
-                       flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE;
+               flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE;
 
-                       for (i = 0; i < folders->len; i++) {
-                               const gchar *full_name;
-                               gchar *new;
+               for (ii = 0; ii < folders->len; ii++) {
+                       const gchar *full_name;
+                       gchar *new;
 
-                               folder = folders->pdata[i];
-                               full_name = camel_folder_get_full_name (folder);
+                       folder = folders->pdata[ii];
+                       full_name = camel_folder_get_full_name (folder);
 
-                               new = g_strdup_printf ("%s%s", new_name, full_name + strlen (old_name));
-                               camel_object_bag_rekey (store->folders, folder, new);
-                               camel_folder_rename (folder, new);
-                               g_free (new);
+                       new = g_strdup_printf ("%s%s", new_name, full_name + strlen (old_name));
+                       camel_object_bag_rekey (store->folders, folder, new);
+                       camel_folder_rename (folder, new);
+                       g_free (new);
 
-                               camel_folder_unlock (folder);
-                               g_object_unref (folder);
-                       }
+                       camel_folder_unlock (folder);
+                       g_object_unref (folder);
+               }
 
-                       /* Emit renamed signal */
-                       if (CAMEL_IS_SUBSCRIBABLE (store))
-                               flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
+               /* Emit renamed signal */
+               if (CAMEL_IS_SUBSCRIBABLE (store))
+                       flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
 
-                       folder_info = class->get_folder_info_sync (
-                               store, new_name, flags, cancellable, error);
-                       CAMEL_CHECK_GERROR (store, get_folder_info, folder_info != NULL, error);
+               folder_info = class->get_folder_info_sync (
+                       store, new_name, flags, cancellable, &local_error);
+               CAMEL_CHECK_LOCAL_GERROR (
+                       store, get_folder_info,
+                       folder_info != NULL, local_error);
 
-                       if (folder_info != NULL) {
-                               camel_store_folder_renamed (store, old_name, folder_info);
-                               camel_folder_info_free (folder_info);
-                       }
-               } else {
-                       /* Failed, just unlock our folders for re-use */
-                       for (i = 0; i < folders->len; i++) {
-                               folder = folders->pdata[i];
-                               camel_folder_unlock (folder);
-                               g_object_unref (folder);
-                       }
+               if (folder_info != NULL) {
+                       camel_store_folder_renamed (store, old_name, folder_info);
+                       camel_folder_info_free (folder_info);
+               }
+       } else {
+               /* Failed, just unlock our folders for re-use */
+               for (ii = 0; ii < folders->len; ii++) {
+                       folder = folders->pdata[ii];
+                       camel_folder_unlock (folder);
+                       g_object_unref (folder);
                }
        }
 
-       camel_store_unlock (store);
-
        g_ptr_array_free (folders, TRUE);
-       g_free (old_name);
-
-       return success;
-}
-
-/* Helper for camel_store_rename_folder() */
-static void
-store_rename_folder_thread (GTask *task,
-                            gpointer source_object,
-                            gpointer task_data,
-                            GCancellable *cancellable)
-{
-       gboolean success;
-       AsyncContext *async_context;
-       GError *local_error = NULL;
-
-       async_context = (AsyncContext *) task_data;
-
-       success = camel_store_rename_folder_sync (
-               CAMEL_STORE (source_object),
-               async_context->folder_name_1,
-               async_context->folder_name_2,
-               cancellable, &local_error);
 
        if (local_error != NULL) {
                g_task_return_error (task, local_error);
@@ -2661,12 +2664,15 @@ camel_store_rename_folder (CamelStore *store,
                            gpointer user_data)
 {
        GTask *task;
+       CamelService *service;
        AsyncContext *async_context;
 
        g_return_if_fail (CAMEL_IS_STORE (store));
        g_return_if_fail (old_name != NULL);
        g_return_if_fail (new_name != NULL);
 
+       service = CAMEL_SERVICE (store);
+
        async_context = g_slice_new0 (AsyncContext);
        async_context->folder_name_1 = g_strdup (old_name);
        async_context->folder_name_2 = g_strdup (new_name);
@@ -2679,7 +2685,8 @@ camel_store_rename_folder (CamelStore *store,
                task, async_context,
                (GDestroyNotify) async_context_free);
 
-       g_task_run_in_thread (task, store_rename_folder_thread);
+       camel_service_queue_task (
+               service, task, store_rename_folder_thread);
 
        g_object_unref (task);
 }
diff --git a/camel/camel-store.h b/camel/camel-store.h
index 30e3f4f..d15f7c6 100644
--- a/camel/camel-store.h
+++ b/camel/camel-store.h
@@ -230,8 +230,6 @@ CamelFolderInfo *
 gboolean       camel_store_can_refresh_folder  (CamelStore *store,
                                                 CamelFolderInfo *info,
                                                 GError **error);
-void           camel_store_lock                (CamelStore *store);
-void           camel_store_unlock              (CamelStore *store);
 
 CamelFolder *  camel_store_get_folder_sync     (CamelStore *store,
                                                 const gchar *folder_name,
diff --git a/camel/camel-subscribable.c b/camel/camel-subscribable.c
index e2096bf..6e5c022 100644
--- a/camel/camel-subscribable.c
+++ b/camel/camel-subscribable.c
@@ -21,6 +21,7 @@
 #include <config.h>
 #include <glib/gi18n-lib.h>
 
+#include "camel-async-closure.h"
 #include "camel-debug.h"
 #include "camel-session.h"
 #include "camel-vtrash-folder.h"
@@ -215,42 +216,26 @@ camel_subscribable_subscribe_folder_sync (CamelSubscribable *subscribable,
                                           GCancellable *cancellable,
                                           GError **error)
 {
-       CamelSubscribableInterface *interface;
-       const gchar *message;
+       CamelAsyncClosure *closure;
+       GAsyncResult *result;
        gboolean success;
 
        g_return_val_if_fail (CAMEL_IS_SUBSCRIBABLE (subscribable), FALSE);
        g_return_val_if_fail (folder_name != NULL, FALSE);
 
-       interface = CAMEL_SUBSCRIBABLE_GET_INTERFACE (subscribable);
-       g_return_val_if_fail (interface->subscribe_folder_sync != NULL, FALSE);
+       closure = camel_async_closure_new ();
 
-       camel_store_lock (CAMEL_STORE (subscribable));
-
-       /* Check for cancellation after locking. */
-       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
-               success = FALSE;
-               goto exit;
-       }
+       camel_subscribable_subscribe_folder (
+               subscribable, folder_name,
+               G_PRIORITY_DEFAULT, cancellable,
+               camel_async_closure_callback, closure);
 
-       /* Need to establish a connection before subscribing. */
-       success = camel_service_connect_sync (
-               CAMEL_SERVICE (subscribable), cancellable, error);
-       if (!success)
-               goto exit;
+       result = camel_async_closure_wait (closure);
 
-       message = _("Subscribing to folder '%s'");
-       camel_operation_push_message (cancellable, message, folder_name);
+       success = camel_subscribable_subscribe_folder_finish (
+               subscribable, result, error);
 
-       success = interface->subscribe_folder_sync (
-               subscribable, folder_name, cancellable, error);
-       CAMEL_CHECK_GERROR (
-               subscribable, subscribe_folder_sync, success, error);
-
-       camel_operation_pop_message (cancellable);
-
-exit:
-       camel_store_unlock (CAMEL_STORE (subscribable));
+       camel_async_closure_free (closure);
 
        return success;
 }
@@ -262,16 +247,39 @@ subscribable_subscribe_folder_thread (GTask *task,
                                       gpointer task_data,
                                       GCancellable *cancellable)
 {
+       CamelSubscribable *subscribable;
+       CamelSubscribableInterface *interface;
+       const gchar *folder_name;
+       const gchar *message;
        gboolean success;
        AsyncContext *async_context;
        GError *local_error = NULL;
 
+       subscribable = CAMEL_SUBSCRIBABLE (source_object);
        async_context = (AsyncContext *) task_data;
 
-       success = camel_subscribable_subscribe_folder_sync (
-               CAMEL_SUBSCRIBABLE (source_object),
-               async_context->folder_name,
-               cancellable, &local_error);
+       folder_name = async_context->folder_name;
+
+       interface = CAMEL_SUBSCRIBABLE_GET_INTERFACE (subscribable);
+       g_return_if_fail (interface->subscribe_folder_sync != NULL);
+
+       /* Need to establish a connection before subscribing. */
+       camel_service_connect_sync (
+               CAMEL_SERVICE (subscribable), cancellable, &local_error);
+       if (local_error != NULL) {
+               g_task_return_error (task, local_error);
+               return;
+       }
+
+       message = _("Subscribing to folder '%s'");
+       camel_operation_push_message (cancellable, message, folder_name);
+
+       success = interface->subscribe_folder_sync (
+               subscribable, folder_name, cancellable, &local_error);
+       CAMEL_CHECK_LOCAL_GERROR (
+               subscribable, subscribe_folder_sync, success, local_error);
+
+       camel_operation_pop_message (cancellable);
 
        if (local_error != NULL) {
                g_task_return_error (task, local_error);
@@ -306,11 +314,14 @@ camel_subscribable_subscribe_folder (CamelSubscribable *subscribable,
                                      gpointer user_data)
 {
        GTask *task;
+       CamelService *service;
        AsyncContext *async_context;
 
        g_return_if_fail (CAMEL_IS_SUBSCRIBABLE (subscribable));
        g_return_if_fail (folder_name != NULL);
 
+       service = CAMEL_SERVICE (subscribable);
+
        async_context = g_slice_new0 (AsyncContext);
        async_context->folder_name = g_strdup (folder_name);
 
@@ -322,7 +333,8 @@ camel_subscribable_subscribe_folder (CamelSubscribable *subscribable,
                task, async_context,
                (GDestroyNotify) async_context_free);
 
-       g_task_run_in_thread (task, subscribable_subscribe_folder_thread);
+       camel_service_queue_task (
+               service, task, subscribable_subscribe_folder_thread);
 
        g_object_unref (task);
 }
@@ -373,47 +385,26 @@ camel_subscribable_unsubscribe_folder_sync (CamelSubscribable *subscribable,
                                             GCancellable *cancellable,
                                             GError **error)
 {
-       CamelSubscribableInterface *interface;
-       const gchar *message;
+       CamelAsyncClosure *closure;
+       GAsyncResult *result;
        gboolean success;
 
        g_return_val_if_fail (CAMEL_IS_SUBSCRIBABLE (subscribable), FALSE);
        g_return_val_if_fail (folder_name != NULL, FALSE);
 
-       interface = CAMEL_SUBSCRIBABLE_GET_INTERFACE (subscribable);
-       g_return_val_if_fail (
-               interface->unsubscribe_folder_sync != NULL, FALSE);
+       closure = camel_async_closure_new ();
 
-       camel_store_lock (CAMEL_STORE (subscribable));
+       camel_subscribable_unsubscribe_folder (
+               subscribable, folder_name,
+               G_PRIORITY_DEFAULT, cancellable,
+               camel_async_closure_callback, closure);
 
-       /* Check for cancellation after locking. */
-       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
-               success = FALSE;
-               goto exit;
-       }
+       result = camel_async_closure_wait (closure);
 
-       /* Need to establish a connection before unsubscribing. */
-       success = camel_service_connect_sync (
-               CAMEL_SERVICE (subscribable), cancellable, error);
-       if (!success)
-               goto exit;
-
-       message = _("Unsubscribing from folder '%s'");
-       camel_operation_push_message (cancellable, message, folder_name);
-
-       success = interface->unsubscribe_folder_sync (
-               subscribable, folder_name, cancellable, error);
-       CAMEL_CHECK_GERROR (
-               subscribable, unsubscribe_folder_sync, success, error);
+       success = camel_subscribable_unsubscribe_folder_finish (
+               subscribable, result, error);
 
-       if (success)
-               subscribable_delete_cached_folder (
-                       CAMEL_STORE (subscribable), folder_name);
-
-       camel_operation_pop_message (cancellable);
-
-exit:
-       camel_store_unlock (CAMEL_STORE (subscribable));
+       camel_async_closure_free (closure);
 
        return success;
 }
@@ -425,16 +416,43 @@ subscribable_unsubscribe_folder_thread (GTask *task,
                                         gpointer task_data,
                                         GCancellable *cancellable)
 {
+       CamelSubscribable *subscribable;
+       CamelSubscribableInterface *interface;
+       const gchar *folder_name;
+       const gchar *message;
        gboolean success;
        AsyncContext *async_context;
        GError *local_error = NULL;
 
+       subscribable = CAMEL_SUBSCRIBABLE (source_object);
        async_context = (AsyncContext *) task_data;
 
-       success = camel_subscribable_unsubscribe_folder_sync (
-               CAMEL_SUBSCRIBABLE (source_object),
-               async_context->folder_name,
-               cancellable, &local_error);
+       folder_name = async_context->folder_name;
+
+       interface = CAMEL_SUBSCRIBABLE_GET_INTERFACE (subscribable);
+       g_return_if_fail (interface->unsubscribe_folder_sync != NULL);
+
+       /* Need to establish a connection before unsubscribing. */
+       camel_service_connect_sync (
+               CAMEL_SERVICE (subscribable), cancellable, &local_error);
+       if (local_error != NULL) {
+               g_task_return_error (task, local_error);
+               return;
+       }
+
+       message = _("Unsubscribing from folder '%s'");
+       camel_operation_push_message (cancellable, message, folder_name);
+
+       success = interface->unsubscribe_folder_sync (
+               subscribable, folder_name, cancellable, &local_error);
+       CAMEL_CHECK_LOCAL_GERROR (
+               subscribable, unsubscribe_folder_sync, success, local_error);
+
+       if (success)
+               subscribable_delete_cached_folder (
+                       CAMEL_STORE (subscribable), folder_name);
+
+       camel_operation_pop_message (cancellable);
 
        if (local_error != NULL) {
                g_task_return_error (task, local_error);
@@ -469,11 +487,14 @@ camel_subscribable_unsubscribe_folder (CamelSubscribable *subscribable,
                                        gpointer user_data)
 {
        GTask *task;
+       CamelService *service;
        AsyncContext *async_context;
 
        g_return_if_fail (CAMEL_IS_SUBSCRIBABLE (subscribable));
        g_return_if_fail (folder_name != NULL);
 
+       service = CAMEL_SERVICE (subscribable);
+
        async_context = g_slice_new0 (AsyncContext);
        async_context->folder_name = g_strdup (folder_name);
 
@@ -485,7 +506,8 @@ camel_subscribable_unsubscribe_folder (CamelSubscribable *subscribable,
                task, async_context,
                (GDestroyNotify) async_context_free);
 
-       g_task_run_in_thread (task, subscribable_unsubscribe_folder_thread);
+       camel_service_queue_task (
+               service, task, subscribable_unsubscribe_folder_thread);
 
        g_object_unref (task);
 }
diff --git a/docs/reference/camel/camel-sections.txt b/docs/reference/camel/camel-sections.txt
index c708753..9621a30 100644
--- a/docs/reference/camel/camel-sections.txt
+++ b/docs/reference/camel/camel-sections.txt
@@ -2057,8 +2057,6 @@ camel_folder_info_free
 camel_folder_info_build
 camel_folder_info_clone
 camel_store_can_refresh_folder
-camel_store_lock
-camel_store_unlock
 camel_store_get_folder_sync
 camel_store_get_folder
 camel_store_get_folder_finish


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