Re: The GDK lock in tinymail



And the patch grows ...

This version of the patch adds GDK lock correctness for g_signal_emit
situations. A few are left uncovered as those require some
infrastructure changes (for example in TnyMergeFolder we don't yet have
the ui_lock).


On Sat, 2007-08-04 at 12:01 +0200, Philip Van Hoof wrote:
> On Fri, 2007-08-03 at 18:51 +0100, Rob Taylor wrote:
> > Philip Van Hoof wrote:
> > > This patch makes Tinymail's callbacks and observer's updates behave like
> > > signals in Gtk+.
> > > 
> > > Please review extensively 
> 
> > That's quite a complex patch! Could you explain it a bit?
> 
> o. The notify_folder_observers, and notify_folder_store_observers got a
>    _in_idle equivalent that will throw the function call into the
>    GMainLoop using a g_idle_add_full. This was done to in a generic way
>    escape the GDK lock or throw the call out of a thread
> 
> o. All locations where folder observers are now called, are in the
>    GMainLoop or at locations where it makes sense to lock the GDK lock
> 
> o. All tny_folder_store_observer_update and tny_folder_observer_update
>    have been wrapped with tny_lockable_lock and tny_lockable_unlock
> 
> o. All callbacks have been wrapped with tny_lockable_lock and
>    tny_lockable_unlock
> 
> o. notify_folder_observers_about_copy got rewritten
> 
> o. inform_observers_about_transfer got renamed to
>    notify_folder_observers_about_transfer
> 
> o. tny_camel_account_get_supported_secure_authentication got rewritten
> 
> o. tny_gtk_folder_store_tree_model_folder_obsr_update got rewritten (it
>    assumed that it got called from a thread, which is not the case
>    anymore)
> 
> o. tny_gtk_folder_store_tree_model_store_obsr_update got rewritten (it
>    assumed that it got called from a thread, which is not the case
>    anymore)
> 
> o. All status_callback invokes got wrapped by tny_lockable_lock and
>    tny_lockable_unlock (in tny-progress-info.c)
> 
> 
-- 
Philip Van Hoof, software developer
home: me at pvanhoof dot be 
gnome: pvanhoof at gnome dot org 
http://www.pvanhoof.be/blog



Index: libtinymail-gpe/tny-gpe-device.c
===================================================================
--- libtinymail-gpe/tny-gpe-device.c	(revision 2551)
+++ libtinymail-gpe/tny-gpe-device.c	(working copy)
@@ -1,4 +1,4 @@
-/* libtinymail-camel - The Tiny Mail base library for Camel
+/* libtinymail-gpe - The Tiny Mail base library for gpe
  * Copyright (C) 2006-2007 Philip Van Hoof <pvanhoof gnome org>
  *
  * This library is free software; you can redistribute it and/or
@@ -31,13 +31,16 @@
 static void tny_gpe_device_on_offline (TnyDevice *self);
 static gboolean tny_gpe_device_is_online (TnyDevice *self);
 
-static void
+
+static gboolean
 emit_status (TnyDevice *self)
 {
 	if (tny_gpe_device_is_online (self))
 		tny_gpe_device_on_online (self);
 	else
 		tny_gpe_device_on_offline (self);
+
+	return FALSE;
 }
 
 static void 
@@ -52,12 +55,16 @@
 
 	/* Signal if it changed: */
 	if (status_before != tny_gpe_device_is_online (self))
-		emit_status (self);
+		g_idle_add_full (G_PRIORITY_DEFAULT, 
+			(GSourceFunc) emit_status, 
+			g_object_ref (self), 
+			(GDestroyNotify) g_object_unref);
 }
 
 static void 
 tny_gpe_device_force_online (TnyDevice *self)
 {
+
 	TnyGpeDevicePriv *priv = TNY_GPE_DEVICE_GET_PRIVATE (self);
 
 	const gboolean already_online = tny_gpe_device_is_online (self);
@@ -67,8 +74,11 @@
 
 	/* Signal if it changed: */
 	if (!already_online)
-		emit_status (self);
-	
+		g_idle_add_full (G_PRIORITY_DEFAULT, 
+			(GSourceFunc) emit_status, 
+			g_object_ref (self), 
+			(GDestroyNotify) g_object_unref);
+
 	return;
 }
 
@@ -85,7 +95,10 @@
 
 	/* Signal if it changed: */
 	if (!already_offline)
-		emit_status (self);
+		g_idle_add_full (G_PRIORITY_DEFAULT, 
+			(GSourceFunc) emit_status, 
+			g_object_ref (self), 
+			(GDestroyNotify) g_object_unref);
 
 	return;
 }
@@ -93,7 +106,9 @@
 static void
 tny_gpe_device_on_online (TnyDevice *self)
 {
+	gdk_threads_enter ();
 	g_signal_emit (self, tny_device_signals [TNY_DEVICE_CONNECTION_CHANGED], 0, TRUE);
+	gdk_threads_leave ();
 
 	return;
 }
@@ -101,7 +116,9 @@
 static void
 tny_gpe_device_on_offline (TnyDevice *self)
 {
+	gdk_threads_enter ();
 	g_signal_emit (self, tny_device_signals [TNY_DEVICE_CONNECTION_CHANGED], 0, FALSE);
+	gdk_threads_leave ();
 
 	return;
 }
