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 attribute_value.hpp Chris@16: * \author Andrey Semashev Chris@16: * \date 21.05.2010 Chris@16: * Chris@16: * The header contains \c attribute_value class definition. Chris@16: */ Chris@16: Chris@16: #ifndef BOOST_LOG_ATTRIBUTE_VALUE_HPP_INCLUDED_ Chris@16: #define BOOST_LOG_ATTRIBUTE_VALUE_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: 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: /*! Chris@16: * \brief An attribute value class Chris@16: * Chris@16: * An attribute value is an object that contains a piece of data that represents an attribute state Chris@16: * at the point of the value acquisition. All major operations with log records, such as filtering and Chris@16: * formatting, involve attribute values contained in a single view. Most likely an attribute value is Chris@16: * implemented as a simple holder of some typed value. This holder implements the Chris@16: * \c attribute_value::implementation interface and acts as a pimpl for the \c attribute_value Chris@16: * object. The \c attribute_value class provides type dispatching support in order to allow Chris@16: * to extract the value from the holder. Chris@16: * Chris@16: * Normally, attributes and their values shall be designed in order to exclude as much interference as Chris@16: * reasonable. Such approach allows to have more than one attribute value simultaneously, which improves Chris@16: * scalability and allows to implement generating attributes. Chris@16: * Chris@16: * However, there are cases when this approach does not help to achieve the required level of independency Chris@16: * of attribute values and attribute itself from each other at a reasonable performance tradeoff. Chris@16: * For example, an attribute or its values may use thread-specific data, which is global and shared Chris@16: * between all the instances of the attribute/value. Passing such an attribute value to another thread Chris@16: * would be a disaster. To solve this the library defines an additional method for attribute values, Chris@16: * namely \c detach_from_thread. The \c attribute_value class forwards the call to its pimpl, Chris@16: * which is supposed to ensure that it no longer refers to any thread-specific data after the call. Chris@16: * The pimpl can create a new holder as a result of this method and return it to the \c attribute_value Chris@16: * wrapper, which will keep the returned reference for any further calls. Chris@16: * This method is called for all attribute values that are passed to another thread. Chris@16: */ Chris@16: class attribute_value Chris@16: { Chris@16: BOOST_COPYABLE_AND_MOVABLE(attribute_value) Chris@16: Chris@16: public: Chris@16: /*! Chris@16: * \brief A base class for an attribute value implementation Chris@16: * Chris@16: * All attribute value holders should derive from this interface. Chris@16: */ Chris@16: struct BOOST_LOG_NO_VTABLE impl : Chris@16: public attribute::impl Chris@16: { Chris@16: public: Chris@16: /*! Chris@16: * The method dispatches the value to the given object. Chris@16: * Chris@16: * \param dispatcher The object that attempts to dispatch the stored value. Chris@16: * \return true if \a dispatcher was capable to consume the real attribute value type and false otherwise. Chris@16: */ Chris@16: virtual bool dispatch(type_dispatcher& dispatcher) = 0; Chris@16: Chris@16: /*! Chris@16: * The method is called when the attribute value is passed to another thread (e.g. Chris@16: * in case of asynchronous logging). The value should ensure it properly owns all thread-specific data. Chris@16: * Chris@16: * \return An actual pointer to the attribute value. It may either point to this object or another. Chris@16: * In the latter case the returned pointer replaces the pointer used by caller to invoke this Chris@16: * method and is considered to be a functional equivalent to the previous pointer. Chris@16: */ Chris@16: virtual intrusive_ptr< impl > detach_from_thread() Chris@16: { Chris@16: return this; Chris@16: } Chris@16: Chris@16: /*! Chris@16: * \return The attribute value that refers to self implementation. Chris@16: */ Chris@16: virtual attribute_value get_value() { return attribute_value(this); } Chris@16: Chris@16: /*! Chris@16: * \return The attribute value type Chris@16: */ Chris@16: virtual type_info_wrapper get_type() const { return type_info_wrapper(); } Chris@16: }; Chris@16: Chris@16: private: Chris@16: //! Pointer to the value implementation Chris@16: intrusive_ptr< impl > m_pImpl; Chris@16: Chris@16: public: Chris@16: /*! Chris@16: * Default constructor. Creates an empty (absent) attribute value. Chris@16: */ Chris@16: BOOST_DEFAULTED_FUNCTION(attribute_value(), {}) Chris@16: Chris@16: /*! Chris@16: * Copy constructor Chris@16: */ Chris@16: attribute_value(attribute_value const& that) BOOST_NOEXCEPT : m_pImpl(that.m_pImpl) {} Chris@16: Chris@16: /*! Chris@16: * Move constructor Chris@16: */ Chris@16: attribute_value(BOOST_RV_REF(attribute_value) that) BOOST_NOEXCEPT { m_pImpl.swap(that.m_pImpl); } Chris@16: Chris@16: /*! Chris@16: * Initializing constructor. Creates an attribute value that refers to the specified holder. Chris@16: * Chris@16: * \param p A pointer to the attribute value holder. Chris@16: */ Chris@16: explicit attribute_value(intrusive_ptr< impl > p) BOOST_NOEXCEPT { m_pImpl.swap(p); } Chris@16: Chris@16: /*! Chris@16: * Copy assignment Chris@16: */ Chris@16: attribute_value& operator= (BOOST_COPY_ASSIGN_REF(attribute_value) that) BOOST_NOEXCEPT Chris@16: { Chris@16: m_pImpl = that.m_pImpl; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: /*! Chris@16: * Move assignment Chris@16: */ Chris@16: attribute_value& operator= (BOOST_RV_REF(attribute_value) that) BOOST_NOEXCEPT Chris@16: { Chris@16: m_pImpl.swap(that.m_pImpl); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: /*! Chris@16: * The operator checks if the attribute value is empty Chris@16: */ Chris@101: BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() Chris@16: /*! Chris@16: * The operator checks if the attribute value is empty Chris@16: */ Chris@16: bool operator! () const BOOST_NOEXCEPT { return !m_pImpl; } Chris@16: Chris@16: /*! Chris@16: * The method returns the type information of the stored value of the attribute. Chris@16: * The returned type info wrapper may be empty if the attribute value is empty or Chris@16: * the information cannot be provided. If the returned value is not empty, the type Chris@16: * can be used for value extraction. Chris@16: */ Chris@16: type_info_wrapper get_type() const Chris@16: { Chris@16: if (m_pImpl.get()) Chris@16: return m_pImpl->get_type(); Chris@16: else Chris@16: return type_info_wrapper(); Chris@16: } Chris@16: Chris@16: /*! Chris@16: * The method is called when the attribute value is passed to another thread (e.g. Chris@16: * in case of asynchronous logging). The value should ensure it properly owns all thread-specific data. Chris@16: * Chris@16: * \post The attribute value no longer refers to any thread-specific resources. Chris@16: */ Chris@16: void detach_from_thread() Chris@16: { Chris@16: if (m_pImpl.get()) Chris@16: m_pImpl->detach_from_thread().swap(m_pImpl); Chris@16: } Chris@16: Chris@16: /*! Chris@16: * The method dispatches the value to the given object. This method is a low level interface for Chris@16: * attribute value visitation and extraction. For typical usage these interfaces may be more convenient. Chris@16: * Chris@16: * \param dispatcher The object that attempts to dispatch the stored value. Chris@16: * \return \c true if the value is not empty and the \a dispatcher was capable to consume Chris@16: * the real attribute value type and \c false otherwise. Chris@16: */ Chris@16: bool dispatch(type_dispatcher& dispatcher) const Chris@16: { Chris@16: if (m_pImpl.get()) Chris@16: return m_pImpl->dispatch(dispatcher); Chris@16: else Chris@16: return false; Chris@16: } Chris@16: Chris@16: #if !defined(BOOST_LOG_DOXYGEN_PASS) Chris@16: #if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) Chris@16: #define BOOST_LOG_AUX_VOID_DEFAULT = void Chris@16: #else Chris@16: #define BOOST_LOG_AUX_VOID_DEFAULT Chris@16: #endif Chris@16: #endif // !defined(BOOST_LOG_DOXYGEN_PASS) Chris@16: Chris@16: /*! Chris@16: * The method attempts to extract the stored value, assuming the value has the specified type. Chris@16: * One can specify either a single type or an MPL type sequence, in which case the stored value Chris@16: * is checked against every type in the sequence. Chris@16: * Chris@16: * \note Include value_extraction.hpp prior to using this method. Chris@16: * Chris@16: * \return The extracted value, if the attribute value is not empty and the value is the same Chris@16: * as specified. Otherwise returns an empty value. See description of the \c result_of::extract Chris@16: * metafunction for information on the nature of the result value. Chris@16: */ Chris@16: template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT > Chris@16: typename result_of::extract< T, TagT >::type extract() const; Chris@16: Chris@16: /*! Chris@16: * The method attempts to extract the stored value, assuming the value has the specified type. Chris@16: * One can specify either a single type or an MPL type sequence, in which case the stored value Chris@16: * is checked against every type in the sequence. Chris@16: * Chris@16: * \note Include value_extraction.hpp prior to using this method. Chris@16: * Chris@16: * \return The extracted value, if the attribute value is not empty and the value is the same Chris@16: * as specified. Otherwise an exception is thrown. See description of the \c result_of::extract_or_throw Chris@16: * metafunction for information on the nature of the result value. Chris@16: */ Chris@16: template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT > Chris@16: typename result_of::extract_or_throw< T, TagT >::type extract_or_throw() const; Chris@16: Chris@16: /*! Chris@16: * The method attempts to extract the stored value, assuming the value has the specified type. Chris@16: * One can specify either a single type or an MPL type sequence, in which case the stored value Chris@16: * is checked against every type in the sequence. If extraction fails, the default value is returned. Chris@16: * Chris@16: * \note Include value_extraction.hpp prior to using this method. Chris@16: * Chris@16: * \param def_value Default value. Chris@16: * Chris@16: * \return The extracted value, if the attribute value is not empty and the value is the same Chris@16: * as specified. Otherwise returns the default value. See description of the \c result_of::extract_or_default Chris@16: * metafunction for information on the nature of the result value. Chris@16: */ Chris@16: template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT > Chris@16: typename result_of::extract_or_default< T, T, TagT >::type extract_or_default(T const& def_value) const; Chris@16: Chris@16: /*! Chris@16: * The method attempts to extract the stored value, assuming the value has the specified type. Chris@16: * One can specify either a single type or an MPL type sequence, in which case the stored value Chris@16: * is checked against every type in the sequence. If extraction fails, the default value is returned. Chris@16: * Chris@16: * \note Include value_extraction.hpp prior to using this method. Chris@16: * Chris@16: * \param def_value Default value. Chris@16: * Chris@16: * \return The extracted value, if the attribute value is not empty and the value is the same Chris@16: * as specified. Otherwise returns the default value. See description of the \c result_of::extract_or_default Chris@16: * metafunction for information on the nature of the result value. Chris@16: */ Chris@16: template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT, typename DefaultT > Chris@16: typename result_of::extract_or_default< T, DefaultT, TagT >::type extract_or_default(DefaultT const& def_value) const; Chris@16: Chris@16: #if defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) Chris@16: /*! Chris@16: * The method attempts to extract the stored value, assuming the value has the specified type. Chris@16: * One can specify either a single type or an MPL type sequence, in which case the stored value Chris@16: * is checked against every type in the sequence. Chris@16: * Chris@16: * \note Include value_extraction.hpp prior to using this method. Chris@16: * Chris@16: * \return The extracted value, if the attribute value is not empty and the value is the same Chris@16: * as specified. Otherwise returns an empty value. See description of the \c result_of::extract Chris@16: * metafunction for information on the nature of the result value. Chris@16: */ Chris@16: template< typename T > Chris@16: typename result_of::extract< T >::type extract() const; Chris@16: Chris@16: /*! Chris@16: * The method attempts to extract the stored value, assuming the value has the specified type. Chris@16: * One can specify either a single type or an MPL type sequence, in which case the stored value Chris@16: * is checked against every type in the sequence. Chris@16: * Chris@16: * \note Include value_extraction.hpp prior to using this method. Chris@16: * Chris@16: * \return The extracted value, if the attribute value is not empty and the value is the same Chris@16: * as specified. Otherwise an exception is thrown. See description of the \c result_of::extract_or_throw Chris@16: * metafunction for information on the nature of the result value. Chris@16: */ Chris@16: template< typename T > Chris@16: typename result_of::extract_or_throw< T >::type extract_or_throw() const; Chris@16: Chris@16: /*! Chris@16: * The method attempts to extract the stored value, assuming the value has the specified type. Chris@16: * One can specify either a single type or an MPL type sequence, in which case the stored value Chris@16: * is checked against every type in the sequence. If extraction fails, the default value is returned. Chris@16: * Chris@16: * \note Include value_extraction.hpp prior to using this method. Chris@16: * Chris@16: * \param def_value Default value. Chris@16: * Chris@16: * \return The extracted value, if the attribute value is not empty and the value is the same Chris@16: * as specified. Otherwise returns the default value. See description of the \c result_of::extract_or_default Chris@16: * metafunction for information on the nature of the result value. Chris@16: */ Chris@16: template< typename T > Chris@16: typename result_of::extract_or_default< T, T >::type extract_or_default(T const& def_value) const; Chris@16: Chris@16: /*! Chris@16: * The method attempts to extract the stored value, assuming the value has the specified type. Chris@16: * One can specify either a single type or an MPL type sequence, in which case the stored value Chris@16: * is checked against every type in the sequence. If extraction fails, the default value is returned. Chris@16: * Chris@16: * \note Include value_extraction.hpp prior to using this method. Chris@16: * Chris@16: * \param def_value Default value. Chris@16: * Chris@16: * \return The extracted value, if the attribute value is not empty and the value is the same Chris@16: * as specified. Otherwise returns the default value. See description of the \c result_of::extract_or_default Chris@16: * metafunction for information on the nature of the result value. Chris@16: */ Chris@16: template< typename T, typename DefaultT > Chris@16: typename result_of::extract_or_default< T, DefaultT >::type extract_or_default(DefaultT const& def_value) const; Chris@16: #endif // defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) Chris@16: Chris@16: #undef BOOST_LOG_AUX_VOID_DEFAULT Chris@16: Chris@16: /*! Chris@16: * The method attempts to extract the stored value, assuming the value has the specified type, Chris@16: * and pass it to the \a visitor function object. Chris@16: * One can specify either a single type or an MPL type sequence, in which case the stored value Chris@16: * is checked against every type in the sequence. Chris@16: * Chris@16: * \note Include value_visitation.hpp prior to using this method. Chris@16: * Chris@16: * \param visitor A function object that will be invoked on the extracted attribute value. Chris@16: * The visitor should be capable to be called with a single argument of Chris@16: * any type of the specified types in \c T. Chris@16: * Chris@16: * \return The result of visitation. Chris@16: */ Chris@16: template< typename T, typename VisitorT > Chris@16: visitation_result visit(VisitorT visitor) const; Chris@16: Chris@16: /*! Chris@16: * The method swaps two attribute values Chris@16: */ Chris@16: void swap(attribute_value& that) BOOST_NOEXCEPT Chris@16: { Chris@16: m_pImpl.swap(that.m_pImpl); Chris@16: } Chris@16: }; Chris@16: Chris@16: /*! Chris@16: * The function swaps two attribute values Chris@16: */ Chris@16: inline void swap(attribute_value& left, attribute_value& right) BOOST_NOEXCEPT Chris@16: { Chris@16: left.swap(right); Chris@16: } Chris@16: Chris@16: BOOST_LOG_CLOSE_NAMESPACE // namespace log Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: #include Chris@16: #if defined(BOOST_LOG_ATTRIBUTES_ATTRIBUTE_HPP_INCLUDED_) Chris@16: #include Chris@16: #endif Chris@16: Chris@16: #endif // BOOST_LOG_ATTRIBUTE_VALUE_HPP_INCLUDED_