[gnome-builder] code-index: cleanup mutex usage and improve thread safety
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] code-index: cleanup mutex usage and improve thread safety
- Date: Thu, 18 Jan 2018 14:44:02 +0000 (UTC)
commit b45526b79a1eabcfd4f51831a7321157705af704
Author: Christian Hergert <chergert redhat com>
Date: Wed Jan 17 03:05:45 2018 -0800
code-index: cleanup mutex usage and improve thread safety
There is still plenty more to do, but this is a good check-in point
before fixing up things more.
src/plugins/code-index/ide-code-index-builder.c | 205 +++++++++++++-----------
1 file changed, 115 insertions(+), 90 deletions(-)
---
diff --git a/src/plugins/code-index/ide-code-index-builder.c b/src/plugins/code-index/ide-code-index-builder.c
index c9d3b6f2d..27fc62434 100644
--- a/src/plugins/code-index/ide-code-index-builder.c
+++ b/src/plugins/code-index/ide-code-index-builder.c
@@ -39,6 +39,7 @@ typedef struct
{
GFile *directory;
GPtrArray *changes;
+ GFile *destination;
guint recursive : 1;
} GetChangesTaskData;
@@ -63,6 +64,7 @@ static void
get_changes_task_data_free (GetChangesTaskData *data)
{
g_clear_object (&data->directory);
+ g_clear_object (&data->destination);
g_clear_pointer (&data->changes, g_ptr_array_unref);
g_slice_free (GetChangesTaskData, data);
}
@@ -105,6 +107,7 @@ ide_code_index_builder_get_all_files (IdeCodeIndexBuilder *self,
GPtrArray *changes)
{
g_autoptr(GPtrArray) all_files = NULL;
+ g_autoptr(GMutexLocker) locker = NULL;
IdeContext *context;
g_assert (IDE_IS_CODE_INDEX_BUILDER (self));
@@ -113,14 +116,15 @@ ide_code_index_builder_get_all_files (IdeCodeIndexBuilder *self,
context = ide_object_get_context (IDE_OBJECT (self));
all_files = g_ptr_array_new_with_free_func (g_object_unref);
+ locker = g_mutex_locker_new (&self->mutex);
+
for (guint i = 0; i < changes->len; i++)
{
const IndexingData *change = g_ptr_array_index (changes, i);
- GPtrArray *dir_files = change->files;
- for (guint j = 0; j < dir_files->len; j++)
+ for (guint j = 0; j < change->files->len; j++)
{
- GFile *gfile = g_ptr_array_index (dir_files, j);
+ GFile *gfile = g_ptr_array_index (change->files, j);
g_autoptr(IdeFile) file = ide_file_new (context, gfile);
if (!g_hash_table_contains (self->build_flags, file))
@@ -462,12 +466,7 @@ ide_code_index_builder_get_changes (IdeCodeIndexBuilder *self,
g_file_enumerator_close (enumerator, cancellable, NULL);
if ((files->len != 0) &&
- !ide_code_index_index_load_if_nmod (self->index,
- destination,
- files,
- max_mod_time,
- cancellable,
- NULL))
+ !ide_code_index_index_load_if_nmod (self->index, destination, files, max_mod_time, cancellable, NULL))
{
IndexingData *idata;
@@ -499,38 +498,32 @@ ide_code_index_builder_get_changes (IdeCodeIndexBuilder *self,
static void
ide_code_index_builder_get_changes_worker (GTask *task,
gpointer source_object,
- gpointer task_data_ptr,
+ gpointer task_data,
GCancellable *cancellable)
{
IdeCodeIndexBuilder *self = source_object;
- IdeContext *context;
- GFile *workdir;
- g_autoptr(GFile) destination = NULL;
- g_autofree gchar *relative_path = NULL;
- GetChangesTaskData *data = task_data_ptr;
+ GetChangesTaskData *data = task_data;
g_assert (IDE_IS_CODE_INDEX_BUILDER (self));
g_assert (G_IS_TASK (task));
g_assert (data != NULL);
-
- context = ide_object_get_context (IDE_OBJECT (self));
- workdir = ide_vcs_get_working_directory (ide_context_get_vcs (context));
- relative_path = g_file_get_relative_path (workdir, data->directory);
- destination = ide_context_cache_file (context, "code-index", relative_path, NULL);
-
- data->changes = g_ptr_array_new_with_free_func ((GDestroyNotify)indexing_data_free);
+ g_assert (G_IS_FILE (data->directory));
+ g_assert (G_IS_FILE (data->destination));
+ g_assert (data->changes != NULL);
if (g_task_return_error_if_cancelled (task))
return;
ide_code_index_builder_get_changes (self,
data->directory,
- destination,
+ data->destination,
data->recursive,
data->changes,
cancellable);
- g_task_return_pointer (task, g_ptr_array_ref (data->changes), (GDestroyNotify)g_ptr_array_unref);
+ g_task_return_pointer (task,
+ g_steal_pointer (&data->changes),
+ (GDestroyNotify)g_ptr_array_unref);
}
static void
@@ -542,24 +535,31 @@ ide_code_index_builder_get_changes_async (IdeCodeIndexBuilder *self,
gpointer user_data)
{
g_autoptr(GTask) task = NULL;
+ g_autofree gchar *relative_path = NULL;
+ g_autoptr(GFile) destination = NULL;
GetChangesTaskData *data;
+ IdeContext *context;
+ GFile *workdir;
g_assert (IDE_IS_CODE_INDEX_BUILDER (self));
g_assert (G_IS_FILE (directory));
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
- g_debug ("Getting file changes");
+ context = ide_object_get_context (IDE_OBJECT (self));
+ workdir = ide_vcs_get_working_directory (ide_context_get_vcs (context));
+ relative_path = g_file_get_relative_path (workdir, directory);
+ destination = ide_context_cache_file (context, "code-index", relative_path, NULL);
data = g_slice_new0 (GetChangesTaskData);
-
data->directory = g_object_ref (directory);
- data->recursive = recursive;
+ data->destination = g_steal_pointer (&destination);
+ data->changes = g_ptr_array_new_with_free_func ((GDestroyNotify)indexing_data_free);
+ data->recursive = !!recursive;
task = g_task_new (self, cancellable, callback, user_data);
-
- g_task_set_task_data (task, data, (GDestroyNotify)get_changes_task_data_free);
- g_task_set_priority (task, G_PRIORITY_LOW);
g_task_set_source_tag (task, ide_code_index_builder_get_changes_async);
+ g_task_set_priority (task, G_PRIORITY_LOW);
+ g_task_set_task_data (task, data, (GDestroyNotify)get_changes_task_data_free);
ide_thread_pool_push_task (IDE_THREAD_POOL_INDEXER,
task,
@@ -567,35 +567,34 @@ ide_code_index_builder_get_changes_async (IdeCodeIndexBuilder *self,
}
static GPtrArray *
-ide_code_index_builder_get_changes_finish (IdeCodeIndexBuilder *self,
- GAsyncResult *result,
- GError **error)
+ide_code_index_builder_get_changes_finish (IdeCodeIndexBuilder *self,
+ GAsyncResult *result,
+ GError **error)
{
- GTask *task = (GTask *)result;
-
- g_assert (G_IS_TASK (task));
+ g_assert (IDE_IS_CODE_INDEX_BUILDER (self));
+ g_assert (G_IS_TASK (result));
- return g_task_propagate_pointer (task, error);
+ return g_task_propagate_pointer (G_TASK (result), error);
}
- /* Main task: get changes, retrive build flags and index directories */
-
static void
ide_code_index_builder_build_cb3 (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
IdeCodeIndexBuilder *self = (IdeCodeIndexBuilder *)object;
- g_autoptr(GTask) main_task = user_data;
+ g_autoptr(GTask) task = user_data;
g_autoptr(GError) error = NULL;
+ g_assert (IDE_IS_MAIN_THREAD ());
g_assert (IDE_IS_CODE_INDEX_BUILDER (self));
- g_assert (G_IS_TASK (main_task));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (G_IS_TASK (task));
if (ide_code_index_builder_index_directories_finish (self, result, &error))
- g_task_return_boolean (main_task, TRUE);
+ g_task_return_boolean (task, TRUE);
else
- g_task_return_error (main_task, g_steal_pointer (&error));
+ g_task_return_error (task, g_steal_pointer (&error));
}
static void
@@ -605,44 +604,50 @@ ide_code_index_builder_build_cb2 (GObject *object,
{
IdeBuildSystem *build_system = (IdeBuildSystem *)object;
g_autoptr(GHashTable) build_flags = NULL;
- g_autoptr(GTask) main_task = user_data;
+ g_autoptr(GTask) task = user_data;
g_autoptr(GError) error = NULL;
+ g_autoptr(GMutexLocker) locker = NULL;
IdeCodeIndexBuilder *self;
GCancellable *cancellable;
GPtrArray *changes;
- IdeFile *key;
- gchar **value;
GHashTableIter iter;
+ gpointer k, v;
+ g_assert (IDE_IS_MAIN_THREAD ());
g_assert (IDE_IS_BUILD_SYSTEM (build_system));
g_assert (G_IS_ASYNC_RESULT (result));
- g_assert (G_IS_TASK (main_task));
+ g_assert (G_IS_TASK (task));
build_flags = ide_build_system_get_build_flags_for_files_finish (build_system, result, &error);
if (build_flags == NULL)
{
- g_message ("Failed to fetch build flags %s", error->message);
- g_task_return_error (main_task, g_steal_pointer (&error));
+ g_task_return_error (task, g_steal_pointer (&error));
return;
}
- if (g_task_return_error_if_cancelled (main_task))
+ if (g_task_return_error_if_cancelled (task))
return;
- self = g_task_get_source_object (main_task);
+ self = g_task_get_source_object (task);
g_assert (IDE_IS_CODE_INDEX_BUILDER (self));
- cancellable = g_task_get_cancellable (main_task);
+ cancellable = g_task_get_cancellable (task);
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
- changes = g_task_get_task_data (main_task);
+ changes = g_task_get_task_data (task);
g_assert (changes != NULL);
- /* Update self->build_flags hash table with new flags */
+ locker = g_mutex_locker_new (&self->mutex);
+
g_hash_table_iter_init (&iter, build_flags);
- while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value))
+ while (g_hash_table_iter_next (&iter, &k, &v))
{
+ IdeFile *key = k;
+ gchar **value = v;
+
+ g_assert (IDE_IS_FILE (key));
+
g_hash_table_iter_steal (&iter);
g_hash_table_insert (self->build_flags, key, value);
}
@@ -651,7 +656,7 @@ ide_code_index_builder_build_cb2 (GObject *object,
changes,
cancellable,
ide_code_index_builder_build_cb3,
- g_steal_pointer (&main_task));
+ g_steal_pointer (&task));
}
static void
@@ -660,55 +665,75 @@ ide_code_index_builder_build_cb (GObject *object,
gpointer user_data)
{
IdeCodeIndexBuilder *self = (IdeCodeIndexBuilder *)object;
- g_autoptr(GTask) main_task = user_data;
+ g_autoptr(GTask) task = user_data;
g_autoptr(GError) error = NULL;
g_autoptr(GPtrArray) changes = NULL;
- IdeBuildSystem *build_system;
- IdeContext *context;
g_autoptr(GPtrArray) files = NULL;
+ IdeBuildSystem *build_system;
GCancellable *cancellable;
+ IdeContext *context;
+ g_assert (IDE_IS_MAIN_THREAD ());
g_assert (IDE_IS_CODE_INDEX_BUILDER (self));
- g_assert (G_IS_TASK (main_task));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (G_IS_TASK (task));
- if (NULL == (changes = ide_code_index_builder_get_changes_finish (self, result, &error)))
- {
- g_message ("Failed to get file changes, %s", error->message);
- g_task_return_error (main_task, g_steal_pointer (&error));
- return;
- }
- else if (changes->len == 0)
+ changes = ide_code_index_builder_get_changes_finish (self, result, &error);
+
+ if (changes == NULL)
{
- g_debug ("No changes are there, completing task");
- g_task_return_boolean (main_task, TRUE);
+ g_task_return_error (task, g_steal_pointer (&error));
return;
}
- else if (g_task_return_error_if_cancelled (main_task))
+
+ if (changes->len == 0)
{
+ g_task_return_boolean (task, TRUE);
return;
}
+ if (g_task_return_error_if_cancelled (task))
+ return;
+
context = ide_object_get_context (IDE_OBJECT (self));
+ g_assert (IDE_IS_CONTEXT (context));
+
build_system = ide_context_get_build_system (context);
+ g_assert (IDE_IS_BUILD_SYSTEM (build_system));
+
files = ide_code_index_builder_get_all_files (self, changes);
- cancellable = g_task_get_cancellable (main_task);
+ g_assert (files != NULL);
+
+ cancellable = g_task_get_cancellable (task);
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
g_message ("Getting build flags for %d directories", changes->len);
- g_task_set_task_data (main_task,
+ g_task_set_task_data (task,
g_steal_pointer (&changes),
(GDestroyNotify)g_ptr_array_unref);
- /* TODO: add time out to finish task. This will help of build system fails to get flags */
-
ide_build_system_get_build_flags_for_files_async (build_system,
files,
cancellable,
ide_code_index_builder_build_cb2,
- g_steal_pointer (&main_task));
+ g_steal_pointer (&task));
}
-/* This function will index a directory (recursively) and load that index */
+/**
+ * ide_code_index_builder_build_async:
+ * @self: a #IdeCodeIndexBuilder
+ * @directory: a #GFile for the directory to load
+ * @recursive: if descendants should be recursed into and loaded
+ * @cancellable: (nullable): a #GCancellable or %NULL
+ * @callback: a callback to execute upon completion
+ * @user_data: closure data for @callback
+ *
+ * This function will index a directory, potentially recursively, and then
+ * map those indexes into memory.
+ *
+ * Thread safety: this function may only be called from the main thread.
+ */
void
ide_code_index_builder_build_async (IdeCodeIndexBuilder *self,
GFile *directory,
@@ -717,27 +742,25 @@ ide_code_index_builder_build_async (IdeCodeIndexBuilder *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
- g_autoptr(GTask) main_task = NULL;
+ g_autoptr(GTask) task = NULL;
+ g_return_if_fail (IDE_IS_MAIN_THREAD ());
g_return_if_fail (IDE_IS_CODE_INDEX_BUILDER (self));
g_return_if_fail (G_IS_FILE (directory));
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
- g_debug ("Started building index");
-
- main_task = g_task_new (self, cancellable, callback, user_data);
- g_task_set_priority (main_task, G_PRIORITY_LOW);
- g_task_set_source_tag (main_task, ide_code_index_builder_build_async);
+ g_debug ("Started building code index");
- if (g_task_return_error_if_cancelled (main_task))
- return;
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_priority (task, G_PRIORITY_LOW);
+ g_task_set_source_tag (task, ide_code_index_builder_build_async);
ide_code_index_builder_get_changes_async (self,
directory,
recursive,
cancellable,
ide_code_index_builder_build_cb,
- g_steal_pointer (&main_task));
+ g_steal_pointer (&task));
}
gboolean
@@ -745,11 +768,11 @@ ide_code_index_builder_build_finish (IdeCodeIndexBuilder *self,
GAsyncResult *result,
GError **error)
{
- GTask *main_task = (GTask *)result;
+ g_return_val_if_fail (IDE_IS_MAIN_THREAD (), FALSE);
+ g_return_val_if_fail (IDE_IS_CODE_INDEX_BUILDER (self), FALSE);
+ g_return_val_if_fail (G_IS_TASK (result), FALSE);
- g_return_val_if_fail (G_IS_TASK (main_task), FALSE);
-
- return g_task_propagate_boolean (main_task, error);
+ return g_task_propagate_boolean (G_TASK (result), error);
}
static void
@@ -757,10 +780,10 @@ ide_code_index_builder_finalize (GObject *object)
{
IdeCodeIndexBuilder *self = (IdeCodeIndexBuilder *)object;
+ g_mutex_clear (&self->mutex);
g_clear_object (&self->index);
g_clear_object (&self->service);
g_clear_pointer (&self->build_flags, g_hash_table_unref);
- g_mutex_clear (&self->mutex);
G_OBJECT_CLASS(ide_code_index_builder_parent_class)->finalize (object);
}
@@ -873,5 +896,7 @@ ide_code_index_builder_drop_caches (IdeCodeIndexBuilder *self)
* around forever.
*/
+ g_mutex_lock (&self->mutex);
g_hash_table_remove_all (self->build_flags);
+ g_mutex_unlock (&self->mutex);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]