The GDK lock in tinymail



This patch makes Tinymail's callbacks and observer's updates behave like
signals in Gtk+.

Please review extensively 

note. We'll update Modest's usage of gdk_threads_enter and leave very
soon. Once both patches are tested and ready, I'll commit this patch to
Tinymail's repository.


-- 
Philip Van Hoof, software developer
home: me at pvanhoof dot be 
gnome: pvanhoof at gnome dot org 
http://www.pvanhoof.be/blog



Index: libtinymail-camel/tny-camel-folder.c
===================================================================
--- libtinymail-camel/tny-camel-folder.c	(revision 2551)
+++ libtinymail-camel/tny-camel-folder.c	(working copy)
@@ -77,71 +77,190 @@
 
 static GObjectClass *parent_class = NULL;
 
+
+typedef struct { 
+	GObject *self;
+	GObject *change; 
+} NotFolObInIdleInfo;
+
+static void 
+do_notify_in_idle_destroy (gpointer user_data)
+{
+	NotFolObInIdleInfo *info = (NotFolObInIdleInfo *) user_data;
+	TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (info->self);
+
+	g_object_unref (info->change);
+	_tny_camel_folder_unreason (priv);
+	g_object_unref (info->self);
+	g_slice_free (NotFolObInIdleInfo, info);
+}
+
 static void
 notify_folder_store_observers_about (TnyFolderStore *self, TnyFolderStoreChange *change)
 {
 	TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
+	TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (priv->account);
 	TnyIterator *iter;
 	TnyList *list;
 
 	g_static_rec_mutex_lock (priv->obs_lock);
-
 	if (!priv->sobservers) {
 		g_static_rec_mutex_unlock (priv->obs_lock);
 		return;
 	}
-
 	list = tny_list_copy (priv->sobservers);
 	g_static_rec_mutex_unlock (priv->obs_lock);
 
 	iter = tny_list_create_iterator (list);
-
 	while (!tny_iterator_is_done (iter))
 	{
 		TnyFolderStoreObserver *observer = TNY_FOLDER_STORE_OBSERVER (tny_iterator_get_current (iter));
-
+		tny_lockable_lock (apriv->session->priv->ui_lock);
 		tny_folder_store_observer_update (observer, change);
-		g_object_unref (G_OBJECT (observer));
+		tny_lockable_unlock (apriv->session->priv->ui_lock);
+		g_object_unref (observer);
 		tny_iterator_next (iter);
 	}
-	g_object_unref (G_OBJECT (iter));
-
+	g_object_unref (iter);
 	g_object_unref (list);
 
+	return;
 }
 
+static gboolean 
+notify_folder_store_observers_about_idle (gpointer user_data)
+{
+	NotFolObInIdleInfo *info = (NotFolObInIdleInfo *) user_data;
+	notify_folder_store_observers_about (TNY_FOLDER_STORE (info->self), 
+		TNY_FOLDER_STORE_CHANGE (info->change));
+	return FALSE;
+}
+
 static void
+notify_folder_store_observers_about_in_idle (TnyFolderStore *self, TnyFolderStoreChange *change)
+{
+	NotFolObInIdleInfo *info = g_slice_new (NotFolObInIdleInfo);
+	TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
+
+	_tny_camel_folder_reason (priv);
+	info->self = g_object_ref (self);
+	info->change = g_object_ref (change);
+	g_idle_add_full (G_PRIORITY_HIGH, notify_folder_store_observers_about_idle,
+		info, do_notify_in_idle_destroy);
+}
+
+
+static void
 notify_folder_observers_about (TnyFolder *self, TnyFolderChange *change)
 {
 	TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
+	TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (priv->account);
 	TnyIterator *iter;
 	TnyList *list;
 
 	g_static_rec_mutex_lock (priv->obs_lock);
-
 	if (!priv->observers) {
 		g_static_rec_mutex_unlock (priv->obs_lock);
 		return;
 	}
-
 	list = tny_list_copy (priv->observers);
 	g_static_rec_mutex_unlock (priv->obs_lock);
 
 	iter = tny_list_create_iterator (list);
-
 	while (!tny_iterator_is_done (iter))
 	{
 		TnyFolderObserver *observer = TNY_FOLDER_OBSERVER (tny_iterator_get_current (iter));
+		tny_lockable_lock (apriv->session->priv->ui_lock);
 		tny_folder_observer_update (observer, change);
-		g_object_unref (G_OBJECT (observer));
+		tny_lockable_unlock (apriv->session->priv->ui_lock);
+		g_object_unref (observer);
 		tny_iterator_next (iter);
 	}
-	g_object_unref (G_OBJECT (iter));
+	g_object_unref (iter);
+	g_object_unref (list);
 
+	return;
+}
+
+
+static gboolean 
+notify_folder_observers_about_idle (gpointer user_data)
+{
+	NotFolObInIdleInfo *info = (NotFolObInIdleInfo *) user_data;
+	notify_folder_observers_about (TNY_FOLDER (info->self), 
+		TNY_FOLDER_CHANGE (info->change));
+	return FALSE;
+}
+
+static void
+notify_folder_observers_about_in_idle (TnyFolder *self, TnyFolderChange *change)
+{
+	NotFolObInIdleInfo *info = g_slice_new (NotFolObInIdleInfo);
+	TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
+
+	_tny_camel_folder_reason (priv);
+	info->self = g_object_ref (self);
+	info->change = g_object_ref (change);
+	g_idle_add_full (G_PRIORITY_HIGH, notify_folder_observers_about_idle,
+		info, do_notify_in_idle_destroy);
+}
+
+
+static void
+notify_folder_store_observers_about_for_store_acc (TnyFolderStore *self, TnyFolderStoreChange *change)
+{
+	TnyCamelStoreAccountPriv *priv = TNY_CAMEL_STORE_ACCOUNT_GET_PRIVATE (self);
+	TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (self);
+	TnyIterator *iter;
+	TnyList *list = NULL;
+
+	g_static_rec_mutex_lock (priv->obs_lock);
+	if (!priv->sobservers) {
+		g_static_rec_mutex_unlock (priv->obs_lock);
+		return;
+	}
+	list = tny_list_copy (priv->sobservers);
+	g_static_rec_mutex_unlock (priv->obs_lock);
+
+	iter = tny_list_create_iterator (list);
+	while (!tny_iterator_is_done (iter))
+	{
+		TnyFolderStoreObserver *observer = TNY_FOLDER_STORE_OBSERVER (tny_iterator_get_current (iter));
+		tny_lockable_lock (apriv->session->priv->ui_lock);
+		tny_folder_store_observer_update (observer, change);
+		tny_lockable_unlock (apriv->session->priv->ui_lock);
+		g_object_unref (observer);
+		tny_iterator_next (iter);
+	}
+	g_object_unref (iter);
 	g_object_unref (list);
 
+	return;
 }
 
+static gboolean 
+notify_folder_store_observers_about_for_store_acc_idle (gpointer user_data)
+{
+	NotFolObInIdleInfo *info = (NotFolObInIdleInfo *) user_data;
+	notify_folder_store_observers_about_for_store_acc (TNY_FOLDER_STORE (info->self), 
+		TNY_FOLDER_STORE_CHANGE (info->change));
+	return FALSE;
+}
+
+static void
+notify_folder_store_observers_about_for_store_acc_in_idle (TnyFolderStore *self, TnyFolderStoreChange *change)
+{
+	NotFolObInIdleInfo *info = g_slice_new (NotFolObInIdleInfo);
+	TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
+
+	_tny_camel_folder_reason (priv);
+	info->self = g_object_ref (self);
+	info->change = g_object_ref (change);
+	g_idle_add_full (G_PRIORITY_HIGH, notify_folder_store_observers_about_for_store_acc_idle,
+		info, do_notify_in_idle_destroy);
+}
+
+
 static void 
 update_iter_counts (TnyCamelFolderPriv *priv)
 {
@@ -163,7 +282,7 @@
 	update_iter_counts (priv);
 	tny_folder_change_set_new_unread_count (change, priv->unread_length);
 	tny_folder_change_set_new_all_count (change, priv->cached_length);
-	notify_folder_observers_about (TNY_FOLDER (self), change);
+	notify_folder_observers_about_in_idle (TNY_FOLDER (self), change);
 	g_object_unref (change);
 }
 
