[gnome-builder] libide/foundry: add IdePathCache



commit 5d457ce9efa8f2eb0ac90cf18dc8502a86da2610
Author: Christian Hergert <chergert redhat com>
Date:   Tue Oct 4 16:45:58 2022 -0700

    libide/foundry: add IdePathCache
    
    This utility object is a thread-safe cache for positive/negative path
    lookups to avoid repeated lookups against the filesystem/SDK.

 src/libide/foundry/ide-path-cache.c | 185 ++++++++++++++++++++++++++++++++++++
 src/libide/foundry/ide-path-cache.h |  51 ++++++++++
 src/libide/foundry/libide-foundry.h |   1 +
 src/libide/foundry/meson.build      |   2 +
 4 files changed, 239 insertions(+)
---
diff --git a/src/libide/foundry/ide-path-cache.c b/src/libide/foundry/ide-path-cache.c
new file mode 100644
index 000000000..e430b6e78
--- /dev/null
+++ b/src/libide/foundry/ide-path-cache.c
@@ -0,0 +1,185 @@
+/* ide-path-cache.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "ide-path-cache"
+
+#include "config.h"
+
+#include "ide-path-cache.h"
+
+/**
+ * SECTION:ide-path-cache
+ * @title: IdePathCache
+ * @Short_description: thread-safe cache for path lookups
+ *
+ * #IdePathCache can be used to cache path lookup entries as often
+ * needed by runtimes.
+ *
+ * This object is thread-safe and may be accessed from multiple
+ * threads simultaneously.
+ */
+
+struct _IdePathCache
+{
+  GObject     parent_instance;
+  GMutex      mutex;
+  GHashTable *cache;
+};
+
+G_DEFINE_FINAL_TYPE (IdePathCache, ide_path_cache, G_TYPE_OBJECT)
+
+static void
+ide_path_cache_dispose (GObject *object)
+{
+  IdePathCache *self = (IdePathCache *)object;
+
+  g_hash_table_remove_all (self->cache);
+
+  G_OBJECT_CLASS (ide_path_cache_parent_class)->dispose (object);
+}
+
+static void
+ide_path_cache_finalize (GObject *object)
+{
+  IdePathCache *self = (IdePathCache *)object;
+
+  g_clear_pointer (&self->cache, g_hash_table_unref);
+  g_mutex_clear (&self->mutex);
+
+  G_OBJECT_CLASS (ide_path_cache_parent_class)->finalize (object);
+}
+
+static void
+ide_path_cache_class_init (IdePathCacheClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = ide_path_cache_dispose;
+  object_class->finalize = ide_path_cache_finalize;
+}
+
+static void
+ide_path_cache_init (IdePathCache *self)
+{
+  g_mutex_init (&self->mutex);
+  self->cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+}
+
+IdePathCache *
+ide_path_cache_new (void)
+{
+  return g_object_new (IDE_TYPE_PATH_CACHE, NULL);
+}
+
+/**
+ * ide_path_cache_lookup:
+ * @self: a #IdePathCache
+ * @program_name: the program name to lookup
+ * @program_path: (out) (transfer full) (nullable): a location to store
+ *   the @program_path for @program_name.
+ *
+ * %TRUE is returned when an entry is found in the cache. That entry
+ * may be %NULL indicating a negative cache entry.
+ *
+ * Returns: %TRUE if @program_name was found and @program_path is set;
+ *   otherwise %FALSE is returned.
+ */
+gboolean
+ide_path_cache_lookup (IdePathCache  *self,
+                       const char    *program_name,
+                       char         **program_path)
+{
+  const char *path = NULL;
+  gboolean ret;
+
+  g_return_val_if_fail (IDE_IS_PATH_CACHE (self), FALSE);
+  g_return_val_if_fail (program_name, FALSE);
+
+  g_mutex_lock (&self->mutex);
+  ret = g_hash_table_lookup_extended (self->cache, program_name, NULL, (gpointer *)&path);
+  if (program_path != NULL)
+    *program_path = path ? g_strdup (path) : NULL;
+  g_mutex_unlock (&self->mutex);
+
+  return ret;
+}
+
+/**
+ * ide_path_cache_contains:
+ * @self: a #IdePathCache
+ * @program_name: the name of the program to lookup
+ * @had_program_path: (out) (nullable): a location to store if a path
+ *   was found for @program_name.
+ *
+ * This function helps for detecting negative cache entries without
+ * copying the program_path string.
+ *
+ * Returns: %TRUE if an entry was found and @had_program_path is set;
+ *   otherwise %FALSE.
+ */
+gboolean
+ide_path_cache_contains (IdePathCache *self,
+                         const char   *program_name,
+                         gboolean     *had_program_path)
+{
+  const char *path = NULL;
+  gboolean ret;
+
+  g_return_val_if_fail (IDE_IS_PATH_CACHE (self), FALSE);
+  g_return_val_if_fail (program_name, FALSE);
+
+  g_mutex_lock (&self->mutex);
+  ret = g_hash_table_lookup_extended (self->cache, program_name, NULL, (gpointer *)&path);
+  if (had_program_path)
+    *had_program_path = path != NULL;
+  g_mutex_unlock (&self->mutex);
+
+  return ret;
+}
+
+/**
+ * ide_path_cache_insert:
+ * @self: a #IdePathCache
+ * @program_name: the name of the program
+ * @program_path: (nullable): the path for the program
+ *
+ * Inserts a cache entry for @program_name for @program_path.
+ *
+ * @program_path may be %NULL to register a negative cache entry. See
+ * ide_path_cache_lookup() for handling negative cache entries.
+ */
+void
+ide_path_cache_insert (IdePathCache *self,
+                       const char   *program_name,
+                       const char   *program_path)
+{
+  char *key;
+  char *value;
+
+  g_return_if_fail (IDE_IS_PATH_CACHE (self));
+  g_return_if_fail (program_name != NULL);
+
+  key = g_strdup (program_name);
+  value = g_strdup (program_path);
+
+  g_mutex_lock (&self->mutex);
+  g_hash_table_insert (self->cache, key, value);
+  g_mutex_unlock (&self->mutex);
+}
diff --git a/src/libide/foundry/ide-path-cache.h b/src/libide/foundry/ide-path-cache.h
new file mode 100644
index 000000000..7f2c27e6a
--- /dev/null
+++ b/src/libide/foundry/ide-path-cache.h
@@ -0,0 +1,51 @@
+/* ide-path-cache.h
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#if !defined (IDE_FOUNDRY_INSIDE) && !defined (IDE_FOUNDRY_COMPILATION)
+# error "Only <libide-foundry.h> can be included directly."
+#endif
+
+#include <libide-core.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_PATH_CACHE (ide_path_cache_get_type())
+
+IDE_AVAILABLE_IN_44
+G_DECLARE_FINAL_TYPE (IdePathCache, ide_path_cache, IDE, PATH_CACHE, GObject)
+
+IDE_AVAILABLE_IN_44
+IdePathCache *ide_path_cache_new      (void);
+IDE_AVAILABLE_IN_44
+gboolean      ide_path_cache_lookup   (IdePathCache  *self,
+                                       const char    *program_name,
+                                       char         **program_path);
+IDE_AVAILABLE_IN_44
+gboolean      ide_path_cache_contains (IdePathCache  *self,
+                                       const char    *program_name,
+                                       gboolean      *had_program_path);
+IDE_AVAILABLE_IN_44
+void          ide_path_cache_insert   (IdePathCache  *self,
+                                       const char    *program_name,
+                                       const char    *program_path);
+
+G_END_DECLS
diff --git a/src/libide/foundry/libide-foundry.h b/src/libide/foundry/libide-foundry.h
index e2c14fea3..91e963894 100644
--- a/src/libide/foundry/libide-foundry.h
+++ b/src/libide/foundry/libide-foundry.h
@@ -49,6 +49,7 @@ G_BEGIN_DECLS
 #include "ide-foundry-compat.h"
 #include "ide-foundry-global.h"
 #include "ide-local-device.h"
+#include "ide-path-cache.h"
 #include "ide-pipeline-addin.h"
 #include "ide-pipeline-stage-command.h"
 #include "ide-pipeline-stage-launcher.h"
diff --git a/src/libide/foundry/meson.build b/src/libide/foundry/meson.build
index 7c22c396d..a10105644 100644
--- a/src/libide/foundry/meson.build
+++ b/src/libide/foundry/meson.build
@@ -33,6 +33,7 @@ libide_foundry_public_headers = [
   'ide-foundry-global.h',
   'ide-foundry-types.h',
   'ide-local-device.h',
+  'ide-path-cache.h',
   'ide-pipeline-addin.h',
   'ide-pipeline-phase.h',
   'ide-pipeline-stage-command.h',
@@ -119,6 +120,7 @@ libide_foundry_public_sources = [
   'ide-foundry-compat.c',
   'ide-foundry-global.c',
   'ide-local-device.c',
+  'ide-path-cache.c',
   'ide-pipeline-addin.c',
   'ide-pipeline-stage-command.c',
   'ide-pipeline-stage-launcher.c',


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