From 41802db26312f2d70ff5624e331e45277ce8a8ec Mon Sep 17 00:00:00 2001 From: 6 Date: Tue, 16 Oct 2001 17:34:59 +0000 Subject: New function to return the id of the currently executing proxied event. 2001-10-16 * mail-mt.c (mail_proxy_event_id): New function to return the id of the currently executing proxied event. * folder-browser.h: Added private field. * folder-browser.c (folder_changed): Keep track of tasks outstanding in the tasks list, locked access. (FOLDER_BROWSER_LOCK, UNLOCK): Macros to lock the folder browser for poking about in diff threads. (folder_browser_finalise): Wait for any outstanding takss to finish before cleaning ourself up. (folder_browser_destroy): Move the seen_id handling to finalise, also add a loading_id handling code. (main_folder_changed): Remove our running task when done. svn path=/trunk/; revision=13695 --- mail/ChangeLog | 17 ++++++++++ mail/folder-browser.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++----- mail/folder-browser.h | 4 ++- mail/mail-mt.c | 14 +++++++++ mail/mail-mt.h | 2 ++ 5 files changed, 116 insertions(+), 8 deletions(-) diff --git a/mail/ChangeLog b/mail/ChangeLog index 0700991a68..b2422fe53b 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,20 @@ +2001-10-16 + + * mail-mt.c (mail_proxy_event_id): New function to return the id + of the currently executing proxied event. + + * folder-browser.h: Added private field. + + * folder-browser.c (folder_changed): Keep track of tasks + outstanding in the tasks list, locked access. + (FOLDER_BROWSER_LOCK, UNLOCK): Macros to lock the folder browser + for poking about in diff threads. + (folder_browser_finalise): Wait for any outstanding takss to + finish before cleaning ourself up. + (folder_browser_destroy): Move the seen_id handling to finalise, + also add a loading_id handling code. + (main_folder_changed): Remove our running task when done. + 2001-10-15 Larry Ewing * mail-display.c (mail_error_write): don't write strings longer diff --git a/mail/folder-browser.c b/mail/folder-browser.c index d68ccacae9..bd0c4bbb2f 100644 --- a/mail/folder-browser.c +++ b/mail/folder-browser.c @@ -58,6 +58,18 @@ #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); @@ -112,10 +124,38 @@ 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); + folder_browser->seen_id = 0; + } + + if (folder_browser->loading_id != 0) { + gtk_timeout_remove(folder_browser->loading_id); + folder_browser->loading_id = 0; + } if (folder_browser->search_full) gtk_object_unref (GTK_OBJECT (folder_browser->search_full)); @@ -167,6 +207,9 @@ 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); } @@ -176,12 +219,7 @@ folder_browser_destroy (GtkObject *object) FolderBrowser *folder_browser; folder_browser = FOLDER_BROWSER (object); - - if (folder_browser->seen_id) { - gtk_timeout_remove (folder_browser->seen_id); - folder_browser->seen_id = 0; - } - + if (folder_browser->message_list) { gtk_widget_destroy (GTK_WIDGET (folder_browser->message_list)); folder_browser->message_list = NULL; @@ -783,13 +821,43 @@ 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) { - mail_msg_wait(mail_proxy_event(main_folder_changed, o, event_data, 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); + } } static void @@ -1897,6 +1965,11 @@ on_message_selected (MessageList *ml, const char *uid, FolderBrowser *fb) 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(); } static void diff --git a/mail/folder-browser.h b/mail/folder-browser.h index 85a6d6bbaf..fcedd9e352 100644 --- a/mail/folder-browser.h +++ b/mail/folder-browser.h @@ -35,6 +35,8 @@ typedef enum _FolderBrowserSelectionState { struct _FolderBrowser { GtkTable parent; + + struct _FolderBrowserPrivate *priv; BonoboPropertyBag *properties; @@ -56,7 +58,7 @@ struct _FolderBrowser { char *new_uid; /* place to save the next uid during idle timeout */ char *loaded_uid; /* what we have loaded */ guint loading_id, seen_id; - + /* a folder we are expunging, dont use other than to compare the pointer value */ CamelFolder *expunging; diff --git a/mail/mail-mt.c b/mail/mail-mt.c index e9803a80e3..0892688853 100644 --- a/mail/mail-mt.c +++ b/mail/mail-mt.c @@ -770,12 +770,16 @@ struct _proxy_msg { void *data; }; +static int mail_proxy_event_current = -1; + static void do_proxy_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; } struct _mail_msg_op proxy_event_op = { @@ -785,6 +789,12 @@ struct _mail_msg_op proxy_event_op = { NULL, }; +/* returns the current id of the executing proxy event */ +int mail_proxy_event_id(void) +{ + return mail_proxy_event_current; +} + int mail_proxy_event(CamelObjectEventHookFunc func, CamelObject *o, void *event_data, void *data) { struct _proxy_msg *m; @@ -792,7 +802,11 @@ int mail_proxy_event(CamelObjectEventHookFunc func, CamelObject *o, void *event_ 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 { diff --git a/mail/mail-mt.h b/mail/mail-mt.h index feeddd10cc..057de1ddb0 100644 --- a/mail/mail-mt.h +++ b/mail/mail-mt.h @@ -70,6 +70,8 @@ gboolean mail_user_message (const char *type, const char *prompt, gboolean allow /* 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); /* Call a function in the gui thread, wait for it to return, type is the marshaller to use */ typedef enum { -- cgit v1.2.3