Re: add-finalizer!

Martin Gasbichler <[email protected]> Wed, 28 Jun 2006 09:07:22 +0200
Newsgroups gmane.lisp.scheme.scsh
Message-ID <[email protected]>
"Emilio Lopes" <[email protected]> writes:

> I have here some objects whose creation involves starting external
> processes.  I would like these processes to be properly shut down when
> the corresponding objects are garbage-collected.
>
> So I tried using `add-finalizer!' for this purpose and couldn't get it
> to work.  Here is an example:
>
>    Welcome to scsh 0.6.7 (RC 1)
>    Type ,? for help.
>    > ,open define-record-types primitives
>    > (define-record-type foo :foo
>        (really-make-foo x)
>        (x foo:x))
>    > (define bar #f)
>    > (define (make-foo x)
>        (let ((new-foo (really-make-foo x)))
>          (add-finalizer! new-foo
>                          (lambda (obj)
>                            (set! bar 1)))
>          new-foo))
>    > (make-foo 43)
>    '#{Foo}
>    > ,collect
>    Before: 10608482 words free in semispace
>    After:  10673414 words free in semispace
>    > bar
>    #f
>    >
>
> I was expecting `bar' to be 1 at this point.  The same example works
> as expected under Scheme 48 1.3.
>
> Isn't this the way it's supposed to work?

The problem is that NEW-FOO is part of the closure that you pass as
the finializer and thus can never be GCed (since the finalizer closure
is always alive, NEW-FOO is always alive).

You therefore need to re-write your code as follows:

Welcome to scsh 0.6.7 (R6RS)
Type ,? for help.
>  ,open define-record-types primitives
> (define-record-type foo :foo
       (really-make-foo x)
       (x foo:x))
> (define bar #f)
> (define (finalize-foo! a-foo) (set! bar 1))
> (define (make-foo x)  
    (let ((new-foo (really-make-foo x)))
      (add-finalizer! new-foo finalize-foo!)
      new-foo))
> (make-foo 43)
'#{Foo}
> ,collect
Before: 1204331 words free in semispace
After:  1294606 words free in semispace
>  bar
#f                    [1]
>  ,collect
Before: 1287285 words free in semispace
After:  1295642 words free in semispace
>  bar
1


Your code works as expected in S48 1.3 because S48 1.3 uses a
different environment representation where only needed variables are
contained in a closure's environment.


Footnotes: 
[1]  the finalizer did not run here because the focus object (##) is bound to {Foo}


-- 
Martin