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 severity_feature.hpp Chris@16: * \author Andrey Semashev Chris@16: * \date 08.03.2007 Chris@16: * Chris@16: * The header contains implementation of a severity level support feature. Chris@16: */ Chris@16: Chris@16: #ifndef BOOST_LOG_SOURCES_SEVERITY_FEATURE_HPP_INCLUDED_ Chris@16: #define BOOST_LOG_SOURCES_SEVERITY_FEATURE_HPP_INCLUDED_ Chris@16: 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: #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: namespace boost { Chris@16: Chris@16: BOOST_LOG_OPEN_NAMESPACE Chris@16: Chris@16: namespace sources { Chris@16: Chris@16: namespace aux { Chris@16: Chris@16: //! The method returns the storage for severity level for the current thread Chris@16: BOOST_LOG_API uintmax_t& get_severity_level(); Chris@16: Chris@16: //! Severity level attribute implementation Chris@16: template< typename LevelT > Chris@16: class severity_level : Chris@16: public attribute Chris@16: { Chris@16: typedef severity_level this_type; Chris@16: BOOST_COPYABLE_AND_MOVABLE(this_type) Chris@16: Chris@16: public: Chris@16: //! Stored level type Chris@16: typedef LevelT value_type; Chris@16: BOOST_STATIC_ASSERT_MSG(sizeof(value_type) <= sizeof(uintmax_t), "Boost.Log: Unsupported severity level type, the severity level must fit into uintmax_t"); Chris@16: Chris@16: protected: Chris@16: //! Factory implementation Chris@16: class BOOST_SYMBOL_VISIBLE impl : Chris@16: public attribute_value::impl Chris@16: { Chris@16: public: Chris@16: //! The method dispatches the value to the given object Chris@16: bool dispatch(type_dispatcher& dispatcher) Chris@16: { Chris@16: type_dispatcher::callback< value_type > callback = dispatcher.get_callback< value_type >(); Chris@16: if (callback) Chris@16: { Chris@16: callback(reinterpret_cast< value_type const& >(get_severity_level())); Chris@16: return true; Chris@16: } Chris@16: else Chris@16: return false; Chris@16: } Chris@16: Chris@16: //! The method is called when the attribute value is passed to another thread Chris@16: intrusive_ptr< attribute_value::impl > detach_from_thread() Chris@16: { Chris@16: #if !defined(BOOST_LOG_NO_THREADS) Chris@16: return new attributes::attribute_value_impl< value_type >( Chris@16: reinterpret_cast< value_type const& >(get_severity_level())); Chris@16: #else Chris@16: // With multithreading disabled we may safely return this here. This method will not be called anyway. Chris@16: return this; Chris@16: #endif Chris@16: } Chris@16: }; Chris@16: Chris@16: public: Chris@16: //! Default constructor Chris@16: severity_level() : attribute(new impl()) Chris@16: { Chris@16: } Chris@16: //! Copy constructor Chris@16: severity_level(severity_level const& that) : attribute(static_cast< attribute const& >(that)) Chris@16: { Chris@16: } Chris@16: //! Move constructor Chris@16: severity_level(BOOST_RV_REF(severity_level) that) : attribute(boost::move(static_cast< attribute& >(that))) Chris@16: { Chris@16: } Chris@16: //! Constructor for casting support Chris@16: explicit severity_level(attributes::cast_source const& source) : Chris@16: attribute(source.as< impl >()) Chris@16: { Chris@16: } Chris@16: Chris@16: /*! Chris@16: * Copy assignment Chris@16: */ Chris@16: severity_level& operator= (BOOST_COPY_ASSIGN_REF(severity_level) that) Chris@16: { Chris@16: attribute::operator= (that); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: /*! Chris@16: * Move assignment Chris@16: */ Chris@16: severity_level& operator= (BOOST_RV_REF(severity_level) that) Chris@16: { Chris@16: this->swap(that); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: //! The method sets the actual level Chris@16: void set_value(value_type level) Chris@16: { Chris@16: reinterpret_cast< value_type& >(get_severity_level()) = level; Chris@16: } Chris@16: }; Chris@16: Chris@16: } // namespace aux Chris@16: Chris@16: /*! Chris@16: * \brief Severity level feature implementation Chris@16: */ Chris@16: template< typename BaseT, typename LevelT = int > Chris@16: class basic_severity_logger : Chris@16: public BaseT Chris@16: { Chris@16: //! Base type Chris@16: typedef BaseT base_type; Chris@16: typedef basic_severity_logger this_type; Chris@16: BOOST_COPYABLE_AND_MOVABLE_ALT(this_type) Chris@16: Chris@16: public: Chris@16: //! Character type Chris@16: typedef typename base_type::char_type char_type; Chris@16: //! Final type Chris@16: typedef typename base_type::final_type final_type; Chris@16: //! Threading model being used Chris@16: typedef typename base_type::threading_model threading_model; Chris@16: Chris@16: //! Severity level type Chris@16: typedef LevelT severity_level; Chris@16: //! Severity attribute type Chris@16: typedef aux::severity_level< severity_level > severity_attribute; Chris@16: Chris@16: #if defined(BOOST_LOG_DOXYGEN_PASS) Chris@16: //! Lock requirement for the \c open_record_unlocked method Chris@16: typedef typename strictest_lock< Chris@16: typename base_type::open_record_lock, Chris@16: no_lock< threading_model > Chris@16: >::type open_record_lock; Chris@16: #endif // defined(BOOST_LOG_DOXYGEN_PASS) Chris@16: Chris@16: //! Lock requirement for the \c swap_unlocked method Chris@16: typedef typename strictest_lock< Chris@16: typename base_type::swap_lock, Chris@16: #ifndef BOOST_LOG_NO_THREADS Chris@16: boost::log::aux::exclusive_lock_guard< threading_model > Chris@16: #else Chris@16: no_lock< threading_model > Chris@16: #endif // !defined(BOOST_LOG_NO_THREADS) Chris@16: >::type swap_lock; Chris@16: Chris@16: private: Chris@16: //! Default severity Chris@16: severity_level m_DefaultSeverity; Chris@16: //! Severity attribute Chris@16: severity_attribute m_SeverityAttr; Chris@16: Chris@16: public: Chris@16: /*! Chris@16: * Default constructor. The constructed logger will have a severity attribute registered. Chris@16: * The default level for log records will be 0. Chris@16: */ Chris@16: basic_severity_logger() : Chris@16: base_type(), Chris@16: m_DefaultSeverity(static_cast< severity_level >(0)) Chris@16: { Chris@16: base_type::add_attribute_unlocked(boost::log::aux::default_attribute_names::severity(), m_SeverityAttr); Chris@16: } Chris@16: /*! Chris@16: * Copy constructor Chris@16: */ Chris@16: basic_severity_logger(basic_severity_logger const& that) : Chris@16: base_type(static_cast< base_type const& >(that)), Chris@16: m_DefaultSeverity(that.m_DefaultSeverity), Chris@16: m_SeverityAttr(that.m_SeverityAttr) Chris@16: { Chris@16: base_type::attributes()[boost::log::aux::default_attribute_names::severity()] = m_SeverityAttr; Chris@16: } Chris@16: /*! Chris@16: * Move constructor Chris@16: */ Chris@16: basic_severity_logger(BOOST_RV_REF(basic_severity_logger) that) : Chris@16: base_type(boost::move(static_cast< base_type& >(that))), Chris@16: m_DefaultSeverity(boost::move(that.m_DefaultSeverity)), Chris@16: m_SeverityAttr(boost::move(that.m_SeverityAttr)) Chris@16: { Chris@16: base_type::attributes()[boost::log::aux::default_attribute_names::severity()] = m_SeverityAttr; Chris@16: } Chris@16: /*! Chris@16: * Constructor with named arguments. Allows to setup the default level for log records. Chris@16: * Chris@16: * \param args A set of named arguments. The following arguments are supported: Chris@16: * \li \c severity - default severity value Chris@16: */ Chris@16: template< typename ArgsT > Chris@16: explicit basic_severity_logger(ArgsT const& args) : Chris@16: base_type(args), Chris@16: m_DefaultSeverity(args[keywords::severity | severity_level()]) Chris@16: { Chris@16: base_type::add_attribute_unlocked(boost::log::aux::default_attribute_names::severity(), m_SeverityAttr); Chris@16: } Chris@16: Chris@16: /*! Chris@16: * Default severity value getter Chris@16: */ Chris@16: severity_level default_severity() const { return m_DefaultSeverity; } Chris@16: Chris@16: protected: Chris@16: /*! Chris@16: * Severity attribute accessor Chris@16: */ Chris@16: severity_attribute const& get_severity_attribute() const { return m_SeverityAttr; } Chris@16: Chris@16: /*! Chris@16: * Unlocked \c open_record Chris@16: */ Chris@16: template< typename ArgsT > Chris@16: record open_record_unlocked(ArgsT const& args) Chris@16: { Chris@16: m_SeverityAttr.set_value(args[keywords::severity | m_DefaultSeverity]); Chris@16: return base_type::open_record_unlocked(args); Chris@16: } Chris@16: Chris@16: //! Unlocked \c swap Chris@16: void swap_unlocked(basic_severity_logger& that) Chris@16: { Chris@16: base_type::swap_unlocked(static_cast< base_type& >(that)); Chris@16: severity_level t = m_DefaultSeverity; Chris@16: m_DefaultSeverity = that.m_DefaultSeverity; Chris@16: that.m_DefaultSeverity = t; Chris@16: m_SeverityAttr.swap(that.m_SeverityAttr); Chris@16: } Chris@16: }; Chris@16: Chris@16: /*! Chris@16: * \brief Severity level support feature Chris@16: * Chris@16: * The logger with this feature registers a special attribute with an integral value type on construction. Chris@16: * This attribute will provide severity level for each log record being made through the logger. Chris@16: * The severity level can be omitted on logging record construction, in which case the default Chris@16: * level will be used. The default level can also be customized by passing it to the logger constructor. Chris@16: * Chris@16: * The type of the severity level attribute can be specified as a template parameter for the feature Chris@16: * template. By default, \c int will be used. Chris@16: */ Chris@16: template< typename LevelT = int > Chris@16: struct severity Chris@16: { Chris@16: template< typename BaseT > Chris@16: struct apply Chris@16: { Chris@16: typedef basic_severity_logger< Chris@16: BaseT, Chris@16: LevelT Chris@16: > type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: } // namespace sources Chris@16: Chris@16: BOOST_LOG_CLOSE_NAMESPACE // namespace log Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: //! The macro allows to put a record with a specific severity level into log Chris@16: #define BOOST_LOG_STREAM_SEV(logger, lvl)\ Chris@16: BOOST_LOG_STREAM_WITH_PARAMS((logger), (::boost::log::keywords::severity = (lvl))) Chris@16: Chris@16: #ifndef BOOST_LOG_NO_SHORTHAND_NAMES Chris@16: Chris@16: //! An equivalent to BOOST_LOG_STREAM_SEV(logger, lvl) Chris@16: #define BOOST_LOG_SEV(logger, lvl) BOOST_LOG_STREAM_SEV(logger, lvl) Chris@16: Chris@16: #endif // BOOST_LOG_NO_SHORTHAND_NAMES Chris@16: Chris@16: #include Chris@16: Chris@16: #endif // BOOST_LOG_SOURCES_SEVERITY_FEATURE_HPP_INCLUDED_