PreviousNext

Syntax for C

Access to exceptions from the C language is defined by the macros in the exc_handling.h file. The exc_handling.h header file is included automatically when you include pthread_exc.h (see Invoking the Exception-Returning Interface).

The following example shows the syntax for handling exceptions:

TRY

try_block

[CATCH (exception_name)

handler_block]...

[CATCH_ALL

handler_block]

ENDTRY

A try_block or a handler_block is a sequence of statements, the first of which may be declarations, as in a normal block. If an exception is raised in the try_block, the catch clauses are evaluated in order to see if any one matches the current exception.

The CATCH or CATCH_ALL clauses absorb an exception; that is, they catch an exception propagating out of the try_block, and direct execution into the associated handler_block. Propagation of the exception, by default, then ends. Within the lexical scope of a handler, it is possible to explicitly cause propagation of the same exception to resume (this is called reraising the exception), or it is possible to raise some new exception.

The RERAISE statement is allowed in any handler statements and causes the current exception to be reraised. Propagation of the caught exception resumes.

The RAISE (exception_name) statement is allowed anywhere and causes a particular exception to start propagating. For example:

TRY

sort(); /* Call a function that may raise an exception.

* An exception is accomplished by longjumping

* out of some nested routine back to the TRY

* clause. Any output parameters or return

* values of the called routine are therefore

* indeterminate.

*/

CATCH (pthread_cancel_e)

printf("Alerted while sorting\n"); RERAISE;

CATCH_ALL

printf("Some other exception while sorting\n"); RERAISE;

ENDTRY

In the preceding example, if the pthread_cancel_e exception propagates out of the function call, the first printf is executed. If any other exception propagates out of sort, the second printf is executed. In either situation, propagation of the exception resumes because of the RERAISE statement. (If the code is unable to fully recover from the error, or does not understand the error, it needs to do what it did in the previous example and further propagate the error to its callers.)

The following shows the syntax for an epilogue:

TRY try_block

[FINALLY final_block]

ENDTRY

The final_block is executed whether the try_block executes to completion without raising an exception, or if an exception is raised in the try_block. If an exception is raised in the try_block, propagation of the exception is resumed after executing the final_block.

Note that a CATCH_ALL handler and RERAISE could be used to do this, but the epilogue code would then have to be duplicated in two places, as follows:

TRY

try_block

CATCH_ALL

final_block

RERAISE;

ENDTRY

{ final_block }

A FINALLY statement has exactly this meaning, but avoids code duplication.

Note: The behavior of FINALLY along with the CATCH or CATCH_ALL clauses is undefined. Do not combine them for the same try_block.

Another example of the FINALLY statement is as follows:

pthread__mutex_lock (some_object.mutex);

some_object.num_waiters = some_object.num_waiters + 1;

TRY

while (! some_object.data_available)

pthread_cond_wait (some_object.condition);

/* The code to act on the data_available goes here */

FINALLY

some_object.num_waiters = some_object.num_waiters - 1;

pthread_mutex_unlock (some_object.mutex);

ENDTRY

In the preceding example, the call to pthread_cond_wait( ) could raise the pthread_cancel_e exception. The final_block ensures that the shared data associated with the lock is correct for the next thread that acquires the mutex.