Proposal: Automatic Resource Management

Peter Mount peter at retep.org.uk
Fri Mar 13 10:08:53 PDT 2009


On Fri, Mar 13, 2009 at 4:26 PM, Joshua Bloch <jjb at google.com> wrote:

> Matthias,
>
> Hi. This would work, but I'd have concerns about the performance. Locks
> have to be really fast.  If we want to solve the locking case (and I'm not
> so sure we do), I believe that we should do so with another construct.  I
> made a "Preproposal" for such a construct, but no one showed any enthusiasm.


I think there was some enthusiasm but Tim Peierls response about three days
ago sort of killed the discussion a bit.

Peter


>
>           Josh
>
>
> On Fri, Mar 13, 2009 at 2:47 AM, Matthias Ernst <matthias at mernst.org>wrote:
>
>> On Sun, Mar 8, 2009 at 10:39 AM, Peter Mount <peter at retep.org.uk> wrote:
>> > On Sun, Mar 8, 2009 at 9:00 AM, Reinier Zwitserloot <
>> reinier at zwitserloot.com
>> >> wrote:
>> >
>> >> We're veering waaay offtopic here; the ARM proposal does not address
>> >> locks. Period. Would everyone be happy if this was added in the 'major
>> >> disadvantages' section?
>> >
>> >
>> > Yes this is becoming more offtopic but hopefully my comments have
>> brought up
>> > two points:
>> >
>> > 1: Although Locks are a form of resource, the ARM proposal as is cannot
>> > support them
>> > 2: Someone will abuse it to support Lock's at some point with
>> potentially
>> > disastrous consequences.
>>
>> What would be the problem with:
>>
>> package j.u.c:
>> abstract class AbstractLock implements Lock {
>>  private final AutoCloseable locked = new AutoCloseable() {
>>    public void close() { AbstractLock.this.unlock(); }
>>  }
>>
>>
>>  public AutoCloseable locked() {
>>    lock();
>>    return locked;
>>  }
>> }
>>
>> Have the j.u.c locks inherit from AbstractLock.
>>
>> Add in class LockSupport:
>>  public static AutoCloseable locked(final Lock lock) {
>>    return (lock instanceof AbstractLock) ?
>> ((AbstractLock)lock).locked() : new AutoCloseable() {
>>      public void close() { lock.unlock(); }
>>    };
>>  }
>>
>> Use:
>>
>> import static LockSupport.locked;
>>
>> try(locked(guard)) {
>>
>> }
>>
>>
>> Matthias
>>
>> >
>> >
>> >>
>> >> If locks are truly deemed crucial, or the consensus is that,
>> >> eventhough evidently ARM-as-is can't do locks, people will try anyway
>> >> and the resulting confusion must be avoided, I suggest that the ARM
>> >> proposal is updated to do the right thing when an expression of type
>> >> Lock shows up in a try ( lockShowsUpHere ) { code} block. Someone else
>> >> proposed this before and I can't see any downside to this. It would be
>> >> bad if, for every release, a bunch more types get special uniquely
>> >> defined semantics in relation to the ARM expression, but that seems
>> >> very unlikely. Nobody else has named a use-case that doesn't work in
>> >> vanilla ARM yet seems likely to be abused, other than Lock, IIRC.
>> >
>> >
>> > Yes I did yesterday.
>> >
>> > The one thing I've learned from experience is that a lot of programmers
>> are
>> > lazy when it comes to resources. Although for some resources are cleaned
>> up
>> > occasionally by the garbage collector, most are not and unless the
>> system is
>> > under heavy load the problem doesn't show itself until it's in the live
>> > environment. For this reason I do feel that the ARM proposal would
>> alleviate
>> > this as long as the programmers know that the new construct exists.
>> >
>> > Now I do feel that Locks are a form of resource but one that is actively
>> > short lived. Although it seems simple to just write them manually with a
>> try
>> > finally block you'll be surprised how easy it is for someone to miss the
>> > finally block or refactor it out without noticing. In a large system
>> this
>> > can be costly (my gaming background coming in here).
>> >
>> > Over the last few years I've ended up wasting so much time debugging a
>> > complex system to locate a deadlock just to find that someone has
>> forgotten
>> > to release a lock. It is this reason why I think the ARM proposal should
>> > support Lock's as a separate use-case.
>> >
>> > The main issues with Disposable and Lock that I can see are:
>> >
>> > 1: Lock is an interface and cannot extend Disposable as that would break
>> > existing code. Also implementing Disposable in the Lock implementations
>> > would not work if you use try( Lock ) as javac would not see it as being
>> > Disposable.
>> >
>> > 2: Normal resources are already open/active before the try so with
>> > Disposable the try(Disposable) would simply call Disposable.close() at
>> the
>> > end. With Locks they are not active until lock() is called so try(Lock)
>> > would have to call Lock.lock() before the method body and then
>> Lock.unlock()
>> > at the end.
>> >
>> > As I said in an earlier email I implement this pattern in JDK1.6 by
>> having a
>> > set of annotations which with a processor inject the try...finally block
>> > around a method thats locked (yes I know annotation processors shouldn't
>> do
>> > this but it's removed the problem completely). Having the ARM proposal
>> would
>> > not just obsolete the hack but make it more flexible (as the hack only
>> works
>> > at the method level).
>> >
>> > As for any other use-cases that don't work with the current proposal
>> other
>> > than Lock, I can't think of any at the moment.
>> >
>> >
>> >>
>> >>  --Reinier Zwitserloot
>> >>
>> >>
>> >> On Mar 8, 2009, at 09:03, Peter Mount wrote:
>> >>
>> >> > On Sun, Mar 8, 2009 at 7:58 AM, Jeremy Manson
>> >> > <jeremy.manson at gmail.com>wrote:
>> >> >
>> >> >> I am aware Lock is an interface.  You wouldn't actually change the
>> >> >> Lock interface, you would change the classes.  Just as they retrofit
>> >> >> Iterable everywhere.  That's why I put "class Lock" there; perhaps
>> it
>> >> >> would have been clearer if it said "class MyLock".
>> >> >
>> >> >
>> >> > What about when someone just references the lock as Lock rather than
>> >> > the
>> >> > implementing class? Javac won't be able to determine that the lock
>> >> > implements Disposable so in that case it will fail..
>> >> >
>> >> >
>> >> >
>> >> >
>> >> >>
>> >> >>
>> >> >> Jeremy
>> >> >>
>> >> >> On Sat, Mar 7, 2009 at 10:23 AM, Stephen Colebourne
>> >> >> <jodastephen at gmail.com> wrote:
>> >> >>> Jeremy Manson wrote:
>> >> >>>> The "right" fix, if we want to support this pattern, is to allow
>> >> >>>> the
>> >> >>>> try resource statement to accept expressions that return
>> >> >>>> Disposables,
>> >> >>>> and to retrofit the relevant lock APIs with disposables and lock
>> >> >>>> methods that return this:
>> >> >>>>
>> >> >>>> class Lock implements Disposable {
>> >> >>>>  public Lock dlock() {
>> >> >>>>    return this;
>> >> >>>>  }
>> >> >>>>  @Override public void dispose() {
>> >> >>>>    unlock();
>> >> >>>>  }
>> >> >>>> }
>> >> >>>>
>> >> >>> Lock is an interface. No changes are possible.
>> >> >>>
>> >> >>> Stephen
>> >> >>>
>> >> >>>
>> >> >>>
>> >> >>
>> >> >>
>> >> >
>> >> >
>> >> > --
>> >> > Peter Mount
>> >> > e: peter at retep.org.uk
>> >> > w: http://retep.org
>> >> > Jabber/GTalk: peter at retep.org MSN: retep207 at hotmail.com
>> >> >
>> >>
>> >>
>> >>
>> >
>> >
>> > --
>> > Peter Mount
>> > e: peter at retep.org.uk
>> > w: http://retep.org
>> > Jabber/GTalk: peter at retep.org MSN: retep207 at hotmail.com
>> >
>> >
>>
>>
>


-- 
Peter Mount
e: peter at retep.org.uk
w: http://retep.org
Jabber/GTalk: peter at retep.org MSN: retep207 at hotmail.com



More information about the coin-dev mailing list