P99

◆ P99_TRY

#define P99_TRY
Value:
/* one phase for the try, one for the finally */ \
for (register unsigned p00_pha = 0; p00_pha < 2u; ++p00_pha) \
/* Restrict the first phase to the try */ \
if (!p00_pha) \
P00_BLK_START \
P00_BLK_BEFORE(p00_jmp_push(p00_unwind_top)) \
do

Create a block that can catch exceptions.

Remarks
This must be used with either P99_CATCH or P99_FINALLY following immediately after the depending block.

The simplest use of this feature is together with P99_FINALLY

unsigned char*volatile buffer = 0;
buffer = malloc(bignumber);
if (!buffer) P99_THROW(thrd_nomem);
// do something complicated with buffer
favorite_func(buffer);
free(buffer);
}

This will ensure that the buffer allocated in buffer will always be freed, regardless of any error conditions the code encounters. In particular this will work, even if an exception is thrown from below the call to favorite_func.

If no exception occurs, the P99_FINALLY clause is always executed. Execution then continues after the clause, just as for normal code.

If an exception occurs, the P99_FINALLY clause is executed (and in this case the call to free is issued). But afterwards, execution will not continue as normal but instead will jump to the next P99_FINALLY or P99_CATCH block on the call stack.

An alternative way is to use P99_CATCH and to handle different exceptions explicitly.

unsigned char*volatile buffer = 0;
buffer = malloc(bignumber);
if (!buffer) P99_THROW(thrd_nomem);
// do something complicated with buffer
} P99_CATCH(int code) {
switch(code) {
case thrd_nomem: perror("we had an allocation error"); break;
case thrd_timedout: perror("we were timed out"); break;
}
free(buffer);
if (code) P99_RETHROW;
}

The difference here is that we receive the error code through the variable code and we can thus take different action for different exceptional conditions. If it weren't for the P99_RETHROW, the unrolling of the call stack would stop at this point and execution would continue after the catch block. The exception would be considered caught.

Here, since there is a P99_RETHROW, execution will jump to the next P99_FINALLY or P99_CATCH block on the call stack. In fact a catch clause of

P99_CATCH(int code) {
// do something here and then
if (code) P99_RETHROW;
}

Would be equivalent to

// do something here
}

except that this wouldn't give access to code.

Note that the code depending on P99_TRY must always be an entire block with { } surrounding it. The code depending on P99_FINALLY or P99_CATCH doesn't have that restriction and could be just a single statement.

Warning
Utilities that change control flow in an unexpected way may result in the loss of some modifications that are effected on variables. A modern compiler should tell you when you are in such a situation. If it is the case you'd have to declare the variable in question with the volatile qualifier. For an explanation see P99_UNWIND_PROTECT.

Definition at line 585 of file p99_try.h.

thrd_timedout
@ thrd_timedout
returned by a timed wait function to indicate that the time specified in the call was reached without...
Definition: p99_tss.h:114
P99_TRY
#define P99_TRY
Create a block that can catch exceptions.
Definition: p99_try.h:585
P99_THROW
#define P99_THROW(X)
Stop execution at the current point and signal an exception of value X to the next P99_TRY clause on ...
Definition: p99_try.h:128
P99_FINALLY
#define P99_FINALLY
Designate a block that is executed regardless of the exceptions that were encountered in the correspo...
Definition: p99_try.h:630
P99_UNWIND_PROTECT
#define P99_UNWIND_PROTECT
Unwind execution from several levels of nesting inside a function.
Definition: p99_block.h:612
thrd_nomem
@ thrd_nomem
returned by a function to indicate that the requested operation failed because it was unable to alloc...
Definition: p99_tss.h:133
P99_RETHROW
#define P99_RETHROW
Stop execution at the current point inside a P99_FINALLY or P99_CATCH clause and propagate the same e...
Definition: p99_try.h:495
P99_CATCH
#define P99_CATCH(...)
Designate a block that is executed regardless of the exceptions that were encountered in the correspo...
Definition: p99_try.h:676