From: Tamas Papp
Subject: portable finalizer
Date: 
Message-ID: <87zm2don6j.fsf@pu100877.student.princeton.edu>
Hi,

I am wrapping a void * cffi pointer and some extra information in a
CLOS object.  When the object is garbage-collected, I would like to
have the memory location freed.  I have found out how to do
finalization in SBCL, but I want to make my code portable.

I have seen finalize implementations with #+ directives floating
around, could somebody post a reasonably comprehensive version?  Or is
there a library to do this?

Thanks,

Tamas

From: Edi Weitz
Subject: Re: portable finalizer
Date: 
Message-ID: <ur6npbzly.fsf@agharta.de>
On Tue, 03 Jul 2007 11:23:48 +0200, Tamas Papp <······@gmail.com> wrote:

> I have seen finalize implementations with #+ directives floating
> around, could somebody post a reasonably comprehensive version?

You can look at the source of RDNZL which includes finalizing code for
LispWorks, AllegroCL, SBCL, CLISP, and Corman Lisp.  (CMUCL is
probably similar to SBCL.)  Or you can wait for someone to do the work
for you.

Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Marco Gidde
Subject: Re: portable finalizer
Date: 
Message-ID: <87ved1abvb.fsf@tristan.br-automation.com>
Tamas Papp <······@gmail.com> writes:

> I am wrapping a void * cffi pointer and some extra information in a
> CLOS object.  When the object is garbage-collected, I would like to
> have the memory location freed.  I have found out how to do
> finalization in SBCL, but I want to make my code portable.
>
> I have seen finalize implementations with #+ directives floating
> around, could somebody post a reasonably comprehensive version?  Or is
> there a library to do this?

there is a small library out there called trivial-garbage with
finalization code for several CL implementations.


Regards,

Marco
From: Mark Hoemmen
Subject: Re: portable finalizer
Date: 
Message-ID: <f6e3us$2knl$1@geode.berkeley.edu>
Marco Gidde wrote:
> Tamas Papp <······@gmail.com> writes:
> 
>> I am wrapping a void * cffi pointer and some extra information in a
>> CLOS object.  When the object is garbage-collected, I would like to
>> have the memory location freed.  I have found out how to do
>> finalization in SBCL, but I want to make my code portable.

A related question -- are finalizers called when the object falls out of 
scope, or when a GC is called?

