Patch to TnyCamelFolder



Hi all,

find attached a patch against TnyCamelFolder that changes the following things:

* If the _tny_session_check_operation check fails in the asynchronous operations, then call the callback into an idle call if the GMainLoop is available. This allows the clients to always wrap their callbacks -that executes gtk+ code- with gkd_threads_enter/leave() stuff.

* Refactored the calls to the callbacks in a function called execute_callback, because they all do the same with different parameters.

* Changed the priority of the idles. Now the status callbacks have more priority than the function callbacks. This way we'll call first, all the status callbacks, and then the function callback.

Br
Index: tny-camel-folder.c
===================================================================
--- tny-camel-folder.c	(revision 2388)
+++ tny-camel-folder.c	(working copy)
@@ -834,6 +834,26 @@
 	return;
 }
 
+/**
+ * When using a #GMainLoop this method will execute a callback using
+ * g_idle_add_full.  Note that without a #GMainLoop, the callbacks
+ * could happen in a worker thread (depends on who call it) at an
+ * unknown moment in time (check your locking in this case).
+ */
+static void
+execute_callback (gint depth, 
+		  gint priority,
+		  GSourceFunc idle_func,
+		  gpointer data, 
+		  GDestroyNotify destroy_func)
+{
+	if (depth > 0){
+		g_idle_add_full (priority, idle_func, data, destroy_func);
+	} else {
+		idle_func (data);
+		destroy_func (data);
+	}
+}
 
 
 typedef struct 
@@ -914,15 +934,9 @@
 		TNY_FOLDER_STATUS, TNY_FOLDER_STATUS_CODE_REFRESH, what, sofar, 
 		oftotal, oinfo->stopper, oinfo->user_data);
 
-	if (oinfo->depth > 0)
-	{
-		g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
-			tny_progress_info_idle_func, info, 
-			tny_progress_info_destroy);
-	} else {
-		tny_progress_info_idle_func (info);
-		tny_progress_info_destroy (info);
-	}
+	execute_callback (oinfo->depth, G_PRIORITY_HIGH,
+			  tny_progress_info_idle_func, info,
+			  tny_progress_info_destroy);
 
 	return;
 }
@@ -982,15 +996,9 @@
 
 	if (info->callback)
 	{
-		if (info->depth > 0)
-		{
-			g_idle_add_full (G_PRIORITY_HIGH, 
-				tny_camel_folder_refresh_async_callback, 
-				info, tny_camel_folder_refresh_async_destroyer);
-		} else {
-			tny_camel_folder_refresh_async_callback (info);
-			tny_camel_folder_refresh_async_destroyer (info);
-		}
+		execute_callback (info->depth, G_PRIORITY_DEFAULT, 
+				  tny_camel_folder_refresh_async_callback, info, 
+				  tny_camel_folder_refresh_async_destroyer);
 	} else { /* Thread reference */
 		g_object_unref (G_OBJECT (self));
 		_tny_camel_folder_unreason (priv);
@@ -1007,6 +1015,28 @@
 	return;
 }
 
+static void
+tny_camel_folder_refresh_async_cancelled_destroyer (gpointer thr_user_data)
+{
+	RefreshFolderInfo *info = thr_user_data;
+
+	g_error_free (info->err);
+	g_object_unref (info->self);
+	g_slice_free (RefreshFolderInfo, thr_user_data);
+}
+
+static gboolean
+tny_camel_folder_refresh_async_cancelled_callback (gpointer thr_user_data)
+{
+	RefreshFolderInfo *info = thr_user_data;
+
+	if (info->callback)
+		info->callback (info->self, TRUE, &info->err, info->user_data);
+
+	return FALSE;
+}
+
+
 /**
  * tny_camel_folder_refresh_async_default:
  *
@@ -1028,17 +1058,7 @@
 	GError *err = NULL;
 	TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
 
-	if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, &err, 
-			TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_REFRESH))
-	{
-		if (callback)
-			callback (self, TRUE, &err, user_data);
-		g_error_free (err);
-		return;
-	}
-
-	/* Idle info for the status callback: */
-
+	/* Idle info for the callbacks */
 	info = g_slice_new (RefreshFolderInfo);
 	info->session = TNY_FOLDER_PRIV_GET_SESSION (priv);
 	info->err = NULL;
