From ed24dfc2832e41d3666dcd9f421b561efc209b1d Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Wed, 1 Oct 2008 08:26:24 +0000 Subject: ** Fix for bug #553527 2008-10-01 Milan Crha ** Fix for bug #553527 * bbdb.c: (struct todo_struct), (free_todo_struct), (bbdb_do_in_thread), (bbdb_do_thread), (bbdb_handle_reply): Do the EBook work in a separate thread to have better performance on reply with slow address books. svn path=/trunk/; revision=36518 --- plugins/bbdb/bbdb.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 98 insertions(+), 13 deletions(-) (limited to 'plugins/bbdb/bbdb.c') diff --git a/plugins/bbdb/bbdb.c b/plugins/bbdb/bbdb.c index a2ec60d243..547a779961 100644 --- a/plugins/bbdb/bbdb.c +++ b/plugins/bbdb/bbdb.c @@ -132,33 +132,120 @@ bbdb_timeout (gpointer data) return TRUE; } -/* Code to populate addressbook when you reply to a mail follows */ +typedef struct +{ + char *name; + char *email; +} todo_struct; -void -bbdb_handle_reply (EPlugin *ep, EMEventTargetMessage *target) +static void +free_todo_struct (todo_struct *td) { - const CamelInternetAddress *cia; - EBook *book = NULL; - int i; + if (td) { + g_free (td->name); + g_free (td->email); + g_free (td); + } +} + +static GSList *todo = NULL; +G_LOCK_DEFINE_STATIC (todo); + +static gpointer +bbdb_do_in_thread (gpointer data) +{ + EBook *book; /* Open the addressbook */ book = bbdb_open_addressbook (AUTOMATIC_CONTACTS_ADDRESSBOOK); - if (book == NULL) + if (book == NULL) { + G_LOCK (todo); + + g_slist_foreach (todo, (GFunc)free_todo_struct, NULL); + g_slist_free (todo); + todo = NULL; + + G_UNLOCK (todo); + return NULL; + } + + G_LOCK (todo); + while (todo) { + todo_struct *td = todo->data; + + todo = g_slist_remove (todo, td); + + G_UNLOCK (todo); + + if (td) { + bbdb_do_it (book, td->name, td->email); + free_todo_struct (td); + } + + G_LOCK (todo); + } + G_UNLOCK (todo); + + g_object_unref (book); + + return NULL; +} + +static void +bbdb_do_thread (const char *name, const char *email) +{ + todo_struct *td; + + if (!name && !email) return; + td = g_new (todo_struct, 1); + td->name = g_strdup (name); + td->email = g_strdup (email); + + G_LOCK (todo); + if (todo) { + /* the list isn't empty, which means there is a thread taking + care of that, thus just add it to the queue */ + todo = g_slist_append (todo, td); + } else { + GError *error = NULL; + + /* list was empty, add item and create a thread */ + todo = g_slist_append (todo, td); + g_thread_create (bbdb_do_in_thread, NULL, FALSE, &error); + + if (error) { + g_warning ("%s: Creation of the thread failed with error: %s", G_STRFUNC, error->message); + g_error_free (error); + + G_UNLOCK (todo); + bbdb_do_in_thread (NULL); + G_LOCK (todo); + } + } + G_UNLOCK (todo); +} + +/* Code to populate addressbook when you reply to a mail follows */ +void +bbdb_handle_reply (EPlugin *ep, EMEventTargetMessage *target) +{ + const CamelInternetAddress *cia; + int i; + cia = camel_mime_message_get_from (target->message); if (cia) { for (i = 0; i < camel_address_length (CAMEL_ADDRESS (cia)); i ++) { const char *name=NULL, *email=NULL; if (!(camel_internet_address_get (cia, i, &name, &email))) continue; - bbdb_do_it (book, name, email); + bbdb_do_thread (name, email); } } /* If this is a reply-all event, process To: and Cc: also. */ if (((EEventTarget *) target)->mask & EM_EVENT_MESSAGE_REPLY_ALL) { - g_object_unref (G_OBJECT (book)); return; } @@ -168,7 +255,7 @@ bbdb_handle_reply (EPlugin *ep, EMEventTargetMessage *target) const char *name=NULL, *email=NULL; if (!(camel_internet_address_get (cia, i, &name, &email))) continue; - bbdb_do_it (book, name, email); + bbdb_do_thread (name, email); } } @@ -178,11 +265,9 @@ bbdb_handle_reply (EPlugin *ep, EMEventTargetMessage *target) const char *name=NULL, *email=NULL; if (!(camel_internet_address_get (cia, i, &name, &email))) continue; - bbdb_do_it (book, name, email); + bbdb_do_thread (name, email); } } - - g_object_unref (G_OBJECT (book)); } static void -- cgit v1.2.3