CppAD: A C++ Algorithmic Differentiation Package  20130918
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-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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines