attribute_value_set.hpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. /*
  2. * Copyright Andrey Semashev 2007 - 2015.
  3. * Distributed under the Boost Software License, Version 1.0.
  4. * (See accompanying file LICENSE_1_0.txt or copy at
  5. * http://www.boost.org/LICENSE_1_0.txt)
  6. */
  7. /*!
  8. * \file attribute_value_set.hpp
  9. * \author Andrey Semashev
  10. * \date 21.04.2007
  11. *
  12. * This header file contains definition of attribute value set. The set is constructed from
  13. * three attribute sets (global, thread-specific and source-specific) and contains attribute
  14. * values.
  15. */
  16. #ifndef BOOST_LOG_ATTRIBUTE_VALUE_SET_HPP_INCLUDED_
  17. #define BOOST_LOG_ATTRIBUTE_VALUE_SET_HPP_INCLUDED_
  18. #include <cstddef>
  19. #include <utility>
  20. #include <iterator>
  21. #include <boost/move/core.hpp>
  22. #include <boost/log/detail/config.hpp>
  23. #include <boost/log/attributes/attribute_name.hpp>
  24. #include <boost/log/attributes/attribute.hpp>
  25. #include <boost/log/attributes/attribute_value.hpp>
  26. #include <boost/log/attributes/attribute_set.hpp>
  27. #include <boost/log/expressions/keyword_fwd.hpp>
  28. #include <boost/log/detail/header.hpp>
  29. #ifdef BOOST_HAS_PRAGMA_ONCE
  30. #pragma once
  31. #endif
  32. namespace boost {
  33. BOOST_LOG_OPEN_NAMESPACE
  34. /*!
  35. * \brief A set of attribute values
  36. *
  37. * The set of attribute values is an associative container with attribute name as a key and
  38. * a pointer to attribute value object as a mapped type. This is a collection of elements with unique
  39. * keys, that is, there can be only one attribute value with a given name in the set. With respect to
  40. * read-only capabilities, the set interface is close to \c std::unordered_map.
  41. *
  42. * The set is designed to be only capable of adding elements to it. Once added, the attribute value
  43. * cannot be removed from the set.
  44. *
  45. * An instance of attribute value set can be constructed from three attribute sets. The constructor attempts to
  46. * accommodate values of all attributes from the sets. The situation when a same-named attribute is found
  47. * in more than one attribute set is possible. This problem is solved on construction of the value set: the three
  48. * attribute sets have different priorities when it comes to solving conflicts.
  49. *
  50. * From the library perspective the three source attribute sets are global, thread-specific and source-specific
  51. * attributes, with the latter having the highest priority. This feature allows to override attributes of wider scopes
  52. * with the more specific ones.
  53. *
  54. * For sake of performance, the attribute values are not immediately acquired from attribute sets at construction.
  55. * Instead, on-demand acquisition is performed either on iterator dereferencing or on call to the \c freeze method.
  56. * Once acquired, the attribute value stays within the set until its destruction. This nuance does not affect
  57. * other set properties, such as size or lookup ability. The logging core automatically freezes the set
  58. * at the right point, so users should not be bothered unless they manually create attribute value sets.
  59. *
  60. * \note The attribute sets that were used for the value set construction must not be modified or destroyed
  61. * until the value set is frozen. Otherwise the behavior is undefined.
  62. */
  63. class attribute_value_set
  64. {
  65. BOOST_COPYABLE_AND_MOVABLE_ALT(attribute_value_set)
  66. public:
  67. //! Key type
  68. typedef attribute_name key_type;
  69. //! Mapped attribute type
  70. typedef attribute_value mapped_type;
  71. //! Value type
  72. typedef std::pair< const key_type, mapped_type > value_type;
  73. //! Reference type
  74. typedef value_type& reference;
  75. //! Const reference type
  76. typedef value_type const& const_reference;
  77. //! Pointer type
  78. typedef value_type* pointer;
  79. //! Const pointer type
  80. typedef value_type const* const_pointer;
  81. //! Size type
  82. typedef std::size_t size_type;
  83. //! Pointer difference type
  84. typedef std::ptrdiff_t difference_type;
  85. #ifndef BOOST_LOG_DOXYGEN_PASS
  86. private:
  87. struct implementation;
  88. friend struct implementation;
  89. //! A base class for the container nodes
  90. struct node_base
  91. {
  92. node_base* m_pPrev;
  93. node_base* m_pNext;
  94. node_base();
  95. BOOST_DELETED_FUNCTION(node_base(node_base const&))
  96. BOOST_DELETED_FUNCTION(node_base& operator= (node_base const&))
  97. };
  98. //! Container elements
  99. struct node;
  100. friend struct node;
  101. struct node :
  102. public node_base
  103. {
  104. value_type m_Value;
  105. bool m_DynamicallyAllocated;
  106. node(key_type const& key, mapped_type& data, bool dynamic);
  107. };
  108. public:
  109. class const_iterator;
  110. friend class const_iterator;
  111. class const_iterator
  112. {
  113. public:
  114. // Standard typedefs
  115. typedef attribute_value_set::difference_type difference_type;
  116. typedef attribute_value_set::value_type value_type;
  117. typedef attribute_value_set::const_reference reference;
  118. typedef attribute_value_set::const_pointer pointer;
  119. typedef std::bidirectional_iterator_tag iterator_category;
  120. public:
  121. // Constructors
  122. BOOST_CONSTEXPR const_iterator() : m_pNode(NULL), m_pContainer(NULL) {}
  123. explicit const_iterator(node_base* n, attribute_value_set* cont) BOOST_NOEXCEPT :
  124. m_pNode(n),
  125. m_pContainer(cont)
  126. {
  127. }
  128. // Comparison
  129. bool operator== (const_iterator const& that) const BOOST_NOEXCEPT
  130. {
  131. return (m_pNode == that.m_pNode);
  132. }
  133. bool operator!= (const_iterator const& that) const BOOST_NOEXCEPT
  134. {
  135. return (m_pNode != that.m_pNode);
  136. }
  137. // Modification
  138. const_iterator& operator++ ()
  139. {
  140. m_pContainer->freeze();
  141. m_pNode = m_pNode->m_pNext;
  142. return *this;
  143. }
  144. const_iterator& operator-- ()
  145. {
  146. m_pContainer->freeze();
  147. m_pNode = m_pNode->m_pPrev;
  148. return *this;
  149. }
  150. const_iterator operator++ (int)
  151. {
  152. const_iterator tmp(*this);
  153. m_pContainer->freeze();
  154. m_pNode = m_pNode->m_pNext;
  155. return tmp;
  156. }
  157. const_iterator operator-- (int)
  158. {
  159. const_iterator tmp(*this);
  160. m_pContainer->freeze();
  161. m_pNode = m_pNode->m_pPrev;
  162. return tmp;
  163. }
  164. // Dereferencing
  165. pointer operator-> () const BOOST_NOEXCEPT { return &(static_cast< node* >(m_pNode)->m_Value); }
  166. reference operator* () const BOOST_NOEXCEPT { return static_cast< node* >(m_pNode)->m_Value; }
  167. private:
  168. node_base* m_pNode;
  169. attribute_value_set* m_pContainer;
  170. };
  171. #else
  172. /*!
  173. * Constant iterator type with bidirectional capabilities.
  174. */
  175. typedef implementation_defined const_iterator;
  176. #endif // BOOST_LOG_DOXYGEN_PASS
  177. private:
  178. //! Pointer to the container implementation
  179. implementation* m_pImpl;
  180. public:
  181. /*!
  182. * Default constructor
  183. *
  184. * The constructor creates an empty set which can be filled later by subsequent
  185. * calls of \c insert method. Optionally, the amount of storage reserved for elements
  186. * to be inserted may be passed to the constructor.
  187. * The constructed set is frozen.
  188. *
  189. * \param reserve_count Number of elements to reserve space for.
  190. */
  191. BOOST_LOG_API explicit attribute_value_set(size_type reserve_count = 8);
  192. /*!
  193. * Move constructor
  194. */
  195. attribute_value_set(BOOST_RV_REF(attribute_value_set) that) BOOST_NOEXCEPT : m_pImpl(that.m_pImpl)
  196. {
  197. that.m_pImpl = NULL;
  198. }
  199. /*!
  200. * The constructor adopts three attribute sets into the value set.
  201. * The \a source_attrs attributes have the greatest preference when a same-named
  202. * attribute is found in several sets, \a global_attrs has the least.
  203. * The constructed set is not frozen.
  204. *
  205. * \param source_attrs A set of source-specific attributes.
  206. * \param thread_attrs A set of thread-specific attributes.
  207. * \param global_attrs A set of global attributes.
  208. * \param reserve_count Amount of elements to reserve space for, in addition to the elements in the three attribute sets provided.
  209. */
  210. BOOST_LOG_API attribute_value_set(
  211. attribute_set const& source_attrs,
  212. attribute_set const& thread_attrs,
  213. attribute_set const& global_attrs,
  214. size_type reserve_count = 8);
  215. /*!
  216. * The constructor adopts three attribute sets into the value set.
  217. * The \a source_attrs attributes have the greatest preference when a same-named
  218. * attribute is found in several sets, \a global_attrs has the least.
  219. * The constructed set is not frozen.
  220. *
  221. * \pre The \a source_attrs set is frozen.
  222. *
  223. * \param source_attrs A set of source-specific attributes.
  224. * \param thread_attrs A set of thread-specific attributes.
  225. * \param global_attrs A set of global attributes.
  226. * \param reserve_count Amount of elements to reserve space for, in addition to the elements in the three attribute sets provided.
  227. */
  228. BOOST_LOG_API attribute_value_set(
  229. attribute_value_set const& source_attrs,
  230. attribute_set const& thread_attrs,
  231. attribute_set const& global_attrs,
  232. size_type reserve_count = 8);
  233. /*!
  234. * The constructor adopts three attribute sets into the value set.
  235. * The \a source_attrs attributes have the greatest preference when a same-named
  236. * attribute is found in several sets, \a global_attrs has the least.
  237. * The constructed set is not frozen.
  238. *
  239. * \pre The \a source_attrs set is frozen.
  240. *
  241. * \param source_attrs A set of source-specific attributes.
  242. * \param thread_attrs A set of thread-specific attributes.
  243. * \param global_attrs A set of global attributes.
  244. * \param reserve_count Amount of elements to reserve space for, in addition to the elements in the three attribute sets provided.
  245. */
  246. attribute_value_set(
  247. BOOST_RV_REF(attribute_value_set) source_attrs,
  248. attribute_set const& thread_attrs,
  249. attribute_set const& global_attrs,
  250. size_type reserve_count = 8) : m_pImpl(NULL)
  251. {
  252. construct(static_cast< attribute_value_set& >(source_attrs), thread_attrs, global_attrs, reserve_count);
  253. }
  254. /*!
  255. * Copy constructor.
  256. *
  257. * \pre The original set is frozen.
  258. * \post The constructed set is frozen, <tt>std::equal(begin(), end(), that.begin()) == true</tt>
  259. */
  260. BOOST_LOG_API attribute_value_set(attribute_value_set const& that);
  261. /*!
  262. * Destructor. Releases all referenced attribute values.
  263. */
  264. BOOST_LOG_API ~attribute_value_set() BOOST_NOEXCEPT;
  265. /*!
  266. * Assignment operator
  267. */
  268. attribute_value_set& operator= (attribute_value_set that) BOOST_NOEXCEPT
  269. {
  270. this->swap(that);
  271. return *this;
  272. }
  273. /*!
  274. * Swaps two sets
  275. *
  276. * \b Throws: Nothing.
  277. */
  278. void swap(attribute_value_set& that) BOOST_NOEXCEPT
  279. {
  280. implementation* const p = m_pImpl;
  281. m_pImpl = that.m_pImpl;
  282. that.m_pImpl = p;
  283. }
  284. /*!
  285. * \return Iterator to the first element of the set.
  286. */
  287. BOOST_LOG_API const_iterator begin() const;
  288. /*!
  289. * \return Iterator to the after-the-last element of the set.
  290. */
  291. BOOST_LOG_API const_iterator end() const;
  292. /*!
  293. * \return Number of elements in the set.
  294. */
  295. BOOST_LOG_API size_type size() const;
  296. /*!
  297. * \return \c true if there are no elements in the container, \c false otherwise.
  298. */
  299. bool empty() const { return (this->size() == 0); }
  300. /*!
  301. * The method finds the attribute value by name.
  302. *
  303. * \param key Attribute name.
  304. * \return Iterator to the found element or \c end() if the attribute with such name is not found.
  305. */
  306. BOOST_LOG_API const_iterator find(key_type key) const;
  307. /*!
  308. * Alternative lookup syntax.
  309. *
  310. * \param key Attribute name.
  311. * \return A pointer to the attribute value if it is found with \a key, default-constructed mapped value otherwise.
  312. */
  313. mapped_type operator[] (key_type key) const
  314. {
  315. const_iterator it = this->find(key);
  316. if (it != this->end())
  317. return it->second;
  318. else
  319. return mapped_type();
  320. }
  321. /*!
  322. * Alternative lookup syntax.
  323. *
  324. * \param keyword Attribute keyword.
  325. * \return A \c value_ref with extracted attribute value if it is found, empty \c value_ref otherwise.
  326. */
  327. template< typename DescriptorT, template< typename > class ActorT >
  328. typename result_of::extract< typename expressions::attribute_keyword< DescriptorT, ActorT >::value_type, DescriptorT >::type
  329. operator[] (expressions::attribute_keyword< DescriptorT, ActorT > const& keyword) const
  330. {
  331. typedef typename expressions::attribute_keyword< DescriptorT, ActorT >::value_type attr_value_type;
  332. typedef typename result_of::extract< attr_value_type, DescriptorT >::type result_type;
  333. const_iterator it = this->find(keyword.get_name());
  334. if (it != this->end())
  335. return it->second.extract< attr_value_type, DescriptorT >();
  336. else
  337. return result_type();
  338. }
  339. /*!
  340. * The method counts the number of the attribute value occurrences in the set. Since there can be only one
  341. * attribute value with a particular key, the method always return 0 or 1.
  342. *
  343. * \param key Attribute name.
  344. * \return The number of times the attribute value is found in the container.
  345. */
  346. size_type count(key_type key) const { return size_type(this->find(key) != this->end()); }
  347. /*!
  348. * The method acquires values of all adopted attributes.
  349. *
  350. * \post The set is frozen.
  351. */
  352. BOOST_LOG_API void freeze();
  353. /*!
  354. * Inserts an element into the set. The complexity of the operation is amortized constant.
  355. *
  356. * \pre The set is frozen.
  357. *
  358. * \param key The attribute name.
  359. * \param mapped The attribute value.
  360. *
  361. * \returns An iterator to the inserted element and \c true if insertion succeeded. Otherwise,
  362. * if the set already contains a same-named attribute value, iterator to the
  363. * existing element and \c false.
  364. */
  365. BOOST_LOG_API std::pair< const_iterator, bool > insert(key_type key, mapped_type const& mapped);
  366. /*!
  367. * Inserts an element into the set. The complexity of the operation is amortized constant.
  368. *
  369. * \pre The set is frozen.
  370. *
  371. * \param value The attribute name and value.
  372. *
  373. * \returns An iterator to the inserted element and \c true if insertion succeeded. Otherwise,
  374. * if the set already contains a same-named attribute value, iterator to the
  375. * existing element and \c false.
  376. */
  377. std::pair< const_iterator, bool > insert(const_reference value) { return this->insert(value.first, value.second); }
  378. /*!
  379. * Mass insertion method. The complexity of the operation is linear to the number of elements inserted.
  380. *
  381. * \pre The set is frozen.
  382. *
  383. * \param begin A forward iterator that points to the first element to be inserted.
  384. * \param end A forward iterator that points to the after-the-last element to be inserted.
  385. */
  386. template< typename FwdIteratorT >
  387. void insert(FwdIteratorT begin, FwdIteratorT end)
  388. {
  389. for (; begin != end; ++begin)
  390. this->insert(*begin);
  391. }
  392. /*!
  393. * Mass insertion method with ability to acquire iterators to the inserted elements.
  394. * The complexity of the operation is linear to the number of elements inserted times the complexity
  395. * of filling the \a out iterator.
  396. *
  397. * \pre The set is frozen.
  398. *
  399. * \param begin A forward iterator that points to the first element to be inserted.
  400. * \param end A forward iterator that points to the after-the-last element to be inserted.
  401. * \param out An output iterator that receives results of insertion of the elements.
  402. */
  403. template< typename FwdIteratorT, typename OutputIteratorT >
  404. void insert(FwdIteratorT begin, FwdIteratorT end, OutputIteratorT out)
  405. {
  406. for (; begin != end; ++begin, ++out)
  407. *out = this->insert(*begin);
  408. }
  409. #ifndef BOOST_LOG_DOXYGEN_PASS
  410. private:
  411. //! Constructs the object by moving from \a source_attrs. This function is mostly needed to maintain ABI stable between C++03 and C++11.
  412. BOOST_LOG_API void construct(
  413. attribute_value_set& source_attrs,
  414. attribute_set const& thread_attrs,
  415. attribute_set const& global_attrs,
  416. size_type reserve_count);
  417. #endif // BOOST_LOG_DOXYGEN_PASS
  418. };
  419. /*!
  420. * Free swap overload
  421. */
  422. inline void swap(attribute_value_set& left, attribute_value_set& right) BOOST_NOEXCEPT
  423. {
  424. left.swap(right);
  425. }
  426. BOOST_LOG_CLOSE_NAMESPACE // namespace log
  427. } // namespace boost
  428. #include <boost/log/detail/footer.hpp>
  429. #endif // BOOST_LOG_ATTRIBUTE_VALUE_SET_HPP_INCLUDED_