@@ -616,9 +735,9 @@
 		tny_folder_change_set_new_all_count (change, priv->cached_length);
 		tny_folder_change_set_new_unread_count (change, priv->unread_length);
 
-		notify_folder_observers_about (self, change);
+		notify_folder_observers_about_in_idle (self, change);
 
-		g_object_unref (G_OBJECT (change));
+		g_object_unref (change);
 
 		if (dst_orig_uids) {
 			g_ptr_array_foreach (dst_orig_uids, (GFunc) g_free, NULL);
@@ -690,7 +809,7 @@
 	/* Notify header has been removed */
 	change = tny_folder_change_new (self);
 	tny_folder_change_add_expunged_header (change, header);
-	notify_folder_observers_about (self, change);
+	notify_folder_observers_about_in_idle (self, change);
 	g_object_unref (change);
 
 	g_static_rec_mutex_unlock (priv->folder_lock);
@@ -993,8 +1112,11 @@
 	notify_folder_observers_about (self, change);
 	g_object_unref (change);
 
-	if (info->callback)
+	if (info->callback) {
+		tny_lockable_lock (info->session->priv->ui_lock);
 		info->callback (info->self, info->cancelled, &info->err, info->user_data);
+		tny_lockable_unlock (info->session->priv->ui_lock);
+	}
 
 	tny_idle_stopper_stop (info->stopper);
 
@@ -1010,7 +1132,7 @@
 
 	info = tny_progress_info_new (G_OBJECT (oinfo->self), oinfo->status_callback, 
 		TNY_FOLDER_STATUS, TNY_FOLDER_STATUS_CODE_SYNC, what, sofar, 
-		oftotal, oinfo->stopper, oinfo->user_data);
+		oftotal, oinfo->stopper, oinfo->session->priv->ui_lock, oinfo->user_data);
 
 	execute_callback (oinfo->depth, G_PRIORITY_HIGH,
 			  tny_progress_info_idle_func, info,
@@ -1109,8 +1231,11 @@
 tny_camel_folder_sync_async_cancelled_callback (gpointer thr_user_data)
 {
 	SyncFolderInfo *info = thr_user_data;
-	if (info->callback)
+	if (info->callback) {
+		tny_lockable_lock (info->session->priv->ui_lock);
 		info->callback (info->self, TRUE, &info->err, info->user_data);
+		tny_lockable_unlock (info->session->priv->ui_lock);
+	}
 	return FALSE;
 }
 
@@ -1229,8 +1354,11 @@
 	notify_folder_observers_about (self, change);
 	g_object_unref (change);
 
-	if (info->callback)
+	if (info->callback) {
+		tny_lockable_lock (info->session->priv->ui_lock);
 		info->callback (info->self, info->cancelled, &info->err, info->user_data);
+		tny_lockable_unlock (info->session->priv->ui_lock);
+	}
 
 	/* Prevent status callbacks from being called after this
 	 * (can happen because the 2 idle callbacks have different priorities)
@@ -1250,7 +1378,8 @@
 
 	info = tny_progress_info_new (G_OBJECT (oinfo->self), oinfo->status_callback, 
 		TNY_FOLDER_STATUS, TNY_FOLDER_STATUS_CODE_REFRESH, what, sofar, 
-		oftotal, oinfo->stopper, oinfo->user_data);
+		oftotal, oinfo->stopper, oinfo->session->priv->ui_lock, 
+		oinfo->user_data);
 
 	execute_callback (oinfo->depth, G_PRIORITY_HIGH,
 			  tny_progress_info_idle_func, info,
@@ -1353,8 +1482,11 @@
 tny_camel_folder_refresh_async_cancelled_callback (gpointer thr_user_data)
 {
 	RefreshFolderInfo *info = thr_user_data;
-	if (info->callback)
+	if (info->callback) {
+		tny_lockable_lock (info->session->priv->ui_lock);
 		info->callback (info->self, TRUE, &info->err, info->user_data);
+		tny_lockable_unlock (info->session->priv->ui_lock);
+	}
 	return FALSE;
 }
 
@@ -1482,7 +1614,7 @@
 	change = tny_folder_change_new (self);
 	tny_folder_change_set_new_all_count (change, priv->cached_length);
 	tny_folder_change_set_new_unread_count (change, priv->unread_length);
-	notify_folder_observers_about (self, change);
+	notify_folder_observers_about_in_idle (self, change);
 	g_object_unref (change);
 
 	return;
@@ -1568,8 +1700,11 @@
 tny_camel_folder_get_headers_async_callback (gpointer thr_user_data)
 {
 	GetHeadersInfo *info = thr_user_data;
-	if (info->callback)
+	if (info->callback) {
+		tny_lockable_lock (info->session->priv->ui_lock);
 		info->callback (info->self, FALSE, info->headers, &info->err, info->user_data);
+		tny_lockable_unlock (info->session->priv->ui_lock);
+	}
 	return FALSE;
 }
 
@@ -1625,8 +1760,11 @@
 tny_camel_folder_get_headers_async_cancelled_callback (gpointer thr_user_data)
 {
 	GetHeadersInfo *info = thr_user_data;
-	if (info->callback)
+	if (info->callback) {
+		tny_lockable_lock (info->session->priv->ui_lock);
 		info->callback (info->self, TRUE, info->headers, &info->err, info->user_data);
+		tny_lockable_unlock (info->session->priv->ui_lock);
+	}
 	return FALSE;
 }
 
@@ -1823,8 +1961,11 @@
 		g_object_unref (change);
 	}
 
-	if (info->callback)
+	if (info->callback) {
+		tny_lockable_lock (info->session->priv->ui_lock);
 		info->callback (info->self, info->cancelled, info->msg, &info->err, info->user_data);
+		tny_lockable_unlock (info->session->priv->ui_lock);
+	}
 
 	if (info->msg)
 		g_object_unref (info->msg);
@@ -1847,7 +1988,7 @@
 
 	info = tny_progress_info_new (G_OBJECT (oinfo->self), oinfo->status_callback, 
 		TNY_FOLDER_STATUS, TNY_FOLDER_STATUS_CODE_GET_MSG, what, sofar, 
-		oftotal, oinfo->stopper, oinfo->user_data);
+		oftotal, oinfo->stopper, oinfo->session->priv->ui_lock, oinfo->user_data);
 
 	execute_callback (oinfo->depth, G_PRIORITY_HIGH, 
 			  tny_progress_info_idle_func, info, 
@@ -1946,8 +2087,11 @@
 {
 
 	GetMsgInfo *info = (GetMsgInfo *) thr_user_data;
-	if (info->callback)
+	if (info->callback) {
+		tny_lockable_lock (info->session->priv->ui_lock);
 		info->callback (info->self, TRUE, NULL, &info->err, info->user_data);
+		tny_lockable_unlock (info->session->priv->ui_lock);
+	}
 	return FALSE;
 }
 
@@ -2088,8 +2232,8 @@
 	{
 		change = tny_folder_change_new (self);
 		tny_folder_change_set_received_msg (change, retval);
-		notify_folder_observers_about (self, change);
-		g_object_unref (G_OBJECT (change));
+		notify_folder_observers_about_in_idle (self, change);
+		g_object_unref (change);
 	}
 
 	g_static_rec_mutex_unlock (priv->folder_lock);
@@ -2441,80 +2585,106 @@
 }
 
 
+
+typedef struct {
+	TnyFolder *folder;
+	gboolean rem;
+} NotFolObsItem;
+
 static void
-notify_folder_store_observers_about_for_store_acc (TnyFolderStore *self, TnyFolderStoreChange *change)
+not_fol_obs_foreach (gpointer key, gpointer value, gpointer user_data)
 {
-	TnyCamelStoreAccountPriv *priv = TNY_CAMEL_STORE_ACCOUNT_GET_PRIVATE (self);
-	TnyIterator *iter;
+	GList *items = (GList *) value;
+	TnyFolderStore *str = (TnyFolderStore *) key;
+	TnyFolderStoreChange *change = tny_folder_store_change_new (str);
+	gboolean in_idle = (gboolean) user_data;
 
-	if (!priv->sobservers)
-		return;
+	while (items)
+	{
+		NotFolObsItem *item = (NotFolObsItem *) items->data;
 
-	iter = tny_list_create_iterator (priv->sobservers);
-	while (!tny_iterator_is_done (iter))
-	{
-		TnyFolderStoreObserver *observer = TNY_FOLDER_STORE_OBSERVER (tny_iterator_get_current (iter));
-		tny_folder_store_observer_update (observer, change);
-		g_object_unref (observer);
-		tny_iterator_next (iter);
+		tny_debug ("tny_folder_copy: observers notify folder-%s %s\n", 
+			item->rem ? "del" : "add",
+			tny_folder_get_name (item->folder));
+
+		if (item->rem)
+			tny_folder_store_change_add_removed_folder (change, item->folder);
+		else
+			tny_folder_store_change_add_created_folder (change, item->folder);
+
+		g_slice_free (NotFolObsItem, item);
+		items = g_list_next (items);
 	}
-	g_object_unref (iter);
+
+	g_list_free (items);
+
+	if (TNY_IS_CAMEL_STORE_ACCOUNT (str)) {
+		if (in_idle)
+			notify_folder_store_observers_about_for_store_acc_in_idle (str, change);
+		else
+			notify_folder_store_observers_about_for_store_acc (str, change);
+	} else {
+		if (in_idle)
+			notify_folder_store_observers_about_in_idle (str, change);
+		else
+			notify_folder_store_observers_about (str, change);
+	}
+	g_object_unref (change);
+
+	return;
 }
 
 static void
-notify_folder_observers_about_copy (GList *adds, GList *rems, gboolean del)
+notify_folder_observers_about_copy (GList *adds, GList *rems, gboolean del, gboolean in_idle)
 {
+
+	GHashTable *table = g_hash_table_new_full (g_direct_hash, g_direct_equal, 
+					NULL, NULL);
+
 	rems = g_list_first (rems);
-
 	while (rems)
 	{
 		CpyEvent *evt = rems->data;
-
-
 		if (del) {
-			TnyFolderStoreChange *change = tny_folder_store_change_new (evt->str);
-			tny_folder_store_change_add_removed_folder (change, evt->fol);
+			gboolean add = FALSE;
+			NotFolObsItem *item = g_slice_new (NotFolObsItem);
+			GList *items = g_hash_table_lookup (table, evt->str);
+			if (!items)
+				add = TRUE;
+			item->folder = TNY_FOLDER (g_object_ref (evt->fol));
+			item->rem = TRUE;
+			items = g_list_append (items, item);
+			if (add)
+				g_hash_table_insert (table, evt->str, items);
 
-			if (TNY_IS_CAMEL_STORE_ACCOUNT (evt->str))
-				notify_folder_store_observers_about_for_store_acc (evt->str, change);
-			else
-				notify_folder_store_observers_about (evt->str, change);
-
-			tny_debug ("tny_folder_copy: observers notify folder-del %s\n", 
-				tny_folder_get_name (evt->fol));
-
-			g_object_unref (change);
 		}
-
 		cpy_event_free (evt);
 		rems = g_list_next (rems);
 	}
-
 	g_list_free (rems);
 
 	while (adds)
 	{
-		TnyFolderStoreChange *change;
 		CpyEvent *evt = adds->data;
-
-		change = tny_folder_store_change_new (evt->str);
-		tny_folder_store_change_add_created_folder (change, evt->fol);
-
-		if (TNY_IS_CAMEL_STORE_ACCOUNT (evt->str))
-			notify_folder_store_observers_about_for_store_acc (evt->str, change);
-		else
-			notify_folder_store_observers_about (evt->str, change);
-
-		g_object_unref (change);
-
-		tny_debug ("tny_folder_copy: observers notify folder-add %s\n",
-			 tny_folder_get_name (evt->fol));
-
+		gboolean add = FALSE;
+		NotFolObsItem *item = g_slice_new (NotFolObsItem);
+		GList *items = g_hash_table_lookup (table, evt->str);
+		if (!items)
+			add = TRUE;
+		item->folder = TNY_FOLDER (g_object_ref (evt->fol));
+		item->rem = FALSE;
+		items = g_list_append (items, item);
+		if (add)
+			g_hash_table_insert (table, evt->str, items);
 		cpy_event_free (evt);
 		adds = g_list_next (adds);
 	}
+	g_list_free (adds);
 
-	g_list_free (adds);
+	g_hash_table_foreach (table, not_fol_obs_foreach, (gpointer) in_idle);
+	g_hash_table_destroy (table);
+
+	return;
 }
 
 static CpyRecRet*
@@ -2674,7 +2844,14 @@
 			g_static_rec_mutex_lock (priv->folder_lock);
 			camel_folder_info_free  (priv->iter);
 			priv->iter = NULL;
-			/* unload_folder_no_lock (priv, FALSE); */
+
+			/* PVH investigated this and noticed that it made things
+			 * crash in the following situation:
+			 * You rename folder A to B, you copy B to C
+			 *
+			 * unload_folder_no_lock (priv, FALSE); 
+			 **/
+
 			g_static_rec_mutex_unlock (priv->folder_lock);
 		}
 
