26 Aug
2016
26 Aug
'16
1:17 p.m.
>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 <dbm@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 <nick@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 > > > > >