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
42
43#if defined(NEKTAR_USE_MPI)
44#include <mpi.h>
45#endif
46
47#ifndef _WIN32
48#include <execinfo.h>
49#endif
50
51namespace Nektar
52{
53
55{
56public:
57 class NekError : public std::runtime_error
58 {
59 public:
60 NekError(const std::string &message) : std::runtime_error(message)
61 {
62 }
63 };
64
66 {
69 };
70
71 inline static void SetErrorStream(std::ostream &o)
72 {
73 m_outStream = &o;
74 }
75
76 inline static void SetPrintBacktrace(bool b)
77 {
79 }
80
81 inline static bool HasCustomErrorStream()
82 {
83 return m_outStream != &std::cerr;
84 }
85
86 inline static void Error(ErrType type, [[maybe_unused]] const char *routine,
87 [[maybe_unused]] int lineNumber, const char *msg,
88 unsigned int level,
89 [[maybe_unused]] bool DoComm = false)
90 {
91 // The user of outStream is primarily for the unit tests. The unit
92 // tests often generate errors on purpose to make sure invalid usage is
93 // flagged appropriately. Printing the error messages to cerr made the
94 // unit test output hard to parse.
95
96 std::string baseMsg =
97 "Level " + std::to_string(level) + " assertion violation\n";
98#if defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)
99 baseMsg += "Where : " + std::string(routine) + "[" +
100 std::to_string(lineNumber) + "]\nMessage : ";
101#endif
102 baseMsg += std::string(msg);
103
104 // Default rank is zero. If MPI used and initialised, populate with
105 // the correct rank. Messages are only printed on rank zero.
106 int rank = 0;
107#if defined(NEKTAR_USE_MPI) && !defined(NEKTAR_USE_CWIPI)
108 int flag = 0;
109 if (DoComm)
110 {
111 MPI_Initialized(&flag);
112 if (flag)
113 {
114 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
115 }
116 }
117#endif
118
119 std::string btMessage("");
120#if defined(NEKTAR_FULLDEBUG)
121#ifndef _WIN32
123 {
124 void *btArray[40];
125 int btSize;
126 char **btStrings;
127
128 btSize = backtrace(btArray, 40);
129 btStrings = backtrace_symbols(btArray, btSize);
130
131 for (int i = 0; i < btSize; ++i)
132 {
133 btMessage += std::string(btStrings[i]) + "\n";
134 }
135 free(btStrings);
136 }
137#endif
138#endif
139
140 switch (type)
141 {
142 case efatal:
143 if (!rank)
144 {
146 {
147 (*m_outStream) << btMessage;
148 }
149 (*m_outStream) << "Fatal : " << baseMsg << std::endl;
150 }
151
152#if defined(NEKTAR_USE_MPI) && !defined(NEKTAR_USE_CWIPI)
153 if (DoComm)
154 {
155 if (flag)
156 {
157 MPI_Barrier(MPI_COMM_WORLD);
158 }
159 }
160#endif
161 throw NekError(baseMsg);
162 break;
163 case ewarning:
164 if (!rank)
165 {
167 {
168 (*m_outStream) << btMessage;
169 }
170 (*m_outStream) << "Warning : " << baseMsg << std::endl;
171 }
172 break;
173 default:
174 (*m_outStream)
175 << "Unknown warning type: " << baseMsg << std::endl;
176 }
177 }
178
179 inline static void Error(ErrType type, const char *routine, int lineNumber,
180 const std::string &msg, unsigned int level)
181 {
182 Error(type, routine, lineNumber, msg.c_str(), level);
183 }
184
185 inline static void Error(ErrType type, const char *routine, int lineNumber,
186 const char *msg)
187 {
188 Error(type, routine, lineNumber, msg, 0);
189 }
190
191private:
192 LIB_UTILITIES_EXPORT static std::ostream *m_outStream;
194};
195
196/// Assert Level 0 -- Fundamental assert which
197/// is used whether in FULLDEBUG, DEBUG or OPT
198/// compilation mode. This level assert is
199/// considered code critical, even under
200/// optimized compilation.
201
202#define NEKERROR(type, msg) \
203 Nektar::ErrorUtil::Error(type, __FILE__, __LINE__, msg, 0);
204
205#define ROOTONLY_NEKERROR(type, msg) \
206 Nektar::ErrorUtil::Error(type, __FILE__, __LINE__, msg, 0, true);
207
208#define ASSERTL0(condition, msg) \
209 if (!(condition)) \
210 { \
211 Nektar::ErrorUtil::Error(Nektar::ErrorUtil::efatal, __FILE__, \
212 __LINE__, msg, 0); \
213 }
214
215#define WARNINGL0(condition, msg) \
216 if (!(condition)) \
217 { \
218 Nektar::ErrorUtil::Error(Nektar::ErrorUtil::ewarning, __FILE__, \
219 __LINE__, msg, 0); \
220 }
221
222/// Assert Level 1 -- Debugging which is used whether in FULLDEBUG or
223/// DEBUG compilation mode. This level assert is designed for aiding
224/// in standard debug (-g) mode
225#if defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)
226
227#define ASSERTL1(condition, msg) \
228 if (!(condition)) \
229 { \
230 Nektar::ErrorUtil::Error(Nektar::ErrorUtil::efatal, __FILE__, \
231 __LINE__, msg, 1); \
232 }
233
234#define WARNINGL1(condition, msg) \
235 if (!(condition)) \
236 { \
237 Nektar::ErrorUtil::Error(Nektar::ErrorUtil::ewarning, __FILE__, \
238 __LINE__, msg, 1); \
239 }
240
241#else // defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)
242#define ASSERTL1(condition, msg)
243#define WARNINGL1(condition, msg)
244#endif // defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)
245
246/// Assert Level 2 -- Debugging which is used FULLDEBUG compilation
247/// mode. This level assert is designed to provide addition safety
248/// checks within the code (such as bounds checking, etc.).
249#ifdef NEKTAR_FULLDEBUG
250
251#define ASSERTL2(condition, msg) \
252 if (!(condition)) \
253 { \
254 Nektar::ErrorUtil::Error(Nektar::ErrorUtil::efatal, __FILE__, \
255 __LINE__, msg, 2); \
256 }
257#define WARNINGL2(condition, msg) \
258 if (!(condition)) \
259 { \
260 Nektar::ErrorUtil::Error(Nektar::ErrorUtil::ewarning, __FILE__, \
261 __LINE__, msg, 2); \
262 }
263
264#else // NEKTAR_FULLDEBUG
265#define ASSERTL2(condition, msg)
266#define WARNINGL2(condition, msg)
267#endif // NEKTAR_FULLDEBUG
268
269} // namespace Nektar
270
271#endif // ERRORUTIL_HPP
Nektar::ErrorUtil::NekError NekError
#define LIB_UTILITIES_EXPORT
NekError(const std::string &message)
Definition: ErrorUtil.hpp:60
static bool m_printBacktrace
Definition: ErrorUtil.hpp:193
static void Error(ErrType type, const char *routine, int lineNumber, const char *msg, unsigned int level, bool DoComm=false)
Definition: ErrorUtil.hpp:86
static void Error(ErrType type, const char *routine, int lineNumber, const char *msg)
Definition: ErrorUtil.hpp:185
static std::ostream * m_outStream
Definition: ErrorUtil.hpp:192
static void SetPrintBacktrace(bool b)
Definition: ErrorUtil.hpp:76
static void Error(ErrType type, const char *routine, int lineNumber, const std::string &msg, unsigned int level)
Definition: ErrorUtil.hpp:179
static void SetErrorStream(std::ostream &o)
Definition: ErrorUtil.hpp:71
static bool HasCustomErrorStream()
Definition: ErrorUtil.hpp:81