    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Exception Handling Alternatives (Part 2)</title>
        <link>https://members.accu.org/index.php/articles/555</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Design of applications and programs + Overload Journal #31 - Apr 1999</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c67/">Design</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c173/">31</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c67-173/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c67+173/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Exception Handling Alternatives (Part 2)</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 26 April 1999 17:50:52 +01:00 or Mon, 26 April 1999 17:50:52 +01:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e18" id=
"d0e18"></a>Resum&eacute;</h2>
</div>
<p>In part 1, several alternative mechanisms for handling
exceptional events were presented. One of the conclusions was that
a framework (or library) should not impose a fixed error handling
mechanism on the application design. Also, all of the proposed
mechanisms in part 1 (including standard exception handling) have
one disadvantage in common: they all lose the context of the error
event.</p>
<p>As I have stated several times, C++ standard exception handling
is the necessary substitution for the C longjmp mechanism. But the
longjmp error handling mechanism in C consists of two parts (there
are other error handling mechanisms in C, e.g. errno). While the
handling/recovery mechanism is (at least sometimes) the longjmp
mechanism, the other part is the notification of an error event.
This is done through the signal mechanism.</p>
<p>The C signal mechanism is split into three steps:</p>
<div class="orderedlist">
<ol type="1">
<li>
<p>registration of a signal handler, which can be roughly compared
to try;</p>
</li>
<li>
<p>raising of a signal, which can be compared to throw;</p>
</li>
<li>
<p>handling the problem: here, the problem is solved or recovery is
tried (often using longjmp).</p>
</li>
</ol>
</div>
<p>(Note: There are synchronous and asynchronous signals. While
step 1 is identical for both, step 2 and 3 are quite different;
asynchronous signals are raised by the operating system and for the
handling only very limited functionality is available, longjmp not
among them.)</p>
<p>Though the above description of C signal handling looks quite
similar to C++ exception handling, there is one big difference: the
signal handler is put on top of the stack, instead of unwinding it.
So, you can handle and solve the problem and resume the program
flow where the problem was detected by just returning from the
signal handler function. Of course, if you can not solve the
problem, you have to try to recover from some save point, for which
longjmp is used, which then unwinds the stack (actually, it is not
unwound but just cut off). In C++, a similar mechanism was
introduced with the new_handler(), but in general, C++ promotes
exception handling as the standard mechanism for error events.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e41" id="d0e41"></a>Callbacks</h2>
</div>
<p>C signal handling is just an implementation of a general
callback mechanism, and a general callback mechanism can help in
solving the design problems of error handling. The callbacks defer
the decision of which mechanism to use to handle an exceptional
event to a later stage of the design. You can leave the decision
open until the complete application is assembled. So, you do not
have to decide on the mechanism when you write the framework, not
even when you write the classes and functions the framework uses,
but just before you put everything together and actually use the
framework. And at that time, you still have the option to use one
of the mechanisms I showed you in my first article. Well, not
really all of them. You couldn't provide return codes, and deferred
error handling must at least partially be supported by the classes
you add to the framework.</p>
<p>But, you have the three main options to terminate the program:
to push an error event onto a global stack, or to throw a standard
exception (for this, the framework and application must be
exception safe). And you have another important option with
callbacks you wouldn't have otherwise: you can try to solve the
encountered problem and then continue with the normal flow of the
program! Do you remember the infamous &quot;A: not ready. Abort, Retry,
Ignore?&quot; when you forgot to insert the floppy disk into the drive?
You just inserted the disk and then the program could continue.
Callbacks are a means to do things just like this.</p>
<p>In our example, readChar() could call a callback function in
case of a problem. An interactive application could register a
callback that asks the user what to do: solve the problem (retry),
terminate the program (abort) or just continue (ignore), in which
case an end-of-file marker could be returned (with the framework
possibly returning a &quot;Premature end of file&quot; error). A batch
application (e.g. a standalone program that loads some CASE data
and checks it for consistency) could register a different callback
that just terminates (and perhaps sends some error message to
cerr).</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e50" id="d0e50"></a>Object-Oriented
Callbacks</h2>
</div>
<p>So far, the callback mechanism was just used like the simple C
signal mechanism. But C++ provides more. An object-oriented
callback mechanism uses two objects for the handling of an error
event. One object for the event itself (an exception object) and
another object for the handler. This handler object is just a
function object as is usually used in C++ for callbacks. So, you
can add data to the individual callbacks. And you have inheritance.
A read exception could be handled by a more general IO handler.
This is exactly what you do if you throw a derived exception and
catch a base class of that exception. With C++ standard exceptions,
the compiler provides you that mechanism. With callbacks, you have
to implement your own.</p>
<p>The problem here is partly the typical double dispatch problem,
since you must find the best match for the exception and the
handler. A common solution for this kind of problem is the Visitor
pattern. But most implementations of Visitor that I've seen depend
on compile-time resolution. Since handler callbacks are registered
at run-time, that approach cannot be used here. Martin E. Nordberg
proposed in [<a href="#Nordberg">Nordberg</a>] for his Extrinsic
Visitor the usage of a map&lt;&gt; based on type IDs, and this is
the approach chosen here. This allows a dynamic lookup to find the
registered handler for an exception.</p>
<p>But one problem remains: if for the exception to handle no
handler was registered, but only for a base class, then the lookup
will not find it. To solve this, another pattern from the GoF book
[<a href="#GoF">GoF</a>] is used: Chain of Responsibility. This is
used to look for a handler for the base class, if none was found
for the original exception. This is continued until the top of the
exception hierarchy is reached. If no appropriate handler was
found, terminate() will be called (before stack unwinding!).</p>
<div class="c2"><img src=
"/var/uploads/journals/resources/Vollmann%20callback%20class%20diagram.png" align=
"middle"></div>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e66" id="d0e66"></a>Sample
Implementation</h2>
</div>
<p>The implementation shown here consists of the two class
hierarchies for exceptions and handlers and of the manager that
registers the handlers and dispatches the exception.</p>
<p>(N.B. At any single point in time, we don't really have a double
dispatch, as you have only one set of handlers that are currently
registered and of which you must find the best suited one. So, we
have only one map&lt;&gt;, and not one for each handler hierarchy
as we would have in the original double dispatch problem.)</p>
<pre class="programlisting">
class CBHandler;
template &lt;typename Base, typename Current&gt;
void raise(Current &amp;self) {
 const CBHandler *h = 0;
 if (h = currentCBManager()-&gt;getHandler(
   typeid(Current), self))
 { // a handler exists for this exception
   // and is called now
   h-&gt;handle(self);
 }
 else
 { // no handler for current class, look
   // for base class - this implements 
   // the Chain of Responsibility
   self.Base::raise();
 }
}
class CBException : public std::exception {
public:
 virtual ~CBException() throw() {}
 virtual void raise() = 0
 { terminate(), abort(); }
};
class IOException : public CBException {
public:
 IOException(const char *reason) throw()
 : text(reason) {}
 virtual void raise()
 { ::raise&lt; CBException&gt;(*this); }
 virtual const char *what() const throw()
 { return text; }
private:
 const char *text;
};
class ReadException : public IOException {
public:
 ReadException(const char *reason) throw()
 : IOException(reason) {}
 virtual void raise()
 { ::raise&lt;IOException&gt;(*this); }
};
</pre>
<p>CBException is an abstract base class, but nevertheless must
provide an implementation for its pure virtual raise() function.
Here, CBException is derived from std::exception, but this wouldn't
really be necessary in the general case.</p>
<p>In the presented solution I definitely don't like the raise()
functions in the concrete exception classes. They are all identical
except the argument of the template raise() function. The problem
is the argument that gives the base class. As they are, the
functions are typical candidates for copy-and-paste, with the
potential to introduce programming errors by accidentally giving
the wrong argument to the template.</p>
<p>While I understand that it is difficult with multiple
inheritance to provide some keyword base or super to access the
base class, RTTI with type_info could provide some mechanism. This
is just one example for the shortages of the standard RTTI. While
it wouldn't have put much burden on the compiler implementers to
provide a full reflection functionality like java.lang.reflect, it
would have been a great relief for programmers who need some
meta-class facilities.</p>
<pre class="programlisting">
class CBHandler {
public:
 virtual ~CBHandler() {}
 virtual void handle(CBException &amp;) const=0;
};


