[gnome-builder] worker: allow asynchronous creation of worker proxy
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] worker: allow asynchronous creation of worker proxy
- Date: Fri, 30 Oct 2015 21:16:35 +0000 (UTC)
commit 4f458e337f9ebc4d4bd492f96256b30980a24ff3
Author: Christian Hergert <chergert redhat com>
Date: Tue Oct 20 00:04:06 2015 -0700
worker: allow asynchronous creation of worker proxy
This allows the proxy to be requeste before the client process has
completed starting up and connected back to the UI process.
libide/ide-worker-manager.c | 103 +++++++++++++++++++++--------
libide/ide-worker-manager.h | 13 +++-
libide/ide-worker-process.c | 151 ++++++++++++++++++++++++++++++-------------
libide/ide-worker-process.h | 29 +++++---
libide/ide-worker.c | 8 ++-
libide/ide-worker.h | 18 +++--
6 files changed, 223 insertions(+), 99 deletions(-)
---
diff --git a/libide/ide-worker-manager.c b/libide/ide-worker-manager.c
index 12beda0..1076b99 100644
--- a/libide/ide-worker-manager.c
+++ b/libide/ide-worker-manager.c
@@ -34,11 +34,9 @@ struct _IdeWorkerManager
{
GObject parent_instance;
- GMutex mutex;
-
gchar *argv0;
- GHashTable *workers_by_plugin_name;
GDBusServer *dbus_server;
+ GHashTable *plugin_name_to_worker;
};
G_DEFINE_TYPE (IdeWorkerManager, ide_worker_manager, G_TYPE_OBJECT)
@@ -88,9 +86,7 @@ ide_worker_manager_new_connection_cb (IdeWorkerManager *self,
if ((credentials == NULL) || !g_credentials_get_unix_pid (credentials, NULL))
return FALSE;
- g_mutex_lock (&self->mutex);
-
- g_hash_table_iter_init (&iter, self->workers_by_plugin_name);
+ g_hash_table_iter_init (&iter, self->plugin_name_to_worker);
while (g_hash_table_iter_next (&iter, &key, &value))
{
@@ -103,8 +99,6 @@ ide_worker_manager_new_connection_cb (IdeWorkerManager *self,
}
}
- g_mutex_unlock (&self->mutex);
-
return handled;
}
@@ -174,7 +168,8 @@ ide_worker_manager_finalize (GObject *object)
{
IdeWorkerManager *self = (IdeWorkerManager *)object;
- g_clear_pointer (&self->workers_by_plugin_name, g_hash_table_unref);
+ g_clear_pointer (&self->plugin_name_to_worker, g_hash_table_unref);
+ g_clear_pointer (&self->argv0, g_free);
g_clear_object (&self->dbus_server);
G_OBJECT_CLASS (ide_worker_manager_parent_class)->finalize (object);
@@ -225,42 +220,92 @@ ide_worker_manager_init (IdeWorkerManager *self)
{
EGG_COUNTER_INC (instances);
- g_mutex_init (&self->mutex);
-
self->argv0 = g_strdup ("gnome-builder");
- self->workers_by_plugin_name =
+ self->plugin_name_to_worker =
g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
ide_worker_manager_force_exit_worker);
}
-GDBusProxy *
-ide_worker_manager_get_worker (IdeWorkerManager *self,
- const gchar *plugin_name,
- GError **error)
+static IdeWorkerProcess *
+ide_worker_manager_get_worker_process (IdeWorkerManager *self,
+ const gchar *plugin_name)
{
- IdeWorkerProcess *worker;
-
- g_return_val_if_fail (IDE_IS_WORKER_MANAGER (self), NULL);
- g_return_val_if_fail (plugin_name != NULL, NULL);
+ IdeWorkerProcess *worker_process;
- g_mutex_lock (&self->mutex);
+ g_assert (IDE_IS_WORKER_MANAGER (self));
+ g_assert (plugin_name != NULL);
- worker = g_hash_table_lookup (self->workers_by_plugin_name, plugin_name);
+ worker_process = g_hash_table_lookup (self->plugin_name_to_worker, plugin_name);
- if (worker == NULL)
+ if (worker_process == NULL)
{
- worker = ide_worker_process_new (self->argv0, plugin_name,
- g_dbus_server_get_client_address (self->dbus_server));
- g_hash_table_insert (self->workers_by_plugin_name, g_strdup (plugin_name), worker);
- ide_worker_process_run (worker);
+ worker_process = ide_worker_process_new (self->argv0,
+ plugin_name,
+ g_dbus_server_get_client_address (self->dbus_server));
+ g_hash_table_insert (self->plugin_name_to_worker, g_strdup (plugin_name), worker_process);
+ ide_worker_process_run (worker_process);
}
- g_mutex_unlock (&self->mutex);
+ return worker_process;
+}
+
+static void
+ide_worker_manager_get_worker_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeWorkerProcess *worker_process = (IdeWorkerProcess *)object;
+ g_autoptr(GTask) task = user_data;
+ GDBusProxy *proxy;
+ GError *error = NULL;
+
+ g_assert (IDE_IS_WORKER_PROCESS (worker_process));
+ g_assert (G_IS_TASK (task));
+
+ proxy = ide_worker_process_get_proxy_finish (worker_process, result, &error);
+
+ if (proxy == NULL)
+ g_task_return_error (task, error);
+ else
+ g_task_return_pointer (task, proxy, g_object_unref);
+}
+
+void
+ide_worker_manager_get_worker_async (IdeWorkerManager *self,
+ const gchar *plugin_name,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ IdeWorkerProcess *worker_process;
+ GTask *task;
+
+ g_return_if_fail (IDE_IS_WORKER_MANAGER (self));
+ g_return_if_fail (plugin_name != NULL);
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ worker_process = ide_worker_manager_get_worker_process (self, plugin_name);
+ ide_worker_process_get_proxy_async (worker_process,
+ cancellable,
+ ide_worker_manager_get_worker_cb,
+ task);
+}
+
+GDBusProxy *
+ide_worker_manager_get_worker_finish (IdeWorkerManager *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ GTask *task = (GTask *)result;
+
+ g_return_val_if_fail (IDE_IS_WORKER_MANAGER (self), NULL);
+ g_return_val_if_fail (G_IS_TASK (task), NULL);
- return ide_worker_process_create_proxy (worker, error);
+ return g_task_propagate_pointer (task, error);
}
IdeWorkerManager *
diff --git a/libide/ide-worker-manager.h b/libide/ide-worker-manager.h
index 3ad9faa..cd56aad 100644
--- a/libide/ide-worker-manager.h
+++ b/libide/ide-worker-manager.h
@@ -27,10 +27,15 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (IdeWorkerManager, ide_worker_manager, IDE, WORKER_MANAGER, GObject)
-IdeWorkerManager *ide_worker_manager_new (const gchar *argv0);
-GDBusProxy *ide_worker_manager_get_worker (IdeWorkerManager *self,
- const gchar *plugin_name,
- GError **error);
+IdeWorkerManager *ide_worker_manager_new (const gchar *argv0);
+void ide_worker_manager_get_worker_async (IdeWorkerManager *self,
+ const gchar *plugin_name,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GDBusProxy *ide_worker_manager_get_worker_finish (IdeWorkerManager *self,
+ GAsyncResult *result,
+ GError **error);
G_END_DECLS
diff --git a/libide/ide-worker-process.c b/libide/ide-worker-process.c
index 780443a..4f7322b 100644
--- a/libide/ide-worker-process.c
+++ b/libide/ide-worker-process.c
@@ -35,12 +35,12 @@ struct _IdeWorkerProcess
gchar *plugin_name;
GSubprocess *subprocess;
GDBusConnection *connection;
+ GPtrArray *tasks;
+ IdeWorker *worker;
guint quit : 1;
};
-static void ide_worker_process_respawn (IdeWorkerProcess *self);
-
G_DEFINE_TYPE (IdeWorkerProcess, ide_worker_process, G_TYPE_OBJECT)
EGG_DEFINE_COUNTER (instances, "IdeWorkerProcess", "Instances", "Number of IdeWorkerProcess instances")
@@ -55,6 +55,8 @@ enum {
static GParamSpec *gParamSpecs [LAST_PROP];
+static void ide_worker_process_respawn (IdeWorkerProcess *self);
+
IdeWorkerProcess *
ide_worker_process_new (const gchar *argv0,
const gchar *plugin_name,
@@ -137,6 +139,22 @@ ide_worker_process_respawn (IdeWorkerProcess *self)
ide_worker_process_wait_check_cb,
g_object_ref (self));
+ if (self->worker == NULL)
+ {
+ PeasEngine *engine;
+ PeasExtension *exten;
+ PeasPluginInfo *plugin_info;
+
+ engine = peas_engine_get_default ();
+ plugin_info = peas_engine_get_plugin_info (engine, self->plugin_name);
+
+ if (plugin_info != NULL)
+ {
+ exten = peas_engine_create_extension (engine, plugin_info, IDE_TYPE_WORKER, NULL);
+ self->worker = IDE_WORKER (exten);
+ }
+ }
+
IDE_EXIT;
}
@@ -187,8 +205,10 @@ ide_worker_process_finalize (GObject *object)
g_clear_pointer (&self->argv0, g_free);
g_clear_pointer (&self->plugin_name, g_free);
g_clear_pointer (&self->dbus_address, g_free);
+ g_clear_pointer (&self->tasks, g_ptr_array_unref);
g_clear_object (&self->connection);
g_clear_object (&self->subprocess);
+ g_clear_object (&self->worker);
G_OBJECT_CLASS (ide_worker_process_parent_class)->finalize (object);
@@ -289,47 +309,6 @@ ide_worker_process_init (IdeWorkerProcess *self)
EGG_COUNTER_INC (instances);
}
-gpointer
-ide_worker_process_create_proxy (IdeWorkerProcess *self,
- GError **error)
-{
- PeasEngine *engine;
- PeasPluginInfo *plugin_info;
- PeasExtension *exten;
- GDBusProxy *proxy;
-
- g_assert (IDE_IS_WORKER_PROCESS (self));
- g_assert (self->plugin_name != NULL);
-
- engine = peas_engine_get_default ();
- plugin_info = peas_engine_get_plugin_info (engine, self->plugin_name);
-
- if (plugin_info == NULL)
- {
- g_set_error (error,
- G_IO_ERROR,
- G_IO_ERROR_PROXY_FAILED,
- "The plugin named \"%s\" could not be found.",
- self->plugin_name);
- return NULL;
- }
-
- if (self->connection == NULL)
- {
- g_set_error (error,
- G_IO_ERROR,
- G_IO_ERROR_PROXY_FAILED,
- "No connection has been established with the worker process");
- return NULL;
- }
-
- exten = peas_engine_create_extension (engine, plugin_info, IDE_TYPE_WORKER, NULL);
- proxy = ide_worker_create_proxy (IDE_WORKER (exten), self->connection);
- g_clear_object (&exten);
-
- return proxy;
-}
-
gboolean
ide_worker_process_matches_credentials (IdeWorkerProcess *self,
GCredentials *credentials)
@@ -353,6 +332,36 @@ ide_worker_process_matches_credentials (IdeWorkerProcess *self,
return FALSE;
}
+static void
+ide_worker_process_create_proxy_for_task (IdeWorkerProcess *self,
+ GTask *task)
+{
+ GDBusProxy *proxy;
+ GError *error = NULL;
+
+ g_assert (IDE_IS_WORKER_PROCESS (self));
+ g_assert (G_IS_TASK (task));
+
+ if (self->worker == NULL)
+ {
+ g_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_PROXY_FAILED,
+ "Failed to create IdeWorker instance.");
+ return;
+ }
+
+ proxy = ide_worker_create_proxy (self->worker, self->connection, &error);
+
+ if (proxy == NULL)
+ {
+ g_task_return_error (task, error);
+ return;
+ }
+
+ g_task_return_pointer (task, proxy, g_object_unref);
+}
+
void
ide_worker_process_set_connection (IdeWorkerProcess *self,
GDBusConnection *connection)
@@ -360,5 +369,59 @@ ide_worker_process_set_connection (IdeWorkerProcess *self,
g_return_if_fail (IDE_IS_WORKER_PROCESS (self));
g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
- g_set_object (&self->connection, connection);
+ if (g_set_object (&self->connection, connection))
+ {
+ if (self->tasks != NULL)
+ {
+ g_autoptr(GPtrArray) ar = NULL;
+ guint i;
+
+ ar = self->tasks;
+ self->tasks = NULL;
+
+ for (i = 0; i < ar->len; i++)
+ {
+ GTask *task = g_ptr_array_index (ar, i);
+ ide_worker_process_create_proxy_for_task (self, task);
+ }
+ }
+ }
+}
+
+void
+ide_worker_process_get_proxy_async (IdeWorkerProcess *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (IDE_IS_WORKER_PROCESS (self));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = g_task_new (self, cancellable, callback, user_data);
+
+ if (self->connection != NULL)
+ {
+ ide_worker_process_create_proxy_for_task (self, task);
+ return;
+ }
+
+ if (self->tasks == NULL)
+ self->tasks = g_ptr_array_new_with_free_func (g_object_unref);
+
+ g_ptr_array_add (self->tasks, g_object_ref (task));
+}
+
+GDBusProxy *
+ide_worker_process_get_proxy_finish (IdeWorkerProcess *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ GTask *task = (GTask *)result;
+
+ g_return_val_if_fail (IDE_IS_WORKER_PROCESS (self), NULL);
+ g_return_val_if_fail (G_IS_TASK (task), NULL);
+
+ return g_task_propagate_pointer (task, error);
}
diff --git a/libide/ide-worker-process.h b/libide/ide-worker-process.h
index 73e3361..4133874 100644
--- a/libide/ide-worker-process.h
+++ b/libide/ide-worker-process.h
@@ -27,17 +27,24 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (IdeWorkerProcess, ide_worker_process, IDE, WORKER_PROCESS, GObject)
-IdeWorkerProcess *ide_worker_process_new (const gchar *argv0,
- const gchar *type,
- const gchar *dbus_address);
-void ide_worker_process_run (IdeWorkerProcess *self);
-void ide_worker_process_quit (IdeWorkerProcess *self);
-gpointer ide_worker_process_create_proxy (IdeWorkerProcess *self,
- GError **error);
-gboolean ide_worker_process_matches_credentials (IdeWorkerProcess *self,
- GCredentials *credentials);
-void ide_worker_process_set_connection (IdeWorkerProcess *self,
- GDBusConnection *connection);
+IdeWorkerProcess *ide_worker_process_new (const gchar *argv0,
+ const gchar *type,
+ const gchar *dbus_address);
+void ide_worker_process_run (IdeWorkerProcess *self);
+void ide_worker_process_quit (IdeWorkerProcess *self);
+gpointer ide_worker_process_create_proxy (IdeWorkerProcess *self,
+ GError **error);
+gboolean ide_worker_process_matches_credentials (IdeWorkerProcess *self,
+ GCredentials *credentials);
+void ide_worker_process_set_connection (IdeWorkerProcess *self,
+ GDBusConnection *connection);
+void ide_worker_process_get_proxy_async (IdeWorkerProcess *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GDBusProxy *ide_worker_process_get_proxy_finish (IdeWorkerProcess *self,
+ GAsyncResult *result,
+ GError **error);
G_END_DECLS
diff --git a/libide/ide-worker.c b/libide/ide-worker.c
index ccf456a..9c1be12 100644
--- a/libide/ide-worker.c
+++ b/libide/ide-worker.c
@@ -41,6 +41,7 @@ ide_worker_register_service (IdeWorker *self,
* ide_worker_create_proxy:
* @self: An #IdeWorker.
* @connection: A #GDBusConnection connected to the worker process.
+ * @error: (allow-none): a location for a #GError, or %NULL.
*
* Creates a new proxy to be connected to the subprocess peer on the other
* end of @connection.
@@ -48,11 +49,12 @@ ide_worker_register_service (IdeWorker *self,
* Returns: (transfer full): A #GDBusProxy or %NULL.
*/
GDBusProxy *
-ide_worker_create_proxy (IdeWorker *self,
- GDBusConnection *connection)
+ide_worker_create_proxy (IdeWorker *self,
+ GDBusConnection *connection,
+ GError **error)
{
g_return_val_if_fail (IDE_IS_WORKER (self), NULL);
g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
- return IDE_WORKER_GET_IFACE (self)->create_proxy (self, connection);
+ return IDE_WORKER_GET_IFACE (self)->create_proxy (self, connection, error);
}
diff --git a/libide/ide-worker.h b/libide/ide-worker.h
index d44eecf..fd7278e 100644
--- a/libide/ide-worker.h
+++ b/libide/ide-worker.h
@@ -31,16 +31,18 @@ struct _IdeWorkerInterface
{
GTypeInterface parent;
- GDBusProxy *(*create_proxy) (IdeWorker *self,
- GDBusConnection *connection);
- void (*register_service) (IdeWorker *self,
- GDBusConnection *connection);
+ GDBusProxy *(*create_proxy) (IdeWorker *self,
+ GDBusConnection *connection,
+ GError **error);
+ void (*register_service) (IdeWorker *self,
+ GDBusConnection *connection);
};
-GDBusProxy *ide_worker_create_proxy (IdeWorker *self,
- GDBusConnection *connection);
-void ide_worker_register_service (IdeWorker *self,
- GDBusConnection *connection);
+GDBusProxy *ide_worker_create_proxy (IdeWorker *self,
+ GDBusConnection *connection,
+ GError **error);
+void ide_worker_register_service (IdeWorker *self,
+ GDBusConnection *connection);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]