]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
15 | #ifndef BOOST_LOG_ATTRIBUTES_MUTABLE_CONSTANT_HPP_INCLUDED_ | |
16 | #define BOOST_LOG_ATTRIBUTES_MUTABLE_CONSTANT_HPP_INCLUDED_ | |
17 | ||
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> | |
30 | ||
31 | #ifdef BOOST_HAS_PRAGMA_ONCE | |
32 | #pragma once | |
33 | #endif | |
34 | ||
35 | namespace boost { | |
36 | ||
37 | BOOST_LOG_OPEN_NAMESPACE | |
38 | ||
39 | namespace attributes { | |
40 | ||
41 | /*! | |
42 | * \brief A class of an attribute that holds a single constant value with ability to change it | |
43 | * | |
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. | |
46 | * | |
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. | |
51 | * | |
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. | |
54 | */ | |
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 | |
58 | template< | |
59 | typename T, | |
60 | typename MutexT = void, | |
61 | typename ScopedWriteLockT = | |
62 | #ifndef BOOST_LOG_NO_THREADS | |
63 | typename mpl::if_c< | |
64 | boost::log::aux::is_exclusively_lockable< MutexT >::value, | |
65 | boost::log::aux::exclusive_lock_guard< MutexT >, | |
66 | void | |
67 | >::type, | |
68 | #else | |
69 | void, | |
70 | #endif // BOOST_LOG_NO_THREADS | |
71 | typename ScopedReadLockT = | |
72 | #ifndef BOOST_LOG_NO_THREADS | |
73 | typename mpl::if_c< | |
74 | boost::log::aux::is_shared_lockable< MutexT >::value, | |
75 | boost::log::aux::shared_lock_guard< MutexT >, | |
76 | ScopedWriteLockT | |
77 | >::type | |
78 | #else | |
79 | ScopedWriteLockT | |
80 | #endif // BOOST_LOG_NO_THREADS | |
81 | #endif // BOOST_LOG_DOXYGEN_PASS | |
82 | > | |
83 | class mutable_constant : | |
84 | public attribute | |
85 | { | |
86 | public: | |
87 | //! The attribute value type | |
88 | typedef T value_type; | |
89 | ||
90 | protected: | |
91 | //! Factory implementation | |
92 | class BOOST_SYMBOL_VISIBLE impl : | |
93 | public attribute::impl | |
94 | { | |
95 | private: | |
96 | //! Mutex type | |
97 | typedef MutexT mutex_type; | |
98 | //! Shared lock 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; | |
105 | ||
106 | private: | |
107 | //! Thread protection mutex | |
108 | mutable mutex_type m_Mutex; | |
109 | //! Pointer to the actual attribute value | |
110 | intrusive_ptr< attr_value > m_Value; | |
111 | ||
112 | public: | |
113 | /*! | |
114 | * Initializing constructor | |
115 | */ | |
116 | explicit impl(value_type const& value) : m_Value(new attr_value(value)) | |
117 | { | |
118 | } | |
119 | /*! | |
120 | * Initializing constructor | |
121 | */ | |
122 | explicit impl(BOOST_RV_REF(value_type) value) : m_Value(new attr_value(boost::move(value))) | |
123 | { | |
124 | } | |
125 | ||
126 | attribute_value get_value() | |
127 | { | |
128 | scoped_read_lock lock(m_Mutex); | |
129 | return attribute_value(m_Value); | |
130 | } | |
131 | ||
132 | void set(value_type const& value) | |
133 | { | |
134 | intrusive_ptr< attr_value > p = new attr_value(value); | |
135 | scoped_write_lock lock(m_Mutex); | |
136 | m_Value.swap(p); | |
137 | } | |
138 | ||
139 | void set(BOOST_RV_REF(value_type) value) | |
140 | { | |
141 | intrusive_ptr< attr_value > p = new attr_value(boost::move(value)); | |
142 | scoped_write_lock lock(m_Mutex); | |
143 | m_Value.swap(p); | |
144 | } | |
145 | ||
146 | value_type get() const | |
147 | { | |
148 | scoped_read_lock lock(m_Mutex); | |
149 | return m_Value->get(); | |
150 | } | |
151 | }; | |
152 | ||
153 | public: | |
154 | /*! | |
155 | * Constructor with the stored value initialization | |
156 | */ | |
157 | explicit mutable_constant(value_type const& value) : attribute(new impl(value)) | |
158 | { | |
159 | } | |
160 | /*! | |
161 | * Constructor with the stored value initialization | |
162 | */ | |
163 | explicit mutable_constant(BOOST_RV_REF(value_type) value) : attribute(new impl(boost::move(value))) | |
164 | { | |
165 | } | |
166 | /*! | |
167 | * Constructor for casting support | |
168 | */ | |
169 | explicit mutable_constant(cast_source const& source) : attribute(source.as< impl >()) | |
170 | { | |
171 | } | |
172 | ||
173 | /*! | |
174 | * The method sets a new attribute value. The implementation exclusively locks the mutex in order | |
175 | * to protect the value assignment. | |
176 | */ | |
177 | void set(value_type const& value) | |
178 | { | |
179 | get_impl()->set(value); | |
180 | } | |
181 | ||
182 | /*! | |
183 | * The method sets a new attribute value. | |
184 | */ | |
185 | void set(BOOST_RV_REF(value_type) value) | |
186 | { | |
187 | get_impl()->set(boost::move(value)); | |
188 | } | |
189 | ||
190 | /*! | |
191 | * The method acquires the current attribute value. The implementation non-exclusively locks the mutex in order | |
192 | * to protect the value acquisition. | |
193 | */ | |
194 | value_type get() const | |
195 | { | |
196 | return get_impl()->get(); | |
197 | } | |
198 | ||
199 | protected: | |
200 | /*! | |
201 | * \returns Pointer to the factory implementation | |
202 | */ | |
203 | impl* get_impl() const | |
204 | { | |
205 | return static_cast< impl* >(attribute::get_impl()); | |
206 | } | |
207 | }; | |
208 | ||
209 | ||
210 | /*! | |
211 | * \brief Specialization for unlocked case | |
212 | * | |
213 | * This version of attribute does not perform thread synchronization to access the stored value. | |
214 | */ | |
215 | template< typename T > | |
216 | class mutable_constant< T, void, void, void > : | |
217 | public attribute | |
218 | { | |
219 | public: | |
220 | //! The attribute value type | |
221 | typedef T value_type; | |
222 | ||
223 | protected: | |
224 | //! Factory implementation | |
225 | class BOOST_SYMBOL_VISIBLE impl : | |
226 | public attribute::impl | |
227 | { | |
228 | private: | |
229 | //! Attribute value wrapper | |
230 | typedef attribute_value_impl< value_type > attr_value; | |
231 | ||
232 | private: | |
233 | //! The actual value | |
234 | intrusive_ptr< attr_value > m_Value; | |
235 | ||
236 | public: | |
237 | /*! | |
238 | * Initializing constructor | |
239 | */ | |
240 | explicit impl(value_type const& value) : m_Value(new attr_value(value)) | |
241 | { | |
242 | } | |
243 | /*! | |
244 | * Initializing constructor | |
245 | */ | |
246 | explicit impl(BOOST_RV_REF(value_type) value) : m_Value(new attr_value(boost::move(value))) | |
247 | { | |
248 | } | |
249 | ||
250 | attribute_value get_value() | |
251 | { | |
252 | return attribute_value(m_Value); | |
253 | } | |
254 | ||
255 | void set(value_type const& value) | |
256 | { | |
257 | m_Value = new attr_value(value); | |
258 | } | |
259 | void set(BOOST_RV_REF(value_type) value) | |
260 | { | |
261 | m_Value = new attr_value(boost::move(value)); | |
262 | } | |
263 | ||
264 | value_type get() const | |
265 | { | |
266 | return m_Value->get(); | |
267 | } | |
268 | }; | |
269 | ||
270 | public: | |
271 | /*! | |
272 | * Constructor with the stored value initialization | |
273 | */ | |
274 | explicit mutable_constant(value_type const& value) : attribute(new impl(value)) | |
275 | { | |
276 | } | |
277 | /*! | |
278 | * Constructor with the stored value initialization | |
279 | */ | |
280 | explicit mutable_constant(BOOST_RV_REF(value_type) value) : attribute(new impl(boost::move(value))) | |
281 | { | |
282 | } | |
283 | /*! | |
284 | * Constructor for casting support | |
285 | */ | |
286 | explicit mutable_constant(cast_source const& source) : attribute(source.as< impl >()) | |
287 | { | |
288 | } | |
289 | ||
290 | /*! | |
291 | * The method sets a new attribute value. | |
292 | */ | |
293 | void set(value_type const& value) | |
294 | { | |
295 | get_impl()->set(value); | |
296 | } | |
297 | ||
298 | /*! | |
299 | * The method sets a new attribute value. | |
300 | */ | |
301 | void set(BOOST_RV_REF(value_type) value) | |
302 | { | |
303 | get_impl()->set(boost::move(value)); | |
304 | } | |
305 | ||
306 | /*! | |
307 | * The method acquires the current attribute value. | |
308 | */ | |
309 | value_type get() const | |
310 | { | |
311 | return get_impl()->get(); | |
312 | } | |
313 | ||
314 | protected: | |
315 | /*! | |
316 | * \returns Pointer to the factory implementation | |
317 | */ | |
318 | impl* get_impl() const | |
319 | { | |
320 | return static_cast< impl* >(attribute::get_impl()); | |
321 | } | |
322 | }; | |
323 | ||
324 | } // namespace attributes | |
325 | ||
326 | BOOST_LOG_CLOSE_NAMESPACE // namespace log | |
327 | ||
328 | } // namespace boost | |
329 | ||
330 | #include <boost/log/detail/footer.hpp> | |
331 | ||
332 | #endif // BOOST_LOG_ATTRIBUTES_MUTABLE_CONSTANT_HPP_INCLUDED_ |