Back to home page

EIC code displayed by LXR

 
 

    


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

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