[balsa/gtk3] Open mailbox in a thread



commit dbd8c81b26c5356a5885f8ac9e866cff89fa0e4c
Author: Peter Bloomfield <PeterBloomfield bellsouth net>
Date:   Thu Feb 21 11:50:34 2013 -0500

    Open mailbox in a thread
    
        * src/balsa-index.c (balsa_index_load_mailbox_node): move
        libbalsa_mailbox_open call to balsa_window_real_open_mbnode.
        * src/balsa-index.h: drop unused argument.
        * src/main-window.c: open mailbox in a thread.

 ChangeLog         |    7 ++
 src/balsa-index.c |   28 +------
 src/balsa-index.h |    3 +-
 src/main-window.c |  206 +++++++++++++++++++++++++++--------------------------
 4 files changed, 117 insertions(+), 127 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 4fd686d..efc0645 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2013-02-21  Peter Bloomfield
 
+       * src/balsa-index.c (balsa_index_load_mailbox_node): move
+       libbalsa_mailbox_open call to balsa_window_real_open_mbnode.
+       * src/balsa-index.h: drop unused argument.
+       * src/main-window.c: open mailbox in a thread.
+
+2013-02-21  Peter Bloomfield
+
        * src/main.c (balsa_progress_set_text): do not check for
        subthread, as balsa_window_setup_progress is thread-safe.
 