@@ -121,7 +138,7 @@
 static void
 tny_gpe_device_instance_init (GTypeInstance *instance, gpointer g_class)
 {
-	TnyGpeDevice *self = (TnyGpeDevice *)instance;
+	TnyGpeDevice *self = (TnyGpeDevice *) instance;
 	TnyGpeDevicePriv *priv = TNY_GPE_DEVICE_GET_PRIVATE (self);
 
 	return;
@@ -131,7 +148,7 @@
 /**
  * tny_gpe_device_new:
  *
- * Return value: A new #TnyDevice instance
+ * Return value: A new #TnyDevice implemented for GPE
  **/
 TnyDevice*
 tny_gpe_device_new (void)
@@ -145,8 +162,11 @@
 static void
 tny_gpe_device_finalize (GObject *object)
 {
+	TnyGpeDevice *self = (TnyGpeDevice *) object;
+	TnyGpeDevicePriv *priv = TNY_GPE_DEVICE_GET_PRIVATE (self);
+
 	(*parent_class->finalize) (object);
-    
+
 	return;
 }
 
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-send-queue.c
===================================================================
--- libtinymail-camel/tny-camel-send-queue.c	(revision 2551)
+++ libtinymail-camel/tny-camel-send-queue.c	(working copy)
@@ -55,19 +55,32 @@
 } ErrorInfo;
 
 typedef struct {
-       TnySendQueue *self;
-       TnyMsg *msg;
-       TnyHeader *header;
-       gint i, total;
-       guint signal_id;
+	TnySendQueue *self;
+	TnyMsg *msg;
+	TnyHeader *header;
+	gint i, total;
+	guint signal_id;
 } ControlInfo;
 
 static gboolean 
 emit_error_on_mainloop (gpointer data)
 {
 	ErrorInfo *info = data;
+	TnyCamelSendQueuePriv *priv = TNY_CAMEL_SEND_QUEUE_GET_PRIVATE (info->self);
+	TnyCamelAccountPriv *apriv = NULL;
+
+	if (priv->trans_account)
+		apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (priv->trans_account);
+
+	if (apriv)
+		tny_lockable_lock (apriv->session->priv->ui_lock);
+
 	g_signal_emit (info->self, tny_send_queue_signals [TNY_SEND_QUEUE_ERROR_HAPPENED], 
 				0, info->header, info->msg, info->error);
+
+	if (apriv)
+		tny_lockable_unlock (apriv->session->priv->ui_lock);
+
 	return FALSE;
 }
 
@@ -90,7 +103,12 @@
 emit_error (TnySendQueue *self, TnyHeader *header, TnyMsg *msg, GError *error, int i, int total)
 {
 	ErrorInfo *info = g_slice_new0 (ErrorInfo);
+	TnyCamelSendQueuePriv *priv = TNY_CAMEL_SEND_QUEUE_GET_PRIVATE (info->self);
+	TnyCamelAccountPriv *apriv = NULL;
 
+	if (priv->trans_account)
+		apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (priv->trans_account);
+
 	if (error != NULL)
 		info->error = g_error_copy ((const GError *) error);
 	if (self)
@@ -103,9 +121,15 @@
 	info->i = i;
 	info->total = total;
 
+	if (apriv)
+		tny_lockable_lock (apriv->session->priv->ui_lock);
+
 	g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
 		emit_error_on_mainloop, info, destroy_error_info);
 
+	if (apriv)
+		tny_lockable_unlock (apriv->session->priv->ui_lock);
+
 	return;
 }
 
@@ -113,47 +137,71 @@
 static gboolean 
 emit_control_signals_on_mainloop (gpointer data)
 {
-       ControlInfo *info = data;
-       g_signal_emit (info->self, tny_send_queue_signals [info->signal_id], 
-		      0, info->header, info->msg, info->i, info->total);
-       return FALSE;
+	ControlInfo *info = data;
+	TnyCamelSendQueuePriv *priv = TNY_CAMEL_SEND_QUEUE_GET_PRIVATE (info->self);
+	TnyCamelAccountPriv *apriv = NULL;
+
+	if (priv->trans_account)
+		apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (priv->trans_account);
+
+	if (apriv)
+		tny_lockable_lock (apriv->session->priv->ui_lock);
+
+	g_signal_emit (info->self, tny_send_queue_signals [info->signal_id], 
+		0, info->header, info->msg, info->i, info->total);
+
+	if (apriv)
+		tny_lockable_unlock (apriv->session->priv->ui_lock);
+
+	return FALSE;
 }
 
 static void
 destroy_control_info (gpointer data)
 {
-       ControlInfo *info = data;
+	ControlInfo *info = data;
 
-       if (info->msg)
-               g_object_unref (G_OBJECT (info->msg));
-       if (info->header)
-               g_object_unref (G_OBJECT (info->header));
-       if (info->self)
-               g_object_unref (G_OBJECT (info->self));
+	if (info->msg)
+		g_object_unref (G_OBJECT (info->msg));
+	if (info->header)
+		g_object_unref (G_OBJECT (info->header));
+	if (info->self)
+		g_object_unref (G_OBJECT (info->self));
 
-       g_slice_free (ControlInfo, info);
+	g_slice_free (ControlInfo, info);
 }
 
 static void
 emit_control (TnySendQueue *self, TnyHeader *header, TnyMsg *msg, guint signal_id, int i, int total)
 {
-       ControlInfo *info = g_slice_new0 (ControlInfo);
+	ControlInfo *info = g_slice_new0 (ControlInfo);
+	TnyCamelSendQueuePriv *priv = TNY_CAMEL_SEND_QUEUE_GET_PRIVATE (info->self);
+	TnyCamelAccountPriv *apriv = NULL;
 
-       if (self)
-               info->self = TNY_SEND_QUEUE (g_object_ref (G_OBJECT (self)));
-       if (msg)
-               info->msg = TNY_MSG (g_object_ref (G_OBJECT (msg)));
-       if (header)
-               info->header = TNY_HEADER (g_object_ref (G_OBJECT (header)));
+	if (priv->trans_account)
+		apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (priv->trans_account);
 
-       info->signal_id = signal_id;
-       info->i = i;
-       info->total = total;
-       
-       g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+	if (self)
+		info->self = TNY_SEND_QUEUE (g_object_ref (G_OBJECT (self)));
+	if (msg)
+		info->msg = TNY_MSG (g_object_ref (G_OBJECT (msg)));
+	if (header)
+		info->header = TNY_HEADER (g_object_ref (G_OBJECT (header)));
+
+	info->signal_id = signal_id;
+	info->i = i;
+	info->total = total;
+
+	if (apriv)
+		tny_lockable_lock (apriv->session->priv->ui_lock);
+
+	g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
 			emit_control_signals_on_mainloop, info, destroy_control_info);
 
-       return;
+	if (apriv)
+		tny_lockable_unlock (apriv->session->priv->ui_lock);
+
+	return;
 }
 
 
