Boost logo

Boost :

From: Miro Jurisic (macdev_at_[hidden])
Date: 2004-02-14 12:20:34


I recently spent some time thinking about a similar problem, and after looking
at transporting exceptions for some time, I decided that it's a big pain for a
variety of reasons (all of which have been mentioned in this thread already),
and that the interface would not be particularly pleasant (what with having to
register exceptions types from every 3rd party C++ library that I use), so I am
currently considering an alternate approach: having an object whose
responsibility it is to handle exceptions in the appropriate way, and passing
that object around.

When I need to handle an exception, instead of trying to teleport the exception
out of the C++ exception handling mechanism, I'd simply tell that object to
handle the current exception in whatever manner it seems fit. Something along
the lines of:

void
my_thread_main {
   ...
   catch (...) {
     current_exception_handler(get_current_thread())->handle_current_exception();
   }
}

Here I assume that my thread model gives me a way to get at the current thread,
and that it gives me a way to have some thread local data in which I can stash a
copy of the current thread exception handler.

handle_current_exception would then use the standard rethrow/catch technique to
get at the exception:

void
my_exception_handler::handle_current_exception()
{
   try {
      throw;
   } catch (std::exception& e) {
      ...
   } ...
}

This mechanism also allows for a hierarchy of exception handling policies. For
example, the top level of the application creates an exception handling object
with a sensible default behavior. When the application enters a state in which a
more specific exception handling behavior is desirable, the per-thread exception
handling object is set to some object that understands the more specific
context. The more specific object, when created, obtains a reference to the more
generic one, and calls through to it when it doesn't know what to do with an
exception:

void
my_exception_handler::handler_current_exception()
{
   try {
      try {
         throw;
      } catch (my_exception) {
         if (know how to handle) {
            // ...
         } else {
            throw;
         }
      }
   } catch (...) {
     next_exception_handler()->handle_current_exception();
   }
}

(The double try makes sure that any exceptions rethrown by the inner handler are
propagated to the next handler in the chain.)

This is an idea that has only recently started brewing in my head -- so recently
that I haven't actually had the time to implement it -- so I am quite aware that
there may be something that I am missing. However, it does have all the
properties that I want in my exception handling:
 - the exception handling policy is specified orthogonally to non-exception flow
 - the exception handling policy is specifed by the code that will handle the
error, not by the code that generates the error
 - exception handling policies can be layered in a hierarchy that corresponds to
user actions (even when the hierarchy of user actions does not directly
correspond to the machine stack -- e.g. with threads, or various message and
event passing architectures).
 - it does not require me to solve the problem of transporting exceptions

I find myself wondering why an architecture of this kind is not being considered
in the current discussion.

meeroh

-- 
If this message helped you, consider buying an item
from my wish list: <http://web.meeroh.org/wishlist>

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk