Throw to code:
try
{
tex.loadFromFile("pic.jpg");
}
catch(loadFromFileFailed& e)
{//by this point I am already kind of discouraged and want to go play with some other library that doesn't force exceptions
return errcode::loadFromFileFailed;
}
definitely can't be faster
Of course it can be.
If the exception handling method is a so-called "free" exception handling, like DWARF2 or 64-bit SEH, then in the usual case, i.e. no exception is thrown, the cost of setting up a
try/catch is
zero. As in,
no code has to be run, for all the stuff required is in the static data already.
On the other hand, the reverse conversion,
if(result == ERROR) { throw something; }, requires a conditional branch. Yes, it may will be well-predicted, making it cheap, but even if it is, it will pollute the branch predictor history, possibly evicting a branch that occurs in the hot path from there. And sure, that hot branch will eventually get there back again, but for the first few times, it's more likely to be mispredicted. The cost of mispredictions is typically measured in tens of cycles, which sure doesn't sound like a lot, except it's already way more than the cost incurred by
try/catch in the aforementioned case.
There's also the question of the callee detecting the error. Perhaps surprisingly, it's the same in both cases: it's
if(someLowerLevelStuffResult == ERROR) { propagate the error to the caller; }. Given the usual behavior is for no error to occur, it's a simply a not taken branch.
Obviously, if the expected behavior is for an error to actually happen, then the above considerations don't apply, but something is probably amiss anyway.
on MinGW DW2 […] breaks winapi callbacks, SJLJ […] doesn't break callbacks.
It's the other way around. No, really.
It's the other way around.
If one throws across callbacks while using DWARF2 unwinding, the unwinder has no idea whatsoever what to do with that foreign stack frame for which there are no unwind data available. So it calls
std::terminate.
If one throws across callbacks while using setjmp/longjmp unwinding, the unwinder has no idea whatsoever
about anything, its only job is to
longjmp to the nearest matching handler. If there is a matching handler, it blindly
longjmps to it,
completely ignoring any possible cleanup code that the foreign code would otherwise execute. If the foreign code acquired some resources, they're leaked. If it held a lock, a deadlock awaits.
To sum up: with DWARF2, you get a loud immediate crash. With setjmp/longjmp, you get a silent corruption. I'd take the former over the latter any day.
To be completely safe, don't
ever throw across foreign code.
EDIT: fixed a typo.