@@ -162,7 +210,6 @@
 {
 	TnySendQueue *self = (TnySendQueue *) data;
 	TnyCamelSendQueuePriv *priv = TNY_CAMEL_SEND_QUEUE_GET_PRIVATE (self);
-	/* TnyCamelAccountPriv *apriv = NULL; */
 	TnyFolder *sentbox, *outbox;
 	guint i = 0, length = 0;
 	TnyList *list;
@@ -172,10 +219,6 @@
 	priv->is_running = TRUE;
 	priv->creating_spin = FALSE;
 
-/*	apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (priv->trans_account);
-	if (apriv)
-		tny_session_camel_join_connecting (apriv->session); */
-
 	list = tny_simple_list_new ();
 
 	g_mutex_lock (priv->todo_lock);
@@ -254,7 +297,6 @@
 			}
 			if (to_remove)
 				g_list_free (to_remove);
-			/**/
 
 			length = tny_list_get_length (headers);
 
@@ -287,7 +329,7 @@
 
 			/* Emits msg-sending signal to inform a new msg is being sent */
 			emit_control (self, header, msg, TNY_SEND_QUEUE_MSG_SENDING, i, priv->total);
-			
+
 			if (err == NULL) 
 			{
 				tny_transport_account_send (priv->trans_account, msg, &err);
@@ -348,12 +390,12 @@
 errorhandler:
 
 
-	g_object_unref (G_OBJECT (sentbox));
-	g_object_unref (G_OBJECT (outbox));
+	g_object_unref (sentbox);
+	g_object_unref (outbox);
 
 	g_object_unref (self); /* The one added here */
 
-	g_object_unref (G_OBJECT (self));
+	g_object_unref (self);
 
 	priv->thread = NULL;
 	priv->is_running = FALSE;
@@ -371,8 +413,8 @@
 	{
 		while (priv->creating_spin);
 		priv->creating_spin = TRUE;
-		priv->thread = g_thread_create (thread_main, 
-			g_object_ref (self), TRUE, NULL);
+		g_object_ref (self);
+		priv->thread = g_thread_create (thread_main, self, TRUE, NULL);
 	}
 
 	return;
@@ -391,6 +433,8 @@
 
 	if (priv->thread)
 		g_thread_join (priv->thread);
+
+	return;
 }
 
 static void
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-session-camel.c
===================================================================
--- libtinymail-camel/tny-session-camel.c	(revision 2551)
+++ libtinymail-camel/tny-session-camel.c	(working copy)
@@ -719,7 +719,33 @@
 	return;
 }
 
+typedef struct {
+	TnySessionCamel *self;
+	TnyAccount *account;
+	gboolean online;
+} SetOnlHapInfo;
 
+static gboolean
+set_online_happened_idle (gpointer user_data)
+{
+	SetOnlHapInfo *info = (SetOnlHapInfo *) user_data;
+	tny_lockable_lock (info->self->priv->ui_lock);
+	g_signal_emit (info->account, 
+		tny_camel_account_signals [TNY_CAMEL_ACCOUNT_SET_ONLINE_HAPPENED], 
+		0, info->online);
+	tny_lockable_unlock (info->self->priv->ui_lock);
+	return FALSE;
+}
+
+static void
+set_online_happened_destroy (gpointer user_data)
+{
+	SetOnlHapInfo *info = (SetOnlHapInfo *) user_data;
+	camel_object_unref (info->self);
+	g_object_unref (info->account);
+	g_slice_free (SetOnlHapInfo, info);
+}
+
 static void 
 tny_session_queue_going_online_for_account (TnySessionCamel *self, TnyCamelAccount *account, gboolean online)
 {
@@ -741,8 +767,16 @@
 
 	if (TNY_IS_CAMEL_TRANSPORT_ACCOUNT (account))
 	{
-		g_signal_emit (account, 
-			tny_camel_account_signals [TNY_CAMEL_ACCOUNT_SET_ONLINE_HAPPENED], 0, online);
+		SetOnlHapInfo *info = g_slice_new (SetOnlHapInfo);
+
+		info->self = self;
+		camel_object_ref (info->self);
+		info->account = TNY_ACCOUNT (g_object_ref (account));
+		info->online = online;
+
+		g_idle_add_full (G_PRIORITY_DEFAULT, set_online_happened_idle, 
+			info, set_online_happened_destroy);
+
 		return;
 	}
 }
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,35 +69,84 @@
 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)
 {
 	TnyAccount *self = (TnyAccount *) data;
 	TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (self);
 
+	tny_lockable_lock (apriv->session->priv->ui_lock);
 	g_signal_emit (G_OBJECT (self), 
 		tny_account_signals [TNY_ACCOUNT_CONNECTION_STATUS_CHANGED], 
 			0, apriv->status);
+	tny_lockable_unlock (apriv->session->priv->ui_lock);
 
 	return FALSE;
 }
@@ -434,7 +483,37 @@
  * subscribe parameter is TRUE, then we're asking for a folder
  * subscription, else for a folder unsubscription */
 
+typedef struct {
+	TnySessionCamel *session;
+	GObject *self, *folder;
+} SetSubsInfo;
+
+static gboolean 
+set_subscription_idle (gpointer user_data)
+{
+	SetSubsInfo *info = (SetSubsInfo *) user_data;
+
+	tny_lockable_lock (info->session->priv->ui_lock);
+	g_signal_emit (info->self, 
+		tny_store_account_signals [TNY_STORE_ACCOUNT_SUBSCRIPTION_CHANGED], 
+		0, info->folder);
+	tny_lockable_unlock (info->session->priv->ui_lock);
+
+	return FALSE;
+}
+
 static void
