lock the idle mutex around this function, reset it to -1, and return
authorChris Toshok <toshok@ximian.com>
Sun, 8 Feb 2004 20:54:54 +0000 (20:54 +0000)
committerChris Toshok <toshok@src.gnome.org>
Sun, 8 Feb 2004 20:54:54 +0000 (20:54 +0000)
2004-02-08  Chris Toshok  <toshok@ximian.com>

* libebook/e-book-async.c (main_thread_get_response): lock the
idle mutex around this function, reset it to -1, and return FALSE.
(push_response): abstract out all the g_async_queue_push stuff
from the various handlers.  do proper locking, and register the
main thread idle handler if we need to.
(e_book_async_load_local_addressbook): new function.  async
version of e_book_load_local_addressbok.
(*_handler): use push_response instead of g_async_queue_push.
(init_async): remove the timeout stuff.  we register idle handlers
when we need to.  no more polling the async queue.

* libebook/e-book-async.h: add prototype for
e_book_async_load_local_addressbook.

* libebook/e-book-view-listener.c (main_thread_get_response): new
function to read responses from the CORBA request threads.
(e_book_view_listener_queue_response): don't just emit a signal
here, as that causes the response to be handled on the request
thread, and hoists re-entrancy requirements on calling code.
instead, push the response onto the async queue.
(e_book_view_listener_new): initialize the
queue/idle_mutex/idle_id.
(e_book_view_listener_dispose): dispose of the idle foo/queue.

addressbook/ChangeLog
addressbook/libebook/e-book-async.c
addressbook/libebook/e-book-async.h
addressbook/libebook/e-book-view-listener.c

index 390e7e8..cb97299 100644 (file)
@@ -1,5 +1,31 @@
 2004-02-08  Chris Toshok  <toshok@ximian.com>
 
+       * libebook/e-book-async.c (main_thread_get_response): lock the
+       idle mutex around this function, reset it to -1, and return FALSE.
+       (push_response): abstract out all the g_async_queue_push stuff
+       from the various handlers.  do proper locking, and register the
+       main thread idle handler if we need to.
+       (e_book_async_load_local_addressbook): new function.  async
+       version of e_book_load_local_addressbok.
+       (*_handler): use push_response instead of g_async_queue_push.
+       (init_async): remove the timeout stuff.  we register idle handlers
+       when we need to.  no more polling the async queue.
+
+       * libebook/e-book-async.h: add prototype for
+       e_book_async_load_local_addressbook.
+
+       * libebook/e-book-view-listener.c (main_thread_get_response): new
+       function to read responses from the CORBA request threads.
+       (e_book_view_listener_queue_response): don't just emit a signal
+       here, as that causes the response to be handled on the request
+       thread, and hoists re-entrancy requirements on calling code.
+       instead, push the response onto the async queue.
+       (e_book_view_listener_new): initialize the
+       queue/idle_mutex/idle_id.
+       (e_book_view_listener_dispose): dispose of the idle foo/queue.
+
+2004-02-08  Chris Toshok  <toshok@ximian.com>
+
        * backends/file/e-book-backend-file.c
        (e_book_backend_file_start_book_view): don't free the
        closure/mutex inside the loop, then access it again right after
index 75ec1cb..9879ad7 100644 (file)
@@ -5,6 +5,8 @@
 static GThread *worker_thread;
 static GAsyncQueue *to_worker_queue;
 static GAsyncQueue *from_worker_queue;
+static GStaticMutex idle_mutex = G_STATIC_MUTEX_INIT;
+static guint idle_id = -1;
 
 typedef struct _EBookMsg EBookMsg;
 
@@ -29,16 +31,34 @@ worker (gpointer data)
 }
 
 static gboolean
-main_thread_check_for_response (gpointer data)
+main_thread_get_response (gpointer data)
 {
        EBookMsg *msg;
 
+       g_static_mutex_lock (&idle_mutex);
+
+       idle_id = -1;
+
        while ((msg = g_async_queue_try_pop (from_worker_queue)) != NULL) {
                msg->handler (msg);
                msg->dtor (msg);
        }
-       
-       return TRUE;
+
+       g_static_mutex_unlock (&idle_mutex);
+
+       return FALSE;
+}
+
+static void
+push_response (gpointer response)
+{
+       g_static_mutex_lock (&idle_mutex);
+
+       g_async_queue_push (from_worker_queue, response);
+       if (idle_id == -1)
+               idle_id = g_idle_add (main_thread_get_response, NULL);
+
+       g_static_mutex_unlock (&idle_mutex);
 }
 
 static void
@@ -57,7 +77,6 @@ init_async()
                to_worker_queue = g_async_queue_new ();
                from_worker_queue = g_async_queue_new ();
                worker_thread = g_thread_create (worker, NULL, FALSE, NULL);
-               g_timeout_add (300, main_thread_check_for_response, NULL);
        }
 }
 
