Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-09-11 04:33:00

0001 #ifndef FWCore_Utilities_Exception_h
0002 #define FWCore_Utilities_Exception_h
0003 
0004 /**
0005    This a basic exception type expected to be thrown by
0006    developer-written code.  We recommend that you use it directly.
0007    It can also be used as a base class if needed.
0008 
0009    Each Exception is identified by a category string.  This category
0010    is a short word or phrase (no spaces) that described the problem
0011    that was encountered.
0012 
0013    Information can be added to the Exception using the stream insertion
0014    operator (as one uses cout).  We recommend using it in the following
0015    manner:
0016 
0017    Example:
0018    if ((rc=func()) < 0)
0019    {
0020    throw cms::Exception("DataCorrupt") << "I died with rc = " 
0021      << rc << std::endl;
0022    }
0023 
0024    Derived types are expected to fix the category, either by
0025    1) passing a string literal to the base class constructor, or
0026    2) ensuring the developer gives a category name.
0027 
0028    Example:
0029    class InfiniteLoop : public Exception
0030    {
0031    InfiniteLoop(const std::string& msg) : Exception("InfiniteLoop",msg) { }
0032    };
0033 **/
0034 
0035 #include <atomic>
0036 #include <list>
0037 #include <sstream>
0038 #include <string>
0039 #include <exception>
0040 #include <type_traits>
0041 #include <string_view>
0042 #include <concepts>
0043 
0044 #include "fmt/format.h"
0045 
0046 #include "FWCore/Utilities/interface/thread_safety_macros.h"
0047 #include "FWCore/Utilities/interface/Likely.h"
0048 #include "FWCore/Utilities/interface/Visibility.h"
0049 
0050 namespace cms {
0051 
0052   class dso_export Exception : public std::exception {
0053   public:
0054     explicit Exception(std::string const& aCategory);
0055     explicit Exception(char const* aCategory);
0056 
0057     Exception(std::string const& aCategory, std::string const& message);
0058     Exception(char const* aCategory, std::string const& message);
0059     Exception(std::string const& aCategory, char const* message);
0060     Exception(char const* aCategory, char const* message);
0061 
0062     Exception(std::string const& aCategory, std::string const& message, Exception const& another);
0063 
0064     Exception(Exception const& other);
0065     ~Exception() noexcept override;
0066 
0067     void swap(Exception& other);
0068 
0069     Exception& operator=(Exception const& other);
0070 
0071     // The signature for what() must be identical to that of std::exception::what().
0072     // This function is NOT const thread safe
0073     char const* what() const noexcept override;
0074 
0075     virtual std::string explainSelf() const;
0076 
0077     std::string const& category() const;
0078     std::string message() const;
0079     std::list<std::string> const& context() const;
0080     std::list<std::string> const& additionalInfo() const;
0081     int returnCode() const;
0082 
0083     void raise() { rethrow(); }
0084 
0085     void append(Exception const& another);
0086     void append(std::string const& more_information);
0087     void append(char const* more_information);
0088 
0089     void clearMessage();
0090     void clearContext();
0091     void clearAdditionalInfo();
0092 
0093     void addContext(std::string const& context);
0094     void addContext(char const* context);
0095 
0096     void addAdditionalInfo(std::string const& info);
0097     void addAdditionalInfo(char const* info);
0098 
0099     void setContext(std::list<std::string> const& context);
0100     void setAdditionalInfo(std::list<std::string> const& info);
0101 
0102     bool alreadyPrinted() const;
0103     void setAlreadyPrinted();
0104 
0105     virtual Exception* clone() const;
0106 
0107     // In the following templates, class E is our Exception class or
0108     // any subclass thereof. The complicated return type exists to
0109     // make sure the template can only be instantiated for such
0110     // classes.
0111     //
0112 
0113     template <typename E, typename T>
0114       requires std::derived_from<std::remove_reference_t<E>, Exception>
0115     friend E& operator<<(E&& e, T const& stuff);
0116 
0117     template <typename E>
0118       requires std::derived_from<std::remove_reference_t<E>, Exception>
0119     friend E& operator<<(E&& e, std::ostream& (*f)(std::ostream&));
0120 
0121     template <typename E>
0122       requires std::derived_from<std::remove_reference_t<E>, Exception>
0123     friend E& operator<<(E&& e, std::ios_base& (*f)(std::ios_base&));
0124 
0125     template <typename... Args>
0126     inline void format(fmt::format_string<Args...> format, Args&&... args);
0127     inline void vformat(std::string_view fmt, fmt::format_args args);
0128 
0129     // This function is deprecated and we are in the process of removing
0130     // all code that uses it from CMSSW.  It will then be deleted.
0131     std::list<std::string> history() const;
0132 
0133   private:
0134     void init(std::string const& message);
0135     virtual void rethrow();
0136     virtual int returnCode_() const;
0137 
0138     // data members
0139     std::ostringstream ost_;
0140     std::string category_;
0141     //The exception class should not be accessed across threads
0142     CMS_SA_ALLOW mutable std::string what_;
0143     std::list<std::string> context_;
0144     std::list<std::string> additionalInfo_;
0145     std::atomic<bool> alreadyPrinted_;
0146   };
0147 
0148   inline std::ostream& operator<<(std::ostream& ost, Exception const& e) {
0149     ost << e.explainSelf();
0150     return ost;
0151   }
0152 
0153   // -------- implementation ---------
0154 
0155   template <typename... Args>
0156   inline void Exception::format(fmt::format_string<Args...> format, Args&&... args) {
0157     ost_ << fmt::format(std::move(format), std::forward<Args>(args)...);
0158   }
0159 
0160   inline void Exception::vformat(std::string_view format, fmt::format_args args) { ost_ << fmt::vformat(format, args); }
0161 
0162   template <typename E, typename T>
0163     requires std::derived_from<std::remove_reference_t<E>, Exception>
0164   inline E& operator<<(E&& e, T const& stuff) {
0165     e.ost_ << stuff;
0166     return e;
0167   }
0168 
0169   template <typename E>
0170     requires std::derived_from<std::remove_reference_t<E>, Exception>
0171   inline E& operator<<(E&& e, std::ostream& (*f)(std::ostream&)) {
0172     f(e.ost_);
0173     return e;
0174   }
0175 
0176   template <typename E>
0177     requires std::derived_from<std::remove_reference_t<E>, Exception>
0178   inline E& operator<<(E&& e, std::ios_base& (*f)(std::ios_base&)) {
0179     f(e.ost_);
0180     return e;
0181   }
0182 
0183 }  // namespace cms
0184 
0185 #endif