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