]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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> | |
20effc67 | 21 | #include <boost/type_traits/is_nothrow_move_constructible.hpp> |
7c673cae FG |
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 | |
20effc67 | 80 | boost::log::aux::multiple_unique_lock2< threading_model, threading_model > |
7c673cae FG |
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; | |
91 | 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 | */ | |
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 | */ | |
109 | basic_channel_logger(basic_channel_logger const& that) : | |
110 | base_type(static_cast< base_type const& >(that)), | |
1e59de90 | 111 | m_ChannelAttr(that.m_ChannelAttr.get()) |
7c673cae | 112 | { |
20effc67 | 113 | // Our attributes must refer to our channel attribute |
7c673cae FG |
114 | base_type::attributes()[boost::log::aux::default_attribute_names::channel()] = m_ChannelAttr; |
115 | } | |
116 | /*! | |
117 | * Move constructor | |
118 | */ | |
20effc67 | 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) : |
7c673cae FG |
120 | base_type(boost::move(static_cast< base_type& >(that))), |
121 | m_ChannelAttr(boost::move(that.m_ChannelAttr)) | |
122 | { | |
7c673cae FG |
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 > | |
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 | */ | |
143 | 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 | */ | |
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 | */ | |
164 | channel_attribute const& get_channel_attribute() const { return m_ChannelAttr; } | |
165 | ||
166 | /*! | |
167 | * Unlocked \c open_record | |
168 | */ | |
169 | template< typename ArgsT > | |
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 | */ | |
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 > | |
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 > | |
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_ |