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
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;
}
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
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);
}
}
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;
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
g_object_unref (group);
}
+
\f
typedef struct {
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
response->cb = fields_msg->cb;
response->closure = fields_msg->closure;
- g_async_queue_push (from_worker_queue, response);
+ push_response (response);
}
guint
response->cb = methods_msg->cb;
response->closure = methods_msg->closure;
- g_async_queue_push (from_worker_queue, response);
+ push_response (response);
}
guint
response->cb = auth_msg->cb;
response->closure = auth_msg->closure;
- g_async_queue_push (from_worker_queue, response);
+ push_response (response);
}
static void
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
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
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
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
response->cb = view_msg->cb;
response->closure = view_msg->closure;
- g_async_queue_push (from_worker_queue, response);
+ push_response (response);
}
static void
response->cb = view_msg->cb;
response->closure = view_msg->closure;
- g_async_queue_push (from_worker_queue, response);
+ push_response (response);
}
static void
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)
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 */
}
}
-static void
-e_book_view_listener_construct (EBookViewListener *listener)
-{
- /* nothing needed here */
-}
-
/**
* 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;
}
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;
}