CppAD: A C++ Algorithmic Differentiation Package 20110419
error_handler.hpp
Go to the documentation of this file.
00001 /* $Id$ */
00002 # ifndef CPPAD_ERROR_HANDLER_INCLUDED
00003 # define CPPAD_ERROR_HANDLER_INCLUDED
00004 /* --------------------------------------------------------------------------
00005 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-10 Bradley M. Bell
00006 
00007 CppAD is distributed under multiple licenses. This distribution is under
00008 the terms of the 
00009                     Common Public License Version 1.0.
00010 
00011 A copy of this license is included in the COPYING file of this distribution.
00012 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
00013 -------------------------------------------------------------------------- */
00014 
00015 /*
00016 $begin ErrorHandler$$
00017 $spell
00018         cppad.hpp
00019         CppAD
00020         exp
00021         bool
00022         const
00023 $$
00024 
00025 $section Replacing the CppAD Error Handler$$
00026 $index error, handler$$
00027 $index handler, error$$
00028 $index replace, error handler$$
00029 $index assert, error handler$$
00030 $index exception, error handler$$
00031 
00032 $head Syntax$$
00033 $syntax%ErrorHandler %info%(%handler%)%$$
00034 $pre
00035 $$
00036 $syntax%ErrorHandler::Call(%known%, %line%, %file%, %exp%, %msg%)%$$
00037 
00038 
00039 $head Constructor$$
00040 When you construct a $code ErrorHandler$$ object,
00041 the current CppAD error handler is replaced by $italic handler$$.
00042 When the object is destructed, the previous CppAD error handler is restored.
00043 
00044 $head Call$$
00045 When $code ErrorHandler::Call$$ is called,
00046 the current CppAD error handler is used to report an error.
00047 This starts out as a default error handler and can be replaced
00048 using the $code ErrorHandler$$ constructor. 
00049 
00050 $head info$$
00051 The object $italic info$$ is used to store information
00052 that is necessary to restore the previous CppAD error handler.
00053 This is done when the destructor for $italic info$$ is called.
00054 
00055 
00056 $head handler$$
00057 The argument $italic handler$$ has prototype
00058 $syntax%
00059         void (*%handler%) 
00060                 (bool, int, const char *, const char *, const char *);
00061 %$$
00062 When an error is detected,
00063 it is called with the syntax
00064 $syntax%
00065         %handler% (%known%, %line%, %file%, %exp%, %msg%)
00066 %$$
00067 This routine should not return; i.e., upon detection of the error,
00068 the routine calling $italic handler$$ does not know how to proceed.
00069 
00070 $head known$$
00071 The $italic handler$$ argument $italic known$$ has prototype
00072 $syntax%
00073         bool %known%
00074 %$$
00075 If it is true, the error being reported is from a know problem.
00076 
00077 $head line$$
00078 The $italic handler$$ argument $italic line$$ has prototype
00079 $syntax%
00080         int %line%
00081 %$$
00082 It reports the source code line number where the error is detected. 
00083 
00084 $head file$$
00085 The $italic handler$$ argument $italic file$$ has prototype
00086 $syntax%
00087         const char *%file%
00088 %$$
00089 and is a $code '\0'$$ terminated character vector.
00090 It reports the source code file where the error is detected. 
00091 
00092 $head exp$$
00093 The $italic handler$$ argument $italic exp$$ has prototype
00094 $syntax%
00095         const char *%exp%
00096 %$$
00097 and is a $code '\0'$$ terminated character vector.
00098 It is a source code boolean expression that should have been true, 
00099 but is false,
00100 and thereby causes this call to $italic handler$$.
00101 
00102 $head msg$$
00103 The $italic handler$$ argument $italic msg$$ has prototype
00104 $syntax%
00105         const char *%msg%
00106 %$$
00107 and is a $code '\0'$$ terminated character vector.
00108 It reports the meaning of the error from the C++ programmers point of view.
00109 
00110 $children%
00111         example/error_handler.cpp%
00112         cppad/local/cppad_assert.hpp
00113 %$$
00114 $head Example$$
00115 The file
00116 $xref/ErrorHandler.cpp/$$
00117 contains an example and test a test of using this routine.
00118 It returns true if it succeeds and false otherwise.
00119 
00120 $end
00121 ---------------------------------------------------------------------------
00122 */
00123 
00124 # include <iostream>
00125 
00126 # ifdef _OPENMP
00127 # include <omp.h>
00128 # endif
00129 
00130 # include <cppad/configure.hpp>
00131 # include <cassert>
00132 # include <cstdlib>
00133 
00134 namespace CppAD { // BEGIN CppAD namespace
00135 
00136 class ErrorHandler {
00137 public:
00138         typedef void (*Handler) 
00139                 (bool, int, const char *, const char *, const char *);
00140 
00141 
00142         // construct an handler
00143         ErrorHandler(Handler handler) : previous( Current() )
00144         {       Current() = handler; }
00145 
00146         // destructor for an error handler
00147         ~ErrorHandler(void)
00148         {       Current() = previous; }
00149         
00150         // report an error
00151         static void Call(
00152                 bool        known, 
00153                 int         line , 
00154                 const char *file , 
00155                 const char *exp  ,
00156                 const char *msg  )
00157         {       Handler handler = Current();
00158                 handler(known, line, file, exp, msg);
00159         }
00160 
00161 private:
00162         const Handler previous;
00163 
00164         // The default error handler
00165         static void Default(
00166                 bool        known, 
00167                 int         line , 
00168                 const char *file , 
00169                 const char *exp  ,
00170                 const char *msg  )
00171         {       using std::cerr;
00172                 using std::endl;
00173 
00174 # ifdef _OPENMP
00175                 int thread_num = omp_get_thread_num();
00176 # endif
00177 
00178 // if OpenMP multi-threading, only run output on master thread
00179 # ifdef _OPENMP
00180 # pragma omp master
00181 # endif
00182                 {
00183                         cerr << CPPAD_PACKAGE_STRING;
00184                         if( known )
00185                                 cerr << " error from a known source:" << endl;
00186                         else    cerr << " error from unknown source"  << endl;
00187                         if( msg[0] != '\0' )
00188                                 cerr << msg << endl;
00189                         cerr << "Error detected by false result for"  << endl;
00190                         cerr << "    "     << exp                     << endl;
00191                         cerr << "at line " << line << " in the file " << endl;
00192                         cerr << "    "     << file                    << endl;
00193 # ifdef _OPENMP
00194                         cerr << "OpenMP: thread_num = " << thread_num << endl;
00195 # endif
00196 
00197                         // terminate program execution
00198                         assert(false);
00199 
00200                         // termination when NDEBUG is defined
00201                         std::exit(1);
00202                 }
00203 // pragma omp master
00204         }
00205 
00206         // current error handler
00207         static Handler &Current(void)
00208         {       static Handler current = Default;
00209                 return current;
00210         }
00211 };
00212 
00213 } // END CppAD namespace
00214 
00215 
00216 
00217 # endif