Resumption
Resumption is an exception-raising mechanism where the handler runs in place of the faulting code, then control returns to the raiser — no stack unwinding happens.
Why have resumption when we already have termination (throw/catch)?
Termination forcibly unwinds the stack to the handler — the raiser’s execution is gone. That’s the right model when the fault means you can’t continue. But some faults are repairable — the handler can fix the situation and the raiser should resume where it left off. Termination can’t do that; resumption can. Think of it as “asking for help” rather than “giving up”.
uC++ raising syntax
_Throw [ exception-type ] ; // termination — unwinds
_Resume [ exception-type ] [ _At uBaseCoroutine-id ] ; // resumption — no unwind_Throwwith no exception-type is a rethrow._Resumewith no exception-type is a re-resume._Attargets another coroutine — see Nonlocal Exception.
Handler syntax
uC++ extends try blocks with _CatchResume clauses alongside normal catch:
try {
...
} _CatchResume( E1 ) { ... } // must appear before catch clauses
_CatchResume( ... ) { ... } // catch-any for resumption — must be last _CatchResume
catch( E2 ) { ... } // catch clauses after all _CatchResume
catch( ... ) { ... } // catch-any for terminationTip
All
_CatchResumehandlers must precede anycatchhandlers. A resumption handler cannot performbreak,continue,goto, orreturn— control must return to the raise site.
Resumption matches only _Resume; termination matches only _Throw
The raise mechanism dictates which handler set is searched:
_Throw→ onlycatchclauses are examined_Resume→ only_CatchResumeclauses are examined
They don’t cross over. A _Throw will never be caught by _CatchResume, and vice versa.
Worked example
_Exception E {};
int main() {
try {
cout << "before throw" << endl;
_Throw E{};
cout << "after throw" << endl; // never reached — stack unwinds
} catch( E ) {
cout << "catch" << endl;
}
cout << "after try1" << endl;
try {
cout << "before resume" << endl;
_Resume E{};
cout << "after resume" << endl; // IS reached — handler returned
} _CatchResume( E ) {
cout << "_CatchResume" << endl;
}
cout << "after try2" << endl;
}Output:
before throw
catch
after try1
before resume
_CatchResume
after resume
after try2
Note the key difference: after throw is skipped (termination unwinds past it), but after resume runs (the _CatchResume handler ran, then control returned).
defaultResume
Every resumption-raising exception has a defaultResume — what happens if no _CatchResume handler matches during propagation. uC++‘s default is to convert the resumption into a termination (_Throw the same exception), so an unhandled _Resume degrades gracefully to a catch search.