|
Sierra Toolkit
Version of the Day
|
00001 /*--------------------------------------------------------------------*/ 00002 /* Copyright 2003 - 2008 Sandia Corporation. */ 00003 /* Under the terms of Contract DE-AC04-94AL85000, there is a */ 00004 /* non-exclusive license for use of this work by or on behalf */ 00005 /* of the U.S. Government. Export of this program may require */ 00006 /* a license from the United States Government. */ 00007 /*--------------------------------------------------------------------*/ 00008 00009 #ifndef STK_UTIL_PARALLEL_Exception_hpp 00010 #define STK_UTIL_PARALLEL_Exception_hpp 00011 00012 /*--------------------------------------------------------------------*/ 00063 #include <stdexcept> 00064 #include <exception> 00065 #include <new> 00066 #include <typeinfo> 00067 #include <string> 00068 #include <vector> 00069 // #include <iostream> // for std::cerr 00070 #include <sstream> 00071 00072 #include <stk_util/stk_config.h> 00073 #if defined( STK_HAS_MPI ) 00074 #include <mpi.h> 00075 #endif 00076 00077 #include <stk_util/environment/ReportHandler.hpp> 00078 00079 #include <stk_util/util/FeatureTest.hpp> 00080 #include <stk_util/diag/String.hpp> 00081 #include <stk_util/diag/StringUtil.hpp> 00082 #include <stk_util/diag/Trace.hpp> 00083 00084 namespace sierra { 00085 00090 00091 class ExParallel; 00092 00098 void register_stl_parallel_exceptions(); 00099 00106 void set_exception(); 00107 00115 void set_exception(std::exception &x); 00116 00125 void set_exception(ExParallel &x); 00126 00133 void sierra_exception_throw(); 00134 00151 void throw_copy(const std::exception &x, const std::string &message); 00152 00162 void parallel_throw(MPI_Comm mpi_comm); 00163 00164 00182 class ParallelThrowRegistry 00183 { 00184 public: 00191 static ParallelThrowRegistry &instance(); 00192 00200 static bool areExceptionsRegistered() { 00201 return !ParallelThrowRegistry::instance().m_registry.empty(); 00202 } 00203 00213 template<class T> 00214 ExParallel ®isterException() { 00215 T *x = new T(); 00216 register_exception_a(typeid(T), x); 00217 register_exception_a(typeid(typename T::BaseExceptionType), x); 00218 return *x; 00219 } 00220 00230 ExParallel *findException(const std::type_info &exception_type); 00231 00232 private: 00244 ExParallel ®ister_exception_a(const std::type_info ¶llel_exception_type, ExParallel *exception); 00245 00246 private: 00252 class Registry : public std::vector<std::pair<const std::type_info *, ExParallel *> > 00253 { 00254 public: 00255 Registry(); 00256 00257 ~Registry(); 00258 }; 00259 00260 Registry m_registry; 00261 }; 00262 00263 00271 class ExParallel 00272 { 00273 protected: 00279 ExParallel() 00280 : m_descriptionStream(), 00281 m_whatBuffer(), 00282 m_traceback(Diag::Trace::printTraceback(Diag::Trace::Traceback::snapshot())), 00283 m_parallel(-1) 00284 { 00285 if (ParallelThrowRegistry::areExceptionsRegistered()) 00286 sierra_exception_throw(); 00287 } 00288 00299 explicit ExParallel(const std::string & message, int parallel = -1) 00300 : m_descriptionStream(), 00301 m_whatBuffer(), 00302 m_traceback(Diag::Trace::printTraceback(Diag::Trace::Traceback::snapshot())), 00303 m_parallel(parallel) 00304 { 00305 m_descriptionStream << message; 00306 if (ParallelThrowRegistry::areExceptionsRegistered()) 00307 sierra_exception_throw(); 00308 } 00309 00316 ExParallel(const ExParallel &x) 00317 : m_descriptionStream(), 00318 m_whatBuffer(), 00319 m_traceback(x.m_traceback), 00320 m_parallel(x.m_parallel) 00321 { 00322 m_descriptionStream << x.m_descriptionStream.str(); 00323 } 00324 00325 public: 00330 virtual ~ExParallel() 00331 {} 00332 00339 virtual const char *what() const throw() { 00340 try { 00341 m_whatBuffer = m_descriptionStream.str(); 00342 return m_whatBuffer.c_str(); 00343 } 00344 catch(...) { 00345 return NULL; 00346 } 00347 } 00348 00354 ExParallel &clear() { 00355 m_descriptionStream.str(""); 00356 m_traceback.clear(); 00357 m_parallel = -1; 00358 return *this; 00359 } 00360 00370 ExParallel &setDescription(const std::string &description) { 00371 clear(); 00372 m_descriptionStream << description; 00373 return *this; 00374 } 00375 00383 std::string getDescription() const{ 00384 return m_descriptionStream.str(); 00385 } 00386 00394 std::ostringstream &getDescriptionStream() { 00395 return m_descriptionStream; 00396 } 00397 00405 const std::ostringstream &getDescriptionStream() const { 00406 return m_descriptionStream; 00407 } 00408 00418 ExParallel &setTraceback(const std::string &traceback) { 00419 m_traceback = traceback; 00420 return *this; 00421 } 00422 00429 const std::string &getTraceback() const { 00430 return m_traceback; 00431 } 00432 00443 ExParallel &setParallel(int parallel) { 00444 m_parallel = parallel; 00445 return *this; 00446 } 00447 00455 int getParallel() const { 00456 return m_parallel; 00457 } 00458 00459 00467 bool isParallel() const { 00468 return m_parallel != -1; 00469 } 00470 00479 ExParallel &operator<<(std::ostream& (*f)(std::ostream&)) { 00480 f(m_descriptionStream); 00481 return *this; 00482 } 00483 00493 template<class U> 00494 ExParallel &operator<<(const U &t) { 00495 m_descriptionStream << t; 00496 return *this; 00497 } 00498 00509 virtual void throw_copy() const = 0; 00510 00518 virtual void parallel_handler(); 00519 00520 private: 00521 std::ostringstream m_descriptionStream; 00522 mutable std::string m_whatBuffer; 00523 std::string m_traceback; 00524 int m_parallel; 00525 }; 00526 00527 00535 template<class T> 00536 class ExTemp : public ExParallel, public T 00537 { 00538 public: 00539 typedef ExTemp<T> ParallelExceptionType; 00540 typedef T BaseExceptionType; 00541 00546 ExTemp() 00547 : ExParallel(), 00548 T() 00549 {} 00550 00557 explicit ExTemp(const std::string &message) 00558 : ExParallel(message), 00559 T() 00560 {} 00561 00567 ExTemp(const ExTemp & x) 00568 : ExParallel(static_cast<const ExParallel &>(x)), 00569 T(static_cast<const T &>(x)) 00570 {} 00571 00576 virtual ~ExTemp() throw() 00577 {} 00578 00585 virtual const char *what() const throw() { 00586 return ExParallel::what(); 00587 } 00588 00597 ExTemp &operator<<(std::ostream& (*f)(std::ostream&)) { 00598 f(getDescriptionStream()); 00599 return *this; 00600 } 00601 00611 template<class U> 00612 ExTemp &operator<<(const U &t) { 00613 getDescriptionStream() << t; 00614 return *this; 00615 } 00616 00623 virtual void throw_copy() const { 00624 ParallelExceptionType t(*this); 00625 00626 // std::cerr << "throwing " << this->what() << std::endl 00627 // << " as " << t.what(); 00628 throw t; 00629 } 00630 00638 static void registerException() { 00639 #ifdef SIERRA_TEMPLATE_CALL_BUG 00640 ParallelThrowRegistry::instance().template registerException<ExTemp>(); 00641 #else 00642 ParallelThrowRegistry::instance().registerException<ExTemp>(); 00643 #endif 00644 } 00645 }; 00646 00647 00648 template<class T> 00649 class ExTemp1 : public ExParallel, public T 00650 { 00651 public: 00652 typedef ExTemp1<T> ParallelExceptionType; 00653 typedef T BaseExceptionType; 00654 00659 ExTemp1() 00660 : ExParallel(), 00661 T(std::string()) 00662 {} 00663 00670 explicit ExTemp1(const std::string & message) 00671 : ExParallel(message), 00672 T(message) 00673 {} 00674 00680 ExTemp1(const ExTemp1 & x) 00681 : ExParallel(static_cast<const ExParallel &>(x)), 00682 T(static_cast<const T &>(x)) 00683 {} 00684 00689 virtual ~ExTemp1() throw() 00690 {} 00691 00698 virtual const char *what() const throw() { 00699 return ExParallel::what(); 00700 } 00701 00710 ExTemp1 &operator<<(std::ostream& (*f)(std::ostream&)) { 00711 f(getDescriptionStream()); 00712 return *this; 00713 } 00714 00715 00725 template<class U> 00726 ExTemp1 &operator<<(const U &t) { 00727 getDescriptionStream() << t; 00728 return *this; 00729 } 00730 00740 virtual void throw_copy() const { 00741 ParallelExceptionType t(*this); 00742 00743 // std::cerr << "throwing " << this->what() << std::endl 00744 // << " as " << t.what(); 00745 throw t; 00746 } 00747 00755 static ExParallel ®isterException() { 00756 #ifdef SIERRA_TEMPLATE_CALL_BUG 00757 return ParallelThrowRegistry::instance().template registerException<ExTemp1>(); 00758 #else 00759 return ParallelThrowRegistry::instance().registerException<ExTemp1>(); 00760 #endif 00761 } 00762 }; 00763 00764 typedef ExTemp<std::exception> Exception; 00765 typedef ExTemp<std::bad_exception> BadException; 00766 typedef ExTemp<std::bad_alloc> BadAlloc; 00767 typedef ExTemp<std::bad_typeid> BadTypeid; 00768 typedef ExTemp<std::bad_cast> BadCast; 00769 typedef ExTemp1<std::ios_base::failure> IosBaseFailure; 00770 typedef ExTemp1<std::logic_error> LogicError; 00771 typedef ExTemp1<std::domain_error> DomainError; 00772 typedef ExTemp1<std::invalid_argument> InvalidArgument; 00773 typedef ExTemp1<std::length_error> LengthError; 00774 typedef ExTemp1<std::out_of_range> OutOfRange; 00775 typedef ExTemp1<std::runtime_error> RuntimeError; 00776 typedef ExTemp1<std::range_error> RangeError; 00777 typedef ExTemp1<std::overflow_error> OverflowError; 00778 typedef ExTemp1<std::underflow_error> UnderflowError; 00779 00780 //---------------------------------------------------------------------- 00781 00786 class runtime_user_error : public std::runtime_error 00787 { 00788 public: 00789 explicit runtime_user_error(const std::string &message) throw() 00790 : std::runtime_error(message) 00791 {} 00792 00793 runtime_user_error(const runtime_user_error &x) throw() 00794 : std::runtime_error(x) 00795 {} 00796 00797 virtual ~runtime_user_error() throw () 00798 {} 00799 }; 00800 00801 typedef ExTemp1<runtime_user_error> RuntimeUserError; 00802 00806 00807 } // namepace sierra 00808 00809 // DO NOT USE ParallelStackTrace, unless you know that the exception will be thrown in 00810 // parallel. This is a magic string used by the parallel_throw routine that makes 00811 // sure the printout will only be done on processor 0. Since the exception is 00812 // parallel there is no reason to print the same message many times. 00813 #define StackTraceMessage " exception thrown from " 00814 #define ParallelStackTraceMessage " parallel exception thrown from " 00815 #define ParallelStackTrace std::string(std::string(ParallelStackTraceMessage) + stk_classic::source_relative_path(STR_TRACE)) 00816 00817 #endif // STK_UTIL_PARALLEL_Exception_hpp