Chris@16: /* Chris@101: * Copyright Andrey Semashev 2007 - 2015. Chris@16: * Distributed under the Boost Software License, Version 1.0. Chris@16: * (See accompanying file LICENSE_1_0.txt or copy at Chris@16: * http://www.boost.org/LICENSE_1_0.txt) Chris@16: */ Chris@16: /*! Chris@16: * \file exception_handler.hpp Chris@16: * \author Andrey Semashev Chris@16: * \date 12.07.2009 Chris@16: * Chris@16: * This header contains tools for exception handlers support in different parts of the library. Chris@16: */ Chris@16: Chris@16: #ifndef BOOST_LOG_UTILITY_EXCEPTION_HANDLER_HPP_INCLUDED_ Chris@16: #define BOOST_LOG_UTILITY_EXCEPTION_HANDLER_HPP_INCLUDED_ Chris@16: Chris@101: #include // std::nothrow_t Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #ifdef BOOST_HAS_PRAGMA_ONCE Chris@16: #pragma once Chris@16: #endif Chris@16: Chris@16: #ifndef BOOST_LOG_MAX_EXCEPTION_TYPES Chris@16: //! Maximum number of exception types that can be specified for exception handlers Chris@16: #define BOOST_LOG_MAX_EXCEPTION_TYPES 10 Chris@16: #endif Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: BOOST_LOG_OPEN_NAMESPACE Chris@16: Chris@16: namespace aux { Chris@16: Chris@16: BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_exception_types, exception_types, false) Chris@16: Chris@16: //! Root class for the exception handler class hierarchy Chris@16: template< typename HandlerT > Chris@16: class eh_root Chris@16: { Chris@16: public: Chris@16: //! The exception handler type Chris@16: typedef HandlerT handler_type; Chris@16: //! The handler result type Chris@16: typedef void result_type; Chris@16: Chris@16: protected: Chris@16: //! Exception handler Chris@16: handler_type m_Handler; Chris@16: Chris@16: public: Chris@16: //! Initializing constructor Chris@16: explicit eh_root(handler_type const& handler) : m_Handler(handler) Chris@16: { Chris@16: } Chris@16: Chris@16: //! Exception launcher Chris@16: void operator()() const Chris@16: { Chris@16: throw; Chris@16: } Chris@16: }; Chris@16: Chris@16: //! A cons-list element of the exception handler class hierarchy Chris@16: template< typename ExceptionT, typename BaseT > Chris@16: class eh_cons : Chris@16: public BaseT Chris@16: { Chris@16: //! Base type Chris@16: typedef BaseT base_type; Chris@16: Chris@16: public: Chris@16: //! The exception handler type Chris@16: typedef typename base_type::handler_type handler_type; Chris@16: Chris@16: public: Chris@16: //! Initializing constructor Chris@16: explicit eh_cons(handler_type const& handler) : base_type(handler) Chris@16: { Chris@16: } Chris@16: Chris@16: //! Exception launcher Chris@16: void operator()() const Chris@16: { Chris@16: try Chris@16: { Chris@16: base_type::operator()(); Chris@16: } Chris@16: catch (ExceptionT& e) Chris@16: { Chris@16: this->m_Handler(e); Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: template< template< typename, typename > class EHT, typename HandlerT > Chris@16: struct make_self_contained_exception_handler Chris@16: { Chris@16: typedef EHT< typename HandlerT::exception_types, HandlerT > type; Chris@16: }; Chris@16: Chris@16: } // namespace aux Chris@16: Chris@16: /*! Chris@16: * An exception handler functional object. The handler aggregates a user-defined Chris@16: * functional object that will be called when one of the specified exception types Chris@16: * is caught. Chris@16: */ Chris@16: template< typename SequenceT, typename HandlerT > Chris@16: class exception_handler : Chris@16: public mpl::fold< Chris@16: SequenceT, Chris@16: aux::eh_root< HandlerT >, Chris@16: mpl::bind< mpl::quote2< aux::eh_cons >, mpl::_2, mpl::_1 > Chris@16: >::type Chris@16: { Chris@16: //! Base type Chris@16: typedef typename mpl::fold< Chris@16: SequenceT, Chris@16: aux::eh_root< HandlerT >, Chris@16: mpl::bind< mpl::quote2< aux::eh_cons >, mpl::_2, mpl::_1 > Chris@16: >::type base_type; Chris@16: Chris@16: public: Chris@16: #ifndef BOOST_LOG_DOXYGEN_PASS Chris@16: typedef typename base_type::handler_type handler_type; Chris@16: #else Chris@16: //! The exception handler type Chris@16: typedef HandlerT handler_type; Chris@16: //! The handler result type Chris@16: typedef void result_type; Chris@16: #endif Chris@16: Chris@16: public: Chris@16: /*! Chris@16: * Initializing constructor. Creates an exception handler with the specified Chris@16: * function object that will receive the exception. Chris@16: */ Chris@16: explicit exception_handler(handler_type const& handler) : base_type(handler) Chris@16: { Chris@16: } Chris@16: Chris@16: /*! Chris@16: * Exception launcher. Rethrows the current exception in order to detect its type Chris@16: * and pass it to the aggregated function object. Chris@16: * Chris@16: * \note Must be called from within a \c catch statement. Chris@16: */ Chris@16: void operator()() const Chris@16: { Chris@16: base_type::operator()(); Chris@16: } Chris@16: }; Chris@16: Chris@16: /*! Chris@16: * A no-throw exception handler functional object. Acts similar to \c exception_handler, Chris@16: * but in case if the exception cannot be handled the exception is not propagated Chris@16: * from the handler. Instead the user-defined functional object is called with Chris@16: * no parameters. Chris@16: */ Chris@16: template< typename SequenceT, typename HandlerT > Chris@16: class nothrow_exception_handler : Chris@16: public exception_handler< SequenceT, HandlerT > Chris@16: { Chris@16: //! Base type Chris@16: typedef exception_handler< SequenceT, HandlerT > base_type; Chris@16: Chris@16: public: Chris@16: #ifndef BOOST_LOG_DOXYGEN_PASS Chris@16: typedef typename base_type::handler_type handler_type; Chris@16: #else Chris@16: //! The exception handler type Chris@16: typedef HandlerT handler_type; Chris@16: //! The handler result type Chris@16: typedef void result_type; Chris@16: #endif Chris@16: Chris@16: public: Chris@16: /*! Chris@16: * Initializing constructor. Creates an exception handler with the specified Chris@16: * function object that will receive the exception. Chris@16: */ Chris@16: explicit nothrow_exception_handler(handler_type const& handler) : base_type(handler) Chris@16: { Chris@16: } Chris@16: Chris@16: /*! Chris@16: * Exception launcher. Rethrows the current exception in order to detect its type Chris@16: * and pass it to the aggregated function object. If the type of the exception Chris@16: * could not be detected, the user-defined handler is called with no arguments. Chris@16: * Chris@16: * \note Must be called from within a \c catch statement. Chris@16: */ Chris@16: void operator()() const Chris@16: { Chris@16: try Chris@16: { Chris@16: base_type::operator()(); Chris@16: } Chris@16: catch (...) Chris@16: { Chris@16: this->m_Handler(); Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: /*! Chris@16: * The function creates an empty exception handler that effectively suppresses any exception Chris@16: */ Chris@16: inline nop make_exception_suppressor() Chris@16: { Chris@16: return nop(); Chris@16: } Chris@16: Chris@16: #ifndef BOOST_LOG_DOXYGEN_PASS Chris@16: Chris@16: template< typename HandlerT > Chris@16: inline typename lazy_enable_if< Chris@16: aux::has_exception_types< HandlerT >, Chris@16: aux::make_self_contained_exception_handler< exception_handler, HandlerT > Chris@16: >::type make_exception_handler(HandlerT const& handler) Chris@16: { Chris@16: typedef typename aux::make_self_contained_exception_handler< exception_handler, HandlerT >::type eh_t; Chris@16: return eh_t(handler); Chris@16: } Chris@16: Chris@16: template< typename HandlerT > Chris@16: inline typename lazy_enable_if< Chris@16: aux::has_exception_types< HandlerT >, Chris@16: aux::make_self_contained_exception_handler< nothrow_exception_handler, HandlerT > Chris@16: >::type make_exception_handler(HandlerT const& handler, std::nothrow_t const&) Chris@16: { Chris@16: typedef typename aux::make_self_contained_exception_handler< nothrow_exception_handler, HandlerT >::type eh_t; Chris@16: return eh_t(handler); Chris@16: } Chris@16: Chris@16: #define BOOST_LOG_MAKE_EXCEPTION_HANDLER_INTERNAL(z, n, data)\ Chris@16: template< BOOST_PP_ENUM_PARAMS(n, typename T), typename HandlerT >\ Chris@16: inline exception_handler<\ Chris@16: BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(n, T) >,\ Chris@16: HandlerT\ Chris@16: > make_exception_handler(HandlerT const& handler)\ Chris@16: {\ Chris@16: typedef exception_handler<\ Chris@16: BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(n, T) >,\ Chris@16: HandlerT\ Chris@16: > eh_t;\ Chris@16: return eh_t(handler);\ Chris@16: }\ Chris@16: template< BOOST_PP_ENUM_PARAMS(n, typename T), typename HandlerT >\ Chris@16: inline nothrow_exception_handler<\ Chris@16: BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(n, T) >,\ Chris@16: HandlerT\ Chris@16: > make_exception_handler(HandlerT const& handler, std::nothrow_t const&)\ Chris@16: {\ Chris@16: typedef nothrow_exception_handler<\ Chris@16: BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(n, T) >,\ Chris@16: HandlerT\ Chris@16: > eh_t;\ Chris@16: return eh_t(handler);\ Chris@16: } Chris@16: Chris@16: BOOST_PP_REPEAT_FROM_TO(1, BOOST_LOG_MAX_EXCEPTION_TYPES, BOOST_LOG_MAKE_EXCEPTION_HANDLER_INTERNAL, ~) Chris@16: Chris@16: #undef BOOST_LOG_MAKE_EXCEPTION_HANDLER_INTERNAL Chris@16: Chris@16: #else // BOOST_LOG_DOXYGEN_PASS Chris@16: Chris@16: /*! Chris@16: * The function creates an exception handler functional object. The handler will call to the Chris@16: * user-specified functional object with an exception as its argument. Chris@16: * Chris@16: * \param handler User-defined functional object that will receive exceptions. Chris@16: * \return A nullary functional object that should be called from within a \c catch statement. Chris@16: * Chris@16: * \note This form requires the user-defined functional object to have an \c exception_types Chris@16: * nested type. This type should be an MPL sequence of all expected exception types. Chris@16: */ Chris@16: template< typename HandlerT > Chris@16: exception_handler< typename HandlerT::exception_types, HandlerT > Chris@16: make_exception_handler(HandlerT const& handler); Chris@16: Chris@16: /*! Chris@16: * The function creates an exception handler functional object. The handler will call to the Chris@16: * user-specified functional object with an exception as its argument. If the exception type Chris@16: * cannot be identified, the handler will call the user-defined functor with no arguments, Chris@16: * instead of propagating exception to the caller. Chris@16: * Chris@16: * \overload Chris@16: * Chris@16: * \param handler User-defined functional object that will receive exceptions. Chris@16: * \return A nullary functional object that should be called from within a \c catch statement. Chris@16: * Chris@16: * \note This form requires the user-defined functional object to have an \c exception_types Chris@16: * nested type. This type should be an MPL sequence of all expected exception types. Chris@16: */ Chris@16: template< typename HandlerT > Chris@16: nothrow_exception_handler< typename HandlerT::exception_types, HandlerT > Chris@16: make_exception_handler(HandlerT const& handler, std::nothrow_t const&); Chris@16: Chris@16: /*! Chris@16: * The function creates an exception handler functional object. The handler will call to the Chris@16: * user-specified functional object with an exception as its argument. All expected exception Chris@16: * types should be specified as first template parameters explicitly, in the order they would Chris@16: * be specified in a corresponding try/catch statement. Chris@16: * Chris@16: * \overload Chris@16: * Chris@16: * \param handler User-defined functional object that will receive exceptions. Chris@16: * \return A nullary functional object that should be called from within a \c catch statement. Chris@16: */ Chris@16: template< typename... ExceptionsT, typename HandlerT > Chris@16: exception_handler< MPL_sequence_of_ExceptionsT, HandlerT > Chris@16: make_exception_handler(HandlerT const& handler); Chris@16: Chris@16: /*! Chris@16: * The function creates an exception handler functional object. The handler will call to the Chris@16: * user-specified functional object with an exception as its argument. If the exception type Chris@16: * cannot be identified, the handler will call the user-defined functor with no arguments, Chris@16: * instead of propagating exception to the caller. All expected exception types should be Chris@16: * specified as first template parameters explicitly, in the order they would be specified in Chris@16: * a corresponding try/catch statement. Chris@16: * Chris@16: * \overload Chris@16: * Chris@16: * \param handler User-defined functional object that will receive exceptions. Chris@16: * \return A nullary functional object that should be called from within a \c catch statement. Chris@16: */ Chris@16: template< typename... ExceptionsT, typename HandlerT > Chris@16: nothrow_exception_handler< MPL_sequence_of_ExceptionsT, HandlerT > Chris@16: make_exception_handler(HandlerT const& handler, std::nothrow_t const&); Chris@16: Chris@16: #endif // BOOST_LOG_DOXYGEN_PASS Chris@16: Chris@16: BOOST_LOG_CLOSE_NAMESPACE // namespace log Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: #include Chris@16: Chris@16: #endif // BOOST_LOG_UTILITY_EXCEPTION_HANDLER_HPP_INCLUDED_