Flow123d  jenkins-Flow123d-linux-release-multijob-282
exceptions.hh
Go to the documentation of this file.
1 /*
2  * exceptions.hh
3  *
4  * Created on: Apr 10, 2012
5  * Author: jb
6  */
7 
8 
9 #ifndef EXCEPTIONS_HH_
10 #define EXCEPTIONS_HH_
11 
12 
13 #include <boost/exception/all.hpp>
14 #include <iostream>
15 #include <string>
16 
17 
18 
19 /**
20  * @brief Wrapper for throw. Saves the throwing point.
21  *
22  * Macro for throwing with saving place of the throw. Just shortcut for BOOST_THROW_EXCEPTION. Creates boost kind of exception, that may
23  * accept further information through redirection.
24  *
25  * Usage:
26  * @code
27  * THROW( ExcError() << EI_SomeValue(42) );
28  * @endcode
29  *
30  * EI_SomeValue is an @p error_info object for transfer of values form throw point to catch point. See @p EI<Tag,Type> class template.
31  *
32  * @ingroup exceptions
33  */
34 #define THROW(whole_exception_expr) BOOST_THROW_EXCEPTION( whole_exception_expr)
35 
36 
37 namespace internal {
38  class ExcStream;
39 }
40 
41 /**
42  * @brief Base of exceptions used in Flow123d.
43  *
44  * We use boost::exception as parent in order to allow passing
45  * some data through the exception object from the throw point to the catch point.
46  * See DECLARE_EXCEPTION macro for usage.
47  *
48  * When deriving particular exceptions always use virtual inheritance:
49  * @code
50  * struct my_exception : virtual ExceptionBase {};
51  * @endcode
52  *
53  * @ingroup exceptions
54  */
55 class ExceptionBase : public virtual std::exception, public virtual boost::exception
56 {
57 public:
58  /// Default constructor, just calls @p fill_stacktrace().
59  ExceptionBase();
60  /// Copy constructor, performs deep copy of stacktrace.
61  ExceptionBase(const ExceptionBase &other);
62  /// Call GNU backtrace if available, save call stack information into @p stacktrace member.
63  void fill_stacktrace();
64  /// Prints formated stacktrace into given stream @p out.
65  void print_stacktrace(std::ostream &out) const;
66  /**
67  * Purely virtual method, that should be implemented by descendants. Prints specific error message into
68  * stream @p out. In particular you can use macros DECLARE_EXCEPTION or DECLARE_INPUT_EXCEPTION for easy declarations.
69  */
70  virtual void print_info(std::ostringstream &out) const=0;
71  /**
72  * Overloaded method for output the exception message if it is not catched.
73  * Implements composition of complex message including diagnostic informations and stack trace.
74  * Should not be overloded in descendant classes. Use @p print_info instead.
75  */
76  virtual const char * what () const throw ();
77  /// Destructor, possibly free stacktrace.
78  virtual ~ExceptionBase() throw ();
79 
80 private:
81 
82  /// Array of backtrace frames returned by glibc backtrace_symbols.
83  char ** stacktrace;
84 
85  /// Size of stacktrace table - number of frames.
87 };
88 
89 
90 
91 
92 
93 /**
94  * @brief Macro for simple definition of exceptions.
95  *
96  * First parameter, @p ExcName, is name of the exception class to define. Macro expands to
97  * the class derived from @p ExceptionBase and implements virtual method @p print_info
98  * with output given by @p Format, the second parameter of the macro. This method is used
99  * by what() method to produce specific part of the error message.
100  *
101  * You can use error info classes (see @p TYPEDEFERR_INFO) and stream modifiers
102  * @p val, @p qval to output relevant data. Modifier @p val outputs plain value,
103  * modifier @p qval outputs value in quotas.
104  *
105  * Example:
106  * @code
107  * TYPEDEF_ERR_INFO( EI_Dim1Mismatch, int);
108  * TYPEDEF_ERR_INFO( EI_Dim2Mismatch, int);
109  * DECLARE_EXCEPTION( ExcDimensionMismatch,
110  * << "Dimensions dim1=" << EI_Dim1Missmatch::val
111  * << " and dim2=" << EI_Dim2Mismatch::val << " should be same.");
112  * @endcode
113  *
114  * One can also pass whole classes through the exception as long as they are default constructable and copy constructable.
115  *
116  * Example:
117  * @code
118  * class Matrix;
119  * TYPEDEF_ERR_INFO( EI_Matrix, Matrix);
120  * DECLARE_EXCEPTION( ExcWrongMatrixState,
121  * << "Matrix state: " << EI_Matrix::ptr(*this)->state() << "\n"
122  * << "Matrix info: " << EI_Matrix::ref(*this).info() );
123  * @endcode
124  *
125  * The example shows two ways how to call methods of the object of class Matrix passed through the exception. One can either get pointer to the object or
126  * reference. The @p ref method checks that the pointer to the object is not NULL (so that the object was actually passed).
127  * The @p ptr method do not perform the check. However, when using one of these methods you have to guarantee that the @p error_info object
128  * is passed to the exception at every throw point that use that exception. Otherwise you get an error,
129  * meaningful in case of the @p ref method, seg. fault for the @p ptr method.
130  *
131  * Currently implemented mechanism do no support standard stream modifiers, namely "endl". Please, use "\n" instead.
132  *
133  * @ingroup exceptions
134  */
135 #define DECLARE_EXCEPTION( ExcName, Format) \
136 struct ExcName : public virtual ::ExceptionBase { \
137  virtual void print_info(std::ostringstream &out) const { \
138  using namespace internal; \
139  ::internal::ExcStream estream(out, *this); \
140  estream Format ; \
141  out << std::endl; \
142  } \
143  virtual ~ExcName() throw () {} \
144 }
145 
146 
147 
148 /**
149  * @brief Macro to simplify declaration of error_info types.
150  *
151  * Is used to declare types of data that can be passed through exceptions from the throw point to the catch point, or possibly collect
152  * various data along stack rewinding when an exception is thrown.
153  *
154  * Typical usage:
155  * @code
156  * // declares type EI_ParticularNumber
157  * TYPEDEF_ERR_INFO( EI_ParticularNumber, int);
158  * // declares exception that use it
159  * DECLARE_EXCEPTION(SomeException, << " Particular number: " << EI_ParticularNumber::val );
160  * // ... some code ...
161  *
162  * // here you pass particular number important for
163  * // determination of cause of the exception
164  * THROW( SomeException() << EI_ParticularNumber(10) );
165  *
166  * @endcode
167  *
168  * @ingroup exceptions
169  *
170  */
171 #define TYPEDEF_ERR_INFO(EI_Type, Type) typedef EI< struct EI_Type##_TAG, Type > EI_Type
172 
173 /**
174  * This class should not be used directly but through macro TYPEDEF_ERR_INFO.
175  * It is derived from boost::error_info<tag, type> and similarly as its parent it
176  * is tailored for passing a value of type @p Type from the throw point to
177  * the catch point. Compared to boost::error_info it provides manipulators @p val and @p qval
178  * which can by used in formating exception message to the ExcStream. The first manipulator evaluates
179  * directly to the output of the stored value, while @p qval puts the output into single quotas.
180  *
181  * The static function @p ref can be used when you want to extract and output some particular information
182  * from the passed value. However, if no value is given at throw point this function simply aborts. There is
183  * probably no way how to make the check and still keep flexibility in manipulation with the result of @p ref
184  * function.
185  *
186  * For usage see documentation of @p TYPEDEF_ERR_INFO mecro.
187  */
188 template<class Tag, class Type>
189 class EI : public boost::error_info< Tag, Type > {
190 public:
191  typedef typename boost::error_info< Tag, Type> ErrorInfo;
192 
193  /// Construction from given value, that has to bee passed to the catch point.
194  EI(Type const & value) : ErrorInfo(value) {}
195  /**
196  * Stream manipulator used to output the stored value. We have to use special stream ExcStream, that
197  * has overloaded << operator in order to support manipulators 'val' and 'qval'.
198  */
200  /**
201  * Stream manipulator for output of quoted value.
202  */
204 
205  /**
206  * Returns reference to stored value in given exception object @p e.
207  * Check validity of the value.
208  */
209  static Type const & ref( ExceptionBase const &e);
210 
211  /**
212  * Similar to the previous but returns pointer to the stored value and check nothing.
213  */
214  static Type const * ptr( ExceptionBase const &e);
215 
216 };
217 
218 
219 
220 
221 
222 
223 
224 
225 namespace internal {
226 
227 /*
228  * Helper class template. Together with its redirection operator it either outputs value pointed by pointer given to the constructor or
229  * , if the pointer is null, outputs string 'NO_VALUE'. If the optional parameter quoted is true, the value is printed in single quotation marks.
230  */
231 template <class Type>
233 public:
234  NullOutputEnvelope( const Type * x, bool quoted =false)
235  : x_(x), quoted_(quoted) {}
236  inline bool is_null() const {return x_ == NULL;}
237  inline bool is_quoted() const { return quoted_; }
238  inline const Type & value() const {return (*x_);}
239 private:
240  const Type * x_;
241  bool quoted_;
242 };
243 
244 template<class Type>
245 std::ostream& operator<<
246  (std::ostream& stream, const NullOutputEnvelope<Type> & value)
247 {
248  if (value.is_null()) return (stream << "NO_VALUE");
249  else if (value.is_quoted()) return (stream << "'" << value.value() << "'");
250  else return (stream << value.value() );
251 }
252 
253 
254 /**
255  * Helper stream that knows stream and exception for which we format the message.
256  *
257  * TODO: Make std manipulators work!
258  */
259 
260 class ExcStream : public std::ostream {
261 public:
262  ExcStream(std::ostream & stream,const ExceptionBase &exc) : stream_(stream), exc_(exc) {}
263  std::ostream & stream_;
265 
266  // treat exception manipulators
268  {
269  return pf(*this);
270  }
271  /*
272  // treat other manipulators ( This doesn't work. Why?? )
273  template <class T>
274  ExcStream & operator<<(T & (*pf) (T &) )
275  {
276  pf(stream_);
277  return (*this);
278  }*/
279 };
280 
281 
282 template < class T>
283 ExcStream & operator<<(ExcStream & estream, const T & x)
284 {
285  estream.stream_ << x;
286  return estream;
287 }
288 
289 template < class Tag, class Type, class Func>
290 internal::ExcStream & operator<<(internal::ExcStream & estream, typename EI<Tag, Type>::template lambda<Func> const & lambda_func)
291 {
292  if (EI<Tag,Type>::get_value_ptr()) estream.stream_ << "NO_VALUE";
293  else estream.stream_ << lambda_func.func_(* EI<Tag,Type>::get_value_ptr());
294  return estream;
295 }
296 
297 
298 } // namespace internal
299 
300 
301 
302 /**
303  * Exception thrown in xprintf function.
304  */
305 TYPEDEF_ERR_INFO( EI_XprintfHeader, std::string);
306 TYPEDEF_ERR_INFO( EI_XprintfMessage, std::string);
307 DECLARE_EXCEPTION( ExcXprintfMsg, << EI_XprintfHeader::val << EI_XprintfMessage::val);
308 
309 
310 
311 
312 /***********************************************************************
313  * Implementation of templated method
314  */
315 
316 template <class Tag, class Type>
319  ( ptr(es.exc_), false );
320  return es;
321 }
322 
323 
324 
325 template <class Tag, class Type>
328  ( ptr(es.exc_), true );
329  return es;
330 }
331 
332 
333 template <class Tag, class Type>
334 Type const & EI<Tag, Type>::ref( ExceptionBase const &e)
335  {
336  Type const * val_ptr = boost::get_error_info< ErrorInfo > (e);
337  if (! val_ptr) {
338  // try to printout unfinished ErrStream
339  std::cerr << "------------------------------------------------------------------------------\n";
340  std::cerr << " Fatal Error - dereferencing null pointer when formating an exception message.\n";
341  std::cerr << "------------------------------------------------------------------------------\n";
342  std::cerr << "** Diagnosting Informations **\n";
343  std::cerr << boost::diagnostic_information_what( e );
344  abort();
345  }
346  return *val_ptr;
347  }
348 
349 
350 template <class Tag, class Type>
351 Type const * EI<Tag, Type>::ptr( ExceptionBase const &e)
352  { return boost::get_error_info< ErrorInfo > (e); }
353 
354 
355 /**
356  * Assertion that results in an exception.
357  */
358 /*
359 #ifdef DEBUG_ASSERTS
360 
361 #define ASSERT_THROW( condition, exception ) \
362  (condition) ? : throw
363 
364 #else
365 
366 #define ASSERT_THROW( condition, exception )
367 #endif
368 */
369 
370 
371 
372 
373 /*******************************************************************
374 
375 Myslenky ohledne exceptions, chybovych hlasek a logovani (co dnes zajistuje xprintf
376 
377 1) Nutno oddelit nechybove logovani (vcetne warningu) a chybove zpravy (ty pokud je nekdo neodchyti tak vedou na terminate() )
378 
379 2) Logovani ted neresim.
380 
381 3) Jakakoliv chyba by mela radeji vyvolavat vyjimku (lze odchytit, lze pridavat inforamace behem stack unfolding. )
382  A to vcetne ASSERT.
383 
384 4) Neprijemne je, ze exception musim definovat jako zvlastni tridy, zejmena pokud chci mit nejake specialni formaty chybovych hlasek.
385  ale navrhl jsem makro a navazujici implementacni sablony, ktere by to mely zjednodusit. (inspirovano deal.ii)
386 
387 5) bylo by dobre mit par preddefinovanych vyjimek a preddefinovanych assertions.
388 
389 
390 
391 
392 */
393 
394 #endif /* EXCEPTIONS_HH_ */
static internal::ExcStream & qval(internal::ExcStream &es)
Definition: exceptions.hh:326
std::ostream & stream_
Definition: exceptions.hh:263
virtual const char * what() const
Definition: exceptions.cc:116
ExceptionBase()
Default constructor, just calls fill_stacktrace().
Definition: exceptions.cc:22
#define DECLARE_EXCEPTION(ExcName, Format)
Macro for simple definition of exceptions.
Definition: exceptions.hh:135
const ExceptionBase & exc_
Definition: exceptions.hh:264
void fill_stacktrace()
Call GNU backtrace if available, save call stack information into stacktrace member.
Definition: exceptions.cc:57
static Type const & ref(ExceptionBase const &e)
Definition: exceptions.hh:334
static Type const * ptr(ExceptionBase const &e)
Definition: exceptions.hh:351
static internal::ExcStream & val(internal::ExcStream &es)
Definition: exceptions.hh:317
#define TYPEDEF_ERR_INFO(EI_Type, Type)
Macro to simplify declaration of error_info types.
Definition: exceptions.hh:171
EI(Type const &value)
Construction from given value, that has to bee passed to the catch point.
Definition: exceptions.hh:194
ExcStream & operator<<(ExcStream &(*pf)(ExcStream &))
Definition: exceptions.hh:267
std::ostream & operator<<(std::ostream &stream, const NullOutputEnvelope< Type > &value)
Definition: exceptions.hh:246
NullOutputEnvelope(const Type *x, bool quoted=false)
Definition: exceptions.hh:234
ExcStream(std::ostream &stream, const ExceptionBase &exc)
Definition: exceptions.hh:262
const Type & value() const
Definition: exceptions.hh:238
virtual ~ExceptionBase()
Destructor, possibly free stacktrace.
Definition: exceptions.cc:48
Base of exceptions used in Flow123d.
Definition: exceptions.hh:55
char ** stacktrace
Array of backtrace frames returned by glibc backtrace_symbols.
Definition: exceptions.hh:83
void print_stacktrace(std::ostream &out) const
Prints formated stacktrace into given stream out.
Definition: exceptions.cc:75
boost::error_info< Tag, Type > ErrorInfo
Definition: exceptions.hh:191
int n_stacktrace_frames
Size of stacktrace table - number of frames.
Definition: exceptions.hh:86
virtual void print_info(std::ostringstream &out) const =0