attribute_value.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  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.hpp
  9. * \author Andrey Semashev
  10. * \date 21.05.2010
  11. *
  12. * The header contains \c attribute_value class definition.
  13. */
  14. #ifndef BOOST_LOG_ATTRIBUTE_VALUE_HPP_INCLUDED_
  15. #define BOOST_LOG_ATTRIBUTE_VALUE_HPP_INCLUDED_
  16. #include <boost/type_index.hpp>
  17. #include <boost/move/core.hpp>
  18. #include <boost/smart_ptr/intrusive_ptr.hpp>
  19. #include <boost/core/explicit_operator_bool.hpp>
  20. #include <boost/log/detail/config.hpp>
  21. #include <boost/log/utility/type_dispatch/type_dispatcher.hpp>
  22. #include <boost/log/attributes/attribute.hpp>
  23. #include <boost/log/attributes/value_extraction_fwd.hpp>
  24. #include <boost/log/attributes/value_visitation_fwd.hpp>
  25. #include <boost/log/detail/header.hpp>
  26. #ifdef BOOST_HAS_PRAGMA_ONCE
  27. #pragma once
  28. #endif
  29. namespace boost {
  30. BOOST_LOG_OPEN_NAMESPACE
  31. /*!
  32. * \brief An attribute value class
  33. *
  34. * An attribute value is an object that contains a piece of data that represents an attribute state
  35. * at the point of the value acquisition. All major operations with log records, such as filtering and
  36. * formatting, involve attribute values contained in a single view. Most likely an attribute value is
  37. * implemented as a simple holder of some typed value. This holder implements the
  38. * \c attribute_value::implementation interface and acts as a pimpl for the \c attribute_value
  39. * object. The \c attribute_value class provides type dispatching support in order to allow
  40. * to extract the value from the holder.
  41. *
  42. * Normally, attributes and their values shall be designed in order to exclude as much interference as
  43. * reasonable. Such approach allows to have more than one attribute value simultaneously, which improves
  44. * scalability and allows to implement generating attributes.
  45. *
  46. * However, there are cases when this approach does not help to achieve the required level of independency
  47. * of attribute values and attribute itself from each other at a reasonable performance tradeoff.
  48. * For example, an attribute or its values may use thread-specific data, which is global and shared
  49. * between all the instances of the attribute/value. Passing such an attribute value to another thread
  50. * would be a disaster. To solve this the library defines an additional method for attribute values,
  51. * namely \c detach_from_thread. The \c attribute_value class forwards the call to its pimpl,
  52. * which is supposed to ensure that it no longer refers to any thread-specific data after the call.
  53. * The pimpl can create a new holder as a result of this method and return it to the \c attribute_value
  54. * wrapper, which will keep the returned reference for any further calls.
  55. * This method is called for all attribute values that are passed to another thread.
  56. */
  57. class attribute_value
  58. {
  59. BOOST_COPYABLE_AND_MOVABLE(attribute_value)
  60. public:
  61. /*!
  62. * \brief A base class for an attribute value implementation
  63. *
  64. * All attribute value holders should derive from this interface.
  65. */
  66. struct BOOST_LOG_NO_VTABLE impl :
  67. public attribute::impl
  68. {
  69. public:
  70. /*!
  71. * The method dispatches the value to the given object.
  72. *
  73. * \param dispatcher The object that attempts to dispatch the stored value.
  74. * \return true if \a dispatcher was capable to consume the real attribute value type and false otherwise.
  75. */
  76. virtual bool dispatch(type_dispatcher& dispatcher) = 0;
  77. /*!
  78. * The method is called when the attribute value is passed to another thread (e.g.
  79. * in case of asynchronous logging). The value should ensure it properly owns all thread-specific data.
  80. *
  81. * \return An actual pointer to the attribute value. It may either point to this object or another.
  82. * In the latter case the returned pointer replaces the pointer used by caller to invoke this
  83. * method and is considered to be a functional equivalent to the previous pointer.
  84. */
  85. virtual intrusive_ptr< impl > detach_from_thread()
  86. {
  87. return this;
  88. }
  89. /*!
  90. * \return The attribute value that refers to self implementation.
  91. */
  92. attribute_value get_value() BOOST_OVERRIDE { return attribute_value(this); }
  93. /*!
  94. * \return The attribute value type
  95. */
  96. virtual typeindex::type_index get_type() const { return typeindex::type_index(); }
  97. };
  98. private:
  99. //! Pointer to the value implementation
  100. intrusive_ptr< impl > m_pImpl;
  101. public:
  102. /*!
  103. * Default constructor. Creates an empty (absent) attribute value.
  104. */
  105. BOOST_DEFAULTED_FUNCTION(attribute_value(), BOOST_NOEXCEPT {})
  106. /*!
  107. * Copy constructor
  108. */
  109. attribute_value(attribute_value const& that) BOOST_NOEXCEPT : m_pImpl(that.m_pImpl) {}
  110. /*!
  111. * Move constructor
  112. */
  113. attribute_value(BOOST_RV_REF(attribute_value) that) BOOST_NOEXCEPT { m_pImpl.swap(that.m_pImpl); }
  114. /*!
  115. * Initializing constructor. Creates an attribute value that refers to the specified holder.
  116. *
  117. * \param p A pointer to the attribute value holder.
  118. */
  119. explicit attribute_value(intrusive_ptr< impl > p) BOOST_NOEXCEPT { m_pImpl.swap(p); }
  120. /*!
  121. * Copy assignment
  122. */
  123. attribute_value& operator= (BOOST_COPY_ASSIGN_REF(attribute_value) that) BOOST_NOEXCEPT
  124. {
  125. m_pImpl = that.m_pImpl;
  126. return *this;
  127. }
  128. /*!
  129. * Move assignment
  130. */
  131. attribute_value& operator= (BOOST_RV_REF(attribute_value) that) BOOST_NOEXCEPT
  132. {
  133. m_pImpl.swap(that.m_pImpl);
  134. return *this;
  135. }
  136. /*!
  137. * The operator checks if the attribute value is empty
  138. */
  139. BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
  140. /*!
  141. * The operator checks if the attribute value is empty
  142. */
  143. bool operator! () const BOOST_NOEXCEPT { return !m_pImpl; }
  144. /*!
  145. * The method returns the type information of the stored value of the attribute.
  146. * The returned type info wrapper may be empty if the attribute value is empty or
  147. * the information cannot be provided. If the returned value is not empty, the type
  148. * can be used for value extraction.
  149. */
  150. typeindex::type_index get_type() const
  151. {
  152. if (m_pImpl.get())
  153. return m_pImpl->get_type();
  154. else
  155. return typeindex::type_index();
  156. }
  157. /*!
  158. * The method is called when the attribute value is passed to another thread (e.g.
  159. * in case of asynchronous logging). The value should ensure it properly owns all thread-specific data.
  160. *
  161. * \post The attribute value no longer refers to any thread-specific resources.
  162. */
  163. void detach_from_thread()
  164. {
  165. if (m_pImpl.get())
  166. m_pImpl->detach_from_thread().swap(m_pImpl);
  167. }
  168. /*!
  169. * The method dispatches the value to the given object. This method is a low level interface for
  170. * attribute value visitation and extraction. For typical usage these interfaces may be more convenient.
  171. *
  172. * \param dispatcher The object that attempts to dispatch the stored value.
  173. * \return \c true if the value is not empty and the \a dispatcher was capable to consume
  174. * the real attribute value type and \c false otherwise.
  175. */
  176. bool dispatch(type_dispatcher& dispatcher) const
  177. {
  178. if (m_pImpl.get())
  179. return m_pImpl->dispatch(dispatcher);
  180. else
  181. return false;
  182. }
  183. #if !defined(BOOST_LOG_DOXYGEN_PASS)
  184. #if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
  185. #define BOOST_LOG_AUX_VOID_DEFAULT = void
  186. #else
  187. #define BOOST_LOG_AUX_VOID_DEFAULT
  188. #endif
  189. #endif // !defined(BOOST_LOG_DOXYGEN_PASS)
  190. /*!
  191. * The method attempts to extract the stored value, assuming the value has the specified type.
  192. * One can specify either a single type or an MPL type sequence, in which case the stored value
  193. * is checked against every type in the sequence.
  194. *
  195. * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
  196. *
  197. * \return The extracted value, if the attribute value is not empty and the value is the same
  198. * as specified. Otherwise returns an empty value. See description of the \c result_of::extract
  199. * metafunction for information on the nature of the result value.
  200. */
  201. template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT >
  202. typename result_of::extract< T, TagT >::type extract() const;
  203. /*!
  204. * The method attempts to extract the stored value, assuming the value has the specified type.
  205. * One can specify either a single type or an MPL type sequence, in which case the stored value
  206. * is checked against every type in the sequence.
  207. *
  208. * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
  209. *
  210. * \return The extracted value, if the attribute value is not empty and the value is the same
  211. * as specified. Otherwise an exception is thrown. See description of the \c result_of::extract_or_throw
  212. * metafunction for information on the nature of the result value.
  213. */
  214. template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT >
  215. typename result_of::extract_or_throw< T, TagT >::type extract_or_throw() const;
  216. /*!
  217. * The method attempts to extract the stored value, assuming the value has the specified type.
  218. * One can specify either a single type or an MPL type sequence, in which case the stored value
  219. * is checked against every type in the sequence. If extraction fails, the default value is returned.
  220. *
  221. * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
  222. *
  223. * \param def_value Default value.
  224. *
  225. * \return The extracted value, if the attribute value is not empty and the value is the same
  226. * as specified. Otherwise returns the default value. See description of the \c result_of::extract_or_default
  227. * metafunction for information on the nature of the result value.
  228. */
  229. template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT >
  230. typename result_of::extract_or_default< T, T, TagT >::type extract_or_default(T const& def_value) const;
  231. /*!
  232. * The method attempts to extract the stored value, assuming the value has the specified type.
  233. * One can specify either a single type or an MPL type sequence, in which case the stored value
  234. * is checked against every type in the sequence. If extraction fails, the default value is returned.
  235. *
  236. * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
  237. *
  238. * \param def_value Default value.
  239. *
  240. * \return The extracted value, if the attribute value is not empty and the value is the same
  241. * as specified. Otherwise returns the default value. See description of the \c result_of::extract_or_default
  242. * metafunction for information on the nature of the result value.
  243. */
  244. template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT, typename DefaultT >
  245. typename result_of::extract_or_default< T, DefaultT, TagT >::type extract_or_default(DefaultT const& def_value) const;
  246. #if defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
  247. /*!
  248. * The method attempts to extract the stored value, assuming the value has the specified type.
  249. * One can specify either a single type or an MPL type sequence, in which case the stored value
  250. * is checked against every type in the sequence.
  251. *
  252. * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
  253. *
  254. * \return The extracted value, if the attribute value is not empty and the value is the same
  255. * as specified. Otherwise returns an empty value. See description of the \c result_of::extract
  256. * metafunction for information on the nature of the result value.
  257. */
  258. template< typename T >
  259. typename result_of::extract< T >::type extract() const;
  260. /*!
  261. * The method attempts to extract the stored value, assuming the value has the specified type.
  262. * One can specify either a single type or an MPL type sequence, in which case the stored value
  263. * is checked against every type in the sequence.
  264. *
  265. * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
  266. *
  267. * \return The extracted value, if the attribute value is not empty and the value is the same
  268. * as specified. Otherwise an exception is thrown. See description of the \c result_of::extract_or_throw
  269. * metafunction for information on the nature of the result value.
  270. */
  271. template< typename T >
  272. typename result_of::extract_or_throw< T >::type extract_or_throw() const;
  273. /*!
  274. * The method attempts to extract the stored value, assuming the value has the specified type.
  275. * One can specify either a single type or an MPL type sequence, in which case the stored value
  276. * is checked against every type in the sequence. If extraction fails, the default value is returned.
  277. *
  278. * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
  279. *
  280. * \param def_value Default value.
  281. *
  282. * \return The extracted value, if the attribute value is not empty and the value is the same
  283. * as specified. Otherwise returns the default value. See description of the \c result_of::extract_or_default
  284. * metafunction for information on the nature of the result value.
  285. */
  286. template< typename T >
  287. typename result_of::extract_or_default< T, T >::type extract_or_default(T const& def_value) const;
  288. /*!
  289. * The method attempts to extract the stored value, assuming the value has the specified type.
  290. * One can specify either a single type or an MPL type sequence, in which case the stored value
  291. * is checked against every type in the sequence. If extraction fails, the default value is returned.
  292. *
  293. * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
  294. *
  295. * \param def_value Default value.
  296. *
  297. * \return The extracted value, if the attribute value is not empty and the value is the same
  298. * as specified. Otherwise returns the default value. See description of the \c result_of::extract_or_default
  299. * metafunction for information on the nature of the result value.
  300. */
  301. template< typename T, typename DefaultT >
  302. typename result_of::extract_or_default< T, DefaultT >::type extract_or_default(DefaultT const& def_value) const;
  303. #endif // defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
  304. #undef BOOST_LOG_AUX_VOID_DEFAULT
  305. /*!
  306. * The method attempts to extract the stored value, assuming the value has the specified type,
  307. * and pass it to the \a visitor function object.
  308. * One can specify either a single type or an MPL type sequence, in which case the stored value
  309. * is checked against every type in the sequence.
  310. *
  311. * \note Include <tt>value_visitation.hpp</tt> prior to using this method.
  312. *
  313. * \param visitor A function object that will be invoked on the extracted attribute value.
  314. * The visitor should be capable to be called with a single argument of
  315. * any type of the specified types in \c T.
  316. *
  317. * \return The result of visitation.
  318. */
  319. template< typename T, typename VisitorT >
  320. visitation_result visit(VisitorT visitor) const;
  321. /*!
  322. * The method swaps two attribute values
  323. */
  324. void swap(attribute_value& that) BOOST_NOEXCEPT
  325. {
  326. m_pImpl.swap(that.m_pImpl);
  327. }
  328. };
  329. /*!
  330. * The function swaps two attribute values
  331. */
  332. inline void swap(attribute_value& left, attribute_value& right) BOOST_NOEXCEPT
  333. {
  334. left.swap(right);
  335. }
  336. BOOST_LOG_CLOSE_NAMESPACE // namespace log
  337. } // namespace boost
  338. #include <boost/log/detail/footer.hpp>
  339. #if defined(BOOST_LOG_ATTRIBUTES_ATTRIBUTE_HPP_INCLUDED_)
  340. #include <boost/log/detail/attribute_get_value_impl.hpp>
  341. #endif
  342. #endif // BOOST_LOG_ATTRIBUTE_VALUE_HPP_INCLUDED_