@@ -1047,11 +1067,26 @@
 	info->status_callback = status_callback;
 	info->user_data = user_data;
 	info->depth = g_main_depth ();
-	
+
+	if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, &err, 
+					   TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_REFRESH))
+	{
+		if (callback) {
+			info->err = g_error_copy (err);
+			g_object_ref (info->self);
+
+			execute_callback (info->depth, G_PRIORITY_DEFAULT,
+					  tny_camel_folder_refresh_async_cancelled_callback, info, 
+					  tny_camel_folder_refresh_async_cancelled_destroyer);
+		}
+		g_error_free (err);
+		return;
+	}
+
+
 	/* 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.*/
-
 	info->stopper = tny_idle_stopper_new();
 
 	/* thread reference */
@@ -1310,15 +1345,9 @@
 		TNY_FOLDER_STATUS, TNY_FOLDER_STATUS_CODE_GET_MSG, what, sofar, 
 		oftotal, oinfo->stopper, oinfo->user_data);
 
-	if (oinfo->depth > 0)
-	{
-		g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
-			tny_progress_info_idle_func, info, 
-			tny_progress_info_destroy);
-	} else {
-		tny_progress_info_idle_func (info);
-		tny_progress_info_destroy (info);
-	}
+	execute_callback (oinfo->depth, G_PRIORITY_HIGH, 
+			  tny_progress_info_idle_func, info, 
+			  tny_progress_info_destroy);
 
 	return;
 }
@@ -1375,15 +1404,9 @@
 
 	if (info->callback)
 	{
-		if (info->depth > 0)
-		{
-			g_idle_add_full (G_PRIORITY_HIGH, 
-				tny_camel_folder_get_msg_async_callback, 
-				info, tny_camel_folder_get_msg_async_destroyer);
-		} else {
-			tny_camel_folder_get_msg_async_callback (info);
-			tny_camel_folder_get_msg_async_destroyer (info);
-		}
+		execute_callback (info->depth, G_PRIORITY_DEFAULT, 
+				  tny_camel_folder_get_msg_async_callback, info, 
+				  tny_camel_folder_get_msg_async_destroyer);
 	} else {/* thread reference */
 		_tny_camel_folder_unreason (priv);
 		g_object_unref (G_OBJECT (info->self));
@@ -1394,7 +1417,30 @@
 	return NULL;
 
 }
+
 static void
+tny_camel_folder_get_msg_async_cancelled_destroyer (gpointer thr_user_data)
+{
+	GetMsgInfo *info = (GetMsgInfo *) thr_user_data;
+
+	g_error_free (info->err);
+	g_object_unref (info->self);
+	g_slice_free (GetMsgInfo, info);
+}
+
+static gboolean
+tny_camel_folder_get_msg_async_cancelled_callback (gpointer thr_user_data)
+{
+
+	GetMsgInfo *info = (GetMsgInfo *) thr_user_data;
+
+	if (info->callback)
+		info->callback (info->self, TRUE, NULL, &info->err, info->user_data);
+
+	return FALSE;
+}
+
+static void
 tny_camel_folder_get_msg_async (TnyFolder *self, TnyHeader *header, TnyGetMsgCallback callback, TnyStatusCallback status_callback, gpointer user_data)
 {
 	return TNY_CAMEL_FOLDER_GET_CLASS (self)->get_msg_async_func (self, header, callback, status_callback, user_data);
@@ -1409,15 +1455,7 @@
 	GError *err = NULL;
 	TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
 
-	if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, &err, 
-			TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_GET_MSG))
-	{
-		if (callback)
-			callback (self, TRUE, NULL, &err, user_data);
-		g_error_free (err);
-		return;
-	}
-
+	/* Idle info for the callbacks */
 	info = g_slice_new (GetMsgInfo);
 	info->cancelled = FALSE;
 	info->session = TNY_FOLDER_PRIV_GET_SESSION (priv);
@@ -1428,10 +1466,24 @@
 	info->user_data = user_data;
 	info->depth = g_main_depth ();
 
+	if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, &err, 
+			TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_GET_MSG))
+	{
+		if (callback) {
+			info->err = g_error_copy (err);
+			g_object_ref (info->self);
+
+			execute_callback (info->depth, G_PRIORITY_DEFAULT,
+					  tny_camel_folder_get_msg_async_cancelled_callback, info, 
+					  tny_camel_folder_get_msg_async_cancelled_destroyer);
+		}
+		g_error_free (err);
+		return;
+	}
+
 	/* 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. */
-
 	info->stopper = tny_idle_stopper_new();
 
 	/* thread reference */
@@ -2247,15 +2299,9 @@
 		TNY_FOLDER_STATUS, TNY_FOLDER_STATUS_CODE_COPY_FOLDER, what, sofar, 
 		oftotal, oinfo->stopper, oinfo->user_data);
 
-	if (oinfo->depth > 0)
-	{
-		g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
-			tny_progress_info_idle_func, info, 
-			tny_progress_info_destroy);
-	} else {
-		tny_progress_info_idle_func (info);
-		tny_progress_info_destroy (info);
-	}
+	execute_callback (oinfo->depth, G_PRIORITY_HIGH,
+			  tny_progress_info_idle_func, info, 
+			  tny_progress_info_destroy);
 
 	return;
 }
@@ -2306,15 +2352,9 @@
 
 	if (info->callback)
 	{
-		if (info->depth > 0)
-		{
-			g_idle_add_full (G_PRIORITY_HIGH, 
-				tny_camel_folder_copy_async_callback, 
-				info, tny_camel_folder_copy_async_destroyer);
-		} else {
-			tny_camel_folder_copy_async_callback (info);
-			tny_camel_folder_copy_async_destroyer (info);
-		}
+		execute_callback (info->depth, G_PRIORITY_DEFAULT, 
+				  tny_camel_folder_copy_async_callback, info, 
+				  tny_camel_folder_copy_async_destroyer);
 	} else { /* Thread reference */
 		g_object_unref (info->into);
 		g_object_unref (info->self);
@@ -2326,6 +2366,30 @@
 }
 
 static void
+tny_camel_folder_copy_async_cancelled_destroyer (gpointer thr_user_data)
+{
+	CopyFolderInfo *info = (CopyFolderInfo *) thr_user_data;
+
+	g_free (info->new_name);
+	g_error_free (info->err);
+	g_object_unref (info->self);
+	g_object_unref (info->into);
+	g_slice_free (CopyFolderInfo, info);
+}
+
+static gboolean
+tny_camel_folder_copy_async_cancelled_callback (gpointer thr_user_data)
+{
+
+	CopyFolderInfo *info = (CopyFolderInfo *) thr_user_data;
+
+	if (info->callback)
+		info->callback (info->self, info->into, TRUE, NULL, &info->err, info->user_data);
+
+	return FALSE;
+}
+
+static void
 tny_camel_folder_copy_async (TnyFolder *self, TnyFolderStore *into, const gchar *new_name, gboolean del, TnyCopyFolderCallback callback, TnyStatusCallback status_callback, gpointer user_data)
 {
 	TNY_CAMEL_FOLDER_GET_CLASS (self)->copy_async_func (self, into, new_name, del, callback, status_callback, user_data);
@@ -2340,17 +2404,8 @@
 	GThread *thread;
 	GError *err = NULL;
 
-	if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, &err, 
-			TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_COPY))
-	{
-		if (callback)
-			callback (self, into, TRUE, NULL, &err, user_data);
-		g_error_free (err);
-		return;
-	}
-
+	/* Idle info for the callbacks */
 	info = g_slice_new (CopyFolderInfo);
-
 	info->cancelled = FALSE;
 	info->session = TNY_FOLDER_PRIV_GET_SESSION (priv);
 	info->self = self;
@@ -2364,10 +2419,25 @@
 	info->delete_originals = del;
 	info->new_name = g_strdup (new_name);
 
