summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2011-04-15 18:31:06 +0200
committerAndy Wingo <wingo@pobox.com>2011-04-15 18:31:06 +0200
commit66b229d56ec8f3e023a76b9ebcf8c9fed7640834 (patch)
tree9fa767de0cb3bc3a1bed3438b0053b60c0ffc10d
parent631e49ed767a877fc1776dc5b07818512fdc8c06 (diff)
downloadguile-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.ac2
-rw-r--r--libguile/gc.c6
-rw-r--r--libguile/hashtab.c39
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,