Sierra Toolkit Version of the Day
Exception.hpp
Go to the documentation of this file.
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 &registerException() {
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 &register_exception_a(const std::type_info &parallel_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 &registerException() {
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::source_relative_path(STR_TRACE))
00816 
00817 #endif // STK_UTIL_PARALLEL_Exception_hpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines