severity_feature.hpp 10 KB

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