2
* Copyright Andrey Semashev 2007 - 2013.
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/shared_ptr.hpp>
19
#include <boost/make_shared.hpp>
20
#include <boost/static_assert.hpp>
21
#include <boost/mpl/if.hpp>
22
#include <boost/move/core.hpp>
23
#include <boost/move/utility.hpp>
24
#include <boost/type_traits/is_void.hpp>
25
#include <boost/log/detail/config.hpp>
26
#include <boost/log/detail/locks.hpp>
27
#include <boost/log/attributes/attribute.hpp>
28
#include <boost/log/attributes/attribute_cast.hpp>
29
#include <boost/log/attributes/attribute_value_impl.hpp>
30
#include <boost/log/detail/header.hpp>
32
#ifdef BOOST_LOG_HAS_PRAGMA_ONCE
38
BOOST_LOG_OPEN_NAMESPACE
40
namespace attributes {
43
* \brief A class of an attribute that holds a single constant value with ability to change it
45
* The mutable_constant attribute stores a single value of type, specified as the first template argument.
46
* This value is returned on each attribute value acquisition.
48
* The attribute also allows to modify the stored value, even if the attribute is registered in an attribute set.
49
* In order to ensure thread safety of such modifications the \c mutable_constant class is also parametrized
50
* with three additional template arguments: mutex type, scoped write and scoped read lock types. If not specified,
51
* the lock types are automatically deduced based on the mutex type.
53
* The implementation may avoid using these types to actually create and use the mutex, if a more efficient synchronization method is
54
* available (such as atomic operations on the value type). By default no synchronization is done.
56
#ifdef BOOST_LOG_DOXYGEN_PASS
57
template< typename T, typename MutexT = void, typename ScopedWriteLockT = auto, typename ScopedReadLockT = auto >
58
#else // BOOST_LOG_DOXYGEN_PASS
61
typename MutexT = void,
62
typename ScopedWriteLockT =
63
#ifndef BOOST_LOG_NO_THREADS
65
boost::log::aux::is_exclusively_lockable< MutexT >::value,
66
boost::log::aux::exclusive_lock_guard< MutexT >,
71
#endif // BOOST_LOG_NO_THREADS
72
typename ScopedReadLockT =
73
#ifndef BOOST_LOG_NO_THREADS
75
boost::log::aux::is_shared_lockable< MutexT >::value,
76
boost::log::aux::shared_lock_guard< MutexT >,
81
#endif // BOOST_LOG_NO_THREADS
82
#endif // BOOST_LOG_DOXYGEN_PASS
84
class mutable_constant :
88
//! The attribute value type
92
//! Factory implementation
93
class BOOST_LOG_VISIBLE impl :
94
public attribute::impl
98
typedef MutexT mutex_type;
100
typedef ScopedReadLockT scoped_read_lock;
101
//! Exclusive lock type
102
typedef ScopedWriteLockT scoped_write_lock;
103
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");
104
//! Attribute value wrapper
105
typedef attribute_value_impl< value_type > attr_value;
108
//! Thread protection mutex
109
mutable mutex_type m_Mutex;
110
//! Pointer to the actual attribute value
111
intrusive_ptr< attr_value > m_Value;
115
* Initializing constructor
117
explicit impl(value_type const& value) : m_Value(new attr_value(value))
121
* Initializing constructor
123
explicit impl(BOOST_RV_REF(value_type) value) : m_Value(new attr_value(boost::move(value)))
127
attribute_value get_value()
129
scoped_read_lock lock(m_Mutex);
130
return attribute_value(m_Value);
133
void set(value_type const& value)
135
intrusive_ptr< attr_value > p = new attr_value(value);
136
scoped_write_lock lock(m_Mutex);
140
void set(BOOST_RV_REF(value_type) value)
142
intrusive_ptr< attr_value > p = new attr_value(boost::move(value));
143
scoped_write_lock lock(m_Mutex);
147
value_type get() const
149
scoped_read_lock lock(m_Mutex);
150
return m_Value->get();
156
* Constructor with the stored value initialization
158
explicit mutable_constant(value_type const& value) : attribute(new impl(value))
162
* Constructor with the stored value initialization
164
explicit mutable_constant(BOOST_RV_REF(value_type) value) : attribute(new impl(boost::move(value)))
168
* Constructor for casting support
170
explicit mutable_constant(cast_source const& source) : attribute(source.as< impl >())
175
* The method sets a new attribute value. The implementation exclusively locks the mutex in order
176
* to protect the value assignment.
178
void set(value_type const& value)
180
get_impl()->set(value);
184
* The method sets a new attribute value.
186
void set(BOOST_RV_REF(value_type) value)
188
get_impl()->set(boost::move(value));
192
* The method acquires the current attribute value. The implementation non-exclusively locks the mutex in order
193
* to protect the value acquisition.
195
value_type get() const
197
return get_impl()->get();
202
* \returns Pointer to the factory implementation
204
impl* get_impl() const
206
return static_cast< impl* >(attribute::get_impl());
212
* \brief Specialization for unlocked case
214
* This version of attribute does not perform thread synchronization to access the stored value.
216
template< typename T >
217
class mutable_constant< T, void, void, void > :
221
//! The attribute value type
222
typedef T value_type;
225
//! Factory implementation
226
class BOOST_LOG_VISIBLE impl :
227
public attribute::impl
230
//! Attribute value wrapper
231
typedef attribute_value_impl< value_type > attr_value;
235
intrusive_ptr< attr_value > m_Value;
239
* Initializing constructor
241
explicit impl(value_type const& value) : m_Value(new attr_value(value))
245
* Initializing constructor
247
explicit impl(BOOST_RV_REF(value_type) value) : m_Value(new attr_value(boost::move(value)))
251
attribute_value get_value()
253
return attribute_value(m_Value);
256
void set(value_type const& value)
258
m_Value = new attr_value(value);
260
void set(BOOST_RV_REF(value_type) value)
262
m_Value = new attr_value(boost::move(value));
265
value_type get() const
267
return m_Value->get();
273
* Constructor with the stored value initialization
275
explicit mutable_constant(value_type const& value) : attribute(new impl(value))
279
* Constructor with the stored value initialization
281
explicit mutable_constant(BOOST_RV_REF(value_type) value) : attribute(new impl(boost::move(value)))
285
* Constructor for casting support
287
explicit mutable_constant(cast_source const& source) : attribute(source.as< impl >())
292
* The method sets a new attribute value.
294
void set(value_type const& value)
296
get_impl()->set(value);
300
* The method sets a new attribute value.
302
void set(BOOST_RV_REF(value_type) value)
304
get_impl()->set(boost::move(value));
308
* The method acquires the current attribute value.
310
value_type get() const
312
return get_impl()->get();
317
* \returns Pointer to the factory implementation
319
impl* get_impl() const
321
return static_cast< impl* >(attribute::get_impl());
325
} // namespace attributes
327
BOOST_LOG_CLOSE_NAMESPACE // namespace log
331
#include <boost/log/detail/footer.hpp>
333
#endif // BOOST_LOG_ATTRIBUTES_MUTABLE_CONSTANT_HPP_INCLUDED_