On Friday, 13 September 2013 at 23:58:33 UTC, Sean Kelly wrote:
Exception chaining is actually built-in. I did some digging
for an official description, but couldn't find one. Here's a
summary:
If an Exception is thrown when an Exception or Error is already
in flight, it is considered collateral damage and appended to
the chain (built via Throwable.next).
If an Error is thrown when an Exception is already in flight,
it will replace the in flight Exception and reference it via
Error.bypassedException.
If an Error is thrown when an Error is already in flight, it
will be considered collateral damage and appended to the
Throwable.next chain.
Hum. The problem here, is the concept of "in flight". It implies
an exception is *currently* going up, and that the exceptions
thrown come from automatically called destructor (or functions
called by destructor).
My problem though, is that I am already in an exception handling
"block", so there is no "in flight" exception, just the exception
that's in my handle. Here is a reduced pseudo code of what I
have, where "doThem" needs to do "doIt" "n" times, but needs to
"unDoIt" if an exception is thrown. My code looks like this:
//--------
void doThem(size_t n)
{
size_t i;
try
{
for ( ; i < n ; ++i)
doIt(i);
}
catch (Exception e)
{
//Grab the tail.
Throwable tail = e;
while(tail.next !is null)
tail = tail.next;
try //Start cleaning up
{
//undo everything individually
for ( --i ; i < n ; --i)
{
try
unDoIt(i); //This is the actual call
catch (Exception ee)
tail = (tail.next = ee);
}
}
catch (Error ee) //An Error!
{
//insert the current exception before the currently
bypassed exceptions.
tail = ee.bypassedException;
ee.bypassedException = e;
throw ee;
}
}
}
//--------
I think this is crazy.
The two questions I have are:
1. Am I doing it right?
2. Should I even bother? Even dmd doesn't bother printing the
chained exceptions on death.
I mean, my code could just as well be:
//----
void doThem(size_t n)
{
size_t i;
try
{
for ( ; i < n ; ++i)
doIt(i);
}
catch (Exception e)
{
for ( --i ; i < n ; --i)
{
try
unDoIt(i);
catch (Exception /+ee+/)
{/+ignore ee+/}
}
}
}
//----
Much simpler!
For a bit of context, the code I have in mind is static array
postblit: Postblit each element. If this fails, then destroy all
previously post-blitted elements.