Commit 4468ac6f authored by Christian Hergert's avatar Christian Hergert

cache: make cache thread-safe

The cache owns all objects, and they are never destroyed, so we
just need to synchronize readers and writers (who insert objects
into the cache).
parent 40691ae6
......@@ -30,6 +30,7 @@
#include "girst-cache.h"
#include "girst-util.h"
static GRWLock cache_rw_lock;
static GHashTable *cache;
static GHashTable *resolve_cache;
static GHashTable *ignored;
......@@ -41,6 +42,8 @@ girst_cache_set (const gchar *ns_name,
g_return_if_fail (ns_name);
g_return_if_fail (GIRST_IS_REPOSITORY (repository));
g_rw_lock_writer_lock (&cache_rw_lock);
if G_UNLIKELY (cache == NULL)
{
cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
......@@ -70,6 +73,8 @@ girst_cache_set (const gchar *ns_name,
}
g_hash_table_insert (cache, g_strdup (ns_name), g_object_ref (repository));
g_rw_lock_writer_unlock (&cache_rw_lock);
}
/**
......@@ -80,9 +85,15 @@ girst_cache_set (const gchar *ns_name,
GirstRepository *
girst_cache_get (const gchar *name)
{
GirstRepository *ret;
g_return_val_if_fail (name != NULL, NULL);
return cache ? g_hash_table_lookup (cache, name) : NULL;
g_rw_lock_reader_lock (&cache_rw_lock);
ret = cache ? g_hash_table_lookup (cache, name) : NULL;
g_rw_lock_reader_unlock (&cache_rw_lock);
return ret;
}
/**
......@@ -98,25 +109,41 @@ girst_cache_resolve (const gchar *ns_name,
GirstRepository *repository;
GirstParserObject *ns;
GPtrArray *children;
GirstParserObject *ret;
GirstParserObject *ret = NULL;
if G_UNLIKELY (cache == NULL)
return NULL;
g_rw_lock_reader_lock (&cache_rw_lock);
if (g_hash_table_contains (ignored, type_name))
return NULL;
goto release_reader_and_fail;
resolve_key = g_strdup_printf ("%s|%s", ns_name, type_name);
if G_UNLIKELY (resolve_cache == NULL)
resolve_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
{
g_rw_lock_reader_unlock (&cache_rw_lock);
g_rw_lock_writer_lock (&cache_rw_lock);
resolve_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
g_rw_lock_writer_unlock (&cache_rw_lock);
g_rw_lock_reader_lock (&cache_rw_lock);
}
if ((ret = g_hash_table_lookup (resolve_cache, resolve_key)))
return ret;
{
g_rw_lock_reader_unlock (&cache_rw_lock);
return ret;
}
if (!(repository = g_hash_table_lookup (cache, ns_name)) ||
!(ns = girst_parser_object_first_typed (GIRST_PARSER_OBJECT (repository), GIRST_TYPE_NAMESPACE)))
return NULL;
{
g_rw_lock_reader_unlock (&cache_rw_lock);
return NULL;
}
g_rw_lock_reader_unlock (&cache_rw_lock);
children = girst_parser_object_get_children (ns);
......@@ -129,7 +156,9 @@ girst_cache_resolve (const gchar *ns_name,
girst_str_equal0 (type_name, \
girst_##t##_get_##func (GIRST_##T (obj)))) \
{ \
g_rw_lock_writer_lock (&cache_rw_lock); \
g_hash_table_insert (resolve_cache, g_steal_pointer (&resolve_key), obj); \
g_rw_lock_writer_unlock (&cache_rw_lock); \
return obj; \
}
......@@ -147,6 +176,11 @@ girst_cache_resolve (const gchar *ns_name,
}
return NULL;
release_reader_and_fail:
g_rw_lock_reader_unlock (&cache_rw_lock);
return NULL;
}
/**
......@@ -166,8 +200,13 @@ girst_cache_foreach (GFunc foreach_func,
return;
/* Need to be re-entrant safe */
g_rw_lock_reader_lock (&cache_rw_lock);
values = g_hash_table_get_values (cache);
g_rw_lock_reader_unlock (&cache_rw_lock);
for (const GList *iter = values; iter != NULL; iter = iter->next)
foreach_func (iter->data, user_data);
g_list_free (values);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment