[concurrency-interest] InterruptedException-free wrappers for calls that "will never be interrupted"

Joe Bowbeer joe.bowbeer at gmail.com
Thu Apr 8 13:57:18 EDT 2010


I think the proper choice depends on the intent:

Are you expecting the thread waiting on the future to be interrupted (but
want to keep waiting regardless), or are you trying to hide the interrupted
exception in your API (because the waiting thread will never be
interrupted)?

Based on the subject of this message, I assume the waiting thread will never
be interrupted.

If so, then rethrowing IE as a RuntimeException (e.g. IllegalStateException)
seems like the right thing to do.  Ideally, this policy would be designed
into your higher-level API.  Of the options you list at the system level, I
prefer a static tool class method, such as Futures.getUninterruptibly.

The former (waiting regardless and then reasserting) is not responsive to
interrupts.  This seems more specialized, and would not be applicable to
most Futures in practice.

Note that if you convert the future to send a result-bearing event when its
done, then get isn't needed.  Moving the problem somewhere else...

Joe

On Thu, Apr 8, 2010 at 9:46 AM, Chris Povirk <cpovirk at google.com> wrote:

> My goal is a family of operations like these:
>
> // Neither of these throws InterruptedException.
> V result = Futures.getUninterruptibly(future);
> CountDownLatches.awaitUninterruptibly(latch);
>
> These methods would retry the operation until it completes without
> interruption and then restore the interrupt.  (Another option is to
> wrap the InterruptedException in a custom InterruptedRuntimeException
> class; I'd be happy to hear people's opinions on this, as well.)
>
> Google has implementations of some of these operations, and we're
> planning to expand our coverage and release them in our open-source
> Guava project.  However, we're uncertain about a few issues.
>
> Below I've listed the two main decisions we need to make along with a
> number of pros and cons for each of their options.
>
>
> Decision A: The interface to these uninterruptible methods could take
> one of three forms:
> 1. Static Futures.getUninterruptibly methods.
> 2. A static uninterruptibleFuture method that returns an
> UninterruptibleFuture, which adds getUninterruptibly methods to
> Future.
> 3. A static uninterruptibleFuture method that returns an
> UninterruptibleFuture, which overrides Future's get methods to no
> longer throw InterruptedException.
>
> (1) requires the fewest method declarations.
>
> The method declarations from (1) are likely to be jumbled together
> with unrelated declarations.  A person who sees
> BlockingQueues.putUninterruptibly, takeUninterruptibly,
> offerUninterruptibly, and pollUninterruptibly may get the impression
> that the BlockingQueues contains only InterruptedException-removing
> methods, when perhaps it contains methods like takeMultiple(Queue<E>,
> int).  Plus, subclassing is awkward: does BlockingDeques provide a
> static putUninterruptibly method, too?  (An alternative is to put
> methods for all interfaces in a single Uninterruptibles class.)
>
> (1) is the best solution for classes with final methods (notably
> Thread.join).  Even (2) suffers from this problem:
> joinUninterruptibly() would join the delegate thread, as desired, but
> join() (which we can't override) would join the unstarted wrapper
> thread.  This is confusing.  Luckily, Thread.join and other primitives
> are used less frequently than they used to be, especially among the
> kind of people that I hope will use the uninterruptible wrappers.
> (Related: Developers who want to make their methods final can define
> interfaces so that we don't need to override the class's methods.)
>
> Declaring a variable or field to be an UninterruptibleFuture (possible
> in (2) or (3)) can express our intention to use it that way to readers
> and make the uninterruptible methods available in IDE autocompletion.
>
> Methods can declare a return type of UninterruptibleFuture, making the
> uninterruptible operations more convenient and bringing them to the
> attention of more users.
>
> (3) hides the original, interruptible methods.  This is especially a
> problem if a method has returned an UninterruptibleFuture to the user
> for "convenience," as proposed above.
>
> (2) is most consistent with the JDK's existing uninterruptible methods.
>
> In principle, a Future implementation could implement
> UninterruptibleFuture and some other Future subinterface (e.g., one
> whose get methods do not throw ExecutionException).  In practice, this
> seems unlikely.
>
> "UninterruptibleFuture" is a poor name.  The name may suggest to some
> that a *task* whose value the Future awaits may not be interrupted
> through Future.cancel.  But "Uninterruptible" refers only to the get
> methods; it's more like "UninterruptiblyGettableFuture," which is an
> ugly name.
>
> "UninterruptibleFuture" is a particularly poor name in the case of
> (2), since its get methods would still be interruptible.  (This is
> another problem that "UninterruptiblyGettableFuture" could solve.)
>
>
> Decision B: There are two ways to handle the retry boilerplate:
> 1. Repeat it everywhere it's needed.
> 2. Delegate to a performUninterruptibly method that takes an
> InterruptibleOperation parameter.
> (<
> http://cs.oswego.edu/pipermail/concurrency-interest/2007-March/003775.html
> >)
>
> (A colleague proposed a reflection-based alternative, but we found it
> to have two problems:  First, CountDownLatch isn't an interface, so we
> can't extend it to create an UninterruptibleCountDownLatch interface
> to pass to Proxy.  Second, we can't handle timeouts without either
> annotating the long+TimeUnit parameters or assuming that there's a
> convention for them.)
>
> (1) has the usual advantages and disadvantages of copy-and-paste
> programming.
>
> If there's a significant performance difference, (1) is surely the winner.
>
> (2) requires three variants of InterruptibleOperation: one for
> operations without timeout, one for operations that time out by
> returning a sentinel value, and one for operations that time out by
> throwing TimeoutException.  (We might be able to combine the last two
> with suitable generics, but my claim of "three variants" already
> presumes some awkward parameterization to handle exceptions.)
>
>
> I'm currently leaning toward 2-1
> (UninterruptibleFuture.getUninterruptibly, repeat the boilerplate),
> but some smart people disagree.  Opinions?
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20100408/e6b740a8/attachment.html>


More information about the Concurrency-interest mailing list