Proposal: Automatic Resource Management

Joshua Bloch jjb at google.com
Fri Mar 13 09:26:09 PDT 2009


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.

          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
> >
> >
>
>



More information about the coin-dev mailing list