@@ -2725,7 +2902,7 @@
 	if (nerr != NULL)
 		g_propagate_error (err, nerr);
 	else
-		notify_folder_observers_about_copy (adds, rems, del);
+		notify_folder_observers_about_copy (adds, rems, del, TRUE);
 
 	_tny_session_stop_operation (TNY_FOLDER_PRIV_GET_SESSION (priv));
 
@@ -2765,7 +2942,7 @@
 
 	if (info->err == NULL)
 		notify_folder_observers_about_copy (info->adds, info->rems, 
-			info->delete_originals);
+			info->delete_originals, FALSE);
 
 	if (info->new_folder)
 		g_object_unref (info->new_folder);
@@ -2800,13 +2977,13 @@
 {
 	CopyFolderInfo *info = (CopyFolderInfo *) thr_user_data;
 
-	if (info->callback)
+	if (info->callback) {
+		tny_lockable_lock (info->session->priv->ui_lock);
 		info->callback (info->self, info->into, info->cancelled, 
 			info->new_folder, &info->err, info->user_data);
+		tny_lockable_unlock (info->session->priv->ui_lock);
+	}
 
-	/* Prevent status callbacks from being called after this
-	 * (can happen because the 2 idle callbacks have different priorities)
-	 * by causing tny_idle_stopper_is_stopped() to return TRUE. */
 	tny_idle_stopper_stop (info->stopper);
 
 	return FALSE;
@@ -2830,7 +3007,7 @@
 	
 	info = tny_progress_info_new (G_OBJECT (oinfo->self), oinfo->status_callback, 
 		TNY_FOLDER_STATUS, TNY_FOLDER_STATUS_CODE_COPY_FOLDER, what, sofar, 
-		oftotal, oinfo->stopper, oinfo->user_data);
+		oftotal, oinfo->stopper, oinfo->session->priv->ui_lock, oinfo->user_data);
 
 	execute_callback (oinfo->depth, G_PRIORITY_HIGH,
 			  tny_progress_info_idle_func, info, 
@@ -2920,8 +3097,11 @@
 {
 
 	CopyFolderInfo *info = (CopyFolderInfo *) thr_user_data;
-	if (info->callback)
+	if (info->callback) {
+		tny_lockable_lock (info->session->priv->ui_lock);
 		info->callback (info->self, info->into, TRUE, NULL, &info->err, info->user_data);
+		tny_lockable_unlock (info->session->priv->ui_lock);
+	}
 	return FALSE;
 }
 
@@ -3016,7 +3196,7 @@
 
 
 static void 
-inform_observers_about_transfer (TnyFolder *from, TnyFolder *to, gboolean del_orig, TnyList *headers, TnyList *new_header_list, gint from_all, gint to_all, gint from_unread, gint to_unread)
+notify_folder_observers_about_transfer (TnyFolder *from, TnyFolder *to, gboolean del_orig, TnyList *headers, TnyList *new_header_list, gint from_all, gint to_all, gint from_unread, gint to_unread, gboolean in_idle)
 {
 	TnyFolderChange *tochange = tny_folder_change_new (to);
 	TnyFolderChange *fromchange = tny_folder_change_new (from);
@@ -3025,15 +3205,14 @@
 	iter = tny_list_create_iterator (new_header_list);
 	while (!tny_iterator_is_done (iter)) 
 	{
-		TnyHeader *header;
-		header = TNY_HEADER (tny_iterator_get_current (iter));
+		TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
 		if (del_orig)
 			tny_folder_change_add_expunged_header (fromchange, header);
 		tny_folder_change_add_added_header (tochange, header);
 		g_object_unref (header);
 		tny_iterator_next (iter);
 	}
-	g_object_unref (G_OBJECT (iter));
+	g_object_unref (iter);
 
 	tny_folder_change_set_new_all_count (tochange, to_all);
 	tny_folder_change_set_new_unread_count (tochange, to_unread);
@@ -3041,8 +3220,14 @@
 	tny_folder_change_set_new_all_count (fromchange, from_all);
 	tny_folder_change_set_new_unread_count (fromchange, from_unread);
 
-	notify_folder_observers_about (to, tochange);
-	notify_folder_observers_about (from, fromchange);
+	if (in_idle)
+	{
+		notify_folder_observers_about_in_idle (to, tochange);
+		notify_folder_observers_about_in_idle (from, fromchange);
+	} else {
+		notify_folder_observers_about (to, tochange);
+		notify_folder_observers_about (from, fromchange);
+	}
 
 	g_object_unref (tochange);
 	g_object_unref (fromchange);
@@ -3057,10 +3242,6 @@
 	TnyCamelFolderPriv *priv_src = TNY_CAMEL_FOLDER_GET_PRIVATE (info->self);
 	TnyCamelFolderPriv *priv_dst = TNY_CAMEL_FOLDER_GET_PRIVATE (info->folder_dst);
 
-	inform_observers_about_transfer (info->self, info->folder_dst, info->delete_originals,
-		info->header_list, info->new_header_list, info->from_all, 
-		info->to_all, info->from_unread, info->to_unread);
-
 	/* thread reference */
 	_tny_camel_folder_unreason (priv_src);
 	g_object_unref (info->self);
@@ -3092,12 +3273,21 @@
 tny_camel_folder_transfer_msgs_async_callback (gpointer thr_user_data)
 {
 	TransferMsgsInfo *info = thr_user_data;
-	if (info->callback)
+	TnyCamelFolderPriv *priv_src = TNY_CAMEL_FOLDER_GET_PRIVATE (info->self);
+	TnyCamelFolderPriv *priv_dst = TNY_CAMEL_FOLDER_GET_PRIVATE (info->folder_dst);
+
+	notify_folder_observers_about_transfer (info->self, info->folder_dst, info->delete_originals,
+		info->header_list, info->new_header_list, info->from_all, 
+		info->to_all, info->from_unread, info->to_unread, FALSE);
+
+	if (info->callback) {
+		tny_lockable_lock (info->session->priv->ui_lock);
 		info->callback (info->self, info->cancelled, &info->err, info->user_data);
-	/* Prevent status callbacks from being called after this
-	 * (can happen because the 2 idle callbacks have different priorities)
-	 * by causing tny_idle_stopper_is_stopped() to return TRUE. */
+		tny_lockable_unlock (info->session->priv->ui_lock);
+	}
+
 	tny_idle_stopper_stop (info->stopper);
+
 	return FALSE;
 }
 
@@ -3276,8 +3466,10 @@
 			{
 				TnyHeader *hdr = _tny_camel_header_new ();
 				/* This adds a reason to live for folder_dst */
+				printf ("A %d\n", priv_dst->reason_to_live);
 				_tny_camel_header_set_folder (TNY_CAMEL_HEADER (hdr), 
 					TNY_CAMEL_FOLDER (folder_dst), priv_dst);
+				printf ("A %d\n", priv_dst->reason_to_live);
 				/* hdr will take care of the freeup */
 				_tny_camel_header_set_as_memory (TNY_CAMEL_HEADER (hdr), minfo);
 				succeeded_news = g_list_prepend (succeeded_news, hdr);
@@ -3344,8 +3536,10 @@
 					TnyHeader *hdr = _tny_camel_header_new ();
 
 					/* This adds a reason to live for folder_dst */
+		printf ("B %d\n", priv_dst->reason_to_live);
 					_tny_camel_header_set_folder (TNY_CAMEL_HEADER (hdr), 
 						TNY_CAMEL_FOLDER (folder_dst), priv_dst);
+		printf ("B %d\n", priv_dst->reason_to_live);
 					/* hdr will take care of the freeup */
 					_tny_camel_header_set_as_memory (TNY_CAMEL_HEADER (hdr), om);
 					tny_list_prepend (new_headers, G_OBJECT (hdr));
@@ -3412,7 +3606,7 @@
 
 	info = tny_progress_info_new (G_OBJECT (oinfo->self), oinfo->status_callback, 
 		TNY_FOLDER_STATUS, TNY_FOLDER_STATUS_CODE_XFER_MSGS, what, sofar, 
-		oftotal, oinfo->stopper, oinfo->user_data);
+		oftotal, oinfo->stopper, oinfo->session->priv->ui_lock, oinfo->user_data);
 
 	execute_callback (oinfo->depth, G_PRIORITY_HIGH,
 			  tny_progress_info_idle_func, info, 
@@ -3474,8 +3668,8 @@
 	info->had_callback = FALSE;
 
 	execute_callback (info->depth, G_PRIORITY_DEFAULT, 
-			  tny_camel_folder_transfer_msgs_async_callback, info, 
-			  tny_camel_folder_transfer_msgs_async_destroyer);
+		tny_camel_folder_transfer_msgs_async_callback, info, 
+		tny_camel_folder_transfer_msgs_async_destroyer);
 
 	/* Wait on the queue for the mainloop callback to be finished */
 	g_mutex_lock (info->mutex);
@@ -3506,8 +3700,11 @@
 tny_camel_folder_transfer_msgs_async_cancelled_callback (gpointer thr_user_data)
 {
 	TransferMsgsInfo *info = thr_user_data;
-	if (info->callback)
+	if (info->callback) {
+		tny_lockable_lock (info->session->priv->ui_lock);
 		info->callback (info->self, TRUE, &info->err, info->user_data);
+		tny_lockable_unlock (info->session->priv->ui_lock);
+	}
 	return FALSE;
 }
 
@@ -3551,8 +3748,8 @@
 			g_object_ref (info->self);
 
 			execute_callback (info->depth, G_PRIORITY_DEFAULT,
-					  tny_camel_folder_transfer_msgs_async_cancelled_callback, info, 
-					  tny_camel_folder_transfer_msgs_async_cancelled_destroyer);
+				tny_camel_folder_transfer_msgs_async_cancelled_callback, info, 
+				tny_camel_folder_transfer_msgs_async_cancelled_destroyer);
 		}
 		g_error_free (err);
 		return;
