Back to home page

EIC code displayed by LXR

 
 

    


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

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   attribute_value.hpp
0009  * \author Andrey Semashev
0010  * \date   21.05.2010
0011  *
0012  * The header contains \c attribute_value class definition.
0013  */
0014 
0015 #ifndef BOOST_LOG_ATTRIBUTE_VALUE_HPP_INCLUDED_
0016 #define BOOST_LOG_ATTRIBUTE_VALUE_HPP_INCLUDED_
0017 
0018 #include <boost/type_index.hpp>
0019 #include <boost/move/core.hpp>
0020 #include <boost/smart_ptr/intrusive_ptr.hpp>
0021 #include <boost/core/explicit_operator_bool.hpp>
0022 #include <boost/log/detail/config.hpp>
0023 #include <boost/log/utility/type_dispatch/type_dispatcher.hpp>
0024 #include <boost/log/attributes/attribute.hpp>
0025 #include <boost/log/attributes/value_extraction_fwd.hpp>
0026 #include <boost/log/attributes/value_visitation_fwd.hpp>
0027 #include <boost/log/detail/header.hpp>
0028 
0029 #ifdef BOOST_HAS_PRAGMA_ONCE
0030 #pragma once
0031 #endif
0032 
0033 namespace boost {
0034 
0035 BOOST_LOG_OPEN_NAMESPACE
0036 
0037 /*!
0038  * \brief An attribute value class
0039  *
0040  * An attribute value is an object that contains a piece of data that represents an attribute state
0041  * at the point of the value acquisition. All major operations with log records, such as filtering and
0042  * formatting, involve attribute values contained in a single view. Most likely an attribute value is
0043  * implemented as a simple holder of some typed value. This holder implements the
0044  * \c attribute_value::implementation interface and acts as a pimpl for the \c attribute_value
0045  * object. The \c attribute_value class provides type dispatching support in order to allow
0046  * to extract the value from the holder.
0047  *
0048  * Normally, attributes and their values shall be designed in order to exclude as much interference as
0049  * reasonable. Such approach allows to have more than one attribute value simultaneously, which improves
0050  * scalability and allows to implement generating attributes.
0051  *
0052  * However, there are cases when this approach does not help to achieve the required level of independency
0053  * of attribute values and attribute itself from each other at a reasonable performance tradeoff.
0054  * For example, an attribute or its values may use thread-specific data, which is global and shared
0055  * between all the instances of the attribute/value. Passing such an attribute value to another thread
0056  * would be a disaster. To solve this the library defines an additional method for attribute values,
0057  * namely \c detach_from_thread. The \c attribute_value class forwards the call to its pimpl,
0058  * which is supposed to ensure that it no longer refers to any thread-specific data after the call.
0059  * The pimpl can create a new holder as a result of this method and return it to the \c attribute_value
0060  * wrapper, which will keep the returned reference for any further calls.
0061  * This method is called for all attribute values that are passed to another thread.
0062  */
0063 class attribute_value
0064 {
0065     BOOST_COPYABLE_AND_MOVABLE(attribute_value)
0066 
0067 public:
0068     /*!
0069      * \brief A base class for an attribute value implementation
0070      *
0071      * All attribute value holders should derive from this interface.
0072      */
0073     struct BOOST_LOG_NO_VTABLE impl :
0074         public attribute::impl
0075     {
0076     public:
0077         /*!
0078          * The method dispatches the value to the given object.
0079          *
0080          * \param dispatcher The object that attempts to dispatch the stored value.
0081          * \return true if \a dispatcher was capable to consume the real attribute value type and false otherwise.
0082          */
0083         virtual bool dispatch(type_dispatcher& dispatcher) = 0;
0084 
0085         /*!
0086          * The method is called when the attribute value is passed to another thread (e.g.
0087          * in case of asynchronous logging). The value should ensure it properly owns all thread-specific data.
0088          *
0089          * \return An actual pointer to the attribute value. It may either point to this object or another.
0090          *         In the latter case the returned pointer replaces the pointer used by caller to invoke this
0091          *         method and is considered to be a functional equivalent to the previous pointer.
0092          */
0093         virtual intrusive_ptr< impl > detach_from_thread()
0094         {
0095             return this;
0096         }
0097 
0098         /*!
0099          * \return The attribute value that refers to self implementation.
0100          */
0101         attribute_value get_value() BOOST_OVERRIDE { return attribute_value(this); }
0102 
0103         /*!
0104          * \return The attribute value type
0105          */
0106         virtual typeindex::type_index get_type() const { return typeindex::type_index(); }
0107     };
0108 
0109 private:
0110     //! Pointer to the value implementation
0111     intrusive_ptr< impl > m_pImpl;
0112 
0113 public:
0114     /*!
0115      * Default constructor. Creates an empty (absent) attribute value.
0116      */
0117     BOOST_DEFAULTED_FUNCTION(attribute_value(), BOOST_NOEXCEPT {})
0118 
0119     /*!
0120      * Copy constructor
0121      */
0122     attribute_value(attribute_value const& that) BOOST_NOEXCEPT : m_pImpl(that.m_pImpl) {}
0123 
0124     /*!
0125      * Move constructor
0126      */
0127     attribute_value(BOOST_RV_REF(attribute_value) that) BOOST_NOEXCEPT { m_pImpl.swap(that.m_pImpl); }
0128 
0129     /*!
0130      * Initializing constructor. Creates an attribute value that refers to the specified holder.
0131      *
0132      * \param p A pointer to the attribute value holder.
0133      */
0134     explicit attribute_value(intrusive_ptr< impl > p) BOOST_NOEXCEPT { m_pImpl.swap(p); }
0135 
0136     /*!
0137      * Copy assignment
0138      */
0139     attribute_value& operator= (BOOST_COPY_ASSIGN_REF(attribute_value) that) BOOST_NOEXCEPT
0140     {
0141         m_pImpl = that.m_pImpl;
0142         return *this;
0143     }
0144 
0145     /*!
0146      * Move assignment
0147      */
0148     attribute_value& operator= (BOOST_RV_REF(attribute_value) that) BOOST_NOEXCEPT
0149     {
0150         m_pImpl.swap(that.m_pImpl);
0151         return *this;
0152     }
0153 
0154     /*!
0155      * The operator checks if the attribute value is empty
0156      */
0157     BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
0158     /*!
0159      * The operator checks if the attribute value is empty
0160      */
0161     bool operator! () const BOOST_NOEXCEPT { return !m_pImpl; }
0162 
0163     /*!
0164      * The method returns the type information of the stored value of the attribute.
0165      * The returned type info wrapper may be empty if the attribute value is empty or
0166      * the information cannot be provided. If the returned value is not empty, the type
0167      * can be used for value extraction.
0168      */
0169     typeindex::type_index get_type() const
0170     {
0171         if (m_pImpl.get())
0172             return m_pImpl->get_type();
0173         else
0174             return typeindex::type_index();
0175     }
0176 
0177     /*!
0178      * The method is called when the attribute value is passed to another thread (e.g.
0179      * in case of asynchronous logging). The value should ensure it properly owns all thread-specific data.
0180      *
0181      * \post The attribute value no longer refers to any thread-specific resources.
0182      */
0183     void detach_from_thread()
0184     {
0185         if (m_pImpl.get())
0186             m_pImpl->detach_from_thread().swap(m_pImpl);
0187     }
0188 
0189     /*!
0190      * The method dispatches the value to the given object. This method is a low level interface for
0191      * attribute value visitation and extraction. For typical usage these interfaces may be more convenient.
0192      *
0193      * \param dispatcher The object that attempts to dispatch the stored value.
0194      * \return \c true if the value is not empty and the \a dispatcher was capable to consume
0195      *         the real attribute value type and \c false otherwise.
0196      */
0197     bool dispatch(type_dispatcher& dispatcher) const
0198     {
0199         if (m_pImpl.get())
0200             return m_pImpl->dispatch(dispatcher);
0201         else
0202             return false;
0203     }
0204 
0205 #if !defined(BOOST_LOG_DOXYGEN_PASS)
0206 #if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
0207 #define BOOST_LOG_AUX_VOID_DEFAULT = void
0208 #else
0209 #define BOOST_LOG_AUX_VOID_DEFAULT
0210 #endif
0211 #endif // !defined(BOOST_LOG_DOXYGEN_PASS)
0212 
0213     /*!
0214      * The method attempts to extract the stored value, assuming the value has the specified type.
0215      * One can specify either a single type or an MPL type sequence, in which case the stored value
0216      * is checked against every type in the sequence.
0217      *
0218      * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
0219      *
0220      * \return The extracted value, if the attribute value is not empty and the value is the same
0221      *         as specified. Otherwise returns an empty value. See description of the \c result_of::extract
0222      *         metafunction for information on the nature of the result value.
0223      */
0224     template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT >
0225     typename result_of::extract< T, TagT >::type extract() const;
0226 
0227     /*!
0228      * The method attempts to extract the stored value, assuming the value has the specified type.
0229      * One can specify either a single type or an MPL type sequence, in which case the stored value
0230      * is checked against every type in the sequence.
0231      *
0232      * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
0233      *
0234      * \return The extracted value, if the attribute value is not empty and the value is the same
0235      *         as specified. Otherwise an exception is thrown. See description of the \c result_of::extract_or_throw
0236      *         metafunction for information on the nature of the result value.
0237      */
0238     template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT >
0239     typename result_of::extract_or_throw< T, TagT >::type extract_or_throw() const;
0240 
0241     /*!
0242      * The method attempts to extract the stored value, assuming the value has the specified type.
0243      * One can specify either a single type or an MPL type sequence, in which case the stored value
0244      * is checked against every type in the sequence. If extraction fails, the default value is returned.
0245      *
0246      * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
0247      *
0248      * \param def_value Default value.
0249      *
0250      * \return The extracted value, if the attribute value is not empty and the value is the same
0251      *         as specified. Otherwise returns the default value. See description of the \c result_of::extract_or_default
0252      *         metafunction for information on the nature of the result value.
0253      */
0254     template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT >
0255     typename result_of::extract_or_default< T, T, TagT >::type extract_or_default(T const& def_value) const;
0256 
0257     /*!
0258      * The method attempts to extract the stored value, assuming the value has the specified type.
0259      * One can specify either a single type or an MPL type sequence, in which case the stored value
0260      * is checked against every type in the sequence. If extraction fails, the default value is returned.
0261      *
0262      * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
0263      *
0264      * \param def_value Default value.
0265      *
0266      * \return The extracted value, if the attribute value is not empty and the value is the same
0267      *         as specified. Otherwise returns the default value. See description of the \c result_of::extract_or_default
0268      *         metafunction for information on the nature of the result value.
0269      */
0270     template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT, typename DefaultT >
0271     typename result_of::extract_or_default< T, DefaultT, TagT >::type extract_or_default(DefaultT const& def_value) const;
0272 
0273 #if defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
0274     /*!
0275      * The method attempts to extract the stored value, assuming the value has the specified type.
0276      * One can specify either a single type or an MPL type sequence, in which case the stored value
0277      * is checked against every type in the sequence.
0278      *
0279      * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
0280      *
0281      * \return The extracted value, if the attribute value is not empty and the value is the same
0282      *         as specified. Otherwise returns an empty value. See description of the \c result_of::extract
0283      *         metafunction for information on the nature of the result value.
0284      */
0285     template< typename T >
0286     typename result_of::extract< T >::type extract() const;
0287 
0288     /*!
0289      * The method attempts to extract the stored value, assuming the value has the specified type.
0290      * One can specify either a single type or an MPL type sequence, in which case the stored value
0291      * is checked against every type in the sequence.
0292      *
0293      * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
0294      *
0295      * \return The extracted value, if the attribute value is not empty and the value is the same
0296      *         as specified. Otherwise an exception is thrown. See description of the \c result_of::extract_or_throw
0297      *         metafunction for information on the nature of the result value.
0298      */
0299     template< typename T >
0300     typename result_of::extract_or_throw< T >::type extract_or_throw() const;
0301 
0302     /*!
0303      * The method attempts to extract the stored value, assuming the value has the specified type.
0304      * One can specify either a single type or an MPL type sequence, in which case the stored value
0305      * is checked against every type in the sequence. If extraction fails, the default value is returned.
0306      *
0307      * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
0308      *
0309      * \param def_value Default value.
0310      *
0311      * \return The extracted value, if the attribute value is not empty and the value is the same
0312      *         as specified. Otherwise returns the default value. See description of the \c result_of::extract_or_default
0313      *         metafunction for information on the nature of the result value.
0314      */
0315     template< typename T >
0316     typename result_of::extract_or_default< T, T >::type extract_or_default(T const& def_value) const;
0317 
0318     /*!
0319      * The method attempts to extract the stored value, assuming the value has the specified type.
0320      * One can specify either a single type or an MPL type sequence, in which case the stored value
0321      * is checked against every type in the sequence. If extraction fails, the default value is returned.
0322      *
0323      * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
0324      *
0325      * \param def_value Default value.
0326      *
0327      * \return The extracted value, if the attribute value is not empty and the value is the same
0328      *         as specified. Otherwise returns the default value. See description of the \c result_of::extract_or_default
0329      *         metafunction for information on the nature of the result value.
0330      */
0331     template< typename T, typename DefaultT >
0332     typename result_of::extract_or_default< T, DefaultT >::type extract_or_default(DefaultT const& def_value) const;
0333 #endif // defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
0334 
0335 #undef BOOST_LOG_AUX_VOID_DEFAULT
0336 
0337     /*!
0338      * The method attempts to extract the stored value, assuming the value has the specified type,
0339      * and pass it to the \a visitor function object.
0340      * One can specify either a single type or an MPL type sequence, in which case the stored value
0341      * is checked against every type in the sequence.
0342      *
0343      * \note Include <tt>value_visitation.hpp</tt> prior to using this method.
0344      *
0345      * \param visitor A function object that will be invoked on the extracted attribute value.
0346      *                The visitor should be capable to be called with a single argument of
0347      *                any type of the specified types in \c T.
0348      *
0349      * \return The result of visitation.
0350      */
0351     template< typename T, typename VisitorT >
0352     visitation_result visit(VisitorT visitor) const;
0353 
0354     /*!
0355      * The method swaps two attribute values
0356      */
0357     void swap(attribute_value& that) BOOST_NOEXCEPT
0358     {
0359         m_pImpl.swap(that.m_pImpl);
0360     }
0361 };
0362 
0363 /*!
0364  * The function swaps two attribute values
0365  */
0366 inline void swap(attribute_value& left, attribute_value& right) BOOST_NOEXCEPT
0367 {
0368     left.swap(right);
0369 }
0370 
0371 BOOST_LOG_CLOSE_NAMESPACE // namespace log
0372 
0373 } // namespace boost
0374 
0375 #include <boost/log/detail/footer.hpp>
0376 #if defined(BOOST_LOG_ATTRIBUTES_ATTRIBUTE_HPP_INCLUDED_)
0377 #include <boost/log/detail/attribute_get_value_impl.hpp>
0378 #endif
0379 
0380 #endif // BOOST_LOG_ATTRIBUTE_VALUE_HPP_INCLUDED_