1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-02 04:40:29 +02:00

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
This commit is contained in:
Ludovic Courtes 2006-05-26 13:50:21 +00:00 committed by Ludovic Courtès
parent a4a141f679
commit 10fb3386dd
5 changed files with 134 additions and 145 deletions

View file

@ -678,100 +678,8 @@ scm_gc_unregister_roots (SCM *b, unsigned long n)
int scm_i_terminating; int scm_i_terminating;
/* Finalizers. */
static void
finalizer_trampoline (GC_PTR ptr, GC_PTR data)
{
register SCM obj, finalizers;
obj = PTR2SCM (ptr);
for (finalizers = PTR2SCM (data);
scm_is_pair (finalizers);
finalizers = SCM_CDR (finalizers))
{
SCM (* finalize) (SCM, SCM);
SCM f = SCM_CAR (finalizers);
finalize = (SCM (*) (SCM, SCM)) SCM2PTR (SCM_CAR (f));
finalize (obj, SCM_CDR (f));
}
}
/* Register FINALIZER as a finalization procedure for OBJ. FINALIZER will be
invoked when storage for OBJ is to be reclaimed and will be passed OBJ and
DATA. If ORDERED is non-zero, finalization will be "ordered" (see the
Boehm-GC doc for details). The function returns the data previously
registered for OBJ and FINALIZER, or `#f' if FINALIZER had not been
registered for OBJ before.
Note that finalizers in general are known to be problematic. As such,
this function should only be used internally, and only to implement
functionalities that could not be implemented otherwise (e.g., guardians,
SMOB's free procedures). */
SCM
scm_gc_register_finalizer (SCM obj, SCM (*finalizer) (SCM, SCM),
SCM data, int ordered)
{
SCM prev_data = SCM_BOOL_F;
SCM finalization_data, finalization_subr;
GC_finalization_proc old_finalizer;
GC_PTR old_finalization_data;
/* XXX: We don't use real `subrs' here because (i) it would add unnecessary
overhead and (ii) it creates a bootstrap problem (because SMOBs may rely
on this, and SMOBs are initialized before `gsubrs'). */
finalization_subr = PTR2SCM (finalizer);
finalization_data = scm_cons (scm_cons (finalization_subr, data),
SCM_EOL);
if (ordered)
GC_REGISTER_FINALIZER (SCM2PTR (obj), finalizer_trampoline,
SCM2PTR (finalization_data),
&old_finalizer, &old_finalization_data);
else
GC_REGISTER_FINALIZER_NO_ORDER (SCM2PTR (obj), finalizer_trampoline,
SCM2PTR (finalization_data),
&old_finalizer, &old_finalization_data);
if ((old_finalizer != NULL) && (old_finalizer != finalizer_trampoline))
/* Inconsistent use of the mechanism. */
abort ();
if (old_finalization_data != NULL)
{
SCM f, prev, old_finalizer_list = PTR2SCM (old_finalization_data);
if (!scm_is_pair (old_finalizer_list))
abort ();
/* Look for FINALIZER among the previously-installed finalizers. */
for (f = old_finalizer_list, prev = SCM_BOOL_F;
scm_is_pair (f);
prev = f, f = SCM_CDR (f))
{
if (SCM_SUBRF (SCM_CAR (f)) == finalizer)
break;
}
if (scm_is_pair (f))
{
prev_data = SCM_CDAR (f);
if (prev != SCM_BOOL_F)
SCM_SETCDR (prev, SCM_CDR (f));
else
old_finalizer_list = SCM_CDR (old_finalizer_list);
}
/* Concatenate the new finalizer list with the old one. */
SCM_SETCDR (finalization_data, old_finalizer_list);
}
return prev_data;
}
/* /*
MOVE THIS FUNCTION. IT DOES NOT HAVE ANYTHING TODO WITH GC. MOVE THIS FUNCTION. IT DOES NOT HAVE ANYTHING TODO WITH GC.
*/ */

View file

