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

Jim Newsham jnewsham at referentia-test.com
Thu Apr 8 20:32:11 EDT 2010


Regarding decision A.  We have a collection of static 
XXXUninterruptibly() methods in a single utility class.  This is like 
your approach #1, except they are all in the same class (ours is called 
ThreadUtils and has some other thread-related methods, but I've 
sometimes considered breaking them out into a separate class which 
contained only XXXUninterruptibly()...  maybe 
UninterruptibleUtils.get(Future) or Uninterruptibly.get(Future)?).  We 
didn't really consider (or have a need for) the wrapper approach -- it's 
really the invoker who decides whether to mask interruption.

Regarding decision B.  In our case, the code for each method is 
repeated, but it's really not much code at all so I have no issue with it.

Jim

On 4/8/2010 6:46 AM, Chris Povirk 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?
>
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>    



More information about the Concurrency-interest mailing list