@@ -3618,8 +3815,8 @@
 		ufrom = camel_folder_get_unread_message_count (priv_src->folder);
 		uto = camel_folder_get_unread_message_count (priv_dst->folder);
 
-		inform_observers_about_transfer (self, folder_dst, delete_originals, 
-				headers, new_headers, from, to, ufrom, uto);
+		notify_folder_observers_about_transfer (self, folder_dst, delete_originals, 
+			headers, new_headers, from, to, ufrom, uto, TRUE);
 	}
 
 	g_object_unref (new_headers);
@@ -3840,8 +4037,8 @@
 
 		change = tny_folder_store_change_new (self);
 		tny_folder_store_change_add_removed_folder (change, folder);
-		notify_folder_store_observers_about (self, change);
-		g_object_unref (G_OBJECT (change));
+		notify_folder_store_observers_about_in_idle (self, change);
+		g_object_unref (change);
 	}
 
 	g_static_rec_mutex_unlock (apriv->factory_lock);
@@ -4041,8 +4238,8 @@
 
 	change = tny_folder_store_change_new (self);
 	tny_folder_store_change_add_created_folder (change, folder);
-	notify_folder_store_observers_about (self, change);
-	g_object_unref (G_OBJECT (change));
+	notify_folder_store_observers_about_in_idle (self, change);
+	g_object_unref (change);
 
 	_tny_session_stop_operation (TNY_FOLDER_PRIV_GET_SESSION (priv));
 
