]> git.sesse.net Git - casparcg/blob - tbb/include/tbb/tbb_exception.h
2.0.0.2: Updated tbb version.
[casparcg] / tbb / include / tbb / tbb_exception.h
1 /*
2     Copyright 2005-2011 Intel Corporation.  All Rights Reserved.
3
4     This file is part of Threading Building Blocks.
5
6     Threading Building Blocks is free software; you can redistribute it
7     and/or modify it under the terms of the GNU General Public License
8     version 2 as published by the Free Software Foundation.
9
10     Threading Building Blocks is distributed in the hope that it will be
11     useful, but WITHOUT ANY WARRANTY; without even the implied warranty
12     of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with Threading Building Blocks; if not, write to the Free Software
17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
19     As a special exception, you may use this file as part of a free software
20     library without restriction.  Specifically, if other files instantiate
21     templates or use macros or inline functions from this file, or you compile
22     this file and link it with other files to produce an executable, this
23     file does not by itself cause the resulting executable to be covered by
24     the GNU General Public License.  This exception does not however
25     invalidate any other reasons why the executable file might be covered by
26     the GNU General Public License.
27 */
28
29 #ifndef __TBB_exception_H
30 #define __TBB_exception_H
31
32 #include "tbb_stddef.h"
33
34 #if !TBB_USE_EXCEPTIONS && _MSC_VER
35     // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers
36     #pragma warning (push)
37     #pragma warning (disable: 4530)
38 #endif
39
40 #include <stdexcept>
41 #include <string> // required to construct std exception classes
42
43 #if !TBB_USE_EXCEPTIONS && _MSC_VER
44     #pragma warning (pop)
45 #endif
46
47 namespace tbb {
48
49 //! Exception for concurrent containers
50 class bad_last_alloc : public std::bad_alloc {
51 public:
52     /*override*/ const char* what() const throw();
53 #if __TBB_DEFAULT_DTOR_THROW_SPEC_BROKEN
54     /*override*/ ~bad_last_alloc() throw() {}
55 #endif
56 };
57
58 //! Exception for PPL locks
59 class improper_lock : public std::exception {
60 public:
61     /*override*/ const char* what() const throw();
62 };
63
64 //! Exception for missing wait on structured_task_group
65 class missing_wait : public std::exception {
66 public:
67     /*override*/ const char* what() const throw();
68 };
69
70 //! Exception for repeated scheduling of the same task_handle
71 class invalid_multiple_scheduling : public std::exception {
72 public:
73     /*override*/ const char* what() const throw();
74 };
75
76 namespace internal {
77 //! Obsolete
78 void __TBB_EXPORTED_FUNC throw_bad_last_alloc_exception_v4();
79
80 enum exception_id {
81     eid_bad_alloc = 1,
82     eid_bad_last_alloc,
83     eid_nonpositive_step,
84     eid_out_of_range,
85     eid_segment_range_error,
86     eid_index_range_error,
87     eid_missing_wait,
88     eid_invalid_multiple_scheduling,
89     eid_improper_lock,
90     eid_possible_deadlock,
91     eid_operation_not_permitted,
92     eid_condvar_wait_failed,
93     eid_invalid_load_factor,
94     eid_reserved, // free slot for backward compatibility, can be reused.
95     eid_invalid_swap,
96     eid_reservation_length_error,
97     eid_invalid_key,
98     //! The last enumerator tracks the number of defined IDs. It must remain the last one.
99     /** When adding new IDs, place them immediately _before_ this comment (that is
100         _after_ all the existing IDs. NEVER insert new IDs between the existing ones. **/
101     eid_max
102 };
103
104 //! Gathers all throw operators in one place.
105 /** Its purpose is to minimize code bloat that can be caused by throw operators
106     scattered in multiple places, especially in templates. **/
107 void __TBB_EXPORTED_FUNC throw_exception_v4 ( exception_id );
108
109 //! Versionless convenience wrapper for throw_exception_v4()
110 inline void throw_exception ( exception_id eid ) { throw_exception_v4(eid); }
111
112 } // namespace internal
113 } // namespace tbb
114
115 #if __TBB_TASK_GROUP_CONTEXT
116 #include "tbb_allocator.h"
117 #include <exception>
118 #include <typeinfo>
119 #include <new>
120
121 namespace tbb {
122
123 //! Interface to be implemented by all exceptions TBB recognizes and propagates across the threads.
124 /** If an unhandled exception of the type derived from tbb::tbb_exception is intercepted
125     by the TBB scheduler in one of the worker threads, it is delivered to and re-thrown in
126     the root thread. The root thread is the thread that has started the outermost algorithm
127     or root task sharing the same task_group_context with the guilty algorithm/task (the one
128     that threw the exception first).
129
130     Note: when documentation mentions workers with respect to exception handling,
131     masters are implied as well, because they are completely equivalent in this context.
132     Consequently a root thread can be master or worker thread.
133
134     NOTE: In case of nested algorithms or complex task hierarchies when the nested
135     levels share (explicitly or by means of implicit inheritance) the task group
136     context of the outermost level, the exception may be (re-)thrown multiple times
137     (ultimately - in each worker on each nesting level) before reaching the root
138     thread at the outermost level. IMPORTANT: if you intercept an exception derived
139     from this class on a nested level, you must re-throw it in the catch block by means
140     of the "throw;" operator.
141
142     TBB provides two implementations of this interface: tbb::captured_exception and
143     template class tbb::movable_exception. See their declarations for more info. **/
144 class tbb_exception : public std::exception
145 {
146     /** No operator new is provided because the TBB usage model assumes dynamic
147         creation of the TBB exception objects only by means of applying move()
148         operation on an exception thrown out of TBB scheduler. **/
149     void* operator new ( size_t );
150
151 public:
152     //! Creates and returns pointer to the deep copy of this exception object.
153     /** Move semantics is allowed. **/
154     virtual tbb_exception* move () throw() = 0;
155
156     //! Destroys objects created by the move() method.
157     /** Frees memory and calls destructor for this exception object.
158         Can and must be used only on objects created by the move method. **/
159     virtual void destroy () throw() = 0;
160
161     //! Throws this exception object.
162     /** Make sure that if you have several levels of derivation from this interface
163         you implement or override this method on the most derived level. The implementation
164         is as simple as "throw *this;". Failure to do this will result in exception
165         of a base class type being thrown. **/
166     virtual void throw_self () = 0;
167
168     //! Returns RTTI name of the originally intercepted exception
169     virtual const char* name() const throw() = 0;
170
171     //! Returns the result of originally intercepted exception's what() method.
172     virtual const char* what() const throw() = 0;
173
174     /** Operator delete is provided only to allow using existing smart pointers
175         with TBB exception objects obtained as the result of applying move()
176         operation on an exception thrown out of TBB scheduler.
177
178         When overriding method move() make sure to override operator delete as well
179         if memory is allocated not by TBB's scalable allocator. **/
180     void operator delete ( void* p ) {
181         internal::deallocate_via_handler_v3(p);
182     }
183 };
184
185 //! This class is used by TBB to propagate information about unhandled exceptions into the root thread.
186 /** Exception of this type is thrown by TBB in the root thread (thread that started a parallel
187     algorithm ) if an unhandled exception was intercepted during the algorithm execution in one
188     of the workers.
189     \sa tbb::tbb_exception **/
190 class captured_exception : public tbb_exception
191 {
192 public:
193     captured_exception ( const captured_exception& src )
194         : tbb_exception(src), my_dynamic(false)
195     {
196         set(src.my_exception_name, src.my_exception_info);
197     }
198
199     captured_exception ( const char* name_, const char* info )
200         : my_dynamic(false)
201     {
202         set(name_, info);
203     }
204
205     __TBB_EXPORTED_METHOD ~captured_exception () throw();
206
207     captured_exception& operator= ( const captured_exception& src ) {
208         if ( this != &src ) {
209             clear();
210             set(src.my_exception_name, src.my_exception_info);
211         }
212         return *this;
213     }
214
215     /*override*/
216     captured_exception* __TBB_EXPORTED_METHOD move () throw();
217
218     /*override*/
219     void __TBB_EXPORTED_METHOD destroy () throw();
220
221     /*override*/
222     void throw_self () { __TBB_THROW(*this); }
223
224     /*override*/
225     const char* __TBB_EXPORTED_METHOD name() const throw();
226
227     /*override*/
228     const char* __TBB_EXPORTED_METHOD what() const throw();
229
230     void __TBB_EXPORTED_METHOD set ( const char* name, const char* info ) throw();
231     void __TBB_EXPORTED_METHOD clear () throw();
232
233 private:
234     //! Used only by method clone().
235     captured_exception() {}
236
237     //! Functionally equivalent to {captured_exception e(name,info); return e.clone();}
238     static captured_exception* allocate ( const char* name, const char* info );
239
240     bool my_dynamic;
241     const char* my_exception_name;
242     const char* my_exception_info;
243 };
244
245 //! Template that can be used to implement exception that transfers arbitrary ExceptionData to the root thread
246 /** Code using TBB can instantiate this template with an arbitrary ExceptionData type
247     and throw this exception object. Such exceptions are intercepted by the TBB scheduler
248     and delivered to the root thread ().
249     \sa tbb::tbb_exception **/
250 template<typename ExceptionData>
251 class movable_exception : public tbb_exception
252 {
253     typedef movable_exception<ExceptionData> self_type;
254
255 public:
256     movable_exception ( const ExceptionData& data_ )
257         : my_exception_data(data_)
258         , my_dynamic(false)
259         , my_exception_name(
260 #if TBB_USE_EXCEPTIONS
261         typeid(self_type).name()
262 #else /* !TBB_USE_EXCEPTIONS */
263         "movable_exception"
264 #endif /* !TBB_USE_EXCEPTIONS */
265         )
266     {}
267
268     movable_exception ( const movable_exception& src ) throw ()
269         : tbb_exception(src)
270         , my_exception_data(src.my_exception_data)
271         , my_dynamic(false)
272         , my_exception_name(src.my_exception_name)
273     {}
274
275     ~movable_exception () throw() {}
276
277     const movable_exception& operator= ( const movable_exception& src ) {
278         if ( this != &src ) {
279             my_exception_data = src.my_exception_data;
280             my_exception_name = src.my_exception_name;
281         }
282         return *this;
283     }
284
285     ExceptionData& data () throw() { return my_exception_data; }
286
287     const ExceptionData& data () const throw() { return my_exception_data; }
288
289     /*override*/ const char* name () const throw() { return my_exception_name; }
290
291     /*override*/ const char* what () const throw() { return "tbb::movable_exception"; }
292
293     /*override*/
294     movable_exception* move () throw() {
295         void* e = internal::allocate_via_handler_v3(sizeof(movable_exception));
296         if ( e ) {
297             ::new (e) movable_exception(*this);
298             ((movable_exception*)e)->my_dynamic = true;
299         }
300         return (movable_exception*)e;
301     }
302     /*override*/
303     void destroy () throw() {
304         __TBB_ASSERT ( my_dynamic, "Method destroy can be called only on dynamically allocated movable_exceptions" );
305         if ( my_dynamic ) {
306             this->~movable_exception();
307             internal::deallocate_via_handler_v3(this);
308         }
309     }
310     /*override*/
311     void throw_self () { __TBB_THROW( *this ); }
312
313 protected:
314     //! User data
315     ExceptionData  my_exception_data;
316
317 private:
318     //! Flag specifying whether this object has been dynamically allocated (by the move method)
319     bool my_dynamic;
320
321     //! RTTI name of this class
322     /** We rely on the fact that RTTI names are static string constants. **/
323     const char* my_exception_name;
324 };
325
326 #if !TBB_USE_CAPTURED_EXCEPTION
327 namespace internal {
328
329 //! Exception container that preserves the exact copy of the original exception
330 /** This class can be used only when the appropriate runtime support (mandated
331     by C++0x) is present **/
332 class tbb_exception_ptr {
333     std::exception_ptr  my_ptr;
334
335 public:
336     static tbb_exception_ptr* allocate ();
337     static tbb_exception_ptr* allocate ( const tbb_exception& tag );
338     //! This overload uses move semantics (i.e. it empties src)
339     static tbb_exception_ptr* allocate ( captured_exception& src );
340
341     //! Destroys this objects
342     /** Note that objects of this type can be created only by the allocate() method. **/
343     void destroy () throw();
344
345     //! Throws the contained exception .
346     void throw_self () { std::rethrow_exception(my_ptr); }
347
348 private:
349     tbb_exception_ptr ( const std::exception_ptr& src ) : my_ptr(src) {}
350     tbb_exception_ptr ( const captured_exception& src ) : my_ptr(std::copy_exception(src)) {}
351 }; // class tbb::internal::tbb_exception_ptr
352
353 } // namespace internal
354 #endif /* !TBB_USE_CAPTURED_EXCEPTION */
355
356 } // namespace tbb
357
358 #endif /* __TBB_TASK_GROUP_CONTEXT */
359
360 #endif /* __TBB_exception_H */