[balsa/gtk3] Revert changes moving Gtk access to main thread



commit e3de8ec07dde3ab1a7625c99c10dffaa6e95ce79
Author: Peter Bloomfield <PeterBloomfield bellsouth net>
Date:   Mon Sep 17 20:43:56 2012 -0400

    Revert changes moving Gtk access to main thread
    
    	Revert all changes moving Gtk access from subthreads to main
    	thread.

 ChangeLog                |   18 ++++
 libbalsa/libbalsa.c      |    3 -
 libbalsa/mailbox.c       |  248 +++++-----------------------------------------
 libbalsa/mailbox_local.c |    5 +
 src/balsa-app.c          |   87 +---------------
 src/balsa-index.c        |  153 +++++++++--------------------
 src/balsa-index.h        |    6 +-
 src/main-window.c        |  129 ++++++++++++++++++++----
 src/main.c               |   79 +--------------
 9 files changed, 218 insertions(+), 510 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 62733a6..47788e1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2012-09-17  Peter Bloomfield
+
+	Revert all changes moving Gtk access from subthreads to main
+	thread.
+
+	* libbalsa/libbalsa.c (libbalsa_threads_enter):
+	* libbalsa/mailbox.c (lbm_index_entry_new_from_msg),
+	(libbalsa_mailbox_close), (libbalsa_mailbox_msgno_inserted),
+	(libbalsa_mailbox_msgno_removed),
+	(libbalsa_mailbox_msgno_filt_check), (lbm_cache_message):
+	* libbalsa/mailbox_local.c (libbalsa_mailbox_local_load_messages):
+	* src/balsa-app.c (find_url), (balsa_find_url):
+	* src/balsa-index.c (balsa_index_load_mailbox_node):
+	* src/balsa-index.h:
+	* src/main-window.c:
+	* src/main.c (balsa_progress_set_text),
+	(balsa_progress_set_fraction):
+
 2012-09-08  Peter Bloomfield
 
 	* configure.in:  _NL_MEASUREMENT_MEASUREMENT is an enum and not
diff --git a/libbalsa/libbalsa.c b/libbalsa/libbalsa.c
index 4a090b9..0407cc4 100644
--- a/libbalsa/libbalsa.c
+++ b/libbalsa/libbalsa.c
@@ -761,9 +761,6 @@ libbalsa_threads_enter(void)
 
     self = pthread_self();
 
-    if (libbalsa_am_i_subthread())
-        g_warning("Locking a subthread");
-
     if (self != libbalsa_threads_id) {
         pthread_mutex_lock(&libbalsa_threads_mutex);
         libbalsa_threads_id = self;
diff --git a/libbalsa/mailbox.c b/libbalsa/mailbox.c
index 4186c1e..870a2c3 100644
--- a/libbalsa/mailbox.c
+++ b/libbalsa/mailbox.c
@@ -367,6 +367,14 @@ lbm_index_entry_populate_from_msg(LibBalsaMailboxIndexEntry * entry,
     libbalsa_mailbox_msgno_changed(msg->mailbox, msg->msgno);
 }
 
+static LibBalsaMailboxIndexEntry*
+lbm_index_entry_new_from_msg(LibBalsaMessage *msg)
+{
+    LibBalsaMailboxIndexEntry *entry = g_new(LibBalsaMailboxIndexEntry,1);
+    lbm_index_entry_populate_from_msg(entry, msg);
+    return entry;
+}
+
 #ifdef BALSA_USE_THREADS
 static LibBalsaMailboxIndexEntry*
 lbm_index_entry_new_pending(void)
@@ -643,10 +651,12 @@ libbalsa_mailbox_close(LibBalsaMailbox * mailbox, gboolean expunge)
         /* do not try expunging read-only mailboxes, it's a waste of time */
         expunge = expunge && !mailbox->readonly;
         LIBBALSA_MAILBOX_GET_CLASS(mailbox)->close_mailbox(mailbox, expunge);
+        gdk_threads_enter();
         if(mailbox->msg_tree) {
             g_node_destroy(mailbox->msg_tree);
             mailbox->msg_tree = NULL;
         }
+        gdk_threads_leave();
         libbalsa_mailbox_free_mindex(mailbox);
         mailbox->stamp++;
 	mailbox->state = LB_MAILBOX_STATE_CLOSED;
@@ -1339,21 +1349,18 @@ libbalsa_mailbox_msgno_changed(LibBalsaMailbox * mailbox, guint seqno)
         gdk_threads_leave();
 }
 
