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_set.hpp
0009  * \author Andrey Semashev
0010  * \date   21.04.2007
0011  *
0012  * This header file contains definition of attribute value set. The set is constructed from
0013  * three attribute sets (global, thread-specific and source-specific) and contains attribute
0014  * values.
0015  */
0016 
0017 #ifndef BOOST_LOG_ATTRIBUTE_VALUE_SET_HPP_INCLUDED_
0018 #define BOOST_LOG_ATTRIBUTE_VALUE_SET_HPP_INCLUDED_
0019 
0020 #include <cstddef>
0021 #include <utility>
0022 #include <iterator>
0023 #include <boost/move/core.hpp>
0024 #include <boost/log/detail/config.hpp>
0025 #include <boost/log/attributes/attribute_name.hpp>
0026 #include <boost/log/attributes/attribute.hpp>
0027 #include <boost/log/attributes/attribute_value.hpp>
0028 #include <boost/log/attributes/attribute_set.hpp>
0029 #include <boost/log/expressions/keyword_fwd.hpp>
0030 #include <boost/log/detail/header.hpp>
0031 
0032 #ifdef BOOST_HAS_PRAGMA_ONCE
0033 #pragma once
0034 #endif
0035 
0036 namespace boost {
0037 
0038 BOOST_LOG_OPEN_NAMESPACE
0039 
0040 /*!
0041  * \brief A set of attribute values
0042  *
0043  * The set of attribute values is an associative container with attribute name as a key and
0044  * a pointer to attribute value object as a mapped type. This is a collection of elements with unique
0045  * keys, that is, there can be only one attribute value with a given name in the set. With respect to
0046  * read-only capabilities, the set interface is close to \c std::unordered_map.
0047  *
0048  * The set is designed to be only capable of adding elements to it. Once added, the attribute value
0049  * cannot be removed from the set.
0050  *
0051  * An instance of attribute value set can be constructed from three attribute sets. The constructor attempts to
0052  * accommodate values of all attributes from the sets. The situation when a same-named attribute is found
0053  * in more than one attribute set is possible. This problem is solved on construction of the value set: the three
0054  * attribute sets have different priorities when it comes to solving conflicts.
0055  *
0056  * From the library perspective the three source attribute sets are global, thread-specific and source-specific
0057  * attributes, with the latter having the highest priority. This feature allows to override attributes of wider scopes
0058  * with the more specific ones.
0059  *
0060  * For sake of performance, the attribute values are not immediately acquired from attribute sets at construction.
0061  * Instead, on-demand acquisition is performed either on iterator dereferencing or on call to the \c freeze method.
0062  * Once acquired, the attribute value stays within the set until its destruction. This nuance does not affect
0063  * other set properties, such as size or lookup ability. The logging core automatically freezes the set
0064  * at the right point, so users should not be bothered unless they manually create attribute value sets.
0065  *
0066  * \note The attribute sets that were used for the value set construction must not be modified or destroyed
0067  *       until the value set is frozen. Otherwise the behavior is undefined.
0068  */
0069 class attribute_value_set
0070 {
0071     BOOST_COPYABLE_AND_MOVABLE_ALT(attribute_value_set)
0072 
0073 public:
0074     //! Key type
0075     typedef attribute_name key_type;
0076     //! Mapped attribute type
0077     typedef attribute_value mapped_type;
0078 
0079     //! Value type
0080     typedef std::pair< const key_type, mapped_type > value_type;
0081     //! Reference type
0082     typedef value_type& reference;
0083     //! Const reference type
0084     typedef value_type const& const_reference;
0085     //! Pointer type
0086     typedef value_type* pointer;
0087     //! Const pointer type
0088     typedef value_type const* const_pointer;
0089     //! Size type
0090     typedef std::size_t size_type;
0091     //! Pointer difference type
0092     typedef std::ptrdiff_t difference_type;
0093 
0094 #ifndef BOOST_LOG_DOXYGEN_PASS
0095 
0096 private:
0097     struct implementation;
0098     friend struct implementation;
0099 
0100     //! A base class for the container nodes
0101     struct node_base
0102     {
0103         node_base* m_pPrev;
0104         node_base* m_pNext;
0105 
0106         node_base();
0107 
0108         BOOST_DELETED_FUNCTION(node_base(node_base const&))
0109         BOOST_DELETED_FUNCTION(node_base& operator= (node_base const&))
0110     };
0111 
0112     //! Container elements
0113     struct node;
0114     friend struct node;
0115     struct node :
0116         public node_base
0117     {
0118         value_type m_Value;
0119         bool m_DynamicallyAllocated;
0120 
0121         node(key_type const& key, mapped_type& data, bool dynamic);
0122     };
0123 
0124 public:
0125     class const_iterator;
0126     friend class const_iterator;
0127     class const_iterator
0128     {
0129     public:
0130         //  Standard typedefs
0131         typedef attribute_value_set::difference_type difference_type;
0132         typedef attribute_value_set::value_type value_type;
0133         typedef attribute_value_set::const_reference reference;
0134         typedef attribute_value_set::const_pointer pointer;
0135         typedef std::bidirectional_iterator_tag iterator_category;
0136 
0137     public:
0138         //  Constructors
0139         BOOST_CONSTEXPR const_iterator() : m_pNode(NULL), m_pContainer(NULL) {}
0140         explicit const_iterator(node_base* n, attribute_value_set* cont) BOOST_NOEXCEPT :
0141             m_pNode(n),
0142             m_pContainer(cont)
0143         {
0144         }
0145 
0146         //  Comparison
0147         bool operator== (const_iterator const& that) const BOOST_NOEXCEPT
0148         {
0149             return (m_pNode == that.m_pNode);
0150         }
0151         bool operator!= (const_iterator const& that) const BOOST_NOEXCEPT
0152         {
0153             return (m_pNode != that.m_pNode);
0154         }
0155 
0156         //  Modification
0157         const_iterator& operator++ ()
0158         {
0159             m_pContainer->freeze();
0160             m_pNode = m_pNode->m_pNext;
0161             return *this;
0162         }
0163         const_iterator& operator-- ()
0164         {
0165             m_pContainer->freeze();
0166             m_pNode = m_pNode->m_pPrev;
0167             return *this;
0168         }
0169         const_iterator operator++ (int)
0170         {
0171             const_iterator tmp(*this);
0172             m_pContainer->freeze();
0173             m_pNode = m_pNode->m_pNext;
0174             return tmp;
0175         }
0176         const_iterator operator-- (int)
0177         {
0178             const_iterator tmp(*this);
0179             m_pContainer->freeze();
0180             m_pNode = m_pNode->m_pPrev;
0181             return tmp;
0182         }
0183 
0184         //  Dereferencing
0185         pointer operator-> () const BOOST_NOEXCEPT { return &(static_cast< node* >(m_pNode)->m_Value); }
0186         reference operator* () const BOOST_NOEXCEPT { return static_cast< node* >(m_pNode)->m_Value; }
0187 
0188     private:
0189         node_base* m_pNode;
0190         attribute_value_set* m_pContainer;
0191     };
0192 
0193 #else
0194 
0195     /*!
0196      * Constant iterator type with bidirectional capabilities.
0197      */
0198     typedef implementation_defined const_iterator;
0199 
0200 #endif // BOOST_LOG_DOXYGEN_PASS
0201 
0202 private:
0203     //! Pointer to the container implementation
0204     implementation* m_pImpl;
0205 
0206 public:
0207     /*!
0208      * Default constructor
0209      *
0210      * The constructor creates an empty set which can be filled later by subsequent
0211      * calls of \c insert method. Optionally, the amount of storage reserved for elements
0212      * to be inserted may be passed to the constructor.
0213      * The constructed set is frozen.
0214      *
0215      * \param reserve_count Number of elements to reserve space for.
0216      */
0217     BOOST_LOG_API explicit attribute_value_set(size_type reserve_count = 8);
0218 
0219     /*!
0220      * Move constructor
0221      */
0222     attribute_value_set(BOOST_RV_REF(attribute_value_set) that) BOOST_NOEXCEPT : m_pImpl(that.m_pImpl)
0223     {
0224         that.m_pImpl = NULL;
0225     }
0226 
0227     /*!
0228      * The constructor adopts three attribute sets into the value set.
0229      * The \a source_attrs attributes have the greatest preference when a same-named
0230      * attribute is found in several sets, \a global_attrs has the least.
0231      * The constructed set is not frozen.
0232      *
0233      * \param source_attrs A set of source-specific attributes.
0234      * \param thread_attrs A set of thread-specific attributes.
0235      * \param global_attrs A set of global attributes.
0236      * \param reserve_count Amount of elements to reserve space for, in addition to the elements in the three attribute sets provided.
0237      */
0238     BOOST_LOG_API attribute_value_set(
0239         attribute_set const& source_attrs,
0240         attribute_set const& thread_attrs,
0241         attribute_set const& global_attrs,
0242         size_type reserve_count = 8);
0243 
0244     /*!
0245      * The constructor adopts three attribute sets into the value set.
0246      * The \a source_attrs attributes have the greatest preference when a same-named
0247      * attribute is found in several sets, \a global_attrs has the least.
0248      * The constructed set is not frozen.
0249      *
0250      * \pre The \a source_attrs set is frozen.
0251      *
0252      * \param source_attrs A set of source-specific attributes.
0253      * \param thread_attrs A set of thread-specific attributes.
0254      * \param global_attrs A set of global attributes.
0255      * \param reserve_count Amount of elements to reserve space for, in addition to the elements in the three attribute sets provided.
0256      */
0257     BOOST_LOG_API attribute_value_set(
0258         attribute_value_set const& source_attrs,
0259         attribute_set const& thread_attrs,
0260         attribute_set const& global_attrs,
0261         size_type reserve_count = 8);
0262 
0263     /*!
0264      * The constructor adopts three attribute sets into the value set.
0265      * The \a source_attrs attributes have the greatest preference when a same-named
0266      * attribute is found in several sets, \a global_attrs has the least.
0267      * The constructed set is not frozen.
0268      *
0269      * \pre The \a source_attrs set is frozen.
0270      *
0271      * \param source_attrs A set of source-specific attributes.
0272      * \param thread_attrs A set of thread-specific attributes.
0273      * \param global_attrs A set of global attributes.
0274      * \param reserve_count Amount of elements to reserve space for, in addition to the elements in the three attribute sets provided.
0275      */
0276     attribute_value_set(
0277         BOOST_RV_REF(attribute_value_set) source_attrs,
0278         attribute_set const& thread_attrs,
0279         attribute_set const& global_attrs,
0280         size_type reserve_count = 8) : m_pImpl(NULL)
0281     {
0282         construct(static_cast< attribute_value_set& >(source_attrs), thread_attrs, global_attrs, reserve_count);
0283     }
0284 
0285     /*!
0286      * Copy constructor.
0287      *
0288      * \pre The original set is frozen.
0289      * \post The constructed set is frozen, <tt>std::equal(begin(), end(), that.begin()) == true</tt>
0290      */
0291     BOOST_LOG_API attribute_value_set(attribute_value_set const& that);
0292 
0293     /*!
0294      * Destructor. Releases all referenced attribute values.
0295      */
0296     BOOST_LOG_API ~attribute_value_set() BOOST_NOEXCEPT;
0297 
0298     /*!
0299      * Assignment operator
0300      */
0301     attribute_value_set& operator= (attribute_value_set that) BOOST_NOEXCEPT
0302     {
0303         this->swap(that);
0304         return *this;
0305     }
0306 
0307     /*!
0308      * Swaps two sets
0309      *
0310      * \b Throws: Nothing.
0311      */
0312     void swap(attribute_value_set& that) BOOST_NOEXCEPT
0313     {
0314         implementation* const p = m_pImpl;
0315         m_pImpl = that.m_pImpl;
0316         that.m_pImpl = p;
0317     }
0318 
0319     /*!
0320      * \return Iterator to the first element of the set.
0321      */
0322     BOOST_LOG_API const_iterator begin() const;
0323     /*!
0324      * \return Iterator to the after-the-last element of the set.
0325      */
0326     BOOST_LOG_API const_iterator end() const;
0327 
0328     /*!
0329      * \return Number of elements in the set.
0330      */
0331     BOOST_LOG_API size_type size() const;
0332     /*!
0333      * \return \c true if there are no elements in the container, \c false otherwise.
0334      */
0335     bool empty() const { return (this->size() == 0); }
0336 
0337     /*!
0338      * The method finds the attribute value by name.
0339      *
0340      * \param key Attribute name.
0341      * \return Iterator to the found element or \c end() if the attribute with such name is not found.
0342      */
0343     BOOST_LOG_API const_iterator find(key_type key) const;
0344 
0345     /*!
0346      * Alternative lookup syntax.
0347      *
0348      * \param key Attribute name.
0349      * \return A pointer to the attribute value if it is found with \a key, default-constructed mapped value otherwise.
0350      */
0351     mapped_type operator[] (key_type key) const
0352     {
0353         const_iterator it = this->find(key);
0354         if (it != this->end())
0355             return it->second;
0356         else
0357             return mapped_type();
0358     }
0359 
0360     /*!
0361      * Alternative lookup syntax.
0362      *
0363      * \param keyword Attribute keyword.
0364      * \return A \c value_ref with extracted attribute value if it is found, empty \c value_ref otherwise.
0365      */
0366     template< typename DescriptorT, template< typename > class ActorT >
0367     typename result_of::extract< typename expressions::attribute_keyword< DescriptorT, ActorT >::value_type, DescriptorT >::type
0368     operator[] (expressions::attribute_keyword< DescriptorT, ActorT > const& keyword) const
0369     {
0370         typedef typename expressions::attribute_keyword< DescriptorT, ActorT >::value_type attr_value_type;
0371         typedef typename result_of::extract< attr_value_type, DescriptorT >::type result_type;
0372         const_iterator it = this->find(keyword.get_name());
0373         if (it != this->end())
0374             return it->second.extract< attr_value_type, DescriptorT >();
0375         else
0376             return result_type();
0377     }
0378 
0379     /*!
0380      * The method counts the number of the attribute value occurrences in the set. Since there can be only one
0381      * attribute value with a particular key, the method always return 0 or 1.
0382      *
0383      * \param key Attribute name.
0384      * \return The number of times the attribute value is found in the container.
0385      */
0386     size_type count(key_type key) const { return size_type(this->find(key) != this->end()); }
0387 
0388     /*!
0389      * The method acquires values of all adopted attributes.
0390      *
0391      * \post The set is frozen.
0392      */
0393     BOOST_LOG_API void freeze();
0394 
0395     /*!
0396      * Inserts an element into the set. The complexity of the operation is amortized constant.
0397      *
0398      * \pre The set is frozen.
0399      *
0400      * \param key The attribute name.
0401      * \param mapped The attribute value.
0402      *
0403      * \returns An iterator to the inserted element and \c true if insertion succeeded. Otherwise,
0404      *          if the set already contains a same-named attribute value, iterator to the
0405      *          existing element and \c false.
0406      */
0407     BOOST_LOG_API std::pair< const_iterator, bool > insert(key_type key, mapped_type const& mapped);
0408 
0409     /*!
0410      * Inserts an element into the set. The complexity of the operation is amortized constant.
0411      *
0412      * \pre The set is frozen.
0413      *
0414      * \param value The attribute name and value.
0415      *
0416      * \returns An iterator to the inserted element and \c true if insertion succeeded. Otherwise,
0417      *          if the set already contains a same-named attribute value, iterator to the
0418      *          existing element and \c false.
0419      */
0420     std::pair< const_iterator, bool > insert(const_reference value) { return this->insert(value.first, value.second); }
0421 
0422     /*!
0423      * Mass insertion method. The complexity of the operation is linear to the number of elements inserted.
0424      *
0425      * \pre The set is frozen.
0426      *
0427      * \param begin A forward iterator that points to the first element to be inserted.
0428      * \param end A forward iterator that points to the after-the-last element to be inserted.
0429      */
0430     template< typename FwdIteratorT >
0431     void insert(FwdIteratorT begin, FwdIteratorT end)
0432     {
0433         for (; begin != end; ++begin)
0434             this->insert(*begin);
0435     }
0436 
0437     /*!
0438      * Mass insertion method with ability to acquire iterators to the inserted elements.
0439      * The complexity of the operation is linear to the number of elements inserted times the complexity
0440      * of filling the \a out iterator.
0441      *
0442      * \pre The set is frozen.
0443      *
0444      * \param begin A forward iterator that points to the first element to be inserted.
0445      * \param end A forward iterator that points to the after-the-last element to be inserted.
0446      * \param out An output iterator that receives results of insertion of the elements.
0447      */
0448     template< typename FwdIteratorT, typename OutputIteratorT >
0449     void insert(FwdIteratorT begin, FwdIteratorT end, OutputIteratorT out)
0450     {
0451         for (; begin != end; ++begin, ++out)
0452             *out = this->insert(*begin);
0453     }
0454 
0455 #ifndef BOOST_LOG_DOXYGEN_PASS
0456 private:
0457     //! Constructs the object by moving from \a source_attrs. This function is mostly needed to maintain ABI stable between C++03 and C++11.
0458     BOOST_LOG_API void construct(
0459         attribute_value_set& source_attrs,
0460         attribute_set const& thread_attrs,
0461         attribute_set const& global_attrs,
0462         size_type reserve_count);
0463 #endif // BOOST_LOG_DOXYGEN_PASS
0464 };
0465 
0466 /*!
0467  * Free swap overload
0468  */
0469 inline void swap(attribute_value_set& left, attribute_value_set& right) BOOST_NOEXCEPT
0470 {
0471     left.swap(right);
0472 }
0473 
0474 BOOST_LOG_CLOSE_NAMESPACE // namespace log
0475 
0476 } // namespace boost
0477 
0478 #include <boost/log/detail/footer.hpp>
0479 
0480 #endif // BOOST_LOG_ATTRIBUTE_VALUE_SET_HPP_INCLUDED_