Proposal: Automatic Resource Management

Xavi Miró xmirog at gmail.com
Sat Mar 7 07:09:20 PST 2009


Peter,

   good point, there would be a lot of objects. Maybe a better adapter 
would be one similar to your example, but that doesn't lock in the 
constructor and which returns its instance when locks:

public class SafeUnlocker implements Disposable {

 private final Lock lock;

 public SafeUnlocker(Lock lock){
   this.lock = lock;
 }

 public SafeUnlocker lock(){
   this.lock.lock();
   return this;
 }

 public void close throws Exception {
   this.lock.unlock();
 }
}

...so it could be used this way:

// -- This could be used as a private field or as a variable
// -- It doesn't lock when it's built, only when its lock method is invoked
SafeUnlocker myUnlocker = new SafeUnlocker(myLock);
...
...
try (myUnlocker.lock()) {
    // access the resource protected by myLock
}

But I would like to emphasize that the benefits of using this proposal 
are huge without direct support for Locks. Josh has made very clear it 
is not intended to be used with Locks.

  Regards,

     Xavi

Peter Mount escribió:
>
>
> On Sat, Mar 7, 2009 at 10:02 AM, Xavi Miró <xmirog at gmail.com 
> <mailto:xmirog at gmail.com>> wrote:
>
>     Neal,
>
>       this proposal tries to achieve big benefits with small changes.
>     In my
>     opinion, Streams, Readers, Writers, Formatters, Channels, Sockets,
>     Connections, Statements, ResultSets, or java.awt.Graphics are much
>     more
>     used than Locks. This does not mean that Locks are not important.
>     If the
>     proposal can be applied to the formers it will be a huge benefit,
>     although Locks can't be used directly with it.
>
>       I agree with Bob, adapters can be used for many use cases where
>     "close" methods are incompatible with the Disposable or Resource
>     interface. And although the proposal is not designed to manage Locks,
>     perhaps a kind of "safe unlocker" can be easily made, so this
>     original code:
>
>         myLock.lock();
>         try {
>             // access the resource protected by myLock
>         } finally {
>             myLock.unlock();
>         }
>
>     could be written this way:
>
>         try (SafeUnlocker = new SafeUnlocker(myLock)) {
>             // access the resource protected by myLock
>         }
>
>     where SafeUnlocker would be more or less like this:
>
>     public class SafeUnlocker implements Disposable {
>
>      private final Lock lock;
>
>      public SafeUnlocker(Lock lock){
>        this.lock = lock;
>        lock.lock();
>      }
>
>      public void close throws Exception {
>        lock.unlock();
>      }
>     }
>
>     The name SafeUnlocker maybe it's not appropriate, but I haven't
>     found a
>     better one. There can be problems in this source code that I haven't
>     seen...this is only an idea.
>
>      Regards,
>
>          Xavi
>
>
> I use the concurrency package extensively, mainly within a high load 
> online gaming environment and I would be concerned about the overhead 
> of the large number of SafeUnlocker instances generated, their effects 
> with the Garbage Collector and the increase in the memory footprint 
> when the locks are used recursively (ReentrantLock and 
> ReadWriteReentrantLock) - please correct me if I'm wrong here.
>
> The only way I can see my concerns satisfied would be to use something 
> like:
>
> public class DisposableLock implements Disposable {
>
>  private final Lock lock;
>
>  public DisposableLock(Lock lock){
>    this.lock = lock;
>    lock.lock();
>  }
>
>  public void close throws Exception {
>    lock.unlock();
>  }
> }
>
> Then in my useage:
>
> final DisposableLock lock = new DisposableLock( new ReentrantLock() );
>
> public void method()
> {
>    try ( lock ) {
>         // access the resource protected by lock
>     }
> }
>
> That would account for a simple ReentrantLock, but for 
> ReentrantReadWriteLock we could then use something like:
>
> final ReadWriteLock lock = new ReentrantReadWriteLock();
> final DisposableLock readLock = new DisposableLock( lock.readLock() );
> final DisposableLock writeLock = new DisposableLock( lock.writeLock() );
>
> public void method()
> {
>    try ( readLock ) {
>         // access the resource protected by the read lock
>     }
> }
>
> public void setSomething()
> {
>    try ( writeLock ) {
>         // access the resource protected by the write lock
>     }
> }
>
> It does make the code a lot easier to read, and is cleaner than how I 
> currently do something similar in 1.6 - naughtily using an annotation 
> processor to inject a try {} finally {} around the locked methods.
>
> Peter
>
> -- 
> Peter Mount
> e: peter at retep.org.uk <mailto:peter at retep.org.uk>
> w: http://retep.org
> Jabber/GTalk: peter at retep.org <mailto:peter at retep.org> MSN: 
> retep207 at hotmail.com <mailto:retep207 at hotmail.com>




More information about the coin-dev mailing list