-static void
-lbm_msgno_inserted(LibBalsaMailbox *mailbox, guint seqno, GNode * parent,
-                   GNode ** sibling)
+void
+libbalsa_mailbox_msgno_inserted(LibBalsaMailbox *mailbox, guint seqno,
+                                GNode * parent, GNode ** sibling)
 {
     GtkTreeIter iter;
     GtkTreePath *path;
     GSList **unthreaded;
 
-    gdk_threads_enter();
-
-    if (!mailbox->msg_tree) {
-        gdk_threads_leave();
+    if (!libbalsa_threads_has_lock())
+        g_warning("Thread is not holding gdk lock");
+    if (!mailbox->msg_tree)
         return;
-    }
-
 #undef SANITY_CHECK
 #ifdef SANITY_CHECK
     g_return_if_fail(!g_node_find(mailbox->msg_tree,
@@ -1382,91 +1389,6 @@ lbm_msgno_inserted(LibBalsaMailbox *mailbox, guint seqno, GNode * parent,
             g_slist_prepend(*unthreaded, GUINT_TO_POINTER(seqno));
 
     mailbox->msg_tree_changed = TRUE;
-
-    gdk_threads_leave();
-}
-
-#ifdef BALSA_USE_THREADS
-typedef struct {
-#if GLIB_CHECK_VERSION(2, 32, 0)
-    GMutex mutex;
-    GCond cond;
-#else                           /* GLIB_CHECK_VERSION(2, 32, 0) */
-    GMutex *mutex;
-    GCond *cond;
-#endif                          /* GLIB_CHECK_VERSION(2, 32, 0) */
-    LibBalsaMailbox *mailbox;
-    guint seqno;
-    GNode *parent;
-    GNode **sibling;
-    gboolean wait;
-} LbmMsgnoInsertedInfo;
-
-static gboolean
-lbm_msgno_inserted_idle_cb(LbmMsgnoInsertedInfo * info)
-{
-#if GLIB_CHECK_VERSION(2, 32, 0)
-    g_mutex_lock(&info->mutex);
-#else                           /* GLIB_CHECK_VERSION(2, 32, 0) */
-    g_mutex_lock(info->mutex);
-#endif                          /* GLIB_CHECK_VERSION(2, 32, 0) */
-
-    lbm_msgno_inserted(info->mailbox, info->seqno, info->parent,
-                       info->sibling);
-    info->wait = FALSE;
-
-#if GLIB_CHECK_VERSION(2, 32, 0)
-    g_cond_signal(&info->cond);
-    g_mutex_unlock(&info->mutex);
-#else                           /* GLIB_CHECK_VERSION(2, 32, 0) */
-    g_cond_signal(info->cond);
-    g_mutex_unlock(info->mutex);
-#endif                          /* GLIB_CHECK_VERSION(2, 32, 0) */
-
-    return FALSE;
-}
-#endif                          /* BALSA_USE_THREADS */
-
-void
-libbalsa_mailbox_msgno_inserted(LibBalsaMailbox *mailbox, guint seqno,
-                                GNode * parent, GNode ** sibling)
-{
-#ifdef BALSA_USE_THREADS
-    if (libbalsa_am_i_subthread()) {
-        LbmMsgnoInsertedInfo info;
-
-        info.mailbox = g_object_ref(mailbox);
-        info.seqno = seqno;
-        info.parent = parent;
-        info.sibling = sibling;
-        info.wait = TRUE;
-#if GLIB_CHECK_VERSION(2, 32, 0)
-        g_mutex_init(&info.mutex);
-        g_cond_init(&info.cond);
-        g_mutex_lock(&info.mutex);
-        g_idle_add((GSourceFunc) lbm_msgno_inserted_idle_cb, &info);
-        while (info.wait)
-            g_cond_wait(&info.cond, &info.mutex);
-        g_mutex_unlock(&info.mutex);
-        g_mutex_clear(&info.mutex);
-        g_cond_clear(&info.cond);
-#else                           /* GLIB_CHECK_VERSION(2, 32, 0) */
-        info.mutex = g_mutex_new();
-        info.cond = g_cond_new();
-        g_mutex_lock(info.mutex);
-        g_idle_add((GSourceFunc) lbm_msgno_inserted_idle_cb, &info);
-        while (info.wait)
-            g_cond_wait(info.cond, info.mutex);
-        g_mutex_unlock(info.mutex);
-        g_mutex_free(info.mutex);
-        g_cond_free(info.cond);
-#endif                          /* GLIB_CHECK_VERSION(2, 32, 0) */
-        g_object_unref(mailbox);
-    } else
-        lbm_msgno_inserted(mailbox, seqno, parent, sibling);
-#else                           /* BALSA_USE_THREADS */
-    lbm_msgno_inserted(mailbox, seqno, parent, sibling);
-#endif                          /* BALSA_USE_THREADS */
 }
 
 static void
@@ -1497,23 +1419,6 @@ libbalsa_mailbox_msgno_filt_in(LibBalsaMailbox *mailbox, guint seqno)
     gdk_threads_leave();
 }
 
-#ifdef BALSA_USE_THREADS
-/*
- * Handler for "message-expunged" signal
- *
- * Adjust msgno; it will be invalid (zero) if msgno was expunged.
- */
-static void
-lbm_message_expunged_cb(LibBalsaMailbox * mailbox, guint expunged_msgno,
-                        guint * msgno)
-{
-    if (*msgno > expunged_msgno)
-        --*msgno;
-    else if (*msgno == expunged_msgno)
-        *msgno = 0;
-}
-#endif                          /* BALSA_USE_THREADS */
-
 /*
  * libbalsa_mailbox_msgno_removed and helpers
  */
@@ -1534,8 +1439,8 @@ decrease_post(GNode *node, gpointer data)
     return FALSE;
 }
 
-static void
-lbm_msgno_removed(LibBalsaMailbox * mailbox, guint seqno)
+void
+libbalsa_mailbox_msgno_removed(LibBalsaMailbox * mailbox, guint seqno)
 {
     GtkTreeIter iter;
     GtkTreePath *path;
@@ -1623,50 +1528,6 @@ lbm_msgno_removed(LibBalsaMailbox * mailbox, guint seqno)
     gdk_threads_leave();
 }
 
-#ifdef BALSA_USE_THREADS
-typedef struct {
-    LibBalsaMailbox *mailbox;
-    guint seqno;
-    gulong expunged_cb_handler_id;
-} LbmMsgnoRemovedInfo;
-
-static gboolean
-lbm_msgno_removed_idle_cb(LbmMsgnoRemovedInfo * info)
-{
-    g_signal_handler_disconnect(info->mailbox,
-                                info->expunged_cb_handler_id);
-    if (info->seqno)
-        lbm_msgno_removed(info->mailbox, info->seqno);
-    g_object_unref(info->mailbox);
-    g_slice_free(LbmMsgnoRemovedInfo, info);
-    return FALSE;
-}
-#endif                          /* BALSA_USE_THREADS */
-
-void
-libbalsa_mailbox_msgno_removed(LibBalsaMailbox * mailbox, guint seqno)
-{
-#ifdef BALSA_USE_THREADS
-    if (libbalsa_am_i_subthread()) {
-        LbmMsgnoRemovedInfo *info;
-
-        info = g_slice_new(LbmMsgnoRemovedInfo);
-        info->mailbox = g_object_ref(mailbox);
-        info->seqno = seqno;
-        info->expunged_cb_handler_id =
-            g_signal_connect(mailbox, "message-expunged",
-                             G_CALLBACK(lbm_message_expunged_cb),
-                             &info->seqno);
-        g_idle_add((GSourceFunc) lbm_msgno_removed_idle_cb,
-                             info);
-    } else {
-        lbm_msgno_removed(mailbox, seqno);
-    }
-#else                           /* BALSA_USE_THREADS */
-    lbm_msgno_removed(mailbox, seqno);
-#endif                          /* BALSA_USE_THREADS */
-}
-
 static void
 libbalsa_mailbox_msgno_filt_out(LibBalsaMailbox * mailbox, GNode * node)
 {
@@ -1734,14 +1595,16 @@ libbalsa_mailbox_msgno_filt_out(LibBalsaMailbox * mailbox, GNode * node)
  *   messages;
  * - if it isn't in the view and it matches the condition, filter it in.
  */
-static void
-lbm_msgno_filt_check(LibBalsaMailbox * mailbox, guint seqno,
-                     LibBalsaMailboxSearchIter * search_iter,
-                     gboolean hold_selected)
+void
+libbalsa_mailbox_msgno_filt_check(LibBalsaMailbox * mailbox, guint seqno,
+                                  LibBalsaMailboxSearchIter * search_iter,
+                                  gboolean hold_selected)
 {
     gboolean match;
     GNode *node;
 
+    g_return_if_fail(LIBBALSA_IS_MAILBOX(mailbox));
+
     gdk_threads_enter();
 
     if (!mailbox->msg_tree) {
@@ -1780,58 +1643,6 @@ lbm_msgno_filt_check(LibBalsaMailbox * mailbox, guint seqno,
     gdk_threads_leave();
 }
 
-#ifdef BALSA_USE_THREADS
-typedef struct {
-    LibBalsaMailbox *mailbox;
-    guint seqno;
-    LibBalsaMailboxSearchIter *search_iter;
-    gboolean hold_selected;
-    gulong expunged_cb_handler_id;
-} LbmMsgnoFiltCheckInfo;
-
-static gboolean
-lbm_msgno_filt_check_idle_cb(LbmMsgnoFiltCheckInfo * info)
-{
-    g_signal_handler_disconnect(info->mailbox,
-                                info->expunged_cb_handler_id);
-    if (info->seqno)
-        lbm_msgno_filt_check(info->mailbox, info->seqno, info->search_iter,
-                             info->hold_selected);
-    g_object_unref(info->mailbox);
-    libbalsa_mailbox_search_iter_unref(info->search_iter);
-    g_slice_free(LbmMsgnoFiltCheckInfo, info);
-    return FALSE;
-}
-#endif                          /* BALSA_USE_THREADS */
-
-void
-libbalsa_mailbox_msgno_filt_check(LibBalsaMailbox * mailbox, guint seqno,
-                                  LibBalsaMailboxSearchIter * search_iter,
-                                  gboolean hold_selected)
-{
-    g_return_if_fail(LIBBALSA_IS_MAILBOX(mailbox));
-
-#ifdef BALSA_USE_THREADS
-    if (libbalsa_am_i_subthread()) {
-        LbmMsgnoFiltCheckInfo *info;
-
-        info = g_slice_new(LbmMsgnoFiltCheckInfo);
-        info->mailbox = g_object_ref(mailbox);
-        info->seqno = seqno;
-        info->expunged_cb_handler_id =
-            g_signal_connect(mailbox, "message-expunged",
-                             G_CALLBACK(lbm_message_expunged_cb),
-                             &info->seqno);
-        info->search_iter = libbalsa_mailbox_search_iter_ref(search_iter);
-        info->hold_selected = hold_selected;
-        g_idle_add((GSourceFunc) lbm_msgno_filt_check_idle_cb, info);
-    } else
-        lbm_msgno_filt_check(mailbox, seqno, search_iter, hold_selected);
-#else                           /* BALSA_USE_THREADS */
-    lbm_msgno_filt_check(mailbox, seqno, search_iter, hold_selected);
-#endif                          /* BALSA_USE_THREADS */
-}
-
 /* Search iters */
 LibBalsaMailboxSearchIter *
 libbalsa_mailbox_search_iter_new(LibBalsaCondition * condition)
@@ -2116,18 +1927,13 @@ lbm_cache_message(LibBalsaMailbox * mailbox, guint msgno,
 
     entry = g_ptr_array_index(mailbox->mindex, msgno - 1);
 
-    if (!entry) {
-        /* Assign pointer in mailbox->mindex before populating the
-         * entry, because we may recursively enter lbm_cache_message
-         * while populating it. */
+    if (!entry)
         g_ptr_array_index(mailbox->mindex, msgno - 1) =
-            entry = g_new0(LibBalsaMailboxIndexEntry, 1);
-        lbm_index_entry_populate_from_msg(entry, message);
+            lbm_index_entry_new_from_msg(message);
 #if BALSA_USE_THREADS
-    } else if (entry->idle_pending) {
+    else if (entry->idle_pending)
         lbm_index_entry_populate_from_msg(entry, message);
 #endif                          /* BALSA_USE_THREADS */
-    }
 }
 
 LibBalsaMessage *
diff --git a/libbalsa/mailbox_local.c b/libbalsa/mailbox_local.c
index 8eccfa6..5dbb08f 100644
--- a/libbalsa/mailbox_local.c
+++ b/libbalsa/mailbox_local.c
@@ -1023,8 +1023,11 @@ libbalsa_mailbox_local_load_messages(LibBalsaMailbox *mailbox,
 
     g_return_if_fail(LIBBALSA_IS_MAILBOX_LOCAL(mailbox));
 
+    gdk_threads_enter();
+
     if (!mailbox->msg_tree) {
 	/* Mailbox is closed, or no view has been created. */
+        gdk_threads_leave();
 	return;
     }
 
@@ -1043,6 +1046,8 @@ libbalsa_mailbox_local_load_messages(LibBalsaMailbox *mailbox,
                                                  msg_info->message);
     }
 
+    gdk_threads_leave();
+
     if (new_messages) {
 	libbalsa_mailbox_run_filters_on_reception(mailbox);
 	libbalsa_mailbox_set_unread_messages_flag(mailbox,
diff --git a/src/balsa-app.c b/src/balsa-app.c
index ededebd..828f27b 100644
--- a/src/balsa-app.c
+++ b/src/balsa-app.c
@@ -694,8 +694,8 @@ balsa_find_dir(LibBalsaServer *server, const gchar * path)
 }
 
 static gint
-find_url_func(GtkTreeModel * model, GtkTreePath * path, GtkTreeIter * iter,
-              BalsaFind * bf)
+find_url(GtkTreeModel * model, GtkTreePath * path, GtkTreeIter * iter,
+	 BalsaFind * bf)
 {
     BalsaMailboxNode *mbnode;
     LibBalsaMailbox *mailbox;
@@ -715,8 +715,8 @@ find_url_func(GtkTreeModel * model, GtkTreePath * path, GtkTreeIter * iter,
  * returns NULL on failure; caller must unref mbnode when non-NULL.
  */
 
-static BalsaMailboxNode *
-find_url(const gchar * url)
+BalsaMailboxNode *
+balsa_find_url(const gchar * url)
 {
     BalsaFind bf;
 
@@ -726,7 +726,7 @@ find_url(const gchar * url)
     bf.mbnode = NULL;
     if (balsa_app.mblist_tree_store)
         gtk_tree_model_foreach(GTK_TREE_MODEL(balsa_app.mblist_tree_store),
-                               (GtkTreeModelForeachFunc) find_url_func,
+                               (GtkTreeModelForeachFunc) find_url,
                                &bf);
 
     gdk_threads_leave();
@@ -734,83 +734,6 @@ find_url(const gchar * url)
     return bf.mbnode;
 }
 
-#ifdef BALSA_USE_THREADS
-typedef struct {
-    const gchar * url;
-#if GLIB_CHECK_VERSION(2, 32, 0)
-    GMutex mutex;
-    GCond cond;
-#else                           /* GLIB_CHECK_VERSION(2, 32, 0) */
-    GMutex *mutex;
-    GCond *cond;
-#endif                          /* GLIB_CHECK_VERSION(2, 32, 0) */
-    gboolean wait;
-    BalsaMailboxNode *mbnode;
-} BalsaFindUrlInfo;
-
-static gboolean
-find_url_idle_cb(BalsaFindUrlInfo * info)
-{
-#if GLIB_CHECK_VERSION(2, 32, 0)
-    g_mutex_lock(&info->mutex);
-
-    info->mbnode = find_url(info->url);
-    info->wait = FALSE;
-
-    g_cond_signal(&info->cond);
-    g_mutex_unlock(&info->mutex);
-#else                           /* GLIB_CHECK_VERSION(2, 32, 0) */
-    g_mutex_lock(info->mutex);
-
-    info->mbnode = find_url(info->url);
-    info->wait = FALSE;
-
-    g_cond_signal(info->cond);
-    g_mutex_unlock(info->mutex);
-#endif                          /* GLIB_CHECK_VERSION(2, 32, 0) */
-
-    return FALSE;
-}
-#endif                          /* BALSA_USE_THREADS */
-
-BalsaMailboxNode *
-balsa_find_url(const gchar * url)
-{
-#ifdef BALSA_USE_THREADS
-    if (libbalsa_am_i_subthread()) {
-        BalsaFindUrlInfo info;
-
-        info.url = url;
-        info.wait = TRUE;
-#if GLIB_CHECK_VERSION(2, 32, 0)
-        g_mutex_init(&info.mutex);
-        g_cond_init(&info.cond);
-        g_mutex_lock(&info.mutex);
-        g_idle_add((GSourceFunc) find_url_idle_cb, &info);
-        while (info.wait)
-            g_cond_wait(&info.cond, &info.mutex);
-        g_mutex_unlock(&info.mutex);
-        g_mutex_clear(&info.mutex);
-        g_cond_clear(&info.cond);
-#else                           /* GLIB_CHECK_VERSION(2, 32, 0) */
-        info.mutex = g_mutex_new();
-        info.cond = g_cond_new();
-        g_mutex_lock(info.mutex);
-        g_idle_add((GSourceFunc) find_url_idle_cb, &info);
-        while (info.wait)
-            g_cond_wait(info.cond, info.mutex);
-        g_mutex_unlock(info.mutex);
-        g_mutex_free(info.mutex);
-        g_cond_free(info.cond);
-#endif                          /* GLIB_CHECK_VERSION(2, 32, 0) */
-        return info.mbnode;
-    } else
-        return find_url(url);
-#else                           /* BALSA_USE_THREADS */
-    return find_url(url);
-#endif                          /* BALSA_USE_THREADS */
-}
-
 /* balsa_find_mailbox_by_url:
  * looks for a mailbox with the given url.
  * returns NULL on failure
diff --git a/src/balsa-index.c b/src/balsa-index.c
index 0a8ca25..79365c4 100644
--- a/src/balsa-index.c
+++ b/src/balsa-index.c
@@ -885,7 +885,7 @@ bi_view_on_open(struct view_on_open_data *data)
     return FALSE;
 }
 
-static void
+void
 balsa_index_scroll_on_open(BalsaIndex *index)
 {
     LibBalsaMailbox *mailbox = index->mailbox_node->mailbox;
@@ -1006,151 +1006,90 @@ bndx_mailbox_message_expunged_cb(LibBalsaMailbox * mailbox, guint msgno,
         --bindex->next_msgno;
 }
 
-/*
- * balsa_index_load_mailbox_node:
- */
-
-typedef struct {
-    BalsaIndex *index;
-    BalsaMailboxNode *mbnode;
-    GError *err;
-    gboolean successp;
-} bndx_open_mailbox_info;
+/* balsa_index_load_mailbox_node:
+   open mailbox_node, the opening is done in thread to keep UI alive.
 
-/* Idle callback to complete opening a mailbox */
+   Called NOT holding the gdk lock, so we must wrap gtk calls in
+   gdk_threads_{enter,leave}.
+*/
 
-static gboolean
-bndx_set_mailbox(bndx_open_mailbox_info * info)
+gboolean
+balsa_index_load_mailbox_node(BalsaIndex * index,
+                              BalsaMailboxNode* mbnode, GError **err)
 {
     GtkTreeView *tree_view;
     LibBalsaMailbox *mailbox;
+    gboolean successp;
+    gint try_cnt;
 
-    if (!info->successp) {
-        libbalsa_information(LIBBALSA_INFORMATION_ERROR,
-                             _("Unable to Open Mailbox!\n%s."),
-                             info->err ?
-                             info->err->message : _("Unknown error"));
-        g_error_free(info->err);
-        g_object_unref(g_object_ref_sink(info->index));
-        g_free(info);
+    g_return_val_if_fail(BALSA_IS_INDEX(index), TRUE);
+    g_return_val_if_fail(index->mailbox_node == NULL, TRUE);
+    g_return_val_if_fail(BALSA_IS_MAILBOX_NODE(mbnode), TRUE);
+    g_return_val_if_fail(LIBBALSA_IS_MAILBOX(mbnode->mailbox), TRUE);
 
-        return FALSE;
-    }
+    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
      */
-    info->index->mailbox_node = info->mbnode;
-    g_object_weak_ref(G_OBJECT(info->mbnode),
-                      (GWeakNotify) bndx_mbnode_weak_notify, info->index);
+    index->mailbox_node = mbnode;
+    g_object_weak_ref(G_OBJECT(mbnode),
+                      (GWeakNotify) bndx_mbnode_weak_notify, index);
     /*
      * rename "from" column to "to" for outgoing mail
      */
-    tree_view = GTK_TREE_VIEW(info->index);
-    mailbox = info->mbnode->mailbox;
+    gdk_threads_enter();
+    tree_view = GTK_TREE_VIEW(index);
     if (libbalsa_mailbox_get_show(mailbox) == LB_MAILBOX_SHOW_TO) {
         GtkTreeViewColumn *column =
-            gtk_tree_view_get_column(tree_view, LB_MBOX_FROM_COL);
-        info->index->filter_no = 1;     /* FIXME: this is hack! */
+	    gtk_tree_view_get_column(tree_view, LB_MBOX_FROM_COL);
+        index->filter_no = 1; /* FIXME: this is hack! */
         gtk_tree_view_column_set_title(column, _("To"));
     }
 
     g_signal_connect_swapped(G_OBJECT(mailbox), "changed",
-                             G_CALLBACK(bndx_mailbox_changed_cb),
-                             info->index);
+			     G_CALLBACK(bndx_mailbox_changed_cb),
+			     (gpointer) index);
     g_signal_connect(mailbox, "row-inserted",
-                     G_CALLBACK(bndx_mailbox_row_inserted_cb),
-                     info->index);
+                     G_CALLBACK(bndx_mailbox_row_inserted_cb), index);
     g_signal_connect(mailbox, "message-expunged",
-                     G_CALLBACK(bndx_mailbox_message_expunged_cb),
-                     info->index);
+                     G_CALLBACK(bndx_mailbox_message_expunged_cb), index);
 
     /* Set the tree store */
 #ifndef GTK2_FETCHES_ONLY_VISIBLE_CELLS
     g_object_set_data(G_OBJECT(mailbox), "tree-view", tree_view);
 #endif
     gtk_tree_view_set_model(tree_view, GTK_TREE_MODEL(mailbox));
+    gdk_threads_leave();
 
     /* Create a search-iter for SEARCH UNDELETED. */
     if (!cond_undeleted)
         cond_undeleted =
             libbalsa_condition_new_flag_enum(TRUE,
                                              LIBBALSA_MESSAGE_FLAG_DELETED);
-    info->index->search_iter =
-        libbalsa_mailbox_search_iter_new(cond_undeleted);
+    index->search_iter = libbalsa_mailbox_search_iter_new(cond_undeleted);
     /* Note when this mailbox was opened, for use in auto-closing. */
-    time(&info->index->mailbox_node->last_use);
-
-    balsa_index_scroll_on_open(info->index);
-
-    g_free(info);
+    time(&index->mailbox_node->last_use);
 
     return FALSE;
 }
 
-/*
- * Subthread to do the actual opening
- */
-static void
-bndx_open_mailbox(bndx_open_mailbox_info * info)
-{
-    gint try_cnt;
-    LibBalsaMailbox *mailbox;
-
-    mailbox = info->mbnode->mailbox;
-
-    info->err = NULL;
-    try_cnt = 0;
-    do {
-        g_clear_error(&info->err);
-        info->successp = libbalsa_mailbox_open(mailbox, &info->err);
-        if (!balsa_app.main_window)
-            return;
-
-        if (info->successp)
-            break;
-        if (info->err &&
-            info->err->code != LIBBALSA_MAILBOX_TOOMANYOPEN_ERROR)
-            break;
-        balsa_mblist_close_lru_peer_mbx(balsa_app.mblist, mailbox);
-    } while (try_cnt++ < 3);
-
-#ifdef BALSA_USE_THREADS
-    gdk_threads_add_idle((GSourceFunc) bndx_set_mailbox, info);
-
-    pthread_exit(0);
-#else                           /* BALSA_USE_THREADS */
-    bndx_set_mailbox(info);
-#endif                          /* BALSA_USE_THREADS */
-}
-
-void
-balsa_index_load_mailbox_node (BalsaIndex * index,
-                               BalsaMailboxNode* mbnode)
-{
-    bndx_open_mailbox_info *info;
-#ifdef BALSA_USE_THREADS
-    pthread_t open_thread;
-#endif                          /* BALSA_USE_THREADS */
-
-    g_return_if_fail(BALSA_IS_INDEX(index));
-    g_return_if_fail(index->mailbox_node == NULL);
-    g_return_if_fail(BALSA_IS_MAILBOX_NODE(mbnode));
-    g_return_if_fail(LIBBALSA_IS_MAILBOX(mbnode->mailbox));
-
-    info = g_new(bndx_open_mailbox_info, 1);
-    info->index = index;
-    info->mbnode = mbnode;
-
-#ifdef BALSA_USE_THREADS
-    pthread_create(&open_thread, NULL,
-                   (void*(*)(void*))bndx_open_mailbox, info);
-    pthread_detach(open_thread);
-#else                           /* BALSA_USE_THREADS */
-    bndx_open_mailbox(info);
-#endif                          /* BALSA_USE_THREADS */
-}
-
 void
 balsa_index_set_width_preference(BalsaIndex *bindex,
                                  BalsaIndexWidthPreference pref)
diff --git a/src/balsa-index.h b/src/balsa-index.h
index f69f679..dc5ab15 100644
--- a/src/balsa-index.h
+++ b/src/balsa-index.h
@@ -105,10 +105,12 @@ extern "C" {
 
 /* sets the mail stream; if it's a new stream, then it's 
  * contents is loaded into the index */
-    void balsa_index_load_mailbox_node(BalsaIndex * bindex,
-                                       BalsaMailboxNode * mbnode);
+    gboolean balsa_index_load_mailbox_node(BalsaIndex * bindex,
+                                           BalsaMailboxNode * mbnode,
+					   GError **err);
     void balsa_index_set_width_preference(BalsaIndex *bindex,
                                           BalsaIndexWidthPreference pref);
+    void balsa_index_scroll_on_open(BalsaIndex *index);
     void balsa_index_update_tree(BalsaIndex *bindex, gboolean expand);
     void balsa_index_set_threading_type(BalsaIndex * bindex, int thtype);
     void balsa_index_set_view_filter(BalsaIndex *bindex,
diff --git a/src/main-window.c b/src/main-window.c
index 5591c73..0874dd5 100644
--- a/src/main-window.c
+++ b/src/main-window.c
@@ -2323,20 +2323,22 @@ bw_notebook_label_new(BalsaMailboxNode * mbnode)
     return box;
 }
 
-/* Class method */
+/* Called with the gdk lock held (when threads are enabled). */
 static void
-balsa_window_real_open_mbnode(BalsaWindow * window,
-                              BalsaMailboxNode * mbnode,
-                              gboolean set_current)
+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;
 
-    if (bw_is_open_mailbox(mailbox = mbnode->mailbox))
+    /* FIXME: the check is not needed in non-MT-mode */
+    if (!window || bw_is_open_mailbox(mailbox = mbnode->mailbox))
         return;
 
     index = BALSA_INDEX(balsa_index_new());
@@ -2345,16 +2347,36 @@ balsa_window_real_open_mbnode(BalsaWindow * window,
          (balsa_app.layout_type == LAYOUT_WIDE_SCREEN)
          ? BALSA_INDEX_NARROW : BALSA_INDEX_WIDE);
 
+    g_object_add_weak_pointer(G_OBJECT(window), (gpointer) &window);
     message = g_strdup_printf(_("Opening %s"), mailbox->name);
     balsa_window_increase_activity(window, message);
-    balsa_index_load_mailbox_node(index, mbnode);
-    balsa_window_decrease_activity(window, message);
+
+    /* 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();
+
+    if (window) {
+        balsa_window_decrease_activity(window, message);
+        g_object_remove_weak_pointer(G_OBJECT(window), (gpointer) &window);
+    }
     g_free(message);
 
-    index->mailbox_node = mbnode;
+    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);
 
+    /* if(config_short_label) label = gtk_label_new(mbnode->mailbox->name);
+       else */
     label = bw_notebook_label_new(mbnode);
 
     /* store for easy access */
@@ -2385,6 +2407,82 @@ balsa_window_real_open_mbnode(BalsaWindow * window,
     libbalsa_mailbox_set_threading(mailbox,
                                    libbalsa_mailbox_get_threading_type
                                    (mailbox));
+    balsa_index_scroll_on_open(index);
+}
+
+#ifdef BALSA_USE_THREADS
+static pthread_mutex_t open_lock = PTHREAD_MUTEX_INITIALIZER;
+
+struct bw_open_mbnode_info {
+    BalsaWindow *window;
+    BalsaMailboxNode * mbnode;
+    gboolean set_current;
+};
+
+static void
+bw_real_open_mbnode_thread(GPtrArray *info_array)
+{
+    guint i;
+
+    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+    pthread_mutex_lock(&open_lock);
+
+    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();
+
+        bw_real_open_mbnode(info->window, info->mbnode, info->set_current);
+
+	if (info->window)
+            g_object_remove_weak_pointer(G_OBJECT(info->window),
+                                         (gpointer) &info->window);
+        g_object_unref(info->mbnode);
+
+        gdk_threads_leave();
+        g_free(info);
+        pthread_mutex_lock(&open_lock);
+    }
+
+    info_array->len = 0;
+    pthread_mutex_unlock(&open_lock);
+}
+#endif
+
+static void
+balsa_window_real_open_mbnode(BalsaWindow * window,
+                              BalsaMailboxNode * mbnode,
+                              gboolean set_current)
+{
+#ifdef BALSA_USE_THREADS
+    struct bw_open_mbnode_info *info;
+    static GPtrArray *info_array;
+
+    info = g_new(struct bw_open_mbnode_info, 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
 }
 
 /* balsa_window_real_close_mbnode:
@@ -3029,15 +3127,6 @@ bw_mailbox_check(LibBalsaMailbox * mailbox, BalsaWindow * window)
     libbalsa_mailbox_check(mailbox);
 }
 
-static gboolean
-bw_check_messages_thread_idle(BalsaWindow * window)
-{
-    bw_set_sensitive(window, "GetNewMail", TRUE);
-    g_object_unref(window);
-
-    return FALSE;
-}
-
 static void
 bw_check_messages_thread(struct check_messages_thread_info *info)
 {
@@ -3065,12 +3154,14 @@ bw_check_messages_thread(struct check_messages_thread_info *info)
     checking_mail = 0;
 
     if (info->window) {
-        gdk_threads_add_idle((GSourceFunc) bw_check_messages_thread_idle,
-                             info->window);
+        gdk_threads_enter();
+        bw_set_sensitive(info->window, "GetNewMail", TRUE);
 #if defined(HAVE_LIBNM_GLIB)
         if (info->window->nm_state == NM_STATE_CONNECTED)
             time(&info->window->last_check_time);
 #endif                          /* defined(HAVE_LIBNM_GLIB) */
+        g_object_unref(info->window);
+        gdk_threads_leave();
     }
     pthread_mutex_unlock(&checking_mail_lock);
 
diff --git a/src/main.c b/src/main.c
index cf773a4..7c4676f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -486,8 +486,8 @@ periodic_expunge_cb(void)
 static GTimeVal prev_time_val;
 static gdouble  min_fraction;
 static void
-progress_set_text(LibBalsaProgress * progress, const gchar * text,
-                  guint total)
+balsa_progress_set_text(LibBalsaProgress * progress, const gchar * text,
+                        guint total)
 {
     gboolean rc = FALSE;
 
@@ -508,53 +508,12 @@ progress_set_text(LibBalsaProgress * progress, const gchar * text,
         LIBBALSA_PROGRESS_YES : LIBBALSA_PROGRESS_NO;
 }
 
-#ifdef BALSA_USE_THREADS
-typedef struct {
-    LibBalsaProgress *progress;
-    const gchar *text;
-    guint total;
-    gdouble fraction;
-} BalsaProgressSetTextInfo;
-
-static gboolean
-progress_set_text_idle_cb(BalsaProgressSetTextInfo * info)
-{
-    progress_set_text(info->progress, info->text, info->total);
-
-    g_free(info);
-
-    return FALSE;
-}
-#endif                          /* BALSA_USE_THREADS */
-
-static void
-balsa_progress_set_text(LibBalsaProgress * progress, const gchar * text,
-                        guint total)
-{
-#ifdef BALSA_USE_THREADS
-    if (libbalsa_am_i_subthread()) {
-        BalsaProgressSetTextInfo *info;
-
-        info = g_new(BalsaProgressSetTextInfo, 1);
-        info->progress = progress;
-        info->text = text;
-        info->total = total;
-
-        gdk_threads_add_idle((GSourceFunc) progress_set_text_idle_cb,
-                             info);
-    } else
-        progress_set_text(progress, text, total);
-#else                           /* BALSA_USE_THREADS */
-    progress_set_text(progress, text, total);
-#endif                          /* BALSA_USE_THREADS */
-}
-
 /*
  * Set the fraction in the progress bar.
  */
 
 static void
-progress_set_fraction(LibBalsaProgress * progress, gdouble fraction)
+balsa_progress_set_fraction(LibBalsaProgress * progress, gdouble fraction)
 {
     GTimeVal time_val;
     guint elapsed;
@@ -582,38 +541,6 @@ progress_set_fraction(LibBalsaProgress * progress, gdouble fraction)
     gdk_threads_leave();
 }
 
-#ifdef BALSA_USE_THREADS
-static gboolean
-progress_set_fraction_idle_cb(BalsaProgressSetTextInfo * info)
-{
-    progress_set_fraction(info->progress, info->fraction);
-
-    g_free(info);
-
-    return FALSE;
-}
-#endif                          /* BALSA_USE_THREADS */
-
-static void
-balsa_progress_set_fraction(LibBalsaProgress * progress, gdouble fraction)
-{
-#ifdef BALSA_USE_THREADS
-    if (libbalsa_am_i_subthread()) {
-        BalsaProgressSetTextInfo *info;
-
-        info = g_new(BalsaProgressSetTextInfo, 1);
-        info->progress = progress;
-        info->fraction = fraction;
-
-        gdk_threads_add_idle((GSourceFunc) progress_set_fraction_idle_cb,
-                             info);
-    } else
-        progress_set_fraction(progress, fraction);
-#else                           /* BALSA_USE_THREADS */
-    progress_set_fraction(progress, fraction);
-#endif                          /* BALSA_USE_THREADS */
-}
-
 static void
 balsa_progress_set_activity(gboolean set, const gchar * text)
 {



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