diff options
author | Ludovic Courtes <ludovic.courtes@laas.fr> | 2006-05-26 13:50:21 +0000 |
---|---|---|
committer | Ludovic Courtès <ludo@gnu.org> | 2008-09-05 09:34:35 +0200 |
commit | 10fb3386dd186244becc493d83c291b9bec2075e (patch) | |
tree | 3c959fe2d9170e4e05810de4f71930a1d16c6b51 /libguile/guardians.c | |
parent | a4a141f679fa66b1538148aae8046a9f351b3216 (diff) | |
download | guile-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.c | 99 |
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); + } } } |