home
about
news
download
doc
source
systems
tests
bugs
contact
IMP Reference Guide
2.20.0
The Integrative Modeling Platform
IMP Manual
Reference Guide
Tutorial Index
Modules
Classes
Examples
include
IMP
version 2.20.0
check_macros.h
Go to the documentation of this file.
1
/**
2
* \file IMP/check_macros.h
3
* \brief Helper macros for throwing and handling exceptions
4
*
5
* Copyright 2007-2022 IMP Inventors. All rights reserved.
6
*
7
*/
8
9
#ifndef IMPKERNEL_CHECK_MACROS_H
10
#define IMPKERNEL_CHECK_MACROS_H
11
12
#include <IMP/kernel_config.h>
13
#include "
exception.h
"
14
#include "
compiler_macros.h
"
15
#include <iostream>
16
#include <cmath>
17
18
#if !defined(IMP_HAS_CHECKS)
19
#error "IMP_HAS_CHECKS is not defined, compilation is broken"
20
#endif
21
22
#if !defined(IMP_NONE)
23
#error "IMP_NONE is not defined, compilation is broken"
24
#endif
25
26
/** Catch any IMP exception thrown by expr and terminate with an
27
error message. Use this for basic error handling in main functions
28
in C++. Do not use within the \imp library.
29
*/
30
#define IMP_CATCH_AND_TERMINATE(expr) \
31
try { \
32
expr; \
33
} \
34
catch (const IMP::Exception &e) { \
35
std::cerr << "Application terminated with error :" << e.what() \
36
<< std::endl; \
37
exit(1); \
38
}
39
40
//! Throw an exception with a message
41
/** The exception thrown must inherit from Exception and not be
42
UsageException or InternalException as those are reserved for
43
disableable checks (the IMP_INTERNAL_CHECK() and IMP_USAGE_CHECK()
44
macros).
45
\code
46
IMP_THROW("Could not open file " << file_name,
47
IOException);
48
\endcode
49
*/
50
#define IMP_THROW(message, exception_name) \
51
do { \
52
std::ostringstream imp_throw_oss; \
53
imp_throw_oss << message << std::endl; \
54
throw exception_name(imp_throw_oss.str().c_str()); \
55
} while (true)
56
57
//! Throw an exception if a check fails
58
/** Do IMP_THROW() if the check as the first argument fails. Unlike
59
IMP_USAGE_CHECK() and IMP_INTERNAL_CHECK() these checks are
60
always present.*/
61
#define IMP_ALWAYS_CHECK(condition, message, exception_name) \
62
if (!(condition)) { \
63
IMP_THROW(message, exception_name); \
64
}
65
66
//! A runtime failure for IMP.
67
/** \param[in] message Failure message to write.
68
This macro is used to provide nice error messages when there is
69
an internal error in \imp. It causes an IMP::InternalException to be
70
thrown.
71
*/
72
#define IMP_FAILURE(message) \
73
do { \
74
std::ostringstream imp_failure_oss; \
75
imp_failure_oss << message << std::endl; \
76
IMP::handle_error(imp_failure_oss.str().c_str()); \
77
throw IMP::InternalException(imp_failure_oss.str().c_str()); \
78
} while (true)
79
80
//! Use this to mark that the method is not implemented yet
81
#define IMP_NOT_IMPLEMENTED \
82
do { \
83
IMP::handle_error("This method is not implemented."); \
84
throw IMP::InternalException("Not implemented"); \
85
} while (true)
86
87
#ifdef IMP_DOXYGEN
88
89
//! Execute the code block if a certain level checks are on
90
/**
91
The next code block (delimited by { }) is executed if
92
get_check_level() <= level.
93
94
For example:
95
\code
96
IMP_IF_CHECK(USAGE) {
97
Vector<Particle*> testp(input.begin(), input.end());
98
std::sort(testp.begin(), testp.end());
99
IMP_USAGE_CHECK(std::unique(testp.begin(), testp.end()) == testp.end(),
100
"Duplicate particles found in the input list.");
101
}
102
\endcode
103
*/
104
#define IMP_IF_CHECK(level)
105
106
//! Only compile the code if checks are enabled
107
/** For example
108
\code
109
IMP_CHECK_CODE({
110
Vector<Particle*> testp(input.begin(), input.end());
111
std::sort(testp.begin(), testp.end());
112
IMP_USAGE_CHECK(std::unique(testp.begin(), testp.end()) == testp.end(),
113
"Duplicate particles found in the input list.");
114
});
115
\endcode
116
**/
117
#define IMP_CHECK_CODE(expr)
118
119
/** \brief An assertion to check for internal errors in \imp. An
120
IMP::ErrorException will be thrown.
121
122
Since it is a debug-only check and no attempt should be made to
123
recover from it, the exception type cannot be specified.
124
125
For example:
126
\code
127
IMP_INTERNAL_CHECK((3.14-PI) < .01,
128
"PI is not close to 3.14. It is instead " << PI);
129
\endcode
130
131
\note if the code is compiled with 'fast', or the check level is
132
less than IMP::USAGE_AND_INTERNAL, the check is not performed. Do
133
not use asserts as a shorthand to throw exceptions (throw the
134
exception yourself); use them only to check for logic errors.
135
136
\param[in] expr The assertion expression.
137
\param[in] message Write this message if the assertion fails.
138
*/
139
#define IMP_INTERNAL_CHECK(expr, message)
140
141
/** This is like IMP_INTERNAL_CHECK, however designed to check if
142
two floating point numbers are almost equal. The check looks something
143
like
144
\code
145
std::abs(a-b) < .1*(a+b)+.1
146
\endcode
147
Using this makes such tests a bit easier to spot and not mess up.
148
*/
149
#define IMP_INTERNAL_CHECK_FLOAT_EQUAL(expra, exprb, message)
150
151
//! A runtime test for incorrect usage of a class or method.
152
/** \param[in] expr The assertion expression.
153
\param[in] message Write this message if the assertion fails.
154
155
It should be used to check arguments to function. For example
156
\code
157
IMP_USAGE_CHECK(positive_argument >0,
158
"Argument positive_argument to function my_function "
159
<< " must be positive. Instead got " << positive_argument);
160
\endcode
161
162
\note if the build is 'fast', or the check level
163
is less than IMP::USAGE, the check is not performed. Do not use these
164
checks as a shorthand to throw necessary exceptions (throw the
165
exception yourself); use them only to check for errors, such as
166
inappropriate input.
167
*/
168
#define IMP_USAGE_CHECK(expr, message)
169
170
/** This is like IMP_USAGE_CHECK, however designed to check if
171
two floating point numbers are almost equal. The check looks something
172
like
173
\code
174
std::abs(a-b) < .1*(a+b)+.1
175
\endcode
176
Using this makes such tests a bit easier to spot and not mess up.
177
*/
178
#define IMP_USAGE_CHECK_FLOAT_EQUAL(expra, exprb, message)
179
180
#ifndef IMP_DOXYGEN
181
/** Mark a variable as one that is only used in checks. This disables
182
unused variable warnings on it in fast mode.
183
*/
184
#define IMP_CHECK_VARIABLE(variable)
185
#endif
186
187
/** Mark a variable as one that is only used in checks. This disables
188
unused variable warnings on it in fast mode.
189
*/
190
#define IMP_USAGE_CHECK_VARIABLE(variable)
191
192
/** Mark a variable as one that is only used in checks. This disables
193
unused variable warnings on it in fast mode.
194
*/
195
#define IMP_INTERNAL_CHECK_VARIABLE(variable)
196
197
#else // IMP_DOXYGEN
198
199
#if IMP_HAS_CHECKS == IMP_INTERNAL
200
#define IMP_CHECK_VARIABLE(variable)
201
#define IMP_USAGE_CHECK_VARIABLE(variable)
202
#define IMP_INTERNAL_CHECK_VARIABLE(variable)
203
#elif IMP_HAS_CHECKS == IMP_USAGE
204
#define IMP_CHECK_VARIABLE(variable)
205
#define IMP_USAGE_CHECK_VARIABLE(variable)
206
#define IMP_INTERNAL_CHECK_VARIABLE(variable) IMP_UNUSED(variable)
207
#else
208
#define IMP_CHECK_VARIABLE(variable) IMP_UNUSED(variable)
209
#define IMP_USAGE_CHECK_VARIABLE(variable) IMP_UNUSED(variable)
210
#define IMP_INTERNAL_CHECK_VARIABLE(variable) IMP_UNUSED(variable)
211
#endif
212
213
#if IMP_HAS_CHECKS > IMP_NONE
214
#define IMP_IF_CHECK(level) \
215
if (level <= ::IMP::get_check_level())
216
217
#define IMP_CHECK_CODE(expr) expr
218
219
#if IMP_KERNEL_HAS_LOG4CXX
220
#define IMP_KERNEL_CONTEXT
221
#else
222
#define IMP_KERNEL_CONTEXT << IMP::get_context_message()
223
#endif
224
225
#else // IMP_HAS_CHECKS == IMP_NONE
226
#define IMP_IF_CHECK(level) if (0)
227
#define IMP_CHECK_CODE(expr)
228
#endif // IMP_HAS_CHECKS
229
230
#if IMP_HAS_CHECKS >= IMP_INTERNAL
231
#define IMP_INTERNAL_CHECK(expr, message) \
232
do { \
233
if (IMP::get_check_level() >= IMP::USAGE_AND_INTERNAL && \
234
!(expr)) { \
235
std::ostringstream imp_check_oss; \
236
imp_check_oss << "Internal check failure: " << message << std::endl \
237
<< " File \"" << __FILE__ << "\", line " \
238
<< __LINE__ IMP_KERNEL_CONTEXT << std::endl; \
239
IMP::handle_error(imp_check_oss.str().c_str()); \
240
throw IMP::InternalException(imp_check_oss.str().c_str()); \
241
} \
242
} while (false)
243
244
#define IMP_INTERNAL_CHECK_FLOAT_EQUAL(expra, exprb, message) \
245
IMP_INTERNAL_CHECK( \
246
std::abs((expra) - (exprb)) < .1 * std::abs((expra) + (exprb)) + .1, \
247
(expra) << " != " << (exprb) << " - " << message)
248
#else
249
#define IMP_INTERNAL_CHECK(expr, message)
250
#define IMP_INTERNAL_CHECK_FLOAT_EQUAL(expra, exprb, message)
251
#endif
252
253
#if IMP_HAS_CHECKS >= IMP_USAGE
254
#define IMP_USAGE_CHECK(expr, message) \
255
do { \
256
if (IMP::get_check_level() >= IMP::USAGE && !(expr)) { \
257
std::ostringstream imp_check_oss; \
258
imp_check_oss << "Usage check failure: " << message IMP_KERNEL_CONTEXT \
259
<< std::endl; \
260
IMP::handle_error(imp_check_oss.str().c_str()); \
261
throw IMP::UsageException(imp_check_oss.str().c_str()); \
262
} \
263
} while (false)
264
#define IMP_USAGE_CHECK_FLOAT_EQUAL(expra, exprb, message) \
265
IMP_USAGE_CHECK( \
266
std::abs((expra) - (exprb)) < .1 * std::abs((expra) + (exprb)) + .1, \
267
expra << " != " << exprb << " - " << message)
268
#else
269
#define IMP_USAGE_CHECK(expr, message)
270
#define IMP_USAGE_CHECK_FLOAT_EQUAL(expra, exprb, message)
271
#endif
272
273
#endif // IMP_DOXYGEN
274
275
#if defined(IMP_DOXYGEN) || IMP_HAS_CHECKS == IMP_NONE
276
//! Perform some basic validity checks on the object for memory debugging
277
#define IMP_CHECK_OBJECT(obj) IMP_UNUSED(obj)
278
#define IMP_CHECK_OBJECT_IF_NOT_nullptr(obj) IMP_UNUSED(obj)
279
#else
280
281
#define IMP_CHECK_OBJECT(obj) \
282
do { \
283
IMP_UNUSED(obj); \
284
IMP_INTERNAL_CHECK((obj!=nullptr), "nullptr object"); \
285
IMP_INTERNAL_CHECK((obj)->get_is_valid(), \
286
"Check object " << static_cast<const void *>(obj) \
287
<< " was previously freed"); \
288
} while (false)
289
290
#define IMP_CHECK_OBJECT_IF_NOT_nullptr(obj) \
291
do { \
292
if (obj) { \
293
IMP_INTERNAL_CHECK((obj)->get_is_valid(), \
294
"Check object " << static_cast<const void *>(obj) \
295
<< " was previously freed"); \
296
} \
297
} while (false)
298
#endif
299
300
#endif
/* IMPKERNEL_CHECK_MACROS_H */
exception.h
Exception definitions and assertions.
compiler_macros.h
Various compiler workarounds.