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