@@ -4227,8 +4424,11 @@
 tny_camel_folder_get_folders_async_callback (gpointer thr_user_data)
 {
 	GetFoldersInfo *info = thr_user_data;
-	if (info->callback)
+	if (info->callback) {
+		tny_lockable_lock (info->session->priv->ui_lock);
 		info->callback (info->self, info->list, &info->err, info->user_data);
+		tny_lockable_unlock (info->session->priv->ui_lock);
+	}
 	return FALSE;
 }
 
@@ -4288,8 +4488,11 @@
 tny_camel_folder_get_folders_async_cancelled_callback (gpointer thr_user_data)
 {
 	GetFoldersInfo *info = thr_user_data;
-	if (info->callback)
+	if (info->callback) {
+		tny_lockable_lock (info->session->priv->ui_lock);
 		info->callback (info->self, info->list, &info->err, info->user_data);
+		tny_lockable_unlock (info->session->priv->ui_lock);
+	}
 	return FALSE;
 }
 
Index: libtinymail-camel/camel-lite/camel/camel-folder-summary.c
===================================================================
--- libtinymail-camel/camel-lite/camel/camel-folder-summary.c	(revision 2551)
+++ libtinymail-camel/camel-lite/camel/camel-folder-summary.c	(working copy)
@@ -3206,7 +3206,8 @@
 
 	g_return_if_fail(mi != NULL);
 
