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 scoped_attribute.hpp
|
Chris@16
|
9 * \author Andrey Semashev
|
Chris@16
|
10 * \date 13.05.2007
|
Chris@16
|
11 *
|
Chris@16
|
12 * The header contains definition of facilities to define scoped attributes.
|
Chris@16
|
13 */
|
Chris@16
|
14
|
Chris@16
|
15 #ifndef BOOST_LOG_ATTRIBUTES_SCOPED_ATTRIBUTE_HPP_INCLUDED_
|
Chris@16
|
16 #define BOOST_LOG_ATTRIBUTES_SCOPED_ATTRIBUTE_HPP_INCLUDED_
|
Chris@16
|
17
|
Chris@16
|
18 #include <utility>
|
Chris@16
|
19 #include <boost/move/core.hpp>
|
Chris@16
|
20 #include <boost/move/utility.hpp>
|
Chris@16
|
21 #include <boost/utility/addressof.hpp>
|
Chris@16
|
22 #include <boost/log/detail/config.hpp>
|
Chris@16
|
23 #include <boost/log/core/core.hpp>
|
Chris@16
|
24 #include <boost/log/sources/basic_logger.hpp>
|
Chris@16
|
25 #include <boost/log/attributes/attribute.hpp>
|
Chris@16
|
26 #include <boost/log/attributes/attribute_set.hpp>
|
Chris@16
|
27 #include <boost/log/attributes/attribute_name.hpp>
|
Chris@16
|
28 #include <boost/log/attributes/constant.hpp>
|
Chris@16
|
29 #include <boost/log/utility/unused_variable.hpp>
|
Chris@16
|
30 #include <boost/log/utility/unique_identifier_name.hpp>
|
Chris@16
|
31 #include <boost/log/detail/header.hpp>
|
Chris@16
|
32
|
Chris@16
|
33 #ifdef BOOST_HAS_PRAGMA_ONCE
|
Chris@16
|
34 #pragma once
|
Chris@16
|
35 #endif
|
Chris@16
|
36
|
Chris@16
|
37 namespace boost {
|
Chris@16
|
38
|
Chris@16
|
39 BOOST_LOG_OPEN_NAMESPACE
|
Chris@16
|
40
|
Chris@16
|
41 namespace aux {
|
Chris@16
|
42
|
Chris@16
|
43 //! A base class for all scoped attribute guards
|
Chris@16
|
44 class attribute_scope_guard
|
Chris@16
|
45 {
|
Chris@16
|
46 };
|
Chris@16
|
47
|
Chris@16
|
48 } // namespace aux
|
Chris@16
|
49
|
Chris@16
|
50 //! Scoped attribute guard type
|
Chris@16
|
51 typedef aux::attribute_scope_guard const& scoped_attribute;
|
Chris@16
|
52
|
Chris@16
|
53 namespace aux {
|
Chris@16
|
54
|
Chris@16
|
55 //! A scoped logger attribute guard
|
Chris@16
|
56 template< typename LoggerT >
|
Chris@16
|
57 class scoped_logger_attribute :
|
Chris@16
|
58 public attribute_scope_guard
|
Chris@16
|
59 {
|
Chris@16
|
60 BOOST_COPYABLE_AND_MOVABLE_ALT(scoped_logger_attribute)
|
Chris@16
|
61
|
Chris@16
|
62 private:
|
Chris@16
|
63 //! Logger type
|
Chris@16
|
64 typedef LoggerT logger_type;
|
Chris@16
|
65
|
Chris@16
|
66 private:
|
Chris@16
|
67 //! A reference to the logger
|
Chris@16
|
68 logger_type* m_pLogger;
|
Chris@16
|
69 //! An iterator to the added attribute
|
Chris@16
|
70 attribute_set::iterator m_itAttribute;
|
Chris@16
|
71
|
Chris@16
|
72 public:
|
Chris@16
|
73 //! Constructor
|
Chris@16
|
74 scoped_logger_attribute(logger_type& l, attribute_name const& name, attribute const& attr) :
|
Chris@16
|
75 m_pLogger(boost::addressof(l))
|
Chris@16
|
76 {
|
Chris@16
|
77 std::pair<
|
Chris@16
|
78 attribute_set::iterator,
|
Chris@16
|
79 bool
|
Chris@16
|
80 > res = l.add_attribute(name, attr);
|
Chris@16
|
81 if (res.second)
|
Chris@16
|
82 m_itAttribute = res.first;
|
Chris@16
|
83 else
|
Chris@16
|
84 m_pLogger = 0; // if there already is a same-named attribute, don't register anything
|
Chris@16
|
85 }
|
Chris@16
|
86 //! Move constructor
|
Chris@16
|
87 scoped_logger_attribute(BOOST_RV_REF(scoped_logger_attribute) that) :
|
Chris@16
|
88 m_pLogger(that.m_pLogger),
|
Chris@16
|
89 m_itAttribute(that.m_itAttribute)
|
Chris@16
|
90 {
|
Chris@16
|
91 that.m_pLogger = 0;
|
Chris@16
|
92 }
|
Chris@16
|
93
|
Chris@16
|
94 //! Destructor
|
Chris@16
|
95 ~scoped_logger_attribute()
|
Chris@16
|
96 {
|
Chris@16
|
97 if (m_pLogger)
|
Chris@16
|
98 m_pLogger->remove_attribute(m_itAttribute);
|
Chris@16
|
99 }
|
Chris@16
|
100
|
Chris@16
|
101 #ifndef BOOST_LOG_BROKEN_REFERENCE_FROM_RVALUE_INIT
|
Chris@16
|
102 BOOST_DELETED_FUNCTION(scoped_logger_attribute(scoped_logger_attribute const&))
|
Chris@16
|
103 #else // BOOST_LOG_BROKEN_REFERENCE_FROM_RVALUE_INIT
|
Chris@16
|
104 scoped_logger_attribute(scoped_logger_attribute const& that) : m_pLogger(that.m_pLogger), m_itAttribute(that.m_itAttribute)
|
Chris@16
|
105 {
|
Chris@16
|
106 const_cast< scoped_logger_attribute& >(that).m_pLogger = 0;
|
Chris@16
|
107 }
|
Chris@16
|
108 #endif // BOOST_LOG_BROKEN_REFERENCE_FROM_RVALUE_INIT
|
Chris@16
|
109
|
Chris@16
|
110 BOOST_DELETED_FUNCTION(scoped_logger_attribute& operator= (scoped_logger_attribute const&))
|
Chris@16
|
111 };
|
Chris@16
|
112
|
Chris@16
|
113 } // namespace aux
|
Chris@16
|
114
|
Chris@16
|
115 // Generator helper functions
|
Chris@16
|
116 /*!
|
Chris@16
|
117 * Registers an attribute in the logger
|
Chris@16
|
118 *
|
Chris@16
|
119 * \param l Logger to register the attribute in
|
Chris@16
|
120 * \param name Attribute name
|
Chris@16
|
121 * \param attr The attribute. Must not be NULL.
|
Chris@16
|
122 * \return An unspecified guard object which may be used to initialize a \c scoped_attribute variable.
|
Chris@16
|
123 */
|
Chris@16
|
124 template< typename LoggerT >
|
Chris@16
|
125 BOOST_FORCEINLINE aux::scoped_logger_attribute< LoggerT > add_scoped_logger_attribute(LoggerT& l, attribute_name const& name, attribute const& attr)
|
Chris@16
|
126 {
|
Chris@16
|
127 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
Chris@16
|
128 return aux::scoped_logger_attribute< LoggerT >(l, name, attr);
|
Chris@16
|
129 #else
|
Chris@16
|
130 aux::scoped_logger_attribute< LoggerT > guard(l, name, attr);
|
Chris@16
|
131 return boost::move(guard);
|
Chris@16
|
132 #endif
|
Chris@16
|
133 }
|
Chris@16
|
134
|
Chris@16
|
135 #ifndef BOOST_LOG_DOXYGEN_PASS
|
Chris@16
|
136
|
Chris@16
|
137 #define BOOST_LOG_SCOPED_LOGGER_ATTR_INTERNAL(logger, attr_name, attr, sentry_var_name)\
|
Chris@16
|
138 BOOST_LOG_UNUSED_VARIABLE(::boost::log::scoped_attribute, sentry_var_name,\
|
Chris@16
|
139 = ::boost::log::add_scoped_logger_attribute(logger, attr_name, (attr)));
|
Chris@16
|
140
|
Chris@16
|
141 #endif // BOOST_LOG_DOXYGEN_PASS
|
Chris@16
|
142
|
Chris@16
|
143 //! The macro sets a scoped logger-wide attribute in a more compact way
|
Chris@16
|
144 #define BOOST_LOG_SCOPED_LOGGER_ATTR(logger, attr_name, attr)\
|
Chris@16
|
145 BOOST_LOG_SCOPED_LOGGER_ATTR_INTERNAL(\
|
Chris@16
|
146 logger,\
|
Chris@16
|
147 attr_name,\
|
Chris@16
|
148 attr,\
|
Chris@16
|
149 BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_scoped_logger_attr_sentry_))
|
Chris@16
|
150
|
Chris@16
|
151 //! The macro sets a scoped logger-wide tag in a more compact way
|
Chris@16
|
152 #define BOOST_LOG_SCOPED_LOGGER_TAG(logger, attr_name, attr_value)\
|
Chris@16
|
153 BOOST_LOG_SCOPED_LOGGER_ATTR(logger, attr_name, ::boost::log::attributes::make_constant(attr_value))
|
Chris@16
|
154
|
Chris@16
|
155 namespace aux {
|
Chris@16
|
156
|
Chris@16
|
157 //! A scoped thread-specific attribute guard
|
Chris@16
|
158 class scoped_thread_attribute :
|
Chris@16
|
159 public attribute_scope_guard
|
Chris@16
|
160 {
|
Chris@16
|
161 BOOST_COPYABLE_AND_MOVABLE_ALT(scoped_thread_attribute)
|
Chris@16
|
162
|
Chris@16
|
163 private:
|
Chris@16
|
164 //! A pointer to the logging core
|
Chris@16
|
165 core_ptr m_pCore;
|
Chris@16
|
166 //! An iterator to the added attribute
|
Chris@16
|
167 attribute_set::iterator m_itAttribute;
|
Chris@16
|
168
|
Chris@16
|
169 public:
|
Chris@16
|
170 //! Constructor
|
Chris@16
|
171 scoped_thread_attribute(attribute_name const& name, attribute const& attr) :
|
Chris@16
|
172 m_pCore(core::get())
|
Chris@16
|
173 {
|
Chris@16
|
174 std::pair<
|
Chris@16
|
175 attribute_set::iterator,
|
Chris@16
|
176 bool
|
Chris@16
|
177 > res = m_pCore->add_thread_attribute(name, attr);
|
Chris@16
|
178 if (res.second)
|
Chris@16
|
179 m_itAttribute = res.first;
|
Chris@16
|
180 else
|
Chris@16
|
181 m_pCore.reset(); // if there already is a same-named attribute, don't register anything
|
Chris@16
|
182 }
|
Chris@16
|
183 //! Move constructor
|
Chris@16
|
184 scoped_thread_attribute(BOOST_RV_REF(scoped_thread_attribute) that) : m_itAttribute(that.m_itAttribute)
|
Chris@16
|
185 {
|
Chris@16
|
186 m_pCore.swap(that.m_pCore);
|
Chris@16
|
187 }
|
Chris@16
|
188
|
Chris@16
|
189 //! Destructor
|
Chris@16
|
190 ~scoped_thread_attribute()
|
Chris@16
|
191 {
|
Chris@16
|
192 if (!!m_pCore)
|
Chris@16
|
193 m_pCore->remove_thread_attribute(m_itAttribute);
|
Chris@16
|
194 }
|
Chris@16
|
195
|
Chris@16
|
196 #ifndef BOOST_LOG_BROKEN_REFERENCE_FROM_RVALUE_INIT
|
Chris@16
|
197 BOOST_DELETED_FUNCTION(scoped_thread_attribute(scoped_thread_attribute const&))
|
Chris@16
|
198 #else // BOOST_LOG_BROKEN_REFERENCE_FROM_RVALUE_INIT
|
Chris@16
|
199 scoped_thread_attribute(scoped_thread_attribute const& that) : m_itAttribute(that.m_itAttribute)
|
Chris@16
|
200 {
|
Chris@16
|
201 m_pCore.swap(const_cast< scoped_thread_attribute& >(that).m_pCore);
|
Chris@16
|
202 }
|
Chris@16
|
203 #endif // BOOST_LOG_BROKEN_REFERENCE_FROM_RVALUE_INIT
|
Chris@16
|
204
|
Chris@16
|
205 BOOST_DELETED_FUNCTION(scoped_thread_attribute& operator= (scoped_thread_attribute const&))
|
Chris@16
|
206 };
|
Chris@16
|
207
|
Chris@16
|
208 } // namespace aux
|
Chris@16
|
209
|
Chris@16
|
210 // Generator helper functions
|
Chris@16
|
211 /*!
|
Chris@16
|
212 * Registers a thread-specific attribute
|
Chris@16
|
213 *
|
Chris@16
|
214 * \param name Attribute name
|
Chris@16
|
215 * \param attr The attribute. Must not be NULL.
|
Chris@16
|
216 * \return An unspecified guard object which may be used to initialize a \c scoped_attribute variable.
|
Chris@16
|
217 */
|
Chris@16
|
218 BOOST_FORCEINLINE aux::scoped_thread_attribute add_scoped_thread_attribute(attribute_name const& name, attribute const& attr)
|
Chris@16
|
219 {
|
Chris@16
|
220 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
Chris@16
|
221 return aux::scoped_thread_attribute(name, attr);
|
Chris@16
|
222 #else
|
Chris@16
|
223 aux::scoped_thread_attribute guard(name, attr);
|
Chris@16
|
224 return boost::move(guard);
|
Chris@16
|
225 #endif
|
Chris@16
|
226 }
|
Chris@16
|
227
|
Chris@16
|
228 #ifndef BOOST_LOG_DOXYGEN_PASS
|
Chris@16
|
229
|
Chris@16
|
230 #define BOOST_LOG_SCOPED_THREAD_ATTR_INTERNAL(attr_name, attr, sentry_var_name)\
|
Chris@16
|
231 BOOST_LOG_UNUSED_VARIABLE(::boost::log::scoped_attribute, sentry_var_name,\
|
Chris@16
|
232 = ::boost::log::add_scoped_thread_attribute(attr_name, (attr)));
|
Chris@16
|
233
|
Chris@16
|
234 #endif // BOOST_LOG_DOXYGEN_PASS
|
Chris@16
|
235
|
Chris@16
|
236 //! The macro sets a scoped thread-wide attribute in a more compact way
|
Chris@16
|
237 #define BOOST_LOG_SCOPED_THREAD_ATTR(attr_name, attr)\
|
Chris@16
|
238 BOOST_LOG_SCOPED_THREAD_ATTR_INTERNAL(\
|
Chris@16
|
239 attr_name,\
|
Chris@16
|
240 attr,\
|
Chris@16
|
241 BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_scoped_thread_attr_sentry_))
|
Chris@16
|
242
|
Chris@16
|
243 //! The macro sets a scoped thread-wide tag in a more compact way
|
Chris@16
|
244 #define BOOST_LOG_SCOPED_THREAD_TAG(attr_name, attr_value)\
|
Chris@16
|
245 BOOST_LOG_SCOPED_THREAD_ATTR(attr_name, ::boost::log::attributes::make_constant(attr_value))
|
Chris@16
|
246
|
Chris@16
|
247 BOOST_LOG_CLOSE_NAMESPACE // namespace log
|
Chris@16
|
248
|
Chris@16
|
249 } // namespace boost
|
Chris@16
|
250
|
Chris@16
|
251 #include <boost/log/detail/footer.hpp>
|
Chris@16
|
252
|
Chris@16
|
253 #endif // BOOST_LOG_ATTRIBUTES_SCOPED_ATTRIBUTE_HPP_INCLUDED_
|