Sort all includes in src/gromacs
[alexxy/gromacs.git] / src / gromacs / utility / exceptions.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2011,2012,2013,2014, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 /*! \file
36  * \brief
37  * Declares common exception classes and macros for fatal error handling.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \inpublicapi
41  * \ingroup module_utility
42  */
43 #ifndef GMX_UTILITY_EXCEPTIONS_H
44 #define GMX_UTILITY_EXCEPTIONS_H
45
46 #include <cstdio>
47 #include <cstdlib>
48
49 #include <exception>
50 #include <string>
51 #include <vector>
52
53 #include <boost/exception_ptr.hpp>
54 #include <boost/throw_exception.hpp>
55 #include <boost/exception/errinfo_api_function.hpp>
56 #include <boost/exception/errinfo_errno.hpp>
57 #include <boost/exception/exception.hpp>
58 #include <boost/exception/info.hpp>
59
60 namespace gmx
61 {
62
63 namespace internal
64 {
65 //! Internal container type for storing a list of nested exceptions.
66 typedef std::vector<boost::exception_ptr> NestedExceptionList;
67 }   // namespace internal
68
69 //! \addtogroup module_utility
70 //! \{
71
72 /*! \brief
73  * Provides information for Gromacs exception constructors.
74  *
75  * This class exists to implement common functionality for initializing all
76  * Gromacs exceptions without having extra code in each exception class.
77  * In simple cases, it can be implicitly constructed by passing a simple string
78  * to an exception constructor.
79  * If more complex initialization is necessary, it is possible to explicitly
80  * construct an object of this type and then call other methods to add
81  * information before actually creating the exception object.
82  *
83  * \todo
84  * With the exception of the reason string, information added with this class
85  * is not currently accessible through any public API, except for calling
86  * printFatalErrorMessage(), formatExceptionMessageToString() or
87  * formatExceptionMessageToFile().  This is not implemented as there is not yet
88  * need for it, and it is not clear what would be the best alternative for the
89  * access.  It should be possible to refactor the internal implementation to
90  * suit the needs of such external access without requiring changes in code
91  * that throws these exceptions.
92  *
93  * \ingroup module_utility
94  */
95 class ExceptionInitializer
96 {
97     public:
98         /*! \brief
99          * Creates an initialized with the given string as the reason.
100          *
101          * \param[in] reason  Detailed reason for the exception.
102          * \throw     std::bad_alloc if out of memory.
103          *
104          * This constructor is not explicit to allow constructing exceptions
105          * with a plain string argument given to the constructor without adding
106          * extra code to each exception class.
107          */
108         ExceptionInitializer(const char *reason)
109             : reason_(reason)
110         {
111         }
112         //! \copydoc ExceptionInitializer(const char *)
113         ExceptionInitializer(const std::string &reason)
114             : reason_(reason)
115         {
116         }
117
118         /*! \brief
119          * Returns true if addCurrentExceptionAsNested() has been called.
120          *
121          * Provided for convenience for cases where exceptions will be added
122          * conditionally, and the caller wants to check whether any excetions
123          * were actually added.
124          */
125         bool hasNestedExceptions() const { return !nested_.empty(); }
126         /*! \brief
127          * Adds the currently caught exception as a nested exception.
128          *
129          * May be called multiple times; all provided exceptions will be added
130          * in a list of nested exceptions.
131          *
132          * Must not be called outside a catch block.
133          */
134         void addCurrentExceptionAsNested()
135         {
136             nested_.push_back(boost::current_exception());
137         }
138         /*! \brief
139          * Adds the specified exception as a nested exception.
140          *
141          * May be called multiple times; all provided exceptions will be added
142          * in a list of nested exceptions.
143          *
144          * This is equivalent to throwing \p ex and calling
145          * addCurrentExceptionAsNested() in the catch block, but potentially
146          * more efficient.
147          */
148         template <class Exception>
149         void addNested(const Exception &ex)
150         {
151             nested_.push_back(boost::copy_exception(ex));
152         }
153
154     private:
155         std::string                     reason_;
156         internal::NestedExceptionList   nested_;
157
158         friend class GromacsException;
159 };
160
161 /*! \brief
162  * Base class for all exception objects in Gromacs.
163  *
164  * Although boost recommends using virtual inheritance in exception hiearchies,
165  * it is not used here for two reasons:
166  * -# It is only useful when there is diamond inheritance, and that should
167  *    never occur in this exception hierarchy because this class is the only
168  *    instance of multiple inheritance (Gromacs programming guidelines prohibit
169  *    multiple inheritance from concrete classes, but it is unavoidable here
170  *    because of the design of boost::exception).
171  * -# Because the constructor takes an argument, virtual inheritance would
172  *    complicate any classes that inherit indirectly from this class.
173  *
174  * \inpublicapi
175  */
176 class GromacsException : public std::exception, public boost::exception
177 {
178     public:
179         /*! \brief
180          * Returns the reason string for the exception.
181          *
182          * The return value is the string that was passed to the constructor.
183          */
184         virtual const char *what() const throw();
185         /*! \brief
186          * Returns the error code corresponding to the exception type.
187          */
188         virtual int errorCode() const = 0;
189
190         /*! \brief
191          * Adds context information to this exception.
192          *
193          * \param[in] context  Context string to add.
194          * \throws    std::bad_alloc if out of memory.
195          *
196          * Typical use is to add additional information higher up in the call
197          * stack using this function in a catch block and the rethrow the
198          * exception.
199          *
200          * \todo
201          * The added information is currently not accessible through what(),
202          * nor through any other means except for calling
203          * printFatalErrorMessage(), formatExceptionMessageToString() or
204          * formatExceptionMessageToFile(). See ExceptionInitializer for more
205          * discussion.
206          */
207         void prependContext(const std::string &context);
208
209     protected:
210         /*! \brief
211          * Creates an exception object with the provided initializer/reason.
212          *
213          * \param[in] details  Initializer for the exception.
214          * \throws    std::bad_alloc if out of memory.
215          */
216         explicit GromacsException(const ExceptionInitializer &details);
217 };
218
219 /*! \brief
220  * Exception class for file I/O errors.
221  *
222  * \inpublicapi
223  */
224 class FileIOError : public GromacsException
225 {
226     public:
227         /*! \brief
228          * Creates an exception object with the provided initializer/reason.
229          *
230          * \param[in] details  Initializer for the exception.
231          * \throws    std::bad_alloc if out of memory.
232          *
233          * It is possible to call this constructor either with an explicit
234          * ExceptionInitializer object (useful for more complex cases), or
235          * a simple string if only a reason string needs to be provided.
236          */
237         explicit FileIOError(const ExceptionInitializer &details)
238             : GromacsException(details) {}
239
240         virtual int errorCode() const;
241 };
242
243 /*! \brief
244  * Exception class for user input errors.
245  *
246  * Derived classes should be used to indicate the nature of the error instead
247  * of throwing this class directly.
248  *
249  * \inpublicapi
250  */
251 class UserInputError : public GromacsException
252 {
253     protected:
254         //! \copydoc FileIOError::FileIOError()
255         explicit UserInputError(const ExceptionInitializer &details)
256             : GromacsException(details) {}
257 };
258
259 /*! \brief
260  * Exception class for situations where user input cannot be parsed/understood.
261  *
262  * \inpublicapi
263  */
264 class InvalidInputError : public UserInputError
265 {
266     public:
267         //! \copydoc FileIOError::FileIOError()
268         explicit InvalidInputError(const ExceptionInitializer &details)
269             : UserInputError(details) {}
270
271         virtual int errorCode() const;
272 };
273
274 /*! \brief
275  * Exception class for situations where user input is inconsistent.
276  *
277  * \inpublicapi
278  */
279 class InconsistentInputError : public UserInputError
280 {
281     public:
282         //! \copydoc FileIOError::FileIOError()
283         explicit InconsistentInputError(const ExceptionInitializer &details)
284             : UserInputError(details) {}
285
286         virtual int errorCode() const;
287 };
288
289 /*! \brief
290  * Exception class for simulation instabilities.
291  *
292  * \inpublicapi
293  */
294 class SimulationInstabilityError : public GromacsException
295 {
296     public:
297         //! \copydoc FileIOError::FileIOError()
298         explicit SimulationInstabilityError(const ExceptionInitializer &details)
299             : GromacsException(details) {}
300
301         virtual int errorCode() const;
302 };
303
304 /*! \brief
305  * Exception class for internal errors.
306  *
307  * \inpublicapi
308  */
309 class InternalError : public GromacsException
310 {
311     public:
312         //! \copydoc FileIOError::FileIOError()
313         explicit InternalError(const ExceptionInitializer &details)
314             : GromacsException(details) {}
315
316         virtual int errorCode() const;
317 };
318
319 /*! \brief
320  * Exception class for incorrect use of an API.
321  *
322  * \inpublicapi
323  */
324 class APIError : public GromacsException
325 {
326     public:
327         //! \copydoc FileIOError::FileIOError()
328         explicit APIError(const ExceptionInitializer &details)
329             : GromacsException(details) {}
330
331         virtual int errorCode() const;
332 };
333
334 /*! \brief
335  * Exception class for use of an unimplemented feature.
336  *
337  * \inpublicapi
338  */
339 class NotImplementedError : public APIError
340 {
341     public:
342         //! \copydoc FileIOError::FileIOError()
343         explicit NotImplementedError(const ExceptionInitializer &details)
344             : APIError(details) {}
345
346         virtual int errorCode() const;
347 };
348
349
350 /*! \brief
351  * Macro for throwing an exception.
352  *
353  * \param[in] e    Exception object to throw.
354  *
355  * Using this macro instead of \c throw directly makes it possible to uniformly
356  * attach information into the exception objects.
357  * \p e should evaluate to an instance of an object derived from
358  * GromacsException.
359  *
360  * Basic usage:
361  * \code
362    if (value < 0)
363    {
364        GMX_THROW(InconsistentUserInput("Negative values not allowed for value"));
365    }
366    \endcode
367  */
368 #define GMX_THROW(e) \
369     BOOST_THROW_EXCEPTION((e))
370
371 /*! \brief
372  * Macro for throwing an exception based on errno.
373  *
374  * \param[in] e       Exception object to throw.
375  * \param[in] syscall Name of the syscall that returned the error.
376  * \param[in] err     errno value returned by the syscall.
377  *
378  * This macro provides a convenience interface for throwing an exception to
379  * report an error based on a errno value.  In addition to adding the necessary
380  * information to the exception object, the macro also ensures that \p errno is
381  * evaluated before, e.g., the constructor of \p e may call other functions
382  * that could overwrite the errno value.
383  * \p e should evaluate to an instance of an object derived from
384  * GromacsException.
385  *
386  * Typical usage (note that gmx::File wraps this particular case):
387  * \code
388    FILE *fp = fopen("filename.txt", "r");
389    if (fp == NULL)
390    {
391        GMX_THROW(FileIOError("Could not open file"), "fopen", errno);
392    }
393    \endcode
394  */
395 #define GMX_THROW_WITH_ERRNO(e, syscall, err) \
396     do { \
397         int stored_errno_ = (err); \
398         GMX_THROW((e) << boost::errinfo_errno(stored_errno_) \
399                   << boost::errinfo_api_function(syscall)); \
400     } while (0)
401
402 /*! \brief
403  * Formats a standard fatal error message for reporting an exception.
404  *
405  * \param[in] fp  %File to format the message to.
406  * \param[in] ex  Exception to format.
407  *
408  * Does not throw.  If memory allocation fails or some other error occurs
409  * while formatting the error, tries to print a reasonable alternative message.
410  *
411  * Normal usage in Gromacs command-line programs is like this:
412  * \code
413    int main(int argc, char *argv[])
414    {
415        gmx::init(&argc, &argv);
416        try
417        {
418            // The actual code for the program
419            return 0;
420        }
421        catch (const std::exception &ex)
422        {
423            gmx::printFatalErrorMessage(stderr, ex);
424            return gmx::processExceptionAtExit(ex);
425        }
426    }
427    \endcode
428  */
429 void printFatalErrorMessage(FILE *fp, const std::exception &ex);
430 /*! \brief
431  * Formats an error message for reporting an exception.
432  *
433  * \param[in] ex  Exception to format.
434  * \returns   Formatted string containing details of \p ex.
435  * \throws    std::bad_alloc if out of memory.
436  */
437 std::string formatExceptionMessageToString(const std::exception &ex);
438 /*! \brief
439  * Formats an error message for reporting an exception.
440  *
441  * \param     fp  %File to write the message to.
442  * \param[in] ex  Exception to format.
443  * \throws    std::bad_alloc if out of memory.
444  */
445 void formatExceptionMessageToFile(FILE *fp, const std::exception &ex);
446 /*! \brief
447  * Handles an exception that is causing the program to terminate.
448  *
449  * \param[in] ex  Exception that is the cause for terminating the program.
450  * \returns   Return code to return from main().
451  *
452  * This method should be called as the last thing before terminating the
453  * program because of an exception.  It exists to terminate the program as
454  * gracefully as possible in the case of MPI processing (but the current
455  * implementation always calls MPI_Abort()).
456  *
457  * See printFatalErrorMessage() for example usage.
458  *
459  * Does not throw.
460  */
461 int processExceptionAtExit(const std::exception &ex);
462
463 /*! \brief
464  * Converts an exception into a return code.
465  */
466 int translateException(const std::exception &ex);
467
468 /*! \brief
469  * Macro for catching exceptions at C++ -> C boundary.
470  *
471  * This macro is intended for uniform handling of exceptions when C++ code is
472  * called from C code within Gromacs.  Since most existing code is written
473  * using the assumption that fatal errors terminate the program, this macro
474  * implements this behavior for exceptions.  It should only be used in cases
475  * where the error cannot be propagated upwards using return values or such.
476  *
477  * Having this as a macro instead of having the same code in each place makes
478  * it easy to 1) find all such locations in the code, and 2) change the exact
479  * behavior if needed.
480  *
481  * Usage:
482    \code
483    try
484    {
485        // C++ code
486    }
487    GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
488    \endcode
489  */
490 #define GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR \
491     catch (const std::exception &ex) { \
492         ::gmx::printFatalErrorMessage(stderr, ex); \
493         ::std::exit(::gmx::processExceptionAtExit(ex)); \
494     }
495
496 //! \}
497
498 } // namespace gmx
499
500 #endif