+set_subscription_destroy (gpointer user_data)
+{
+	SetSubsInfo *info = (SetSubsInfo *) user_data;
+	g_object_unref (info->self);
+	g_object_unref (info->folder);
+	camel_object_unref (info->session);
+	g_slice_free (SetSubsInfo, info);
+	return;
+}
+
+static void
 set_subscription (TnyStoreAccount *self, TnyFolder *folder, gboolean subscribe)
 {
 	TnyCamelAccountPriv *apriv;
@@ -484,17 +563,24 @@
 		camel_exception_clear (&ex);
 	} else 
 	{
+		SetSubsInfo *info = g_slice_new (SetSubsInfo);
+
 		/* Sync */
 		_tny_camel_folder_set_subscribed (TNY_CAMEL_FOLDER (folder), subscribe);
-		
-		g_signal_emit (self, 
-			       tny_store_account_signals [TNY_STORE_ACCOUNT_SUBSCRIPTION_CHANGED], 
-			       0, folder);
+
+		info->session = apriv->session;
+		camel_object_ref (info->session);
+		info->self = g_object_ref (self);
+		info->folder = g_object_ref (folder);
+
+		g_idle_add_full (G_PRIORITY_DEFAULT, set_subscription_idle, info,
+			set_subscription_destroy);
+
 	}
-	camel_object_unref (CAMEL_OBJECT (cfolder));
+	camel_object_unref (cfolder);
 
 cleanup:
-	camel_object_unref (CAMEL_OBJECT (store));
+	camel_object_unref (store);
 }
 
 static void
@@ -546,6 +632,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 +672,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 +753,8 @@
 		camel_exception_clear (&ex);
 	} else 
 	{
+		TnyFolderStoreChange *change = NULL;
+
 		if (aspriv->iter)
 		{
 			/* Known memleak
@@ -673,11 +765,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 +978,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 +1209,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 +1295,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)
@@ -69,8 +69,10 @@
 	TnyAccount *self = (TnyAccount *) data;
 	TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (self);
 
+	tny_lockable_lock (apriv->session->priv->ui_lock);
 	g_signal_emit (G_OBJECT (self), 
 		tny_account_signals [TNY_ACCOUNT_CHANGED], 0);
+	tny_lockable_unlock (apriv->session->priv->ui_lock);
 
 	return FALSE;
 }
@@ -624,10 +626,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)
 	{
@@ -1220,6 +1223,52 @@
  * always happen in a thread. In fact, it will always happen in the operations
  * queue of @self (else it's a bug). */
 
+typedef struct {
+	TnySessionCamel *session;
+	TnyAccount *account;
+	gboolean online;
+} SetOnlInfo;
+
+
+static gboolean
+set_online_happened_idle (gpointer user_data)
+{
+	SetOnlInfo *info = (SetOnlInfo *) user_data;
+	tny_lockable_lock (info->session->priv->ui_lock);
+	g_signal_emit (info->account, 
+		tny_camel_account_signals [TNY_CAMEL_ACCOUNT_SET_ONLINE_HAPPENED], 
+		0, info->online);
+	tny_lockable_unlock (info->session->priv->ui_lock);
+	return FALSE;
+}
+
+static void
+set_online_happened_destroy (gpointer user_data)
+{
+	SetOnlInfo *info = (SetOnlInfo *) user_data;
+	camel_object_unref (info->session);
+	g_object_unref (info->account);
+	g_slice_free (SetOnlInfo, info);
+	return;
+}
+
+static void
+set_online_happened (TnySessionCamel *session, TnyCamelAccount *account, gboolean online)
+{
+	SetOnlInfo *info = g_slice_new (SetOnlInfo);
+
+	info->session = session;
+	camel_object_ref (info->session);
+	info->account = TNY_ACCOUNT (g_object_ref (account));
+	info->online = online;
+
+	g_idle_add_full (G_PRIORITY_DEFAULT, set_online_happened_idle, 
+		info, set_online_happened_destroy);
+
+	return;
+}
+
+
 void 
 _tny_camel_account_set_online (TnyCamelAccount *self, gboolean online, GError **err)
 {
@@ -1268,8 +1317,7 @@
 			}
 
 			if (!camel_exception_is_set (&ex))
-				g_signal_emit (self, 
-					tny_camel_account_signals [TNY_CAMEL_ACCOUNT_SET_ONLINE_HAPPENED], 0, TRUE);
+				set_online_happened (priv->session, self, TRUE);
 
 			goto done;
 
@@ -1308,8 +1356,7 @@
 			}
 
 			if (!camel_exception_is_set (&ex))
-				g_signal_emit (self, 
-					tny_camel_account_signals [TNY_CAMEL_ACCOUNT_SET_ONLINE_HAPPENED], 0, TRUE);
+				set_online_happened (priv->session, self, TRUE);
 
 			goto done;
 		} else {
@@ -1345,8 +1392,7 @@
 		}
 
 		if (!camel_exception_is_set (&ex))
-			g_signal_emit (self, 
-				tny_camel_account_signals [TNY_CAMEL_ACCOUNT_SET_ONLINE_HAPPENED], 0, FALSE);
+			set_online_happened (priv->session, self, FALSE);
 
 	}
 
@@ -1403,8 +1449,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;
 }
 
@@ -1492,19 +1544,16 @@
 void 
 tny_camel_account_set_online_default (TnyCamelAccount *self, gboolean online, TnyCamelSetOnlineCallback callback)
 {
+	TnyCamelAccountPriv *priv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (self);
+	TnySessionCamel *session = priv->session;
 
 	/* In case we  are a store account, this means that we need to throw the 
 	 * request to go online to the account's queue. */
 
 	if (TNY_IS_CAMEL_STORE_ACCOUNT (self))
-	{
-		TnyCamelAccountPriv *priv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (self);
-		TnySessionCamel *session = priv->session;
-
 		_tny_camel_store_account_queue_going_online (
 			TNY_CAMEL_STORE_ACCOUNT (self), session, online, 
 			on_set_online_done, (gpointer) callback);
-	}
 
 
 	/* Else, if it's a transport account, we don't have any transport 
@@ -1513,11 +1562,7 @@
 	 * current implementations will automatically connect themselves. */
 
 	if (TNY_IS_CAMEL_TRANSPORT_ACCOUNT (self))
-	{
-		g_signal_emit (self, 
-			tny_camel_account_signals [TNY_CAMEL_ACCOUNT_SET_ONLINE_HAPPENED], 0, online);
-		return;
-	}
+		set_online_happened (session, self, online);
 }
 
 static gboolean
@@ -1774,13 +1819,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 +1879,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 +1889,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 +1921,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 +1975,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 +1986,6 @@
 		return;
 	}
 
