home
about
news
download
doc
source
systems
tests
bugs
contact
IMP Reference Guide
2.11.1
The Integrative Modeling Platform
IMP Manual
Reference Guide
Tutorial Index
Modules
Classes
Examples
include
IMP
version 2.11.1
check_macros.h
Go to the documentation of this file.
1
/**
2
* \file IMP/check_macros.h
3
* \brief Exception definitions and assertions.
4
*
5
* Copyright 2007-2019 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
using IMP::NONE; \
216
using IMP::USAGE; \
217
using IMP::USAGE_AND_INTERNAL; \
218
if (level <= ::IMP::get_check_level())
219
220
#define IMP_CHECK_CODE(expr) expr
221
222
#if IMP_KERNEL_HAS_LOG4CXX
223
#define IMP_KERNEL_CONTEXT
224
#else
225
#define IMP_KERNEL_CONTEXT << IMP::get_context_message()
226
#endif
227
228
#else // IMP_HAS_CHECKS == IMP_NONE
229
#define IMP_IF_CHECK(level) if (0)
230
#define IMP_CHECK_CODE(expr)
231
#endif // IMP_HAS_CHECKS
232
233
#if IMP_HAS_CHECKS >= IMP_INTERNAL
234
#define IMP_INTERNAL_CHECK(expr, message) \
235
do { \
236
if (IMP::get_check_level() >= IMP::USAGE_AND_INTERNAL && \
237
!(expr)) { \
238
std::ostringstream imp_check_oss; \
239
imp_check_oss << "Internal check failure: " << message << std::endl \
240
<< " File \"" << __FILE__ << "\", line " \
241
<< __LINE__ IMP_KERNEL_CONTEXT << std::endl; \
242
IMP::handle_error(imp_check_oss.str().c_str()); \
243
throw IMP::InternalException(imp_check_oss.str().c_str()); \
244
} \
245
} while (false)
246
247
#define IMP_INTERNAL_CHECK_FLOAT_EQUAL(expra, exprb, message) \
248
IMP_INTERNAL_CHECK( \
249
std::abs((expra) - (exprb)) < .1 * std::abs((expra) + (exprb)) + .1, \
250
(expra) << " != " << (exprb) << " - " << message)
251
#else
252
#define IMP_INTERNAL_CHECK(expr, message)
253
#define IMP_INTERNAL_CHECK_FLOAT_EQUAL(expra, exprb, message)
254
#endif
255
256
#if IMP_HAS_CHECKS >= IMP_USAGE
257
#define IMP_USAGE_CHECK(expr, message) \
258
do { \
259
if (IMP::get_check_level() >= IMP::USAGE && !(expr)) { \
260
std::ostringstream imp_check_oss; \
261
imp_check_oss << "Usage check failure: " << message IMP_KERNEL_CONTEXT \
262
<< std::endl; \
263
IMP::handle_error(imp_check_oss.str().c_str()); \
264
throw IMP::UsageException(imp_check_oss.str().c_str()); \
265
} \
266
} while (false)
267
#define IMP_USAGE_CHECK_FLOAT_EQUAL(expra, exprb, message) \
268
IMP_USAGE_CHECK( \
269
std::abs((expra) - (exprb)) < .1 * std::abs((expra) + (exprb)) + .1, \
270
expra << " != " << exprb << " - " << message)
271
#else
272
#define IMP_USAGE_CHECK(expr, message)
273
#define IMP_USAGE_CHECK_FLOAT_EQUAL(expra, exprb, message)
274
#endif
275
276
#endif // IMP_DOXYGEN
277
278
#if defined(IMP_DOXYGEN) || IMP_HAS_CHECKS == IMP_NONE
279
//! Perform some basic validity checks on the object for memory debugging
280
#define IMP_CHECK_OBJECT(obj) IMP_UNUSED(obj)
281
#define IMP_CHECK_OBJECT_IF_NOT_nullptr(obj) IMP_UNUSED(obj)
282
#else
283
284
#define IMP_CHECK_OBJECT(obj) \
285
do { \
286
IMP_UNUSED(obj); \
287
IMP_INTERNAL_CHECK((obj!=nullptr), "nullptr object"); \
288
IMP_INTERNAL_CHECK((obj)->get_is_valid(), \
289
"Check object " << static_cast<const void *>(obj) \
290
<< " was previously freed"); \
291
} while (false)
292
293
#define IMP_CHECK_OBJECT_IF_NOT_nullptr(obj) \
294
do { \
295
if (obj) { \
296
IMP_INTERNAL_CHECK((obj)->get_is_valid(), \
297
"Check object " << static_cast<const void *>(obj) \
298
<< " was previously freed"); \
299
} \
300
} while (false)
301
#endif
302
303
#endif
/* IMPKERNEL_CHECK_MACROS_H */
exception.h
Exception definitions and assertions.
compiler_macros.h
Various compiler workarounds.