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