Yes, finalizers can sometimes work. I have those in place. But they are tricky. 
Suppose I hand off a local channel to another thread to utilize of 
communication between us. Now there are two copies of that channel pointer. So 
when my local use goes out of scope, there is still one copy in use, by that 
thread. And that thread is likely just hanging, waiting for something to come 
across that channel, that never will, since it just went out of scope from the 
sending side. Hence GC will never have the opportunity to finalize.

Instead, you have to invent contorted references to the channel that can be 
neutralized by the sender when it goes out of scope.  And I say contorted 
because these references have to be complex enough that the compiler won’t 
perform some stack optimization and produce an inadvertent secondary reference.

So, for example, it isn’t sufficient to make a reference to a channel as (list 
ch) / (car ch). That seems to become unwrapped at the receiver side by things 
like handler-case, ignore-errors. Rather you have to use a functional closure 
like (lambda () ch) / funcall. And now we’ve lost the symmetry of use on each 
side of the channel. 

Not only that, but now we have to understand Lisp implementation details that 
we never needed to know before. And so we likely aren’t semantically portable.

Secondly, as you mentioned, not all Lisp support finalization, or not very 
well. Lispworks does fine, but I find SBCL particularly weak in that you only 
get told about an object being scavenged after it has already happened. Hence 
you have to keep a display array and use indirect references in SBCL.

What I recall from C++ world is that the automatic destructor calls at scope 
exit only happen on stack allocated objects, not pointers. Makes sense, since 
pointers allow for the possibility of alias pointers all over the place. Well, 
that’s exactly the situation we have in most Lisps too. In fact there can be no 
such thing as a stack allocated object, even if it really is allocated on the 
stack.

So then we have to invent reference counting to be sure we don’t destroy a 
shared object pointer too soon.

What I’m asking for really isn’t safe in Lisp. The best we can do, it seems, is 
what David proposes with his Scope macro, or my WITH- / UNWIND-PROTECT.

- DM


> On Aug 25, 2016, at 22:42, Nick Levine <n...@nicklevine.org> wrote:
> 
> Would finalisers do the trick? 
> 
> Not part of the language itself, but many implementations support them. 
> 
> Various caveats apply. In particular you cannot guarantee when (or I guess 
> whether) any particular resource will be finalised; only that the GC will get 
> around to most resources in the fullness of time. So this solution might not 
> meet your needs. 
> 
> - nick
> 


Reply via email to