summaryrefslogtreecommitdiff
path: root/libguile/weak-table.c
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2017-03-13 15:47:51 +0100
committerAndy Wingo <wingo@pobox.com>2017-03-13 15:47:51 +0100
commitc9910c604279f438728cd268272e1839cbc53835 (patch)
treecb20e718574bacce1e9356d1b4585e4cbb5b4906 /libguile/weak-table.c
parente3374320415df973a6d8b0e1065b5b74e9e3e5e0 (diff)
downloadguile-c9910c604279f438728cd268272e1839cbc53835.tar.gz
Fix finalizer resuscitation causing excessive GC
* libguile/finalizers.c (async_gc_finalizer): (scm_i_register_async_gc_callback): Replace "weak gc callback" mechanism with "async gc callback" mechanism. Very similar but the new API is designed to be called a bounded number of times, to avoid running afoul of libgc heuristics. * libguile/weak-list.h: New internal header. * libguile/Makefile.am (noinst_HEADERS): Add weak-list.h. * libguile/weak-set.c (vacuum_all_weak_sets): (scm_c_make_weak_set, scm_init_weak_set): * libguile/weak-table.c (vacuum_all_weak_tables): (scm_c_make_weak_table, scm_init_weak_table): Arrange to vacuum all weak sets from a single async GC callback, and likewise for weak tables. Thanks to Ludovic Courtès for tracking this bug down!
Diffstat (limited to 'libguile/weak-table.c')
-rw-r--r--libguile/weak-table.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/libguile/weak-table.c b/libguile/weak-table.c
index 1bb513b17..599c4cf0e 100644
--- a/libguile/weak-table.c
+++ b/libguile/weak-table.c
@@ -33,6 +33,7 @@
#include "libguile/ports.h"
#include "libguile/validate.h"
+#include "libguile/weak-list.h"
#include "libguile/weak-table.h"
@@ -832,6 +833,17 @@ do_vacuum_weak_table (SCM table)
return;
}
+static scm_i_pthread_mutex_t all_weak_tables_lock = SCM_I_PTHREAD_MUTEX_INITIALIZER;
+static SCM all_weak_tables = SCM_EOL;
+
+static void
+vacuum_all_weak_tables (void)
+{
+ scm_i_pthread_mutex_lock (&all_weak_tables_lock);
+ scm_i_visit_weak_list (&all_weak_tables, do_vacuum_weak_table);
+ scm_i_pthread_mutex_unlock (&all_weak_tables_lock);
+}
+
SCM
scm_c_make_weak_table (unsigned long k, scm_t_weak_table_kind kind)
{
@@ -839,7 +851,9 @@ scm_c_make_weak_table (unsigned long k, scm_t_weak_table_kind kind)
ret = make_weak_table (k, kind);
- scm_i_register_weak_gc_callback (ret, do_vacuum_weak_table);
+ scm_i_pthread_mutex_lock (&all_weak_tables_lock);
+ all_weak_tables = scm_i_weak_cons (ret, all_weak_tables);
+ scm_i_pthread_mutex_unlock (&all_weak_tables_lock);
return ret;
}
@@ -1155,6 +1169,8 @@ void
scm_init_weak_table ()
{
#include "libguile/weak-table.x"
+
+ scm_i_register_async_gc_callback (vacuum_all_weak_tables);
}
/*