• 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   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