Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:13:00

0001 /*
0002     Copyright (c) 2005-2020 Intel Corporation
0003 
0004     Licensed under the Apache License, Version 2.0 (the "License");
0005     you may not use this file except in compliance with the License.
0006     You may obtain a copy of the License at
0007 
0008         http://www.apache.org/licenses/LICENSE-2.0
0009 
0010     Unless required by applicable law or agreed to in writing, software
0011     distributed under the License is distributed on an "AS IS" BASIS,
0012     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013     See the License for the specific language governing permissions and
0014     limitations under the License.
0015 */
0016 
0017 #ifndef __TBB_exception_H
0018 #define __TBB_exception_H
0019 
0020 #define __TBB_tbb_exception_H_include_area
0021 #include "internal/_warning_suppress_enable_notice.h"
0022 
0023 #include "tbb_stddef.h"
0024 #include <exception>
0025 #include <new>    // required for bad_alloc definition, operators new
0026 #include <string> // required to construct std exception classes
0027 
0028 namespace tbb {
0029 
0030 //! Exception for concurrent containers
0031 class bad_last_alloc : public std::bad_alloc {
0032 public:
0033     const char* what() const throw() __TBB_override;
0034 #if __TBB_DEFAULT_DTOR_THROW_SPEC_BROKEN
0035     ~bad_last_alloc() throw() __TBB_override {}
0036 #endif
0037 };
0038 
0039 //! Exception for PPL locks
0040 class __TBB_DEPRECATED improper_lock : public std::exception {
0041 public:
0042     const char* what() const throw() __TBB_override;
0043 };
0044 
0045 //! Exception for user-initiated abort
0046 class user_abort : public std::exception {
0047 public:
0048     const char* what() const throw() __TBB_override;
0049 };
0050 
0051 //! Exception for missing wait on structured_task_group
0052 class missing_wait : public std::exception {
0053 public:
0054     const char* what() const throw() __TBB_override;
0055 };
0056 
0057 //! Exception for repeated scheduling of the same task_handle
0058 class invalid_multiple_scheduling : public std::exception {
0059 public:
0060     const char* what() const throw() __TBB_override;
0061 };
0062 
0063 namespace internal {
0064 //! Obsolete
0065 void __TBB_EXPORTED_FUNC throw_bad_last_alloc_exception_v4();
0066 
0067 enum exception_id {
0068     eid_bad_alloc = 1,
0069     eid_bad_last_alloc,
0070     eid_nonpositive_step,
0071     eid_out_of_range,
0072     eid_segment_range_error,
0073     eid_index_range_error,
0074     eid_missing_wait,
0075     eid_invalid_multiple_scheduling,
0076     eid_improper_lock,
0077     eid_possible_deadlock,
0078     eid_operation_not_permitted,
0079     eid_condvar_wait_failed,
0080     eid_invalid_load_factor,
0081     eid_reserved, // free slot for backward compatibility, can be reused.
0082     eid_invalid_swap,
0083     eid_reservation_length_error,
0084     eid_invalid_key,
0085     eid_user_abort,
0086     eid_reserved1,
0087 #if __TBB_SUPPORTS_WORKERS_WAITING_IN_TERMINATE
0088     // This id is used only from inside the library and only for support of CPF functionality.
0089     // So, if we drop the functionality, eid_reserved1 can be safely renamed and reused.
0090     eid_blocking_thread_join_impossible = eid_reserved1,
0091 #endif
0092     eid_bad_tagged_msg_cast,
0093     //! The last enumerator tracks the number of defined IDs. It must remain the last one.
0094     /** When adding new IDs, place them immediately _before_ this comment (that is
0095         _after_ all the existing IDs. NEVER insert new IDs between the existing ones. **/
0096     eid_max
0097 };
0098 
0099 //! Gathers all throw operators in one place.
0100 /** Its purpose is to minimize code bloat that can be caused by throw operators
0101     scattered in multiple places, especially in templates. **/
0102 void __TBB_EXPORTED_FUNC throw_exception_v4 ( exception_id );
0103 
0104 //! Versionless convenience wrapper for throw_exception_v4()
0105 inline void throw_exception ( exception_id eid ) { throw_exception_v4(eid); }
0106 
0107 } // namespace internal
0108 } // namespace tbb
0109 
0110 #if __TBB_TASK_GROUP_CONTEXT
0111 #include "tbb_allocator.h"
0112 #include <typeinfo> //for typeid
0113 
0114 namespace tbb {
0115 
0116 //! Interface to be implemented by all exceptions TBB recognizes and propagates across the threads.
0117 /** If an unhandled exception of the type derived from tbb::tbb_exception is intercepted
0118     by the TBB scheduler in one of the worker threads, it is delivered to and re-thrown in
0119     the root thread. The root thread is the thread that has started the outermost algorithm
0120     or root task sharing the same task_group_context with the guilty algorithm/task (the one
0121     that threw the exception first).
0122 
0123     Note: when documentation mentions workers with respect to exception handling,
0124     masters are implied as well, because they are completely equivalent in this context.
0125     Consequently a root thread can be master or worker thread.
0126 
0127     NOTE: In case of nested algorithms or complex task hierarchies when the nested
0128     levels share (explicitly or by means of implicit inheritance) the task group
0129     context of the outermost level, the exception may be (re-)thrown multiple times
0130     (ultimately - in each worker on each nesting level) before reaching the root
0131     thread at the outermost level. IMPORTANT: if you intercept an exception derived
0132     from this class on a nested level, you must re-throw it in the catch block by means
0133     of the "throw;" operator.
0134 
0135     TBB provides two implementations of this interface: tbb::captured_exception and
0136     template class tbb::movable_exception. See their declarations for more info. **/
0137 class __TBB_DEPRECATED tbb_exception : public std::exception
0138 {
0139     /** No operator new is provided because the TBB usage model assumes dynamic
0140         creation of the TBB exception objects only by means of applying move()
0141         operation on an exception thrown out of TBB scheduler. **/
0142     void* operator new ( size_t );
0143 
0144 public:
0145 #if __clang__
0146     // At -O3 or even -O2 optimization level, Clang may fully throw away an empty destructor
0147     // of tbb_exception from destructors of derived classes. As a result, it does not create
0148     // vtable for tbb_exception, which is a required part of TBB binary interface.
0149     // Making the destructor non-empty (with just a semicolon) prevents that optimization.
0150     ~tbb_exception() throw() { /* keep the semicolon! */ ; }
0151 #endif
0152 
0153     //! Creates and returns pointer to the deep copy of this exception object.
0154     /** Move semantics is allowed. **/
0155     virtual tbb_exception* move() throw() = 0;
0156 
0157     //! Destroys objects created by the move() method.
0158     /** Frees memory and calls destructor for this exception object.
0159         Can and must be used only on objects created by the move method. **/
0160     virtual void destroy() throw() = 0;
0161 
0162     //! Throws this exception object.
0163     /** Make sure that if you have several levels of derivation from this interface
0164         you implement or override this method on the most derived level. The implementation
0165         is as simple as "throw *this;". Failure to do this will result in exception
0166         of a base class type being thrown. **/
0167     virtual void throw_self() = 0;
0168 
0169     //! Returns RTTI name of the originally intercepted exception
0170     virtual const char* name() const throw() = 0;
0171 
0172     //! Returns the result of originally intercepted exception's what() method.
0173     virtual const char* what() const throw() __TBB_override = 0;
0174 
0175     /** Operator delete is provided only to allow using existing smart pointers
0176         with TBB exception objects obtained as the result of applying move()
0177         operation on an exception thrown out of TBB scheduler.
0178 
0179         When overriding method move() make sure to override operator delete as well
0180         if memory is allocated not by TBB's scalable allocator. **/
0181     void operator delete ( void* p ) {
0182         internal::deallocate_via_handler_v3(p);
0183     }
0184 };
0185 
0186 //! This class is used by TBB to propagate information about unhandled exceptions into the root thread.
0187 /** Exception of this type is thrown by TBB in the root thread (thread that started a parallel
0188     algorithm ) if an unhandled exception was intercepted during the algorithm execution in one
0189     of the workers.
0190     \sa tbb::tbb_exception **/
0191 class __TBB_DEPRECATED_IN_VERBOSE_MODE captured_exception : public tbb_exception
0192 {
0193 public:
0194     captured_exception( const captured_exception& src )
0195         : tbb_exception(src), my_dynamic(false)
0196     {
0197         set(src.my_exception_name, src.my_exception_info);
0198     }
0199 
0200     captured_exception( const char* name_, const char* info )
0201         : my_dynamic(false)
0202     {
0203         set(name_, info);
0204     }
0205 
0206     __TBB_EXPORTED_METHOD ~captured_exception() throw();
0207 
0208     captured_exception& operator= ( const captured_exception& src ) {
0209         if ( this != &src ) {
0210             clear();
0211             set(src.my_exception_name, src.my_exception_info);
0212         }
0213         return *this;
0214     }
0215 
0216     captured_exception* __TBB_EXPORTED_METHOD move() throw() __TBB_override;
0217 
0218     void __TBB_EXPORTED_METHOD destroy() throw() __TBB_override;
0219 
0220     void throw_self() __TBB_override { __TBB_THROW(*this); }
0221 
0222     const char* __TBB_EXPORTED_METHOD name() const throw() __TBB_override;
0223 
0224     const char* __TBB_EXPORTED_METHOD what() const throw() __TBB_override;
0225 
0226     void __TBB_EXPORTED_METHOD set( const char* name, const char* info ) throw();
0227     void __TBB_EXPORTED_METHOD clear() throw();
0228 
0229 private:
0230     //! Used only by method move().
0231     captured_exception() : my_dynamic(), my_exception_name(), my_exception_info() {}
0232 
0233     //! Functionally equivalent to {captured_exception e(name,info); return e.move();}
0234     static captured_exception* allocate( const char* name, const char* info );
0235 
0236     bool my_dynamic;
0237     const char* my_exception_name;
0238     const char* my_exception_info;
0239 };
0240 
0241 //! Template that can be used to implement exception that transfers arbitrary ExceptionData to the root thread
0242 /** Code using TBB can instantiate this template with an arbitrary ExceptionData type
0243     and throw this exception object. Such exceptions are intercepted by the TBB scheduler
0244     and delivered to the root thread ().
0245     \sa tbb::tbb_exception **/
0246 template<typename ExceptionData>
0247 class __TBB_DEPRECATED movable_exception : public tbb_exception
0248 {
0249     typedef movable_exception<ExceptionData> self_type;
0250 
0251 public:
0252     movable_exception( const ExceptionData& data_ )
0253         : my_exception_data(data_)
0254         , my_dynamic(false)
0255         , my_exception_name(
0256 #if TBB_USE_EXCEPTIONS
0257         typeid(self_type).name()
0258 #else /* !TBB_USE_EXCEPTIONS */
0259         "movable_exception"
0260 #endif /* !TBB_USE_EXCEPTIONS */
0261         )
0262     {}
0263 
0264     movable_exception( const movable_exception& src ) throw ()
0265         : tbb_exception(src)
0266         , my_exception_data(src.my_exception_data)
0267         , my_dynamic(false)
0268         , my_exception_name(src.my_exception_name)
0269     {}
0270 
0271     ~movable_exception() throw() {}
0272 
0273     const movable_exception& operator= ( const movable_exception& src ) {
0274         if ( this != &src ) {
0275             my_exception_data = src.my_exception_data;
0276             my_exception_name = src.my_exception_name;
0277         }
0278         return *this;
0279     }
0280 
0281     ExceptionData& data() throw() { return my_exception_data; }
0282 
0283     const ExceptionData& data() const throw() { return my_exception_data; }
0284 
0285     const char* name() const throw() __TBB_override { return my_exception_name; }
0286 
0287     const char* what() const throw() __TBB_override { return "tbb::movable_exception"; }
0288 
0289     movable_exception* move() throw() __TBB_override {
0290         void* e = internal::allocate_via_handler_v3(sizeof(movable_exception));
0291         if ( e ) {
0292             ::new (e) movable_exception(*this);
0293             ((movable_exception*)e)->my_dynamic = true;
0294         }
0295         return (movable_exception*)e;
0296     }
0297     void destroy() throw() __TBB_override {
0298         __TBB_ASSERT ( my_dynamic, "Method destroy can be called only on dynamically allocated movable_exceptions" );
0299         if ( my_dynamic ) {
0300             this->~movable_exception();
0301             internal::deallocate_via_handler_v3(this);
0302         }
0303     }
0304     void throw_self() __TBB_override { __TBB_THROW( *this ); }
0305 
0306 protected:
0307     //! User data
0308     ExceptionData  my_exception_data;
0309 
0310 private:
0311     //! Flag specifying whether this object has been dynamically allocated (by the move method)
0312     bool my_dynamic;
0313 
0314     //! RTTI name of this class
0315     /** We rely on the fact that RTTI names are static string constants. **/
0316     const char* my_exception_name;
0317 };
0318 
0319 #if !TBB_USE_CAPTURED_EXCEPTION
0320 namespace internal {
0321 
0322 //! Exception container that preserves the exact copy of the original exception
0323 /** This class can be used only when the appropriate runtime support (mandated
0324     by C++11) is present **/
0325 class tbb_exception_ptr {
0326     std::exception_ptr  my_ptr;
0327 
0328 public:
0329     static tbb_exception_ptr* allocate();
0330     static tbb_exception_ptr* allocate( const tbb_exception& tag );
0331     //! This overload uses move semantics (i.e. it empties src)
0332     static tbb_exception_ptr* allocate( captured_exception& src );
0333 
0334     //! Destroys this objects
0335     /** Note that objects of this type can be created only by the allocate() method. **/
0336     void destroy() throw();
0337 
0338     //! Throws the contained exception .
0339     void throw_self() { std::rethrow_exception(my_ptr); }
0340 
0341 private:
0342     tbb_exception_ptr( const std::exception_ptr& src ) : my_ptr(src) {}
0343     tbb_exception_ptr( const captured_exception& src ) :
0344         #if __TBB_MAKE_EXCEPTION_PTR_PRESENT
0345             my_ptr(std::make_exception_ptr(src))  // the final function name in C++11
0346         #else
0347             my_ptr(std::copy_exception(src))      // early C++0x drafts name
0348         #endif
0349     {}
0350 }; // class tbb::internal::tbb_exception_ptr
0351 
0352 } // namespace internal
0353 #endif /* !TBB_USE_CAPTURED_EXCEPTION */
0354 
0355 } // namespace tbb
0356 
0357 #endif /* __TBB_TASK_GROUP_CONTEXT */
0358 
0359 #include "internal/_warning_suppress_disable_notice.h"
0360 #undef __TBB_tbb_exception_H_include_area
0361 
0362 #endif /* __TBB_exception_H */