I think we are trying to accommodate any of several GC systems to be
selected amongst in future.
Ken Fox <[EMAIL PROTECTED]> wrote:
> John Tobey wrote:
> > Picture this. A Lisp (or Java, ...) structure holds a Perl
> > interpreter. A Perl variable holds a reference to the Lisp structure.
> > Structure and interpreter become inaccessible to all threads. Perl
> > will never know it's done with the Lisp structure, neither Perl nor
> > the structure will ever be collected, and we will have defeated
> > mark-and-sweep.
>
> In the normal case, lisp runs the finalizer when the perl structure
> becomes garbage. In the finalizer, perl can erase the external
> reference and then next time perl collects, the structure may be
> marked as garbage. If you're talking about the situation where
> an object is only reachable through a pointer held by an external
> system, then lisp needs to use a two-phase finalization. First it
> tells the foreign system (perl) that the object is considered
> garbage except for the foreign reference. That allows perl to release
> the reference and then the object really does become garbage. If perl
> decides not to release, then the object remains a weak root. This is
> a really weird situation though and I wouldn't be surprised if most
> systems just ignore the possibility. Did you ever have this problem
> or is it contrived?
I personally guarantee the issue will arise. :-)
> Foreign references are not swept and can't be swept unless you
> are building a gc system for non-cooperative environments (Boehm's
> collector for example) and they have a *lot* of constraints that
> most lisp systems I know of violate. The theoretical cycle won't
> be found.
Alas, I don't have a CS background. But I have implemented garbage
collection glue between Perl and Lisp. Here's my finalizer. As far
as I know, it is safe and complete, but the code has never been
heavily tested, to my knowledge. This implementation does not have
the concept of weak roots. Every blessed Emacs::Lisp::Object holds a
mark slot within the perl-interpreter object, and perl-interpreter's
mark method marks them all.
/* Called from Fgarbage_collect. */
static void
lisp_sv_destroy (object)
Lisp_Object object;
{
struct emacs_perl_interpreter *perl;
SV *sv;
/* Check the interpreter's status to avoid a crash after `perl-destruct'.
During Emacs destruction, even this is dangerous.
(The solution is to call `perl-destruct' *before* Emacs starts to
destruct.) */
if (EQ (emacs_phase, Qdestructing))
return;
perl = LISP_SV_INTERP (object);
if (PERL_DEFUNCT_P (perl)
|| EQ (perl->phase, Qdestructing))
return;
sv = (SV *) XFOREIGN_OBJECT (object)->data;
if (SvREFCNT (sv) > 1 || ! perl->frame_p || ! SvROK (sv))
{
SvREFCNT_dec (sv);
return;
}
call_perl (SV_FREE, sv);
}
-John