-
-	/* Idle info for the status callback: */
 	info = g_slice_new (GetSupportedAuthInfo);
 	info->session = priv->session;
 	info->err = NULL;
@@ -1935,22 +1995,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: tests/shared/device.c
===================================================================
--- tests/shared/device.c	(revision 2551)
+++ tests/shared/device.c	(working copy)
@@ -73,7 +73,9 @@
 static void
 tny_test_device_on_online (TnyDevice *self)
 {
+	/* TNY TODO: tny_lockable_lock (ui_lock); */
 	g_signal_emit (self, tny_device_signals [TNY_DEVICE_CONNECTION_CHANGED], 0, TRUE);
+	/* TNY TODO: tny_lockable_unlock (ui_lock); */
 
 	return;
 }
@@ -81,7 +83,9 @@
 static void
 tny_test_device_on_offline (TnyDevice *self)
 {
+	/* TNY TODO: tny_lockable_lock (ui_lock); */
 	g_signal_emit (self, tny_device_signals [TNY_DEVICE_CONNECTION_CHANGED], 0, FALSE);
+	/* TNY TODO: tny_lockable_unlock (ui_lock); */
 
 	return;
 }
Index: libtinymail-maemo/tny-maemo-device.c
===================================================================
--- libtinymail-maemo/tny-maemo-device.c	(revision 2551)
+++ libtinymail-maemo/tny-maemo-device.c	(working copy)
@@ -1,4 +1,4 @@
-/* libtinymail-camel - The Tiny Mail base library for Camel
+/* libtinymail-maemo - The Tiny Mail base library for maemo
  * Copyright (C) 2006-2007 Philip Van Hoof <pvanhoof gnome org>
  *
  * This library is free software; you can redistribute it and/or
@@ -25,39 +25,59 @@
 
 static GObjectClass *parent_class = NULL;
 
+#include "tny-maemo-device-priv.h"
 
-typedef struct {
-	gboolean fset, forced;
-} TnyMaemoDevicePriv;
-
-#define TNY_MAEMO_DEVICE_GET_PRIVATE(o)	\
-	(G_TYPE_INSTANCE_GET_PRIVATE ((o), TNY_TYPE_MAEMO_DEVICE, TnyMaemoDevicePriv))
-
-
 static void tny_maemo_device_on_online (TnyDevice *self);
 static void tny_maemo_device_on_offline (TnyDevice *self);
 static gboolean tny_maemo_device_is_online (TnyDevice *self);
 
 
+static gboolean
+emit_status (TnyDevice *self)
+{
+	if (tny_maemo_device_is_online (self))
+		tny_maemo_device_on_online (self);
+	else
+		tny_maemo_device_on_offline (self);
+
+	return FALSE;
+}
+
 static void 
 tny_maemo_device_reset (TnyDevice *self)
 {
 	TnyMaemoDevicePriv *priv = TNY_MAEMO_DEVICE_GET_PRIVATE (self);
 
+	const gboolean status_before = tny_maemo_device_is_online (self);
+
 	priv->fset = FALSE;
 	priv->forced = FALSE;
 
+	/* Signal if it changed: */
+	if (status_before != tny_maemo_device_is_online (self))
+		g_idle_add_full (G_PRIORITY_DEFAULT, 
+			(GSourceFunc) emit_status, 
+			g_object_ref (self), 
+			(GDestroyNotify) g_object_unref);
 }
 
 static void 
 tny_maemo_device_force_online (TnyDevice *self)
 {
+
 	TnyMaemoDevicePriv *priv = TNY_MAEMO_DEVICE_GET_PRIVATE (self);
 
+	const gboolean already_online = tny_maemo_device_is_online (self);
+
 	priv->fset = TRUE;
 	priv->forced = TRUE;
 
-	tny_maemo_device_on_online (self);
+	/* Signal if it changed: */
+	if (!already_online)
+		g_idle_add_full (G_PRIORITY_DEFAULT, 
+			(GSourceFunc) emit_status, 
+			g_object_ref (self), 
+			(GDestroyNotify) g_object_unref);
 
 	return;
 }
@@ -68,10 +88,17 @@
 {
 	TnyMaemoDevicePriv *priv = TNY_MAEMO_DEVICE_GET_PRIVATE (self);
 
+	const gboolean already_offline = !tny_maemo_device_is_online (self);
+
 	priv->fset = TRUE;
 	priv->forced = FALSE;
 
-	tny_maemo_device_on_offline (self);
+	/* Signal if it changed: */
+	if (!already_offline)
+		g_idle_add_full (G_PRIORITY_DEFAULT, 
+			(GSourceFunc) emit_status, 
+			g_object_ref (self), 
+			(GDestroyNotify) g_object_unref);
 
 	return;
 }
@@ -79,7 +106,9 @@
 static void
 tny_maemo_device_on_online (TnyDevice *self)
 {
+	gdk_threads_enter ();
 	g_signal_emit (self, tny_device_signals [TNY_DEVICE_CONNECTION_CHANGED], 0, TRUE);
+	gdk_threads_leave ();
 
 	return;
 }
@@ -87,7 +116,9 @@
 static void
 tny_maemo_device_on_offline (TnyDevice *self)
 {
+	gdk_threads_enter ();
 	g_signal_emit (self, tny_device_signals [TNY_DEVICE_CONNECTION_CHANGED], 0, FALSE);
+	gdk_threads_leave ();
 
 	return;
 }
@@ -117,14 +148,13 @@
 /**
  * tny_maemo_device_new:
  *
- * Return value: A new #TnyDevice instance
+ * Return value: A new #TnyDevice implemented for MAEMO
  **/
 TnyDevice*
 tny_maemo_device_new (void)
 {
 	TnyMaemoDevice *self = g_object_new (TNY_TYPE_MAEMO_DEVICE, NULL);
 
-
 	return TNY_DEVICE (self);
 }
 
@@ -132,6 +162,9 @@
 static void
 tny_maemo_device_finalize (GObject *object)
 {
+	TnyMaemoDevice *self = (TnyMaemoDevice *) object;
+	TnyMaemoDevicePriv *priv = TNY_MAEMO_DEVICE_GET_PRIVATE (self);
+
 	(*parent_class->finalize) (object);
 
 	return;
@@ -206,3 +239,4 @@
 
 	return type;
 }
