3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
9 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11 * Copyright (c) 2001-2009, The GROMACS development team,
12 * check out http://www.gromacs.org for more information.
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * If you want to redistribute modifications, please consider that
20 * scientific software is very special. Version control is crucial -
21 * bugs must be traceable. We will be happy to consider code for
22 * inclusion in the official distribution, but derived work must not
23 * be called official GROMACS. Details are found in the README & COPYING
24 * files - if they are missing, get the official version at www.gromacs.org.
26 * To help us fund GROMACS development, we humbly ask that you cite
27 * the papers on the package - you can find them in the top README file.
29 * For more info, check our website at http://www.gromacs.org
33 * Declares common exception classes for fatal error handling.
35 * \author Teemu Murtola <teemu.murtola@cbr.su.se>
37 * \ingroup module_utility
39 #ifndef GMX_UTILITY_EXCEPTIONS_H
40 #define GMX_UTILITY_EXCEPTIONS_H
49 #include <boost/exception_ptr.hpp>
50 #include <boost/exception/errinfo_api_function.hpp>
51 #include <boost/exception/errinfo_errno.hpp>
52 #include <boost/exception/exception.hpp>
53 #include <boost/exception/info.hpp>
54 #include <boost/throw_exception.hpp>
61 //! Internal container type for storing a list of nested exceptions.
62 typedef std::vector<boost::exception_ptr> NestedExceptionList;
63 } // namespace internal
70 * Provides information for Gromacs exception constructors.
72 * This class exists to implement common functionality for initializing all
73 * Gromacs exceptions without having extra code in each exception class.
74 * In simple cases, it can be implicitly constructed by passing a simple string
75 * to an exception constructor.
76 * If more complex initialization is necessary, it is possible to explicitly
77 * construct an object of this type and then call other methods to add
78 * information before actually creating the exception object.
81 * With the exception of the reason string, information added with this class
82 * is not currently accessible through any public API, except for calling
83 * printFatalErrorMessage(). This is not implemented as there is no current
84 * need for it, and it is not clear what would be the best alternative for the
85 * access. It should be possible to refactor the internal implementation to
86 * suit the needs of such external access without requiring changes in code
87 * that throws these exceptions.
89 * \ingroup module_utility
91 class ExceptionInitializer
95 * Creates an initialized with the given string as the reason.
97 * \param[in] reason Detailed reason for the exception.
98 * \throw std::bad_alloc if out of memory.
100 * This constructor is not explicit to allow constructing exceptions
101 * with a plain string argument given to the constructor without adding
102 * extra code to each exception class.
104 ExceptionInitializer(const char *reason)
108 //! \copydoc ExceptionInitializer(const char *)
109 ExceptionInitializer(const std::string &reason)
115 * Returns true if addCurrentExceptionAsNested() has been called.
117 * Provided for convenience for cases where exceptions will be added
118 * conditionally, and the caller wants to check whether any excetions
119 * were actually added.
121 bool hasNestedExceptions() const { return !nested_.empty(); }
123 * Adds the currently caught exception as a nested exception.
125 * May be called multiple times; all provided exceptions will be added
126 * in a list of nested exceptions.
128 * Must not be called outside a catch block.
130 void addCurrentExceptionAsNested()
132 nested_.push_back(boost::current_exception());
137 internal::NestedExceptionList nested_;
139 friend class GromacsException;
143 * Base class for all exception objects in Gromacs.
145 * Although boost recommends using virtual inheritance in exception hiearchies,
146 * it is not used here for two reasons:
147 * -# It is only useful when there is diamond inheritance, and that should
148 * never occur in this exception hierarchy because this class is the only
149 * instance of multiple inheritance (Gromacs programming guidelines prohibit
150 * multiple inheritance from concrete classes, but it is unavoidable here
151 * because of the design of boost::exception).
152 * -# Because the constructor takes an argument, virtual inheritance would
153 * complicate any classes that inherit indirectly from this class.
155 * \ingroup module_utility
157 class GromacsException : public std::exception, public boost::exception
161 * Returns the reason string for the exception.
163 * The return value is the string that was passed to the constructor.
165 virtual const char *what() const throw();
167 * Returns the error code corresponding to the exception type.
169 virtual int errorCode() const = 0;
172 * Adds context information to this exception.
174 * \param[in] context Context string to add.
175 * \throws std::bad_alloc if out of memory.
177 * Typical use is to add additional information higher up in the call
178 * stack using this function in a catch block and the rethrow the
182 * The added information is currently not accessible through what(),
183 * nor through any other means except for calling
184 * printFatalErrorMessage(). See ExceptionInitializer for more
187 void prependContext(const std::string &context);
191 * Creates an exception object with the provided initializer/reason.
193 * \param[in] details Initializer for the exception.
194 * \throws std::bad_alloc if out of memory.
196 explicit GromacsException(const ExceptionInitializer &details);
200 * Exception class for file I/O errors.
202 * \ingroup module_utility
204 class FileIOError : public GromacsException
208 * Creates an exception object with the provided initializer/reason.
210 * \param[in] details Initializer for the exception.
211 * \throws std::bad_alloc if out of memory.
213 * It is possible to call this constructor either with an explicit
214 * ExceptionInitializer object (useful for more complex cases), or
215 * a simple string if only a reason string needs to be provided.
217 explicit FileIOError(const ExceptionInitializer &details)
218 : GromacsException(details) {}
220 virtual int errorCode() const;
224 * Exception class for user input errors.
226 * Derived classes should be used to indicate the nature of the error instead
227 * of throwing this class directly.
229 * \ingroup module_utility
231 class UserInputError : public GromacsException
234 //! \copydoc FileIOError::FileIOError()
235 explicit UserInputError(const ExceptionInitializer &details)
236 : GromacsException(details) {}
240 * Exception class for situations where user input cannot be parsed/understood.
242 * \ingroup module_utility
244 class InvalidInputError : public UserInputError
247 //! \copydoc FileIOError::FileIOError()
248 explicit InvalidInputError(const ExceptionInitializer &details)
249 : UserInputError(details) {}
251 virtual int errorCode() const;
255 * Exception class for situations where user input is inconsistent.
257 * \ingroup module_utility
259 class InconsistentInputError : public UserInputError
262 //! \copydoc FileIOError::FileIOError()
263 explicit InconsistentInputError(const ExceptionInitializer &details)
264 : UserInputError(details) {}
266 virtual int errorCode() const;
270 * Exception class for simulation instabilities.
272 * \ingroup module_utility
274 class SimulationInstabilityError : public GromacsException
277 //! \copydoc FileIOError::FileIOError()
278 explicit SimulationInstabilityError(const ExceptionInitializer &details)
279 : GromacsException(details) {}
281 virtual int errorCode() const;
285 * Exception class for internal errors.
287 * \ingroup module_utility
289 class InternalError : public GromacsException
292 //! \copydoc FileIOError::FileIOError()
293 explicit InternalError(const ExceptionInitializer &details)
294 : GromacsException(details) {}
296 virtual int errorCode() const;
300 * Exception class for incorrect use of an API.
302 * \ingroup module_utility
304 class APIError : public GromacsException
307 //! \copydoc FileIOError::FileIOError()
308 explicit APIError(const ExceptionInitializer &details)
309 : GromacsException(details) {}
311 virtual int errorCode() const;
315 * Exception class for use of an unimplemented feature.
317 * \ingroup module_utility
319 class NotImplementedError : public APIError
322 //! \copydoc FileIOError::FileIOError()
323 explicit NotImplementedError(const ExceptionInitializer &details)
324 : APIError(details) {}
326 virtual int errorCode() const;
331 * Macro for throwing an exception.
333 * \param[in] e Exception object to throw.
335 * Using this macro instead of \c throw directly makes it possible to uniformly
336 * attach information into the exception objects.
337 * \p e should evaluate to an instance of an object derived from
344 GMX_THROW(InconsistentUserInput("Negative values not allowed for value"));
348 #define GMX_THROW(e) \
349 BOOST_THROW_EXCEPTION((e))
352 * Macro for throwing an exception based on errno.
354 * \param[in] e Exception object to throw.
355 * \param[in] syscall Name of the syscall that returned the error.
356 * \param[in] err errno value returned by the syscall.
358 * This macro provides a convenience interface for throwing an exception to
359 * report an error based on a errno value. In addition to adding the necessary
360 * information to the exception object, the macro also ensures that \p errno is
361 * evaluated before, e.g., the constructor of \p e may call other functions
362 * that could overwrite the errno value.
363 * \p e should evaluate to an instance of an object derived from
366 * Typical usage (note that gmx::File wraps this particular case):
368 FILE *fp = fopen("filename.txt", "r");
371 GMX_THROW(FileIOError("Could not open file"), "fopen", errno);
375 #define GMX_THROW_WITH_ERRNO(e, syscall, err) \
377 int stored_errno_ = (err); \
378 GMX_THROW((e) << boost::errinfo_errno(stored_errno_) \
379 << boost::errinfo_api_function(syscall)); \
383 * Formats a standard fatal error message for reporting an exception.
385 * Does not throw. If memory allocation fails or some other error occurs
386 * while formatting the error, tries to print a reasonable alternative message.
388 * Normal usage in Gromacs command-line programs is like this:
390 int main(int argc, char *argv[])
392 gmx::ProgramInfo::init(argc, argv);
395 // The actual code for the program
398 catch (const std::exception &ex)
400 gmx::printFatalErrorMessage(stderr, ex);
406 void printFatalErrorMessage(FILE *fp, const std::exception &ex);
409 * Converts an exception into a return code.
411 int translateException(const std::exception &ex);
416 /*! \libinternal \brief
417 * Macro for catching exceptions at C++ -> C boundary.
419 * This macro is intended for uniform handling of exceptions when C++ code is
420 * called from C code within Gromacs. Since most existing code is written
421 * using the assumption that fatal errors terminate the program, this macro
422 * implements this behavior for exceptions. It should only be used in cases
423 * where the error cannot be propagated upwards using return values or such.
425 * Having this as a macro instead of having the same code in each place makes
426 * it easy to 1) find all such locations in the code, and 2) change the exact
427 * behavior if needed.
435 GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
440 #define GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR \
441 catch (const std::exception &ex) { \
442 ::gmx::printFatalErrorMessage(stderr, ex); \