+	if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, &err, 
+			TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_COPY))
+	{
+		if (callback) {
+			info->err = g_error_copy (err);
+			g_object_ref (info->self);
+			g_object_ref (info->into);
+
+			execute_callback (info->depth, G_PRIORITY_DEFAULT,
+					  tny_camel_folder_copy_async_cancelled_callback, info, 
+					  tny_camel_folder_copy_async_cancelled_destroyer);
+		}
+		g_error_free (err);
+		return;
+	}
+
 	/* 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. */
-
 	info->stopper = tny_idle_stopper_new();
 
 	/* thread reference */
@@ -2665,15 +2735,9 @@
 		TNY_FOLDER_STATUS, TNY_FOLDER_STATUS_CODE_XFER_MSGS, what, sofar, 
 		oftotal, oinfo->stopper, oinfo->user_data);
 
-	if (oinfo->depth > 0)
-	{
-		g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
-			tny_progress_info_idle_func, info, 
-			tny_progress_info_destroy);
-	} else {
-		tny_progress_info_idle_func (info);
-		tny_progress_info_destroy (info);
-	}
+	execute_callback (oinfo->depth, G_PRIORITY_HIGH,
+			  tny_progress_info_idle_func, info, 
+			  tny_progress_info_destroy);
 
 	return;
 }
@@ -2728,15 +2792,9 @@
 	/* Call callback function, if it exists */
 	if (info->callback)
 	{
-		if (info->depth > 0)
-		{
-			g_idle_add_full (G_PRIORITY_HIGH, 
-				tny_camel_folder_transfer_msgs_async_callback, 
-				info, tny_camel_folder_transfer_msgs_async_destroyer);
-		} else {
-			tny_camel_folder_transfer_msgs_async_callback (info);
-			tny_camel_folder_transfer_msgs_async_destroyer (info);
-		}
+		execute_callback (info->depth, G_PRIORITY_DEFAULT, 
+				  tny_camel_folder_transfer_msgs_async_callback, info, 
+				  tny_camel_folder_transfer_msgs_async_destroyer);
 	} else { 
 		/* Thread reference */
 		_tny_camel_folder_unreason (priv_src);
@@ -2752,6 +2810,29 @@
 }
 
 static void
+tny_camel_folder_transfer_msgs_async_cancelled_destroyer (gpointer thr_user_data)
+{
+	TransferMsgsInfo *info = thr_user_data;
+
+	g_error_free (info->err);
+	g_object_unref (info->new_header_list);
+	g_object_unref (info->self);
+	g_slice_free (TransferMsgsInfo, info);
+}
+
+static gboolean
+tny_camel_folder_transfer_msgs_async_cancelled_callback (gpointer thr_user_data)
+{
+	TransferMsgsInfo *info = thr_user_data;
+
+	if (info->callback)
+		info->callback (info->self, TRUE, &info->err, info->user_data);
+
+	return FALSE;
+}
+
+
+static void
 tny_camel_folder_transfer_msgs_async (TnyFolder *self, TnyList *header_list, TnyFolder *folder_dst, gboolean delete_originals, TnyTransferMsgsCallback callback, TnyStatusCallback status_callback, gpointer user_data)
 {
 	TNY_CAMEL_FOLDER_GET_CLASS (self)->transfer_msgs_async_func (self, header_list, folder_dst, delete_originals, callback, status_callback, user_data);
@@ -2768,15 +2849,7 @@
 	TnyCamelFolderPriv *priv_src = priv;
 	TnyCamelFolderPriv *priv_dst = TNY_CAMEL_FOLDER_GET_PRIVATE (folder_dst);
 
-	if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, &err, 
-			TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_TRANSFER_MSGS))
-	{
-		if (callback)
-			callback (self, TRUE, &err, user_data);
-		g_error_free (err);
-		return;
-	}
-
+	/* Idle info for the callbacks */
 	info = g_slice_new (TransferMsgsInfo);
 	info->cancelled = FALSE;
 	info->session = TNY_FOLDER_PRIV_GET_SESSION (priv);
@@ -2790,10 +2863,24 @@
 	info->delete_originals = delete_originals;
 	info->depth = g_main_depth ();
 
