Merge remote-tracking branch 'origin/release-4-6' into HEAD
[alexxy/gromacs.git] / src / gromacs / utility / exceptions.h
1 /*
2  *
3  *                This source code is part of
4  *
5  *                 G   R   O   M   A   C   S
6  *
7  *          GROningen MAchine for Chemical Simulations
8  *
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.
13  *
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.
18  *
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.
25  *
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.
28  *
29  * For more info, check our website at http://www.gromacs.org
30  */
31 /*! \file
32  * \brief
33  * Declares common exception classes for fatal error handling.
34  *
35  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36  * \inpublicapi
37  * \ingroup module_utility
38  */
39 #ifndef GMX_UTILITY_EXCEPTIONS_H
40 #define GMX_UTILITY_EXCEPTIONS_H
41
42 #include <cstdio>
43 #include <cstdlib>
44
45 #include <exception>
46 #include <string>
47
48 #include <boost/exception/errinfo_api_function.hpp>
49 #include <boost/exception/errinfo_errno.hpp>
50 #include <boost/exception/exception.hpp>
51 #include <boost/exception/info.hpp>
52 #include <boost/throw_exception.hpp>
53
54 namespace gmx
55 {
56
57 /*! \brief
58  * Stores a user-friendly explanation for the reason of an exception.
59  *
60  * Typically, should not be used directly, but through the GromacsException
61  * class: it is initialized by the constructor, and can be accessed with
62  * GromacsException::what().
63  *
64  * \inlibraryapi
65  */
66 typedef boost::error_info<struct errinfo_message_, std::string> errinfo_message;
67
68 /*! \addtopublicapi
69  * \{
70  */
71
72 /*! \brief
73  * Base class for all exception objects in Gromacs.
74  *
75  * Although boost recommends using virtual inheritance in exception hiearchies,
76  * it is not used here for two reasons:
77  * -# It is only useful when there is diamond inheritance, and that should
78  *    never occur in this exception hierarchy because this class is the only
79  *    instance of multiple inheritance (Gromacs programming guidelines prohibit
80  *    multiple inheritance from concrete classes, but it is unavoidable here
81  *    because of the design of boost::exception).
82  * -# Because the constructor takes an argument, virtual inheritance would
83  *    complicate any classes that inherit indirectly from this class.
84  *
85  * \ingroup module_utility
86  */
87 class GromacsException : public std::exception, public boost::exception
88 {
89     public:
90         /*! \brief
91          * Returns the reason string for the exception.
92          *
93          * The return value is the string that was passed to the constructor.
94          */
95         virtual const char *what() const throw();
96         /*! \brief
97          * Returns the error code corresponding to the exception type.
98          */
99         virtual int errorCode() const = 0;
100
101     protected:
102         /*! \brief
103          * Creates an exception object with the provided detailed reason.
104          *
105          * \param[in] reason Detailed reason for the exception.
106          */
107         explicit GromacsException(const std::string &reason);
108 };
109
110 /*! \brief
111  * Exception class for file I/O errors.
112  *
113  * \ingroup module_utility
114  */
115 class FileIOError : public GromacsException
116 {
117     public:
118         /*! \brief
119          * Creates an exception object with the provided detailed reason.
120          *
121          * \param[in] reason Detailed reason for the exception.
122          */
123         explicit FileIOError(const std::string &reason)
124             : GromacsException(reason) {}
125
126         virtual int errorCode() const;
127 };
128
129 /*! \brief
130  * Exception class for user input errors.
131  *
132  * Derived classes should be used to indicate the nature of the error instead
133  * of throwing this class directly.
134  *
135  * \ingroup module_utility
136  */
137 class UserInputError : public GromacsException
138 {
139     protected:
140         //! \copydoc FileIOError::FileIOError()
141         explicit UserInputError(const std::string &reason)
142             : GromacsException(reason) {}
143 };
144
145 /*! \brief
146  * Exception class for situations where user input cannot be parsed/understood.
147  *
148  * \ingroup module_utility
149  */
150 class InvalidInputError : public UserInputError
151 {
152     public:
153         //! \copydoc FileIOError::FileIOError()
154         explicit InvalidInputError(const std::string &reason)
155             : UserInputError(reason) {}
156
157         virtual int errorCode() const;
158 };
159
160 /*! \brief
161  * Exception class for situations where user input is inconsistent.
162  *
163  * \ingroup module_utility
164  */
165 class InconsistentInputError : public UserInputError
166 {
167     public:
168         //! \copydoc FileIOError::FileIOError()
169         explicit InconsistentInputError(const std::string &reason)
170             : UserInputError(reason) {}
171
172         virtual int errorCode() const;
173 };
174
175 /*! \brief
176  * Exception class for simulation instabilities.
177  *
178  * \ingroup module_utility
179  */
180 class SimulationInstabilityError : public GromacsException
181 {
182     public:
183         //! \copydoc FileIOError::FileIOError()
184         explicit SimulationInstabilityError(const std::string &reason)
185             : GromacsException(reason) {}
186
187         virtual int errorCode() const;
188 };
189
190 /*! \brief
191  * Exception class for internal errors.
192  *
193  * \ingroup module_utility
194  */
195 class InternalError : public GromacsException
196 {
197     public:
198         //! \copydoc FileIOError::FileIOError()
199         explicit InternalError(const std::string &reason)
200             : GromacsException(reason) {}
201
202         virtual int errorCode() const;
203 };
204
205 /*! \brief
206  * Exception class for incorrect use of an API.
207  *
208  * \ingroup module_utility
209  */
210 class APIError : public GromacsException
211 {
212     public:
213         //! \copydoc FileIOError::FileIOError()
214         explicit APIError(const std::string &reason)
215             : GromacsException(reason) {}
216
217         virtual int errorCode() const;
218 };
219
220 /*! \brief
221  * Exception class for use of an unimplemented feature.
222  *
223  * \ingroup module_utility
224  */
225 class NotImplementedError : public APIError
226 {
227     public:
228         //! \copydoc FileIOError::FileIOError()
229         explicit NotImplementedError(const std::string &reason)
230             : APIError(reason) {}
231
232         virtual int errorCode() const;
233 };
234
235
236 /*! \brief
237  * Macro for throwing an exception.
238  *
239  * \param[in] e    Exception object to throw.
240  *
241  * Using this macro instead of \c throw directly makes it possible to uniformly
242  * attach information into the exception objects.
243  * \p e should evaluate to an instance of an object derived from
244  * GromacsException.
245  *
246  * Basic usage:
247  * \code
248 if (value < 0)
249 {
250     GMX_THROW(InconsistentUserInput("Negative values not allowed for value"));
251 }
252  * \endcode
253  */
254 #define GMX_THROW(e) \
255     BOOST_THROW_EXCEPTION((e))
256
257 /*! \brief
258  * Macro for throwing an exception based on errno.
259  *
260  * \param[in] e       Exception object to throw.
261  * \param[in] syscall Name of the syscall that returned the error.
262  * \param[in] err     errno value returned by the syscall.
263  *
264  * This macro provides a convenience interface for throwing an exception to
265  * report an error based on a errno value.  In addition to adding the necessary
266  * information to the exception object, the macro also ensures that \p errno is
267  * evaluated before, e.g., the constructor of \p e may call other functions
268  * that could overwrite the errno value.
269  * \p e should evaluate to an instance of an object derived from
270  * GromacsException.
271  *
272  * Typical usage (note that gmx::File wraps this particular case):
273  * \code
274 FILE *fp = fopen("filename.txt", "r");
275 if (fp == NULL)
276 {
277     GMX_THROW(FileIOError("Could not open file"), "fopen", errno);
278 }
279  * \endcode
280  */
281 #define GMX_THROW_WITH_ERRNO(e, syscall, err) \
282     do { \
283         int stored_errno_ = (err); \
284         GMX_THROW((e) << boost::errinfo_errno(stored_errno_) \
285                       << boost::errinfo_api_function(syscall)); \
286     } while(0)
287
288 /*! \brief
289  * Formats a standard fatal error message for reporting an exception.
290  *
291  * Does not throw.  If memory allocation fails or some other error occurs
292  * while formatting the error, tries to print a reasonable alternative message.
293  *
294  * Normal usage in Gromacs command-line programs is like this:
295  * \code
296 int main(int argc, char *argv[])
297 {
298     gmx::ProgramInfo::init(argc, argv);
299     try
300     {
301         // The actual code for the program
302         return 0;
303     }
304     catch (const std::exception &ex)
305     {
306         gmx::printFatalErrorMessage(stderr, ex);
307         return 1;
308     }
309 }
310  * \endcode
311  */
312 void printFatalErrorMessage(FILE *fp, const std::exception &ex);
313
314 /*! \brief
315  * Converts an exception into a return code.
316  */
317 int translateException(const std::exception &ex);
318
319 /*!\}*/
320
321 /*! \cond libapi */
322 /*! \libinternal \brief
323  * Macro for catching exceptions at C++ -> C boundary.
324  *
325  * This macro is intended for uniform handling of exceptions when C++ code is
326  * called from C code within Gromacs.  Since most existing code is written
327  * using the assumption that fatal errors terminate the program, this macro
328  * implements this behavior for exceptions.  It should only be used in cases
329  * where the error cannot be propagated upwards using return values or such.
330  *
331  * Having this as a macro instead of having the same code in each place makes
332  * it easy to 1) find all such locations in the code, and 2) change the exact
333  * behavior if needed.
334  *
335  * Usage:
336  * \code
337 try
338 {
339     // C++ code
340 }
341 GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
342  * \endcode
343  *
344  * \inlibraryapi
345  */
346 #define GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR \
347     catch (const std::exception &ex) { \
348         ::gmx::printFatalErrorMessage(stderr, ex); \
349         std::exit(1); \
350     }
351 //! \endcond
352
353 } // namespace gmx
354
355 #endif