freeing hash nodes (Re: GNOME CVS: glib johnsonm)



On Tue, 24 Nov 1998, Michael K. Johnson wrote:

> 
> >Modified files:
> >	.              : ChangeLog ghash.c glib.h 
> >
> >Log message:
> >Tue Nov 24 14:05:47 EST 1998	Michael K. Johnson <johnsonm@redhat.com>
> >
> >* glib.h: added GFreeFunc and g_hash_table_set_key_freefunc()
> >prototype.
> >* ghash.c: added g_hash_table_set_key_freefunc() implementation.
> >Modified the prototypes of the functions g_hash_node_destroy() and
> >g_hash_nodes_destroy(), and changed the functions that call them
> >to match the new definitions.
> >This changes no external interfaces, and should create no binary
> >or source incompatibilities.  It does add a member to the
> >GHashTable structure.
> 
> The point of this change is to be able to do
> g_hash_table_insert(table, g_strdup(blah), baz);
> and then when you remove that entry later, the key will be freed.
> This is useful for tables where all the data is dynamically generated,
> not kept in static tables of strings.  It's important to have because
> there is no other intrinsic way to free the key.

hm, this is actually an extremly specialized implementation to
free hash nodes contents:

typedef void            (*GFreeFunc)      (gpointer      data);
void        g_hash_table_set_key_freefunc (GHashTable   *hash_table,
                                           GFreeFunc    *free_func);

on some occasions you need the ability to free only individual nodes,
e.g. sometimes you insert a static const gchar*; and sometimes you
insert g_strdup()ed strings into a hashtable. also, the hash value
may need to be freed as well, again, eventually only on specific
occasions.

i've discussed matters a bit with josh on irc, and what we came up with
are basically two possibilities (josh may jump on me if i left out
some important aspects ;).
note however, that for either possibility, the value and key need to
be freed from different functions, because keys and values can be
removed out of order.
i.e. when adding a new item to a hash table:

g_hash_table_insert_full (ht, k1, v1);

it internally stores a hash node of (k1, v1), then, when you readd
another value v2 with k2==k1:

g_hash_table_insert_full (ht, k2, v2);

internally, v1 becomes invalidated and the hash table now keeps
a node of (k1, v2).

now here's the approach with global free functions:


void g_hash_table_set_key_free   (GHashTable *hash_table,
                                  GFreeFunc   key_free_func);
void g_hash_table_set_value_free (GHashTable *hash_table,
                                  GFreeFunc   value_free_func);
void g_hash_table_insert_full    (GHashTable     *hash_table,
                                  gpointer        key,
                                  gpointer        value,
                                  gboolean        key_needs_free,
                                  gboolean        value_needs_free);

or, more simply, but also a little more memory consuming:

void g_hash_table_insert_full    (GHashTable     *hash_table,
                                  gpointer        key,
                                  gpointer        value,
                                  GFreeFunc       key_free_func,
                                  GFreeFunc       value_free_func);

in either case, the current implementation behaviour will be preserved,
especially memory wise, so that a node allocated from g_hash_table_insert()
will not increase in size. rather a g_hash_table_insert_full() will
either use it's own type of nodes that can store two additional function
pointers, or just flag the existing nodes appropriatedly (while keeping
their current size) so the global key/value free functions will be
invoked if desired.

any input on this matter is greatly apprechiated.


> 
> michaelkjohnson
> 

---
ciaoTJ



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