Re: new API proposal find_msg_async
- From: José Dapena Paz <jdapena igalia com>
- To: Philip Van Hoof <spam pvanhoof be>
- Cc: tinymail-devel-list <tinymail-devel-list gnome org>
- Subject: Re: new API proposal find_msg_async
- Date: Mon, 28 Apr 2008 14:51:52 +0200
El lun, 21-04-2008 a las 22:39 +0200, Philip Van Hoof escribió:
> Hey Sergio!
I've been updating this patch following your recommendations. Attached
to this mail is the new version of the find msg async support patch.
>
> Can you also move the original find_msg in the TNY_DISABLE_DEPRECATED
> ifdef and add the deprecation marker in the gtk-doc comments?
Done. Also added proper gtk doc for find msg async.
>
> Unless necessary for Modest it was not required to create a new
> TNY_FOLDER_STATUS_CODE_FIND_MSG. Reusing the status-code for GET_MSG was
> sufficient for me (but you choose, maybe it's indeed better to be more
> fine grained about this).
Removed the new code.
>
> I'm fine with reusing the GetMsg's info structure, but please add some
> comments near the structure explaining that two async implementations
> are using the structure. That way will a future developer be alarmed
> when changing things here.
Now we don't reuse the structure.
>
> ! And now ...
>
> Finally the blocker issue with your patch is that you didn't implement
> it for TnyMergeFolder. Without that implementation of your new method, I
> wont accept the patch. Of course.
:) Implemented too.
--
José Dapena Paz <jdapena igalia com>
Igalia
Index: ChangeLog
===================================================================
--- ChangeLog (revision 3633)
+++ ChangeLog (working copy)
@@ -1,3 +1,12 @@
+2008-04-28 Jose Dapena Paz <jdapena igalia com>, Sergio Villar Senin <svillar igalia com>
+
+ * libtinymail/tny-folder.[ch]: new method find_msg_async. This makes find_msg synchronous
+ version be deprecated now.
+
+ * libtinymail-camel/tny-camel-folder.[ch],
+ libtinymail/tny-merge-folder.[ch]:
+ Added implementations of find_msg_async method.
+
2008-04-25 Philip Van Hoof <pvanhoof gnome org>
* Error reporting when sending a message without From, and a crash-fix
Index: libtinymail/tny-folder.c
===================================================================
--- libtinymail/tny-folder.c (revision 3633)
+++ libtinymail/tny-folder.c (working copy)
@@ -1212,6 +1212,7 @@
* g_object_unref (message);
* </programlisting></informalexample>
*
+ * Deprecated: 1.0: Use tny_folder_find_msg_async in stead
* returns: (null-ok) (caller-owns): The message instance or NULL
* since: 1.0
* audience: application-developer
@@ -1289,6 +1290,55 @@
}
/**
+ * tny_folder_find_msg_async:
+ * @self: a #TnyFolder
+ * @url_string: the url string
+ * @callback: (null-ok): a #TnyGetMsgCallback or NULL
+ * @status_callback: (null-ok): a #TnyStatusCallback or NULL
+ * @user_data: (null-ok): user data that will be passed to the callbacks
+ *
+ * Get a message in @self identified by @url_string asynchronously.
+ *
+ * Example:
+ * <informalexample><programlisting>
+ * static void
+ * status_cb (GObject *sender, TnyStatus *status, gpointer user_data)
+ * {
+ * printf (".");
+ * }
+ * static void
+ * folder_find_msg_cb (TnyFolder *folder, gboolean cancelled, TnyMsg *msg, GError **err, gpointer user_data)
+ * {
+ * TnyMsgView *message_view = user_data;
+ * if (!err && msg && !cancelled)
+ * tny_msg_view_set_msg (message_view, msg);
+ * }
+ * TnyMsgView *message_view = tny_platform_factory_new_msg_view (platfact);
+ * TnyFolder *folder = ...; gchar *url_string = ...;
+ * tny_folder_find_msg_async (folder, msg_url,
+ * folder_get_msg_cb, status_cb, message_view);
+ * </programlisting></informalexample>
+ *
+ * since: 1.0
+ * audience: application-developer
+ **/
+void
+tny_folder_find_msg_async (TnyFolder *self, const gchar *url_string, TnyGetMsgCallback callback, TnyStatusCallback status_callback, gpointer user_data)
+{
+#ifdef DBC /* require */
+ g_assert (TNY_IS_FOLDER (self));
+ g_assert (url_string);
+ g_assert (strlen (url_string) > 0);
+ g_assert (strstr (url_string, "://") != NULL);
+ g_assert (TNY_FOLDER_GET_IFACE (self)->get_msg_async!= NULL);
+#endif
+
+ TNY_FOLDER_GET_IFACE (self)->find_msg_async(self, url_string, callback, status_callback, user_data);
+
+ return;
+}
+
+/**
* tny_folder_get_headers:
* @self: a #TnyFolder
* @headers: A #TnyList where the headers will be prepended to
Index: libtinymail/tny-folder.h
===================================================================
--- libtinymail/tny-folder.h (revision 3633)
+++ libtinymail/tny-folder.h (working copy)
@@ -109,6 +109,7 @@
TnyMsg* (*get_msg) (TnyFolder *self, TnyHeader *header, GError **err);
TnyMsg* (*find_msg) (TnyFolder *self, const gchar *url_string, GError **err);
void (*get_msg_async) (TnyFolder *self, TnyHeader *header, TnyGetMsgCallback callback, TnyStatusCallback status_callback, gpointer user_data);
+ void (*find_msg_async) (TnyFolder *self, const gchar *url_string, TnyGetMsgCallback callback, TnyStatusCallback status_callback, gpointer user_data);
void (*get_headers) (TnyFolder *self, TnyList *headers, gboolean refresh, GError **err);
void (*get_headers_async) (TnyFolder *self, TnyList *headers, gboolean refresh, TnyGetHeadersCallback callback, TnyStatusCallback status_callback, gpointer user_data);
const gchar* (*get_name) (TnyFolder *self);
@@ -147,8 +148,8 @@
void tny_folder_set_msg_receive_strategy (TnyFolder *self, TnyMsgReceiveStrategy *st);
void tny_folder_add_msg_async (TnyFolder *self, TnyMsg *msg, TnyFolderCallback callback, TnyStatusCallback status_callback, gpointer user_data);
void tny_folder_sync_async (TnyFolder *self, gboolean expunge, TnyFolderCallback callback, TnyStatusCallback status_callback, gpointer user_data);
-TnyMsg* tny_folder_find_msg (TnyFolder *self, const gchar *url_string, GError **err);
void tny_folder_get_msg_async (TnyFolder *self, TnyHeader *header, TnyGetMsgCallback callback, TnyStatusCallback status_callback, gpointer user_data);
+void tny_folder_find_msg_async (TnyFolder *self, const gchar *url_string, TnyGetMsgCallback callback, TnyStatusCallback status_callback, gpointer user_data);
void tny_folder_get_headers_async (TnyFolder *self, TnyList *headers, gboolean refresh, TnyGetHeadersCallback callback, TnyStatusCallback status_callback, gpointer user_data);
TnyAccount* tny_folder_get_account (TnyFolder *self);
const gchar* tny_folder_get_id (TnyFolder *self);
@@ -176,6 +177,7 @@
void tny_folder_remove_msg (TnyFolder *self, TnyHeader *header, GError **err);
void tny_folder_remove_msgs (TnyFolder *self, TnyList *headers, GError **err);
TnyMsg* tny_folder_get_msg (TnyFolder *self, TnyHeader *header, GError **err);
+TnyMsg* tny_folder_find_msg (TnyFolder *self, const gchar *url_string, GError **err);
void tny_folder_refresh (TnyFolder *self, GError **err);
void tny_folder_transfer_msgs (TnyFolder *self, TnyList *header_list, TnyFolder *folder_dst, gboolean delete_originals, GError **err);
void tny_folder_get_headers (TnyFolder *self, TnyList *headers, gboolean refresh, GError **err);
Index: libtinymail/tny-merge-folder.c
===================================================================
--- libtinymail/tny-merge-folder.c (revision 3633)
+++ libtinymail/tny-merge-folder.c (working copy)
@@ -638,7 +638,113 @@
}
+typedef struct
+{
+ TnyFolder *self;
+ TnyMsg *msg;
+ gchar *url_string;
+ GError *err;
+ gpointer user_data;
+ guint depth;
+ TnyGetMsgCallback callback;
+ TnyStatusCallback status_callback;
+} FindMsgInfo;
+static void
+find_msg_async_destroyer (gpointer thr_user_data)
+{
+ FindMsgInfo *info = (FindMsgInfo *) thr_user_data;
+
+ /* thread reference */
+ g_object_unref (info->self);
+
+ if (info->msg)
+ g_object_unref (info->msg);
+
+ if (info->url_string)
+ g_free (info->url_string);
+
+ if (info->err)
+ g_error_free (info->err);
+
+ g_slice_free (FindMsgInfo, info);
+}
+
+static gboolean
+find_msg_async_callback (gpointer thr_user_data)
+{
+ FindMsgInfo *info = (FindMsgInfo *) thr_user_data;
+ TnyMergeFolderPriv *priv = TNY_MERGE_FOLDER_GET_PRIVATE (info->self);
+
+ if (info->callback) {
+ /* TNY TODO: the cancelled field */
+ tny_lockable_lock (priv->ui_locker);
+ info->callback (info->self, FALSE, info->msg, info->err, info->user_data);
+ tny_lockable_unlock (priv->ui_locker);
+ }
+
+ return FALSE;
+}
+
+static gpointer
+find_msg_async_thread (gpointer thr_user_data)
+{
+ FindMsgInfo *info = (FindMsgInfo *) thr_user_data;
+
+ info->msg = tny_folder_find_msg (info->self, info->url_string, &info->err);
+
+ if (info->err != NULL)
+ {
+ if (info->msg && G_IS_OBJECT (info->msg))
+ g_object_unref (info->msg);
+ info->msg = NULL;
+ }
+
+ if (info->callback)
+ {
+ if (info->depth > 0)
+ {
+ g_idle_add_full (G_PRIORITY_HIGH,
+ find_msg_async_callback,
+ info, find_msg_async_destroyer);
+ } else {
+ find_msg_async_callback (info);
+ find_msg_async_destroyer (info);
+ }
+ } else /* thread reference */
+ g_object_unref (info->self);
+
+ g_thread_exit (NULL);
+
+ return NULL;
+
+}
+
+static void
+tny_merge_folder_find_msg_async (TnyFolder *self, const gchar *url_string, TnyGetMsgCallback callback, TnyStatusCallback status_callback, gpointer user_data)
+{
+ FindMsgInfo *info;
+ GThread *thread;
+
+ info = g_slice_new (FindMsgInfo);
+ info->self = self;
+ info->url_string = g_strdup (url_string);
+ info->callback = callback;
+ info->status_callback = status_callback;
+ info->user_data = user_data;
+ info->depth = g_main_depth ();
+ info->err = NULL;
+
+ /* thread reference */
+ g_object_ref (info->self);
+
+ thread = g_thread_create (find_msg_async_thread, info, FALSE, NULL);
+
+ return;
+}
+
+
+
typedef struct
{
TnyFolder *self;
@@ -1854,6 +1960,7 @@
klass->get_msg= tny_merge_folder_get_msg;
klass->find_msg= tny_merge_folder_find_msg;
klass->get_msg_async= tny_merge_folder_get_msg_async;
+ klass->find_msg_async= tny_merge_folder_find_msg_async;
klass->get_headers= tny_merge_folder_get_headers;
klass->get_headers_async= tny_merge_folder_get_headers_async;
klass->get_name= tny_merge_folder_get_name;
Index: libtinymail-camel/tny-camel-folder.c
===================================================================
--- libtinymail-camel/tny-camel-folder.c (revision 3633)
+++ libtinymail-camel/tny-camel-folder.c (working copy)
@@ -1270,7 +1270,6 @@
TnyFolderChange *change = NULL;
TnyIterator *iter = NULL;
TnyHeader *header = NULL;
- TnyMsgRemoveStrategy *strat;
g_assert (TNY_IS_LIST (headers));
@@ -2598,7 +2597,181 @@
}
+typedef struct
+{
+ TnyCamelQueueable parent;
+ TnyFolder *self;
+ TnyMsg *msg;
+ gchar *url_string;
+ GError *err;
+ gpointer user_data;
+ TnyGetMsgCallback callback;
+ TnyStatusCallback status_callback;
+ TnySessionCamel *session;
+ TnyIdleStopper *stopper;
+ gboolean cancelled;
+
+} FindMsgInfo;
+
+static void
+tny_camel_folder_find_msg_async_destroyer (gpointer thr_user_data)
+{
+ FindMsgInfo *info = (FindMsgInfo *) thr_user_data;
+ TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (info->self);
+
+ /* thread reference */
+ _tny_camel_folder_unreason (priv);
+ g_object_unref (info->self);
+
+ if (info->err)
+ g_error_free (info->err);
+
+ tny_idle_stopper_destroy (info->stopper);
+ info->stopper = NULL;
+
+ /**/
+
+ camel_object_unref (info->session);
+
+ return;
+}
+
+static gboolean
+tny_camel_folder_find_msg_async_callback (gpointer thr_user_data)
+{
+ FindMsgInfo *info = (FindMsgInfo *) thr_user_data;
+ TnyFolderChange *change;
+
+ if (info->msg)
+ {
+ change = tny_folder_change_new (info->self);
+ tny_folder_change_set_check_duplicates (change, TRUE);
+ tny_folder_change_set_received_msg (change, info->msg);
+ notify_folder_observers_about (info->self, change, info->session);
+ g_object_unref (change);
+ }
+
+ 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);
+
+ tny_idle_stopper_stop (info->stopper);
+
+ return FALSE;
+}
+
+
+static void
+tny_camel_folder_find_msg_async_cancelled_destroyer (gpointer thr_user_data)
+{
+ FindMsgInfo *info = (FindMsgInfo *) thr_user_data;
+ TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (info->self);
+
+ /* thread reference */
+ _tny_camel_folder_unreason (priv);
+ g_object_unref (info->self);
+
+ if (info->err)
+ g_error_free (info->err);
+
+ tny_idle_stopper_destroy (info->stopper);
+ info->stopper = NULL;
+
+ /**/
+
+ camel_object_unref (info->session);
+
+ return;
+}
+
+static gboolean
+tny_camel_folder_find_msg_async_cancelled_callback (gpointer thr_user_data)
+{
+ FindMsgInfo *info = (FindMsgInfo *) thr_user_data;
+ 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;
+}
+
+static gpointer
+tny_camel_folder_find_msg_async_thread (gpointer thr_user_data)
+{
+ FindMsgInfo *info = (FindMsgInfo *) thr_user_data;
+
+ info->msg = tny_folder_find_msg (info->self, info->url_string, &info->err);
+
+ info->cancelled = FALSE;
+ if (info->err != NULL) {
+ if (camel_strstrcase (info->err->message, "cancel") != NULL)
+ info->cancelled = TRUE;
+ }
+
+ /* Free the URL */
+ g_free (info->url_string);
+
+ return NULL;
+}
+
+static void
+tny_camel_folder_find_msg_async (TnyFolder *self, const gchar *url_string, TnyGetMsgCallback callback, TnyStatusCallback status_callback, gpointer user_data)
+{
+ TNY_CAMEL_FOLDER_GET_CLASS (self)->find_msg_async(self, url_string, callback, status_callback, user_data);
+ return;
+}
+
+
+static void
+tny_camel_folder_find_msg_async_default (TnyFolder *self, const gchar *url_string, TnyGetMsgCallback callback, TnyStatusCallback status_callback, gpointer user_data)
+{
+ FindMsgInfo *info;
+ TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
+ TnyCamelQueue *queue;
+
+ /* Idle info for the callbacks */
+ info = g_slice_new (FindMsgInfo);
+ info->cancelled = FALSE;
+ info->session = TNY_FOLDER_PRIV_GET_SESSION (priv);
+ camel_object_ref (info->session);
+ info->self = self;
+ info->url_string = g_strdup (url_string);
+ info->callback = callback;
+ info->status_callback = status_callback;
+ info->user_data = user_data;
+ info->err = NULL;
+
+ info->stopper = tny_idle_stopper_new();
+
+ /* thread reference */
+ _tny_camel_folder_reason (priv);
+ g_object_ref (info->self);
+
+ if (!TNY_IS_CAMEL_POP_FOLDER (self))
+ queue = TNY_FOLDER_PRIV_GET_MSG_QUEUE (priv);
+ else
+ queue = TNY_FOLDER_PRIV_GET_QUEUE (priv);
+
+ _tny_camel_queue_launch (queue,
+ tny_camel_folder_find_msg_async_thread,
+ tny_camel_folder_find_msg_async_callback,
+ tny_camel_folder_find_msg_async_destroyer,
+ tny_camel_folder_find_msg_async_cancelled_callback,
+ tny_camel_folder_find_msg_async_cancelled_destroyer,
+ &info->cancelled,
+ info, sizeof (FindMsgInfo),
+ __FUNCTION__);
+
+ return;
+}
+
static TnyMsgReceiveStrategy*
tny_camel_folder_get_msg_receive_strategy (TnyFolder *self)
{
@@ -5886,6 +6059,7 @@
klass->get_msg= tny_camel_folder_get_msg;
klass->find_msg= tny_camel_folder_find_msg;
klass->get_msg_async= tny_camel_folder_get_msg_async;
+ klass->find_msg_async= tny_camel_folder_find_msg_async;
klass->get_id= tny_camel_folder_get_id;
klass->get_name= tny_camel_folder_get_name;
klass->get_folder_type= tny_camel_folder_get_folder_type;
@@ -5952,6 +6126,7 @@
class->get_msg= tny_camel_folder_get_msg_default;
class->find_msg= tny_camel_folder_find_msg_default;
class->get_msg_async= tny_camel_folder_get_msg_async_default;
+ class->find_msg_async= tny_camel_folder_find_msg_async_default;
class->get_id= tny_camel_folder_get_id_default;
class->get_name= tny_camel_folder_get_name_default;
class->get_folder_type= tny_camel_folder_get_folder_type_default;
Index: libtinymail-camel/tny-camel-folder.h
===================================================================
--- libtinymail-camel/tny-camel-folder.h (revision 3633)
+++ libtinymail-camel/tny-camel-folder.h (working copy)
@@ -67,6 +67,7 @@
TnyMsg* (*get_msg) (TnyFolder *self, TnyHeader *header, GError **err);
TnyMsg* (*find_msg) (TnyFolder *self, const gchar *url_string, GError **err);
void (*get_msg_async) (TnyFolder *self, TnyHeader *header, TnyGetMsgCallback callback, TnyStatusCallback status_callback, gpointer user_data);
+ void (*find_msg_async) (TnyFolder *self, const gchar *url_string, TnyGetMsgCallback callback, TnyStatusCallback status_callback, gpointer user_data);
void (*get_headers) (TnyFolder *self, TnyList *headers, gboolean refresh, GError **err);
void (*get_headers_async) (TnyFolder *self, TnyList *headers, gboolean refresh, TnyGetHeadersCallback callback, TnyStatusCallback status_callback, gpointer user_data);
const gchar* (*get_name) (TnyFolder *self);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]