+
Index: libtinymail-maemo/tny-maemo-conic-device.c
===================================================================
--- libtinymail-maemo/tny-maemo-conic-device.c	(revision 2551)
+++ libtinymail-maemo/tny-maemo-conic-device.c	(working copy)
@@ -77,7 +77,48 @@
 	(G_TYPE_INSTANCE_GET_PRIVATE ((o), TNY_TYPE_MAEMO_CONIC_DEVICE, TnyMaemoConicDevicePriv))
 
 
+typedef struct {
+	GObject *self;
+	gboolean status;
+} EmitStatusInfo;
+
+static gboolean
+conic_emit_status_idle (gpointer user_data)
+{
+	EmitStatusInfo *info = (EmitStatusInfo *) user_data;
+
+	gdk_threads_enter ();
+	g_signal_emit (info->self, tny_device_signals [TNY_DEVICE_CONNECTION_CHANGED],
+		0, self->status);
+	gdk_threads_leave ();
+
+	return FALSE;
+}
+
+static void
+conic_emit_status_destroy (gpointer user_data)
+{
+	EmitStatusInfo *info = (EmitStatusInfo *) user_data;
+	g_object_unref (info->self);
+	g_slice_free (EmitStatusInfo, info);
+	return;
+}
+
 static void 
+conic_emit_status (TnyDevice *self, gboolean status)
+{
+	EmitStatusInfo *info = g_slice_new (EmitStatusInfo);
+
+	info->self = g_object_ref (self);
+	info->status = status;
+
+	g_idle_add_full (G_PRIORITY_DEFAULT, conic_emit_status_idle,
+		info, conic_emit_status_destroy);
+
+	return;
+}
+
+static void 
 tny_maemo_conic_device_reset (TnyDevice *device)
 {
 	TnyMaemoConicDevice *self;
@@ -91,8 +132,7 @@
 	priv->forced = FALSE;
 
 	if (status_before != tny_maemo_conic_device_is_online (device))
-		g_signal_emit (device, tny_device_signals [TNY_DEVICE_CONNECTION_CHANGED],
-		       0, !status_before);
+		conic_emit_status (device, !status_before);
 }
 
 static void 
@@ -170,8 +210,9 @@
 	priv->forced = FALSE; /* is_online is now accurate. */
 	g_message ("DEBUG: %s: emitting signal CONNECTION_CHANGED: %s", 
 		   __FUNCTION__, is_online ? "online" : "offline");
-	g_signal_emit (device, tny_device_signals [TNY_DEVICE_CONNECTION_CHANGED],
-		       0, is_online);
+
+	conic_emit_status (device, is_online);
+
 }
 
 #ifdef MAEMO_CONIC_DUMMY
@@ -186,7 +227,8 @@
 	return filename;
 }
 
-static gboolean dummy_con_ic_connection_connect_by_id (TnyMaemoConicDevice *self, const gchar* iap_id)
+static gboolean 
+dummy_con_ic_connection_connect_by_id (TnyMaemoConicDevice *self, const gchar* iap_id)
 {
 	/* Show a dialog, because libconic would show a dialog here,
 	 * and give the user a chance to refuse a new connection, because libconic would allow that too.
@@ -223,7 +265,8 @@
 }
 
 #endif /* MAEMO_CONIC_DUMMY */
-	
+
+
 /**
  * tny_maemo_conic_device_connect:
  * @self: a #TnyDevice object
@@ -248,12 +291,12 @@
 
 	g_return_val_if_fail (TNY_IS_DEVICE(self), FALSE);
 	priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
-	
+
 	g_return_val_if_fail (priv->cnx, FALSE);
 
 	g_message (__FUNCTION__);
 	g_message ("connecting to %s", iap_id ? iap_id : "<any>");
-	
+
 	priv->loop = g_main_loop_new(NULL, FALSE /* not running immediately. */);
 
 	gboolean request_failed = FALSE;
@@ -311,10 +354,9 @@
 
 	g_return_val_if_fail (TNY_IS_MAEMO_CONIC_DEVICE(self), FALSE);
 
-	priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);	
+	priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
 	g_return_val_if_fail (priv->cnx, FALSE);
 
-	
 	g_message (__FUNCTION__);
 	g_message ("disconnecting from %s", iap_id ? iap_id : "<any>");
 
@@ -341,14 +383,13 @@
 {
 	TnyMaemoConicDevice *self = TNY_MAEMO_CONIC_DEVICE (user_data);
 	TnyMaemoConicDevicePriv *priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
-		
 	/* Check whether the enviroment variable has changed, 
 	 * so we can fake a connection change: */
 	gchar *filename = get_dummy_filename ();
-		
 	gchar *contents = 0;
 	GError* error = 0;
 	gboolean test = g_file_get_contents (filename, &contents, NULL, &error);
+
 	if(error) {
 		/* printf("%s: error from g_file_get_contents(): %s\n", __FUNCTION__, error->message); */
 		g_error_free (error);
@@ -382,8 +423,9 @@
 		}
 		
 		printf ("DEBUG1: %s: emitting is_online=%d\n", __FUNCTION__, priv->is_online);
-		g_signal_emit (self, tny_device_signals [TNY_DEVICE_CONNECTION_CHANGED],
-		       0, priv->is_online);
+
+		conic_emit_status (self, priv->is_online);
+
 	}
 	
 	g_free (contents);
@@ -404,20 +446,21 @@
  **/
 const gchar*
 tny_maemo_conic_device_get_current_iap_id (TnyMaemoConicDevice *self)
