Merge remote-tracking branch 'origin/master'
[bpt/guile.git] / libguile / weak-table.c
index 38fd23d..be73e1b 100644 (file)
@@ -431,6 +431,42 @@ compute_size_index (scm_t_weak_table *table)
   return i;
 }
 
+static int
+is_acceptable_size_index (scm_t_weak_table *table, int size_index)
+{
+  int computed = compute_size_index (table);
+
+  if (size_index == computed)
+    /* We were going to grow or shrink, and allocating the new vector
+       didn't change the target size.  */
+    return 1;
+
+  if (size_index == computed + 1)
+    {
+      /* We were going to enlarge the table, but allocating the new
+         vector finalized some objects, making an enlargement
+         unnecessary.  It might still be a good idea to use the larger
+         table, though.  (This branch also gets hit if, while allocating
+         the vector, some other thread was actively removing items from
+         the table.  That is less likely, though.)  */
+      unsigned long new_lower = hashtable_size[size_index] / 5;
+
+      return table->size > new_lower;
+    }
+
+  if (size_index == computed - 1)
+    {
+      /* We were going to shrink the table, but when we dropped the lock
+         to allocate the new vector, some other thread added elements to
+         the table.  */
+      return 0;
+    }
+
+  /* The computed size differs from our newly allocated size by more
+     than one size index -- recalculate.  */
+  return 0;
+}
+
 static void
 resize_table (scm_t_weak_table *table)
 {
@@ -448,9 +484,9 @@ resize_table (scm_t_weak_table *table)
       /* Allocating memory might cause finalizers to run, which could
          run anything, so drop our lock to avoid deadlocks.  */
       new_entries = allocate_entries (new_size, table->kind);
-      scm_i_pthread_mutex_unlock (&table->lock);
+      scm_i_pthread_mutex_lock (&table->lock);
     }
-  while (new_size_index != compute_size_index (table));
+  while (!is_acceptable_size_index (table, new_size_index));
 
   old_entries = table->entries;
   old_size = table->size;
@@ -817,7 +853,7 @@ static void
 weak_gc_finalizer (void *ptr, void *data)
 {
   if (weak_gc_callback (ptr))
-    GC_REGISTER_FINALIZER_NO_ORDER (ptr, weak_gc_finalizer, data, NULL, NULL);
+    scm_i_set_finalizer (ptr, weak_gc_finalizer, data);
 }
 #endif
 
@@ -833,7 +869,7 @@ scm_c_register_weak_gc_callback (SCM obj, void (*callback) (SCM))
 #ifdef HAVE_GC_TABLE_START_CALLBACK
   scm_c_hook_add (&scm_after_gc_c_hook, weak_gc_hook, weak, 0);
 #else
-  GC_REGISTER_FINALIZER_NO_ORDER (weak, weak_gc_finalizer, NULL, NULL, NULL);
+  scm_i_set_finalizer (weak, weak_gc_finalizer, NULL);
 #endif
 }
 
@@ -935,24 +971,22 @@ scm_weak_table_refq (SCM table, SCM key, SCM dflt)
                                dflt);
 }
 
-SCM
+void
 scm_weak_table_putq_x (SCM table, SCM key, SCM value)
 {
   scm_c_weak_table_put_x (table, scm_ihashq (key, -1),
                           assq_predicate, SCM_UNPACK_POINTER (key),
                           key, value);
-  return SCM_UNSPECIFIED;
 }
 
-SCM
+void
 scm_weak_table_remq_x (SCM table, SCM key)
 {
   scm_c_weak_table_remove_x (table, scm_ihashq (key, -1),
                              assq_predicate, SCM_UNPACK_POINTER (key));
-  return SCM_UNSPECIFIED;
 }
 
-SCM
+void
 scm_weak_table_clear_x (SCM table)
 #define FUNC_NAME "weak-table-clear!"
 {
@@ -968,8 +1002,6 @@ scm_weak_table_clear_x (SCM table)
   t->n_items = 0;
 
   scm_i_pthread_mutex_unlock (&t->lock);
-
-  return SCM_UNSPECIFIED;
 }
 #undef FUNC_NAME
 
@@ -1037,7 +1069,7 @@ for_each_trampoline (void *closure, SCM k, SCM v, SCM seed)
   return seed;
 }
 
-SCM
+void
 scm_weak_table_for_each (SCM proc, SCM table)
 #define FUNC_NAME "weak-table-for-each"
 {
@@ -1045,8 +1077,6 @@ scm_weak_table_for_each (SCM proc, SCM table)
   SCM_VALIDATE_PROC (1, proc);
 
   scm_c_weak_table_fold (for_each_trampoline, SCM_UNPACK_POINTER (proc), SCM_BOOL_F, table);
-
-  return SCM_UNSPECIFIED;
 }
 #undef FUNC_NAME