[gnome-builder/wip/libide: 153/237] libide: add rw lock functions to IdeProject



commit 2ba3558849188711b79830c0f71d96ed8c0faabd
Author: Christian Hergert <christian hergert me>
Date:   Thu Feb 12 16:08:38 2015 -0800

    libide: add rw lock functions to IdeProject

 libide/clang/ide-clang-translation-unit.c |   16 ++++++
 libide/git/ide-git-vcs.c                  |   10 +++-
 libide/ide-project.c                      |   72 +++++++++++++++++++++++++----
 libide/ide-project.h                      |    4 ++
 src/tree/gb-project-tree-builder.c        |    4 ++
 tools/ide-list-diagnostics.c              |    3 +
 tools/ide-list-files.c                    |    2 +
 7 files changed, 99 insertions(+), 12 deletions(-)
---
diff --git a/libide/clang/ide-clang-translation-unit.c b/libide/clang/ide-clang-translation-unit.c
index 765afda..c8676c8 100644
--- a/libide/clang/ide-clang-translation-unit.c
+++ b/libide/clang/ide-clang-translation-unit.c
@@ -131,6 +131,8 @@ ide_clang_translation_unit_get_diagnostics (IdeClangTranslationUnit *self)
 
   if (!priv->diagnostics)
     {
+      IdeContext *context;
+      IdeProject *project;
       GPtrArray *ar;
       guint count;
       guint i;
@@ -138,6 +140,18 @@ ide_clang_translation_unit_get_diagnostics (IdeClangTranslationUnit *self)
       ar = g_ptr_array_new_with_free_func ((GDestroyNotify)ide_diagnostic_unref);
       count = clang_getNumDiagnostics (priv->tu);
 
+      /*
+       * Acquire the reader lock for the project since we will need to do
+       * a bunch of project tree lookups when creating diagnostics. By doing
+       * this outside of the loops, we avoid creating lots of contention on
+       * the reader lock, but potentially hold on to the entire lock for a bit
+       * longer at a time.
+       */
+      context = ide_object_get_context (IDE_OBJECT (self));
+      project = ide_context_get_project (context);
+
+      ide_project_reader_lock (project);
+
       for (i = 0; i < count; i++)
         {
           CXDiagnostic cxdiag;
@@ -150,6 +164,8 @@ ide_clang_translation_unit_get_diagnostics (IdeClangTranslationUnit *self)
           clang_disposeDiagnostic (cxdiag);
         }
 
+      ide_project_reader_unlock (project);
+
       priv->diagnostics = _ide_diagnostics_new (ar);
     }
 
