The GDK lock in tinymail
- From: Philip Van Hoof <spam pvanhoof be>
- To: tinymail-devel-list gnome org
- Cc: Dirk-Jan Binnema <Dirk-Jan Binnema nokia com>
- Subject: The GDK lock in tinymail
- Date: Fri, 03 Aug 2007 19:44:32 +0200
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]