Path: csiph.com!x330-a1.tempe.blueboxinc.net!usenet.pasdenom.info!aioe.org!eternal-september.org!feeder.eternal-september.org!.POSTED!not-for-mail From: Deeyana Newsgroups: comp.lang.java.programmer Subject: Re: Making one or more threads wait for another to produce a value or fail Date: Tue, 31 May 2011 19:23:18 +0000 (UTC) Organization: A noiseless patient Spider Lines: 87 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Injection-Date: Tue, 31 May 2011 19:23:18 +0000 (UTC) Injection-Info: mx04.eternal-september.org; posting-host="JTZ1AoI4l8zXX9SkAWgFQg"; logging-data="10188"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18WynDwApzg2k5kftQCWr8+/yMVGAaWltk=" User-Agent: XanaNews/1.18.1.6 Cancel-Lock: sha1:VWbhhsoB6sOCP7cHxV0hHPq6X0g= Xref: x330-a1.tempe.blueboxinc.net comp.lang.java.programmer:4810 On Tue, 31 May 2011 16:46:55 +0100, Tom Anderson wrote: > On Tue, 31 May 2011, Peter Duniho wrote: > >> (Alternatively, you could provide a custom implementation of Future >> that doesn't wrap a Runnable like FutureTask, letting your thread >> continue even after delivering the Future…but such an implementation >> would be more complicated than just using the wait()/notifyAll() >> pattern, > > Not *that* much more complicated, i don't think. Both varieties of get > map on to calls to their corresponding variety of wait in a loop guarded > by a call to isDone, and isDone maps on to a check on whether the > verdict is delivered. cancel/isCancelled would require code over and > above the simplest wait/notify implentation, but not a lot. > > The thing that bugs me is that if this is so simple, and as generally > useful as i think it is, why isn't it in the JDK already? I don't know. But it is available in at least one other JVM language's standard library: Clojure has functions called "promise" and "deliver" for exactly this sort of scenario. Under the hood it combines a CountDownLatch with a class instance variable to hold the result and implements Clojure's IDeref interface. The Java equivalent would just be some class Promise with internal value and CountDownLatch and deliver and get methods. Deliver would decrement the CountDownLatch and set the value cell; get would see if the CountDownLatch was zero, block if it wasn't, and return the value cell's contents if it was. It would also throw InterruptedException and maybe have a version of get accepting a timeout. Something like: import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; public class Promise { T value; CountDownLatch cdl = new CountDownLatch(1); public void deliver (T value) { this.value = value; cdl.countDown(); } public T get () throws InterruptedException { cdl.await(); return value; } public T get (long timeout, TimeUnit unit) throws InterruptedException { if (cdl.await(timeout, unit)) { return value; } else { return null; } } public T get (long timeout, TimeUnit unit, T to) throws InterruptedException { if (cdl.await(timeout, unit)) { return value; } else { return to; } } public T getEx (long timeout, TimeUnit unit) throws InterruptedException { if (cdl.await(timeout, unit)) { return value; } else { throw new InterruptedException(); } } } Untested and no Javadoc but it *should* work. In particular, the docu for CountDownLatch says that value setting should "happen-before" value getting. The first timeout-accepting get method will return null on timeout. The second accepts a third parameter for the object to return on timeout. The getEx method throws an InterruptedException if it times out. I dedicate the above code into the public domain, so that it may expeditiously find its way into JDK 8 perhaps sometime around 2040 without legal obstacles. :)