-{	
+{
+	TnyMaemoConicDevicePriv *priv = NULL;
+
 	g_return_val_if_fail (TNY_IS_MAEMO_CONIC_DEVICE(self), NULL);
 	g_return_val_if_fail (tny_maemo_conic_device_is_online(TNY_DEVICE(self)), NULL);
 
-	TnyMaemoConicDevicePriv *priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
-	
+	priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
+
 	#ifdef MAEMO_CONIC_DUMMY
 	on_dummy_connection_check (self);
-	
 	/* Handle the special "none" text: */
 	if (priv->iap && (strcmp (priv->iap, MAEMO_CONIC_DUMMY_IAP_ID_NONE) == 0))
 		return NULL;
 	#endif
-	
+
 	return priv->iap;
 }
 
@@ -571,22 +614,19 @@
 	return;
 #endif /*MAEMO_CONIC_DUMMY*/
 
-
-
 	const gboolean already_offline = !tny_maemo_conic_device_is_online (device);
 
 	priv->forced = TRUE;
 
 	/* Signal if it changed: */
 	if (!already_offline)
-		g_signal_emit (device, tny_device_signals [TNY_DEVICE_CONNECTION_CHANGED],
-		       0, FALSE);
+		conic_emit_status (device, FALSE);
 }
 
 static gboolean
 tny_maemo_conic_device_is_online (TnyDevice *self)
 {
-	g_return_val_if_fail (TNY_IS_DEVICE(self), FALSE);	
+	g_return_val_if_fail (TNY_IS_DEVICE(self), FALSE);
 
 	#ifdef MAEMO_CONIC_DUMMY
 	on_dummy_connection_check(self);
Index: libtinymailui-mozembed/tny-moz-embed-stream.c
===================================================================
--- libtinymailui-mozembed/tny-moz-embed-stream.c	(revision 2551)
+++ libtinymailui-mozembed/tny-moz-embed-stream.c	(working copy)
@@ -205,22 +205,6 @@
 }
 
 
-/* Fire "children_changed::add" event to refresh "UI-Grab" window of GOK,
-* this event is not fired when using gtk_moz_embed_xxx_stream,
-* see Mozilla bug #293670.  Done in a timeout to allow mozilla to
-* actually draw to the screen 
-
-static gboolean
-timeout_update_gok (GtkMozEmbed *html)
-{
-	GtkWidget *widget = gtk_widget_get_accessible (GTK_WIDGET (html));
-
-	if (widget
-	g_signal_emit_by_name (gtk_widget_get_accessible (GTK_WIDGET (html)),
-		"children_changed::add", -1, NULL, NULL);
-	return FALSE;
-} */
-
 static gint
 tny_moz_embed_stream_close (TnyStream *self)
 {
Index: libtinymail-gnome-desktop/tny-gnome-device.c
===================================================================
--- libtinymail-gnome-desktop/tny-gnome-device.c	(revision 2551)
+++ libtinymail-gnome-desktop/tny-gnome-device.c	(working copy)
@@ -41,13 +41,15 @@
 static void tny_gnome_device_on_offline (TnyDevice *self);
 static gboolean tny_gnome_device_is_online (TnyDevice *self);
 
-static void
+static gboolean
 emit_status (TnyDevice *self)
 {
 	if (tny_gnome_device_is_online (self))
 		tny_gnome_device_on_online (self);
 	else
 		tny_gnome_device_on_offline (self);
+
+	return FALSE;
 }
 
 
@@ -75,7 +77,12 @@
 
 	/* Signal if it changed: */
 	if (status_before != tny_gnome_device_is_online (self))
-		emit_status (self);
+		g_idle_add_full (G_PRIORITY_DEFAULT, 
+			(GSourceFunc) emit_status, 
+			g_object_ref (self), 
+			(GDestroyNotify) g_object_unref);
+
+	return;
 }
 
 static void 
@@ -90,8 +97,11 @@
 
 	/* Signal if it changed: */
 	if (!already_online)
-		emit_status (self);
-	
+		g_idle_add_full (G_PRIORITY_DEFAULT, 
+			(GSourceFunc) emit_status, 
+			g_object_ref (self), 
+			(GDestroyNotify) g_object_unref);
+
 	return;
 }
 
@@ -108,15 +118,20 @@
 
 	/* Signal if it changed: */
 	if (!already_offline)
-		emit_status (self);
-	
+		g_idle_add_full (G_PRIORITY_DEFAULT, 
+			(GSourceFunc) emit_status, 
+			g_object_ref (self), 
+			(GDestroyNotify) g_object_unref);
+
 	return;
 }
 
 static void
 tny_gnome_device_on_online (TnyDevice *self)
 {
+	gdk_threads_enter ();
 	g_signal_emit (self, tny_device_signals [TNY_DEVICE_CONNECTION_CHANGED], 0, TRUE);
+	gdk_threads_leave ();
 
 	return;
 }
@@ -124,7 +139,9 @@
 static void
 tny_gnome_device_on_offline (TnyDevice *self)
 {
+	gdk_threads_enter ();
 	g_signal_emit (self, tny_device_signals [TNY_DEVICE_CONNECTION_CHANGED], 0, FALSE);
+	gdk_threads_leave ();
 
 	return;
 }
Index: libtinymail-olpc/tny-olpc-device.c
===================================================================
--- libtinymail-olpc/tny-olpc-device.c	(revision 2551)
+++ libtinymail-olpc/tny-olpc-device.c	(working copy)
@@ -1,4 +1,4 @@
-/* libtinymail-camel - The Tiny Mail base library for Camel
+/* libtinymail-olpc - The Tiny Mail base library for olpc
  * Copyright (C) 2006-2007 Philip Van Hoof <pvanhoof gnome org>
  *
  * This library is free software; you can redistribute it and/or
@@ -32,13 +32,15 @@
 static gboolean tny_olpc_device_is_online (TnyDevice *self);
 
 
-static void
+static gboolean
 emit_status (TnyDevice *self)
 {
 	if (tny_olpc_device_is_online (self))
 		tny_olpc_device_on_online (self);
 	else
 		tny_olpc_device_on_offline (self);
+
+	return FALSE;
 }
 
 static void 
@@ -53,7 +55,10 @@
 
 	/* Signal if it changed: */
 	if (status_before != tny_olpc_device_is_online (self))
-		emit_status (self);
+		g_idle_add_full (G_PRIORITY_DEFAULT, 
+			(GSourceFunc) emit_status, 
+			g_object_ref (self), 
+			(GDestroyNotify) g_object_unref);
 }
 
 static void 
@@ -69,8 +74,11 @@
 
 	/* Signal if it changed: */
 	if (!already_online)
