[concurrency-interest] Having TimeoutException be a subclass of InterruptedException

Luke Blanshard blanshlu@netscape.net
Sat, 07 Dec 2002 11:46:05 -0600

Let me state my case constructively instead of as criticism.

Once upon a time, catching an InterruptedException or an 
InterruptedIOException always implied that the current thread had been 
interrupted by another thread.  For those of us who tried to honor 
thread interruption---i.e., to ensure that an interruption actually 
interrupted the thread---this provided a simple way to maintain this 
otherwise quite transient state of a thread.

Then at some point the setSoTimeout method on Socket was added or 
implemented, and the InterruptedIOException was thrown by the input 
stream if a read timed out.  This was bad, because now there was no way 
to distinguish a thread interruption from a timeout.  In 1.4, the 
SocketTimeoutException was added to provide this distinction---and as 
with the TimeoutException, it was made a subclass of InterruptedIOException.

The problem I have with both of these choices is that they change the 
implicit contract of their parent classes.  So here's my constructive 
suggestion.  Let's make the contract explicit, by adding a boolean 
wasThreadInterrupted() method to both InterruptedException and 
InterruptedIOException.  Now any subclass must be able to tell whether 
it was triggered by another thread interrupting this one, or by some 
other event like a timeout; and those of us who try to maintain threads' 
interruption statuses correctly will have again a simple pattern to 
follow.  Best of all, this pattern won't vary depending on the call that 
throws the interrupted exceptions.

As for implementation, I would argue that the base classes should simply 
always return true from this method, and that subclasses should override 
with a constant false (for the two subclasses already defined) or with 
an instance variable (for some future subclass that might be thrown in 
either situation).

Am I making a mountain out of a molehill here?


David Holmes wrote:

>Luke Blanshard wrote:
>>I have a question about having TimeoutException inherit
>>from InterruptedException.  In the current JVM, an
>>InterruptedException always means that the current thread
>>has been interrupted.  I often keep track of this fact by
>>setting a flag in the catch block for InterruptedException,
>>and re-interrupting the thread when I've finished cleaning
>>up after the interruption, so that outer or later code will
>>also know that it is supposed to complete early.
>>With this new subclass, you appear to have destroyed a
>>useful invariant of the JVM.
>The reasons for making TimeoutException extend InterruptedException
>- logically a timeout can be considered an interrupt from a timer. It
>could even be implemented this way under the covers - you couldn't
>tell because the interrupt state is reset when the exception is thrown
>- code that doesn't want to deal with normal or timer-based interrupts
>can just declare that they throw a single exception -
>InterruptedException - rather than two different checked exceptions.
>Higher-level code doesn't need to know, and probably doesn't care
>whether the interrupt was time-out related or not. (It would be
>inconsistent for TimeoutException to not be a checked exception when
>InterruptedException is).
>- back in the old days (1.0/1.02/1.1) many people actually expected a
>timeout from wait to throw InterruptedException :)
>This doesn't break any existing code because the methods that can
>throw TimeoutException are all new methods. To deal with the new
>exception all you have to do is extend your current idiom with an
>additional catch clause:
> try {
>   operation();
> }
> catch(TimeoutException te) {
>    // deal with timeout
> }
> catch(InterruptedException ie) {
>     // deal with general thread interruption
> }
>David Holmes