-	if (mi->summary) {
+	if (mi->summary) 
+	{
 		CAMEL_SUMMARY_LOCK(mi->summary, ref_lock);
 
 		if (mi->refcount >= 1)
Index: libtinymail-camel/tny-camel-store-account-priv.h
===================================================================
--- libtinymail-camel/tny-camel-store-account-priv.h	(revision 2551)
+++ libtinymail-camel/tny-camel-store-account-priv.h	(working copy)
@@ -35,7 +35,7 @@
 	GList *managed_folders;
 	TnyList *sobservers;
 	gboolean cant_reuse_iter;
-	GStaticRecMutex *factory_lock;
+	GStaticRecMutex *factory_lock, *obs_lock;
 	TnyCamelQueue *queue, *msg_queue;
 };
 
Index: libtinymail-camel/tny-camel-store-account.c
===================================================================
--- libtinymail-camel/tny-camel-store-account.c	(revision 2551)
+++ libtinymail-camel/tny-camel-store-account.c	(working copy)
@@ -69,26 +69,73 @@
 char *strcasestr(const char *haystack, const char *needle);
 
 
+typedef struct { 
+	GObject *self;
+	GObject *change; 
+} NotFolObInIdleInfo;
+
+static void 
+do_notify_in_idle_destroy (gpointer user_data)
+{
+	NotFolObInIdleInfo *info = (NotFolObInIdleInfo *) info;
+	g_object_unref (info->self);
+	g_object_unref (info->change);
+	g_slice_free (NotFolObInIdleInfo, info);
+}
+
 static void
 notify_folder_store_observers_about (TnyFolderStore *self, TnyFolderStoreChange *change)
 {
 	TnyCamelStoreAccountPriv *priv = TNY_CAMEL_STORE_ACCOUNT_GET_PRIVATE (self);
-	TnyIterator *iter;
+	TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (self);
 
-	if (!priv->sobservers)
+	TnyIterator *iter = NULL;
+
+	TnyList *list = NULL;
+
+	g_static_rec_mutex_lock (priv->obs_lock);
+	if (!priv->sobservers) {
+		g_static_rec_mutex_unlock (priv->obs_lock);
 		return;
+	}
+	list = tny_list_copy (priv->sobservers);
+	g_static_rec_mutex_unlock (priv->obs_lock);
 
-	iter = tny_list_create_iterator (priv->sobservers);
+	iter = tny_list_create_iterator (list);
 	while (!tny_iterator_is_done (iter))
 	{
 		TnyFolderStoreObserver *observer = TNY_FOLDER_STORE_OBSERVER (tny_iterator_get_current (iter));
+		tny_lockable_lock (apriv->session->priv->ui_lock);
 		tny_folder_store_observer_update (observer, change);
+		tny_lockable_unlock (apriv->session->priv->ui_lock);
 		g_object_unref (observer);
 		tny_iterator_next (iter);
 	}
 	g_object_unref (iter);
+	g_object_unref (list);
+
+	return;
 }
 
+static gboolean 
+notify_folder_store_observers_about_idle (gpointer user_data)
+{
+	NotFolObInIdleInfo *info = (NotFolObInIdleInfo *) info;
+	notify_folder_store_observers_about (TNY_FOLDER_STORE (info->self), 
+		TNY_FOLDER_STORE_CHANGE (info->change));
+	return FALSE;
+}
+
+static void
+notify_folder_store_observers_about_in_idle (TnyFolderStore *self, TnyFolderStoreChange *change)
+{
+	NotFolObInIdleInfo *info = g_slice_new (NotFolObInIdleInfo);
+	info->self = g_object_ref (self);
+	info->change = g_object_ref (change);
+	g_idle_add_full (G_PRIORITY_HIGH, notify_folder_store_observers_about_idle,
+		info, do_notify_in_idle_destroy);
+}
+
 static gboolean
 connection_status_idle (gpointer data)
 {
@@ -546,6 +593,8 @@
 	priv->cant_reuse_iter = TRUE;
 	priv->factory_lock = g_new0 (GStaticRecMutex, 1);
 	g_static_rec_mutex_init (priv->factory_lock);
+	priv->obs_lock = g_new0 (GStaticRecMutex, 1);
+	g_static_rec_mutex_init (priv->obs_lock);
 
 	return;
 }
@@ -584,6 +633,8 @@
 
 	g_static_rec_mutex_free (priv->factory_lock);
 	priv->factory_lock = NULL;
+	g_static_rec_mutex_free (priv->obs_lock);
+	priv->obs_lock = NULL;
 
 	g_object_unref (priv->queue);
 	g_object_unref (priv->msg_queue);
@@ -663,6 +714,8 @@
 		camel_exception_clear (&ex);
 	} else 
 	{
+		TnyFolderStoreChange *change = NULL;
+
 		if (aspriv->iter)
 		{
 			/* Known memleak
@@ -673,11 +726,10 @@
 		if (camel_store_supports_subscriptions (store))
 			camel_store_unsubscribe_folder (store, cpriv->folder_name, &subex);
 
-		TnyFolderStoreChange *change;
 		change = tny_folder_store_change_new (self);
 		tny_folder_store_change_add_removed_folder (change, folder);
-		notify_folder_store_observers_about (self, change);
-		g_object_unref (G_OBJECT (change));
+		notify_folder_store_observers_about_in_idle (self, change);
+		g_object_unref (change);
 	}
 
 	g_free (cpriv->folder_name); 
@@ -887,8 +939,8 @@
 	change = tny_folder_store_change_new (self);
 	tny_folder_store_change_add_created_folder (change, folder);
 	notify_folder_store_observers_about (self, change);
-	g_object_unref (G_OBJECT (change));	
-	
+	g_object_unref (change);
+
 	camel_object_unref (CAMEL_OBJECT (store));
 
 	_tny_session_stop_operation (apriv->session);
@@ -1118,8 +1170,11 @@
 tny_camel_store_account_get_folders_async_callback (gpointer thr_user_data)
 {
 	GetFoldersInfo *info = thr_user_data;
-	if (info->callback)
+	if (info->callback) {
+		tny_lockable_lock (info->session->priv->ui_lock);
 		info->callback (info->self, info->list,&info->err, info->user_data);
+		tny_lockable_unlock (info->session->priv->ui_lock);
+	}
 	return FALSE;
 }
 
@@ -1201,8 +1256,11 @@
 tny_camel_store_account_get_folders_async_cancelled_callback (gpointer thr_user_data)
 {
 	GetFoldersInfo *info = thr_user_data;
-	if (info->callback)
+	if (info->callback) {
+		tny_lockable_lock (info->session->priv->ui_lock);
 		info->callback (info->self, info->list, &info->err, info->user_data);
+		tny_lockable_unlock (info->session->priv->ui_lock);
+	}
 	return FALSE;
 }
 
Index: libtinymail-camel/tny-camel-account.c
===================================================================
--- libtinymail-camel/tny-camel-account.c	(revision 2551)
+++ libtinymail-camel/tny-camel-account.c	(working copy)
@@ -624,10 +624,11 @@
 {
 	RefreshStatusInfo *oinfo = user_data;
 	TnyProgressInfo *info = NULL;
+	TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (oinfo->self);
 
 	info = tny_progress_info_new (G_OBJECT (oinfo->self), oinfo->status_callback, 
 		oinfo->domain, oinfo->code, what, sofar, 
-		oftotal, oinfo->stopper, oinfo->user_data);
+		oftotal, oinfo->stopper, apriv->session->priv->ui_lock, oinfo->user_data);
 
 	if (oinfo->depth > 0)
 	{
@@ -1403,8 +1404,14 @@
 on_set_online_done_idle_func (gpointer data)
 {
 	OnSetOnlineInfo *info = (OnSetOnlineInfo *) data;
-	if (info->callback)
+	TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (info->account);
+	TnySessionCamel *session = apriv->session;
+
+	if (info->callback) {
+		tny_lockable_lock (session->priv->ui_lock);
 		info->callback (info->account, info->err);
+		tny_lockable_unlock (session->priv->ui_lock);
+	}
 	return FALSE;
 }
 
@@ -1774,13 +1781,55 @@
 	gpointer user_data;
 	gboolean cancelled;
 	TnyList *result;
-	/* This stops us from calling a status callback after the operation has 
-	 * finished. */
 	TnyIdleStopper* stopper;
 	GError *err;
 	TnySessionCamel *session;
+
+	GCond* condition;
+	gboolean had_callback;
+	GMutex *mutex;
+
 } GetSupportedAuthInfo;
 
+
+static gboolean 
+on_supauth_idle_func (gpointer user_data)
+{
+	GetSupportedAuthInfo *info = (GetSupportedAuthInfo *) user_data;
+
+	if (info->callback) {
+		tny_lockable_lock (info->session->priv->ui_lock);
+		info->callback (info->self, info->cancelled, info->result, &info->err, info->user_data);
+		tny_lockable_unlock (info->session->priv->ui_lock);
+	}
+
+	tny_idle_stopper_stop (info->stopper);
+}
+
+static void 
+on_supauth_destroy_func (gpointer user_data)
+{
+	GetSupportedAuthInfo *info = (GetSupportedAuthInfo *) user_data;
+
+	/* Thread reference */
+	g_object_unref (info->self);
+	camel_object_ref (info->session);
+
+	/* Result reference */
+	if (info->result)
+		g_object_unref (info->result);
+
+	tny_idle_stopper_destroy (info->stopper);
+	info->stopper = NULL;
+
+	if (info->condition) {
+		g_mutex_lock (info->mutex);
+		g_cond_broadcast (info->condition);
+		info->had_callback = TRUE;
+		g_mutex_unlock (info->mutex);
+	}
+}
+
 /* Starts the operation in the thread: */
 static gpointer 
 tny_camel_account_get_supported_secure_authentication_async_thread (
@@ -1792,6 +1841,9 @@
 	CamelException ex = CAMEL_EXCEPTION_INITIALISER;
 	GError *err = NULL;
 	TnyStatus* status;
+	GList *authtypes = NULL;
+	TnyList *result = NULL;
+	GList *iter = NULL;
 
 	g_static_rec_mutex_lock (priv->service_lock);
 
@@ -1799,47 +1851,26 @@
 		TNY_GET_SUPPORTED_SECURE_AUTH_STATUS_GET_SECURE_AUTH, 0, 1,
 		"Get secure authentication methods");
 
-	info->status_callback(G_OBJECT(self), 
-		status, info->user_data);
-  
-	/* Do the actual work:
-	 * This is happening in a thread, 
-	 * and the status callback is being called regularly while this is 
-	 * happening. */	
-	GList *authtypes = camel_service_query_auth_types (priv->service, &ex);
+	authtypes = camel_service_query_auth_types (priv->service, &ex);
+	/* Result reference */
+	result = tny_simple_list_new ();
+	iter = authtypes;
 
-	tny_status_set_fraction(status, 1);
-	info->status_callback(G_OBJECT(self), 
-		status, info->user_data);
-
-	/* The result will be a TnyList of TnyPairs: */
-	TnyList *result = tny_simple_list_new ();
-	GList *iter = authtypes;
-	while (iter) {
+	while (iter) 
+	{
 		CamelServiceAuthType *item = (CamelServiceAuthType *)iter->data;
 		if (item) {
-			/* Get the name of the auth method:
-			 * Note that, at least for IMAP, authproto=NULL when 
-			 * name=Password. */
-
-			/* We don't use the value part of the TnyPair. */
 			TnyPair *pair = tny_pair_new (item->name, NULL);
 			tny_list_append (result, G_OBJECT (pair));
 			g_object_unref (pair);
 		}
-		
 		iter = g_list_next (iter);
 	}
+
 	g_list_free (authtypes);
 	authtypes = NULL;
-	
-	
-	/* The work has finished, so clean up and provide the result via the 
-	 * main callback: */
 	info->result = result;
 
-	/* Create the GError if necessary,
-	 * from the CamelException: */
 	info->err = NULL;
 	if (camel_exception_is_set (&ex))
 	{
@@ -1852,26 +1883,31 @@
 
 	g_static_rec_mutex_unlock (priv->service_lock);
 
-	/* Call the callback, with the result, in an idle thread,
-	 * and stop this thread: */
-	if (info->callback) {
-		info->callback (info->self, info->cancelled, info->result, &info->err, info->user_data);
-	} else {
-		/* Thread reference */
-		g_object_unref (G_OBJECT (self));
-	}
+	info->mutex = g_mutex_new ();
+	info->condition = g_cond_new ();
+	info->had_callback = FALSE;
+
+	execute_callback (10, G_PRIORITY_HIGH, 
+		on_supauth_idle_func, 
+		info, on_supauth_destroy_func);
+
+	/* Wait on the queue for the mainloop callback to be finished */
+	g_mutex_lock (info->mutex);
+	if (!info->had_callback)
+		g_cond_wait (info->condition, info->mutex);
+	g_mutex_unlock (info->mutex);
+
+	g_mutex_free (info->mutex);
+	g_cond_free (info->condition);
+
+	g_slice_free (GetSupportedAuthInfo, info);
+
 	tny_status_free(status);
-	g_thread_exit (NULL);
 
 	return NULL;
 }
 
 
-/*TODO: This should be a vfunc so that it is generally available 
- * (and implementable) for other imlpementations. But this should not need a 
- * TnyAccount instance, so we need to find some other object to put the vfunc. 
- */
- 
 /** 
  * TnyCamelGetSupportedSecureAuthCallback:
  * @self: The TnyCamelAccount on which tny_camel_account_get_supported_secure_authentication() was called.
@@ -1901,20 +1937,8 @@
 { 
 	TnyCamelAccountPriv *priv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (self);
 	GetSupportedAuthInfo *info = NULL;
+	GError *err = NULL;
 
-	g_return_if_fail (callback);
-	g_return_if_fail (priv->session);
-
-	/* Store all the interesting info in a struct 
-	 * launch a thread and keep that struct-instance around.
-	 * - While the thread is running, we regularly call the status callback in 
-	 * an idle handler.
-	 * - When the thread is finished, the main callback will 
-	 * then be called in an idle handler.
-	 */
-
-	/* Check that the session is ready, and stop with a GError if it is not: */
-	GError *err = NULL;
 	if (!_tny_session_check_operation (priv->session, TNY_ACCOUNT (self), &err, 
 			TNY_ACCOUNT_ERROR, TNY_ACCOUNT_ERROR_GET_SUPPORTED_AUTH))
 	{
@@ -1924,8 +1948,6 @@
 		return;
 	}
 
-
-	/* Idle info for the status callback: */
 	info = g_slice_new (GetSupportedAuthInfo);
 	info->session = priv->session;
 	info->err = NULL;
@@ -1935,22 +1957,22 @@
 	info->status_callback = status_callback;
 	info->user_data = user_data;
 	
-	/* Use a ref count because we do not know which of the 2 idle callbacks 
-	 * will be the last, and we can only unref self in the last callback:
-	 * This is destroyed in the idle GDestroyNotify callback.
-	 * A shared copy is taken and released by the _tny_progress* callback,
-	 * so that it can prevent the stats callback from being called after 
-	 * the main callback. */
 	info->stopper = tny_idle_stopper_new();
 
 	/* thread reference */
-	g_object_ref (G_OBJECT (self));
+	g_object_ref (self);
+	camel_object_ref (info->session);
 
-	/* This will cause the idle status callback to be called,
-	 * via _tny_camel_account_start_camel_operation,
-	 * and also calls the idle main callback: */
 
-	g_thread_create (tny_camel_account_get_supported_secure_authentication_async_thread,
-		info, FALSE, NULL);
+	if (TNY_IS_CAMEL_STORE_ACCOUNT (self)) 
+	{
+		TnyCamelStoreAccountPriv *aspriv = TNY_CAMEL_STORE_ACCOUNT_GET_PRIVATE (self);
+		_tny_camel_queue_launch (aspriv->queue, 
+			tny_camel_account_get_supported_secure_authentication_async_thread, info,
+			__FUNCTION__);
+	} else {
+		g_thread_create (tny_camel_account_get_supported_secure_authentication_async_thread,
+			info, FALSE, NULL);
+	}
 }
 
Index: libtinymailui-gtk/tny-gtk-folder-store-tree-model.c
===================================================================
--- libtinymailui-gtk/tny-gtk-folder-store-tree-model.c	(revision 2551)
+++ libtinymailui-gtk/tny-gtk-folder-store-tree-model.c	(working copy)
@@ -827,75 +827,54 @@
 	return FALSE;
 }
 
