2 Copyright 2005-2010 Intel Corporation. All Rights Reserved.
4 This file is part of Threading Building Blocks.
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.
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.
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
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.
29 #ifndef __TBB_exception_H
30 #define __TBB_exception_H
32 #include "tbb_stddef.h"
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)
42 #if !TBB_USE_EXCEPTIONS && _MSC_VER
47 #include <string> // required to construct std exception classes
52 //! Exception for concurrent containers
53 class bad_last_alloc : public std::bad_alloc {
55 /*override*/ const char* what() const throw();
56 #if __TBB_DEFAULT_DTOR_THROW_SPEC_BROKEN
57 /*override*/ ~bad_last_alloc() throw() {}
61 //! Exception for PPL locks
62 class improper_lock : public std::exception {
64 /*override*/ const char* what() const throw();
67 //! Exception for missing wait on structured_task_group
68 class missing_wait : public std::exception {
70 /*override*/ const char* what() const throw();
73 //! Exception for repeated scheduling of the same task_handle
74 class invalid_multiple_scheduling : public std::exception {
76 /*override*/ const char* what() const throw();
81 void __TBB_EXPORTED_FUNC throw_bad_last_alloc_exception_v4();
88 eid_segment_range_error,
89 eid_index_range_error,
91 eid_invalid_multiple_scheduling,
93 eid_possible_deadlock,
94 eid_operation_not_permitted,
95 eid_condvar_wait_failed,
96 eid_invalid_load_factor,
97 eid_invalid_buckets_number,
99 eid_reservation_length_error,
101 //! The last enumerator tracks the number of defined IDs. It must remain the last one.
102 /** When adding new IDs, place them immediately _before_ this comment (that is
103 _after_ all the existing IDs. NEVER insert new IDs between the existing ones. **/
107 //! Gathers all throw operators in one place.
108 /** Its purpose is to minimize code bloat that can be caused by throw operators
109 scattered in multiple places, especially in templates. **/
110 void __TBB_EXPORTED_FUNC throw_exception_v4 ( exception_id );
112 //! Versionless convenience wrapper for throw_exception_v4()
113 inline void throw_exception ( exception_id eid ) { throw_exception_v4(eid); }
115 } // namespace internal
118 #if __TBB_TASK_GROUP_CONTEXT
119 #include "tbb_allocator.h"
126 //! Interface to be implemented by all exceptions TBB recognizes and propagates across the threads.
127 /** If an unhandled exception of the type derived from tbb::tbb_exception is intercepted
128 by the TBB scheduler in one of the worker threads, it is delivered to and re-thrown in
129 the root thread. The root thread is the thread that has started the outermost algorithm
130 or root task sharing the same task_group_context with the guilty algorithm/task (the one
131 that threw the exception first).
133 Note: when documentation mentions workers with respect to exception handling,
134 masters are implied as well, because they are completely equivalent in this context.
135 Consequently a root thread can be master or worker thread.
137 NOTE: In case of nested algorithms or complex task hierarchies when the nested
138 levels share (explicitly or by means of implicit inheritance) the task group
139 context of the outermost level, the exception may be (re-)thrown multiple times
140 (ultimately - in each worker on each nesting level) before reaching the root
141 thread at the outermost level. IMPORTANT: if you intercept an exception derived
142 from this class on a nested level, you must re-throw it in the catch block by means
143 of the "throw;" operator.
145 TBB provides two implementations of this interface: tbb::captured_exception and
146 template class tbb::movable_exception. See their declarations for more info. **/
147 class tbb_exception : public std::exception
149 /** No operator new is provided because the TBB usage model assumes dynamic
150 creation of the TBB exception objects only by means of applying move()
151 operation on an exception thrown out of TBB scheduler. **/
152 void* operator new ( size_t );
155 //! Creates and returns pointer to the deep copy of this exception object.
156 /** Move semantics is allowed. **/
157 virtual tbb_exception* move () throw() = 0;
159 //! Destroys objects created by the move() method.
160 /** Frees memory and calls destructor for this exception object.
161 Can and must be used only on objects created by the move method. **/
162 virtual void destroy () throw() = 0;
164 //! Throws this exception object.
165 /** Make sure that if you have several levels of derivation from this interface
166 you implement or override this method on the most derived level. The implementation
167 is as simple as "throw *this;". Failure to do this will result in exception
168 of a base class type being thrown. **/
169 virtual void throw_self () = 0;
171 //! Returns RTTI name of the originally intercepted exception
172 virtual const char* name() const throw() = 0;
174 //! Returns the result of originally intercepted exception's what() method.
175 virtual const char* what() const throw() = 0;
177 /** Operator delete is provided only to allow using existing smart pointers
178 with TBB exception objects obtained as the result of applying move()
179 operation on an exception thrown out of TBB scheduler.
181 When overriding method move() make sure to override operator delete as well
182 if memory is allocated not by TBB's scalable allocator. **/
183 void operator delete ( void* p ) {
184 internal::deallocate_via_handler_v3(p);
188 //! This class is used by TBB to propagate information about unhandled exceptions into the root thread.
189 /** Exception of this type is thrown by TBB in the root thread (thread that started a parallel
190 algorithm ) if an unhandled exception was intercepted during the algorithm execution in one
192 \sa tbb::tbb_exception **/
193 class captured_exception : public tbb_exception
196 captured_exception ( const captured_exception& src )
197 : tbb_exception(src), my_dynamic(false)
199 set(src.my_exception_name, src.my_exception_info);
202 captured_exception ( const char* name_, const char* info )
208 __TBB_EXPORTED_METHOD ~captured_exception () throw() {
212 captured_exception& operator= ( const captured_exception& src ) {
213 if ( this != &src ) {
215 set(src.my_exception_name, src.my_exception_info);
221 captured_exception* __TBB_EXPORTED_METHOD move () throw();
224 void __TBB_EXPORTED_METHOD destroy () throw();
227 void throw_self () { __TBB_THROW(*this); }
230 const char* __TBB_EXPORTED_METHOD name() const throw();
233 const char* __TBB_EXPORTED_METHOD what() const throw();
235 void __TBB_EXPORTED_METHOD set ( const char* name, const char* info ) throw();
236 void __TBB_EXPORTED_METHOD clear () throw();
239 //! Used only by method clone().
240 captured_exception() {}
242 //! Functionally equivalent to {captured_exception e(name,info); return e.clone();}
243 static captured_exception* allocate ( const char* name, const char* info );
246 const char* my_exception_name;
247 const char* my_exception_info;
250 //! Template that can be used to implement exception that transfers arbitrary ExceptionData to the root thread
251 /** Code using TBB can instantiate this template with an arbitrary ExceptionData type
252 and throw this exception object. Such exceptions are intercepted by the TBB scheduler
253 and delivered to the root thread ().
254 \sa tbb::tbb_exception **/
255 template<typename ExceptionData>
256 class movable_exception : public tbb_exception
258 typedef movable_exception<ExceptionData> self_type;
261 movable_exception ( const ExceptionData& data_ )
262 : my_exception_data(data_)
265 #if TBB_USE_EXCEPTIONS
266 typeid(self_type).name()
267 #else /* !TBB_USE_EXCEPTIONS */
269 #endif /* !TBB_USE_EXCEPTIONS */
273 movable_exception ( const movable_exception& src ) throw ()
275 , my_exception_data(src.my_exception_data)
277 , my_exception_name(src.my_exception_name)
280 ~movable_exception () throw() {}
282 const movable_exception& operator= ( const movable_exception& src ) {
283 if ( this != &src ) {
284 my_exception_data = src.my_exception_data;
285 my_exception_name = src.my_exception_name;
290 ExceptionData& data () throw() { return my_exception_data; }
292 const ExceptionData& data () const throw() { return my_exception_data; }
294 /*override*/ const char* name () const throw() { return my_exception_name; }
296 /*override*/ const char* what () const throw() { return "tbb::movable_exception"; }
299 movable_exception* move () throw() {
300 void* e = internal::allocate_via_handler_v3(sizeof(movable_exception));
302 ::new (e) movable_exception(*this);
303 ((movable_exception*)e)->my_dynamic = true;
305 return (movable_exception*)e;
308 void destroy () throw() {
309 __TBB_ASSERT ( my_dynamic, "Method destroy can be called only on dynamically allocated movable_exceptions" );
311 this->~movable_exception();
312 internal::deallocate_via_handler_v3(this);
316 void throw_self () { __TBB_THROW( *this ); }
320 ExceptionData my_exception_data;
323 //! Flag specifying whether this object has been dynamically allocated (by the move method)
326 //! RTTI name of this class
327 /** We rely on the fact that RTTI names are static string constants. **/
328 const char* my_exception_name;
331 #if !TBB_USE_CAPTURED_EXCEPTION
334 //! Exception container that preserves the exact copy of the original exception
335 /** This class can be used only when the appropriate runtime support (mandated
336 by C++0x) is present **/
337 class tbb_exception_ptr {
338 std::exception_ptr my_ptr;
341 static tbb_exception_ptr* allocate ();
342 static tbb_exception_ptr* allocate ( const tbb_exception& tag );
343 //! This overload uses move semantics (i.e. it empties src)
344 static tbb_exception_ptr* allocate ( captured_exception& src );
346 //! Destroys this objects
347 /** Note that objects of this type can be created only by the allocate() method. **/
348 void destroy () throw();
350 //! Throws the contained exception .
351 void throw_self () { std::rethrow_exception(my_ptr); }
354 tbb_exception_ptr ( const std::exception_ptr& src ) : my_ptr(src) {}
355 tbb_exception_ptr ( const captured_exception& src ) : my_ptr(std::copy_exception(src)) {}
356 }; // class tbb::internal::tbb_exception_ptr
358 } // namespace internal
359 #endif /* !TBB_USE_CAPTURED_EXCEPTION */
363 #endif /* __TBB_TASK_GROUP_CONTEXT */
365 #endif /* __TBB_exception_H */