CppAD: A C++ Algorithmic Differentiation Package
20130102
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_ERROR_HANDLER_INCLUDED 00003 # define CPPAD_ERROR_HANDLER_INCLUDED 00004 /* -------------------------------------------------------------------------- 00005 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell 00006 00007 CppAD is distributed under multiple licenses. This distribution is under 00008 the terms of the 00009 Eclipse 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 $codei%ErrorHandler %info%(%handler%) 00034 %$$ 00035 $codei%ErrorHandler::Call(%known%, %line%, %file%, %exp%, %msg%) 00036 %$$ 00037 00038 $head Constructor$$ 00039 When you construct a $code ErrorHandler$$ object, 00040 the current CppAD error handler is replaced by $icode handler$$. 00041 When the object is destructed, the previous CppAD error handler is restored. 00042 00043 $subhead Parallel Mode$$ 00044 $index parallel, ErrorHandler$$ 00045 $index ErrorHandler, parallel$$ 00046 The $code ErrorHandler$$ constructor and destructor cannot be called in 00047 $cref/parallel/ta_in_parallel/$$ execution mode. 00048 Furthermore, this rule is not abided by, a raw C++ $code assert$$, 00049 instead of one that uses this error handler, will be generated. 00050 00051 $head Call$$ 00052 When $code ErrorHandler::Call$$ is called, 00053 the current CppAD error handler is used to report an error. 00054 This starts out as a default error handler and can be replaced 00055 using the $code ErrorHandler$$ constructor. 00056 00057 $head info$$ 00058 The object $icode info$$ is used to store information 00059 that is necessary to restore the previous CppAD error handler. 00060 This is done when the destructor for $icode info$$ is called. 00061 00062 00063 $head handler$$ 00064 The argument $icode handler$$ has prototype 00065 $codei% 00066 void (*%handler%) 00067 (bool, int, const char *, const char *, const char *); 00068 %$$ 00069 When an error is detected, 00070 it is called with the syntax 00071 $codei% 00072 %handler% (%known%, %line%, %file%, %exp%, %msg%) 00073 %$$ 00074 This routine should not return; i.e., upon detection of the error, 00075 the routine calling $icode handler$$ does not know how to proceed. 00076 00077 $head known$$ 00078 The $icode handler$$ argument $icode known$$ has prototype 00079 $codei% 00080 bool %known% 00081 %$$ 00082 If it is true, the error being reported is from a know problem. 00083 00084 $head line$$ 00085 The $icode handler$$ argument $icode line$$ has prototype 00086 $codei% 00087 int %line% 00088 %$$ 00089 It reports the source code line number where the error is detected. 00090 00091 $head file$$ 00092 The $icode handler$$ argument $icode file$$ has prototype 00093 $codei% 00094 const char *%file% 00095 %$$ 00096 and is a $code '\0'$$ terminated character vector. 00097 It reports the source code file where the error is detected. 00098 00099 $head exp$$ 00100 The $icode handler$$ argument $icode exp$$ has prototype 00101 $codei% 00102 const char *%exp% 00103 %$$ 00104 and is a $code '\0'$$ terminated character vector. 00105 It is a source code boolean expression that should have been true, 00106 but is false, 00107 and thereby causes this call to $icode handler$$. 00108 00109 $head msg$$ 00110 The $icode handler$$ argument $icode msg$$ has prototype 00111 $codei% 00112 const char *%msg% 00113 %$$ 00114 and is a $code '\0'$$ terminated character vector. 00115 It reports the meaning of the error from the C++ programmers point of view. 00116 00117 $children% 00118 example/error_handler.cpp% 00119 cppad/local/cppad_assert.hpp 00120 %$$ 00121 $head Example$$ 00122 The file 00123 $cref error_handler.cpp$$ 00124 contains an example and test a test of using this routine. 00125 It returns true if it succeeds and false otherwise. 00126 00127 $end 00128 --------------------------------------------------------------------------- 00129 */ 00130 00131 # include <iostream> 00132 00133 # ifdef _OPENMP 00134 # include <omp.h> 00135 # endif 00136 00137 # include <cppad/configure.hpp> 00138 # include <cppad/local/cppad_assert.hpp> 00139 # include <cassert> 00140 # include <cstdlib> 00141 00142 // Cannot use the CPPAD_ASSERT_* macros here because they inturn use the 00143 // error handler. So this code generates a raw assert. 00144 # ifdef _OPENMP 00145 # include <omp.h> 00146 # define CPPAD_ASSERT_NOT_PARALLEL \ 00147 assert( ! omp_in_parallel() ); 00148 # else 00149 # define CPPAD_ASSERT_NOT_PARALLEL 00150 # endif 00151 00152 namespace CppAD { // BEGIN CppAD namespace 00153 00154 class ErrorHandler { 00155 template <class Base> 00156 friend void parallel_ad(void); 00157 public: 00158 typedef void (*Handler) 00159 (bool, int, const char *, const char *, const char *); 00160 00161 00162 // construct an handler 00163 ErrorHandler(Handler handler) : previous( Current() ) 00164 { CPPAD_ASSERT_NOT_PARALLEL; 00165 Current() = handler; 00166 } 00167 00168 // destructor for an error handler 00169 ~ErrorHandler(void) 00170 { CPPAD_ASSERT_NOT_PARALLEL; 00171 Current() = previous; 00172 } 00173 00174 // report an error 00175 static void Call( 00176 bool known, 00177 int line , 00178 const char *file , 00179 const char *exp , 00180 const char *msg ) 00181 { Handler handler = Current(); 00182 handler(known, line, file, exp, msg); 00183 } 00184 00185 private: 00186 const Handler previous; 00187 00188 // The default error handler 00189 static void Default( 00190 bool known, 00191 int line , 00192 const char *file , 00193 const char *exp , 00194 const char *msg ) 00195 { using std::cerr; 00196 using std::endl; 00197 00198 cerr << CPPAD_PACKAGE_STRING; 00199 if( known ) 00200 cerr << " error from a known source:" << endl; 00201 else cerr << " error from unknown source" << endl; 00202 if( msg[0] != '\0' ) 00203 cerr << msg << endl; 00204 cerr << "Error detected by false result for" << endl; 00205 cerr << " " << exp << endl; 00206 cerr << "at line " << line << " in the file " << endl; 00207 cerr << " " << file << endl; 00208 00209 // terminate program execution 00210 assert(false); 00211 00212 // termination when NDEBUG is defined 00213 std::exit(1); 00214 } 00215 00216 // current error handler 00217 static Handler &Current(void) 00218 { 00219 # ifndef NDEBUG 00220 # ifdef _OPENMP 00221 // This assert would be a CppAD error (not user error) 00222 static bool first_call = true; 00223 if( first_call ) 00224 { assert( ! omp_in_parallel() ); 00225 first_call = false; 00226 } 00227 # endif 00228 # endif 00229 static Handler current = Default; 00230 return current; 00231 } 00232 }; 00233 00234 } // END CppAD namespace 00235 00236 00237 00238 # endif