class IOHandler : public CBHandler {
public:
 virtual void handle(CBException &amp;e) const
 {
  IOException *ioe =
   dynamic_cast&lt;IOException *&gt;(&amp;e);
  if (ioe == 0) { terminate(), abort(); }
  // handle the exception-here just throw it
  throw(*ioe);
 }
};
</pre>
<p>Just one concrete handler is given here as an example. This one
throws the exception to handle (hence the derivation of CBException
from std::exception). Another handler could do anything, for which
it might need some data. This would be given by the constructor.
Note that handlers are created and destroyed at &quot;safe&quot; times, i.e.
not while an exception is waiting for handling. So, no empty
exception specifications are necessary for constructors and
destructors.</p>
<p>In handle(), if the exception is no IOException (the only we are
prepared to handle), something went definitely wrong and the
program is terminated, either by terminate(), or, if that returns,
by abort().</p>
<p>void is definitely not a good return type for handle(), as it
cannot tell the raising function whether the problem was
successfully handled or not. But any status type would probably do
(depending on the actual environment).</p>
<pre class="programlisting">
class CBManager {
public:
 const CBHandler *getHandler(
  const type_info &amp;et,
  const CBException &amp;e ) const throw() {
  std::map&lt;const char*,
           const CBHandler*&gt;::iterator hp =
   handlers.find(et.name());
  if (hp != handlers.end())
  { return hp-&gt;second; }
  else { return 0; }
 }
 const CBHandler *registerHandler(
  const type_info &amp;et,
  const CBHandler *newH) {
  const CBHandler *oldH = 0;
  std::map&lt;const char*,
           const CBHandler*&gt;::iterator hp =
   handlers.find(et.name());
  if (hp != handlers.end())
  {// handler already registered
   oldH = hp-&gt;second;
   if (newH) { hp-&gt;second = newH; }
   else { handlers.erase(hp); }
  }
  else { handlers[et.name()] = newH; }
  return oldH;
 }
private:
 std::map&lt;const char*,
          const CBHandler *&gt; handlers;
};

