diff options
Diffstat (limited to 'boost/log/utility/exception_handler.hpp')
-rw-r--r-- | boost/log/utility/exception_handler.hpp | 354 |
1 files changed, 354 insertions, 0 deletions
diff --git a/boost/log/utility/exception_handler.hpp b/boost/log/utility/exception_handler.hpp new file mode 100644 index 0000000000..c5392be687 --- /dev/null +++ b/boost/log/utility/exception_handler.hpp @@ -0,0 +1,354 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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/preprocessor/cat.hpp> +#include <boost/preprocessor/repetition/enum_params.hpp> +#include <boost/preprocessor/repetition/repeat_from_to.hpp> +#include <boost/utility/enable_if.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 lazy_enable_if< + aux::has_exception_types< HandlerT >, + 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 lazy_enable_if< + aux::has_exception_types< HandlerT >, + 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(n, typename T), typename HandlerT >\ + inline exception_handler<\ + BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(n, T) >,\ + HandlerT\ + > make_exception_handler(HandlerT const& handler)\ + {\ + typedef exception_handler<\ + BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(n, T) >,\ + HandlerT\ + > eh_t;\ + return eh_t(handler);\ + }\ + template< BOOST_PP_ENUM_PARAMS(n, typename T), typename HandlerT >\ + inline nothrow_exception_handler<\ + BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(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(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_ |