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 channel_feature.hpp 9 * \author Andrey Semashev 10 * \date 28.02.2008 11 * 12 * The header contains implementation of a channel support feature. 13 */ 14 15 #ifndef BOOST_LOG_SOURCES_CHANNEL_FEATURE_HPP_INCLUDED_ 16 #define BOOST_LOG_SOURCES_CHANNEL_FEATURE_HPP_INCLUDED_ 17 18 #include <string> 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/keywords/channel.hpp> 26 #include <boost/log/attributes/mutable_constant.hpp> 27 #include <boost/log/utility/strictest_lock.hpp> 28 #include <boost/log/core/record.hpp> 29 #include <boost/log/detail/header.hpp> 30 31 #ifdef BOOST_HAS_PRAGMA_ONCE 32 #pragma once 33 #endif 34 35 namespace boost { 36 37 BOOST_LOG_OPEN_NAMESPACE 38 39 namespace sources { 40 41 /*! 42 * \brief Channel feature implementation 43 */ 44 template< typename BaseT, typename ChannelT > 45 class basic_channel_logger : 46 public BaseT 47 { 48 //! Base type 49 typedef BaseT base_type; 50 typedef basic_channel_logger this_type; 51 BOOST_COPYABLE_AND_MOVABLE_ALT(this_type) 52 53 public: 54 //! Character type 55 typedef typename base_type::char_type char_type; 56 //! Final type 57 typedef typename base_type::final_type final_type; 58 //! Threading model being used 59 typedef typename base_type::threading_model threading_model; 60 61 //! Channel type 62 typedef ChannelT channel_type; 63 //! Channel attribute type 64 typedef attributes::mutable_constant< channel_type > channel_attribute; 65 66 //! Lock requirement for the \c open_record_unlocked method 67 typedef typename strictest_lock< 68 typename base_type::open_record_lock, 69 #ifndef BOOST_LOG_NO_THREADS 70 boost::log::aux::exclusive_lock_guard< threading_model > 71 #else 72 no_lock< threading_model > 73 #endif // !defined(BOOST_LOG_NO_THREADS) 74 >::type open_record_lock; 75 76 //! Lock requirement for the \c swap_unlocked method 77 typedef typename strictest_lock< 78 typename base_type::swap_lock, 79 #ifndef BOOST_LOG_NO_THREADS 80 boost::log::aux::multiple_unique_lock2< threading_model, threading_model > 81 #else 82 no_lock< threading_model > 83 #endif // !defined(BOOST_LOG_NO_THREADS) 84 >::type swap_lock; 85 86 private: 87 //! Default channel name generator 88 struct make_default_channel_name 89 { 90 typedef channel_type result_type; operator ()boost::sources::basic_channel_logger::make_default_channel_name91 result_type operator() () const { return result_type(); } 92 }; 93 94 private: 95 //! Channel attribute 96 channel_attribute m_ChannelAttr; 97 98 public: 99 /*! 100 * Default constructor. The constructed logger has the default-constructed channel name. 101 */ basic_channel_logger()102 basic_channel_logger() : base_type(), m_ChannelAttr(channel_type()) 103 { 104 base_type::add_attribute_unlocked(boost::log::aux::default_attribute_names::channel(), m_ChannelAttr); 105 } 106 /*! 107 * Copy constructor 108 */ basic_channel_logger(basic_channel_logger const & that)109 basic_channel_logger(basic_channel_logger const& that) : 110 base_type(static_cast< base_type const& >(that)), 111 m_ChannelAttr(that.m_ChannelAttr) 112 { 113 // Our attributes must refer to our channel attribute 114 base_type::attributes()[boost::log::aux::default_attribute_names::channel()] = m_ChannelAttr; 115 } 116 /*! 117 * Move constructor 118 */ BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<base_type>::value && boost::is_nothrow_move_constructible<channel_attribute>::value)119 basic_channel_logger(BOOST_RV_REF(basic_channel_logger) that) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible< base_type >::value && boost::is_nothrow_move_constructible< channel_attribute >::value) : 120 base_type(boost::move(static_cast< base_type& >(that))), 121 m_ChannelAttr(boost::move(that.m_ChannelAttr)) 122 { 123 } 124 /*! 125 * Constructor with arguments. Allows to register a channel name attribute on construction. 126 * 127 * \param args A set of named arguments. The following arguments are supported: 128 * \li \c channel - a string that represents the channel name 129 */ 130 template< typename ArgsT > basic_channel_logger(ArgsT const & args)131 explicit basic_channel_logger(ArgsT const& args) : 132 base_type(args), 133 m_ChannelAttr(args[keywords::channel || make_default_channel_name()]) 134 { 135 base_type::add_attribute_unlocked(boost::log::aux::default_attribute_names::channel(), m_ChannelAttr); 136 } 137 138 /*! 139 * The observer of the channel name 140 * 141 * \return The channel name that was set by the logger 142 */ channel() const143 channel_type channel() const 144 { 145 BOOST_LOG_EXPR_IF_MT(boost::log::aux::shared_lock_guard< const threading_model > lock(this->get_threading_model());) 146 return m_ChannelAttr.get(); 147 } 148 149 /*! 150 * The setter of the channel name 151 * 152 * \param ch The channel name to be set for the logger 153 */ channel(channel_type const & ch)154 void channel(channel_type const& ch) 155 { 156 BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< threading_model > lock(this->get_threading_model());) 157 m_ChannelAttr.set(ch); 158 } 159 160 protected: 161 /*! 162 * Channel attribute accessor 163 */ get_channel_attribute() const164 channel_attribute const& get_channel_attribute() const { return m_ChannelAttr; } 165 166 /*! 167 * Unlocked \c open_record 168 */ 169 template< typename ArgsT > open_record_unlocked(ArgsT const & args)170 record open_record_unlocked(ArgsT const& args) 171 { 172 return open_record_with_channel_unlocked(args, args[keywords::channel | parameter::void_()]); 173 } 174 175 /*! 176 * Unlocked swap 177 */ swap_unlocked(basic_channel_logger & that)178 void swap_unlocked(basic_channel_logger& that) 179 { 180 base_type::swap_unlocked(static_cast< base_type& >(that)); 181 m_ChannelAttr.swap(that.m_ChannelAttr); 182 } 183 184 private: 185 //! The \c open_record implementation for the case when the channel is specified in log statement 186 template< typename ArgsT, typename T > open_record_with_channel_unlocked(ArgsT const & args,T const & ch)187 record open_record_with_channel_unlocked(ArgsT const& args, T const& ch) 188 { 189 m_ChannelAttr.set(ch); 190 return base_type::open_record_unlocked(args); 191 } 192 //! The \c open_record implementation for the case when the channel is not specified in log statement 193 template< typename ArgsT > open_record_with_channel_unlocked(ArgsT const & args,parameter::void_)194 record open_record_with_channel_unlocked(ArgsT const& args, parameter::void_) 195 { 196 return base_type::open_record_unlocked(args); 197 } 198 }; 199 200 /*! 201 * \brief Channel support feature 202 * 203 * The logger with this feature automatically registers an attribute with the specified 204 * on construction value, which is a channel name. The channel name can be modified 205 * through the logger life time, either by calling the \c channel method or by specifying 206 * the name in the logging statement. 207 * 208 * The type of the channel name can be customized by providing it as a template parameter 209 * to the feature template. By default, a string will be used. 210 */ 211 template< typename ChannelT = std::string > 212 struct channel 213 { 214 template< typename BaseT > 215 struct apply 216 { 217 typedef basic_channel_logger< 218 BaseT, 219 ChannelT 220 > type; 221 }; 222 }; 223 224 } // namespace sources 225 226 BOOST_LOG_CLOSE_NAMESPACE // namespace log 227 228 } // namespace boost 229 230 //! The macro allows to put a record with a specific channel name into log 231 #define BOOST_LOG_STREAM_CHANNEL(logger, chan)\ 232 BOOST_LOG_STREAM_WITH_PARAMS((logger), (::boost::log::keywords::channel = (chan))) 233 234 #ifndef BOOST_LOG_NO_SHORTHAND_NAMES 235 236 //! An equivalent to BOOST_LOG_STREAM_CHANNEL(logger, chan) 237 #define BOOST_LOG_CHANNEL(logger, chan) BOOST_LOG_STREAM_CHANNEL(logger, chan) 238 239 #endif // BOOST_LOG_NO_SHORTHAND_NAMES 240 241 #include <boost/log/detail/footer.hpp> 242 243 #endif // BOOST_LOG_SOURCES_CHANNEL_FEATURE_HPP_INCLUDED_ 244