-		emit_status (self);
-	
+		g_idle_add_full (G_PRIORITY_DEFAULT, 
+			(GSourceFunc) emit_status, 
+			g_object_ref (self), 
+			(GDestroyNotify) g_object_unref);
+
 	return;
 }
 
@@ -87,15 +95,20 @@
 
 	/* Signal if it changed: */
 	if (!already_offline)
-		emit_status (self);
-	
+		g_idle_add_full (G_PRIORITY_DEFAULT, 
+			(GSourceFunc) emit_status, 
+			g_object_ref (self), 
+			(GDestroyNotify) g_object_unref);
+
 	return;
 }
 
 static void
 tny_olpc_device_on_online (TnyDevice *self)
 {
+	gdk_threads_enter ();
 	g_signal_emit (self, tny_device_signals [TNY_DEVICE_CONNECTION_CHANGED], 0, TRUE);
+	gdk_threads_leave ();
 
 	return;
 }
@@ -103,7 +116,9 @@
 static void
 tny_olpc_device_on_offline (TnyDevice *self)
 {
+	gdk_threads_enter ();
 	g_signal_emit (self, tny_device_signals [TNY_DEVICE_CONNECTION_CHANGED], 0, FALSE);
+	gdk_threads_leave ();
 
 	return;
 }
@@ -123,7 +138,7 @@
 static void
 tny_olpc_device_instance_init (GTypeInstance *instance, gpointer g_class)
 {
-	TnyOlpcDevice *self = (TnyOlpcDevice *)instance;
+	TnyOlpcDevice *self = (TnyOlpcDevice *) instance;
 	TnyOlpcDevicePriv *priv = TNY_OLPC_DEVICE_GET_PRIVATE (self);
 
 	return;
@@ -147,7 +162,7 @@
 static void
 tny_olpc_device_finalize (GObject *object)
 {
-	TnyOlpcDevice *self = (TnyOlpcDevice *)object;	
+	TnyOlpcDevice *self = (TnyOlpcDevice *) object;
 	TnyOlpcDevicePriv *priv = TNY_OLPC_DEVICE_GET_PRIVATE (self);
 
 	(*parent_class->finalize) (object);
Index: libtinymail/tny-combined-account.c
===================================================================
--- libtinymail/tny-combined-account.c	(revision 2551)
+++ libtinymail/tny-combined-account.c	(working copy)
@@ -361,8 +361,10 @@
 {
 	GObject *self = user_data;
 
+	/* TNY TODO: tny_lockable_lock (ui_lock); */
 	g_signal_emit (self,  tny_store_account_signals [TNY_STORE_ACCOUNT_SUBSCRIPTION_CHANGED], 
 		0, folder);
+	/* TNY TODO: tny_lockable_unlock (ui_lock); */
 }
 
 /**
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)
@@ -63,7 +63,9 @@
 	while (!tny_iterator_is_done (iter))
 	{
 		TnyFolderObserver *observer = TNY_FOLDER_OBSERVER (tny_iterator_get_current (iter));
+		/* TNY TODO: tny_lockable_lock (ui_lock); */
 		tny_folder_observer_update (observer, change);
+		/* TNY TODO: tny_lockable_unlock (ui_lock); */
 		g_object_unref (G_OBJECT (observer));
 		tny_iterator_next (iter);
 	}
@@ -165,8 +167,11 @@
 {
 	SyncFolderInfo *info = thr_user_data;
 
-	if (info->callback)
+	if (info->callback) {
+		/* TNY TODO: tny_lockable_lock (ui_lock); */
 		info->callback (info->self, info->cancelled, &info->err, info->user_data);
+		/* TNY TODO: tny_lockable_unlock (ui_lock); */
+	}
 
 	return FALSE;
 }
@@ -367,8 +372,13 @@
 {
 	GetMsgInfo *info = (GetMsgInfo *) thr_user_data;
 
-	if (info->callback) /* TODO: the cancelled field */
+	if (info->callback) { 
+		/* TNY TODO: the cancelled field */
+
+		/* TNY TODO: tny_lockable_lock (ui_lock); */
 		info->callback (info->self, FALSE, info->msg, &info->err, info->user_data);
+		/* TNY TODO: tny_lockable_unlock (ui_lock); */
+	}
 
 	return FALSE;
 }
@@ -472,8 +482,13 @@
 get_headers_async_callback (gpointer thr_user_data)
 {
 	GetHeadersFolderInfo *info = thr_user_data;
-	if (info->callback)
+
+	if (info->callback) {
+		/* TNY TODO: tny_lockable_lock (ui_lock); */
 		info->callback (info->self, info->cancelled, info->headers, &info->err, info->user_data);
+		/* TNY TODO: tny_lockable_unlock (ui_lock); */
+	}
+
 	return FALSE;
 }
 
@@ -832,10 +847,14 @@
 {
 	RefreshFolderInfo *info = thr_user_data;
 
-	if (info->callback)
+	if (info->callback) {
+		/* TNY TODO: tny_lockable_lock (ui_lock); */
 		info->callback (info->self, info->cancelled, &info->err, info->user_data);
+		/* TNY TODO: tny_lockable_unlock (ui_lock); */
+	}
 
-	/* TODO: trigger this change notification
+	/* TNY TODO: trigger this change notification
+
 	if (info->oldlen != priv->cached_length || info->oldurlen != priv->unread_length)
 	{
 		TnyFolderChange *change = tny_folder_change_new (self);
@@ -1006,8 +1025,13 @@
 {
 	TransferMsgsInfo *info = thr_user_data;
 
-	if (info->callback) /* TODO: the cancelled field */
+	if (info->callback) {
+		/* TNY TODO: the cancelled field */
+
+		/* TNY TODO: tny_lockable_lock (ui_lock); */
 		info->callback (info->self, FALSE, &info->err, info->user_data);
+		/* TNY TODO: tny_lockable_unlock (ui_lock); */
+	}
 
 	return FALSE;
 }
@@ -1516,9 +1540,7 @@
 
 		g_type_add_interface_static (type, TNY_TYPE_FOLDER_OBSERVER,
 			&tny_folder_observer_info);
-
 	}
 
-
 	return type;
 }
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]