]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/cxx/lib/base/include/exceptions
Inital import
[l4.git] / l4 / pkg / cxx / lib / base / include / exceptions
1 // vi:ft=cpp
2 /**
3  * \file
4  * \brief Base exceptions
5  * \ingroup l4cxx_exceptions
6  */
7 /*
8  * (c) 2008-2009 Technische Universität Dresden
9  * This file is part of TUD:OS and distributed under the terms of the
10  * GNU General Public License 2.
11  * Please see the COPYING-GPL-2 file for details.
12  *
13  * As a special exception, you may use this file as part of a free software
14  * library without restriction.  Specifically, if other files instantiate
15  * templates or use macros or inline functions from this file, or you compile
16  * this file and link it with other files to produce an executable, this
17  * file does not by itself cause the resulting executable to be covered by
18  * the GNU General Public License.  This exception does not however
19  * invalidate any other reasons why the executable file might be covered by
20  * the GNU General Public License.
21  */
22
23 #pragma once
24
25 #include <l4/cxx/l4types.h>
26 #include <l4/cxx/basic_ostream>
27 #include <l4/sys/err.h>
28 #include <l4/sys/capability>
29
30
31 /**
32  * \defgroup l4cxx_exceptions C++ Exceptions
33  * \ingroup api_l4re
34  */
35 /*@{*/
36
37 #ifndef L4_CXX_NO_EXCEPTION_BACKTRACE
38 # define L4_CXX_EXCEPTION_BACKTRACE 20
39 #endif
40
41 #if defined(L4_CXX_EXCEPTION_BACKTRACE)
42 #include <l4/util/backtrace.h>
43 #endif
44
45 /*@}*/
46 namespace L4
47 {
48
49   /**
50    * \addtogroup l4cxx_exceptions
51    */
52   /*@{*/
53   /**
54    * \brief Back-trace support for exceptions.
55    * \headerfile l4/cxx/exceptions
56    *
57    * This class holds an array of at most #L4_CXX_EXCEPTION_BACKTRACE
58    * instruction pointers containing the call trace at the instant when an
59    * exception was thrown.
60    */
61   class Exception_tracer
62   {
63 #if defined(L4_CXX_EXCEPTION_BACKTRACE)
64   private:
65     void *_pc_array[L4_CXX_EXCEPTION_BACKTRACE];
66     int   _frame_cnt;
67
68   protected:
69     /**
70      * \brief Create a back trace.
71      */
72 #if defined(__PIC__)
73     Exception_tracer() throw() : _frame_cnt(0) {}
74 #else
75     Exception_tracer() throw() : _frame_cnt(l4util_backtrace(_pc_array, L4_CXX_EXCEPTION_BACKTRACE)) {}
76 #endif
77
78   public:
79     /**
80      * \brief Get the array containing the call trace.
81      */
82     void const *const *pc_array() const throw() { return _pc_array; }
83     /**
84      * \brief Get the number of entries that are valid in the call trace.
85      */
86     int frame_count() const throw() { return _frame_cnt; }
87 #else
88   protected:
89     /**
90      * \brief Create a back trace.
91      */
92     Exception_tracer() throw() {}
93
94   public:
95     /**
96      * \brief Get the array containing the call trace.
97      */
98     void const *const *pc_array() const throw() { return 0; }
99     /**
100      * \brief Get the number of entries that are valid in the call trace.
101      */
102     int frame_count() const throw() { return 0; }
103 #endif
104   };
105
106   /**
107    * \brief Base class for all exceptions, thrown by the L4Re framework.
108    * \headerfile l4/cxx/exceptions
109    *
110    * This is the abstract base of all exceptions thrown within the
111    * L4Re framework. It is basically also a good idea to use it as base of
112    * all user defined exceptions.
113    */
114   class Base_exception : public Exception_tracer
115   {
116   protected:
117     /// Create a base exception.
118     Base_exception() throw() {}
119
120   public:
121     /**
122      * \brief Should return a human readable string for the exception.
123      */
124     virtual char const *str() const throw () = 0;
125
126     /// Destruction
127     virtual ~Base_exception() throw () {}
128   };
129
130   /**
131    * \brief Exception for an abstract runtime error.
132    * \headerfile l4/cxx/exceptions
133    *
134    * This is the base class for a set of exceptions that cover all errors
135    * that have a C error value (see #l4_error_code_t).
136    */
137   class Runtime_error : public Base_exception
138   {
139   private:
140     long _errno;
141     char _extra[80];
142
143   public:
144     explicit Runtime_error(long err_no, char const *extra = 0) throw ()
145       : _errno(err_no)
146     {
147       for (unsigned i = 0; i < sizeof(_extra) && extra[i]; ++i)
148         _extra[i] = extra[i];
149       _extra[sizeof(_extra) - 1] = 0;
150     }
151     char const *str() const throw ()
152     { return l4sys_errtostr(_errno); }
153     char const *extra_str() const { return _extra; }
154     ~Runtime_error() throw () {}
155
156     long err_no() const throw() { return _errno; }
157   };
158
159   /**
160    * \brief Exception signalling insufficient memory.
161    * \headerfile l4/cxx/exceptions
162    */
163   class Out_of_memory : public Runtime_error
164   {
165   public:
166     /// Create an out-of-memory exception.
167     explicit Out_of_memory(char const *extra = "") throw()
168     : Runtime_error(-L4_ENOMEM, extra) {}
169     /// Destruction
170     ~Out_of_memory() throw() {}
171   };
172
173
174   /**
175    * \brief Exception for duplicate element insertions.
176    * \headerfile l4/cxx/exceptions
177    */
178   class Element_already_exists : public Runtime_error
179   {
180   public:
181     explicit Element_already_exists(char const *e = "") throw()
182     : Runtime_error(-L4_EEXIST, e) {}
183     ~Element_already_exists() throw() {}
184   };
185
186   /**
187    * \brief Exception for an unknown condition.
188    * \headerfile l4/cxx/exceptions
189    *
190    * This error is usually used when a server returns an unknown return state
191    * to the client, this may indicate incompatible messages used by the client
192    * and the server.
193    */
194   class Unknown_error : public Base_exception
195   {
196   public:
197     Unknown_error() throw() {}
198     char const *str() const throw() { return "unknown error"; }
199     ~Unknown_error() throw() {}
200   };
201
202   
203   /**
204    * \brief Exception for a failed lookup (element not found).
205    * \headerfile l4/cxx/exceptions
206    */
207   class Element_not_found : public Runtime_error
208   {
209   public:
210     explicit Element_not_found(char const *e = "") throw()
211     : Runtime_error(-L4_ENOENT, e) {}
212   };
213
214   /**
215    * \brief Indicates that an invalid object was invoked.
216    * \headerfile l4/cxx/exceptions
217    *
218    * An Object is invalid if it has L4_INVALID_ID as server L4 UID,
219    * or if the server does not know the object ID.
220    */
221   class Invalid_capability : public Base_exception
222   {
223   private:
224     Cap<void> const _o;
225
226   public:
227     /**
228      * \brief Create an Invalid_obejct exception for the Object o.
229      * \param o The object that caused the server side error.
230      */
231     explicit Invalid_capability(Cap<void> const &o) throw() : _o(o) {}
232     template< typename T>
233     explicit Invalid_capability(Cap<T> const &o) throw() : _o(o.cap()) {}
234     char const *str() const throw() { return "invalid object"; }
235
236     /**
237      * \brief Get the object that caused the error.
238      * \return The object that caused the error on invocation.
239      */
240     Cap<void> const &cap() const throw() { return _o; }
241     ~Invalid_capability() throw() {}
242   };
243
244   /**
245    * \brief Error conditions during IPC.
246    * \headerfile l4/cxx/exceptions
247    *
248    * This exception encapsulates all IPC error conditions of L4 IPC.
249    */
250   class Com_error : public Runtime_error
251   {
252   public:
253     /**
254      * \brief Create a Com_error for the givel L4 IPC error code.
255      * \param err The L4 IPC error code (l4_ipc... return value).
256      */
257     explicit Com_error(long err) throw() : Runtime_error(err) {}
258
259     ~Com_error() throw() {}
260   };
261
262   /**
263    * \brief Access out of bounds.
264    */
265   class Bounds_error : public Runtime_error
266   {
267   public:
268     explicit Bounds_error(char const *e = "") throw()
269     : Runtime_error(-L4_ERANGE, e) {}
270     ~Bounds_error() throw() {}
271   };
272   /*@}*/
273 };
274
275 inline
276 L4::BasicOStream &
277 operator << (L4::BasicOStream &o, L4::Base_exception const &e)
278 {
279   o << "Exception: " << e.str() << ", backtrace ...\n";
280   for (int i = 0; i < e.frame_count(); ++i)
281     o << L4::n_hex(l4_addr_t(e.pc_array()[i])) << '\n';
282
283   return o;
284 }
285
286 inline
287 L4::BasicOStream &
288 operator << (L4::BasicOStream &o, L4::Runtime_error const &e)
289 {
290   o << "Exception: " << e.str() << ": ";
291   if (e.extra_str())
292     o << e.extra_str() << ": ";
293   o << "backtrace ...\n";
294   for (int i = 0; i < e.frame_count(); ++i)
295     o << L4::n_hex(l4_addr_t(e.pc_array()[i])) << '\n';
296
297   return o;
298 }
299