@@ -67,6 +86,95 @@ typedef struct {
        EBookMsg msg;
 
        EBook *book;
+       EBookCallback open_response;
+       gpointer closure;
+} LoadLocalBookMsg;
+
+typedef struct {
+       EBookMsg msg;
+
+       EBook *book;
+       EBookStatus status;
+       EBookCallback open_response;
+       gpointer closure;
+} LoadLocalBookResponse;
+
+static void
+_load_local_book_response_handler (EBookMsg *msg)
+{
+       LoadLocalBookResponse *resp = (LoadLocalBookResponse*)msg;
+
+       resp->open_response (resp->book, resp->status, resp->closure);
+}
+
+static void
+_load_local_book_response_dtor (EBookMsg *msg)
+{
+       LoadLocalBookResponse *resp = (LoadLocalBookResponse*)msg;
+
+       g_object_unref (resp->book);
+       g_free (resp);
+}
+
+static void
+_load_local_book_handler (EBookMsg *msg)
+{
+       LoadLocalBookMsg *load_msg = (LoadLocalBookMsg *)msg;
+       LoadLocalBookResponse *response;
+       GError *error = NULL;
+
+       response = g_new0 (LoadLocalBookResponse, 1);
+       e_book_msg_init ((EBookMsg*)response, _load_local_book_response_handler, _load_local_book_response_dtor);
+
+       response->status = E_BOOK_ERROR_OK;
+       if (!e_book_load_local_addressbook (load_msg->book, &error)) {
+               response->status = error->code;
+               g_error_free (error);
+       }
+
+       response->book = load_msg->book;
+       response->open_response = load_msg->open_response;
+       response->closure = load_msg->closure;
+
+       push_response (response);
+}
+
+static void
+_load_local_book_dtor (EBookMsg *msg)
+{
+       LoadLocalBookMsg *load_msg = (LoadLocalBookMsg *)msg;
+       
+       g_free (load_msg);
+}
+
+void
+e_book_async_load_local_addressbook (EBook                 *book,
+                                    EBookCallback          open_response,
+                                    gpointer               closure)
+{
+       LoadLocalBookMsg *msg;
+
+       g_return_if_fail (E_IS_BOOK (book));
+       g_return_if_fail (open_response != NULL);
+
+       init_async ();
+
+       msg = g_new (LoadLocalBookMsg, 1);
+       e_book_msg_init ((EBookMsg*)msg, _load_local_book_handler, _load_local_book_dtor);
+
+       msg->book = g_object_ref (book);
+       msg->open_response = open_response;
+       msg->closure = closure;
+
+       g_async_queue_push (to_worker_queue, msg);
+}
+
+\f
+
+typedef struct {
+       EBookMsg msg;
+
+       EBook *book;
        ESource *source;
        EBookCallback open_response;
        gpointer closure;
@@ -118,7 +226,7 @@ _load_source_handler (EBookMsg *msg)
        response->open_response = source_msg->open_response;
        response->closure = source_msg->closure;
 
-       g_async_queue_push (from_worker_queue, response);
+       push_response (response);
 }
 
 static void
@@ -189,6 +297,7 @@ e_book_async_load_uri (EBook                 *book,
        g_object_unref (group);
 }
 
+
 \f
 
 typedef struct {
@@ -243,7 +352,7 @@ _default_book_handler (EBookMsg *msg)
        response->open_response = dfb_msg->open_response;
        response->closure = dfb_msg->closure;
 
-       g_async_queue_push (from_worker_queue, response);
+       push_response (response);
 }
 
 static void
@@ -341,7 +450,7 @@ _get_fields_handler (EBookMsg *msg)
        response->cb = fields_msg->cb;
        response->closure = fields_msg->closure;
 
-       g_async_queue_push (from_worker_queue, response);
+       push_response (response);
 }
 
 guint
@@ -436,7 +545,7 @@ _get_methods_handler (EBookMsg *msg)
        response->cb = methods_msg->cb;
        response->closure = methods_msg->closure;
 
-       g_async_queue_push (from_worker_queue, response);
+       push_response (response);
 }
 
 guint
@@ -521,7 +630,7 @@ _auth_user_handler (EBookMsg *msg)
        response->cb = auth_msg->cb;
        response->closure = auth_msg->closure;
 
-       g_async_queue_push (from_worker_queue, response);
+       push_response (response);
 }
 
 static void
@@ -626,7 +735,7 @@ _get_contact_handler (EBookMsg *msg)
        response->cb = get_contact_msg->cb;
        response->closure = get_contact_msg->closure;
 
-       g_async_queue_push (from_worker_queue, response);
+       push_response (response);
 }
 
 static void
@@ -756,7 +865,7 @@ _remove_contacts_handler (EBookMsg *msg)
        response->cb = remove_contacts_msg->cb;
        response->closure = remove_contacts_msg->closure;
 
-       g_async_queue_push (from_worker_queue, response);
+       push_response (response);
 }
 
 static void
@@ -861,7 +970,7 @@ _add_contact_handler (EBookMsg *msg)
        response->cb = add_contact_msg->cb;
        response->closure = add_contact_msg->closure;
 
-       g_async_queue_push (from_worker_queue, response);
+       push_response (response);
 }
 
 static void
@@ -957,7 +1066,7 @@ _commit_contact_handler (EBookMsg *msg)
        response->cb = commit_contact_msg->cb;
        response->closure = commit_contact_msg->closure;
 
-       g_async_queue_push (from_worker_queue, response);
+       push_response (response);
 }
 
 static void
@@ -1058,7 +1167,7 @@ _get_book_view_handler (EBookMsg *msg)
        response->cb = view_msg->cb;
        response->closure = view_msg->closure;
 
-       g_async_queue_push (from_worker_queue, response);
+       push_response (response);
 }
 
 static void
@@ -1162,7 +1271,7 @@ _get_contacts_handler (EBookMsg *msg)
        response->cb = view_msg->cb;
        response->closure = view_msg->closure;
 
-       g_async_queue_push (from_worker_queue, response);
+       push_response (response);
 }
 
 static void
index 283b7d4..388577f 100644 (file)
@@ -43,6 +43,10 @@ void      e_book_async_load_source              (EBook                 *book,
                                                 EBookCallback          open_response,
                                                 gpointer               closure);
 
+void      e_book_async_load_local_addressbook   (EBook                 *book,
+                                                EBookCallback          open_response,
+                                                gpointer               closure);
+
 void      e_book_async_get_default_addressbook  (EBookCallback          open_response,
                                                 gpointer               closure);
 
index 11e1d10..ba6e79b 100644 (file)
@@ -27,10 +27,45 @@ static guint e_book_view_listener_signals [LAST_SIGNAL];
 
 static BonoboObjectClass          *parent_class;
 
+#define READ_END 0
+#define WRITE_END 1
+
 struct _EBookViewListenerPrivate {
        guint stopped      : 1;
+       GAsyncQueue *queue;
+
+       GMutex *idle_mutex;
+       guint idle_id;
 };
 
+static gboolean
+main_thread_get_response (gpointer data)
+{
+       EBookViewListener *listener = data;
+       EBookViewListenerResponse *response;
+
+       bonobo_object_ref (listener);
+
+       g_mutex_lock (listener->priv->idle_mutex);
+
+       /* remove the idle call */
+
+       while ((response = g_async_queue_try_pop (listener->priv->queue)) != NULL) {
+
+               g_signal_emit (listener, e_book_view_listener_signals [RESPONSE], 0, response);
+
+               bonobo_object_unref (listener);
+       }
+
+       listener->priv->idle_id = -1;
+
+       g_mutex_unlock (listener->priv->idle_mutex);
+
+       bonobo_object_unref (listener);
+       
+       return FALSE;
+}
+
 static void
 e_book_view_listener_queue_response (EBookViewListener         *listener,
                                     EBookViewListenerResponse *response)
@@ -49,7 +84,15 @@ e_book_view_listener_queue_response (EBookViewListener         *listener,
                return;
        }
 
-       g_signal_emit (listener, e_book_view_listener_signals [RESPONSE], 0, response);
+       bonobo_object_ref (listener);
+
+       g_mutex_lock (listener->priv->idle_mutex);
+
+       g_async_queue_push (listener->priv->queue, response);
+
+       if (listener->priv->idle_id == -1)
+               listener->priv->idle_id = g_idle_add (main_thread_get_response, listener);
+       g_mutex_unlock (listener->priv->idle_mutex);
 }
 
 /* Add, Remove, Modify */
@@ -223,12 +266,6 @@ e_book_view_listener_convert_status (const GNOME_Evolution_Addressbook_CallStatu
        }
 }
 
-static void
-e_book_view_listener_construct      (EBookViewListener *listener)
-{
-       /* nothing needed here */
-}
-
 /**
  * e_book_view_listener_new:
  *
@@ -242,10 +279,12 @@ e_book_view_listener_new ()
        EBookViewListener *listener;
 
        listener = g_object_new (E_TYPE_BOOK_VIEW_LISTENER,
-                                "poa", bonobo_poa_get_threaded (ORBIT_THREAD_HINT_ALL_AT_IDLE, NULL),
+                                "poa", bonobo_poa_get_threaded (ORBIT_THREAD_HINT_PER_REQUEST, NULL),
                                 NULL);
 
-       e_book_view_listener_construct (listener);
+       listener->priv->queue = g_async_queue_new();
+       listener->priv->idle_mutex = g_mutex_new();
+       listener->priv->idle_id = -1;
 
        return listener;
 }
@@ -270,6 +309,13 @@ e_book_view_listener_dispose (GObject *object)
        EBookViewListener *listener = E_BOOK_VIEW_LISTENER (object);
 
        if (listener->priv) {
+               if (listener->priv->idle_id != -1)
+                       g_source_remove (listener->priv->idle_id);
+
+               g_mutex_free (listener->priv->idle_mutex);
+
+               g_async_queue_unref (listener->priv->queue);
+
                g_free (listener->priv);
                listener->priv = NULL;
        }