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