|
Re: JCiP Memoizer: msg#00034java.jsr.166-concurrency
Hi Tim, You don't need the interrupted() check in the Callable adapter. If the thread was interrupted during call() then if call() "aborted" it should have thrown InterruptedException. The fact that call() didn't throw indicates that call() completed successfully and the result is available. What we'd really like is to specialise FutureTask.run so that InterruptedException is treated as a cancel request. But there is no way to do that without writing your own Future implementation because any attempt to "wrap" super.run() is too late to stop the IE from being treated as a general exception. Hmmm - with the fixes in the Java 6 version (I think they got in!) that ensures sync.innerRun calls ft.setException then it might be possible to do this: ft = new FutureTask(eval) { protected void setException(Throwable t) { if (t instanceof InterruptedException) cancel(false); else super.setException(t); } }; Still not "pretty" though. The complexity has arisen in this example because of the attempt to treat interruption as a transient error rather than a permanent one, combined with the desire to show handling cancellation even though it isn't actually possible. Cheers, David > Tim Peierls <tim@xxxxxxxxxxx> wrote: > > One of the things that makes the Memoizer example so interesting (and > suitable for inclusion in chapter 5 of JCiP) is that it is a rare > example of > FutureTask used outside of an Executor. > > Does David's last fix with additional interrupt checking in the Callable > adapter do the trick? Something like this: > > public V compute(final A arg) throws InterruptedException { > while (true) { > Future<V> f = cache.get(arg); > FutureTask<V> ft = null; > if (f == null) { > Callable<V> eval = new Callable<V>() { > public V call() throws InterruptedException { > V result = c.compute(arg); > if (Thread.interrupted()) > throw new InterruptedException(); > return result; > } > }; > FutureTask<V> ft = new FutureTask<V>(eval); > f = cache.putIfAbsent(arg, ft); > if (f == null) { > f = ft; > ft.run(); > } else { > ft = null; > } > } > try { > return f.get(); > } catch (CancellationException e) { > throw new IllegalStateException("can't have been > cancelled"); // ?? > } catch (ExecutionException e) { > Throwable t = e.getCause(); > if (t instanceof InterruptedException) { // ft.run() > was interrupted > cache.remove(arg,f); > if (ft != null) // we did ft.run() so we were > interrupted > throw (InterruptedException) t; > // else retry > } else { > throw launderThrowable(t); > } > } > } > } > > > Yuck. Makes that final example a lot harder to explain than we were > hoping > for. > > --tim > > > On 10/18/06, Joe Bowbeer <joe.bowbeer@xxxxxxxxx> wrote: > > > > I think the existing cancellation exception handling would make more > > sense if the task were submitted to an executor. Then a forced > > shutdown of the executor, for example, could cause a cancellation > > exception. > > > > Btw, when I've coded this kind of thing in the past, I've usually > > finessed the problem by adding "throws Exception" to the method in > > question :-) > > > > On 10/18/06, David Holmes <dcholmes@xxxxxxxxxxxxxxx> wrote: > > > Alex, > > > > > > I have to concur with Tim. The intent was that interruption during > > ft.run() > > > implied cancellation and so there was a need to do clean-up of the > cache > > > entry. But there is nothing to convert the interruption to a > cancel() > > > request and so all that happens in the current case is that everyone > who > > > calls f.get() will get ExecutionException with a cause of > > > InterruptedException. > > > > > > [...] > > _______________________________________________ > > Concurrency-interest mailing list > > Concurrency-interest@xxxxxxxxxxxxxxxxxxxx > > http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest > >
|
|
| <Prev in Thread] | Current Thread | [Next in Thread> |
|---|---|---|
| Previous by Date: | Re: JCiP Memoizer, Tim Peierls |
|---|---|
| Next by Date: | ArrayBlockingQueue and addAll(), Kasper Nielsen |
| Previous by Thread: | Re: JCiP Memoizer, Tim Peierls |
| Next by Thread: | ArrayBlockingQueue and addAll(), Kasper Nielsen |
| Indexes: | [Date] [Thread] [Top] [All Lists] |
| News | FAQ | advertise |