[evolution-data-server] Bug 719583 - Get a ESourceRegistry singleton
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Bug 719583 - Get a ESourceRegistry singleton
- Date: Sun, 2 Feb 2014 16:35:16 +0000 (UTC)
commit b5477d56d22a3fa8549a4ec13fdf5b2c6a6854c4
Author: Xavier Claessens <xclaesse gmail com>
Date: Sun Feb 2 09:53:29 2014 -0500
Bug 719583 - Get a ESourceRegistry singleton
libedataserver/e-source-registry.c | 131 +++++++++++++++++++++++++++++-------
1 files changed, 105 insertions(+), 26 deletions(-)
---
diff --git a/libedataserver/e-source-registry.c b/libedataserver/e-source-registry.c
index e7c52e8..51747b1 100644
--- a/libedataserver/e-source-registry.c
+++ b/libedataserver/e-source-registry.c
@@ -111,6 +111,10 @@ struct _ESourceRegistryPrivate {
GMutex sources_lock;
GSettings *settings;
+
+ gboolean initialized;
+ GError *init_error;
+ GMutex init_lock;
};
struct _AsyncContext {
@@ -288,6 +292,27 @@ thread_closure_free (ThreadClosure *closure)
g_slice_free (ThreadClosure, closure);
}
+G_LOCK_DEFINE_STATIC (singleton_lock);
+static GWeakRef singleton;
+
+static ESourceRegistry *
+source_registry_dup_uninitialized_singleton (void)
+{
+ ESourceRegistry *registry;
+
+ G_LOCK (singleton_lock);
+
+ registry = g_weak_ref_get (&singleton);
+ if (registry == NULL) {
+ registry = g_object_new (E_TYPE_SOURCE_REGISTRY, NULL);
+ g_weak_ref_set (&singleton, registry);
+ }
+
+ G_UNLOCK (singleton_lock);
+
+ return registry;
+}
+
static gchar *
source_registry_dbus_object_dup_uid (GDBusObject *dbus_object)
{
@@ -1283,6 +1308,9 @@ source_registry_finalize (GObject *object)
g_hash_table_destroy (priv->sources);
g_mutex_clear (&priv->sources_lock);
+ g_clear_error (&priv->init_error);
+ g_mutex_clear (&priv->init_lock);
+
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (e_source_registry_parent_class)->finalize (object);
}
@@ -1298,6 +1326,11 @@ source_registry_initable_init (GInitable *initable,
registry = E_SOURCE_REGISTRY (initable);
+ g_mutex_lock (®istry->priv->init_lock);
+
+ if (registry->priv->initialized)
+ goto exit;
+
closure = g_slice_new0 (ThreadClosure);
closure->registry = registry; /* do not reference */
closure->main_context = g_main_context_new ();
@@ -1315,9 +1348,6 @@ source_registry_initable_init (GInitable *initable,
source_registry_object_manager_thread,
closure);
- if (registry->priv->manager_thread == NULL)
- return FALSE;
-
/* Wait for notification that the manager
* thread's main loop has been started. */
g_mutex_lock (&closure->main_loop_mutex);
@@ -1330,9 +1360,9 @@ source_registry_initable_init (GInitable *initable,
/* Check for error in the manager thread. */
if (closure->error != NULL) {
g_dbus_error_strip_remote_error (closure->error);
- g_propagate_error (error, closure->error);
+ g_propagate_error (®istry->priv->init_error, closure->error);
closure->error = NULL;
- return FALSE;
+ goto exit;
}
/* The registry should now be populated with sources.
@@ -1367,8 +1397,8 @@ source_registry_initable_init (GInitable *initable,
if (local_error != NULL) {
g_dbus_error_strip_remote_error (local_error);
- g_propagate_error (error, local_error);
- return FALSE;
+ g_propagate_error (®istry->priv->init_error, local_error);
+ goto exit;
}
/* Allow authentication prompts for all exported data sources
@@ -1379,6 +1409,21 @@ source_registry_initable_init (GInitable *initable,
e_dbus_source_manager_call_allow_auth_prompt_all_sync (
registry->priv->dbus_source_manager, cancellable, NULL);
+exit:
+ registry->priv->initialized = TRUE;
+ g_mutex_unlock (®istry->priv->init_lock);
+
+ if (registry->priv->init_error != NULL) {
+ GError *init_error_copy;
+
+ /* Return a copy of the same error to
+ * all pending initialization requests. */
+ init_error_copy = g_error_copy (registry->priv->init_error);
+ g_propagate_error (error, init_error_copy);
+
+ return FALSE;
+ }
+
return TRUE;
}
@@ -1625,6 +1670,8 @@ e_source_registry_init (ESourceRegistry *registry)
g_signal_connect (
registry->priv->settings, "changed",
G_CALLBACK (source_registry_settings_changed_cb), registry);
+
+ g_mutex_init (®istry->priv->init_lock);
}
/**
@@ -1636,6 +1683,9 @@ e_source_registry_init (ESourceRegistry *registry)
* If an error occurs in connecting to the D-Bus service, the function sets
* @error and returns %NULL.
*
+ * Since 3.12 a singleton will be returned. No strong reference is kept
+ * internally, so it is the caller's responsibility to keep one.
+ *
* Returns: a new #ESourceRegistry, or %NULL
*
* Since: 3.6
@@ -1644,14 +1694,42 @@ ESourceRegistry *
e_source_registry_new_sync (GCancellable *cancellable,
GError **error)
{
+ ESourceRegistry *registry;
+
/* XXX Work around http://bugzilla.gnome.org/show_bug.cgi?id=683519
* until GObject's type initialization deadlock issue is fixed.
* Apparently only the synchronous instantiation is affected. */
g_type_ensure (G_TYPE_DBUS_CONNECTION);
- return g_initable_new (
- E_TYPE_SOURCE_REGISTRY,
- cancellable, error, NULL);
+ registry = source_registry_dup_uninitialized_singleton ();
+
+ if (!g_initable_init (G_INITABLE (registry), cancellable, error))
+ g_clear_object (®istry);
+
+ return registry;
+}
+
+/* Helper for e_source_registry_new() */
+static void
+source_registry_init_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GTask *task = user_data;
+ GError *local_error = NULL;
+
+ g_async_initable_init_finish (
+ G_ASYNC_INITABLE (source_object), result, &local_error);
+
+ if (local_error == NULL) {
+ g_task_return_pointer (
+ task, g_object_ref (source_object),
+ (GDestroyNotify) g_object_unref);
+ } else {
+ g_task_return_error (task, local_error);
+ }
+
+ g_object_unref (task);
}
/**
@@ -1667,6 +1745,9 @@ e_source_registry_new_sync (GCancellable *cancellable,
* When the operation is finished, @callback will be called. You can then
* call e_source_registry_new_finish() to get the result of the operation.
*
+ * Since 3.12 a singleton will be returned. No strong reference is kept
+ * internally, so it is the caller's responsibility to keep one.
+ *
* Since: 3.6
**/
void
@@ -1674,10 +1755,19 @@ e_source_registry_new (GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
- g_async_initable_new_async (
- E_TYPE_SOURCE_REGISTRY,
+ ESourceRegistry *registry;
+ GTask *task;
+
+ task = g_task_new (NULL, cancellable, callback, user_data);
+
+ registry = source_registry_dup_uninitialized_singleton ();
+
+ g_async_initable_init_async (
+ G_ASYNC_INITABLE (registry),
G_PRIORITY_DEFAULT, cancellable,
- callback, user_data, NULL);
+ source_registry_init_cb, task);
+
+ g_object_unref (registry);
}
/**
@@ -1697,20 +1787,9 @@ ESourceRegistry *
e_source_registry_new_finish (GAsyncResult *result,
GError **error)
{
- GObject *source_object;
- GObject *object;
-
- g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
-
- source_object = g_async_result_get_source_object (result);
- g_return_val_if_fail (source_object != NULL, NULL);
-
- object = g_async_initable_new_finish (
- G_ASYNC_INITABLE (source_object), result, error);
-
- g_object_unref (source_object);
+ g_return_val_if_fail (g_task_is_valid (result, NULL), NULL);
- return (object != NULL) ? E_SOURCE_REGISTRY (object) : NULL;
+ return g_task_propagate_pointer (G_TASK (result), error);
}
/* Helper for e_source_registry_authenticate() */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]