diff --git a/libide/git/ide-git-vcs.c b/libide/git/ide-git-vcs.c
index 9d7477e..b9515ca 100644
--- a/libide/git/ide-git-vcs.c
+++ b/libide/git/ide-git-vcs.c
@@ -213,12 +213,14 @@ ide_git_vcs_reload_index (IdeGitVcs  *self,
 
   context = ide_object_get_context (IDE_OBJECT (self));
   project = ide_context_get_project (context);
+
+  ide_project_reader_lock (project);
   root = ide_project_get_root (project);
   files = g_object_new (IDE_TYPE_PROJECT_FILES,
                         "context", context,
                         "parent", root,
                         NULL);
-  ide_project_item_append (root, files);
+  ide_project_reader_unlock (project);
 
   g_hash_table_insert (cache, g_strdup ("."), g_object_ref (files));
 
@@ -229,12 +231,14 @@ ide_git_vcs_reload_index (IdeGitVcs  *self,
 
       entry = ggit_index_entries_get_by_index (entries, i);
       path = ggit_index_entry_get_path (entry);
-
       ide_git_vcs_reload_index_add_path (self, cache, path, FALSE);
-
       ggit_index_entry_unref (entry);
     }
 
+  ide_project_writer_lock (project);
+  ide_project_item_append (root, files);
+  ide_project_writer_unlock (project);
+
   ret = TRUE;
 
 cleanup:
diff --git a/libide/ide-project.c b/libide/ide-project.c
index 88e53da..3c8237b 100644
--- a/libide/ide-project.c
+++ b/libide/ide-project.c
@@ -24,8 +24,9 @@
 
 typedef struct
 {
+  GRWLock         rw_lock;
   IdeProjectItem *root;
-  gchar *name;
+  gchar          *name;
 } IdeProjectPrivate;
 
 G_DEFINE_TYPE_WITH_PRIVATE (IdeProject, ide_project, IDE_TYPE_OBJECT)
@@ -39,6 +40,46 @@ enum {
 
 static GParamSpec *gParamSpecs [LAST_PROP];
 
+void
+ide_project_reader_lock (IdeProject *self)
+{
+  IdeProjectPrivate *priv = ide_project_get_instance_private (self);
+
+  g_return_if_fail (IDE_IS_PROJECT (self));
+
+  g_rw_lock_reader_lock (&priv->rw_lock);
+}
+
+void
+ide_project_reader_unlock (IdeProject *self)
+{
+  IdeProjectPrivate *priv = ide_project_get_instance_private (self);
+
+  g_return_if_fail (IDE_IS_PROJECT (self));
+
+  g_rw_lock_reader_unlock (&priv->rw_lock);
+}
+
+void
+ide_project_writer_lock (IdeProject *self)
+{
+  IdeProjectPrivate *priv = ide_project_get_instance_private (self);
+
+  g_return_if_fail (IDE_IS_PROJECT (self));
+
+  g_rw_lock_writer_lock (&priv->rw_lock);
+}
+
+void
+ide_project_writer_unlock (IdeProject *self)
+{
+  IdeProjectPrivate *priv = ide_project_get_instance_private (self);
+
+  g_return_if_fail (IDE_IS_PROJECT (self));
+
+  g_rw_lock_writer_unlock (&priv->rw_lock);
+}
+
 const gchar *
 ide_project_get_name (IdeProject *project)
 {
@@ -50,8 +91,8 @@ ide_project_get_name (IdeProject *project)
 }
 
 void
-ide_project_set_name (IdeProject  *project,
-                      const gchar *name)
+_ide_project_set_name (IdeProject  *project,
+                       const gchar *name)
 {
   IdeProjectPrivate *priv = ide_project_get_instance_private (project);
 
@@ -70,7 +111,16 @@ ide_project_set_name (IdeProject  *project,
  *
  * Retrieves the root item of the project tree.
  *
- * Returns: (transfer none): An #IdeProjectItem
+ * You must be holding the reader lock while calling and using the result of
+ * this function. Other thread may be accessing or modifying the tree without
+ * your knowledge. See ide_project_reader_lock() and ide_project_reader_unlock()
+ * for more information.
+ *
+ * If you need to modify the tree, you must hold a writer lock that has been
+ * acquired with ide_project_writer_lock() and released with
+ * ide_project_writer_unlock() when you are no longer modifiying the tree.
+ *
+ * Returns: (transfer none): An #IdeProjectItem.
  */
 IdeProjectItem *
 ide_project_get_root (IdeProject *project)
@@ -113,6 +163,10 @@ ide_project_set_root (IdeProject     *project,
  * Retrieves an #IdeFile for the path specified. #IdeFile provides access to
  * language specific features via ide_file_get_language().
  *
+ * You must hold the reader lock while calling this function. See
+ * ide_project_reader_lock() and ide_project_reader_unlock() for more
+ * information.
+ *
  * Returns: (transfer full) (nullable): An #IdeFile or %NULL if no matching
  *   file could be found.
  */
@@ -161,6 +215,7 @@ ide_project_finalize (GObject *object)
 
   g_clear_object (&priv->root);
   g_clear_pointer (&priv->name, g_free);
+  g_rw_lock_clear (&priv->rw_lock);
 
   G_OBJECT_CLASS (ide_project_parent_class)->finalize (object);
 }
@@ -198,10 +253,6 @@ ide_project_set_property (GObject      *object,
 
   switch (prop_id)
     {
-    case PROP_NAME:
-      ide_project_set_name (self, g_value_get_string (value));
-      break;
-
     case PROP_ROOT:
       ide_project_set_root (self, g_value_get_object (value));
       break;
@@ -225,7 +276,7 @@ ide_project_class_init (IdeProjectClass *klass)
                          _("Name"),
                          _("The name of the project."),
                          NULL,
-                         (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+                         (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (object_class, PROP_NAME,
                                    gParamSpecs [PROP_NAME]);
 
@@ -244,4 +295,7 @@ ide_project_class_init (IdeProjectClass *klass)
 static void
 ide_project_init (IdeProject *self)
 {
+  IdeProjectPrivate *priv = ide_project_get_instance_private (self);
+
+  g_rw_lock_init (&priv->rw_lock);
 }
diff --git a/libide/ide-project.h b/libide/ide-project.h
index 1a9c255..f4f8211 100644
--- a/libide/ide-project.h
+++ b/libide/ide-project.h
@@ -36,6 +36,10 @@ IdeProjectItem *ide_project_get_root          (IdeProject  *project);
 const gchar    *ide_project_get_name          (IdeProject  *project);
 IdeFile        *ide_project_get_file_for_path (IdeProject  *project,
                                                const gchar *path);
+void            ide_project_reader_lock       (IdeProject  *project);
+void            ide_project_reader_unlock     (IdeProject  *project);
+void            ide_project_writer_lock       (IdeProject  *project);
+void            ide_project_writer_unlock     (IdeProject  *project);
 
 G_END_DECLS
 
diff --git a/src/tree/gb-project-tree-builder.c b/src/tree/gb-project-tree-builder.c
index a16803c..e132144 100644
--- a/src/tree/gb-project-tree-builder.c
+++ b/src/tree/gb-project-tree-builder.c
@@ -140,6 +140,8 @@ build_project (GbProjectTreeBuilder *self,
 
   project = IDE_PROJECT (gb_tree_node_get_item (node));
 
+  ide_project_reader_lock (project);
+
   root = ide_project_get_root (project);
   children = ide_project_item_get_children (root);
 
@@ -169,6 +171,8 @@ build_project (GbProjectTreeBuilder *self,
             }
         }
     }
+
+  ide_project_reader_unlock (project);
 }
 
 static void
diff --git a/tools/ide-list-diagnostics.c b/tools/ide-list-diagnostics.c
index 10e724b..706d6d6 100644
--- a/tools/ide-list-diagnostics.c
+++ b/tools/ide-list-diagnostics.c
@@ -95,7 +95,10 @@ context_cb (GObject      *object,
     }
 
   project = ide_context_get_project (context);
+
+  ide_project_reader_lock (project);
   file = ide_project_get_file_for_path (project, gPath);
+  ide_project_reader_unlock (project);
 
   if (!file)
     {
diff --git a/tools/ide-list-files.c b/tools/ide-list-files.c
index 5eb2f83..52ed55d 100644
--- a/tools/ide-list-files.c
+++ b/tools/ide-list-files.c
@@ -105,7 +105,9 @@ context_cb (GObject      *object,
   project = ide_context_get_project (context);
   root = ide_project_get_root (project);
 
+  ide_project_reader_lock (project);
   walk_tree (root, 0);
+  ide_project_reader_unlock (project);
 
   quit (EXIT_SUCCESS);
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]