$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
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>