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