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

source code of boost/libs/log/include/boost/log/sources/severity_feature.hpp