Topic: Multiple in-flight exceptions (was: C++ wishlist)
Author: usenet-nospam@nmhq.net (Niklas Matthies)
Date: Fri, 10 Sep 2004 23:01:10 GMT Raw View
On 2004-09-09 08:01, Bob Bell wrote:
:
> When B() exits, the invariant checker runs, detects the invariants are
> violated, and throws an InvariantViolation. As the exception passes up
> through A(), the invariant checker runs because A is exiting. It
> detects that the invariants are violated, and throws another
> InvariantViolation. Two exceptions == std::terminate, goodnight, and
> God bless.
I never liked the fact that two exceptions == std::terminate. Here's
one possible scheme I came up with some time ago that avoids this
problem. I didn't dare to mention it back then, since it necessarily
breaks some existing code, but I feel like doing so now, even though
it's just a toy thought experiment.
Let's imagine that instead of at most one exception object, there
could be a whole set of exception objects "in-flight" at any given
moment. For normal stack walkback and destructor execution, this
wouldn't make any difference. Any new exceptions would just join
the existing set when exiting the scope of the respective destructor.
The only real issue is what the semantics of catch clauses would be.
Since in general the blanket assumption that that a later exception is
more important than a former, or vice versa, cannot be made (and
anyway we'd like to retain knowledge about the less important
exception regardless, instead of silently discarding it), and neither
can it be determined in general that one exception may be the cause of
the other (so that there would be a tiny bit more of a justification
for discarding the latter), the semantics should be as symmetric as
possible with regard to the exception objects contained in the set.
The scheme I have in mind works as follows: When a catch clause (or
sequence of catch clauses) is encountered, the subset S of applicable
exception objects of the current in-flight set is determined. Then for
each of the exception objects in S the respective catch clause is
executed. (In unspecified order is probably best.)
Now let T be the subset of non-applicable exception objects. When a
catch clause rethrows the exception or throws a new set of exception
objects, it is added to T. (It is to some degree a judgement call
whether the current exception should also be added to T along with
the set of new exceptions in the non-rethrow case.) After all catch
clause executions for the elements of S have been completed, T becomes
the new current set of in-flight exceptions. If T is empty, execution
resumes normally behind the sequence of catch clauses. Otherwise stack
walkback continues.
The main reason why this breaks existing code is that catch clauses
must be prepared to be executed multiple times for the same try-block
execution. (An exception could be made for 'catch (...)', having it
executed just once, since there is no exception object to parameterize
the executions). Other than that (which in all likelyhood is already a
show-stopper), I don't see any major problems, although I might be
missing something.
One might worry about the RTL's memory management for all those
exception objects. (On the other hand, storage for multiple execption
objects must already be handled in current C++, even though there's
always just one of the exceptions in-flight at any given time. Instead
of just a stack of exceptions, you would now have a stack of sets of
exceptions.) When all available exception memory is exhausted, this
could trigger a std::bad_alloc (or similar) exception, alas causing
infinite recursion since there's no space to store the corresponding
exception object. One solution could be to only keep a count of such
"exception memory exhausted" exceptions and have just one static
singleton instance.
Anyway, I'd be glad to hear any opinions.
-- Niklas Matthies
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]