Hi,
I've been writing a wrapper to libbz2 using trivial-gray-streams and
cffi. It is a stream you create by giving it another stream, then read
from as usual and it decompresses on the fly. Finally, calling close on
it cleans up state and also deallocates some foreign buffers which I
allocated with cffi.
The question is whether the "close" bit can be made optional. I
understand that clos doesn't have destructors on purpose because lisp is
supposed to hide the memory management from you, but clearly there's some
cleanup that my code has to do in order not to leak memory (unless
buffers created with cffi:foreign-alloc are automatically GC'ed, but I
can't find that in the docs).
Is there any way to do this? It seems ugly to force users to call close
on the stream in order to avoid memory leaks - so C-like! :D
Rupert
Rupert Swarbrick wrote:
> Hi,
>
> I've been writing a wrapper to libbz2 using trivial-gray-streams and
> cffi. It is a stream you create by giving it another stream, then read
> from as usual and it decompresses on the fly. Finally, calling close on
> it cleans up state and also deallocates some foreign buffers which I
> allocated with cffi.
>
> The question is whether the "close" bit can be made optional. I
> understand that clos doesn't have destructors on purpose because lisp is
> supposed to hide the memory management from you, but clearly there's some
> cleanup that my code has to do in order not to leak memory (unless
> buffers created with cffi:foreign-alloc are automatically GC'ed, but I
> can't find that in the docs).
No, the real reason is that destructors are not guaranteed to ever be
called at all (because a garbage collector cannot guarantee to ever
collect an object at all). This means that destructors don't provide
enough semantic guarantees, so should be used sparingly.
> Is there any way to do this? It seems ugly to force users to call close
> on the stream in order to avoid memory leaks - so C-like! :D
http://www.cliki.net/trivial-garbage
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
On Tue, 11 Dec 2007 16:44:32 +0100, Pascal Costanza wrote:
> No, the real reason is that destructors are not guaranteed to ever be
> called at all (because a garbage collector cannot guarantee to ever
> collect an object at all). This means that destructors don't provide
> enough semantic guarantees, so should be used sparingly.
Oh, ok. That makes sense.
>> Is there any way to do this? It seems ugly to force users to call close
>> on the stream in order to avoid memory leaks - so C-like! :D
>
> http://www.cliki.net/trivial-garbage
I'm probably being stupid, but I can't see how this would help! Can you
give a pseudo-code explanation maybe? I'm confused...
Rupert
Rupert Swarbrick <··········@gmail.com> writes:
>>> Is there any way to do this? It seems ugly to force users to call close
>>> on the stream in order to avoid memory leaks - so C-like! :D
>>
>> http://www.cliki.net/trivial-garbage
>
> I'm probably being stupid, but I can't see how this would help! Can you
> give a pseudo-code explanation maybe? I'm confused...
You can attach a finalizer (a function) to your stream (or any other
object). That function will be invoked when the stream is garbage
collected and you can use it to free your foreign memory at that point.
SBCL's manual has some examples:
<http://www.sbcl.org/manual/Garbage-Collection.html>
--
Luís Oliveira
http://student.dei.uc.pt/~lmoliv/
Rupert Swarbrick wrote:
> On Tue, 11 Dec 2007 16:44:32 +0100, Pascal Costanza wrote:
>> No, the real reason is that destructors are not guaranteed to ever be
>> called at all (because a garbage collector cannot guarantee to ever
>> collect an object at all). This means that destructors don't provide
>> enough semantic guarantees, so should be used sparingly.
>
> Oh, ok. That makes sense.
>
>>> Is there any way to do this? It seems ugly to force users to call close
>>> on the stream in order to avoid memory leaks - so C-like! :D
>> http://www.cliki.net/trivial-garbage
>
> I'm probably being stupid, but I can't see how this would help! Can you
> give a pseudo-code explanation maybe? I'm confused...
trivial-garbage doesn't only give you a common API for weak pointers,
but also for finalizers. Finalizers are the things you're looking for,
they allow you to add functions to objects that are triggered once they
are garbage collected.
There are some test cases in the download. You can probably also find
examples in the documentations of the several CL implementations (and
the source code of trivial-garbage helps you to find out about the names
to look for in the documentations).
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
Den Tue, 11 Dec 2007 15:23:45 +0000 skrev Rupert Swarbrick:
> Is there any way to do this? It seems ugly to force users to call close
> on the stream in order to avoid memory leaks - so C-like! :D
In addition to what's been said in the other responses, WITH-OPEN-STREAM,
which is infinitely better an interface than anything C could provide. It
makes getting streams management right fairly trivial.
Cheers,
Maciej
In article <············@news.net.uni-c.dk>,
Maciej Katafiasz <········@gmail.com> wrote:
> Den Tue, 11 Dec 2007 15:23:45 +0000 skrev Rupert Swarbrick:
>
> > Is there any way to do this? It seems ugly to force users to call close
> > on the stream in order to avoid memory leaks - so C-like! :D
>
> In addition to what's been said in the other responses, WITH-OPEN-STREAM,
> which is infinitely better an interface than anything C could provide. It
> makes getting streams management right fairly trivial.
>
> Cheers,
> Maciej
Right. That's similar to a destructor that gets called in C++
when you leave a dynamic scope. In Common Lisp one uses
UNWIND-PROTECT, which is used in WITH-OPEN-STREAM. Using
macros, one can create new WITH-... constructs which
do some cleanup when the program leaves the enclosed scope.
--
http://lispm.dyndns.org/