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
_______________________________________________
Concurrency-interest mailing list
Concurrency-interest@xxxxxxxxxxxxxxxxxxxx
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
|