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 record_view.hpp |
9 | * \author Andrey Semashev |
10 | * \date 09.03.2009 |
11 | * |
12 | * This header contains a logging record view class definition. |
13 | */ |
14 | |
15 | #ifndef BOOST_LOG_CORE_RECORD_VIEW_HPP_INCLUDED_ |
16 | #define BOOST_LOG_CORE_RECORD_VIEW_HPP_INCLUDED_ |
17 | |
18 | #include <boost/smart_ptr/intrusive_ptr.hpp> |
19 | #include <boost/move/core.hpp> |
20 | #include <boost/move/utility_core.hpp> |
21 | #include <boost/core/explicit_operator_bool.hpp> |
22 | #include <boost/log/detail/config.hpp> |
23 | #include <boost/log/attributes/attribute_value_set.hpp> |
24 | #include <boost/log/expressions/keyword_fwd.hpp> |
25 | #ifndef BOOST_LOG_NO_THREADS |
26 | #include <boost/detail/atomic_count.hpp> |
27 | #endif // BOOST_LOG_NO_THREADS |
28 | #include <boost/log/detail/header.hpp> |
29 | |
30 | #ifdef BOOST_HAS_PRAGMA_ONCE |
31 | #pragma once |
32 | #endif |
33 | |
34 | namespace boost { |
35 | |
36 | BOOST_LOG_OPEN_NAMESPACE |
37 | |
38 | #ifndef BOOST_LOG_DOXYGEN_PASS |
39 | class core; |
40 | class record; |
41 | #endif // BOOST_LOG_DOXYGEN_PASS |
42 | |
43 | /*! |
44 | * \brief Logging record view class |
45 | * |
46 | * The logging record encapsulates all information related to a single logging statement, |
47 | * in particular, attribute values view and the log message string. The view is immutable, |
48 | * it is implemented as a wrapper around a reference-counted implementation. |
49 | */ |
50 | class record_view |
51 | { |
52 | BOOST_COPYABLE_AND_MOVABLE(record_view) |
53 | |
54 | friend class core; |
55 | friend class record; |
56 | |
57 | #ifndef BOOST_LOG_DOXYGEN_PASS |
58 | private: |
59 | //! Private data |
60 | struct private_data; |
61 | friend struct private_data; |
62 | |
63 | //! Publicly available record data |
64 | struct public_data |
65 | { |
66 | //! Reference counter |
67 | #ifndef BOOST_LOG_NO_THREADS |
68 | mutable boost::detail::atomic_count m_ref_counter; |
69 | #else |
70 | mutable unsigned int m_ref_counter; |
71 | #endif // BOOST_LOG_NO_THREADS |
72 | |
73 | //! Attribute values view |
74 | attribute_value_set m_attribute_values; |
75 | |
76 | //! Constructor from the attribute value set |
77 | explicit public_data(BOOST_RV_REF(attribute_value_set) values) BOOST_NOEXCEPT : |
78 | m_ref_counter(1), |
79 | m_attribute_values(boost::move(t&: values)) |
80 | { |
81 | } |
82 | |
83 | //! Destructor |
84 | BOOST_LOG_API static void destroy(const public_data* p) BOOST_NOEXCEPT; |
85 | |
86 | protected: |
87 | ~public_data() {} |
88 | |
89 | BOOST_DELETED_FUNCTION(public_data(public_data const&)) |
90 | BOOST_DELETED_FUNCTION(public_data& operator= (public_data const&)) |
91 | |
92 | friend void intrusive_ptr_add_ref(const public_data* p) BOOST_NOEXCEPT { ++p->m_ref_counter; } |
93 | friend void intrusive_ptr_release(const public_data* p) BOOST_NOEXCEPT { if (--p->m_ref_counter == 0) public_data::destroy(p); } |
94 | }; |
95 | |
96 | private: |
97 | //! A pointer to the log record implementation |
98 | intrusive_ptr< public_data > m_impl; |
99 | |
100 | private: |
101 | // A private constructor, accessible from record |
102 | explicit record_view(public_data* impl) BOOST_NOEXCEPT : m_impl(impl, false) {} |
103 | |
104 | #endif // BOOST_LOG_DOXYGEN_PASS |
105 | |
106 | public: |
107 | /*! |
108 | * Default constructor. Creates an empty record view that is equivalent to the invalid record handle. |
109 | * |
110 | * \post <tt>!*this == true</tt> |
111 | */ |
112 | BOOST_CONSTEXPR record_view() BOOST_NOEXCEPT |
113 | #if !defined(BOOST_LOG_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS) && !defined(BOOST_LOG_NO_CXX11_DEFAULTED_CONSTEXPR_CONSTRUCTORS) |
114 | = default; |
115 | #else |
116 | {} |
117 | #endif |
118 | |
119 | /*! |
120 | * Copy constructor |
121 | */ |
122 | record_view(record_view const& that) BOOST_NOEXCEPT : m_impl(that.m_impl) {} |
123 | |
124 | /*! |
125 | * Move constructor. Source record contents unspecified after the operation. |
126 | */ |
127 | record_view(BOOST_RV_REF(record_view) that) BOOST_NOEXCEPT |
128 | { |
129 | m_impl.swap(rhs&: that.m_impl); |
130 | } |
131 | |
132 | /*! |
133 | * Destructor. Destroys the record, releases any sinks and attribute values that were involved in processing this record. |
134 | */ |
135 | ~record_view() BOOST_NOEXCEPT {} |
136 | |
137 | /*! |
138 | * Copy assignment |
139 | */ |
140 | record_view& operator= (BOOST_COPY_ASSIGN_REF(record_view) that) BOOST_NOEXCEPT |
141 | { |
142 | m_impl = that.m_impl; |
143 | return *this; |
144 | } |
145 | |
146 | /*! |
147 | * Move assignment. Source record contents unspecified after the operation. |
148 | */ |
149 | record_view& operator= (BOOST_RV_REF(record_view) that) BOOST_NOEXCEPT |
150 | { |
151 | m_impl.swap(rhs&: that.m_impl); |
152 | return *this; |
153 | } |
154 | |
155 | /*! |
156 | * \return A reference to the set of attribute values attached to this record |
157 | * |
158 | * \pre <tt>!!*this</tt> |
159 | */ |
160 | attribute_value_set const& attribute_values() const BOOST_NOEXCEPT |
161 | { |
162 | return m_impl->m_attribute_values; |
163 | } |
164 | |
165 | /*! |
166 | * Equality comparison |
167 | * |
168 | * \param that Comparand |
169 | * \return \c true if both <tt>*this</tt> and \a that identify the same log record or both do not |
170 | * identify any record, \c false otherwise. |
171 | */ |
172 | bool operator== (record_view const& that) const BOOST_NOEXCEPT |
173 | { |
174 | return m_impl == that.m_impl; |
175 | } |
176 | |
177 | /*! |
178 | * Inequality comparison |
179 | * |
180 | * \param that Comparand |
181 | * \return <tt>!(*this == that)</tt> |
182 | */ |
183 | bool operator!= (record_view const& that) const BOOST_NOEXCEPT |
184 | { |
185 | return !operator== (that); |
186 | } |
187 | |
188 | /*! |
189 | * Conversion to an unspecified boolean type |
190 | * |
191 | * \return \c true, if the <tt>*this</tt> identifies a log record, \c false, if the <tt>*this</tt> is not valid |
192 | */ |
193 | BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() |
194 | |
195 | /*! |
196 | * Inverted conversion to an unspecified boolean type |
197 | * |
198 | * \return \c false, if the <tt>*this</tt> identifies a log record, \c true, if the <tt>*this</tt> is not valid |
199 | */ |
200 | bool operator! () const BOOST_NOEXCEPT |
201 | { |
202 | return !m_impl; |
203 | } |
204 | |
205 | /*! |
206 | * Swaps two handles |
207 | * |
208 | * \param that Another record to swap with |
209 | * <b>Throws:</b> Nothing |
210 | */ |
211 | void swap(record_view& that) BOOST_NOEXCEPT |
212 | { |
213 | m_impl.swap(rhs&: that.m_impl); |
214 | } |
215 | |
216 | /*! |
217 | * Resets the log record handle. If there are no other handles left, the log record is closed |
218 | * and all resources referenced by the record are released. |
219 | * |
220 | * \post <tt>!*this == true</tt> |
221 | */ |
222 | void reset() BOOST_NOEXCEPT |
223 | { |
224 | m_impl.reset(); |
225 | } |
226 | |
227 | /*! |
228 | * Attribute value lookup. |
229 | * |
230 | * \param name Attribute name. |
231 | * \return An \c attribute_value, non-empty if it is found, empty otherwise. |
232 | */ |
233 | attribute_value_set::mapped_type operator[] (attribute_value_set::key_type name) const |
234 | { |
235 | return m_impl->m_attribute_values[name]; |
236 | } |
237 | |
238 | /*! |
239 | * Attribute value lookup. |
240 | * |
241 | * \param keyword Attribute keyword. |
242 | * \return A \c value_ref with extracted attribute value if it is found, empty \c value_ref otherwise. |
243 | */ |
244 | template< typename DescriptorT, template< typename > class ActorT > |
245 | typename result_of::extract< typename expressions::attribute_keyword< DescriptorT, ActorT >::value_type, DescriptorT >::type |
246 | operator[] (expressions::attribute_keyword< DescriptorT, ActorT > const& keyword) const |
247 | { |
248 | return m_impl->m_attribute_values[keyword]; |
249 | } |
250 | }; |
251 | |
252 | /*! |
253 | * A free-standing swap function overload for \c record_view |
254 | */ |
255 | inline void swap(record_view& left, record_view& right) BOOST_NOEXCEPT |
256 | { |
257 | left.swap(that&: right); |
258 | } |
259 | |
260 | BOOST_LOG_CLOSE_NAMESPACE // namespace log |
261 | |
262 | } // namespace boost |
263 | |
264 | #include <boost/log/detail/footer.hpp> |
265 | |
266 | #endif // BOOST_LOG_CORE_RECORD_VIEW_HPP_INCLUDED_ |
267 | |