Threads Module User's Guide : PART II Concurrency Packages : Chapter 3 The Threading Package : The Runnable Object Classes : Catching and Rethrowing Exceptions
Catching and Rethrowing Exceptions
Exceptions produced while executing a runnable’s task are captured by the runnable for later recovery. Any of these exceptions can be rethrown by any thread that has access to the runnable object. This operation is implemented by the following function:
void RWRunnable::raise(void) const
A runnable catches any exception that propagates out of its run() member function. This includes any exceptions produced by functions invoked as functors within the runnable. When a runnable catches an exception, it:
1. Makes an internal copy of the exception.
2. Sets the execution state to RW_THR_EXCEPTION[5].
3. Sets the completion state to RW_THR_FAILED{3}.
4. Sets the execution state to RW_THR_INITIAL[6].
5. Ceases execution by returning from start() or exiting the thread.
Any exception caught by the runnable can then be recovered by rethrowing the exception using the RWRunnable::raise() function. If no exception has occurred, this function returns without doing anything.
Testing After Successful Joins
You should test for an exception each time you successfully join with a runnable, as shown in Example 7.
Example 7 – Testing for an exception after joining with a runnable
RWThreadFunction myThread = ...;
try {
myThread.start(); // Start the runnable
myThread.join(); // Join the runnable
myThread.raise(); // Rethrow any exception that was caught!
}
catch(RWTHRxmsg& msg) {
cout << "Exception! " << msg.why() << endl;
}
Types of Rethrown Exceptions
The type of exception that is rethrown by a runnable might not match the original exception class that was thrown or caught.
If the exception is based on the RWTHRxmsg class, then the exception rethrown by raise() is of the same class as the one captured.
Exceptions based on the RWxmsg (or xmsg) class are rethrown as an RWxmsg with the same message value as the captured exception.
Any other type of exception is rethrown as an RWTHRxmsg with a generic message stating that the captured exception was of an unrecognized type.
When designing code that you expect to execute inside a Threading package runnable, you might want to use the RWTHRxmsg class as a base class for your exceptions. An exception derived from this class can be caught as an RWTHRxmsg, copied for storage using a virtual clone() function, and later “reconstituted” using a virtual raise() function defined by the class. This store-and-forward capability allows a runnable to capture and rethrow an exception.
The Threading package includes a template called RWTTHRCompatibleException, which can convert an existing exception class into an RWTHRxmsg-compatible exception.