In the asynchronous environment provided by ProActive, exceptions cannot be handled the same as in a sequential environment. Let's see the problem with exceptions and asynchrony in a piece of code:
try { Result r = someAO.someMethodCall(); // Asynchronous method call that can throw an exception // ... doSomethingWith(r); } catch (SomeException se) { doSomethingWithMyException(se); }
As the method call in line 2 is asynchronous, the program continues execution
without waiting for its completion. So, it is
possible for the control flow to exit the try
.
In this case, if the method call finishes with an exception, we cannot
throw it back in the code anymore because we are no more in the
try
block. That is why ProActive method
calls with potential exceptions are handled synchronously by default.
The ProActive solution to this problem is to put barriers around
try/catch
blocks. This way the control flow cannot
exit the block, the exception can be handled in the appropriate
catch
block, and the call is
asynchronous within the block.
With this configuration, the potential exception can be thrown at several points:
when accessing a future
inside the barrier
by using the provided API (see after)
Let's reuse the previous example to see how to use these barriers
PAException.tryWithCatch(SomeException.class); try { Result r = someAO.someMethodCall(); // Asynchronous method call that can throw an exception // ... doSomethingWith(r); PAException.endTryWithCatch(); } catch (SomeException se) { doSomethingWithMyException(se); } finally { PAException.removeTryWithCatch(); }
With this code, the call in line 3 will be asynchronous, and the
exception will be handled in the correct
catch
block. Even if this implies waiting at the
end of the try
block for the completion
of the call.
Let's see in detail the needed modifications to the code:
PAException.tryWithCatch()
call right before the
try
block. The parameter is either the caught
exception class or an array of these classes if there are
many
PAException.endTryWithCatch()
at the end of the try
block
PAException.removeTryWithCatch()
at the beginning of the
finally
block, so the block becomes
mandatory
These needed annotations can be seen as cumbersome, so we provide a tool to add them automatically to a given source file. It transforms the first example code in the second. Here is a sample session with the tool:
$ ProActive/bin/trywithcatch.sh MyClass.java --- ProActive TryWithCatch annotator ----------------------- $ diff -u MyClass.java~ MyClass.java --- MyClass.java~ +++ MyClass.java @@ -1,9 +1,13 @@ public class MyClass { public MyClass someMethod(AnotherClass a) { + PAException.tryWithCatch(AnException.class); try { return a.aMethod(); + PAException.endTryWithCatch(); } catch (AnException ae) { return null; + } finally { + PAException.removeTryWithCatch(); } } }
As we can see, ProActive method calls are added to make sure all
calls within try/catch
blocks are handled asynchronously. The tool can be
found in ProActive/scripts/unix/
.
We have seen the 3 methods mandatory to perform asynchronous calls with exceptions, however the complete API includes two more calls. So far the blocks boundaries define the barries. But, some control over the barrier is provided thanks to two additional methods.
The first method is PAException.throwArrivedException()
. During a
computation an exception may be raised but there is no point from where
the exception can be thrown (a future or a barrier). The solution is to
call the PAException.throwArrivedException()
method which simply queries
ProActive to see if an exception has arrived with no opportunity of
being thrown back in the user code. In this case, the exception is
thrown by this method.
The method behaviour is thus dependent on the timing. That is,
calling this method may or may not result in an exception being thrown,
depending on the time for an exception to come back. That is why another
method is provided: PAException.waitForPotentialException()
.
Unlike the previous PAException.throwArrivedException()
,
this method is blocking. After calling this
method, either an exception is thrown or it is assured that all
previous calls in the block completed successfully, so no exception can
be thrown from the previous calls.
© 1997-2008 INRIA Sophia Antipolis All Rights Reserved