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