summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius Vollmer <mvo@zagadka.de>2005-04-04 14:53:27 +0000
committerMarius Vollmer <mvo@zagadka.de>2005-04-04 14:53:27 +0000
commitd3a80924bc68db8ad41dad014edac5d61f520537 (patch)
tree1081b1bf2c31ede8e228500e8505c0e48847fed5
parent9aa0c3dd94f26417ef138c9b6f3133134a3dc6d2 (diff)
downloadguile-d3a80924bc68db8ad41dad014edac5d61f520537.tar.gz
(scm_t_hashtable): Removed 'closure' field. The
closure can not be stored since it is no longer valid at GC time. (make_hash_table): Initialize 'hash_fn' field. (scm_i_rehash): Only store hash_fn in hash table when closre is NULL. (rehash_after_gc): Only call scm_i_rehash when 'hash_fn' is non-NULL. Always use a NULL closure. (scm_hash_fn_create_handle_x): Also rehash when table contains too few entries.
-rw-r--r--libguile/hashtab.c30
-rw-r--r--libguile/hashtab.h3
2 files changed, 21 insertions, 12 deletions
diff --git a/libguile/hashtab.c b/libguile/hashtab.c
index 1df1dea1f..488054969 100644
--- a/libguile/hashtab.c
+++ b/libguile/hashtab.c
@@ -102,6 +102,7 @@ make_hash_table (int flags, unsigned long k, const char *func_name)
t->lower = 0;
t->upper = 9 * n / 10;
t->flags = flags;
+ t->hash_fn = NULL;
if (flags)
{
SCM_NEWSMOB3 (table, scm_tc16_hashtable, vector, t, weak_hashtables);
@@ -112,7 +113,6 @@ make_hash_table (int flags, unsigned long k, const char *func_name)
return table;
}
-
void
scm_i_rehash (SCM table,
unsigned long (*hash_fn)(),
@@ -139,9 +139,13 @@ scm_i_rehash (SCM table,
if (i >= HASHTABLE_SIZE_N)
/* don't rehash */
return;
- /* store for use in rehash_after_gc */
- SCM_HASHTABLE (table)->hash_fn = hash_fn;
- SCM_HASHTABLE (table)->closure = closure;
+
+ /* Remember HASH_FN for rehash_after_gc, but only when CLOSURE
+ is not needed since CLOSURE can not be guaranteed to be valid
+ after this function returns.
+ */
+ if (closure == NULL)
+ SCM_HASHTABLE (table)->hash_fn = hash_fn;
}
SCM_HASHTABLE (table)->size_index = i;
@@ -298,11 +302,11 @@ rehash_after_gc (void *dummy1 SCM_UNUSED,
h = first;
do
{
- scm_i_rehash (h,
- /* use same hash_fn and closure as last time */
- SCM_HASHTABLE (h)->hash_fn,
- SCM_HASHTABLE (h)->closure,
- "rehash_after_gc");
+ /* Rehash only when we have a hash_fn.
+ */
+ if (SCM_HASHTABLE (h)->hash_fn)
+ scm_i_rehash (h, SCM_HASHTABLE (h)->hash_fn, NULL,
+ "rehash_after_gc");
last = h;
h = SCM_HASHTABLE_NEXT (h);
} while (!scm_is_null (h));
@@ -507,8 +511,14 @@ scm_hash_fn_create_handle_x (SCM table, SCM obj, SCM init, unsigned long (*hash_
SCM_SIMPLE_VECTOR_SET (buckets, k, new_bucket);
if (!scm_is_eq (table, buckets))
{
+ /* Update element count and maybe rehash the table. The
+ table might have too few entries here since weak hash
+ tables used with the hashx_* functions can not be
+ rehashed after GC.
+ */
SCM_HASHTABLE_INCREMENT (table);
- if (SCM_HASHTABLE_N_ITEMS (table) > SCM_HASHTABLE_UPPER (table))
+ if (SCM_HASHTABLE_N_ITEMS (table) < SCM_HASHTABLE_LOWER (table)
+ || SCM_HASHTABLE_N_ITEMS (table) > SCM_HASHTABLE_UPPER (table))
scm_i_rehash (table, hash_fn, closure, FUNC_NAME);
}
return SCM_CAR (new_bucket);
diff --git a/libguile/hashtab.h b/libguile/hashtab.h
index 5ef30a1c8..e94ffe067 100644
--- a/libguile/hashtab.h
+++ b/libguile/hashtab.h
@@ -73,8 +73,7 @@ typedef struct scm_t_hashtable {
unsigned long upper; /* when to grow */
int size_index; /* index into hashtable_size */
int min_size_index; /* minimum size_index */
- unsigned long (*hash_fn) ();
- void *closure;
+ unsigned long (*hash_fn) (); /* for rehashing after a GC. */
} scm_t_hashtable;