CppAD: A C++ Algorithmic Differentiation Package  20171217
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
error_handler.hpp
Go to the documentation of this file.
1 # ifndef CPPAD_UTILITY_ERROR_HANDLER_HPP
2 # define CPPAD_UTILITY_ERROR_HANDLER_HPP
3 /* --------------------------------------------------------------------------
4 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
5 
6 CppAD is distributed under multiple licenses. This distribution is under
7 the terms of the
8  Eclipse Public License Version 1.0.
9 
10 A copy of this license is included in the COPYING file of this distribution.
11 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
12 -------------------------------------------------------------------------- */
13 
14 /*
15 $begin ErrorHandler$$
16 $spell
17  cppad.hpp
18  CppAD
19  exp
20  bool
21  const
22 $$
23 
24 $section Replacing the CppAD Error Handler$$
25 $mindex replace assert exception ErrorHandler$$
26 
27 $head Syntax$$
28 $codei%# include <cppad/utility/error_handler.hpp>
29 %$$
30 $codei%ErrorHandler %info%(%handler%)
31 %$$
32 $codei%ErrorHandler::Call(%known%, %line%, %file%, %exp%, %msg%)
33 %$$
34 
35 $head Constructor$$
36 When you construct a $code ErrorHandler$$ object,
37 the current CppAD error handler is replaced by $icode handler$$.
38 When the object is destructed, the previous CppAD error handler is restored.
39 
40 $subhead Parallel Mode$$
41 The $code ErrorHandler$$ constructor and destructor cannot be called in
42 $cref/parallel/ta_in_parallel/$$ execution mode.
43 Furthermore, this rule is not abided by, a raw C++ $code assert$$,
44 instead of one that uses this error handler, will be generated.
45 
46 $head Call$$
47 When $code ErrorHandler::Call$$ is called,
48 the current CppAD error handler is used to report an error.
49 This starts out as a default error handler and can be replaced
50 using the $code ErrorHandler$$ constructor.
51 
52 $head info$$
53 The object $icode info$$ is used to store information
54 that is necessary to restore the previous CppAD error handler.
55 This is done when the destructor for $icode info$$ is called.
56 
57 
58 $head handler$$
59 The argument $icode handler$$ has prototype
60 $codei%
61  void (*%handler%)
62  (bool, int, const char *, const char *, const char *);
63 %$$
64 When an error is detected,
65 it is called with the syntax
66 $codei%
67  %handler% (%known%, %line%, %file%, %exp%, %msg%)
68 %$$
69 This routine should not return; i.e., upon detection of the error,
70 the routine calling $icode handler$$ does not know how to proceed.
71 
72 $head known$$
73 The $icode handler$$ argument $icode known$$ has prototype
74 $codei%
75  bool %known%
76 %$$
77 If it is true, the error being reported is from a know problem.
78 
79 $head line$$
80 The $icode handler$$ argument $icode line$$ has prototype
81 $codei%
82  int %line%
83 %$$
84 It reports the source code line number where the error is detected.
85 
86 $head file$$
87 The $icode handler$$ argument $icode file$$ has prototype
88 $codei%
89  const char *%file%
90 %$$
91 and is a $code '\0'$$ terminated character vector.
92 It reports the source code file where the error is detected.
93 
94 $head exp$$
95 The $icode handler$$ argument $icode exp$$ has prototype
96 $codei%
97  const char *%exp%
98 %$$
99 and is a $code '\0'$$ terminated character vector.
100 It is a source code boolean expression that should have been true,
101 but is false,
102 and thereby causes this call to $icode handler$$.
103 
104 $head msg$$
105 The $icode handler$$ argument $icode msg$$ has prototype
106 $codei%
107  const char *%msg%
108 %$$
109 and is a $code '\0'$$ terminated character vector.
110 It reports the meaning of the error from the C++ programmers point of view.
111 
112 $children%
113  example/utility/error_handler.cpp%
114  cppad/core/cppad_assert.hpp
115 %$$
116 $head Example$$
117 The file
118 $cref error_handler.cpp$$
119 contains an example and test a test of using this routine.
120 It returns true if it succeeds and false otherwise.
121 
122 $end
123 ---------------------------------------------------------------------------
124 */
125 
126 # include <iostream>
127 
128 # include <cppad/configure.hpp>
130 # include <cassert>
131 # include <cstdlib>
132 
133 namespace CppAD { // BEGIN CppAD namespace
134 
136  template <class Base>
137  friend void parallel_ad(void);
138 public:
139  typedef void (*Handler)
140  (bool, int, const char *, const char *, const char *);
141 
142  // construct a new handler
144  { if( local::set_get_in_parallel(0) )
145  { bool known = true;
146  int line = __LINE__;
147  const char* file = __FILE__;
148  const char* exp = "! local::set_get_in_parallel(0)";
149  const char* msg =
150  "Using ErrorHandler constructor in parallel mode.";
151  Call(known, line, file, exp, msg);
152  }
153  Current() = handler;
154  }
155 
156  // destructor for an error handler
158  { if( local::set_get_in_parallel(0) )
159  { bool known = true;
160  int line = __LINE__;
161  const char* file = __FILE__;
162  const char* exp = "! local::set_get_in_parallel(0)";
163  const char* msg =
164  "Using ErrorHandler destructor in parallel mode.";
165  Call(known, line, file, exp, msg);
166  }
167  Current() = previous;
168  }
169 
170  // report an error
171  static void Call(
172  bool known,
173  int line ,
174  const char *file ,
175  const char *exp ,
176  const char *msg )
177  { Handler handler = Current();
178  handler(known, line, file, exp, msg);
179  }
180 
181 private:
183 
184  // The default error handler
185  static void Default(
186  bool known,
187  int line ,
188  const char *file ,
189  const char *exp ,
190  const char *msg )
191  { using std::cerr;
192  using std::endl;
193 
194  cerr << CPPAD_PACKAGE_STRING;
195  if( known )
196  cerr << " error from a known source:" << endl;
197  else cerr << " error from unknown source" << endl;
198  if( msg[0] != '\0' )
199  cerr << msg << endl;
200  cerr << "Error detected by false result for" << endl;
201  cerr << " " << exp << endl;
202  cerr << "at line " << line << " in the file " << endl;
203  cerr << " " << file << endl;
204 
205  // terminate program execution
206  assert(false);
207 
208  // termination when NDEBUG is defined
209  std::exit(1);
210  }
211 
212  // current error handler
213  static Handler &Current(void)
214  { static bool first_call = true;
215  static Handler current = Default;
216  if( first_call )
217  { if( local::set_get_in_parallel(0) )
218  { bool known = false;
219  int line = __LINE__;
220  const char* file = __FILE__;
221  const char* exp = "";
222  const char* msg = "";
223  Call(known, line, file, exp, msg);
224  }
225  first_call = false;
226  }
227  return current;
228  }
229 };
230 
231 } // END CppAD namespace
232 
233 
234 
235 # endif
ErrorHandler(Handler handler)
static void Default(bool known, int line, const char *file, const char *exp, const char *msg)
static bool set_get_in_parallel(bool(*in_parallel_new)(void), bool set=false)
Set and call the routine that determine if we are in parallel execution mode.
const Handler previous
AD< Base > exp(const AD< Base > &x)
static void Call(bool known, int line, const char *file, const char *exp, const char *msg)
File used to set and get user in_parallel routine.
friend void parallel_ad(void)
Enable parallel execution mode with AD&lt;Base&gt; by initializing static variables that my be used...
Definition: parallel_ad.hpp:79
static Handler & Current(void)
void(* Handler)(bool, int, const char *, const char *, const char *)