Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:35:10

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_feature.hpp
0009  * \author Andrey Semashev
0010  * \date   17.07.2009
0011  *
0012  * The header contains implementation of an exception handler support feature.
0013  */
0014 
0015 #ifndef BOOST_LOG_SOURCES_EXCEPTION_HANDLER_FEATURE_HPP_INCLUDED_
0016 #define BOOST_LOG_SOURCES_EXCEPTION_HANDLER_FEATURE_HPP_INCLUDED_
0017 
0018 #include <boost/move/core.hpp>
0019 #include <boost/move/utility_core.hpp>
0020 #include <boost/type_traits/is_same.hpp>
0021 #include <boost/type_traits/is_nothrow_move_constructible.hpp>
0022 #include <boost/type_traits/conditional.hpp>
0023 #include <boost/log/detail/config.hpp>
0024 #include <boost/log/detail/light_function.hpp>
0025 #include <boost/log/detail/locks.hpp>
0026 #include <boost/log/core/record.hpp>
0027 #include <boost/log/sources/threading_models.hpp>
0028 #include <boost/log/utility/strictest_lock.hpp>
0029 #include <boost/log/detail/header.hpp>
0030 
0031 #ifdef BOOST_HAS_PRAGMA_ONCE
0032 #pragma once
0033 #endif
0034 
0035 namespace boost {
0036 
0037 BOOST_LOG_OPEN_NAMESPACE
0038 
0039 namespace sources {
0040 
0041 /*!
0042  * \brief Exception handler feature implementation
0043  */
0044 template< typename BaseT >
0045 class basic_exception_handler_logger :
0046     public BaseT
0047 {
0048     //! Base type
0049     typedef BaseT base_type;
0050     typedef basic_exception_handler_logger this_type;
0051     BOOST_COPYABLE_AND_MOVABLE_ALT(this_type)
0052 
0053 public:
0054     //! Threading model being used
0055     typedef typename base_type::threading_model threading_model;
0056     //! Final logger type
0057     typedef typename base_type::final_type final_type;
0058     //! Exception handler function type
0059     typedef boost::log::aux::light_function< void () > exception_handler_type;
0060 
0061 #if defined(BOOST_LOG_DOXYGEN_PASS)
0062     //! Lock requirement for the open_record_unlocked method
0063     typedef typename strictest_lock<
0064         typename base_type::open_record_lock,
0065         no_lock< threading_model >
0066     >::type open_record_lock;
0067     //! Lock requirement for the push_record_unlocked method
0068     typedef typename strictest_lock<
0069         typename base_type::push_record_lock,
0070         no_lock< threading_model >
0071     >::type push_record_lock;
0072 #endif // defined(BOOST_LOG_DOXYGEN_PASS)
0073 
0074     //! Lock requirement for the swap_unlocked method
0075     typedef typename strictest_lock<
0076         typename base_type::swap_lock,
0077 #ifndef BOOST_LOG_NO_THREADS
0078         boost::log::aux::multiple_unique_lock2< threading_model, threading_model >
0079 #else
0080         no_lock< threading_model >
0081 #endif // !defined(BOOST_LOG_NO_THREADS)
0082     >::type swap_lock;
0083 
0084 private:
0085     //! Exception handler
0086     exception_handler_type m_ExceptionHandler;
0087 
0088 public:
0089     /*!
0090      * Default constructor. The constructed logger does not have an exception handler.
0091      */
0092     basic_exception_handler_logger() : base_type()
0093     {
0094     }
0095     /*!
0096      * Copy constructor
0097      */
0098     basic_exception_handler_logger(basic_exception_handler_logger const& that) :
0099         base_type(static_cast< base_type const& >(that)),
0100         m_ExceptionHandler(that.m_ExceptionHandler)
0101     {
0102     }
0103     /*!
0104      * Move constructor
0105      */
0106     basic_exception_handler_logger(BOOST_RV_REF(basic_exception_handler_logger) that) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible< base_type >::value && boost::is_nothrow_move_constructible< exception_handler_type >::value) :
0107         base_type(boost::move(static_cast< base_type& >(that))),
0108         m_ExceptionHandler(boost::move(that.m_ExceptionHandler))
0109     {
0110     }
0111     /*!
0112      * Constructor with arguments. Passes arguments to other features.
0113      */
0114     template< typename ArgsT >
0115     explicit basic_exception_handler_logger(ArgsT const& args) :
0116         base_type(args)
0117     {
0118     }
0119 
0120     /*!
0121      * The method sets exception handler function. The function will be called with no arguments
0122      * in case if an exception occurs during either \c open_record or \c push_record method
0123      * execution. Since exception handler is called from a \c catch statement, the exception
0124      * can be rethrown in order to determine its type.
0125      *
0126      * By default no handler is installed, thus any exception is propagated as usual.
0127      *
0128      * \sa <tt>utility/exception_handler.hpp</tt>
0129      * \param handler Exception handling function
0130      *
0131      * \note The exception handler can be invoked in several threads concurrently.
0132      *
0133      * \note Thread interruptions are not affected by exception handlers.
0134      */
0135     template< typename HandlerT >
0136     void set_exception_handler(HandlerT const& handler)
0137     {
0138 #ifndef BOOST_LOG_NO_THREADS
0139         boost::log::aux::exclusive_lock_guard< threading_model > lock(this->get_threading_model());
0140 #endif
0141         m_ExceptionHandler = handler;
0142     }
0143 
0144 protected:
0145     /*!
0146      * Unlocked \c open_record
0147      */
0148     template< typename ArgsT >
0149     record open_record_unlocked(ArgsT const& args)
0150     {
0151         try
0152         {
0153             return base_type::open_record_unlocked(args);
0154         }
0155         catch (...)
0156         {
0157             handle_exception();
0158             return record();
0159         }
0160     }
0161 
0162     /*!
0163      * Unlocked \c push_record
0164      */
0165     void push_record_unlocked(BOOST_RV_REF(record) rec)
0166     {
0167         try
0168         {
0169             base_type::push_record_unlocked(boost::move(rec));
0170         }
0171         catch (...)
0172         {
0173             handle_exception();
0174         }
0175     }
0176 
0177     /*!
0178      * Unlocked swap
0179      */
0180     void swap_unlocked(basic_exception_handler_logger& that)
0181     {
0182         base_type::swap_unlocked(static_cast< base_type& >(that));
0183         m_ExceptionHandler.swap(that.m_ExceptionHandler);
0184     }
0185 
0186 private:
0187 #if !defined(BOOST_LOG_DOXYGEN_PASS)
0188     //! The function handles the intercepted exception
0189     void handle_exception()
0190     {
0191 #ifndef BOOST_LOG_NO_THREADS
0192         // Here's the trick with the lock type. Since the lock
0193         // is only needed when an exception is caught, we indicate
0194         // no locking requirements in the push_record_lock type.
0195         // However, if other features don't require locking either,
0196         // we shall acquire a read lock here, when an exception is caught.
0197         // If other features do require locking, the thread model is
0198         // already locked by now, and we don't do locking at all.
0199         typedef typename boost::conditional<
0200             is_same< no_lock< threading_model >, typename final_type::push_record_lock >::value,
0201             boost::log::aux::shared_lock_guard< threading_model >,
0202             no_lock< threading_model >
0203         >::type lock_type;
0204         lock_type lock(base_type::get_threading_model());
0205 #endif // !defined(BOOST_LOG_NO_THREADS)
0206 
0207         if (m_ExceptionHandler.empty())
0208             throw;
0209         m_ExceptionHandler();
0210     }
0211 #endif // !defined(BOOST_LOG_DOXYGEN_PASS)
0212 };
0213 
0214 /*!
0215  * \brief Exception handler support feature
0216  *
0217  * The logger with this feature will provide an additional method to
0218  * install an exception handler functional object. This functional
0219  * object will be called if during either opening or pushing a record
0220  * an exception is thrown from the logging core.
0221  */
0222 struct exception_handler
0223 {
0224     template< typename BaseT >
0225     struct apply
0226     {
0227         typedef basic_exception_handler_logger< BaseT > type;
0228     };
0229 };
0230 
0231 } // namespace sources
0232 
0233 BOOST_LOG_CLOSE_NAMESPACE // namespace log
0234 
0235 } // namespace boost
0236 
0237 #include <boost/log/detail/footer.hpp>
0238 
0239 #endif // BOOST_LOG_SOURCES_EXCEPTION_HANDLER_FEATURE_HPP_INCLUDED_