[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
gEDA-cvs: branch: master updated (1.1.2.20070818-126-gd3d40d4)
The branch, master has been updated
via d3d40d46285c5d0e75be9052d9f23480f9e8bff5 (commit)
from e4a1fa8545e76b4ef82cc1253e65a844fa5fea88 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
=========
Summary
=========
libgeda/include/prototype.h | 1 +
libgeda/src/s_clib.c | 129 +++++++++++++++++++++++++++++++++++++++++-
2 files changed, 126 insertions(+), 4 deletions(-)
=================
Commit Messages
=================
commit d3d40d46285c5d0e75be9052d9f23480f9e8bff5
Author: Peter TB Brett <peter@xxxxxxxxxxxxx>
Date: Wed Nov 28 23:20:44 2007 +0000
clib: Cache symbol data between library refreshes
Adds a cache for symbol data, which is flushed whenever the available
component libraries are changed or rescanned. This should speed up
large component copying operations.
:100644 100644 7f4665f... 6e21ef1... M libgeda/include/prototype.h
:100644 100644 aa1f336... 5065bc2... M libgeda/src/s_clib.c
=========
Changes
=========
commit d3d40d46285c5d0e75be9052d9f23480f9e8bff5
Author: Peter TB Brett <peter@xxxxxxxxxxxxx>
Date: Wed Nov 28 23:20:44 2007 +0000
clib: Cache symbol data between library refreshes
Adds a cache for symbol data, which is flushed whenever the available
component libraries are changed or rescanned. This should speed up
large component copying operations.
diff --git a/libgeda/include/prototype.h b/libgeda/include/prototype.h
index 7f4665f..6e21ef1 100644
--- a/libgeda/include/prototype.h
+++ b/libgeda/include/prototype.h
@@ -488,6 +488,7 @@ const CLibSource *s_clib_symbol_get_source (const CLibSymbol *symbol);
gchar *s_clib_symbol_get_data (const CLibSymbol *symbol);
GList *s_clib_search (const gchar *pattern, const CLibSearchMode mode);
void s_clib_flush_search_cache ();
+void s_clib_flush_symbol_cache ();
const CLibSymbol *s_clib_get_symbol_by_name (const gchar *name);
gchar *s_clib_symbol_get_data_by_name (const gchar *name);
GList *s_toplevel_get_symbols (const TOPLEVEL *toplevel);
diff --git a/libgeda/src/s_clib.c b/libgeda/src/s_clib.c
index aa1f336..5065bc2 100644
--- a/libgeda/src/s_clib.c
+++ b/libgeda/src/s_clib.c
@@ -128,6 +128,8 @@
#include <sys/wait.h>
+#include <time.h>
+
#include "defines.h"
#include "struct.h"
#include "globals.h"
@@ -151,6 +153,11 @@
/*! Library command mode used to fetch symbol data */
#define CLIB_DATA_CMD "get"
+/*! Maximum number of symbol cache entries */
+#define CLIB_MAX_SYMBOL_CACHE 128
+/*! When symbol cache gets full, remove down to this level */
+#define CLIB_MIN_SYMBOL_CACHE 96
+
/* Type definitions
* ================
*/
@@ -197,6 +204,17 @@ struct _CLibSymbol {
gchar *name;
};
+/*! Symbol data cache entry */
+typedef struct _CacheEntry CacheEntry;
+struct _CacheEntry {
+ /*! Symbol name */
+ gchar *name;
+ /*! Symbol data */
+ gchar *data;
+ /*! Last access */
+ time_t accessed;
+};
+
/* Static variables
* ================
*/
@@ -204,16 +222,25 @@ struct _CLibSymbol {
/*! Holds the list of all known component sources */
static GList *clib_sources = NULL;
-/*! Caches results of s_clib_search() */
+/*! Caches results of s_clib_search(). The key of the hashtable is a
+ * string describing the search that was carried out, and the value
+ * is a list of symbol pointers. */
static GHashTable *clib_search_cache = NULL;
+/*! Caches symbol data. The key of the hashtable is a symbol pointer,
+ * and the value is a #CacheEntry structure containing the data and
+ * the time it was last used. */
+static GHashTable *clib_symbol_cache = NULL;
+
/* Local static functions
* ======================
*/
static void free_symbol (gpointer data, gpointer user_data);
+static void free_symbol_cache_entry (gpointer data);
static void free_source (gpointer data, gpointer user_data);
static gint compare_source_name (gconstpointer a, gconstpointer b);
static gint compare_symbol_name (gconstpointer a, gconstpointer b);
+static void cache_find_oldest (gpointer key, gpointer value, gpointer user_data);
static gchar *run_source_command (const gchar *command);
static CLibSymbol *source_has_symbol (const CLibSource *source,
const gchar *name);
@@ -246,6 +273,16 @@ void s_clib_init ()
(GDestroyNotify) g_free,
(GDestroyNotify) g_list_free);
}
+
+ if (clib_symbol_cache != NULL) {
+ s_clib_flush_symbol_cache();
+ } else {
+ clib_symbol_cache =
+ g_hash_table_new_full ((GHashFunc) g_str_hash,
+ (GEqualFunc) g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) free_symbol_cache_entry);
+ }
}
/*! \brief Iterator callback for freeing a symbol.
@@ -266,6 +303,19 @@ static void free_symbol (gpointer data, gpointer user_data)
}
}
+/*! \brief Iterator callback for freeing a symbol cache entry.
+ * \par Function Description
+ * Private function used only in s_clib.c.
+ */
+static void free_symbol_cache_entry (gpointer data)
+{
+ CacheEntry *entry = data;
+ g_return_if_fail (entry != NULL);
+ g_free (entry->name);
+ g_free (entry->data);
+ g_free (entry);
+}
+
/*! \brief Iterator callback for freeing a source.
* \par Function Description
* Private function used only in s_clib.c.
@@ -366,6 +416,21 @@ static gint compare_symbol_name (gconstpointer a, gconstpointer b)
return strcasecmp(sym1->name, sym2->name);
}
+/*! \brief Iterator callback for finding oldest symbol cache entry
+ * \par Function Description
+ * Private function used only in s_clib.c.
+ */
+static void cache_find_oldest (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ CacheEntry *current = value;
+ CacheEntry **oldest = user_data;
+
+ if (current->accessed < (*oldest)->accessed) {
+ *oldest = current;
+ }
+}
/*! \brief Execute a library command.
* \par Function Description
@@ -572,6 +637,7 @@ static void refresh_directory (CLibSource *source)
(GCompareFunc) compare_symbol_name);
s_clib_flush_search_cache();
+ s_clib_flush_symbol_cache();
}
/*! \brief Re-poll a library command for symbols.
@@ -634,6 +700,7 @@ static void refresh_command (CLibSource *source)
(GCompareFunc) compare_symbol_name);
s_clib_flush_search_cache();
+ s_clib_flush_symbol_cache();
}
/*! \brief Re-poll a scheme procedure for symbols.
@@ -689,6 +756,7 @@ static void refresh_scm (CLibSource *source)
(GCompareFunc) compare_symbol_name);
s_clib_flush_search_cache();
+ s_clib_flush_symbol_cache();
}
/*! \brief Rescan all available component libraries.
@@ -1083,22 +1151,59 @@ static gchar *get_data_scm (const CLibSymbol *symbol)
*/
gchar *s_clib_symbol_get_data (const CLibSymbol *symbol)
{
+ CacheEntry *cached;
+ gchar *data;
+ gint n;
+
g_return_val_if_fail ((symbol != NULL), NULL);
g_return_val_if_fail ((symbol->source != NULL), NULL);
+ /* First, try the cache. */
+ cached = g_hash_table_lookup (clib_symbol_cache, symbol->name);
+ if (cached != NULL) {
+ cached->accessed = time(NULL);
+ return g_strdup(cached->data);
+ }
+
+ /* If the symbol wasn't found in the cache, get it directly. */
switch (symbol->source->type)
{
case CLIB_DIR:
- return get_data_directory (symbol);
+ data = get_data_directory (symbol);
+ break;
case CLIB_CMD:
- return get_data_command (symbol);
+ data = get_data_command (symbol);
+ break;
case CLIB_SCM:
- return get_data_scm (symbol);
+ data = get_data_scm (symbol);
+ break;
default:
g_critical("s_clib_symbol_get_data: source %p has bad source type %i\n",
symbol->source, (gint) symbol->source->type);
return NULL;
}
+
+ if (data == NULL) return NULL;
+
+ /* Cache the symbol data */
+ cached = g_new (CacheEntry, 1);
+ cached->name = g_strdup (symbol->name);
+ cached->data = g_strdup (data);
+ cached->accessed = time (NULL);
+ g_hash_table_insert (clib_symbol_cache, g_strdup(symbol->name), cached);
+
+ /* Clean out the cache if it's too full */
+ n = g_hash_table_size (clib_symbol_cache);
+ if (n > CLIB_MAX_SYMBOL_CACHE) {
+ for ( ; n > CLIB_MIN_SYMBOL_CACHE; n--) {
+ g_hash_table_foreach (clib_symbol_cache,
+ (GHFunc) cache_find_oldest,
+ &cached);
+ g_hash_table_remove (clib_symbol_cache, cached->name);
+ }
+ }
+
+ return data;
}
@@ -1229,6 +1334,22 @@ void s_clib_flush_search_cache ()
#endif
}
+
+/*! \brief Flush the symbol data cache.
+ * \par Function Description
+ * Clears the hashtable which caches the results of s_clib_symbol_get_data().
+ * You shouldn't ever need to call this, as all functions which
+ * invalidate the cache are supposed to make sure it's flushed.
+ */
+void s_clib_flush_symbol_cache ()
+{
+#if GLIB_CHECK_VERSION(2,12,0)
+ g_hash_table_remove_all (clib_symbol_cache); /* Introduced in glib 2.12 */
+#else
+ g_hash_table_foreach_remove(clib_symbol_cache, remove_entry, NULL);
+#endif
+}
+
/*! \brief Get symbol structure for a given symbol name.
* \par Function Description
* Return the first symbol found with the given \a name. If more
_______________________________________________
geda-cvs mailing list
geda-cvs@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-cvs