Merge branch 'release-4-6'
[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 <exception>
43 #include <string>
44
45 #include <boost/exception/errinfo_api_function.hpp>
46 #include <boost/exception/errinfo_errno.hpp>
47 #include <boost/exception/exception.hpp>
48 #include <boost/exception/info.hpp>
49 #include <boost/throw_exception.hpp>
50
51 namespace gmx
52 {
53
54 /*! \brief
55  * Stores a user-friendly explanation for the reason of an exception.
56  *
57  * Typically, should not be used directly, but through the GromacsException
58  * class: it is initialized by the constructor, and can be accessed with
59  * GromacsException::what().
60  *
61  * \inlibraryapi
62  */
63 typedef boost::error_info<struct errinfo_message_, std::string> errinfo_message;
64
65 /*! \addtopublicapi
66  * \{
67  */
68
69 /*! \brief
70  * Base class for all exception objects in Gromacs.
71  *
72  * Although boost recommends using virtual inheritance in exception hiearchies,
73  * it is not used here for two reasons:
74  * -# It is only useful when there is diamond inheritance, and that should
75  *    never occur in this exception hierarchy because this class is the only
76  *    instance of multiple inheritance (Gromacs programming guidelines prohibit
77  *    multiple inheritance from concrete classes, but it is unavoidable here
78  *    because of the design of boost::exception).
79  * -# Because the constructor takes an argument, virtual inheritance would
80  *    complicate any classes that inherit indirectly from this class.
81  *
82  * \ingroup module_utility
83  */
84 class GromacsException : public std::exception, public boost::exception
85 {
86     public:
87         /*! \brief
88          * Returns the reason string for the exception.
89          *
90          * The return value is the string that was passed to the constructor.
91          */
92         virtual const char *what() const throw();
93         /*! \brief
94          * Returns the error code corresponding to the exception type.
95          */
96         virtual int errorCode() const = 0;
97
98     protected:
99         /*! \brief
100          * Creates an exception object with the provided detailed reason.
101          *
102          * \param[in] reason Detailed reason for the exception.
103          */
104         explicit GromacsException(const std::string &reason);
105 };
106
107 /*! \brief
108  * Exception class for file I/O errors.
109  *
110  * \ingroup module_utility
111  */
112 class FileIOError : public GromacsException
113 {
114     public:
115         /*! \brief
116          * Creates an exception object with the provided detailed reason.
117          *
118          * \param[in] reason Detailed reason for the exception.
119          */
120         explicit FileIOError(const std::string &reason)
121             : GromacsException(reason) {}
122
123         virtual int errorCode() const;
124 };
125
126 /*! \brief
127  * Exception class for user input errors.
128  *
129  * Derived classes should be used to indicate the nature of the error instead
130  * of throwing this class directly.
131  *
132  * \ingroup module_utility
133  */
134 class UserInputError : public GromacsException
135 {
136     protected:
137         //! \copydoc FileIOError::FileIOError()
138         explicit UserInputError(const std::string &reason)
139             : GromacsException(reason) {}
140 };
141
142 /*! \brief
143  * Exception class for situations where user input cannot be parsed/understood.
144  *
145  * \ingroup module_utility
146  */
147 class InvalidInputError : public UserInputError
148 {
149     public:
150         //! \copydoc FileIOError::FileIOError()
151         explicit InvalidInputError(const std::string &reason)
152             : UserInputError(reason) {}
153
154         virtual int errorCode() const;
155 };
156
157 /*! \brief
158  * Exception class for situations where user input is inconsistent.
159  *
160  * \ingroup module_utility
161  */
162 class InconsistentInputError : public UserInputError
163 {
164     public:
165         //! \copydoc FileIOError::FileIOError()
166         explicit InconsistentInputError(const std::string &reason)
167             : UserInputError(reason) {}
168
169         virtual int errorCode() const;
170 };
171
172 /*! \brief
173  * Exception class for simulation instabilities.
174  *
175  * \ingroup module_utility
176  */
177 class SimulationInstabilityError : public GromacsException
178 {
179     public:
180         //! \copydoc FileIOError::FileIOError()
181         explicit SimulationInstabilityError(const std::string &reason)
182             : GromacsException(reason) {}
183
184         virtual int errorCode() const;
185 };
186
187 /*! \brief
188  * Exception class for internal errors.
189  *
190  * \ingroup module_utility
191  */
192 class InternalError : public GromacsException
193 {
194     public:
195         //! \copydoc FileIOError::FileIOError()
196         explicit InternalError(const std::string &reason)
197             : GromacsException(reason) {}
198
199         virtual int errorCode() const;
200 };
201
202 /*! \brief
203  * Exception class for incorrect use of an API.
204  *
205  * \ingroup module_utility
206  */
207 class APIError : public GromacsException
208 {
209     public:
210         //! \copydoc FileIOError::FileIOError()
211         explicit APIError(const std::string &reason)
212             : GromacsException(reason) {}
213
214         virtual int errorCode() const;
215 };
216
217 /*! \brief
218  * Exception class for use of an unimplemented feature.
219  *
220  * \ingroup module_utility
221  */
222 class NotImplementedError : public APIError
223 {
224     public:
225         //! \copydoc FileIOError::FileIOError()
226         explicit NotImplementedError(const std::string &reason)
227             : APIError(reason) {}
228
229         virtual int errorCode() const;
230 };
231
232
233 /*! \brief
234  * Macro for throwing an exception.
235  *
236  * \param[in] e    Exception object to throw.
237  *
238  * Using this macro instead of \c throw directly makes it possible to uniformly
239  * attach information into the exception objects.
240  * \p e should evaluate to an instance of an object derived from
241  * GromacsException.
242  *
243  * Basic usage:
244  * \code
245 if (value < 0)
246 {
247     GMX_THROW(InconsistentUserInput("Negative values not allowed for value"));
248 }
249  * \endcode
250  */
251 #define GMX_THROW(e) \
252     BOOST_THROW_EXCEPTION((e))
253
254 /*! \brief
255  * Macro for throwing an exception based on errno.
256  *
257  * \param[in] e       Exception object to throw.
258  * \param[in] syscall Name of the syscall that returned the error.
259  * \param[in] err     errno value returned by the syscall.
260  *
261  * This macro provides a convenience interface for throwing an exception to
262  * report an error based on a errno value.  In addition to adding the necessary
263  * information to the exception object, the macro also ensures that \p errno is
264  * evaluated before, e.g., the constructor of \p e may call other functions
265  * that could overwrite the errno value.
266  * \p e should evaluate to an instance of an object derived from
267  * GromacsException.
268  *
269  * Typical usage (note that gmx::File wraps this particular case):
270  * \code
271 FILE *fp = fopen("filename.txt", "r");
272 if (fp == NULL)
273 {
274     GMX_THROW(FileIOError("Could not open file"), "fopen", errno);
275 }
276  * \endcode
277  */
278 #define GMX_THROW_WITH_ERRNO(e, syscall, err) \
279     do { \
280         int stored_errno_ = (err); \
281         GMX_THROW((e) << boost::errinfo_errno(stored_errno_) \
282                       << boost::errinfo_api_function(syscall)); \
283     } while(0)
284
285 /*! \brief
286  * Formats a standard error message for reporting an error.
287  *
288  * Normal usage in Gromacs command-line programs is like this:
289  * \code
290 int main(int argc, char *argv[])
291 {
292     try
293     {
294         // The actual code for the program
295         return 0;
296     }
297     catch (const std::exception &ex)
298     {
299         fprintf(stderr, "%s", gmx::formatErrorMessage(ex).c_str());
300         return 1;
301     }
302 }
303  * \endcode
304  */
305 std::string formatErrorMessage(const std::exception &ex);
306
307 /*! \brief
308  * Converts an exception into a return code.
309  */
310 int translateException(const std::exception &ex);
311
312 /*!\}*/
313
314 } // namespace gmx
315
316 #endif