CBManager *currentCBManager() throw();
</pre>
<p>With already using two patterns in this small system, you might
think that CBManager would be a good candidate for yet another
pattern, namely Singleton. But this is not a good idea. Though at
any one time only one manager is valid (which is returned by
currentCBManager()), there could be other instances of CBManager
around so you could easily replace the whole set of handlers at
once by just swapping complete manager objects. And for
multi-threaded applications you definitely need at least one
separate instance for each thread.</p>
<p>currentCBManger() is declared here, but it is the responsibility
of the application to implement this function.</p>
<pre class="programlisting">
CBManager globalCBManager;
CBManager *currentCBManager() throw()
{ return &amp;globalCBManager; }
void f2() {
 ReadException(
  &quot;Something went wrong&quot;).raise();
}
void f1() {
 try { f2(); }
 catch (const IOException &amp;ioe)
 { std::cerr &lt;&lt; ioe.what() &lt;&lt; std::endl; }
}
int main() {
 IOHandler ioh;
 const CBHandler *oldH =
  globalCBManager.registerHandler(
    typeid(IOException), &amp;ioh);
 f1();
 globalCBManager.registerHandler(
   typeid(IOException), oldH);
 return 0;
}
</pre>
<p>In this simple example currentCBManager() returns just the
address of a global instance.</p>
<p>main() creates a local object of IOHandler and registers it. It
is therefore also responsible for deregistering the handler and
reinstalling the previous one. Though the handler is registered in
main(), the exception thrown by this handler is caught in f1().</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e101" id="d0e101"></a>Summary</h2>
</div>
<p>C++ standard exceptions are not the only way to handle
exceptional events. There are several other viable mechanisms for
that purpose. I personally prefer the callback mechanism as it
provides greatest flexibility. However, though the mechanism for
finding a registered callback for a given exception it quite
similar to finding a matching catch for a thrown exception, there
is no compiler support for it and so you have to implement your
own. Therefore the performance for the callback mechanism is
probably worse than throwing an exception, and it is even worse if
the handler itself just decides to throw. As this only happens if a
real exception occurs, this doesn't really matter.</p>
</div>
<div class="bibliography">
<div class="titlepage">
<h2><a name="d0e106" id="d0e106"></a>References</h2>
</div>
<div class="bibliomixed"><a name="Nordberg" id="Nordberg"></a>
<p class="bibliomixed">[Nordberg] Martin E. Nordberg: Default and
Extrinsic Visitor, in: Robert C. Martin, Dirk Riehle, Frank
Buschmann (eds.): <span class="citetitle"><i class=
"citetitle">Pattern Languages of Program Design 3</i></span>,
Addison-Wesley 1998, ISBN 0-201-31011-2</p>
</div>
<div class="bibliomixed"><a name="GoF" id="GoF"></a>
<p class="bibliomixed">[GoF] Erich Gamma, Richard Helm, Ralph
Johnson, John Vlissides: <span class="citetitle"><i class=
"citetitle">Design Patterns</i></span>, Addison-Wesley 1994, ISBN
0-201-63361-2</p>
</div>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
