[gnome-builder] codeindex: make code index service pausable
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] codeindex: make code index service pausable
- Date: Tue, 5 Sep 2017 08:36:49 +0000 (UTC)
commit 45981496d6b85dff73e40958b22e39ce84e986d4
Author: Christian Hergert <chergert redhat com>
Date: Tue Sep 5 01:36:14 2017 -0700
codeindex: make code index service pausable
Background compiling can take up a lot of system resources, so we want
to provide users a way to pause the operation and get some of those CPU
cycles back.
This provides an IdePausable and registers it with the context. The omni
bar can then display the pausable operation in the build popover for
the user to control.
Upon pausing, the current task is cancelled (but work item left on the
queue) and is reprocessed when the operation has been unpaused.
plugins/code-index/ide-code-index-service.c | 149 ++++++++++++++++++++++++--
1 files changed, 137 insertions(+), 12 deletions(-)
---
diff --git a/plugins/code-index/ide-code-index-service.c b/plugins/code-index/ide-code-index-service.c
index 0fa27a6..d54a05d 100644
--- a/plugins/code-index/ide-code-index-service.c
+++ b/plugins/code-index/ide-code-index-service.c
@@ -18,6 +18,7 @@
#define G_LOG_DOMAIN "ide-code-index-service"
+#include <glib/gi18n.h>
#include <libpeas/peas.h>
#include <stdlib.h>
#include <plugins/ide-extension-adapter.h>
@@ -47,6 +48,7 @@ struct _IdeCodeIndexService
GHashTable *code_indexers;
+ IdePausable *pausable;
GCancellable *cancellable;
guint stopped : 1;
@@ -60,12 +62,12 @@ typedef struct
guint recursive : 1;
} BuildData;
-static void build_data_free (BuildData *data);
-static void service_iface_init (IdeServiceInterface *iface);
-static void ide_code_index_service_build (IdeCodeIndexService *self,
- GFile *directory,
- gboolean recursive,
- guint n_trial);
+static void build_data_free (BuildData *data);
+static void service_iface_init (IdeServiceInterface *iface);
+static void ide_code_index_service_build (IdeCodeIndexService *self,
+ GFile *directory,
+ gboolean recursive,
+ guint n_trial);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (BuildData, build_data_free)
G_DEFINE_TYPE_EXTENDED (IdeCodeIndexService, ide_code_index_service, IDE_TYPE_OBJECT, 0,
@@ -88,6 +90,30 @@ build_data_free (BuildData *data)
}
static void
+register_pausable (IdeCodeIndexService *self)
+{
+ IdeContext *context;
+
+ g_assert (IDE_IS_CODE_INDEX_SERVICE (self));
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ if (context != NULL && self->pausable != NULL)
+ ide_context_add_pausable (context, self->pausable);
+}
+
+static void
+unregister_pausable (IdeCodeIndexService *self)
+{
+ IdeContext *context;
+
+ g_assert (IDE_IS_CODE_INDEX_SERVICE (self));
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ if (context != NULL && self->pausable != NULL)
+ ide_context_remove_pausable (context, self->pausable);
+}
+
+static void
ide_code_index_service_build_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
@@ -106,14 +132,27 @@ ide_code_index_service_build_cb (GObject *object,
return;
if (ide_code_index_builder_build_finish (builder, result, &error))
+ g_debug ("Finished building code index");
+ else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to build code index: %s", error->message);
+
+ /*
+ * If we're paused, push this item back on the queue to
+ * be processed when we unpause.
+ */
+ if (ide_pausable_get_paused (self->pausable))
{
- g_debug ("Finished building code index");
+ g_queue_push_head (&self->build_queue, g_steal_pointer (&bdata));
+ return;
}
- else
- {
- g_message ("Failed to build code index, %s, retrying", error->message);
- ide_code_index_service_build (self, bdata->directory, bdata->recursive, bdata->n_trial + 1);
+ if (error != NULL &&
+ !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ ide_code_index_service_build (self,
+ bdata->directory,
+ bdata->recursive,
+ bdata->n_trial + 1);
}
g_clear_object (&self->cancellable);
@@ -135,6 +174,8 @@ ide_code_index_service_build_cb (GObject *object,
ide_code_index_service_build_cb,
g_steal_pointer (&self));
}
+ else
+ unregister_pausable (self);
}
static gboolean
@@ -156,6 +197,8 @@ ide_code_index_serivce_push (BuildData *bdata)
self->cancellable = g_cancellable_new ();
+ register_pausable (self);
+
ide_code_index_builder_build_async (self->builder,
bdata->directory,
bdata->recursive,
@@ -351,7 +394,8 @@ ide_code_index_service_context_loaded (IdeService *service)
g_steal_pointer (&adapter));
}
}
- plugins = plugins->next;
+
+ plugins = plugins->next;
}
self->index = ide_code_index_index_new (context);
@@ -397,6 +441,55 @@ ide_code_index_service_start (IdeService *service)
}
static void
+ide_code_index_service_paused (IdeCodeIndexService *self,
+ IdePausable *pausable)
+{
+ g_assert (IDE_IS_CODE_INDEX_SERVICE (self));
+ g_assert (IDE_IS_PAUSABLE (pausable));
+
+ if (self->stopped)
+ return;
+
+ /*
+ * To pause things, we need to cancel our current task. The completion of
+ * the async task will check for cancelled and leave the build task for
+ * another pass.
+ */
+
+ g_cancellable_cancel (self->cancellable);
+}
+
+static void
+ide_code_index_service_unpaused (IdeCodeIndexService *self,
+ IdePausable *pausable)
+{
+ BuildData *peek;
+
+ g_assert (IDE_IS_CODE_INDEX_SERVICE (self));
+ g_assert (IDE_IS_PAUSABLE (pausable));
+
+ if (self->stopped)
+ return;
+
+ peek = g_queue_peek_head (&self->build_queue);
+
+ if (peek != NULL)
+ {
+ GCancellable *cancellable;
+
+ g_clear_object (&self->cancellable);
+ self->cancellable = cancellable = g_cancellable_new ();
+
+ ide_code_index_builder_build_async (self->builder,
+ peek->directory,
+ peek->recursive,
+ cancellable,
+ ide_code_index_service_build_cb,
+ g_object_ref (self));
+ }
+}
+
+static void
ide_code_index_service_stop (IdeService *service)
{
IdeCodeIndexService *self = (IdeCodeIndexService *)service;
@@ -412,11 +505,26 @@ ide_code_index_service_stop (IdeService *service)
g_queue_clear (&self->build_queue);
g_clear_pointer (&self->build_dirs, g_hash_table_unref);
g_clear_pointer (&self->code_indexers, g_hash_table_unref);
+
+ unregister_pausable (self);
+}
+
+static void
+ide_code_index_service_finalize (GObject *object)
+{
+ IdeCodeIndexService *self = (IdeCodeIndexService *)object;
+
+ g_clear_object (&self->pausable);
+
+ G_OBJECT_CLASS (ide_code_index_service_parent_class)->finalize (object);
}
static void
ide_code_index_service_class_init (IdeCodeIndexServiceClass *klass)
{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = ide_code_index_service_finalize;
}
static void
@@ -430,6 +538,23 @@ service_iface_init (IdeServiceInterface *iface)
static void
ide_code_index_service_init (IdeCodeIndexService *self)
{
+ self->pausable = g_object_new (IDE_TYPE_PAUSABLE,
+ "paused", FALSE,
+ "title", _("Indexing Source Code"),
+ "subtitle", _("Search, diagnostics and autocompletion may be limited until
complete."),
+ NULL);
+
+ g_signal_connect_object (self->pausable,
+ "paused",
+ G_CALLBACK (ide_code_index_service_paused),
+ self,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->pausable,
+ "unpaused",
+ G_CALLBACK (ide_code_index_service_unpaused),
+ self,
+ G_CONNECT_SWAPPED);
}
IdeCodeIndexIndex *
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]