1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-10 14:00:21 +02:00

* hashtab.c (scm_i_rehash): Cope with the case that a GC modifies

the hashtable.
(scm_hash_fn_create_handle_x): Likewise.
* vectors.h (SCM_I_SET_WVECT_TYPE): New, for use in scm_i_rehash.
This commit is contained in:
Marius Vollmer 2005-02-23 17:24:19 +00:00
parent 57491e856d
commit bc6580eb22
2 changed files with 32 additions and 13 deletions

View file

@ -162,25 +162,40 @@ scm_i_rehash (SCM table,
else
new_buckets = scm_c_make_vector (new_size, SCM_EOL);
/* When this is a weak hashtable, running the GC might change it.
We need to cope with this while rehashing its elements. We do
this by first installing the new, empty bucket vector and turning
the old bucket vector into a regularily scanned weak vector.
Then we iterate over the elements in the old bucket vector.
While iterating, the elements in LS will not disappear since they
are protected.
*/
SCM_SET_HASHTABLE_VECTOR (table, new_buckets);
SCM_SET_HASHTABLE_N_ITEMS (table, 0);
if (SCM_HASHTABLE_WEAK_P (table))
SCM_I_SET_WVECT_TYPE (buckets, (SCM_HASHTABLE_FLAGS (table)));
old_size = SCM_SIMPLE_VECTOR_LENGTH (buckets);
for (i = 0; i < old_size; ++i)
{
SCM ls = SCM_SIMPLE_VECTOR_REF (buckets, i), handle;
while (!scm_is_null (ls))
SCM ls, cell, handle;
ls = SCM_SIMPLE_VECTOR_REF (buckets, i);
while (scm_is_pair (ls))
{
unsigned long h;
handle = SCM_CAR (ls);
cell = ls;
handle = SCM_CAR (cell);
ls = SCM_CDR (ls);
h = hash_fn (SCM_CAR (handle), new_size, closure);
if (h >= new_size)
scm_out_of_range (func_name, scm_from_ulong (h));
SCM_SIMPLE_VECTOR_SET
(new_buckets, h,
scm_cons (handle,
SCM_SIMPLE_VECTOR_REF (new_buckets, h)));
ls = SCM_CDR (ls);
SCM_SETCDR (cell, SCM_SIMPLE_VECTOR_REF (new_buckets, h));
SCM_SIMPLE_VECTOR_SET (new_buckets, h, cell);
SCM_HASHTABLE_INCREMENT (table);
}
}
SCM_SET_HASHTABLE_VECTOR (table, new_buckets);
}
@ -475,8 +490,11 @@ scm_hash_fn_create_handle_x (SCM table, SCM obj, SCM init, unsigned long (*hash_
return it;
else
{
SCM old_bucket = SCM_SIMPLE_VECTOR_REF (buckets, k);
SCM new_bucket = scm_acons (obj, init, old_bucket);
/* We need to take care not to run the GC while linking the new
bucket into its chain. A GC might change a weak hashtable.
*/
SCM new_bucket = scm_acons (obj, init, SCM_EOL);
SCM_SETCDR (new_bucket, SCM_SIMPLE_VECTOR_REF (buckets, k));
SCM_SIMPLE_VECTOR_SET (buckets, k, new_bucket);
if (table != buckets)
{

View file

@ -95,8 +95,9 @@ SCM_API SCM scm_i_vector_equal_p (SCM x, SCM y);
#define SCM_I_WVECT_VELTS SCM_I_VECTOR_ELTS
#define SCM_I_WVECT_GC_WVELTS SCM_I_VECTOR_WELTS
#define SCM_I_WVECT_TYPE(x) (SCM_CELL_WORD_2 (x))
#define SCM_I_WVECT_GC_CHAIN(X) (SCM_CELL_OBJECT_3 (X))
#define SCM_I_SET_WVECT_GC_CHAIN(X, o) (SCM_SET_CELL_OBJECT_3 ((X), (o)))
#define SCM_I_SET_WVECT_TYPE(x, t) (SCM_SET_CELL_WORD_2 ((x),(t)))
#define SCM_I_WVECT_GC_CHAIN(x) (SCM_CELL_OBJECT_3 (x))
#define SCM_I_SET_WVECT_GC_CHAIN(x, o) (SCM_SET_CELL_OBJECT_3 ((x), (o)))
SCM_API SCM scm_i_allocate_weak_vector (scm_t_bits type, SCM size, SCM fill);