diff --git a/src/balsa-index.c b/src/balsa-index.c
index 3d3ead1..ffa987f 100644
--- a/src/balsa-index.c
+++ b/src/balsa-index.c
@@ -1010,20 +1010,16 @@ bndx_mailbox_message_expunged_cb(LibBalsaMailbox * mailbox, guint msgno,
 }
 
 /* balsa_index_load_mailbox_node:
-   open mailbox_node, the opening is done in thread to keep UI alive.
-
-   Called NOT holding the gdk lock, so we must wrap gtk calls in
-   gdk_threads_{enter,leave}.
-*/
+ *
+ * mbnode->mailbox is already open
+ */
 
 gboolean
 balsa_index_load_mailbox_node(BalsaIndex * index,
-                              BalsaMailboxNode* mbnode, GError **err)
+                              BalsaMailboxNode* mbnode)
 {
     GtkTreeView *tree_view;
     LibBalsaMailbox *mailbox;
-    gboolean successp;
-    gint try_cnt;
 
     g_return_val_if_fail(BALSA_IS_INDEX(index), TRUE);
     g_return_val_if_fail(index->mailbox_node == NULL, TRUE);
@@ -1032,22 +1028,6 @@ balsa_index_load_mailbox_node(BalsaIndex * index,
 
     mailbox = mbnode->mailbox;
 
-    try_cnt = 0;
-    do {
-        g_clear_error(err);
-        successp = libbalsa_mailbox_open(mailbox, err);
-        if (!balsa_app.main_window)
-            return FALSE;
-
-        if(successp) break;
-        if(*err && (*err)->code != LIBBALSA_MAILBOX_TOOMANYOPEN_ERROR)
-            break;
-        balsa_mblist_close_lru_peer_mbx(balsa_app.mblist, mailbox);
-    } while(try_cnt++<3);
-
-    if (!successp)
-       return TRUE;
-
     /*
      * set the new mailbox
      */
diff --git a/src/balsa-index.h b/src/balsa-index.h
index dc5ab15..f156ca9 100644
--- a/src/balsa-index.h
+++ b/src/balsa-index.h
@@ -106,8 +106,7 @@ extern "C" {
 /* sets the mail stream; if it's a new stream, then it's 
  * contents is loaded into the index */
     gboolean balsa_index_load_mailbox_node(BalsaIndex * bindex,
-                                           BalsaMailboxNode * mbnode,
-                                          GError **err);
+                                           BalsaMailboxNode * mbnode);
     void balsa_index_set_width_preference(BalsaIndex *bindex,
                                           BalsaIndexWidthPreference pref);
     void balsa_index_scroll_on_open(BalsaIndex *index);
diff --git a/src/main-window.c b/src/main-window.c
index 554ccd9..bc0c394 100644
--- a/src/main-window.c
+++ b/src/main-window.c
@@ -2323,61 +2323,48 @@ bw_notebook_label_new(BalsaMailboxNode * mbnode)
     return box;
 }
 
-/* Called with the gdk lock held (when threads are enabled). */
-static void
-bw_real_open_mbnode(BalsaWindow *window, BalsaMailboxNode * mbnode,
-                    gboolean set_current)
-{
-    BalsaIndex * index;
-    GtkWidget *label;
-    GtkWidget *scroll;
-    gint page_num;
-    gboolean failurep;
-    GError *err = NULL;
-    gchar *message;
-    LibBalsaMailbox *mailbox;
+/*
+ * balsa_window_real_open_mbnode
+ */
 
-    /* FIXME: the check is not needed in non-MT-mode */
-    if (!window || bw_is_open_mailbox(mailbox = mbnode->mailbox))
-        return;
+typedef struct {
+    BalsaIndex       *index;
+    BalsaMailboxNode *mbnode;
+    BalsaWindow      *window;
+    gchar            *message;
+    gboolean          set_current;
+} BalsaWindowRealOpenMbnodeInfo;
 
-    index = BALSA_INDEX(balsa_index_new());
-    balsa_index_set_width_preference
-        (index,
-         (balsa_app.layout_type == LAYOUT_WIDE_SCREEN)
-         ? BALSA_INDEX_NARROW : BALSA_INDEX_WIDE);
+static gboolean
+bw_real_open_mbnode_idle_cb(BalsaWindowRealOpenMbnodeInfo * info)
+{
+    BalsaIndex       *index   = info->index;
+    BalsaMailboxNode *mbnode  = info->mbnode;
+    BalsaWindow      *window  = info->window;
+    LibBalsaMailbox  *mailbox = mbnode->mailbox;
+    GtkWidget        *label;
+    GtkWidget        *scroll;
+    gint              page_num;
 
-    g_object_add_weak_pointer(G_OBJECT(window), (gpointer) &window);
-    message = g_strdup_printf(_("Opening %s"), mailbox->name);
-    balsa_window_increase_activity(window, message);
+    if (balsa_find_notebook_page_num(mailbox) >= 0) {
+        g_free(info);
+        return FALSE;
+    }
 
-    /* Call balsa_index_load_mailbox_node NOT holding the gdk lock. */
-    gdk_threads_leave();
-    failurep = balsa_index_load_mailbox_node(index, mbnode, &err);
-    gdk_threads_enter();
+    balsa_index_load_mailbox_node(index, mbnode);
 
     if (window) {
-        balsa_window_decrease_activity(window, message);
-        g_object_remove_weak_pointer(G_OBJECT(window), (gpointer) &window);
+        balsa_window_decrease_activity(window, info->message);
+        g_object_remove_weak_pointer(G_OBJECT(window),
+                                     (gpointer) &info->window);
     }
-    g_free(message);
+    g_free(info->message);
 
-    if (!window || failurep) {
-        libbalsa_information(
-            LIBBALSA_INFORMATION_ERROR,
-            _("Unable to Open Mailbox!\n%s."),
-           err ? err->message : _("Unknown error"));
-       g_clear_error(&err);
-        g_object_unref(g_object_ref_sink(index));
-        return;
-    }
-    g_assert(index->mailbox_node);
-    g_signal_connect(G_OBJECT (index), "index-changed",
-                     G_CALLBACK (bw_index_changed_cb), window);
+    g_signal_connect(index, "index-changed",
+                     G_CALLBACK(bw_index_changed_cb), window);
 
-    /* if(config_short_label) label = gtk_label_new(mbnode->mailbox->name);
-       else */
     label = bw_notebook_label_new(mbnode);
+    g_object_unref(mbnode);
 
     /* store for easy access */
     scroll = gtk_scrolled_window_new(NULL, NULL);
@@ -2390,99 +2377,116 @@ bw_real_open_mbnode(BalsaWindow *window, BalsaMailboxNode * mbnode,
                                         scroll, label);
     gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(window->notebook),
                                      scroll, TRUE);
-    /* This seems to be necessary to avoid critical messages when a new
-     * page is added; see
-     * https://bugzilla.gnome.org/show_bug.cgi?id=658513
-     */
-    gtk_container_resize_children(GTK_CONTAINER(window->notebook));
 
-    if (set_current)
+    if (info->set_current)
         /* change the page to the newly selected notebook item */
         gtk_notebook_set_current_page(GTK_NOTEBOOK(window->notebook),
                                       page_num);
 
     bw_register_open_mailbox(mailbox);
-    /* scroll may select the message and GtkTreeView does not like selecting
-     * without being shown first. */
     libbalsa_mailbox_set_threading(mailbox,
                                    libbalsa_mailbox_get_threading_type
                                    (mailbox));
+    /* scroll may select the message and GtkTreeView does not like selecting
+     * without being shown first. */
     balsa_index_scroll_on_open(index);
-}
 
-#if 0 && defined(BALSA_USE_THREADS)
-static pthread_mutex_t open_lock = PTHREAD_MUTEX_INITIALIZER;
+    g_free(info);
 
-struct bw_open_mbnode_info {
-    BalsaWindow *window;
-    BalsaMailboxNode * mbnode;
-    gboolean set_current;
-};
+    return FALSE;
+}
 
 static void
-bw_real_open_mbnode_thread(GPtrArray *info_array)
+bw_real_open_mbnode_thread(BalsaWindowRealOpenMbnodeInfo * info)
 {
-    guint i;
+#ifdef BALSA_USE_THREADS
+    static pthread_mutex_t open_lock = PTHREAD_MUTEX_INITIALIZER;
+#endif                          /* BALSA_USE_THREADS */
+    gint try_cnt;
+    LibBalsaMailbox *mailbox = info->mbnode->mailbox;
+    GError *err = NULL;
+    gboolean successp;
 
-    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+#ifdef BALSA_USE_THREADS
+    /* Use a mutex to ensure we open only one mailbox at a time */
     pthread_mutex_lock(&open_lock);
+#endif                          /* BALSA_USE_THREADS */
 
-    for (i = 0; i < info_array->len; i++) {
-        struct bw_open_mbnode_info *info =
-            g_ptr_array_index(info_array, i);
-
-        pthread_mutex_unlock(&open_lock);
-        gdk_threads_enter();
+    try_cnt = 0;
+    do {
+        g_clear_error(&err);
+        successp = libbalsa_mailbox_open(mailbox, &err);
+        if (!balsa_app.main_window)
+            return;
 
-        bw_real_open_mbnode(info->window, info->mbnode, info->set_current);
+        if(successp) break;
+        if(err && err->code != LIBBALSA_MAILBOX_TOOMANYOPEN_ERROR)
+            break;
+        balsa_mblist_close_lru_peer_mbx(balsa_app.mblist, mailbox);
+    } while(try_cnt++<3);
 
-       if (info->window)
+    if (successp) {
+        g_idle_add((GSourceFunc) bw_real_open_mbnode_idle_cb, info);
+    } else {
+        libbalsa_information(
+            LIBBALSA_INFORMATION_ERROR,
+            _("Unable to Open Mailbox!\n%s."),
+           err ? err->message : _("Unknown error"));
+        if (info->window) {
+            balsa_window_decrease_activity(info->window, info->message);
             g_object_remove_weak_pointer(G_OBJECT(info->window),
                                          (gpointer) &info->window);
+        }
+        g_free(info->message);
+        g_object_unref(g_object_ref_sink(info->index));
         g_object_unref(info->mbnode);
-
-        gdk_threads_leave();
         g_free(info);
-        pthread_mutex_lock(&open_lock);
     }
-
-    info_array->len = 0;
+#ifdef BALSA_USE_THREADS
     pthread_mutex_unlock(&open_lock);
+#endif                          /* BALSA_USE_THREADS */
 }
-#endif
 
 static void
 balsa_window_real_open_mbnode(BalsaWindow * window,
                               BalsaMailboxNode * mbnode,
                               gboolean set_current)
 {
-#if 0 && defined(BALSA_USE_THREADS)
-    struct bw_open_mbnode_info *info;
-    static GPtrArray *info_array;
+    BalsaIndex * index;
+    gchar *message;
+    LibBalsaMailbox *mailbox;
+#ifdef BALSA_USE_THREADS
+    pthread_t open_thread;
+#endif                          /* BALSA_USE_THREADS */
+    BalsaWindowRealOpenMbnodeInfo *info;
+
+    if (bw_is_open_mailbox(mailbox = mbnode->mailbox))
+        return;
 
-    info = g_new(struct bw_open_mbnode_info, 1);
+    index = BALSA_INDEX(balsa_index_new());
+    balsa_index_set_width_preference
+        (index,
+         (balsa_app.layout_type == LAYOUT_WIDE_SCREEN)
+         ? BALSA_INDEX_NARROW : BALSA_INDEX_WIDE);
+
+    message = g_strdup_printf(_("Opening %s"), mailbox->name);
+    balsa_window_increase_activity(window, message);
+
+    info = g_new(BalsaWindowRealOpenMbnodeInfo, 1);
     info->window = window;
     g_object_add_weak_pointer(G_OBJECT(window), (gpointer) &info->window);
     info->mbnode = g_object_ref(mbnode);
     info->set_current = set_current;
-
-    pthread_mutex_lock(&open_lock);
-
-    if (!info_array)
-        info_array = g_ptr_array_new();
-    if (!info_array->len) {
-        pthread_t open_thread;
-        pthread_create(&open_thread, NULL,
-                       (void*(*)(void*))bw_real_open_mbnode_thread,
-                       info_array);
-        pthread_detach(open_thread);
-    }
-
-    g_ptr_array_add(info_array, info);
-    pthread_mutex_unlock(&open_lock);
-#else
-    bw_real_open_mbnode(window, mbnode, set_current);
-#endif
+    info->index = index;
+    info->message = message;
+#ifdef BALSA_USE_THREADS
+    pthread_create(&open_thread, NULL,
+                   (void*(*)(void*))bw_real_open_mbnode_thread,
+                   info);
+    pthread_detach(open_thread);
+#else                           /* BALSA_USE_THREADS */
+    bw_real_open_mbnode_thread(info);
+#endif                          /* BALSA_USE_THREADS */
 }
 
 /* balsa_window_real_close_mbnode:


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