I knew there would be some old-dog out there that had a few tricks up his 
sleeve. Sadly, I am post-Genera generation. Thanks for chiming in there Scott. 
Gives me a lot to chew on.

- DM


> On Aug 26, 2016, at 06:17, Scott McKay <swmc...@gmail.com> wrote:
> 
> From my perspective, there are two orthogonal things going on here:
>  1. The idea of a "resource" with a well-defined protocol for allocation, 
> initialization,
>    deinitialization, and deallocation. Genera (and CLIM) had macrology for 
> this:
>    defresource to define a resource, using-resource to use it in a "safe"
>    way such that all those things happened in order.
>  2. Having let behave like using-resource.
> 
> It would be perfectly simple to write a let macro that shadows cl:let, which
> tracks allocation/initialization of resources, evaluates the body, and then 
> calls
> the deinitializer/deallocator. How you implement "resources" is up to you. :-)
> 
> 
> On Fri, Aug 26, 2016 at 7:52 AM, David McClain <d...@refined-audiometrics.com 
> <mailto:d...@refined-audiometrics.com>> wrote:
> 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 
> > <mailto: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