aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Zucci <zucchi@src.gnome.org>2001-10-17 03:13:31 +0800
committerMichael Zucci <zucchi@src.gnome.org>2001-10-17 03:13:31 +0800
commit8c85ed61ba64bd548460543dd87445b9a21dbf6a (patch)
tree76d2bc77eb83263b4d5b4122bf47127a1666214b
parente1d0f3dc45692a04dbd93c7ef82c24af74e05f25 (diff)
downloadgsoc2013-evolution-8c85ed61ba64bd548460543dd87445b9a21dbf6a.tar.gz
gsoc2013-evolution-8c85ed61ba64bd548460543dd87445b9a21dbf6a.tar.zst
gsoc2013-evolution-8c85ed61ba64bd548460543dd87445b9a21dbf6a.zip
Added an async_event handler to store_info. (mail_note_store): Setup async
* mail-folder-cache.c: Added an async_event handler to store_info. (mail_note_store): Setup async event handler here. (store_finalised): Flush out async events here. (folder_changed): Use async event handler to emit event. (mail_note_folder): Chagned, do most of the work in the calling context, only do the corba stuff in main. (store_folder_subscribed): Use async event, and do more work locally. (store_folder_unsubscribed): Same. (store_folder_deleted): Call store_folder_unsubscribed if we have to do any work. (store_folder_created): Call store_folder_subscribed if we have to do any work. (store_folder_unsubscribed): Ref store while busy. (real_folder_deleted): And unref here. (store_folder_subscribed): Reg store while busy. (real_folder_created): Unref here. (mail_note_folder): Ref folder while busy. (real_note_folder): And unref here. (mail_note_folder): Hook onto folder_deleted event. (folder_deleted): Just mark this folder as no longer available. * mail-session.c (register_timeout): Use mail_call_main instead of proxy_event. (remove_timeout): Same here. * folder-browser.c (folder_changed): use the new mail_async_event stuff. (folder_changed_main): Remove old async event handling stuff. (FOLDER_BROWSER_LOCK/UNLOCK): Removed. (FolderBrowserPrivate): Removed too, sigh. * mail-mt.c (mail_async_event_new, mail_async_event_emit, mail_async_event_destroy): New functions to handle async events. (mail_proxy_event, mail_proxy_event_id): Removed old functions for async events. (do_call): Add suport for MAIL_CALL_p_pp. (mail_msg_free): Use mail_async_event instead of proxy_event. * message-list.c (message_changed): Promote the message_changed to a folder_changed and use main_folder_changed to process it. (main_message_changed): Remove.d (message_list_init): Setup async event handler. (message_list_destroy): Remove async handler. (folder_changed): Use async hanler to emit event in main loop. (message_changed): Same. svn path=/trunk/; revision=13698
-rw-r--r--mail/ChangeLog46
-rw-r--r--mail/folder-browser.c94
-rw-r--r--mail/folder-browser.h7
-rw-r--r--mail/mail-folder-cache.c108
-rw-r--r--mail/mail-mt.c68
-rw-r--r--mail/mail-mt.h18
-rw-r--r--mail/mail-session.c22
-rw-r--r--mail/message-list.c27
-rw-r--r--mail/message-list.h3
9 files changed, 224 insertions, 169 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog
index b2422fe53b..4b8eb79b34 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,5 +1,51 @@
2001-10-16 <NotZed@Ximian.com>
+ * mail-folder-cache.c: Added an async_event handler to store_info.
+ (mail_note_store): Setup async event handler here.
+ (store_finalised): Flush out async events here.
+ (folder_changed): Use async event handler to emit event.
+ (mail_note_folder): Chagned, do most of the work in the calling
+ context, only do the corba stuff in main.
+ (store_folder_subscribed): Use async event, and do more work locally.
+ (store_folder_unsubscribed): Same.
+ (store_folder_deleted): Call store_folder_unsubscribed if we have
+ to do any work.
+ (store_folder_created): Call store_folder_subscribed if we have to
+ do any work.
+ (store_folder_unsubscribed): Ref store while busy.
+ (real_folder_deleted): And unref here.
+ (store_folder_subscribed): Reg store while busy.
+ (real_folder_created): Unref here.
+ (mail_note_folder): Ref folder while busy.
+ (real_note_folder): And unref here.
+ (mail_note_folder): Hook onto folder_deleted event.
+ (folder_deleted): Just mark this folder as no longer available.
+
+ * mail-session.c (register_timeout): Use mail_call_main instead of
+ proxy_event.
+ (remove_timeout): Same here.
+
+ * folder-browser.c (folder_changed): use the new mail_async_event
+ stuff.
+ (folder_changed_main): Remove old async event handling stuff.
+ (FOLDER_BROWSER_LOCK/UNLOCK): Removed.
+ (FolderBrowserPrivate): Removed too, sigh.
+
+ * mail-mt.c (mail_async_event_new, mail_async_event_emit,
+ mail_async_event_destroy): New functions to handle async events.
+ (mail_proxy_event, mail_proxy_event_id): Removed old functions for
+ async events.
+ (do_call): Add suport for MAIL_CALL_p_pp.
+ (mail_msg_free): Use mail_async_event instead of proxy_event.
+
+ * message-list.c (message_changed): Promote the message_changed to
+ a folder_changed and use main_folder_changed to process it.
+ (main_message_changed): Remove.d
+ (message_list_init): Setup async event handler.
+ (message_list_destroy): Remove async handler.
+ (folder_changed): Use async hanler to emit event in main loop.
+ (message_changed): Same.
+
* mail-mt.c (mail_proxy_event_id): New function to return the id
of the currently executing proxied event.
diff --git a/mail/folder-browser.c b/mail/folder-browser.c
index bd0c4bbb2f..455542808f 100644
--- a/mail/folder-browser.c
+++ b/mail/folder-browser.c
@@ -58,18 +58,6 @@
#define d(x)
-
-typedef struct _FolderBrowserPrivate {
- GMutex *lock;
-
- /* If we have outstanding tasks running */
- GSList *tasks;
- GSList *tasks_done;
-} FolderBrowserPrivate;
-
-#define FOLDER_BROWSER_LOCK(fb) g_mutex_lock(((FolderBrowser *)(fb))->priv->lock);
-#define FOLDER_BROWSER_UNLOCK(fb) g_mutex_unlock(((FolderBrowser *)(fb))->priv->lock);
-
#define PARENT_TYPE (gtk_table_get_type ())
static void folder_changed(CamelObject *o, void *event_data, void *data);
@@ -124,28 +112,8 @@ folder_browser_finalise (GtkObject *object)
{
FolderBrowser *folder_browser;
CORBA_Environment ev;
- FolderBrowserPrivate *p;
folder_browser = FOLDER_BROWSER(object);
- p = folder_browser->priv;
-
- /* This @#$#@ is to make sure we dont have any outstanding implicit
- refs on us from outstanding async tasks */
- FOLDER_BROWSER_LOCK(folder_browser);
- while (p->tasks) {
- int id;
-
- id = (int)p->tasks->data;
- FOLDER_BROWSER_UNLOCK(folder_browser);
- mail_msg_wait(id);
- FOLDER_BROWSER_LOCK(folder_browser);
- }
- /* the tasks_done list is just to avoid races, we can simply free it now */
- g_slist_free(p->tasks_done);
- p->tasks_done = NULL;
- FOLDER_BROWSER_UNLOCK(folder_browser);
-
- CORBA_exception_init (&ev);
if (folder_browser->seen_id != 0) {
gtk_timeout_remove (folder_browser->seen_id);
@@ -156,7 +124,22 @@ folder_browser_finalise (GtkObject *object)
gtk_timeout_remove(folder_browser->loading_id);
folder_browser->loading_id = 0;
}
-
+
+ /* wait for all outstanding async events against us */
+ mail_async_event_destroy(folder_browser->async_event);
+
+ if (folder_browser->folder) {
+ camel_object_unhook_event(CAMEL_OBJECT(folder_browser->folder), "folder_changed",
+ folder_changed, folder_browser);
+ camel_object_unhook_event(CAMEL_OBJECT(folder_browser->folder), "message_changed",
+ folder_changed, folder_browser);
+ mail_sync_folder (folder_browser->folder, NULL, NULL);
+ camel_object_unref (CAMEL_OBJECT (folder_browser->folder));
+ folder_browser->folder = NULL;
+ }
+
+ CORBA_exception_init (&ev);
+
if (folder_browser->search_full)
gtk_object_unref (GTK_OBJECT (folder_browser->search_full));
@@ -179,15 +162,6 @@ folder_browser_finalise (GtkObject *object)
g_free (folder_browser->uri);
folder_browser->uri = NULL;
- if (folder_browser->folder) {
- camel_object_unhook_event(CAMEL_OBJECT(folder_browser->folder), "folder_changed",
- folder_changed, folder_browser);
- camel_object_unhook_event(CAMEL_OBJECT(folder_browser->folder), "message_changed",
- folder_changed, folder_browser);
- mail_sync_folder (folder_browser->folder, NULL, NULL);
- camel_object_unref (CAMEL_OBJECT (folder_browser->folder));
- folder_browser->folder = NULL;
- }
CORBA_exception_free (&ev);
@@ -207,9 +181,6 @@ folder_browser_finalise (GtkObject *object)
if (folder_browser->clipboard_selection)
g_byte_array_free (folder_browser->clipboard_selection, TRUE);
- g_mutex_free(p->lock);
- g_free(p);
-
folder_browser_parent_class->finalize(object);
}
@@ -821,43 +792,18 @@ update_status_bar(FolderBrowser *fb)
static void main_folder_changed(CamelObject *o, void *event_data, void *data)
{
FolderBrowser *fb = data;
- FolderBrowserPrivate *p = fb->priv;
- int id;
/* so some corba unref doesnt blow us away while we're busy */
gtk_object_ref((GtkObject *)fb);
update_status_bar(fb);
-
- id = mail_proxy_event_id();
- if (id != -1) {
- FOLDER_BROWSER_LOCK(fb);
- if (g_slist_find(p->tasks, (void *)id))
- p->tasks = g_slist_remove(p->tasks, (void *)id);
- else
- p->tasks_done = g_slist_prepend(p->tasks_done, (void *)id);
- FOLDER_BROWSER_UNLOCK(fb);
- }
gtk_object_unref((GtkObject *)fb);
}
static void folder_changed(CamelObject *o, void *event_data, void *data)
{
- int id;
FolderBrowser *fb = data;
- FolderBrowserPrivate *p = fb->priv;
-
- /* this snot is so we can implicitly and asynchronosly ref
- the folder browser, since we can't actually ref it because
- gtk_object_ref isn't threadsafe ... #@$@ */
- id = mail_proxy_event(main_folder_changed, o, event_data, data);
- if (id != -1) {
- FOLDER_BROWSER_LOCK(fb);
- if (g_slist_find(p->tasks_done, (void *)id))
- p->tasks_done = g_slist_remove(p->tasks_done, (void *)id);
- else
- p->tasks = g_slist_prepend(p->tasks, (void *)id);
- FOLDER_BROWSER_UNLOCK(fb);
- }
+
+ mail_async_event_emit(fb->async_event, main_folder_changed, o, NULL, data);
}
static void
@@ -1966,10 +1912,8 @@ static void
folder_browser_init (GtkObject *object)
{
FolderBrowser *fb = (FolderBrowser *)object;
- FolderBrowserPrivate *p;
- p = fb->priv = g_malloc0(sizeof(*fb->priv));
- p->lock = g_mutex_new();
+ fb->async_event = mail_async_event_new();
}
static void
diff --git a/mail/folder-browser.h b/mail/folder-browser.h
index fcedd9e352..68a678bf4d 100644
--- a/mail/folder-browser.h
+++ b/mail/folder-browser.h
@@ -17,7 +17,6 @@
#include "mail-types.h"
#include "shell/Evolution.h"
-
#define FOLDER_BROWSER_TYPE (folder_browser_get_type ())
#define FOLDER_BROWSER(o) (GTK_CHECK_CAST ((o), FOLDER_BROWSER_TYPE, FolderBrowser))
#define FOLDER_BROWSER_CLASS(k) (GTK_CHECK_CLASS_CAST((k), FOLDER_BROWSER_TYPE, FolderBrowserClass))
@@ -36,8 +35,6 @@ typedef enum _FolderBrowserSelectionState {
struct _FolderBrowser {
GtkTable parent;
- struct _FolderBrowserPrivate *priv;
-
BonoboPropertyBag *properties;
GNOME_Evolution_Shell shell;
@@ -83,8 +80,10 @@ struct _FolderBrowser {
GtkWidget *invisible;
GByteArray *clipboard_selection;
-};
+ /* for async events */
+ struct _MailAsyncEvent *async_event;
+};
typedef struct {
GtkTableClass parent_class;
diff --git a/mail/mail-folder-cache.c b/mail/mail-folder-cache.c
index b1bf92bee0..ccff8f7555 100644
--- a/mail/mail-folder-cache.c
+++ b/mail/mail-folder-cache.c
@@ -70,6 +70,7 @@ struct _store_info {
/* only 1 should be set */
EvolutionStorage *storage;
GNOME_Evolution_Storage corba_storage;
+ MailAsyncEvent *async_event;
};
static GHashTable *stores;
@@ -195,9 +196,8 @@ folder_changed(CamelObject *o, gpointer event_data, gpointer user_data)
return;
d(printf("Fodler changed!\n"));
- /* hopefully our mfi isn't lost while this is executing ... */
camel_object_ref((CamelObject *)o);
- mail_proxy_event((CamelObjectEventHookFunc)real_folder_changed, o, NULL, mfi);
+ mail_async_event_emit(mfi->store_info->async_event, (CamelObjectEventHookFunc)real_folder_changed, o, NULL, mfi);
}
static void
@@ -210,74 +210,90 @@ folder_finalised(CamelObject *o, gpointer event_data, gpointer user_data)
}
static void
+folder_deleted(CamelObject *o, gpointer event_data, gpointer user_data)
+{
+ struct _folder_info *mfi = user_data;
+
+ (printf("Folder deleted '%s'!\n", ((CamelFolder *)o)->full_name));
+ mfi->folder = NULL;
+}
+
+static void
real_note_folder(CamelFolder *folder, void *event_data, void *data)
{
+ struct _folder_info *mfi = event_data;
+
+ update_1folder(mfi, NULL);
+ camel_object_unref((CamelObject *)folder);
+}
+
+void mail_note_folder(CamelFolder *folder)
+{
CamelStore *store = folder->parent_store;
struct _store_info *si;
struct _folder_info *mfi;
+ if (stores == NULL) {
+ g_warning("Adding a folder `%s' to a store which hasn't been added yet?\n", folder->full_name);
+ return;
+ }
+
LOCK(info_lock);
si = g_hash_table_lookup(stores, store);
- UNLOCK(info_lock);
if (si == NULL) {
g_warning("Adding a folder `%s' to a store %p which hasn't been added yet?\n", folder->full_name, store);
- camel_object_unref((CamelObject *)folder);
+ UNLOCK(info_lock);
return;
}
- LOCK(info_lock);
mfi = g_hash_table_lookup(si->folders, folder->full_name);
- UNLOCK(info_lock);
-
if (mfi == NULL) {
g_warning("Adding a folder `%s' that I dont know about yet?", folder->full_name);
- camel_object_unref((CamelObject *)folder);
+ UNLOCK(info_lock);
return;
}
/* dont do anything if we already have this */
if (mfi->folder == folder) {
- camel_object_unref (CAMEL_OBJECT (folder));
+ UNLOCK(info_lock);
return;
}
mfi->folder = folder;
- update_1folder(mfi, NULL);
camel_object_hook_event((CamelObject *)folder, "folder_changed", folder_changed, mfi);
camel_object_hook_event((CamelObject *)folder, "message_changed", folder_changed, mfi);
+ camel_object_hook_event((CamelObject *)folder, "deleted", folder_deleted, mfi);
camel_object_hook_event((CamelObject *)folder, "finalize", folder_finalised, mfi);
- camel_object_unref((CamelObject *)folder);
+ camel_object_ref((CamelObject *)folder);
+
+ UNLOCK(info_lock);
+
+ mail_async_event_emit(si->async_event, (CamelObjectEventHookFunc)real_note_folder, (CamelObject *)folder, (void *)mfi, NULL);
}
-void mail_note_folder(CamelFolder *folder)
+static void
+real_folder_created(CamelStore *store, struct _store_info *si, CamelFolderInfo *fi)
{
- if (stores == NULL) {
- g_warning("Adding a folder `%s' to a store which hasn't been added yet?\n", folder->full_name);
- return;
- }
-
- camel_object_ref((CamelObject *)folder);
- mail_proxy_event((CamelObjectEventHookFunc)real_note_folder, (CamelObject *)folder, NULL, NULL);
+ setup_folder(fi, si);
+ camel_object_unref((CamelObject *)store);
}
static void
-real_folder_created(CamelStore *store, void *event_data, CamelFolderInfo *fi)
+store_folder_subscribed(CamelObject *o, void *event_data, void *data)
{
struct _store_info *si;
- d(printf("real_folder_created: %s (%s)\n", fi->full_name, fi->url));
-
LOCK(info_lock);
- si = g_hash_table_lookup(stores, store);
+ si = g_hash_table_lookup(stores, o);
+ if (si)
+ camel_object_ref(o);
UNLOCK(info_lock);
+
if (si)
- setup_folder(fi, si);
- else
- /* leaks, so what */
- g_warning("real_folder_created: can't find store: %s\n",
- camel_url_to_string(((CamelService *)store)->url, 0));
+ mail_async_event_emit(si->async_event,
+ (CamelObjectEventHookFunc)real_folder_created, o, si, event_data);
}
static void
@@ -285,14 +301,9 @@ store_folder_created(CamelObject *o, void *event_data, void *data)
{
/* we only want created events to do more work if we dont support subscriptions */
if (!camel_store_supports_subscriptions(CAMEL_STORE(o)))
- mail_msg_wait(mail_proxy_event((CamelObjectEventHookFunc)real_folder_created, o, NULL, event_data));
+ store_folder_subscribed(o, event_data, data);
}
-static void
-store_folder_subscribed(CamelObject *o, void *event_data, void *data)
-{
- mail_msg_wait(mail_proxy_event((CamelObjectEventHookFunc)real_folder_created, o, NULL, event_data));
-}
static void
real_folder_deleted(CamelStore *store, void *event_data, CamelFolderInfo *fi)
@@ -301,22 +312,35 @@ real_folder_deleted(CamelStore *store, void *event_data, CamelFolderInfo *fi)
if (strstr(fi->url, ";noselect") == NULL)
mail_vfolder_remove_uri(store, fi->url);
+
+ camel_object_unref((CamelObject *)store);
}
static void
-store_folder_deleted(CamelObject *o, void *event_data, void *data)
+store_folder_unsubscribed(CamelObject *o, void *event_data, void *data)
{
- /* we only want deleted events to do more work if we dont support subscriptions */
- if (!camel_store_supports_subscriptions(CAMEL_STORE(o)))
- mail_msg_wait(mail_proxy_event((CamelObjectEventHookFunc)real_folder_deleted, o, NULL, event_data));
+ struct _store_info *si;
+
+ LOCK(info_lock);
+ si = g_hash_table_lookup(stores, o);
+ if (si)
+ camel_object_ref(o);
+ UNLOCK(info_lock);
+
+ if (si)
+ mail_async_event_emit(si->async_event,
+ (CamelObjectEventHookFunc)real_folder_deleted, o, si, event_data);
}
static void
-store_folder_unsubscribed(CamelObject *o, void *event_data, void *data)
+store_folder_deleted(CamelObject *o, void *event_data, void *data)
{
- mail_msg_wait(mail_proxy_event((CamelObjectEventHookFunc)real_folder_deleted, o, NULL, event_data));
+ /* we only want deleted events to do more work if we dont support subscriptions */
+ if (!camel_store_supports_subscriptions(CAMEL_STORE(o)))
+ store_folder_unsubscribed(o, event_data, data);
}
+
static void
free_folder_info(char *path, struct _folder_info *info, void *data)
{
@@ -336,6 +360,9 @@ store_finalised(CamelObject *o, void *event_data, void *data)
si = g_hash_table_lookup(stores, store);
if (si) {
g_hash_table_remove(stores, store);
+ UNLOCK(info_lock);
+ mail_async_event_destroy(si->async_event);
+ LOCK(info_lock);
g_hash_table_foreach(si->folders, (GHFunc)free_folder_info, NULL);
g_hash_table_destroy(si->folders);
g_free(si);
@@ -408,6 +435,7 @@ mail_note_store(CamelStore *store, EvolutionStorage *storage, GNOME_Evolution_St
si->corba_storage = corba_storage;
si->store = store;
g_hash_table_insert(stores, store, si);
+ si->async_event = mail_async_event_new();
camel_object_hook_event((CamelObject *)store, "folder_created", store_folder_created, NULL);
camel_object_hook_event((CamelObject *)store, "folder_deleted", store_folder_deleted, NULL);
diff --git a/mail/mail-mt.c b/mail/mail-mt.c
index 0892688853..cf64485d85 100644
--- a/mail/mail-mt.c
+++ b/mail/mail-mt.c
@@ -69,6 +69,8 @@ static pthread_cond_t mail_msg_cond = PTHREAD_COND_INITIALIZER;
pthread_t mail_gui_thread;
+MailAsyncEvent *mail_async_event;
+
static void mail_msg_destroy(EThread *e, EMsg *msg, void *data);
void *mail_msg_new(mail_msg_op_t *ops, EMsgPort *reply_port, size_t size)
@@ -184,7 +186,7 @@ void mail_msg_free(void *msg)
g_free(m);
if (activity)
- mail_proxy_event(destroy_objects, NULL, activity, NULL);
+ mail_async_event_emit(mail_async_event, destroy_objects, NULL, activity, NULL);
}
/* hash table of ops->dialogue of active errors */
@@ -473,6 +475,8 @@ void mail_msg_init(void)
mail_msg_active = g_hash_table_new(NULL, NULL);
mail_gui_thread = pthread_self();
+
+ mail_async_event = mail_async_event_new();
}
/* ********************************************************************** */
@@ -764,65 +768,88 @@ mail_user_message (const char *type, const char *prompt, gboolean allow_cancel)
struct _proxy_msg {
struct _mail_msg msg;
+ MailAsyncEvent *ea;
CamelObjectEventHookFunc func;
CamelObject *o;
void *event_data;
void *data;
};
-static int mail_proxy_event_current = -1;
-
static void
-do_proxy_event(struct _mail_msg *mm)
+do_async_event(struct _mail_msg *mm)
{
struct _proxy_msg *m = (struct _proxy_msg *)mm;
- mail_proxy_event_current = mm->seq;
m->func(m->o, m->event_data, m->data);
- mail_proxy_event_current = -1;
+
+ g_mutex_lock(m->ea->lock);
+ m->ea->tasks = g_slist_remove(m->ea->tasks, (void *)mm->seq);
+ g_mutex_unlock(m->ea->lock);
+
}
-struct _mail_msg_op proxy_event_op = {
+struct _mail_msg_op async_event_op = {
NULL,
- do_proxy_event,
+ do_async_event,
NULL,
NULL,
};
-/* returns the current id of the executing proxy event */
-int mail_proxy_event_id(void)
+MailAsyncEvent *mail_async_event_new(void)
{
- return mail_proxy_event_current;
+ MailAsyncEvent *ea;
+
+ ea = g_malloc0(sizeof(*ea));
+ ea->lock = g_mutex_new();
+
+ return ea;
}
-int mail_proxy_event(CamelObjectEventHookFunc func, CamelObject *o, void *event_data, void *data)
+int mail_async_event_emit(MailAsyncEvent *ea, CamelObjectEventHookFunc func, CamelObject *o, void *event_data, void *data)
{
struct _proxy_msg *m;
int id;
int ismain = pthread_self() == mail_gui_thread;
if (ismain) {
- /* save the current id incase we're proxying an event in a proxied event */
- id = mail_proxy_event_current;
- mail_proxy_event_current = -1;
func(o, event_data, data);
- mail_proxy_event_current = id;
/* id of -1 is 'always finished' */
return -1;
} else {
/* we dont have a reply port for this, we dont care when/if it gets executed, just queue it */
- m = mail_msg_new(&proxy_event_op, NULL, sizeof(*m));
+ m = mail_msg_new(&async_event_op, NULL, sizeof(*m));
m->func = func;
m->o = o;
m->event_data = event_data;
m->data = data;
-
+ m->ea = ea;
+
id = m->msg.seq;
+ g_mutex_lock(ea->lock);
+ ea->tasks = g_slist_prepend(ea->tasks, (void *)id);
+ g_mutex_unlock(ea->lock);
e_msgport_put(mail_gui_port, (EMsg *)m);
return id;
}
}
+void mail_async_event_destroy(MailAsyncEvent *ea)
+{
+ int id;
+
+ g_mutex_lock(ea->lock);
+ while (ea->tasks) {
+ id = (int)ea->tasks->data;
+ g_mutex_unlock(ea->lock);
+ mail_msg_wait(id);
+ g_mutex_lock(ea->lock);
+ }
+ g_mutex_unlock(ea->lock);
+
+ g_mutex_free(ea->lock);
+ g_free(ea);
+}
+
/* ********************************************************************** */
struct _call_msg {
@@ -846,6 +873,11 @@ do_call(struct _mail_msg *mm)
p1 = va_arg(ap, void *);
m->ret = m->func(p1);
break;
+ case MAIL_CALL_p_pp:
+ p1 = va_arg(ap, void *);
+ p2 = va_arg(ap, void *);
+ m->ret = m->func(p1, p2);
+ break;
case MAIL_CALL_p_ppp:
p1 = va_arg(ap, void *);
p2 = va_arg(ap, void *);
diff --git a/mail/mail-mt.h b/mail/mail-mt.h
index 057de1ddb0..e3aebab7c5 100644
--- a/mail/mail-mt.h
+++ b/mail/mail-mt.h
@@ -68,14 +68,23 @@ char *mail_get_password (CamelService *service, const char *prompt,
*/
gboolean mail_user_message (const char *type, const char *prompt, gboolean allow_cancel);
+/* asynchronous event proxies */
+typedef struct _MailAsyncEvent {
+ GMutex *lock;
+ GSList *tasks;
+} MailAsyncEvent;
+
+/* create a new async event handler */
+MailAsyncEvent *mail_async_event_new(void);
/* forward a camel event (or other call) to the gui thread */
-int mail_proxy_event(CamelObjectEventHookFunc func, CamelObject *o, void *event_data, void *data);
-/* in main (only), get the current event id */
-int mail_proxy_event_id(void);
+int mail_async_event_emit(MailAsyncEvent *ea, CamelObjectEventHookFunc func, CamelObject *o, void *event_data, void *data);
+/* wait for all outstanding async events to complete */
+void mail_async_event_destroy(MailAsyncEvent *ea);
/* Call a function in the gui thread, wait for it to return, type is the marshaller to use */
typedef enum {
MAIL_CALL_p_p,
+ MAIL_CALL_p_pp,
MAIL_CALL_p_ppp,
MAIL_CALL_p_pppp,
MAIL_CALL_p_ppippp,
@@ -98,5 +107,8 @@ extern EThread *mail_thread_queued_slow; /* for operations that can (or should)
/* The main thread. */
extern pthread_t mail_gui_thread;
+/* A generic proxy event for anything that can be proxied during the life of the mailer (almost nothing) */
+/* Note that almost all objects care about the lifecycle of their events, so this cannot be used */
+extern MailAsyncEvent *mail_async_event;
#endif /* ! _MAIL_MT */
diff --git a/mail/mail-session.c b/mail/mail-session.c
index bf8d5560c3..0101845f74 100644
--- a/mail/mail-session.c
+++ b/mail/mail-session.c
@@ -271,19 +271,11 @@ camel_timeout (gpointer data)
}
static void
-do_register_timeout(CamelObject *o, void *edata, void *data)
+main_register_timeout(struct _timeout_data *td)
{
- struct _timeout_data *td = (struct _timeout_data *)edata;
-
td->result = gtk_timeout_add_full(td->interval, camel_timeout, NULL, td, g_free);
}
-static void
-do_remove_timeout(CamelObject *o, void *edata, void *data)
-{
- gtk_timeout_remove(*((int *)edata));
-}
-
static guint
register_timeout (CamelSession *session, guint32 interval, CamelTimeoutCallback cb, gpointer camel_data)
{
@@ -298,7 +290,7 @@ register_timeout (CamelSession *session, guint32 interval, CamelTimeoutCallback
g_warning("Timeout %u too small, increased to 1000", interval);
interval = 1000;
}
-
+
/* This is extremely messy, we need to proxy to gtk thread for this */
td = g_malloc (sizeof (*td));
td->interval = interval;
@@ -306,7 +298,7 @@ register_timeout (CamelSession *session, guint32 interval, CamelTimeoutCallback
td->cb = cb;
td->camel_data = camel_data;
- mail_msg_wait(mail_proxy_event(do_register_timeout, (CamelObject *)session, td, NULL));
+ mail_call_main(MAIL_CALL_p_p, (MailMainFunc)main_register_timeout, td);
if (td->result == 0) {
g_free(td);
@@ -316,10 +308,16 @@ register_timeout (CamelSession *session, guint32 interval, CamelTimeoutCallback
return td->result;
}
+static void
+main_remove_timeout(guint *edata)
+{
+ gtk_timeout_remove(*edata);
+}
+
static gboolean
remove_timeout (CamelSession *session, guint handle)
{
- mail_msg_wait(mail_proxy_event(do_remove_timeout, (CamelObject *)session, &handle, NULL));
+ mail_call_main(MAIL_CALL_p_p, (MailMainFunc)main_remove_timeout, &handle);
return TRUE;
}
diff --git a/mail/message-list.c b/mail/message-list.c
index fdb6e912c7..2cb0f081c2 100644
--- a/mail/message-list.c
+++ b/mail/message-list.c
@@ -1120,6 +1120,7 @@ message_list_init (GtkObject *object)
message_list->hide_lock = g_mutex_new();
message_list->uid_nodemap = g_hash_table_new (g_str_hash, g_str_equal);
+ message_list->async_event = mail_async_event_new();
}
static void
@@ -1127,6 +1128,8 @@ message_list_destroy (GtkObject *object)
{
MessageList *message_list = MESSAGE_LIST (object);
+ mail_async_event_destroy(message_list->async_event);
+
if (message_list->folder) {
save_tree_state(message_list);
hide_save_state(message_list);
@@ -1868,9 +1871,8 @@ main_folder_changed (CamelObject *o, gpointer event_data, gpointer user_data)
static void
folder_changed (CamelObject *o, gpointer event_data, gpointer user_data)
{
- /* similarly to message_changed, copy the change list and propagate it to
- the main thread and free it */
CamelFolderChangeInfo *changes;
+ MessageList *ml = MESSAGE_LIST (user_data);
if (event_data) {
changes = camel_folder_change_info_new();
@@ -1878,29 +1880,20 @@ folder_changed (CamelObject *o, gpointer event_data, gpointer user_data)
} else {
changes = NULL;
}
- mail_proxy_event (main_folder_changed, o, changes, user_data);
+
+ mail_async_event_emit(ml->async_event, main_folder_changed, o, changes, user_data);
}
static void
-main_message_changed (CamelObject *o, gpointer uid, gpointer user_data)
+message_changed (CamelObject *o, gpointer event_data, gpointer user_data)
{
- MessageList *ml = MESSAGE_LIST (user_data);
CamelFolderChangeInfo *changes;
+ MessageList *ml = MESSAGE_LIST (user_data);
changes = camel_folder_change_info_new();
- camel_folder_change_info_change_uid(changes, uid);
- main_folder_changed(o, changes, ml);
- g_free(uid);
-}
+ camel_folder_change_info_change_uid(changes, (char *)event_data);
-static void
-message_changed (CamelObject *o, gpointer event_data, gpointer user_data)
-{
- /* Here we copy the data because our thread may free the copy that we would reference.
- * The other thread would be passed a uid parameter that pointed to freed data.
- * We copy it and free it in the handler.
- */
- mail_proxy_event (main_message_changed, o, g_strdup ((gchar *)event_data), user_data);
+ mail_async_event_emit(ml->async_event, main_folder_changed, o, changes, user_data);
}
void
diff --git a/mail/message-list.h b/mail/message-list.h
index 380d57d46d..2846c04ec4 100644
--- a/mail/message-list.h
+++ b/mail/message-list.h
@@ -81,6 +81,9 @@ struct _MessageList {
/* locks */
GMutex *hide_lock; /* for any 'hide' info above */
+
+ /* for message/folder chagned event handling */
+ struct _MailAsyncEvent *async_event;
};
typedef struct {