Nektar++
ErrorUtil.hpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: ErrorUtil.hpp
4 //
5 // For more information, please see: http://www.nektar.info
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description: error related utilities
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 #ifndef ERRORUTIL_HPP
35 #define ERRORUTIL_HPP
36 
37 #include <iostream>
38 #include <stdexcept>
39 #include <string>
40 
41 #include <boost/core/ignore_unused.hpp>
42 
44 
45 #if defined(NEKTAR_USE_MPI)
46 #include <mpi.h>
47 #endif
48 
49 #ifndef _WIN32
50 #include <execinfo.h>
51 #endif
52 
53 namespace Nektar
54 {
55 
56 class ErrorUtil
57 {
58 public:
59  class NekError : public std::runtime_error
60  {
61  public:
62  NekError(const std::string &message) : std::runtime_error(message)
63  {
64  }
65  };
66 
67  enum ErrType
68  {
70  ewarning
71  };
72 
73  inline static void SetErrorStream(std::ostream &o)
74  {
75  m_outStream = &o;
76  }
77 
78  inline static void SetPrintBacktrace(bool b)
79  {
80  m_printBacktrace = b;
81  }
82 
83  inline static bool HasCustomErrorStream()
84  {
85  return m_outStream != &std::cerr;
86  }
87 
88  inline static void Error(ErrType type, const char *routine, int lineNumber,
89  const char *msg, unsigned int level,
90  bool DoComm = false)
91  {
92  boost::ignore_unused(DoComm);
93 
94  // The user of outStream is primarily for the unit tests. The unit
95  // tests often generate errors on purpose to make sure invalid usage is
96  // flagged appropriately. Printing the error messages to cerr made the
97  // unit test output hard to parse.
98 
99  std::string baseMsg =
100  "Level " + std::to_string(level) + " assertion violation\n";
101 #if defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)
102  baseMsg += "Where : " + std::string(routine) + "[" +
103  std::to_string(lineNumber) + "]\nMessage : ";
104 #else
105  boost::ignore_unused(routine, lineNumber);
106 #endif
107  baseMsg += std::string(msg);
108 
109  // Default rank is zero. If MPI used and initialised, populate with
110  // the correct rank. Messages are only printed on rank zero.
111  int rank = 0;
112 #if defined(NEKTAR_USE_MPI) && !defined(NEKTAR_USE_CWIPI)
113  int flag = 0;
114  if (DoComm)
115  {
116  MPI_Initialized(&flag);
117  if (flag)
118  {
119  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
120  }
121  }
122 #else
123  boost::ignore_unused(DoComm);
124 #endif
125 
126  std::string btMessage("");
127 #if defined(NEKTAR_FULLDEBUG)
128 #ifndef _WIN32
129  if (m_printBacktrace)
130  {
131  void *btArray[40];
132  int btSize;
133  char **btStrings;
134 
135  btSize = backtrace(btArray, 40);
136  btStrings = backtrace_symbols(btArray, btSize);
137 
138  for (int i = 0; i < btSize; ++i)
139  {
140  btMessage += std::string(btStrings[i]) + "\n";
141  }
142  free(btStrings);
143  }
144 #endif
145 #endif
146 
147  switch (type)
148  {
149  case efatal:
150  if (!rank)
151  {
152  if (m_printBacktrace)
153  {
154  (*m_outStream) << btMessage;
155  }
156  (*m_outStream) << "Fatal : " << baseMsg << std::endl;
157  }
158 
159 #if defined(NEKTAR_USE_MPI) && !defined(NEKTAR_USE_CWIPI)
160  if (DoComm)
161  {
162  if (flag)
163  {
164  MPI_Barrier(MPI_COMM_WORLD);
165  }
166  }
167 #endif
168  throw NekError(baseMsg);
169  break;
170  case ewarning:
171  if (!rank)
172  {
173  if (m_printBacktrace)
174  {
175  (*m_outStream) << btMessage;
176  }
177  (*m_outStream) << "Warning : " << baseMsg << std::endl;
178  }
179  break;
180  default:
181  (*m_outStream)
182  << "Unknown warning type: " << baseMsg << std::endl;
183  }
184  }
185 
186  inline static void Error(ErrType type, const char *routine, int lineNumber,
187  const std::string &msg, unsigned int level)
188  {
189  Error(type, routine, lineNumber, msg.c_str(), level);
190  }
191 
192  inline static void Error(ErrType type, const char *routine, int lineNumber,
193  const char *msg)
194  {
195  Error(type, routine, lineNumber, msg, 0);
196  }
197 
198 private:
199  LIB_UTILITIES_EXPORT static std::ostream *m_outStream;
201 };
202 
203 /// Assert Level 0 -- Fundamental assert which
204 /// is used whether in FULLDEBUG, DEBUG or OPT
205 /// compilation mode. This level assert is
206 /// considered code critical, even under
207 /// optimized compilation.
208 
209 #define NEKERROR(type, msg) \
210  Nektar::ErrorUtil::Error(type, __FILE__, __LINE__, msg, 0);
211 
212 #define ROOTONLY_NEKERROR(type, msg) \
213  Nektar::ErrorUtil::Error(type, __FILE__, __LINE__, msg, 0, true);
214 
215 #define ASSERTL0(condition, msg) \
216  if (!(condition)) \
217  { \
218  Nektar::ErrorUtil::Error(Nektar::ErrorUtil::efatal, __FILE__, \
219  __LINE__, msg, 0); \
220  }
221 
222 #define WARNINGL0(condition, msg) \
223  if (!(condition)) \
224  { \
225  Nektar::ErrorUtil::Error(Nektar::ErrorUtil::ewarning, __FILE__, \
226  __LINE__, msg, 0); \
227  }
228 
229 /// Assert Level 1 -- Debugging which is used whether in FULLDEBUG or
230 /// DEBUG compilation mode. This level assert is designed for aiding
231 /// in standard debug (-g) mode
232 #if defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)
233 
234 #define ASSERTL1(condition, msg) \
235  if (!(condition)) \
236  { \
237  Nektar::ErrorUtil::Error(Nektar::ErrorUtil::efatal, __FILE__, \
238  __LINE__, msg, 1); \
239  }
240 
241 #define WARNINGL1(condition, msg) \
242  if (!(condition)) \
243  { \
244  Nektar::ErrorUtil::Error(Nektar::ErrorUtil::ewarning, __FILE__, \
245  __LINE__, msg, 1); \
246  }
247 
248 #else // defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)
249 #define ASSERTL1(condition, msg)
250 #define WARNINGL1(condition, msg)
251 #endif // defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)
252 
253 /// Assert Level 2 -- Debugging which is used FULLDEBUG compilation
254 /// mode. This level assert is designed to provide addition safety
255 /// checks within the code (such as bounds checking, etc.).
256 #ifdef NEKTAR_FULLDEBUG
257 
258 #define ASSERTL2(condition, msg) \
259  if (!(condition)) \
260  { \
261  Nektar::ErrorUtil::Error(Nektar::ErrorUtil::efatal, __FILE__, \
262  __LINE__, msg, 2); \
263  }
264 #define WARNINGL2(condition, msg) \
265  if (!(condition)) \
266  { \
267  Nektar::ErrorUtil::Error(Nektar::ErrorUtil::ewarning, __FILE__, \
268  __LINE__, msg, 2); \
269  }
270 
271 #else // NEKTAR_FULLDEBUG
272 #define ASSERTL2(condition, msg)
273 #define WARNINGL2(condition, msg)
274 #endif // NEKTAR_FULLDEBUG
275 
276 } // namespace Nektar
277 
278 #endif // ERRORUTIL_HPP
Nektar::ErrorUtil::NekError NekError
#define LIB_UTILITIES_EXPORT
NekError(const std::string &message)
Definition: ErrorUtil.hpp:62
static bool m_printBacktrace
Definition: ErrorUtil.hpp:200
static void Error(ErrType type, const char *routine, int lineNumber, const char *msg, unsigned int level, bool DoComm=false)
Definition: ErrorUtil.hpp:88
static void Error(ErrType type, const char *routine, int lineNumber, const char *msg)
Definition: ErrorUtil.hpp:192
static std::ostream * m_outStream
Definition: ErrorUtil.hpp:199
static void SetPrintBacktrace(bool b)
Definition: ErrorUtil.hpp:78
static void Error(ErrType type, const char *routine, int lineNumber, const std::string &msg, unsigned int level)
Definition: ErrorUtil.hpp:186
static void SetErrorStream(std::ostream &o)
Definition: ErrorUtil.hpp:73
static bool HasCustomErrorStream()
Definition: ErrorUtil.hpp:83
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2