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)
8 * \file mutable_constant.hpp
9 * \author Andrey Semashev
12 * The header contains implementation of a mutable constant attribute.
15 #ifndef BOOST_LOG_ATTRIBUTES_MUTABLE_CONSTANT_HPP_INCLUDED_
16 #define BOOST_LOG_ATTRIBUTES_MUTABLE_CONSTANT_HPP_INCLUDED_
18 #include <boost/static_assert.hpp>
19 #include <boost/smart_ptr/intrusive_ptr.hpp>
20 #include <boost/mpl/if.hpp>
21 #include <boost/move/core.hpp>
22 #include <boost/move/utility_core.hpp>
23 #include <boost/type_traits/is_void.hpp>
24 #include <boost/log/detail/config.hpp>
25 #include <boost/log/detail/locks.hpp>
26 #include <boost/log/attributes/attribute.hpp>
27 #include <boost/log/attributes/attribute_cast.hpp>
28 #include <boost/log/attributes/attribute_value_impl.hpp>
29 #include <boost/log/detail/header.hpp>
31 #ifdef BOOST_HAS_PRAGMA_ONCE
37 BOOST_LOG_OPEN_NAMESPACE
39 namespace attributes {
42 * \brief A class of an attribute that holds a single constant value with ability to change it
44 * The mutable_constant attribute stores a single value of type, specified as the first template argument.
45 * This value is returned on each attribute value acquisition.
47 * The attribute also allows to modify the stored value, even if the attribute is registered in an attribute set.
48 * In order to ensure thread safety of such modifications the \c mutable_constant class is also parametrized
49 * with three additional template arguments: mutex type, scoped write and scoped read lock types. If not specified,
50 * the lock types are automatically deduced based on the mutex type.
52 * The implementation may avoid using these types to actually create and use the mutex, if a more efficient synchronization method is
53 * available (such as atomic operations on the value type). By default no synchronization is done.
55 #ifdef BOOST_LOG_DOXYGEN_PASS
56 template< typename T, typename MutexT = void, typename ScopedWriteLockT = auto, typename ScopedReadLockT = auto >
57 #else // BOOST_LOG_DOXYGEN_PASS
60 typename MutexT = void,
61 typename ScopedWriteLockT =
62 #ifndef BOOST_LOG_NO_THREADS
64 boost::log::aux::is_exclusively_lockable< MutexT >::value,
65 boost::log::aux::exclusive_lock_guard< MutexT >,
70 #endif // BOOST_LOG_NO_THREADS
71 typename ScopedReadLockT =
72 #ifndef BOOST_LOG_NO_THREADS
74 boost::log::aux::is_shared_lockable< MutexT >::value,
75 boost::log::aux::shared_lock_guard< MutexT >,
80 #endif // BOOST_LOG_NO_THREADS
81 #endif // BOOST_LOG_DOXYGEN_PASS
83 class mutable_constant :
87 //! The attribute value type
91 //! Factory implementation
92 class BOOST_SYMBOL_VISIBLE impl :
93 public attribute::impl
97 typedef MutexT mutex_type;
99 typedef ScopedReadLockT scoped_read_lock;
100 //! Exclusive lock type
101 typedef ScopedWriteLockT scoped_write_lock;
102 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");
103 //! Attribute value wrapper
104 typedef attribute_value_impl< value_type > attr_value;
107 //! Thread protection mutex
108 mutable mutex_type m_Mutex;
109 //! Pointer to the actual attribute value
110 intrusive_ptr< attr_value > m_Value;
114 * Initializing constructor
116 explicit impl(value_type const& value) : m_Value(new attr_value(value))
120 * Initializing constructor
122 explicit impl(BOOST_RV_REF(value_type) value) : m_Value(new attr_value(boost::move(value)))
126 attribute_value get_value()
128 scoped_read_lock lock(m_Mutex);
129 return attribute_value(m_Value);
132 void set(value_type const& value)
134 intrusive_ptr< attr_value > p = new attr_value(value);
135 scoped_write_lock lock(m_Mutex);
139 void set(BOOST_RV_REF(value_type) value)
141 intrusive_ptr< attr_value > p = new attr_value(boost::move(value));
142 scoped_write_lock lock(m_Mutex);
146 value_type get() const
148 scoped_read_lock lock(m_Mutex);
149 return m_Value->get();
155 * Constructor with the stored value initialization
157 explicit mutable_constant(value_type const& value) : attribute(new impl(value))
161 * Constructor with the stored value initialization
163 explicit mutable_constant(BOOST_RV_REF(value_type) value) : attribute(new impl(boost::move(value)))
167 * Constructor for casting support
169 explicit mutable_constant(cast_source const& source) : attribute(source.as< impl >())
174 * The method sets a new attribute value. The implementation exclusively locks the mutex in order
175 * to protect the value assignment.
177 void set(value_type const& value)
179 get_impl()->set(value);
183 * The method sets a new attribute value.
185 void set(BOOST_RV_REF(value_type) value)
187 get_impl()->set(boost::move(value));
191 * The method acquires the current attribute value. The implementation non-exclusively locks the mutex in order
192 * to protect the value acquisition.
194 value_type get() const
196 return get_impl()->get();
201 * \returns Pointer to the factory implementation
203 impl* get_impl() const
205 return static_cast< impl* >(attribute::get_impl());
211 * \brief Specialization for unlocked case
213 * This version of attribute does not perform thread synchronization to access the stored value.
215 template< typename T >
216 class mutable_constant< T, void, void, void > :
220 //! The attribute value type
221 typedef T value_type;
224 //! Factory implementation
225 class BOOST_SYMBOL_VISIBLE impl :
226 public attribute::impl
229 //! Attribute value wrapper
230 typedef attribute_value_impl< value_type > attr_value;
234 intrusive_ptr< attr_value > m_Value;
238 * Initializing constructor
240 explicit impl(value_type const& value) : m_Value(new attr_value(value))
244 * Initializing constructor
246 explicit impl(BOOST_RV_REF(value_type) value) : m_Value(new attr_value(boost::move(value)))
250 attribute_value get_value()
252 return attribute_value(m_Value);
255 void set(value_type const& value)
257 m_Value = new attr_value(value);
259 void set(BOOST_RV_REF(value_type) value)
261 m_Value = new attr_value(boost::move(value));
264 value_type get() const
266 return m_Value->get();
272 * Constructor with the stored value initialization
274 explicit mutable_constant(value_type const& value) : attribute(new impl(value))
278 * Constructor with the stored value initialization
280 explicit mutable_constant(BOOST_RV_REF(value_type) value) : attribute(new impl(boost::move(value)))
284 * Constructor for casting support
286 explicit mutable_constant(cast_source const& source) : attribute(source.as< impl >())
291 * The method sets a new attribute value.
293 void set(value_type const& value)
295 get_impl()->set(value);
299 * The method sets a new attribute value.
301 void set(BOOST_RV_REF(value_type) value)
303 get_impl()->set(boost::move(value));
307 * The method acquires the current attribute value.
309 value_type get() const
311 return get_impl()->get();
316 * \returns Pointer to the factory implementation
318 impl* get_impl() const
320 return static_cast< impl* >(attribute::get_impl());
324 } // namespace attributes
326 BOOST_LOG_CLOSE_NAMESPACE // namespace log
330 #include <boost/log/detail/footer.hpp>
332 #endif // BOOST_LOG_ATTRIBUTES_MUTABLE_CONSTANT_HPP_INCLUDED_