If the latter, how can we instruct the GC to be aware of limited 
resources (like malloc'd memory, file handles, etc.)?

mfh
From: ···@itasoftware.com
Subject: Re: portable finalizer
Date: 
Message-ID: <1183487310.008143.180830@o61g2000hsh.googlegroups.com>
On Jul 3, 2:19 pm, Mark Hoemmen <············@gmail.com> wrote:
> Marco Gidde wrote:
> > Tamas Papp <······@gmail.com> writes:
>
> >> I am wrapping a void * cffi pointer and some extra information in a
> >> CLOS object.  When the object is garbage-collected, I would like to
> >> have the memory location freed.  I have found out how to do
> >> finalization in SBCL, but I want to make my code portable.
>
> A related question -- are finalizers called when the object falls out of
> scope, or when a GC is called?

Maybe when the GC is called.  There are no general guarantees when or
if a finalizer will be called.  That's basically why they're not in
the standard.

> If the latter, how can we instruct the GC to be aware of limited
> resources (like malloc'd memory, file handles, etc.)?

Finalization is the wrong tool for this.  Look in the Lisp concept of
"resources".
From: Mark Hoemmen
Subject: Re: portable finalizer
Date: 
Message-ID: <f6e67k$2lgg$1@geode.berkeley.edu>
···@itasoftware.com wrote:
>> If the latter, how can we instruct the GC to be aware of limited
>> resources (like malloc'd memory, file handles, etc.)?
> 
> Finalization is the wrong tool for this.  Look in the Lisp concept of
> "resources".

Would you happen to have some suggested reading for this?  Googling 
"Lisp resources" brings up general reading on Lisp, and the usual 
documentation isn't helpful.

Many thanks,
mfh
From: ···@itasoftware.com
Subject: Re: portable finalizer
Date: 
Message-ID: <1183491869.276415.209070@n60g2000hse.googlegroups.com>
On Jul 3, 2:57 pm, Mark Hoemmen <············@gmail.com> wrote:
> ····@itasoftware.com wrote:
> >> If the latter, how can we instruct the GC to be aware of limited
> >> resources (like malloc'd memory, file handles, etc.)?
>
> > Finalization is the wrong tool for this.  Look in the Lisp concept of
> > "resources".
>
> Would you happen to have some suggested reading for this?  Googling
> "Lisp resources" brings up general reading on Lisp, and the usual
> documentation isn't helpful.

Not offhand, it's an old concept.  The pdf Alexey Goldin recommends
calls them storages and gives and example with-storage macro
definition.  Basically resources are the Lispy way of explicitly
managing object allocation and deallocation.  Objects are created on a
list, typically held in a defvar, and functions are implemented to
allocate and deallocate objects explicitly.   It is perfectly
reasonable for deallocation to simply clean up the object and put it
back on a free list if object construction is expensive (e.g. I did
that for processes once while working on a parallel Common Lisp
project).

Generally a wrapper macro named WITH-foo is implemented that executes
a block of code with an object allocated for it.  This works out to be
much like C++ stack allocation with constructors and destructors but
IMHO much clearer.
From: Mark H.
Subject: Re: portable finalizer
Date: 
Message-ID: <1183492277.508150.126540@x35g2000prf.googlegroups.com>
On Jul 3, 12:44 pm, ····@itasoftware.com wrote:
> Generally a wrapper macro named WITH-foo is implemented that executes
> a block of code with an object allocated for it.  This works out to be
> much like C++ stack allocation with constructors and destructors but
> IMHO much clearer.

*nods* yes, that's probably the best choice in terms of the
performance / ease-of-use tradeoff...

Many thanks!
mfh
From: Rainer Joswig
Subject: Re: portable finalizer
Date: 
Message-ID: <2007070400541916807-joswig@lispde>
On 2007-07-03 20:57:55 +0200, Mark Hoemmen <············@gmail.com> said:

> ···@itasoftware.com wrote:
>>> If the latter, how can we instruct the GC to be aware of limited
>>> resources (like malloc'd memory, file handles, etc.)?
>> 
>> Finalization is the wrong tool for this.  Look in the Lisp concept of
>> "resources".
> 
> Would you happen to have some suggested reading for this?  Googling 
> "Lisp resources" brings up general reading on Lisp, and the usual 
> documentation isn't helpful.
> 
> Many thanks,
> mfh

Lisp Machine Manual, 6th Edition
Chapter 6. Resources
http://common-lisp.net/project/bknr/static/lmman/resour.xml
(you need something like Firefox/Camino to view the contents)

-- 
http://lispm.dyndns.org/
From: Luke Crook
Subject: Re: portable finalizer
Date: 
Message-ID: <1183491160.217595.70630@z28g2000prd.googlegroups.com>
On Jul 3, 11:19 am, Mark Hoemmen <············@gmail.com> wrote:
>
> A related question -- are finalizers called when the object falls out of
> scope, or when a GC is called?
>

When the GC is called.

- Luke
From: Tamas Papp
Subject: Re: portable finalizer
Date: 
Message-ID: <87ved0o92d.fsf@pu100877.student.princeton.edu>
Marco Gidde <···········@tiscali.de> writes:

> Tamas Papp <······@gmail.com> writes:
>
>> I am wrapping a void * cffi pointer and some extra information in a
>> CLOS object.  When the object is garbage-collected, I would like to
>> have the memory location freed.  I have found out how to do
>> finalization in SBCL, but I want to make my code portable.
>>
>> I have seen finalize implementations with #+ directives floating
>> around, could somebody post a reasonably comprehensive version?  Or is
>> there a library to do this?
>
> there is a small library out there called trivial-garbage with
> finalization code for several CL implementations.

Thanks Marco,

I also found that there is a cffi:finalize that does the thing I want.

Since this thread has drifted towards resources, I have a conceptual
question.  Suppose I have a resource (eg a Cairo context in
cl-cairo2), is a pointer to a C structure.

(defclass foo () ((pointer :initform nil)))

The user has to be able to close the resource explicitly (eg in
cl-cairo2, this indicates that he has finished drawing and the file
can be closed), so there is a destroy method:

(defmethod destroy ((object foo))
  (with-slots (pointer) object
    (when pointer
      (call_c_api_to_destroy pointer)
      (setf pointer nil))))

But suppose that I also want to register a finalizer, and have the
object destroyed when it is garbage collected.  The documentation of
cffi:finalize says

  For portability reasons, function should not attempt to look at
  object by closing over it because, in some lisps, object will
  already have been garbage-collected and is therefore not accessible
  when function is invoked.

So how is the finalizer supposed to look at pointer to determine if
the resource has already been freed explicitly with destroy?

Thanks,

Tamas
From: Rudi Schlatte
Subject: Re: portable finalizer
Date: 
Message-ID: <m2ir90mnn3.fsf@constantly.at>
Tamas Papp <······@gmail.com> writes:

[...]
>
> Since this thread has drifted towards resources, I have a conceptual
> question.  Suppose I have a resource (eg a Cairo context in
> cl-cairo2), is a pointer to a C structure.
>
> (defclass foo () ((pointer :initform nil)))
>
> The user has to be able to close the resource explicitly (eg in
> cl-cairo2, this indicates that he has finished drawing and the file
> can be closed), so there is a destroy method:
>
> (defmethod destroy ((object foo))
>   (with-slots (pointer) object
>     (when pointer
>       (call_c_api_to_destroy pointer)
>       (setf pointer nil))))
>
> But suppose that I also want to register a finalizer, and have the
> object destroyed when it is garbage collected.  The documentation of
> cffi:finalize says
>
>   For portability reasons, function should not attempt to look at
>   object by closing over it because, in some lisps, object will
>   already have been garbage-collected and is therefore not accessible
>   when function is invoked.
>
> So how is the finalizer supposed to look at pointer to determine if
> the resource has already been freed explicitly with destroy?

It's not supposed to:

(defmethod destroy ((object foo))
  (with-slots (pointer) object
    (when pointer
      (call_c_api_to_destroy pointer)
      (setf pointer nil)))
  (cancel-finalization object))

Rudi
From: Tamas Papp
Subject: Re: portable finalizer
Date: 
Message-ID: <87r6noo0bq.fsf@pu100877.student.princeton.edu>
Rudi Schlatte <····@constantly.at> writes:

> Tamas Papp <······@gmail.com> writes:
>
> [...]
>>
>> Since this thread has drifted towards resources, I have a conceptual
>> question.  Suppose I have a resource (eg a Cairo context in
>> cl-cairo2), is a pointer to a C structure.
>>
>> (defclass foo () ((pointer :initform nil)))
>>
>> The user has to be able to close the resource explicitly (eg in
>> cl-cairo2, this indicates that he has finished drawing and the file
>> can be closed), so there is a destroy method:
>>
>> (defmethod destroy ((object foo))
>>   (with-slots (pointer) object
>>     (when pointer
>>       (call_c_api_to_destroy pointer)
>>       (setf pointer nil))))
>>
>> But suppose that I also want to register a finalizer, and have the
>> object destroyed when it is garbage collected.  The documentation of
>> cffi:finalize says
>>
>>   For portability reasons, function should not attempt to look at
>>   object by closing over it because, in some lisps, object will
>>   already have been garbage-collected and is therefore not accessible
>>   when function is invoked.
>>
>> So how is the finalizer supposed to look at pointer to determine if
>> the resource has already been freed explicitly with destroy?
>
> It's not supposed to:
>
> (defmethod destroy ((object foo))
>   (with-slots (pointer) object
>     (when pointer
>       (call_c_api_to_destroy pointer)
>       (setf pointer nil)))
>   (cancel-finalization object))

Thanks Rudi,

This was enlightening.

Tamas
From: Marco Gidde
Subject: Re: portable finalizer
Date: 
Message-ID: <87veczn9gw.fsf@tristan.br-automation.com>
Tamas Papp <······@gmail.com> writes:

> I also found that there is a cffi:finalize that does the thing I want.

This was the first portable FINALIZE that I used but AFAIK it is
deprecated in favour of trivial-garbage :-)


Regards,

Marco
From: Mark H.
Subject: Re: portable finalizer
Date: 
Message-ID: <1183670693.042056.181140@j4g2000prf.googlegroups.com>
On Jul 4, 1:40 am, Tamas Papp <······@gmail.com> wrote:
> (defmethod destroy ((object foo))
>   (with-slots (pointer) object
>     (when pointer
>       (call_c_api_to_destroy pointer)
>       (setf pointer nil))))

You might want to setf pointer to a null pointer instead of to NIL, so
that the type of pointer is always a C pointer.  Not a big deal but it
could be a useful invariant.

mfh
From: Rob Warnock
Subject: Re: portable finalizer
Date: 
Message-ID: <n8KdnZkGHojLWxDbnZ2dnUVZ_jidnZ2d@speakeasy.net>
Mark H. <············@gmail.com> wrote:
+---------------
| On Jul 4, 1:40 am, Tamas Papp <······@gmail.com> wrote:
| > (defmethod destroy ((object foo))
| >   (with-slots (pointer) object
| >     (when pointer
| >       (call_c_api_to_destroy pointer)
| >       (setf pointer nil))))
| 
| You might want to setf pointer to a null pointer instead of to NIL, so
| that the type of pointer is always a C pointer.  Not a big deal but it
| could be a useful invariant.
+---------------

Good point. In CMUCL, for example, NIL is certainly not a null pointer!
Nor is it a "C pointer" in the usual sense. [It has low-tag bits set.]


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: ·············@gmail.com
Subject: Re: portable finalizer
Date: 
Message-ID: <1183490095.905460.286560@m36g2000hse.googlegroups.com>
On Jul 3, 4:23 am, Tamas Papp <······@gmail.com> wrote:
> Hi,
>
> I am wrapping a void * cffi pointer and some extra information in a
> CLOS object.  When the object is garbage-collected, I would like to
> have the memory location freed.  I have found out how to do
> finalization in SBCL, but I want to make my code portable.
>
> I have seen finalize implementations with #+ directives floating
> around, could somebody post a reasonably comprehensive version?  Or is
> there a library to do this?
>
> Thanks,
>
> Tamas

You might want to look through this IMHO very useful paper:

http://p-cos.net/lisp-ecoop06/pdf/112999.pdf
From: ············@gmail.com
Subject: Re: portable finalizer
Date: 
Message-ID: <1183492058.560691.3570@e16g2000pri.googlegroups.com>
On Jul 3, 12:14 pm, ··············@gmail.com"
<·············@gmail.com> wrote:
> You might want to look through this IMHO very useful paper:
>
> http://p-cos.net/lisp-ecoop06/pdf/112999.pdf

Cool, many thanks!

I guess you could also "roll your own" resource management system
(e.g., for file handles), using reference counting and a separate
resource manager thread.  Every so often the thread runs, and disposes
of objects with a zero reference count.  Problem is, every time you
allocate a resource, you have to do thread synchronization of some
sort, but for the case "small number of scarce resources" it should be
OK.

mfh