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