From 3ceff8a9ef70a71f236d56afe92067d81d05c16e Mon Sep 17 00:00:00 2001 From: Allison Lortie Date: Fri, 14 Oct 2016 11:37:18 +0200 Subject: gvdb: remove memory allocation from GvdbPath Modify GvdbPath to never allocate memory. Previously, if we had fewer split points ('/') than the number of pre-allocated items in the arrays in the structure, we would simply use them. At 16, this number is already extremely high, and it's implausible to imagine a real case for which this would be insufficient. This commit simplifies things a bit: if there are more than 16 segments, we will just ignore the later ones, except for the final one (ie: the complete path). For the sake of an example, let the limit be 4, rather than 16. This means that you could lock: / /org/ /org/gnome/ /org/gnome/app/deeply/nested/key but not: /org/gnome/app/ /org/gnome/app/deeply/ /org/gnome/app/deeply/nested/ With 16 segments, everything here could be locked, and much more. In this way, we preserve the previous behaviour of always being able to lock a particular individual key of any depth, while introducing path-based locks for all reasonable cases, and we avoid memory allocations in all cases. --- gvdb/gvdb-reader.c | 42 +++++++----------------------------------- gvdb/gvdb-reader.h | 9 ++------- 2 files changed, 9 insertions(+), 42 deletions(-) diff --git a/gvdb/gvdb-reader.c b/gvdb/gvdb-reader.c index b675a16..ae18831 100644 --- a/gvdb/gvdb-reader.c +++ b/gvdb/gvdb-reader.c @@ -49,28 +49,6 @@ gvdb_path_append_component (GvdbPath *path, { guint this_component = path->components++; - if G_UNLIKELY (path->components % G_N_ELEMENTS (path->my_hashes) == 0) - { - guint next_size; - - G_STATIC_ASSERT (sizeof path->my_hashes == sizeof path->my_lengths); - - if (path->hashes == path->my_hashes) - { - /* It's slightly inefficient to do it this way, but - * we're already on the slow path, and this simplifies - * the code below. - */ - path->hashes = g_memdup (path->hashes, sizeof path->my_hashes); - path->lengths = g_memdup (path->lengths, sizeof path->my_lengths); - } - - /* 16 → 32 → etc. */ - next_size = path->components + G_N_ELEMENTS (path->my_hashes); - path->hashes = g_renew (guint32, path->hashes, next_size); - path->lengths = g_renew (guint, path->lengths, next_size); - } - path->hashes[this_component] = hash_value; path->lengths[this_component] = length; } @@ -86,8 +64,6 @@ gvdb_path_init (GvdbPath *path, path->string = string; path->components = 0; - path->hashes = path->my_hashes; - path->lengths = path->my_lengths; /* Find all of the separators, creating components, up to including * each one. @@ -97,7 +73,13 @@ gvdb_path_init (GvdbPath *path, hash_value = (hash_value * 33) + ((signed char) string[i]); more = TRUE; - if (string[i] == separator) + /* If we have a separator, and if we will not be using the last + * item in the array, add a new split point. + * + * In effect, this always allows locking of individual keys (at + * any depth) but only allows locking paths up to a certain depth. + */ + if (string[i] == separator && path->components + 1 < G_N_ELEMENTS (path->hashes)) { gvdb_path_append_component (path, hash_value, i + 1); more = FALSE; @@ -111,16 +93,6 @@ gvdb_path_init (GvdbPath *path, gvdb_path_append_component (path, hash_value, i); } -void -gvdb_path_clear (GvdbPath *path) -{ - if (path->hashes != path->my_hashes) - g_free (path->hashes); - - if (path->lengths != path->my_lengths) - g_free (path->my_lengths); -} - static const gchar * gvdb_table_item_get_key (GvdbTable *file, const struct gvdb_hash_item *item, diff --git a/gvdb/gvdb-reader.h b/gvdb/gvdb-reader.h index e567a5b..fd76b5e 100644 --- a/gvdb/gvdb-reader.h +++ b/gvdb/gvdb-reader.h @@ -28,10 +28,8 @@ typedef struct { const gchar *string; guint components; - guint32 *hashes; - guint *lengths; - guint32 my_hashes[16]; - guint my_lengths[16]; + guint32 hashes[16]; + guint lengths[16]; } GvdbPath; G_BEGIN_DECLS @@ -41,9 +39,6 @@ void gvdb_path_init (GvdbPat const gchar *string, gchar separator); -G_GNUC_INTERNAL -void gvdb_path_clear (GvdbPath *path); - G_GNUC_INTERNAL GvdbTable * gvdb_table_new_from_bytes (GBytes *bytes, gboolean trusted, -- cgit v1.2.1