@ -235,8 +235,6 @@ SCM_API void *scm_gc_realloc (void *mem, size_t old_size,
SCM_API void scm_gc_free (void *mem, size_t size, const char *what); SCM_API void scm_gc_free (void *mem, size_t size, const char *what);
SCM_API char *scm_gc_strdup (const char *str, const char *what); SCM_API char *scm_gc_strdup (const char *str, const char *what);
SCM_API char *scm_gc_strndup (const char *str, size_t n, const char *what); SCM_API char *scm_gc_strndup (const char *str, size_t n, const char *what);
SCM_API SCM scm_gc_register_finalizer (SCM obj, SCM (*finalizer) (SCM, SCM),
SCM data, int ordered);
SCM_API void scm_remember_upto_here_1 (SCM obj); SCM_API void scm_remember_upto_here_1 (SCM obj);
SCM_API void scm_remember_upto_here_2 (SCM obj1, SCM obj2); SCM_API void scm_remember_upto_here_2 (SCM obj1, SCM obj2);

View file

@ -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 /* Handle finalization of OBJ which is guarded by the guardians listed in
GUARDIAN_LIST. */ GUARDIAN_LIST. */
static SCM static void
finalize_guarded (SCM obj, SCM guardian_list) finalize_guarded (GC_PTR ptr, GC_PTR finalizer_data)
{ {
SCM cell_pool; 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 #if 0
printf ("finalizing guarded %p (%u guardians)\n", printf ("finalizing guarded %p (%u guardians)\n",
SCM2PTR (obj), scm_to_uint (scm_length (guardian_list))); ptr, scm_to_uint (scm_length (guardian_list)));
scm_write (guardian_list, scm_current_output_port ());
#endif #endif
/* Preallocate a bunch of cells so that we can make sure that no garbage /* 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); cell_pool = SCM_CDR (cell_pool);
/* Compute and update G's zombie list. */ /* Compute and update G's zombie list. */
SCM_SETCAR (zombies, obj); SCM_SETCAR (zombies, SCM_PACK (obj));
SCM_SETCDR (zombies, g->zombies); SCM_SETCDR (zombies, g->zombies);
g->zombies = zombies; g->zombies = zombies;
@ -138,11 +142,30 @@ finalize_guarded (SCM obj, SCM guardian_list)
g->zombies = zombies; g->zombies = zombies;
} }
#if 0 if (proxied_finalizer != SCM_BOOL_F)
printf ("end of finalize (%p)\n", SCM2PTR (obj)); {
#endif /* 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;
return SCM_UNSPECIFIED; 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 (" reinstalled proxied finalizer %p for %p\n", finalizer, ptr);
#endif
}
#if 0
printf ("end of finalize (%p)\n", ptr);
#endif
} }
/* Add OBJ as a guarded object of GUARDIAN. */ /* 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); 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 /* Register a finalizer and pass a pair as the ``client data''
as the ``client data'' argument. */ argument. The pair contains in its car `#f' or a pair describing a
SCM guardians_for_obj, prev_guardians_for_obj; ``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++; g->live++;
guardians_for_obj = scm_cons (guardian, SCM_EOL); guardians_for_obj = scm_cons (guardian, SCM_EOL);
finalizer_data = scm_cons (SCM_BOOL_F, guardians_for_obj);
prev_guardians_for_obj = GC_REGISTER_FINALIZER_NO_ORDER (SCM2PTR (obj), finalize_guarded,
scm_gc_register_finalizer (obj, finalize_guarded, SCM2PTR (finalizer_data),
guardians_for_obj, 0); &prev_finalizer, &prev_data);
if (scm_is_pair (prev_guardians_for_obj)) if (prev_finalizer == finalize_guarded)
/* Concatenate the previous list of guardians for OBJ. */ {
SCM_SETCDR (guardians_for_obj, prev_guardians_for_obj); /* 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);
}
} }
} }

View file

@ -604,16 +604,21 @@ scm_i_new_smob_with_mark_proc (scm_t_bits tc, scm_t_bits data1,
/* Finalize SMOB by calling its SMOB type's free function, if any. */ /* Finalize SMOB by calling its SMOB type's free function, if any. */
SCM void
scm_i_finalize_smob (SCM smob, SCM data) scm_i_finalize_smob (GC_PTR ptr, GC_PTR data)
{ {
SCM smob;
size_t (* free_smob) (SCM); size_t (* free_smob) (SCM);
smob = PTR2SCM (ptr);
#if 0
printf ("finalizing SMOB %p (smobnum: %u)\n",
ptr, SCM_SMOBNUM (smob));
#endif
free_smob = scm_smobs[SCM_SMOBNUM (smob)].free; free_smob = scm_smobs[SCM_SMOBNUM (smob)].free;
if (free_smob) if (free_smob)
free_smob (smob); free_smob (smob);
return SCM_UNSPECIFIED;
} }

View file

@ -25,6 +25,9 @@
#include "libguile/__scm.h" #include "libguile/__scm.h"
#include "libguile/print.h" #include "libguile/print.h"
#include <gc/gc.h>
/* This is the internal representation of a smob type */ /* This is the internal representation of a smob type */
@ -60,8 +63,15 @@ do \
0, 0) \ 0, 0) \
: scm_cell (tc, (scm_t_bits)(data))); \ : scm_cell (tc, (scm_t_bits)(data))); \
if (scm_smobs[_smobnum].free) \ if (scm_smobs[_smobnum].free) \
scm_gc_register_finalizer ((z), scm_i_finalize_smob, \ { \
SCM_BOOL_F, 0); \ GC_finalization_proc _prev_finalizer; \
GC_PTR _prev_finalizer_data; \
\
GC_REGISTER_FINALIZER_NO_ORDER (SCM2PTR (z), scm_i_finalize_smob, \
NULL, \
&_prev_finalizer, \
&_prev_finalizer_data); \
} \
} \ } \
while (0) while (0)
@ -92,8 +102,15 @@ do \
(scm_t_bits)(data2), \ (scm_t_bits)(data2), \
(scm_t_bits)(data3))); \ (scm_t_bits)(data3))); \
if (scm_smobs[_smobnum].free) \ if (scm_smobs[_smobnum].free) \
scm_gc_register_finalizer ((z), scm_i_finalize_smob, \ { \
SCM_BOOL_F, 0); \ GC_finalization_proc _prev_finalizer; \
GC_PTR _prev_finalizer_data; \
\
GC_REGISTER_FINALIZER_NO_ORDER (SCM2PTR (z), scm_i_finalize_smob, \
NULL, \
&_prev_finalizer, \
&_prev_finalizer_data); \
} \
} \ } \
while (0) while (0)
@ -139,7 +156,7 @@ SCM_API long scm_numsmob;
SCM_API scm_smob_descriptor scm_smobs[]; SCM_API scm_smob_descriptor scm_smobs[];
SCM_API void scm_i_set_smob_flags (SCM x, scm_t_bits data); SCM_API void scm_i_set_smob_flags (SCM x, scm_t_bits data);
SCM_API SCM scm_i_finalize_smob (SCM smob, SCM data); SCM_API void scm_i_finalize_smob (GC_PTR obj, GC_PTR data);