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