summaryrefslogtreecommitdiff
path: root/libguile/guardians.c
diff options
context:
space:
mode:
authorLudovic Courtes <ludovic.courtes@laas.fr>2006-05-26 13:50:21 +0000
committerLudovic Courtès <ludo@gnu.org>2008-09-05 09:34:35 +0200
commit10fb3386dd186244becc493d83c291b9bec2075e (patch)
tree3c959fe2d9170e4e05810de4f71930a1d16c6b51 /libguile/guardians.c
parenta4a141f679fa66b1538148aae8046a9f351b3216 (diff)
downloadguile-10fb3386dd186244becc493d83c291b9bec2075e.tar.gz
Fixed use of finalizers for guardians and SMOBs (undoes patches 23-24).
* libguile/gc.c (finalizer_trampoline): Removed. (scm_gc_register_finalizer): Removed (undoes patches 23 and 24). * libguile/gc.h (scm_gc_register_finalizer): Removed. * libguile/guardians.c (finalize_guarded): Undid patch 23. Added support for "proxied finalizers". (scm_i_guard): Likewise. * libguile/smob.c (scm_i_finalize_smob): Adapted to `GC_finalization_proc'. * libguile/smob.h: Include <gc/gc.h>. (SCM_NEWSMOB): Use `GC_REGISTER_FINALIZER_NO_ORDER' instead of `scm_gc_register_finalizer ()'. (SCM_NEWSMOB3): Likewise. (scm_i_finalize_smob): Updated. git-archimport-id: lcourtes@laas.fr--2005-libre/guile-core--boehm-gc--1.9--patch-29
Diffstat (limited to 'libguile/guardians.c')
-rw-r--r--libguile/guardians.c99
1 files changed, 80 insertions, 19 deletions
diff --git a/libguile/guardians.c b/libguile/guardians.c
index b73da5467..649ed7820 100644
--- a/libguile/guardians.c
+++ b/libguile/guardians.c
@@ -96,15 +96,19 @@ guardian_print (SCM guardian, SCM port, scm_print_state *pstate SCM_UNUSED)
/* Handle finalization of OBJ which is guarded by the guardians listed in
GUARDIAN_LIST. */
-static SCM
-finalize_guarded (SCM obj, SCM guardian_list)
+static void
+finalize_guarded (GC_PTR ptr, GC_PTR finalizer_data)
{
SCM cell_pool;
+ SCM obj, guardian_list, proxied_finalizer;
+
+ obj = PTR2SCM (ptr);
+ guardian_list = SCM_CDR (PTR2SCM (finalizer_data));
+ proxied_finalizer = SCM_CAR (PTR2SCM (finalizer_data));
#if 0
printf ("finalizing guarded %p (%u guardians)\n",
- SCM2PTR (obj), scm_to_uint (scm_length (guardian_list)));
- scm_write (guardian_list, scm_current_output_port ());
+ ptr, scm_to_uint (scm_length (guardian_list)));
#endif
/* Preallocate a bunch of cells so that we can make sure that no garbage
@@ -130,7 +134,7 @@ finalize_guarded (SCM obj, SCM guardian_list)
cell_pool = SCM_CDR (cell_pool);
/* Compute and update G's zombie list. */
- SCM_SETCAR (zombies, obj);
+ SCM_SETCAR (zombies, SCM_PACK (obj));
SCM_SETCDR (zombies, g->zombies);
g->zombies = zombies;
@@ -138,11 +142,30 @@ finalize_guarded (SCM obj, SCM guardian_list)
g->zombies = zombies;
}
+ if (proxied_finalizer != SCM_BOOL_F)
+ {
+ /* Re-register the finalizer that was in place before we installed this
+ one. */
+ GC_finalization_proc finalizer, prev_finalizer;
+ GC_PTR finalizer_data, prev_finalizer_data;
+
+ finalizer = (GC_finalization_proc) SCM2PTR (SCM_CAR (proxied_finalizer));
+ finalizer_data = SCM2PTR (SCM_CDR (proxied_finalizer));
+
+ if (finalizer == NULL)
+ abort ();
+
+ GC_REGISTER_FINALIZER_NO_ORDER (ptr, finalizer, finalizer_data,
+ &prev_finalizer, &prev_finalizer_data);
+
#if 0
- printf ("end of finalize (%p)\n", SCM2PTR (obj));
+ printf (" reinstalled proxied finalizer %p for %p\n", finalizer, ptr);
#endif
+ }
- return SCM_UNSPECIFIED;
+#if 0
+ printf ("end of finalize (%p)\n", ptr);
+#endif
}
/* Add OBJ as a guarded object of GUARDIAN. */
@@ -151,22 +174,60 @@ scm_i_guard (SCM guardian, SCM obj)
{
t_guardian *g = GUARDIAN_DATA (guardian);
- if (!SCM_IMP (obj))
+ if (SCM_NIMP (obj))
{
- /* Register a finalizer and pass a list of guardians interested in OBJ
- as the ``client data'' argument. */
- SCM guardians_for_obj, prev_guardians_for_obj;
+ /* Register a finalizer and pass a pair as the ``client data''
+ argument. The pair contains in its car `#f' or a pair describing a
+ ``proxied'' finalizer (see below); its cdr contains a list of
+ guardians interested in OBJ.
+
+ A ``proxied'' finalizer is a finalizer that was registered for OBJ
+ before OBJ became guarded (e.g., a SMOB `free' function). We are
+ assuming here that finalizers are only used internally, either at
+ the very beginning of an object's lifetime (e.g., see `SCM_NEWSMOB')
+ or by this function. */
+ GC_finalization_proc prev_finalizer;
+ GC_PTR prev_data;
+ SCM guardians_for_obj, finalizer_data;
g->live++;
guardians_for_obj = scm_cons (guardian, SCM_EOL);
-
- prev_guardians_for_obj =
- scm_gc_register_finalizer (obj, finalize_guarded,
- guardians_for_obj, 0);
-
- if (scm_is_pair (prev_guardians_for_obj))
- /* Concatenate the previous list of guardians for OBJ. */
- SCM_SETCDR (guardians_for_obj, prev_guardians_for_obj);
+ finalizer_data = scm_cons (SCM_BOOL_F, guardians_for_obj);
+
+ GC_REGISTER_FINALIZER_NO_ORDER (SCM2PTR (obj), finalize_guarded,
+ SCM2PTR (finalizer_data),
+ &prev_finalizer, &prev_data);
+
+ if (prev_finalizer == finalize_guarded)
+ {
+ /* OBJ is already guarded by another guardian: add GUARDIAN to its
+ list of guardians. */
+ SCM prev_guardian_list, prev_finalizer_data;
+
+ if (prev_data == NULL)
+ abort ();
+
+ prev_finalizer_data = PTR2SCM (prev_data);
+ if (!scm_is_pair (prev_finalizer_data))
+ abort ();
+
+ prev_guardian_list = SCM_CDR (prev_finalizer_data);
+ SCM_SETCDR (guardians_for_obj, prev_guardian_list);
+
+ /* Also copy information about proxied finalizers. */
+ SCM_SETCAR (finalizer_data, SCM_CAR (prev_finalizer_data));
+ }
+ else if (prev_finalizer != NULL)
+ {
+ /* There was already a finalizer registered for OBJ so we will
+ ``proxy'' it, i.e., record it so that we can re-register it once
+ `finalize_guarded ()' has finished. */
+ SCM proxied_finalizer;
+
+ proxied_finalizer = scm_cons (PTR2SCM (prev_finalizer),
+ PTR2SCM (prev_data));
+ SCM_SETCAR (finalizer_data, proxied_finalizer);
+ }
}
}