GetFEM  5.4.3
gmm_except.h
Go to the documentation of this file.
1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2002-2020 Yves Renard
5 
6  This file is a part of GetFEM
7 
8  GetFEM is free software; you can redistribute it and/or modify it
9  under the terms of the GNU Lesser General Public License as published
10  by the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version along with the GCC Runtime Library
12  Exception either version 3.1 or (at your option) any later version.
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16  License and GCC Runtime Library Exception for more details.
17  You should have received a copy of the GNU Lesser General Public License
18  along with this program; if not, write to the Free Software Foundation,
19  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20 
21  As a special exception, you may use this file as it is a part of a free
22  software library without restriction. Specifically, if other files
23  instantiate templates or use macros or inline functions from this file,
24  or you compile this file and link it with other files to produce an
25  executable, this file does not by itself cause the resulting executable
26  to be covered by the GNU Lesser General Public License. This exception
27  does not however invalidate any other reasons why the executable file
28  might be covered by the GNU Lesser General Public License.
29 
30 ===========================================================================*/
31 
32 /** @file gmm_except.h
33  @author Yves Renard <Yves.Renard@insa-lyon.fr>
34  @author Julien Pommier <Julien.Pommier@insa-toulouse.fr>
35  @date September 01, 2002.
36  @brief Definition of basic exceptions.
37 */
38 
39 #ifndef GMM_EXCEPT_H__
40 #define GMM_EXCEPT_H__
41 
42 #include <sstream>
43 #include "gmm_std.h"
45 
46 
47 //provides external implementation of gmm_exception and logging.
48 
49 namespace gmm {
50 
51 /* *********************************************************************** */
52 /* GetFEM generic errors. */
53 /* *********************************************************************** */
54 
55  // std logic_error with error level information
56  class gmm_error: public std::logic_error {
57  public:
58  gmm_error(const std::string& what_arg, int errorLevel = 1):
59  std::logic_error (what_arg), errorLevel_(errorLevel) {}
60  int errLevel() const { return errorLevel_; }
61 
62  private:
63  int errorLevel_;
64  };
65 
66 #ifdef GMM_HAVE_PRETTY_FUNCTION
67 # define GMM_PRETTY_FUNCTION __PRETTY_FUNCTION__
68 #elif _MSC_VER
69 # define GMM_PRETTY_FUNCTION __FUNCTION__
70 #else
71 # define GMM_PRETTY_FUNCTION ""
72 #endif
73 
74 
75  // Errors : GMM_THROW should not be used on its own.
76  // GMM_ASSERT1 : Non-maskable errors. Typically for in/ouput and
77  // when the test do not significantly reduces the performance.
78  // GMM_ASSERT2 : All tests which are potentially performance
79  // consuming. Not hidden by default. Hidden when NDEBUG is
80  // defined.
81  // GMM_ASSERT3 : For internal checks. Hidden by default. Active
82  // only when DEBUG_MODE is defined.
83  // __EXCEPTIONS is defined by gcc, _CPPUNWIND is defined by visual c++
84 #if defined(__EXCEPTIONS) || defined(_CPPUNWIND)
85  inline void short_error_throw(const char *file, int line, const char *func,
86  const char *errormsg) {
87  std::stringstream msg__;
88  msg__ << "Error in " << file << ", line " << line << " " << func
89  << ": \n" << errormsg << std::ends;
90  throw gmm::gmm_error(msg__.str());
91  }
92 # define GMM_THROW_(type, errormsg) { \
93  std::stringstream msg__; \
94  msg__ << "Error in " << __FILE__ << ", line " \
95  << __LINE__ << " " << GMM_PRETTY_FUNCTION << ": \n" \
96  << errormsg << std::ends; \
97  throw (type)(msg__.str()); \
98  }
99 
100 # define GMM_THROW_AT_LEVEL(errormsg, level) \
101  { \
102  std::stringstream msg; \
103  msg << "Error in " << __FILE__ << ", line " \
104  << __LINE__ << " " << GMM_PRETTY_FUNCTION << ": \n" \
105  << errormsg << std::ends; \
106  throw gmm::gmm_error(msg.str(), level); \
107  }
108 
109 #else
110 #ifndef _MSC_VER
111 # define abort_no_return() ::abort()
112 #else
113 // apparently ::abort() on windows is not declared with __declspec(noreturn) so the compiler spits a lot of warnings when abort is used.
114 # define abort_no_return() { assert("GMM ABORT"==0); throw "GMM ABORT"; }
115 #endif
116 
117  inline void short_error_throw(const char *file, int line, const char *func,
118  const char *errormsg) {
119  std::stringstream msg__;
120  msg__ << "Error in " << file << ", line " << line << " " << func
121  << ": \n" << errormsg << std::ends;
122  std::cerr << msg__.str() << std::endl;
123  abort_no_return();
124  }
125 
126 # define GMM_THROW_(type, errormsg) { \
127  std::stringstream msg__; \
128  msg__ << "Error in " << __FILE__ << ", line " \
129  << __LINE__ << " " << GMM_PRETTY_FUNCTION << ": \n" \
130  << errormsg; \
131  std::cerr << msg__.str() << std::endl; \
132  abort_no_return(); \
133  }
134 
135 # define GMM_THROW_AT_LEVEL(errormsg, level) \
136  { \
137  std::stringstream msg__; \
138  msg__ << "Error in " << __FILE__ << ", line " \
139  << __LINE__ << " " << GMM_PRETTY_FUNCTION << ": \n" \
140  << errormsg << " at level " << level; \
141  std::cerr << msg__.str() << std::endl; \
142  abort_no_return(); \
143  }
144 #endif
145 
146 
147 inline void GMM_THROW() {}
148 #define GMM_THROW(a, b) { GMM_THROW_(a,b); gmm::GMM_THROW(); }
149 
150 # define GMM_THROW_DEFAULT(errormsg) GMM_THROW_AT_LEVEL(errormsg, 1)
151 
152 // This allows not to compile some assertions
153 #ifndef GMM_ASSERT_LEVEL
154 #if defined(NDEBUG)
155 # define GMM_ASSERT_LEVEL 1
156 #elif defined(DEBUG_MODE)
157 # define GMM_ASSERT_LEVEL 3
158 #else
159 # define GMM_ASSERT_LEVEL 2
160 #endif
161 #endif
162 
163 
164 # define GMM_ASSERT1(test, errormsg) { if (!(test)) GMM_THROW_AT_LEVEL(errormsg, 1); }
165 
166 #if GMM_ASSERT_LEVEL < 2
167 # define GMM_ASSERT2(test, errormsg) {}
168 # define GMM_ASSERT3(test, errormsg) {}
169 #elif GMM_ASSERT_LEVEL < 3
170 # define GMM_ASSERT2(test, errormsg){ if (!(test)) GMM_THROW_AT_LEVEL(errormsg, 2); }
171 # define GMM_ASSERT3(test, errormsg){}
172 #else
173 # define GMM_ASSERT2(test, errormsg){ if (!(test)) GMM_THROW_AT_LEVEL(errormsg, 2); }
174 # define GMM_ASSERT3(test, errormsg){ if (!(test)) GMM_THROW_AT_LEVEL(errormsg, 3); }
175 #endif
176 
177 /* *********************************************************************** */
178 /* GetFEM warnings. */
179 /* *********************************************************************** */
180 
181  // This allows not to compile some Warnings
182 #ifndef GMM_WARNING_LEVEL
183 # define GMM_WARNING_LEVEL 4
184 #endif
185 
186  // Warning levels : 0 always printed
187  // 1 very important : specify a possible error in the code.
188  // 2 important : specify a default of optimization for inst.
189  // 3 remark
190  // 4 ignored by default.
191 
192 #define GMM_WARNING_MSG(level_, thestr) { \
193  std::stringstream msg__; \
194  msg__ << "Level " << level_ << " Warning in " << __FILE__ << ", line " \
195  << __LINE__ << ": " << thestr; \
196  gmm::feedback_manager::manage()->send(msg__.str(), gmm::FeedbackType::WARNING, level_); \
197 }
198 
199 #define GMM_WARNING0(thestr) GMM_WARNING_MSG(0, thestr)
200 
201 
202 #if GMM_WARNING_LEVEL > 0
203 # define GMM_WARNING1(thestr) \
204  { if (1 <= gmm::feedback_manager::warning_level()) GMM_WARNING_MSG(1, thestr) }
205 #else
206 # define GMM_WARNING1(thestr) {}
207 #endif
208 
209 #if GMM_WARNING_LEVEL > 1
210 # define GMM_WARNING2(thestr) \
211  { if (2 <= gmm::feedback_manager::warning_level()) GMM_WARNING_MSG(2, thestr) }
212 #else
213 # define GMM_WARNING2(thestr) {}
214 #endif
215 
216 #if GMM_WARNING_LEVEL > 2
217 # define GMM_WARNING3(thestr) \
218  { if (3 <= gmm::feedback_manager::warning_level()) GMM_WARNING_MSG(3, thestr) }
219 #else
220 # define GMM_WARNING3(thestr) {}
221 #endif
222 
223 #if GMM_WARNING_LEVEL > 3
224 # define GMM_WARNING4(thestr) \
225  { if (4 <= gmm::feedback_manager::warning_level()) GMM_WARNING_MSG(4, thestr) }
226 #else
227 # define GMM_WARNING4(thestr) {}
228 #endif
229 
230 /* *********************************************************************** */
231 /* GetFEM traces. */
232 /* *********************************************************************** */
233 
234  // This allow not too compile some Warnings
235 #ifndef GMM_TRACES_LEVEL
236 # define GMM_TRACES_LEVEL 4
237 #endif
238 
239  // Traces levels : 0 always printed
240  // 1 Susceptible to occur once in a program.
241  // 2 Susceptible to occur occasionnaly in a program (10).
242  // 3 Susceptible to occur often (100).
243  // 4 Susceptible to occur very often (>1000).
244 
245 #define GMM_TRACE_MSG_MPI // for Parallelized version
246 #define GMM_TRACE_MSG(level_, thestr) { \
247  GMM_TRACE_MSG_MPI { \
248  std::stringstream msg__; \
249  msg__ << "Trace " << level_ << " in " << __FILE__ << ", line " \
250  << __LINE__ << ": " << thestr; \
251  gmm::feedback_manager::send(msg__.str(), gmm::FeedbackType::TRACE, level_); \
252  } \
253 }
254 
255 #define GMM_TRACE_SIMPLE_MSG(level_, thestr) { \
256  GMM_TRACE_MSG_MPI { \
257  std::stringstream msg__; \
258  msg__ << "Trace " << level_ << ": " << thestr; \
259  gmm::feedback_manager::send(msg__.str(), gmm::FeedbackType::TRACE, level_); \
260  } \
261 }
262 
263 #define GMM_TRACE0(thestr) GMM_TRACE_MSG(0, thestr)
264 #define GMM_SIMPLE_TRACE0(thestr) GMM_TRACE_MSG_SIMPLE(0, thestr)
265 
266 #if GMM_TRACES_LEVEL > 0
267 # define GMM_TRACE1(thestr) \
268  { if (1 <= gmm::feedback_manager::traces_level()) GMM_TRACE_MSG(1, thestr) }
269 # define GMM_SIMPLE_TRACE1(thestr) \
270  { if (1 <= gmm::feedback_manager::traces_level()) GMM_TRACE_SIMPLE_MSG(1, thestr) }
271 #else
272 # define GMM_TRACE1(thestr) {}
273 # define GMM_SIMPLE_TRACE1(thestr) {}
274 #endif
275 
276 #if GMM_TRACES_LEVEL > 1
277 # define GMM_TRACE2(thestr) \
278  { if (2 <= gmm::feedback_manager::traces_level()) GMM_TRACE_MSG(2, thestr) }
279 # define GMM_SIMPLE_TRACE2(thestr) \
280  { if (2 <= gmm::feedback_manager::traces_level()) GMM_TRACE_SIMPLE_MSG(2, thestr) }
281 #else
282 # define GMM_TRACE2(thestr) {}
283 # define GMM_SIMPLE_TRACE2(thestr) {}
284 #endif
285 
286 #if GMM_TRACES_LEVEL > 2
287 # define GMM_TRACE3(thestr) \
288  { if (3 <= gmm::feedback_manager::traces_level()) GMM_TRACE_MSG(3, thestr) }
289 # define GMM_SIMPLE_TRACE3(thestr) \
290  { if (3 <= gmm::feedback_manager::traces_level()) GMM_TRACE_SIMPLE_MSG(3, thestr) }
291 #else
292 # define GMM_TRACE3(thestr) {}
293 # define GMM_SIMPLE_TRACE3(thestr) {}
294 #endif
295 
296 #if GMM_TRACES_LEVEL > 3
297 # define GMM_TRACE4(thestr) \
298  { if (4 <= gmm::feedback_manager::traces_level()) GMM_TRACE_MSG(4, thestr) }
299 # define GMM_SIMPLE_TRACE4(thestr) \
300  { if (4 <= gmm::feedback_manager::traces_level()) GMM_TRACE_SIMPLE_MSG(4, thestr) }
301 #else
302 # define GMM_TRACE4(thestr) {}
303 # define GMM_SIMPLE_TRACE4(thestr) {}
304 #endif
305 
306 #define GMM_STANDARD_CATCH_ERROR \
307  catch(const gmm::gmm_error &e) \
308  { \
309  std::stringstream strStream; \
310  strStream << "============================================\n"; \
311  strStream << "| A GMM error has been detected !!! |\n"; \
312  strStream << "============================================\n"; \
313  strStream << e.what() << std::endl << std::endl; \
314  gmm::feedback_manager::send(strStream.str(), \
315  gmm::FeedbackType::ASSERT, e.errLevel()); \
316  gmm::feedback_manager::terminating_action(); \
317  } \
318  catch(const std::logic_error &e) \
319  { \
320  std::stringstream strStream; \
321  strStream << "============================================\n"; \
322  strStream << "| An error has been detected !!! |\n"; \
323  strStream << "============================================\n"; \
324  strStream << e.what() << std::endl << std::endl; \
325  gmm::feedback_manager::send(strStream.str(), \
326  gmm::FeedbackType::ASSERT, 0); \
327  gmm::feedback_manager::terminating_action(); \
328  } \
329  catch(const std::runtime_error &e) \
330  { \
331  std::stringstream strStream; \
332  strStream << "============================================\n"; \
333  strStream << "| A runtime error has been detected !!! |\n"; \
334  strStream << "============================================\n"; \
335  strStream << e.what() << std::endl << std::endl; \
336  gmm::feedback_manager::send(strStream.str(), \
337  gmm::FeedbackType::ASSERT, 0); \
338  gmm::feedback_manager::terminating_action(); \
339  } \
340  catch(const std::bad_alloc &) \
341  { \
342  std::stringstream strStream; \
343  strStream << "============================================\n"; \
344  strStream << "| A bad allocation has been detected !!! |\n"; \
345  strStream << "============================================\n"; \
346  gmm::feedback_manager::send(strStream.str(), \
347  gmm::FeedbackType::ASSERT, 0); \
348  gmm::feedback_manager::terminating_action(); \
349  } \
350  catch(const std::bad_typeid &) \
351  { \
352  std::stringstream strStream; \
353  strStream << "============================================\n"; \
354  strStream << "| A bad typeid has been detected !!! |\n"; \
355  strStream << "============================================\n"; \
356  gmm::feedback_manager::send(strStream.str(), \
357  gmm::FeedbackType::ASSERT, 0); \
358  gmm::feedback_manager::terminating_action(); \
359  } \
360  catch(const std::bad_exception &) \
361  { \
362  std::stringstream strStream; \
363  strStream << "============================================\n"; \
364  strStream << "| A bad exception has been detected !!! |\n"; \
365  strStream << "============================================\n"; \
366  gmm::feedback_manager::send(strStream.str(), \
367  gmm::FeedbackType::ASSERT, 0); \
368  gmm::feedback_manager::terminating_action(); \
369  } \
370  catch(const std::bad_cast &) \
371  { \
372  std::stringstream strStream; \
373  strStream << "============================================\n"; \
374  strStream << "| A bad_cast has been detected !!! |\n"; \
375  strStream << "============================================\n"; \
376  gmm::feedback_manager::send(strStream.str(), \
377  gmm::FeedbackType::ASSERT, 0); \
378  gmm::feedback_manager::terminating_action(); \
379  } \
380  catch(...) \
381  { \
382  std::stringstream strStream; \
383  strStream << "============================================\n"; \
384  strStream << "| An unknown error has been detected !!! |\n"; \
385  strStream << "============================================\n"; \
386  gmm::feedback_manager::send(strStream.str(), \
387  gmm::FeedbackType::ASSERT, 0); \
388  gmm::feedback_manager::terminating_action(); \
389  }
390  // catch(ios_base::failure) {
391  // std::cerr << "============================================\n";
392  // std::cerr << "| A ios_base::failure has been detected !!!|\n";
393  // std::cerr << "============================================\n";
394  // exit(1);
395  // }
396 
397 #if defined(__GNUC__) && (__GNUC__ > 3) && !defined(__clang__)
398 # define GMM_SET_EXCEPTION_DEBUG \
399  std::set_terminate(__gnu_cxx::__verbose_terminate_handler);
400 #else
401 # define GMM_SET_EXCEPTION_DEBUG
402 #endif
403 
404 } // namespace gmm
405 
406 #endif /* GMM_EXCEPT_H__ */
Support for run time management of trace, warning and assert feedback.
basic setup for gmm (includes, typedefs etc.)