[balsa/gtk3] Call Gtk from only the main thread to open mailbox
- From: Peter Bloomfield <PeterB src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [balsa/gtk3] Call Gtk from only the main thread to open mailbox
- Date: Sun, 3 Jun 2012 20:23:17 +0000 (UTC)
commit ca88b30387d3aaf9dbeef149d6ca3e758742146a
Author: Peter Bloomfield <PeterBloomfield bellsouth net>
Date: Sun Jun 3 13:07:13 2012 -0400
Call Gtk from only the main thread to open mailbox
* libbalsa/mailbox.c (lbm_cache_message): avoid infinite
recursion.
* libbalsa/mailbox.h: do not export
libbalsa_mailbox_index_entry_new_from_msg.
* src/balsa-index.c (bndx_set_mailbox), (bndx_open_mailbox),
(balsa_index_load_mailbox_node): open mailbox in a subthread.
* src/balsa-index.h: do not export balsa_index_load_mailbox_node
and balsa_index_scroll_on_open.
* src/main-window.c: start opening mailbox in the main thread.
ChangeLog | 14 +++++
libbalsa/mailbox.c | 19 +++----
libbalsa/mailbox.h | 2 -
src/balsa-index.c | 157 ++++++++++++++++++++++++++++++++++++----------------
src/balsa-index.h | 6 +-
src/main-window.c | 114 +++-----------------------------------
6 files changed, 141 insertions(+), 171 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index cabe47f..0d1c50e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2012-06-03 Peter Bloomfield
+
+ Call Gtk from only the main thread when opening a mailbox
+
+ * libbalsa/mailbox.c (lbm_cache_message): avoid infinite
+ recursion.
+ * libbalsa/mailbox.h: do not export
+ libbalsa_mailbox_index_entry_new_from_msg.
+ * src/balsa-index.c (bndx_set_mailbox), (bndx_open_mailbox),
+ (balsa_index_load_mailbox_node): open mailbox in a subthread.
+ * src/balsa-index.h: do not export balsa_index_load_mailbox_node
+ and balsa_index_scroll_on_open.
+ * src/main-window.c: start opening mailbox in the main thread.
+
2012-05-28 Peter Bloomfield
* src/balsa-index.c (bi_view_on_open,
diff --git a/libbalsa/mailbox.c b/libbalsa/mailbox.c
index be4a732..073222e 100644
--- a/libbalsa/mailbox.c
+++ b/libbalsa/mailbox.c
@@ -367,14 +367,6 @@ lbm_index_entry_populate_from_msg(LibBalsaMailboxIndexEntry * entry,
libbalsa_mailbox_msgno_changed(msg->mailbox, msg->msgno);
}
-LibBalsaMailboxIndexEntry*
-libbalsa_mailbox_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)
@@ -1913,13 +1905,18 @@ lbm_cache_message(LibBalsaMailbox * mailbox, guint msgno,
entry = g_ptr_array_index(mailbox->mindex, msgno - 1);
- if (!entry)
+ if (!entry) {
+ /* Assign pointer in mailbox->mindex before populating the
+ * entry, because we may recursively enter lbm_cache_message
+ * while populating it. */
g_ptr_array_index(mailbox->mindex, msgno - 1) =
- libbalsa_mailbox_index_entry_new_from_msg(message);
+ entry = g_new0(LibBalsaMailboxIndexEntry, 1);
+ lbm_index_entry_populate_from_msg(entry, 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.h b/libbalsa/mailbox.h
index c90a1a0..fd217f3 100644
--- a/libbalsa/mailbox.h
+++ b/libbalsa/mailbox.h
@@ -502,8 +502,6 @@ gint libbalsa_mailbox_move_duplicates(LibBalsaMailbox * mailbox,
* Mailbox views-related functions.
*/
typedef struct LibBalsaMailboxIndexEntry_ LibBalsaMailboxIndexEntry;
-LibBalsaMailboxIndexEntry* libbalsa_mailbox_index_entry_new_from_msg
- (LibBalsaMessage *msg);
void libbalsa_mailbox_index_entry_set_no(LibBalsaMailboxIndexEntry *entry,
unsigned no);
void libbalsa_mailbox_index_entry_clear(LibBalsaMailbox * mailbox,
diff --git a/src/balsa-index.c b/src/balsa-index.c
index 5627d73..c52396d 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;
}
-void
+static void
balsa_index_scroll_on_open(BalsaIndex *index)
{
LibBalsaMailbox *mailbox = index->mailbox_node->mailbox;
@@ -1006,90 +1006,151 @@ bndx_mailbox_message_expunged_cb(LibBalsaMailbox * mailbox, guint msgno,
--bindex->next_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}.
-*/
+/*
+ * balsa_index_load_mailbox_node:
+ */
-gboolean
-balsa_index_load_mailbox_node (BalsaIndex * index,
- BalsaMailboxNode* mbnode, GError **err)
-{
- GtkTreeView *tree_view;
- LibBalsaMailbox* mailbox;
+typedef struct {
+ BalsaIndex *index;
+ BalsaMailboxNode *mbnode;
+ GError *err;
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);
- g_return_val_if_fail(BALSA_IS_MAILBOX_NODE(mbnode), TRUE);
- g_return_val_if_fail(LIBBALSA_IS_MAILBOX(mbnode->mailbox), TRUE);
+} bndx_open_mailbox_info;
- mailbox = mbnode->mailbox;
+/* Idle callback to complete opening a mailbox */
- try_cnt = 0;
- do {
- g_clear_error(err);
- successp = libbalsa_mailbox_open(mailbox, err);
- if (!balsa_app.main_window)
- return FALSE;
+static gboolean
+bndx_set_mailbox(bndx_open_mailbox_info * info)
+{
+ GtkTreeView *tree_view;
+ LibBalsaMailbox *mailbox;
- 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->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);
- if (!successp)
- return TRUE;
+ return FALSE;
+ }
/*
* set the new mailbox
*/
- index->mailbox_node = mbnode;
- g_object_weak_ref(G_OBJECT(mbnode),
- (GWeakNotify) bndx_mbnode_weak_notify, index);
+ info->index->mailbox_node = info->mbnode;
+ g_object_weak_ref(G_OBJECT(info->mbnode),
+ (GWeakNotify) bndx_mbnode_weak_notify, info->index);
/*
* rename "from" column to "to" for outgoing mail
*/
- gdk_threads_enter();
- tree_view = GTK_TREE_VIEW(index);
+ tree_view = GTK_TREE_VIEW(info->index);
+ mailbox = info->mbnode->mailbox;
if (libbalsa_mailbox_get_show(mailbox) == LB_MAILBOX_SHOW_TO) {
GtkTreeViewColumn *column =
- gtk_tree_view_get_column(tree_view, LB_MBOX_FROM_COL);
- index->filter_no = 1; /* FIXME: this is hack! */
+ gtk_tree_view_get_column(tree_view, LB_MBOX_FROM_COL);
+ info->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),
- (gpointer) index);
+ G_CALLBACK(bndx_mailbox_changed_cb),
+ info->index);
g_signal_connect(mailbox, "row-inserted",
- G_CALLBACK(bndx_mailbox_row_inserted_cb), index);
+ G_CALLBACK(bndx_mailbox_row_inserted_cb),
+ info->index);
g_signal_connect(mailbox, "message-expunged",
- G_CALLBACK(bndx_mailbox_message_expunged_cb), index);
+ G_CALLBACK(bndx_mailbox_message_expunged_cb),
+ info->index);
- /* Set the tree store*/
+ /* 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);
- index->search_iter = libbalsa_mailbox_search_iter_new(cond_undeleted);
+ info->index->search_iter =
+ libbalsa_mailbox_search_iter_new(cond_undeleted);
/* Note when this mailbox was opened, for use in auto-closing. */
- time(&index->mailbox_node->last_use);
+ time(&info->index->mailbox_node->last_use);
+
+ balsa_index_scroll_on_open(info->index);
+
+ g_free(info);
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 dc5ab15..f69f679 100644
--- a/src/balsa-index.h
+++ b/src/balsa-index.h
@@ -105,12 +105,10 @@ 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);
+ void balsa_index_load_mailbox_node(BalsaIndex * bindex,
+ BalsaMailboxNode * mbnode);
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 5064868..a90ba6a 100644
--- a/src/main-window.c
+++ b/src/main-window.c
@@ -2322,22 +2322,20 @@ bw_notebook_label_new(BalsaMailboxNode * mbnode)
return box;
}
-/* Called with the gdk lock held (when threads are enabled). */
+/* Class method */
static void
-bw_real_open_mbnode(BalsaWindow *window, BalsaMailboxNode * mbnode,
- gboolean set_current)
+balsa_window_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;
- /* FIXME: the check is not needed in non-MT-mode */
- if (!window || bw_is_open_mailbox(mailbox = mbnode->mailbox))
+ if (bw_is_open_mailbox(mailbox = mbnode->mailbox))
return;
index = BALSA_INDEX(balsa_index_new());
@@ -2346,36 +2344,16 @@ bw_real_open_mbnode(BalsaWindow *window, BalsaMailboxNode * mbnode,
(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);
-
- /* 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);
- }
+ balsa_index_load_mailbox_node(index, mbnode);
+ balsa_window_decrease_activity(window, message);
g_free(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);
+ index->mailbox_node = mbnode;
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 */
@@ -2406,82 +2384,6 @@ bw_real_open_mbnode(BalsaWindow *window, BalsaMailboxNode * mbnode,
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:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]