2 Copyright 2005-2011 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)
41 #include <string> // required to construct std exception classes
43 #if !TBB_USE_EXCEPTIONS && _MSC_VER
49 //! Exception for concurrent containers
50 class bad_last_alloc : public std::bad_alloc {
52 /*override*/ const char* what() const throw();
53 #if __TBB_DEFAULT_DTOR_THROW_SPEC_BROKEN
54 /*override*/ ~bad_last_alloc() throw() {}
58 //! Exception for PPL locks
59 class improper_lock : public std::exception {
61 /*override*/ const char* what() const throw();
64 //! Exception for missing wait on structured_task_group
65 class missing_wait : public std::exception {
67 /*override*/ const char* what() const throw();
70 //! Exception for repeated scheduling of the same task_handle
71 class invalid_multiple_scheduling : public std::exception {
73 /*override*/ const char* what() const throw();
78 void __TBB_EXPORTED_FUNC throw_bad_last_alloc_exception_v4();
85 eid_segment_range_error,
86 eid_index_range_error,
88 eid_invalid_multiple_scheduling,
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.
96 eid_reservation_length_error,
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. **/
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 );
109 //! Versionless convenience wrapper for throw_exception_v4()
110 inline void throw_exception ( exception_id eid ) { throw_exception_v4(eid); }
112 } // namespace internal
115 #if __TBB_TASK_GROUP_CONTEXT
116 #include "tbb_allocator.h"
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).
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.
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.
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
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 );
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;
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;
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;
168 //! Returns RTTI name of the originally intercepted exception
169 virtual const char* name() const throw() = 0;
171 //! Returns the result of originally intercepted exception's what() method.
172 virtual const char* what() const throw() = 0;
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.
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);
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
189 \sa tbb::tbb_exception **/
190 class captured_exception : public tbb_exception
193 captured_exception ( const captured_exception& src )
194 : tbb_exception(src), my_dynamic(false)
196 set(src.my_exception_name, src.my_exception_info);
199 captured_exception ( const char* name_, const char* info )
205 __TBB_EXPORTED_METHOD ~captured_exception () throw();
207 captured_exception& operator= ( const captured_exception& src ) {
208 if ( this != &src ) {
210 set(src.my_exception_name, src.my_exception_info);
216 captured_exception* __TBB_EXPORTED_METHOD move () throw();
219 void __TBB_EXPORTED_METHOD destroy () throw();
222 void throw_self () { __TBB_THROW(*this); }
225 const char* __TBB_EXPORTED_METHOD name() const throw();
228 const char* __TBB_EXPORTED_METHOD what() const throw();
230 void __TBB_EXPORTED_METHOD set ( const char* name, const char* info ) throw();
231 void __TBB_EXPORTED_METHOD clear () throw();
234 //! Used only by method clone().
235 captured_exception() {}
237 //! Functionally equivalent to {captured_exception e(name,info); return e.clone();}
238 static captured_exception* allocate ( const char* name, const char* info );
241 const char* my_exception_name;
242 const char* my_exception_info;
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
253 typedef movable_exception<ExceptionData> self_type;
256 movable_exception ( const ExceptionData& data_ )
257 : my_exception_data(data_)
260 #if TBB_USE_EXCEPTIONS
261 typeid(self_type).name()
262 #else /* !TBB_USE_EXCEPTIONS */
264 #endif /* !TBB_USE_EXCEPTIONS */
268 movable_exception ( const movable_exception& src ) throw ()
270 , my_exception_data(src.my_exception_data)
272 , my_exception_name(src.my_exception_name)
275 ~movable_exception () throw() {}
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;
285 ExceptionData& data () throw() { return my_exception_data; }
287 const ExceptionData& data () const throw() { return my_exception_data; }
289 /*override*/ const char* name () const throw() { return my_exception_name; }
291 /*override*/ const char* what () const throw() { return "tbb::movable_exception"; }
294 movable_exception* move () throw() {
295 void* e = internal::allocate_via_handler_v3(sizeof(movable_exception));
297 ::new (e) movable_exception(*this);
298 ((movable_exception*)e)->my_dynamic = true;
300 return (movable_exception*)e;
303 void destroy () throw() {
304 __TBB_ASSERT ( my_dynamic, "Method destroy can be called only on dynamically allocated movable_exceptions" );
306 this->~movable_exception();
307 internal::deallocate_via_handler_v3(this);
311 void throw_self () { __TBB_THROW( *this ); }
315 ExceptionData my_exception_data;
318 //! Flag specifying whether this object has been dynamically allocated (by the move method)
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;
326 #if !TBB_USE_CAPTURED_EXCEPTION
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;
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 );
341 //! Destroys this objects
342 /** Note that objects of this type can be created only by the allocate() method. **/
343 void destroy () throw();
345 //! Throws the contained exception .
346 void throw_self () { std::rethrow_exception(my_ptr); }
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
353 } // namespace internal
354 #endif /* !TBB_USE_CAPTURED_EXCEPTION */
358 #endif /* __TBB_TASK_GROUP_CONTEXT */
360 #endif /* __TBB_exception_H */