Proposal: Automatic Resource Management (original) (raw)

Neal Gafter neal at gafter.com
Fri Mar 13 09:54:45 PDT 2009


I agree that one might want to avoid this construct in performance critical code, and I also agree that it probably doesn't make sense to add a construct that addresses locks in particular (but only locks). I think Jeremy was right when he suggested that locks are being discussed as a proxy for a category of resources that are not well handled by the proposal in its current form.

On Fri, Mar 13, 2009 at 9:26 AM, 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.  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