mutable_constant.hpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  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 mutable_constant.hpp
  9. * \author Andrey Semashev
  10. * \date 06.11.2007
  11. *
  12. * The header contains implementation of a mutable constant attribute.
  13. */
  14. #ifndef BOOST_LOG_ATTRIBUTES_MUTABLE_CONSTANT_HPP_INCLUDED_
  15. #define BOOST_LOG_ATTRIBUTES_MUTABLE_CONSTANT_HPP_INCLUDED_
  16. #include <boost/static_assert.hpp>
  17. #include <boost/smart_ptr/intrusive_ptr.hpp>
  18. #include <boost/mpl/if.hpp>
  19. #include <boost/move/core.hpp>
  20. #include <boost/move/utility_core.hpp>
  21. #include <boost/type_traits/is_void.hpp>
  22. #include <boost/log/detail/config.hpp>
  23. #include <boost/log/detail/locks.hpp>
  24. #include <boost/log/attributes/attribute.hpp>
  25. #include <boost/log/attributes/attribute_cast.hpp>
  26. #include <boost/log/attributes/attribute_value_impl.hpp>
  27. #include <boost/log/detail/header.hpp>
  28. #ifdef BOOST_HAS_PRAGMA_ONCE
  29. #pragma once
  30. #endif
  31. namespace boost {
  32. BOOST_LOG_OPEN_NAMESPACE
  33. namespace attributes {
  34. /*!
  35. * \brief A class of an attribute that holds a single constant value with ability to change it
  36. *
  37. * The mutable_constant attribute stores a single value of type, specified as the first template argument.
  38. * This value is returned on each attribute value acquisition.
  39. *
  40. * The attribute also allows to modify the stored value, even if the attribute is registered in an attribute set.
  41. * In order to ensure thread safety of such modifications the \c mutable_constant class is also parametrized
  42. * with three additional template arguments: mutex type, scoped write and scoped read lock types. If not specified,
  43. * the lock types are automatically deduced based on the mutex type.
  44. *
  45. * The implementation may avoid using these types to actually create and use the mutex, if a more efficient synchronization method is
  46. * available (such as atomic operations on the value type). By default no synchronization is done.
  47. */
  48. #ifdef BOOST_LOG_DOXYGEN_PASS
  49. template< typename T, typename MutexT = void, typename ScopedWriteLockT = auto, typename ScopedReadLockT = auto >
  50. #else // BOOST_LOG_DOXYGEN_PASS
  51. template<
  52. typename T,
  53. typename MutexT = void,
  54. typename ScopedWriteLockT =
  55. #ifndef BOOST_LOG_NO_THREADS
  56. typename mpl::if_c<
  57. boost::log::aux::is_exclusively_lockable< MutexT >::value,
  58. boost::log::aux::exclusive_lock_guard< MutexT >,
  59. void
  60. >::type,
  61. #else
  62. void,
  63. #endif // BOOST_LOG_NO_THREADS
  64. typename ScopedReadLockT =
  65. #ifndef BOOST_LOG_NO_THREADS
  66. typename mpl::if_c<
  67. boost::log::aux::is_shared_lockable< MutexT >::value,
  68. boost::log::aux::shared_lock_guard< MutexT >,
  69. ScopedWriteLockT
  70. >::type
  71. #else
  72. ScopedWriteLockT
  73. #endif // BOOST_LOG_NO_THREADS
  74. #endif // BOOST_LOG_DOXYGEN_PASS
  75. >
  76. class mutable_constant :
  77. public attribute
  78. {
  79. public:
  80. //! The attribute value type
  81. typedef T value_type;
  82. protected:
  83. //! Factory implementation
  84. class BOOST_SYMBOL_VISIBLE impl :
  85. public attribute::impl
  86. {
  87. private:
  88. //! Mutex type
  89. typedef MutexT mutex_type;
  90. //! Shared lock type
  91. typedef ScopedReadLockT scoped_read_lock;
  92. //! Exclusive lock type
  93. typedef ScopedWriteLockT scoped_write_lock;
  94. BOOST_STATIC_ASSERT_MSG(!(is_void< mutex_type >::value || is_void< scoped_read_lock >::value || is_void< scoped_write_lock >::value), "Boost.Log: Mutex and both lock types either must not be void or must all be void");
  95. //! Attribute value wrapper
  96. typedef attribute_value_impl< value_type > attr_value;
  97. private:
  98. //! Thread protection mutex
  99. mutable mutex_type m_Mutex;
  100. //! Pointer to the actual attribute value
  101. intrusive_ptr< attr_value > m_Value;
  102. public:
  103. /*!
  104. * Initializing constructor
  105. */
  106. explicit impl(value_type const& value) : m_Value(new attr_value(value))
  107. {
  108. }
  109. /*!
  110. * Initializing constructor
  111. */
  112. explicit impl(BOOST_RV_REF(value_type) value) : m_Value(new attr_value(boost::move(value)))
  113. {
  114. }
  115. attribute_value get_value()
  116. {
  117. scoped_read_lock lock(m_Mutex);
  118. return attribute_value(m_Value);
  119. }
  120. void set(value_type const& value)
  121. {
  122. intrusive_ptr< attr_value > p = new attr_value(value);
  123. scoped_write_lock lock(m_Mutex);
  124. m_Value.swap(p);
  125. }
  126. void set(BOOST_RV_REF(value_type) value)
  127. {
  128. intrusive_ptr< attr_value > p = new attr_value(boost::move(value));
  129. scoped_write_lock lock(m_Mutex);
  130. m_Value.swap(p);
  131. }
  132. value_type get() const
  133. {
  134. scoped_read_lock lock(m_Mutex);
  135. return m_Value->get();
  136. }
  137. };
  138. public:
  139. /*!
  140. * Constructor with the stored value initialization
  141. */
  142. explicit mutable_constant(value_type const& value) : attribute(new impl(value))
  143. {
  144. }
  145. /*!
  146. * Constructor with the stored value initialization
  147. */
  148. explicit mutable_constant(BOOST_RV_REF(value_type) value) : attribute(new impl(boost::move(value)))
  149. {
  150. }
  151. /*!
  152. * Constructor for casting support
  153. */
  154. explicit mutable_constant(cast_source const& source) : attribute(source.as< impl >())
  155. {
  156. }
  157. /*!
  158. * The method sets a new attribute value. The implementation exclusively locks the mutex in order
  159. * to protect the value assignment.
  160. */
  161. void set(value_type const& value)
  162. {
  163. get_impl()->set(value);
  164. }
  165. /*!
  166. * The method sets a new attribute value.
  167. */
  168. void set(BOOST_RV_REF(value_type) value)
  169. {
  170. get_impl()->set(boost::move(value));
  171. }
  172. /*!
  173. * The method acquires the current attribute value. The implementation non-exclusively locks the mutex in order
  174. * to protect the value acquisition.
  175. */
  176. value_type get() const
  177. {
  178. return get_impl()->get();
  179. }
  180. protected:
  181. /*!
  182. * \returns Pointer to the factory implementation
  183. */
  184. impl* get_impl() const
  185. {
  186. return static_cast< impl* >(attribute::get_impl());
  187. }
  188. };
  189. /*!
  190. * \brief Specialization for unlocked case
  191. *
  192. * This version of attribute does not perform thread synchronization to access the stored value.
  193. */
  194. template< typename T >
  195. class mutable_constant< T, void, void, void > :
  196. public attribute
  197. {
  198. public:
  199. //! The attribute value type
  200. typedef T value_type;
  201. protected:
  202. //! Factory implementation
  203. class BOOST_SYMBOL_VISIBLE impl :
  204. public attribute::impl
  205. {
  206. private:
  207. //! Attribute value wrapper
  208. typedef attribute_value_impl< value_type > attr_value;
  209. private:
  210. //! The actual value
  211. intrusive_ptr< attr_value > m_Value;
  212. public:
  213. /*!
  214. * Initializing constructor
  215. */
  216. explicit impl(value_type const& value) : m_Value(new attr_value(value))
  217. {
  218. }
  219. /*!
  220. * Initializing constructor
  221. */
  222. explicit impl(BOOST_RV_REF(value_type) value) : m_Value(new attr_value(boost::move(value)))
  223. {
  224. }
  225. attribute_value get_value()
  226. {
  227. return attribute_value(m_Value);
  228. }
  229. void set(value_type const& value)
  230. {
  231. m_Value = new attr_value(value);
  232. }
  233. void set(BOOST_RV_REF(value_type) value)
  234. {
  235. m_Value = new attr_value(boost::move(value));
  236. }
  237. value_type get() const
  238. {
  239. return m_Value->get();
  240. }
  241. };
  242. public:
  243. /*!
  244. * Constructor with the stored value initialization
  245. */
  246. explicit mutable_constant(value_type const& value) : attribute(new impl(value))
  247. {
  248. }
  249. /*!
  250. * Constructor with the stored value initialization
  251. */
  252. explicit mutable_constant(BOOST_RV_REF(value_type) value) : attribute(new impl(boost::move(value)))
  253. {
  254. }
  255. /*!
  256. * Constructor for casting support
  257. */
  258. explicit mutable_constant(cast_source const& source) : attribute(source.as< impl >())
  259. {
  260. }
  261. /*!
  262. * The method sets a new attribute value.
  263. */
  264. void set(value_type const& value)
  265. {
  266. get_impl()->set(value);
  267. }
  268. /*!
  269. * The method sets a new attribute value.
  270. */
  271. void set(BOOST_RV_REF(value_type) value)
  272. {
  273. get_impl()->set(boost::move(value));
  274. }
  275. /*!
  276. * The method acquires the current attribute value.
  277. */
  278. value_type get() const
  279. {
  280. return get_impl()->get();
  281. }
  282. protected:
  283. /*!
  284. * \returns Pointer to the factory implementation
  285. */
  286. impl* get_impl() const
  287. {
  288. return static_cast< impl* >(attribute::get_impl());
  289. }
  290. };
  291. } // namespace attributes
  292. BOOST_LOG_CLOSE_NAMESPACE // namespace log
  293. } // namespace boost
  294. #include <boost/log/detail/footer.hpp>
  295. #endif // BOOST_LOG_ATTRIBUTES_MUTABLE_CONSTANT_HPP_INCLUDED_