+	if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, &err, 
+			TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_TRANSFER_MSGS))
+	{
+		if (callback) {
+			info->err = g_error_copy (err);
+			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);
+		}
+		g_error_free (err);
+		return;
+	}
+
 	/* 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. */
-
 	info->stopper = tny_idle_stopper_new();
 
 	/* thread reference */
@@ -3462,15 +3549,9 @@
 
 	if (info->callback)
 	{
-		if (info->depth > 0)
-		{
-			g_idle_add_full (G_PRIORITY_HIGH, 
-				tny_camel_folder_get_folders_async_callback, 
-				info, tny_camel_folder_get_folders_async_destroyer);
-		} else {
-			tny_camel_folder_get_folders_async_callback (info);
-			tny_camel_folder_get_folders_async_destroyer (info);
-		}
+		execute_callback (info->depth, G_PRIORITY_DEFAULT, 
+				  tny_camel_folder_get_folders_async_callback, info, 
+				  tny_camel_folder_get_folders_async_destroyer);
 	} else {
 		/* thread reference */
 		_tny_camel_folder_unreason (priv);
@@ -3483,6 +3564,28 @@
 	return NULL;
 }
 
+static void
+tny_camel_folder_get_folders_async_cancelled_destroyer (gpointer thr_user_data)
+{
+	GetFoldersInfo *info = thr_user_data;
+
+	g_error_free (info->err);
+	g_object_unref (info->self);
+	g_object_unref (info->list);
+	g_slice_free (GetFoldersInfo, info);
+}
+
+static gboolean
+tny_camel_folder_get_folders_async_cancelled_callback (gpointer thr_user_data)
+{
+	GetFoldersInfo *info = thr_user_data;
+
+	if (info->callback)
+		info->callback (info->self, info->list, &info->err, info->user_data);
+
+	return FALSE;
+}
+
 static void 
 tny_camel_folder_get_folders_async (TnyFolderStore *self, TnyList *list, TnyGetFoldersCallback callback, TnyFolderStoreQuery *query, TnyStatusCallback status_callback, gpointer user_data)
 {
@@ -3497,15 +3600,7 @@
 	GError *err = NULL;
 	TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
 
-	if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, &err, 
-			TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_REFRESH))
-	{
-		if (callback)
-			callback (self, list, &err, user_data);
-		g_error_free (err);
-		return;
-	}
-
+	/* Idle info for the callbacks */
 	info = g_slice_new (GetFoldersInfo);
 	info->session = TNY_FOLDER_PRIV_GET_SESSION (priv);
 	info->self = self;
@@ -3515,6 +3610,22 @@
 	info->query = query;
 	info->depth = g_main_depth ();
 
+	if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, &err, 
+			TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_REFRESH))
+	{
+		if (callback) {
+			info->err = g_error_copy (err);
+			g_object_ref (info->self);
+			g_object_ref (info->list);
+
+			execute_callback (info->depth, G_PRIORITY_DEFAULT,
+					  tny_camel_folder_get_folders_async_cancelled_callback, info, 
+					  tny_camel_folder_get_folders_async_cancelled_destroyer);			
+		}
+		g_error_free (err);
+		return;
+	}
+
 	/* thread reference */
 	_tny_camel_folder_reason (priv);
 	g_object_ref (G_OBJECT (info->self));
@@ -3737,16 +3848,9 @@
 	{
 		info->self = TNY_FOLDER (g_object_ref (self));
 
-		if (g_main_depth () > 0)
-		{
-			g_idle_add_full (G_PRIORITY_HIGH, 
-					tny_camel_folder_poke_status_callback, 
-					info, tny_camel_folder_poke_status_destroyer);
-		} else 
-		{
-			tny_camel_folder_poke_status_callback (info);
-			tny_camel_folder_poke_status_destroyer (info);
-		}
+		execute_callback (g_main_depth (), G_PRIORITY_HIGH, 
+				  tny_camel_folder_poke_status_callback, info, 
+				  tny_camel_folder_poke_status_destroyer);
 	}
 
 	return;


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