1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 
4 #ifndef DUNE_EXCEPTIONS_HH
5 #define DUNE_EXCEPTIONS_HH
6 
7 #include <exception>
8 #include <string>
9 #include <sstream>
10 
11 namespace Dune {
12 
13   /*! \defgroup Exceptions Exception handling
14      \ingroup Common
15      \{
16 
17      The Dune-exceptions are designed to allow a simple derivation of subclasses
18      and to accept a text written in the '<<' syntax.
19 
20      Example of usage:
21 
22      \code
23      #include <dune/common/exceptions.hh>
24 
25      ...
26 
27      class FileNotFoundError : public Dune::IOError {};
28 
29      ...
30 
31      void fileopen (std::string name) {
32      std::ifstream file;
33 
34      file.open(name.c_str());
35 
36      if (file == 0)
37       DUNE_THROW(FileNotFoundError, "File " << name << " not found!");
38 
39      ...
40 
41      file.close();
42      }
43 
44      ...
45 
46      int main () {
47      try {
48       ...
49      } catch (Dune::IOError &e) {
50       std::cerr << "I/O error: " << e << std::endl;
51       return 1;
52      } catch (Dune::Exception &e) {
53       std::cerr << "Generic Dune error: " << e << std::endl;
54       return 2;
55      }
56      }
57      \endcode
58 
59      \see exceptions.hh for detailed info
60 
61    */
62 
63   /*! \file
64      \brief A few common exception classes
65 
66      This file defines a common framework for generating exception
67      subclasses and to throw them in a simple manner
68 
69    */
70 
71   /* forward declarations */
72   class Exception;
73   struct ExceptionHook;
74 
75   /*! \class Exception
76      \brief Base class for Dune-Exceptions
77 
78      all Dune exceptions are derived from this class via trivial subclassing:
79 
80      \code
81      class MyException : public Dune::Exception {};
82      \endcode
83 
84      You should not \c throw a Dune::Exception directly but use the macro
85      DUNE_THROW() instead which fills the message-buffer of the exception
86      in a standard way and features a way to pass the result in the
87      operator<<-style
88 
89      \see DUNE_THROW, IOError, MathError
90 
91    */
92   class Exception
93   : public std::exception
94   {
95   public:
96     Exception ();
97     void message(const std::string &msg); //!< store string in internal message buffer
98     const char* what() const noexcept override; //!< output internal message buffer
99     static void registerHook (ExceptionHook * hook); //!< add a functor which is called before a Dune::Exception is emitted (see Dune::ExceptionHook) \see Dune::ExceptionHook
100     static void clearHook ();                  //!< remove all hooks
101   private:
102     std::string _message;
103     static ExceptionHook * _hook;
104   };
105 
106   /*! \brief Base class to add a hook to the Dune::Exception
107 
108      The user can add a functor which should be called before a Dune::Exception is emitted.
109 
110 
111      Example: attach a debugger to the process, if an exception is thrown
112      \code
113      struct ExceptionHookDebugger : public Dune::ExceptionHook
114      {
115       char * process_;
116       char * debugger_;
117       ExceptionHookDebugger (int argc, char ** argv, std::string debugger)
118       {
119           process_ = strdup(argv[0]);
120           debugger_ = strdup(debugger.c_str());
121       }
122       virtual void operator () ()
123       {
124           pid_t pid = getpid();
125           pid_t cpid;
126           cpid = fork();
127           if (cpid == 0) // child
128           {
129               char * argv[4];
130               argv[0] = debugger_;
131               argv[1] = process_;
132               argv[2] = new char[12];
133               snprintf(argv[2], 12, "%i", int(pid));
134               argv[3] = 0;
135               // execute debugger
136               std::cout << process_ << "\n";
137               std::cout << argv[0] << " "
138                         << argv[1] << " "
139                         << argv[2] << std::endl;
140               execv(argv[0], argv);
141           }
142           else // parent
143           {
144               // send application to sleep
145               kill(pid, SIGSTOP);
146           }
147       }
148      };
149      \endcode
150 
151      This hook is registered via a static method of Dune::Exception:
152      \code
153      int main(int argc, char** argv) {
154       Dune::MPIHelper & mpihelper = Dune::MPIHelper::instance(argc,argv);
155       ExceptionHookDebugger debugger(argc, argv, "/usr/bin/ddd");
156       Dune::Exception::registerHook(& debugger);
157       try
158       {
159           ...
160       }
161       catch (std::string & s) {
162           std::cout << mpihelper.rank() << ": ERROR: " << s << std::endl;
163       }
164       catch (Dune::Exception & e) {
165           std::cout << mpihelper.rank() << ": DUNE ERROR: " << e.what() << std::endl;
166       }
167      }
168      \endcode
169 
170    */
171   struct ExceptionHook
172   {
~ExceptionHookDune::ExceptionHook173     virtual ~ExceptionHook() {}
174     virtual void operator () () = 0;
175   };
176 
operator <<(std::ostream & stream,const Exception & e)177   inline std::ostream& operator<<(std::ostream &stream, const Exception &e)
178   {
179     return stream << e.what();
180   }
181 
182 #ifndef DOXYGEN
183   // the "format" the exception-type gets printed.  __FILE__ and
184   // __LINE__ are standard C-defines, the GNU cpp-infofile claims that
185   // C99 defines __func__ as well. __FUNCTION__ is a GNU-extension
186 #define THROWSPEC(E) # E << " [" << __func__ << ":" << __FILE__ << ":" << __LINE__ << "]: "
187 #endif // DOXYGEN
188 
189   /*! Macro to throw an exception
190 
191      \code
192      #include <dune/common/exceptions.hh>
193      \endcode
194 
195      \param E exception class derived from Dune::Exception
196      \param m reason for this exception in ostream-notation
197 
198      Example:
199 
200      \code
201      if (filehandle == 0)
202       DUNE_THROW(FileError, "Could not open " << filename << " for reading!");
203      \endcode
204 
205      DUNE_THROW automatically adds information about the exception thrown
206      to the text.
207 
208      \note
209      you can add a hook to be called before a Dune::Exception is emitted,
210      e.g. to add additional information to the exception,
211      or to invoke a debugger during parallel debugging. (see Dune::ExceptionHook)
212 
213    */
214   // this is the magic: use the usual do { ... } while (0) trick, create
215   // the full message via a string stream and throw the created object
216 #define DUNE_THROW(E, m) do { E th__ex; std::ostringstream th__out; \
217                               th__out << THROWSPEC(E) << m; th__ex.message(th__out.str()); throw th__ex; \
218 } while (0)
219 
220   /*! \brief Default exception class for I/O errors
221 
222      This is a superclass for any errors dealing with file/socket I/O problems
223      like
224 
225      - file not found
226      - could not write file
227      - could not connect to remote socket
228    */
229   class IOError : public Exception {};
230 
231   /*! \brief Default exception class for mathematical errors
232 
233      This is the superclass for all errors which are caused by
234      mathematical problems like
235 
236      - matrix not invertible
237      - not convergent
238    */
239   class MathError : public Exception {};
240 
241   /*! \brief Default exception class for range errors
242 
243      This is the superclass for all errors which are caused because
244      the user tries to access data that was not allocated before.
245      These can be problems like
246 
247      - accessing array entries behind the last entry
248      - adding the fourth non zero entry in a sparse matrix
249        with only three non zero entries per row
250 
251    */
252   class RangeError : public Exception {};
253 
254   /*! \brief Default exception for dummy implementations
255 
256      This exception can be used for functions/methods
257 
258      - that have to be implemented but should never be called
259      - that are missing
260    */
261   class NotImplemented : public Exception {};
262 
263   /*! \brief Default exception class for OS errors
264 
265      This class is thrown when a system-call is used and returns an
266      error.
267 
268    */
269   class SystemError : public Exception {};
270 
271   /*! \brief Default exception if memory allocation fails
272 
273    */
274   class OutOfMemoryError : public SystemError {};
275 
276   /*! \brief Default exception if a function was called while
277      the object is not in a valid state for that function.
278    */
279   class InvalidStateException : public Exception {};
280 
281   /*! \brief Default exception if an error in the parallel
282      communication of the program occurred
283      \ingroup ParallelCommunication
284    */
285   class ParallelError : public Exception {};
286 
287 } // end namespace
288 
289 #endif
290