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