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 severity_feature.hpp
|
Chris@16
|
9 * \author Andrey Semashev
|
Chris@16
|
10 * \date 08.03.2007
|
Chris@16
|
11 *
|
Chris@16
|
12 * The header contains implementation of a severity level support feature.
|
Chris@16
|
13 */
|
Chris@16
|
14
|
Chris@16
|
15 #ifndef BOOST_LOG_SOURCES_SEVERITY_FEATURE_HPP_INCLUDED_
|
Chris@16
|
16 #define BOOST_LOG_SOURCES_SEVERITY_FEATURE_HPP_INCLUDED_
|
Chris@16
|
17
|
Chris@16
|
18 #include <boost/cstdint.hpp>
|
Chris@16
|
19 #include <boost/static_assert.hpp>
|
Chris@16
|
20 #include <boost/smart_ptr/intrusive_ptr.hpp>
|
Chris@16
|
21 #include <boost/move/core.hpp>
|
Chris@16
|
22 #include <boost/move/utility.hpp>
|
Chris@16
|
23 #include <boost/log/detail/config.hpp>
|
Chris@16
|
24 #include <boost/log/detail/locks.hpp>
|
Chris@16
|
25 #include <boost/log/detail/default_attribute_names.hpp>
|
Chris@16
|
26 #include <boost/log/attributes/attribute.hpp>
|
Chris@16
|
27 #include <boost/log/attributes/attribute_cast.hpp>
|
Chris@16
|
28 #include <boost/log/attributes/attribute_value_impl.hpp>
|
Chris@16
|
29 #include <boost/log/utility/strictest_lock.hpp>
|
Chris@16
|
30 #include <boost/log/utility/type_dispatch/type_dispatcher.hpp>
|
Chris@16
|
31 #include <boost/log/keywords/severity.hpp>
|
Chris@16
|
32 #include <boost/log/core/record.hpp>
|
Chris@16
|
33 #include <boost/log/detail/header.hpp>
|
Chris@16
|
34
|
Chris@16
|
35 #ifdef BOOST_HAS_PRAGMA_ONCE
|
Chris@16
|
36 #pragma once
|
Chris@16
|
37 #endif
|
Chris@16
|
38
|
Chris@16
|
39 namespace boost {
|
Chris@16
|
40
|
Chris@16
|
41 BOOST_LOG_OPEN_NAMESPACE
|
Chris@16
|
42
|
Chris@16
|
43 namespace sources {
|
Chris@16
|
44
|
Chris@16
|
45 namespace aux {
|
Chris@16
|
46
|
Chris@16
|
47 //! The method returns the storage for severity level for the current thread
|
Chris@16
|
48 BOOST_LOG_API uintmax_t& get_severity_level();
|
Chris@16
|
49
|
Chris@16
|
50 //! Severity level attribute implementation
|
Chris@16
|
51 template< typename LevelT >
|
Chris@16
|
52 class severity_level :
|
Chris@16
|
53 public attribute
|
Chris@16
|
54 {
|
Chris@16
|
55 typedef severity_level this_type;
|
Chris@16
|
56 BOOST_COPYABLE_AND_MOVABLE(this_type)
|
Chris@16
|
57
|
Chris@16
|
58 public:
|
Chris@16
|
59 //! Stored level type
|
Chris@16
|
60 typedef LevelT value_type;
|
Chris@16
|
61 BOOST_STATIC_ASSERT_MSG(sizeof(value_type) <= sizeof(uintmax_t), "Boost.Log: Unsupported severity level type, the severity level must fit into uintmax_t");
|
Chris@16
|
62
|
Chris@16
|
63 protected:
|
Chris@16
|
64 //! Factory implementation
|
Chris@16
|
65 class BOOST_SYMBOL_VISIBLE impl :
|
Chris@16
|
66 public attribute_value::impl
|
Chris@16
|
67 {
|
Chris@16
|
68 public:
|
Chris@16
|
69 //! The method dispatches the value to the given object
|
Chris@16
|
70 bool dispatch(type_dispatcher& dispatcher)
|
Chris@16
|
71 {
|
Chris@16
|
72 type_dispatcher::callback< value_type > callback = dispatcher.get_callback< value_type >();
|
Chris@16
|
73 if (callback)
|
Chris@16
|
74 {
|
Chris@16
|
75 callback(reinterpret_cast< value_type const& >(get_severity_level()));
|
Chris@16
|
76 return true;
|
Chris@16
|
77 }
|
Chris@16
|
78 else
|
Chris@16
|
79 return false;
|
Chris@16
|
80 }
|
Chris@16
|
81
|
Chris@16
|
82 //! The method is called when the attribute value is passed to another thread
|
Chris@16
|
83 intrusive_ptr< attribute_value::impl > detach_from_thread()
|
Chris@16
|
84 {
|
Chris@16
|
85 #if !defined(BOOST_LOG_NO_THREADS)
|
Chris@16
|
86 return new attributes::attribute_value_impl< value_type >(
|
Chris@16
|
87 reinterpret_cast< value_type const& >(get_severity_level()));
|
Chris@16
|
88 #else
|
Chris@16
|
89 // With multithreading disabled we may safely return this here. This method will not be called anyway.
|
Chris@16
|
90 return this;
|
Chris@16
|
91 #endif
|
Chris@16
|
92 }
|
Chris@16
|
93 };
|
Chris@16
|
94
|
Chris@16
|
95 public:
|
Chris@16
|
96 //! Default constructor
|
Chris@16
|
97 severity_level() : attribute(new impl())
|
Chris@16
|
98 {
|
Chris@16
|
99 }
|
Chris@16
|
100 //! Copy constructor
|
Chris@16
|
101 severity_level(severity_level const& that) : attribute(static_cast< attribute const& >(that))
|
Chris@16
|
102 {
|
Chris@16
|
103 }
|
Chris@16
|
104 //! Move constructor
|
Chris@16
|
105 severity_level(BOOST_RV_REF(severity_level) that) : attribute(boost::move(static_cast< attribute& >(that)))
|
Chris@16
|
106 {
|
Chris@16
|
107 }
|
Chris@16
|
108 //! Constructor for casting support
|
Chris@16
|
109 explicit severity_level(attributes::cast_source const& source) :
|
Chris@16
|
110 attribute(source.as< impl >())
|
Chris@16
|
111 {
|
Chris@16
|
112 }
|
Chris@16
|
113
|
Chris@16
|
114 /*!
|
Chris@16
|
115 * Copy assignment
|
Chris@16
|
116 */
|
Chris@16
|
117 severity_level& operator= (BOOST_COPY_ASSIGN_REF(severity_level) that)
|
Chris@16
|
118 {
|
Chris@16
|
119 attribute::operator= (that);
|
Chris@16
|
120 return *this;
|
Chris@16
|
121 }
|
Chris@16
|
122
|
Chris@16
|
123 /*!
|
Chris@16
|
124 * Move assignment
|
Chris@16
|
125 */
|
Chris@16
|
126 severity_level& operator= (BOOST_RV_REF(severity_level) that)
|
Chris@16
|
127 {
|
Chris@16
|
128 this->swap(that);
|
Chris@16
|
129 return *this;
|
Chris@16
|
130 }
|
Chris@16
|
131
|
Chris@16
|
132 //! The method sets the actual level
|
Chris@16
|
133 void set_value(value_type level)
|
Chris@16
|
134 {
|
Chris@16
|
135 reinterpret_cast< value_type& >(get_severity_level()) = level;
|
Chris@16
|
136 }
|
Chris@16
|
137 };
|
Chris@16
|
138
|
Chris@16
|
139 } // namespace aux
|
Chris@16
|
140
|
Chris@16
|
141 /*!
|
Chris@16
|
142 * \brief Severity level feature implementation
|
Chris@16
|
143 */
|
Chris@16
|
144 template< typename BaseT, typename LevelT = int >
|
Chris@16
|
145 class basic_severity_logger :
|
Chris@16
|
146 public BaseT
|
Chris@16
|
147 {
|
Chris@16
|
148 //! Base type
|
Chris@16
|
149 typedef BaseT base_type;
|
Chris@16
|
150 typedef basic_severity_logger this_type;
|
Chris@16
|
151 BOOST_COPYABLE_AND_MOVABLE_ALT(this_type)
|
Chris@16
|
152
|
Chris@16
|
153 public:
|
Chris@16
|
154 //! Character type
|
Chris@16
|
155 typedef typename base_type::char_type char_type;
|
Chris@16
|
156 //! Final type
|
Chris@16
|
157 typedef typename base_type::final_type final_type;
|
Chris@16
|
158 //! Threading model being used
|
Chris@16
|
159 typedef typename base_type::threading_model threading_model;
|
Chris@16
|
160
|
Chris@16
|
161 //! Severity level type
|
Chris@16
|
162 typedef LevelT severity_level;
|
Chris@16
|
163 //! Severity attribute type
|
Chris@16
|
164 typedef aux::severity_level< severity_level > severity_attribute;
|
Chris@16
|
165
|
Chris@16
|
166 #if defined(BOOST_LOG_DOXYGEN_PASS)
|
Chris@16
|
167 //! Lock requirement for the \c open_record_unlocked method
|
Chris@16
|
168 typedef typename strictest_lock<
|
Chris@16
|
169 typename base_type::open_record_lock,
|
Chris@16
|
170 no_lock< threading_model >
|
Chris@16
|
171 >::type open_record_lock;
|
Chris@16
|
172 #endif // defined(BOOST_LOG_DOXYGEN_PASS)
|
Chris@16
|
173
|
Chris@16
|
174 //! Lock requirement for the \c swap_unlocked method
|
Chris@16
|
175 typedef typename strictest_lock<
|
Chris@16
|
176 typename base_type::swap_lock,
|
Chris@16
|
177 #ifndef BOOST_LOG_NO_THREADS
|
Chris@16
|
178 boost::log::aux::exclusive_lock_guard< threading_model >
|
Chris@16
|
179 #else
|
Chris@16
|
180 no_lock< threading_model >
|
Chris@16
|
181 #endif // !defined(BOOST_LOG_NO_THREADS)
|
Chris@16
|
182 >::type swap_lock;
|
Chris@16
|
183
|
Chris@16
|
184 private:
|
Chris@16
|
185 //! Default severity
|
Chris@16
|
186 severity_level m_DefaultSeverity;
|
Chris@16
|
187 //! Severity attribute
|
Chris@16
|
188 severity_attribute m_SeverityAttr;
|
Chris@16
|
189
|
Chris@16
|
190 public:
|
Chris@16
|
191 /*!
|
Chris@16
|
192 * Default constructor. The constructed logger will have a severity attribute registered.
|
Chris@16
|
193 * The default level for log records will be 0.
|
Chris@16
|
194 */
|
Chris@16
|
195 basic_severity_logger() :
|
Chris@16
|
196 base_type(),
|
Chris@16
|
197 m_DefaultSeverity(static_cast< severity_level >(0))
|
Chris@16
|
198 {
|
Chris@16
|
199 base_type::add_attribute_unlocked(boost::log::aux::default_attribute_names::severity(), m_SeverityAttr);
|
Chris@16
|
200 }
|
Chris@16
|
201 /*!
|
Chris@16
|
202 * Copy constructor
|
Chris@16
|
203 */
|
Chris@16
|
204 basic_severity_logger(basic_severity_logger const& that) :
|
Chris@16
|
205 base_type(static_cast< base_type const& >(that)),
|
Chris@16
|
206 m_DefaultSeverity(that.m_DefaultSeverity),
|
Chris@16
|
207 m_SeverityAttr(that.m_SeverityAttr)
|
Chris@16
|
208 {
|
Chris@16
|
209 base_type::attributes()[boost::log::aux::default_attribute_names::severity()] = m_SeverityAttr;
|
Chris@16
|
210 }
|
Chris@16
|
211 /*!
|
Chris@16
|
212 * Move constructor
|
Chris@16
|
213 */
|
Chris@16
|
214 basic_severity_logger(BOOST_RV_REF(basic_severity_logger) that) :
|
Chris@16
|
215 base_type(boost::move(static_cast< base_type& >(that))),
|
Chris@16
|
216 m_DefaultSeverity(boost::move(that.m_DefaultSeverity)),
|
Chris@16
|
217 m_SeverityAttr(boost::move(that.m_SeverityAttr))
|
Chris@16
|
218 {
|
Chris@16
|
219 base_type::attributes()[boost::log::aux::default_attribute_names::severity()] = m_SeverityAttr;
|
Chris@16
|
220 }
|
Chris@16
|
221 /*!
|
Chris@16
|
222 * Constructor with named arguments. Allows to setup the default level for log records.
|
Chris@16
|
223 *
|
Chris@16
|
224 * \param args A set of named arguments. The following arguments are supported:
|
Chris@16
|
225 * \li \c severity - default severity value
|
Chris@16
|
226 */
|
Chris@16
|
227 template< typename ArgsT >
|
Chris@16
|
228 explicit basic_severity_logger(ArgsT const& args) :
|
Chris@16
|
229 base_type(args),
|
Chris@16
|
230 m_DefaultSeverity(args[keywords::severity | severity_level()])
|
Chris@16
|
231 {
|
Chris@16
|
232 base_type::add_attribute_unlocked(boost::log::aux::default_attribute_names::severity(), m_SeverityAttr);
|
Chris@16
|
233 }
|
Chris@16
|
234
|
Chris@16
|
235 /*!
|
Chris@16
|
236 * Default severity value getter
|
Chris@16
|
237 */
|
Chris@16
|
238 severity_level default_severity() const { return m_DefaultSeverity; }
|
Chris@16
|
239
|
Chris@16
|
240 protected:
|
Chris@16
|
241 /*!
|
Chris@16
|
242 * Severity attribute accessor
|
Chris@16
|
243 */
|
Chris@16
|
244 severity_attribute const& get_severity_attribute() const { return m_SeverityAttr; }
|
Chris@16
|
245
|
Chris@16
|
246 /*!
|
Chris@16
|
247 * Unlocked \c open_record
|
Chris@16
|
248 */
|
Chris@16
|
249 template< typename ArgsT >
|
Chris@16
|
250 record open_record_unlocked(ArgsT const& args)
|
Chris@16
|
251 {
|
Chris@16
|
252 m_SeverityAttr.set_value(args[keywords::severity | m_DefaultSeverity]);
|
Chris@16
|
253 return base_type::open_record_unlocked(args);
|
Chris@16
|
254 }
|
Chris@16
|
255
|
Chris@16
|
256 //! Unlocked \c swap
|
Chris@16
|
257 void swap_unlocked(basic_severity_logger& that)
|
Chris@16
|
258 {
|
Chris@16
|
259 base_type::swap_unlocked(static_cast< base_type& >(that));
|
Chris@16
|
260 severity_level t = m_DefaultSeverity;
|
Chris@16
|
261 m_DefaultSeverity = that.m_DefaultSeverity;
|
Chris@16
|
262 that.m_DefaultSeverity = t;
|
Chris@16
|
263 m_SeverityAttr.swap(that.m_SeverityAttr);
|
Chris@16
|
264 }
|
Chris@16
|
265 };
|
Chris@16
|
266
|
Chris@16
|
267 /*!
|
Chris@16
|
268 * \brief Severity level support feature
|
Chris@16
|
269 *
|
Chris@16
|
270 * The logger with this feature registers a special attribute with an integral value type on construction.
|
Chris@16
|
271 * This attribute will provide severity level for each log record being made through the logger.
|
Chris@16
|
272 * The severity level can be omitted on logging record construction, in which case the default
|
Chris@16
|
273 * level will be used. The default level can also be customized by passing it to the logger constructor.
|
Chris@16
|
274 *
|
Chris@16
|
275 * The type of the severity level attribute can be specified as a template parameter for the feature
|
Chris@16
|
276 * template. By default, \c int will be used.
|
Chris@16
|
277 */
|
Chris@16
|
278 template< typename LevelT = int >
|
Chris@16
|
279 struct severity
|
Chris@16
|
280 {
|
Chris@16
|
281 template< typename BaseT >
|
Chris@16
|
282 struct apply
|
Chris@16
|
283 {
|
Chris@16
|
284 typedef basic_severity_logger<
|
Chris@16
|
285 BaseT,
|
Chris@16
|
286 LevelT
|
Chris@16
|
287 > type;
|
Chris@16
|
288 };
|
Chris@16
|
289 };
|
Chris@16
|
290
|
Chris@16
|
291 } // namespace sources
|
Chris@16
|
292
|
Chris@16
|
293 BOOST_LOG_CLOSE_NAMESPACE // namespace log
|
Chris@16
|
294
|
Chris@16
|
295 } // namespace boost
|
Chris@16
|
296
|
Chris@16
|
297 //! The macro allows to put a record with a specific severity level into log
|
Chris@16
|
298 #define BOOST_LOG_STREAM_SEV(logger, lvl)\
|
Chris@16
|
299 BOOST_LOG_STREAM_WITH_PARAMS((logger), (::boost::log::keywords::severity = (lvl)))
|
Chris@16
|
300
|
Chris@16
|
301 #ifndef BOOST_LOG_NO_SHORTHAND_NAMES
|
Chris@16
|
302
|
Chris@16
|
303 //! An equivalent to BOOST_LOG_STREAM_SEV(logger, lvl)
|
Chris@16
|
304 #define BOOST_LOG_SEV(logger, lvl) BOOST_LOG_STREAM_SEV(logger, lvl)
|
Chris@16
|
305
|
Chris@16
|
306 #endif // BOOST_LOG_NO_SHORTHAND_NAMES
|
Chris@16
|
307
|
Chris@16
|
308 #include <boost/log/detail/footer.hpp>
|
Chris@16
|
309
|
Chris@16
|
310 #endif // BOOST_LOG_SOURCES_SEVERITY_FEATURE_HPP_INCLUDED_
|