diff options
author | Andy Wingo <wingo@pobox.com> | 2017-03-13 15:47:51 +0100 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2017-03-13 15:47:51 +0100 |
commit | c9910c604279f438728cd268272e1839cbc53835 (patch) | |
tree | cb20e718574bacce1e9356d1b4585e4cbb5b4906 /libguile/weak-table.c | |
parent | e3374320415df973a6d8b0e1065b5b74e9e3e5e0 (diff) | |
download | guile-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.c | 18 |
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); } /* |