diff options
author | Andy Wingo <wingo@pobox.com> | 2011-04-15 18:31:06 +0200 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2011-04-15 18:31:06 +0200 |
commit | 66b229d56ec8f3e023a76b9ebcf8c9fed7640834 (patch) | |
tree | 9fa767de0cb3bc3a1bed3438b0053b60c0ffc10d | |
parent | 631e49ed767a877fc1776dc5b07818512fdc8c06 (diff) | |
download | guile-66b229d56ec8f3e023a76b9ebcf8c9fed7640834.tar.gz |
pre-GC_set_start_callback compatibility
* configure.ac: Add a check for GC_set_start_callback.
* libguile/gc.c (scm_i_gc): If we don't have GC_set_start_callback, run
the before-gc hook manually here.
(scm_init_gc): Otherwise set it as a start callback.
* libguile/hashtab.c (weak_gc_callback, weak_gc_hook)
(weak_gc_finalizer, scm_c_register_weak_gc_callback): Fix to work
either way, with or without GC_set_start_callback.
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | libguile/gc.c | 6 | ||||
-rw-r--r-- | libguile/hashtab.c | 39 |
3 files changed, 38 insertions, 9 deletions
diff --git a/configure.ac b/configure.ac index fe7777365..3bb6bf6c3 100644 --- a/configure.ac +++ b/configure.ac @@ -1238,7 +1238,7 @@ save_LIBS="$LIBS" LIBS="$BDW_GC_LIBS $LIBS" CFLAGS="$BDW_GC_CFLAGS $CFLAGS" -AC_CHECK_FUNCS([GC_do_blocking GC_call_with_gc_active GC_pthread_exit GC_pthread_cancel GC_allow_register_threads GC_pthread_sigmask]) +AC_CHECK_FUNCS([GC_do_blocking GC_call_with_gc_active GC_pthread_exit GC_pthread_cancel GC_allow_register_threads GC_pthread_sigmask GC_set_start_callback]) # Though the `GC_do_blocking ()' symbol is present in GC 7.1, it is not # declared, and has a different type (returning void instead of diff --git a/libguile/gc.c b/libguile/gc.c index da530ebcf..341af6ff2 100644 --- a/libguile/gc.c +++ b/libguile/gc.c @@ -355,6 +355,9 @@ SCM_DEFINE (scm_gc, "gc", 0, 0, 0, void scm_i_gc (const char *what) { +#ifndef HAVE_GC_SET_START_CALLBACK + run_before_gc_c_hook (); +#endif GC_gcollect (); } @@ -799,7 +802,10 @@ scm_init_gc () SCM_BOOL_F); scm_c_hook_add (&scm_before_gc_c_hook, queue_after_gc_hook, NULL, 0); + +#ifdef HAVE_GC_SET_START_CALLBACK GC_set_start_callback (run_before_gc_c_hook); +#endif #include "libguile/gc.x" } diff --git a/libguile/hashtab.c b/libguile/hashtab.c index f5c86a56f..48660d75c 100644 --- a/libguile/hashtab.c +++ b/libguile/hashtab.c @@ -418,20 +418,39 @@ SCM_DEFINE (scm_make_hash_table, "make-hash-table", 0, 1, 0, } #undef FUNC_NAME -static void* -weak_gc_callback (void *hook_data, void *fn_data, void *data) +/* The before-gc C hook only runs if GC_set_start_callback is available, + so if not, fall back on a finalizer-based implementation. */ +static int +weak_gc_callback (void **weak) { - void **weak = fn_data; void *val = weak[0]; void (*callback) (SCM) = weak[1]; - if (val) - callback (PTR2SCM (val)); - else - scm_c_hook_remove (&scm_before_gc_c_hook, weak_gc_callback, weak); + if (!val) + return 0; + + callback (PTR2SCM (val)); + + return 1; +} + +#ifdef HAVE_GC_SET_START_CALLBACK +static void* +weak_gc_hook (void *hook_data, void *fn_data, void *data) +{ + if (!weak_gc_callback (fn_data)) + scm_c_hook_remove (&scm_before_gc_c_hook, weak_gc_hook, fn_data); return NULL; } +#else +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); +} +#endif static void scm_c_register_weak_gc_callback (SCM obj, void (*callback) (SCM)) @@ -442,7 +461,11 @@ scm_c_register_weak_gc_callback (SCM obj, void (*callback) (SCM)) weak[1] = (void*)callback; GC_GENERAL_REGISTER_DISAPPEARING_LINK (weak, SCM2PTR (obj)); - scm_c_hook_add (&scm_before_gc_c_hook, weak_gc_callback, weak, 0); +#ifdef HAVE_GC_SET_START_CALLBACK + scm_c_hook_add (&scm_before_gc_c_hook, weak_gc_hook, weak, 0); +#else + GC_REGISTER_FINALIZER_NO_ORDER (weak, weak_gc_finalizer, NULL, NULL, NULL); +#endif } SCM_DEFINE (scm_make_weak_key_hash_table, "make-weak-key-hash-table", 0, 1, 0, |