Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:28

0001 /*
0002  *          Copyright Andrey Semashev 2007 - 2015.
0003  * Distributed under the Boost Software License, Version 1.0.
0004  *    (See accompanying file LICENSE_1_0.txt or copy at
0005  *          http://www.boost.org/LICENSE_1_0.txt)
0006  */
0007 /*!
0008  * \file   exception_handler.hpp
0009  * \author Andrey Semashev
0010  * \date   12.07.2009
0011  *
0012  * This header contains tools for exception handlers support in different parts of the library.
0013  */
0014 
0015 #ifndef BOOST_LOG_UTILITY_EXCEPTION_HANDLER_HPP_INCLUDED_
0016 #define BOOST_LOG_UTILITY_EXCEPTION_HANDLER_HPP_INCLUDED_
0017 
0018 #include <new> // std::nothrow_t
0019 #include <boost/mpl/bind.hpp>
0020 #include <boost/mpl/quote.hpp>
0021 #include <boost/mpl/fold.hpp>
0022 #include <boost/mpl/placeholders.hpp>
0023 #include <boost/mpl/has_xxx.hpp>
0024 #include <boost/mpl/vector.hpp>
0025 #include <boost/core/enable_if.hpp>
0026 #include <boost/preprocessor/cat.hpp>
0027 #include <boost/preprocessor/repetition/enum_params.hpp>
0028 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
0029 #include <boost/log/detail/config.hpp>
0030 #include <boost/log/utility/functional/nop.hpp>
0031 #include <boost/log/detail/header.hpp>
0032 
0033 #ifdef BOOST_HAS_PRAGMA_ONCE
0034 #pragma once
0035 #endif
0036 
0037 #ifndef BOOST_LOG_MAX_EXCEPTION_TYPES
0038 //! Maximum number of exception types that can be specified for exception handlers
0039 #define BOOST_LOG_MAX_EXCEPTION_TYPES 10
0040 #endif
0041 
0042 namespace boost {
0043 
0044 BOOST_LOG_OPEN_NAMESPACE
0045 
0046 namespace aux {
0047 
0048 BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_exception_types, exception_types, false)
0049 
0050 //! Root class for the exception handler class hierarchy
0051 template< typename HandlerT >
0052 class eh_root
0053 {
0054 public:
0055     //! The exception handler type
0056     typedef HandlerT handler_type;
0057     //! The handler result type
0058     typedef void result_type;
0059 
0060 protected:
0061     //! Exception handler
0062     handler_type m_Handler;
0063 
0064 public:
0065     //! Initializing constructor
0066     explicit eh_root(handler_type const& handler) : m_Handler(handler)
0067     {
0068     }
0069 
0070     //! Exception launcher
0071     void operator()() const
0072     {
0073         throw;
0074     }
0075 };
0076 
0077 //! A cons-list element of the exception handler class hierarchy
0078 template< typename ExceptionT, typename BaseT >
0079 class eh_cons :
0080     public BaseT
0081 {
0082     //! Base type
0083     typedef BaseT base_type;
0084 
0085 public:
0086     //! The exception handler type
0087     typedef typename base_type::handler_type handler_type;
0088 
0089 public:
0090     //! Initializing constructor
0091     explicit eh_cons(handler_type const& handler) : base_type(handler)
0092     {
0093     }
0094 
0095     //! Exception launcher
0096     void operator()() const
0097     {
0098         try
0099         {
0100             base_type::operator()();
0101         }
0102         catch (ExceptionT& e)
0103         {
0104             this->m_Handler(e);
0105         }
0106     }
0107 };
0108 
0109 template< template< typename, typename > class EHT, typename HandlerT >
0110 struct make_self_contained_exception_handler
0111 {
0112     typedef EHT< typename HandlerT::exception_types, HandlerT > type;
0113 };
0114 
0115 } // namespace aux
0116 
0117 /*!
0118  * An exception handler functional object. The handler aggregates a user-defined
0119  * functional object that will be called when one of the specified exception types
0120  * is caught.
0121  */
0122 template< typename SequenceT, typename HandlerT >
0123 class exception_handler :
0124     public mpl::fold<
0125         SequenceT,
0126         aux::eh_root< HandlerT >,
0127         mpl::bind< mpl::quote2< aux::eh_cons >, mpl::_2, mpl::_1 >
0128     >::type
0129 {
0130     //! Base type
0131     typedef typename mpl::fold<
0132         SequenceT,
0133         aux::eh_root< HandlerT >,
0134         mpl::bind< mpl::quote2< aux::eh_cons >, mpl::_2, mpl::_1 >
0135     >::type base_type;
0136 
0137 public:
0138 #ifndef BOOST_LOG_DOXYGEN_PASS
0139     typedef typename base_type::handler_type handler_type;
0140 #else
0141     //! The exception handler type
0142     typedef HandlerT handler_type;
0143     //! The handler result type
0144     typedef void result_type;
0145 #endif
0146 
0147 public:
0148     /*!
0149      * Initializing constructor. Creates an exception handler with the specified
0150      * function object that will receive the exception.
0151      */
0152     explicit exception_handler(handler_type const& handler) : base_type(handler)
0153     {
0154     }
0155 
0156     /*!
0157      * Exception launcher. Rethrows the current exception in order to detect its type
0158      * and pass it to the aggregated function object.
0159      *
0160      * \note Must be called from within a \c catch statement.
0161      */
0162     void operator()() const
0163     {
0164         base_type::operator()();
0165     }
0166 };
0167 
0168 /*!
0169  * A no-throw exception handler functional object. Acts similar to \c exception_handler,
0170  * but in case if the exception cannot be handled the exception is not propagated
0171  * from the handler. Instead the user-defined functional object is called with
0172  * no parameters.
0173  */
0174 template< typename SequenceT, typename HandlerT >
0175 class nothrow_exception_handler :
0176     public exception_handler< SequenceT, HandlerT >
0177 {
0178     //! Base type
0179     typedef exception_handler< SequenceT, HandlerT > base_type;
0180 
0181 public:
0182 #ifndef BOOST_LOG_DOXYGEN_PASS
0183     typedef typename base_type::handler_type handler_type;
0184 #else
0185     //! The exception handler type
0186     typedef HandlerT handler_type;
0187     //! The handler result type
0188     typedef void result_type;
0189 #endif
0190 
0191 public:
0192     /*!
0193      * Initializing constructor. Creates an exception handler with the specified
0194      * function object that will receive the exception.
0195      */
0196     explicit nothrow_exception_handler(handler_type const& handler) : base_type(handler)
0197     {
0198     }
0199 
0200     /*!
0201      * Exception launcher. Rethrows the current exception in order to detect its type
0202      * and pass it to the aggregated function object. If the type of the exception
0203      * could not be detected, the user-defined handler is called with no arguments.
0204      *
0205      * \note Must be called from within a \c catch statement.
0206      */
0207     void operator()() const
0208     {
0209         try
0210         {
0211             base_type::operator()();
0212         }
0213         catch (...)
0214         {
0215             this->m_Handler();
0216         }
0217     }
0218 };
0219 
0220 /*!
0221  * The function creates an empty exception handler that effectively suppresses any exception
0222  */
0223 inline nop make_exception_suppressor()
0224 {
0225     return nop();
0226 }
0227 
0228 #ifndef BOOST_LOG_DOXYGEN_PASS
0229 
0230 template< typename HandlerT >
0231 inline typename boost::lazy_enable_if_c<
0232     aux::has_exception_types< HandlerT >::value,
0233     aux::make_self_contained_exception_handler< exception_handler, HandlerT >
0234 >::type make_exception_handler(HandlerT const& handler)
0235 {
0236     typedef typename aux::make_self_contained_exception_handler< exception_handler, HandlerT >::type eh_t;
0237     return eh_t(handler);
0238 }
0239 
0240 template< typename HandlerT >
0241 inline typename boost::lazy_enable_if_c<
0242     aux::has_exception_types< HandlerT >::value,
0243     aux::make_self_contained_exception_handler< nothrow_exception_handler, HandlerT >
0244 >::type make_exception_handler(HandlerT const& handler, std::nothrow_t const&)
0245 {
0246     typedef typename aux::make_self_contained_exception_handler< nothrow_exception_handler, HandlerT >::type eh_t;
0247     return eh_t(handler);
0248 }
0249 
0250 #define BOOST_LOG_MAKE_EXCEPTION_HANDLER_INTERNAL(z, n, data)\
0251     template< BOOST_PP_ENUM_PARAMS_Z(z, n, typename T), typename HandlerT >\
0252     inline exception_handler<\
0253         BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS_Z(z, n, T) >,\
0254         HandlerT\
0255     > make_exception_handler(HandlerT const& handler)\
0256     {\
0257         typedef exception_handler<\
0258             BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS_Z(z, n, T) >,\
0259             HandlerT\
0260         > eh_t;\
0261         return eh_t(handler);\
0262     }\
0263     template< BOOST_PP_ENUM_PARAMS_Z(z, n, typename T), typename HandlerT >\
0264     inline nothrow_exception_handler<\
0265         BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS_Z(z, n, T) >,\
0266         HandlerT\
0267     > make_exception_handler(HandlerT const& handler, std::nothrow_t const&)\
0268     {\
0269         typedef nothrow_exception_handler<\
0270             BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS_Z(z, n, T) >,\
0271             HandlerT\
0272         > eh_t;\
0273         return eh_t(handler);\
0274     }
0275 
0276 BOOST_PP_REPEAT_FROM_TO(1, BOOST_LOG_MAX_EXCEPTION_TYPES, BOOST_LOG_MAKE_EXCEPTION_HANDLER_INTERNAL, ~)
0277 
0278 #undef BOOST_LOG_MAKE_EXCEPTION_HANDLER_INTERNAL
0279 
0280 #else // BOOST_LOG_DOXYGEN_PASS
0281 
0282 /*!
0283  * The function creates an exception handler functional object. The handler will call to the
0284  * user-specified functional object with an exception as its argument.
0285  *
0286  * \param handler User-defined functional object that will receive exceptions.
0287  * \return A nullary functional object that should be called from within a \c catch statement.
0288  *
0289  * \note This form requires the user-defined functional object to have an \c exception_types
0290  *       nested type. This type should be an MPL sequence of all expected exception types.
0291  */
0292 template< typename HandlerT >
0293 exception_handler< typename HandlerT::exception_types, HandlerT >
0294 make_exception_handler(HandlerT const& handler);
0295 
0296 /*!
0297  * The function creates an exception handler functional object. The handler will call to the
0298  * user-specified functional object with an exception as its argument. If the exception type
0299  * cannot be identified, the handler will call the user-defined functor with no arguments,
0300  * instead of propagating exception to the caller.
0301  *
0302  * \overload
0303  *
0304  * \param handler User-defined functional object that will receive exceptions.
0305  * \return A nullary functional object that should be called from within a \c catch statement.
0306  *
0307  * \note This form requires the user-defined functional object to have an \c exception_types
0308  *       nested type. This type should be an MPL sequence of all expected exception types.
0309  */
0310 template< typename HandlerT >
0311 nothrow_exception_handler< typename HandlerT::exception_types, HandlerT >
0312 make_exception_handler(HandlerT const& handler, std::nothrow_t const&);
0313 
0314 /*!
0315  * The function creates an exception handler functional object. The handler will call to the
0316  * user-specified functional object with an exception as its argument. All expected exception
0317  * types should be specified as first template parameters explicitly, in the order they would
0318  * be specified in a corresponding <tt>try/catch</tt> statement.
0319  *
0320  * \overload
0321  *
0322  * \param handler User-defined functional object that will receive exceptions.
0323  * \return A nullary functional object that should be called from within a \c catch statement.
0324  */
0325 template< typename... ExceptionsT, typename HandlerT >
0326 exception_handler< MPL_sequence_of_ExceptionsT, HandlerT >
0327 make_exception_handler(HandlerT const& handler);
0328 
0329 /*!
0330  * The function creates an exception handler functional object. The handler will call to the
0331  * user-specified functional object with an exception as its argument. If the exception type
0332  * cannot be identified, the handler will call the user-defined functor with no arguments,
0333  * instead of propagating exception to the caller. All expected exception types should be
0334  * specified as first template parameters explicitly, in the order they would be specified in
0335  * a corresponding <tt>try/catch</tt> statement.
0336  *
0337  * \overload
0338  *
0339  * \param handler User-defined functional object that will receive exceptions.
0340  * \return A nullary functional object that should be called from within a \c catch statement.
0341  */
0342 template< typename... ExceptionsT, typename HandlerT >
0343 nothrow_exception_handler< MPL_sequence_of_ExceptionsT, HandlerT >
0344 make_exception_handler(HandlerT const& handler, std::nothrow_t const&);
0345 
0346 #endif // BOOST_LOG_DOXYGEN_PASS
0347 
0348 BOOST_LOG_CLOSE_NAMESPACE // namespace log
0349 
0350 } // namespace boost
0351 
0352 #include <boost/log/detail/footer.hpp>
0353 
0354 #endif // BOOST_LOG_UTILITY_EXCEPTION_HANDLER_HPP_INCLUDED_