-typedef struct {
-	TnyFolderObserver *self;
-	TnyFolderChange *change;
-} FolObsUpInfo;
 
-static gboolean
-folder_obsr_update_idle (gpointer user_data)
+
+static void
+tny_gtk_folder_store_tree_model_folder_obsr_update (TnyFolderObserver *self, TnyFolderChange *change)
 {
-	FolObsUpInfo *info = user_data;
-	TnyFolderObserver *self = info->self;
-	TnyFolderChange *change = info->change;
 	TnyFolderChangeChanged changed = tny_folder_change_get_changed (change);
-	GtkTreeModel *model = GTK_TREE_MODEL (self);
+	GtkTreeModel *model = (GtkTreeModel *) self;
 
 	if (changed & TNY_FOLDER_CHANGE_CHANGED_FOLDER_RENAME ||
 		changed & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT || 
 		changed & TNY_FOLDER_CHANGE_CHANGED_UNREAD_COUNT)
 	{
-		gdk_threads_enter ();
 		gtk_tree_model_foreach (model, updater, change);
-		gdk_threads_leave ();
 	}
-	return FALSE;
-}
 
-static void 
-folder_obsr_update_idle_destroy (gpointer user_data)
-{
-	FolObsUpInfo *info = user_data;
-	TnyFolderObserver *self = info->self;
-	TnyFolderChange *change = info->change;
-
-	g_object_unref (self);
-	g_object_unref (change);
-	g_slice_free (FolObsUpInfo, info);
-}
-
-static void
-tny_gtk_folder_store_tree_model_folder_obsr_update (TnyFolderObserver *self, TnyFolderChange *change)
-{
-	FolObsUpInfo *info = g_slice_new (FolObsUpInfo);
-	info->self = TNY_FOLDER_OBSERVER (g_object_ref (self));
-	info->change = TNY_FOLDER_CHANGE (g_object_ref (change));
-
-	g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
-		folder_obsr_update_idle, info,
-		folder_obsr_update_idle_destroy);
-
 	return;
 }
 
 
-typedef struct {
-	TnyFolderObserver *self;
-	TnyFolderStoreChange *change;
-} FolStObsUpInfo;
-
-static gboolean
-folder_store_obsr_update_idle (gpointer user_data)
+static void
+tny_gtk_folder_store_tree_model_store_obsr_update (TnyFolderStoreObserver *self, TnyFolderStoreChange *change)
 {
-	FolStObsUpInfo *info = user_data;
-	TnyFolderObserver *self = info->self;
-	TnyFolderStoreChange *change = info->change;
 	TnyFolderStoreChangeChanged changed = tny_folder_store_change_get_changed (change);
 	GtkTreeModel *model = GTK_TREE_MODEL (self);
 	TnyGtkFolderStoreTreeModel *me = (TnyGtkFolderStoreTreeModel*) self;
 
 	if (changed & TNY_FOLDER_STORE_CHANGE_CHANGED_CREATED_FOLDERS)
 	{
+		TnyList *created = tny_simple_list_new ();
+		TnyIterator *miter;
+
+		tny_folder_store_change_get_created_folders (change, created);
+		miter = tny_list_create_iterator (created);
+
+		while (!tny_iterator_is_done (miter))
+		{
+			TnyFolder *folder = TNY_FOLDER (tny_iterator_get_current (miter));
+			tny_folder_add_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (self));
+			tny_folder_store_add_observer (TNY_FOLDER_STORE (folder), TNY_FOLDER_STORE_OBSERVER (self));
+			g_object_unref (folder);
+			tny_iterator_next (miter);
+		}
+		g_object_unref (miter);
+		g_object_unref (created);
+	}
+
+	if (changed & TNY_FOLDER_STORE_CHANGE_CHANGED_CREATED_FOLDERS)
+	{
 		TnyFolderStore *parentstore = tny_folder_store_change_get_folder_store (change);
 		GtkTreeIter first, iter;
 
@@ -913,11 +892,6 @@
 				GtkTreeIter newiter;
 				TnyFolder *folder = TNY_FOLDER (tny_iterator_get_current (miter));
 
-				/* See early added below! (#CCUX)
-
-				tny_folder_add_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (self));
-				tny_folder_store_add_observer (TNY_FOLDER_STORE (folder), TNY_FOLDER_STORE_OBSERVER (self));*/
-
 				me->folder_observables = g_list_prepend (me->folder_observables, folder);
 				me->store_observables = g_list_prepend (me->store_observables, folder);
 
@@ -968,64 +942,6 @@
 	}
 
 
-	return FALSE;
-}
-
-static void
-folder_store_obsr_update_idle_destroy (gpointer user_data)
-{
-	FolStObsUpInfo *info = user_data;
-	TnyFolderObserver *self = info->self;
-	TnyFolderStoreChange *change = info->change;
-
-	g_object_unref (self);
-	g_object_unref (change);
-
-	g_slice_free (FolStObsUpInfo, info);
-}
-
-static void
-tny_gtk_folder_store_tree_model_store_obsr_update (TnyFolderStoreObserver *self, TnyFolderStoreChange *change)
-{
-	TnyFolderStoreChangeChanged changed = tny_folder_store_change_get_changed (change);
-	FolStObsUpInfo *info = g_slice_new (FolStObsUpInfo);
-	info->self = TNY_FOLDER_OBSERVER (g_object_ref (self));
-	info->change = TNY_FOLDER_STORE_CHANGE (g_object_ref (change));
-	
-	if (changed & TNY_FOLDER_STORE_CHANGE_CHANGED_CREATED_FOLDERS)
-	{
-		TnyList *created = tny_simple_list_new ();
-		TnyIterator *miter;
-
-		tny_folder_store_change_get_created_folders (change, created);
-		miter = tny_list_create_iterator (created);
-
-		while (!tny_iterator_is_done (miter))
-		{
-			TnyFolder *folder = TNY_FOLDER (tny_iterator_get_current (miter));
-
-			/* Already added! (#CCUX)
-			 * We can't add these in the idle because the thread might
-			 * be added subfolders right now! (the idle would register
-			 * self as an observer too late!) 
-			 * Question. though: is there any reason why not to do the
-			 * doubly-linked lists here too? (except for locking, which
-			 * would then be necessary of course) */
-
-			tny_folder_add_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (self));
-			tny_folder_store_add_observer (TNY_FOLDER_STORE (folder), TNY_FOLDER_STORE_OBSERVER (self));
-
-			g_object_unref (folder);
-			tny_iterator_next (miter);
-		}
-		g_object_unref (miter);
-		g_object_unref (created);
-	}
-
-	g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
-			folder_store_obsr_update_idle, info, 
-			folder_store_obsr_update_idle_destroy);
-
 	return;
 }
 
Index: libtinymail/tny-progress-info.c
===================================================================
--- libtinymail/tny-progress-info.c	(revision 2551)
+++ libtinymail/tny-progress-info.c	(working copy)
@@ -70,6 +70,7 @@
 	gint sofar;
 	gint oftotal;
 	TnyIdleStopper *stopper;
+	TnyLockable *ui_lock;
 	gpointer user_data;
 };
 
@@ -96,7 +97,7 @@
  * Return value: a #TnyProgressInfo instance that is ready to launch
  **/
 TnyProgressInfo*
-tny_progress_info_new (GObject *self, TnyStatusCallback status_callback, TnyStatusDomain domain, TnyStatusCode code, const gchar *what, gint sofar, gint oftotal, TnyIdleStopper* stopper, gpointer user_data)
+tny_progress_info_new (GObject *self, TnyStatusCallback status_callback, TnyStatusDomain domain, TnyStatusCode code, const gchar *what, gint sofar, gint oftotal, TnyIdleStopper* stopper, TnyLockable *ui_lock, gpointer user_data)
 {
 	TnyProgressInfo *info = g_slice_new (TnyProgressInfo);
 
@@ -105,6 +106,7 @@
 	info->status_callback = status_callback;
 	info->what = g_strdup (what);
 	info->self = g_object_ref (self);
+	info->ui_lock = g_object_ref (ui_lock);
 	info->user_data = user_data;
 	info->oftotal = oftotal;
 
@@ -143,7 +145,8 @@
 {
 	TnyProgressInfo *info = data;
 
-	g_object_unref (G_OBJECT (info->self));
+	g_object_unref (info->self);
+	g_object_unref (info->ui_lock);
 	g_free (info->what);
 	tny_idle_stopper_destroy (info->stopper);
 	info->stopper = NULL;
@@ -185,8 +188,10 @@
 			info->code, info->sofar, info->oftotal, 
 			info->what);
 
+		tny_lockable_lock (info->ui_lock);
 		info->status_callback (G_OBJECT (info->self), status, 
 			info->user_data);
+		tny_lockable_unlock (info->ui_lock);
 
 		tny_status_free (status);
 	}
Index: libtinymail/tny-merge-folder.c
===================================================================
--- libtinymail/tny-merge-folder.c	(revision 2551)
+++ libtinymail/tny-merge-folder.c	(working copy)
@@ -165,8 +165,9 @@
 {
 	SyncFolderInfo *info = thr_user_data;
 
-	if (info->callback)
+	if (info->callback) {
 		info->callback (info->self, info->cancelled, &info->err, info->user_data);
+	}
 
 	return FALSE;
 }
@@ -367,8 +368,9 @@
 {
 	GetMsgInfo *info = (GetMsgInfo *) thr_user_data;
 
-	if (info->callback) /* TODO: the cancelled field */
+	if (info->callback) { /* TODO: the cancelled field */
 		info->callback (info->self, FALSE, info->msg, &info->err, info->user_data);
+	}
 
 	return FALSE;
 }
@@ -474,6 +476,7 @@
 	GetHeadersFolderInfo *info = thr_user_data;
 	if (info->callback)
 		info->callback (info->self, info->cancelled, info->headers, &info->err, info->user_data);
+
 	return FALSE;
 }
 
Index: libtinymail/tny-common-priv.h
===================================================================
--- libtinymail/tny-common-priv.h	(revision 2551)
+++ libtinymail/tny-common-priv.h	(working copy)
@@ -23,6 +23,7 @@
 #include <tny-shared.h>
 #include <tny-status.h>
 #include <tny-error.h>
+#include <tny-lockable.h>
 
 #ifndef TINYMAIL_ENABLE_PRIVATE_API
 #error "This is private API that should only be used by tinymail internally."
@@ -38,7 +39,7 @@
 TnyIdleStopper* tny_idle_stopper_new (void);
 TnyIdleStopper* tny_idle_stopper_copy (TnyIdleStopper *stopper);
 
-TnyProgressInfo* tny_progress_info_new (GObject *self, TnyStatusCallback status_callback, TnyStatusDomain domain, TnyStatusCode code, const gchar *what, gint sofar, gint oftotal, TnyIdleStopper* stopper, gpointer user_data);
+TnyProgressInfo* tny_progress_info_new (GObject *self, TnyStatusCallback status_callback, TnyStatusDomain domain, TnyStatusCode code, const gchar *what, gint sofar, gint oftotal, TnyIdleStopper* stopper, TnyLockable *uid_lock, gpointer user_data);
 gboolean tny_progress_info_idle_func (gpointer data);
 void tny_progress_info_destroy (gpointer data);
 


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