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 basic_logger.hpp
9 * \author Andrey Semashev
10 * \date 08.03.2007
11 *
12 * The header contains implementation of a base class for loggers. Convenience macros
13 * for defining custom loggers are also provided.
14 */
15
16 #ifndef BOOST_LOG_SOURCES_BASIC_LOGGER_HPP_INCLUDED_
17 #define BOOST_LOG_SOURCES_BASIC_LOGGER_HPP_INCLUDED_
18
19 #include <exception>
20 #include <utility>
21 #include <ostream>
22 #include <boost/assert.hpp>
23 #include <boost/move/core.hpp>
24 #include <boost/move/utility_core.hpp>
25 #include <boost/core/addressof.hpp>
26 #include <boost/type_traits/is_nothrow_swappable.hpp>
27 #include <boost/type_traits/is_nothrow_move_constructible.hpp>
28 #include <boost/preprocessor/facilities/empty.hpp>
29 #include <boost/preprocessor/facilities/identity.hpp>
30 #include <boost/preprocessor/repetition/enum_params.hpp>
31 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
32 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
33 #include <boost/preprocessor/seq/enum.hpp>
34 #include <boost/log/detail/config.hpp>
35 #include <boost/log/detail/parameter_tools.hpp>
36 #include <boost/log/attributes/attribute_set.hpp>
37 #include <boost/log/attributes/attribute_name.hpp>
38 #include <boost/log/attributes/attribute.hpp>
39 #include <boost/log/core/core.hpp>
40 #include <boost/log/core/record.hpp>
41 #include <boost/log/sources/features.hpp>
42 #include <boost/log/sources/threading_models.hpp>
43 #include <boost/log/detail/header.hpp>
44
45 #ifdef BOOST_HAS_PRAGMA_ONCE
46 #pragma once
47 #endif
48
49 namespace boost {
50
51 BOOST_LOG_OPEN_NAMESPACE
52
53 namespace sources {
54
55 /*!
56 * \brief Basic logger class
57 *
58 * The \c basic_logger class template serves as a base class for all loggers
59 * provided by the library. It can also be used as a base for user-defined
60 * loggers. The template parameters are:
61 *
62 * \li \c CharT - logging character type
63 * \li \c FinalT - final type of the logger that eventually derives from
64 * the \c basic_logger. There may be other classes in the hierarchy
65 * between the final class and \c basic_logger.
66 * \li \c ThreadingModelT - threading model policy. Must provide methods
67 * of the Boost.Thread locking concept used in \c basic_logger class
68 * and all its derivatives in the hierarchy up to the \c FinalT class.
69 * The \c basic_logger class itself requires methods of the
70 * SharedLockable concept. The threading model policy must also be
71 * default and copy-constructible and support member function \c swap.
72 * There are currently two policies provided: \c single_thread_model
73 * and \c multi_thread_model.
74 *
75 * The logger implements fundamental facilities of loggers, such as storing
76 * source-specific attribute set and formatting log record messages. The basic
77 * logger interacts with the logging core in order to apply filtering and
78 * pass records to sinks.
79 */
80 template< typename CharT, typename FinalT, typename ThreadingModelT >
81 class basic_logger :
82 public ThreadingModelT
83 {
84 typedef basic_logger this_type;
85 BOOST_COPYABLE_AND_MOVABLE_ALT(this_type)
86
87 public:
88 //! Character type
89 typedef CharT char_type;
90 //! Final logger type
91 typedef FinalT final_type;
92 //! Threading model type
93 typedef ThreadingModelT threading_model;
94
95 #if !defined(BOOST_LOG_NO_THREADS)
96 //! Lock requirement for the swap_unlocked method
97 typedef boost::log::aux::multiple_unique_lock2< threading_model, threading_model > swap_lock;
98 //! Lock requirement for the add_attribute_unlocked method
99 typedef boost::log::aux::exclusive_lock_guard< threading_model > add_attribute_lock;
100 //! Lock requirement for the remove_attribute_unlocked method
101 typedef boost::log::aux::exclusive_lock_guard< threading_model > remove_attribute_lock;
102 //! Lock requirement for the remove_all_attributes_unlocked method
103 typedef boost::log::aux::exclusive_lock_guard< threading_model > remove_all_attributes_lock;
104 //! Lock requirement for the get_attributes method
105 typedef boost::log::aux::shared_lock_guard< const threading_model > get_attributes_lock;
106 //! Lock requirement for the open_record_unlocked method
107 typedef boost::log::aux::shared_lock_guard< threading_model > open_record_lock;
108 //! Lock requirement for the set_attributes method
109 typedef boost::log::aux::exclusive_lock_guard< threading_model > set_attributes_lock;
110 #else
111 typedef no_lock< threading_model > swap_lock;
112 typedef no_lock< threading_model > add_attribute_lock;
113 typedef no_lock< threading_model > remove_attribute_lock;
114 typedef no_lock< threading_model > remove_all_attributes_lock;
115 typedef no_lock< const threading_model > get_attributes_lock;
116 typedef no_lock< threading_model > open_record_lock;
117 typedef no_lock< threading_model > set_attributes_lock;
118 #endif
119
120 //! Lock requirement for the push_record_unlocked method
121 typedef no_lock< threading_model > push_record_lock;
122
123 private:
124 //! A pointer to the logging system
125 core_ptr m_pCore;
126
127 //! Logger-specific attribute set
128 attribute_set m_Attributes;
129
130 public:
131 /*!
132 * Constructor. Initializes internal data structures of the basic logger class,
133 * acquires reference to the logging core.
134 */
basic_logger()135 basic_logger() :
136 threading_model(),
137 m_pCore(core::get())
138 {
139 }
140 /*!
141 * Copy constructor. Copies all attributes from the source logger.
142 *
143 * \note Not thread-safe. The source logger must be locked in the final class before copying.
144 *
145 * \param that Source logger
146 */
basic_logger(basic_logger const & that)147 basic_logger(basic_logger const& that) :
148 threading_model(static_cast< threading_model const& >(that)),
149 m_pCore(that.m_pCore),
150 m_Attributes(that.m_Attributes)
151 {
152 }
153 /*!
154 * Move constructor. Moves all attributes from the source logger.
155 *
156 * \note Not thread-safe. The source logger must be locked in the final class before copying.
157 *
158 * \param that Source logger
159 */
BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<threading_model>::value && boost::is_nothrow_move_constructible<core_ptr>::value && boost::is_nothrow_move_constructible<attribute_set>::value)160 basic_logger(BOOST_RV_REF(basic_logger) that) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible< threading_model >::value &&
161 boost::is_nothrow_move_constructible< core_ptr >::value &&
162 boost::is_nothrow_move_constructible< attribute_set >::value) :
163 threading_model(boost::move(static_cast< threading_model& >(that))),
164 m_pCore(boost::move(that.m_pCore)),
165 m_Attributes(boost::move(that.m_Attributes))
166 {
167 }
168 /*!
169 * Constructor with named arguments. The constructor ignores all arguments. The result of
170 * construction is equivalent to default construction.
171 */
172 template< typename ArgsT >
basic_logger(ArgsT const &)173 explicit basic_logger(ArgsT const&) :
174 threading_model(),
175 m_pCore(core::get())
176 {
177 }
178
179 protected:
180 /*!
181 * An accessor to the logging system pointer
182 */
core() const183 core_ptr const& core() const { return m_pCore; }
184 /*!
185 * An accessor to the logger attributes
186 */
attributes()187 attribute_set& attributes() { return m_Attributes; }
188 /*!
189 * An accessor to the logger attributes
190 */
attributes() const191 attribute_set const& attributes() const { return m_Attributes; }
192 /*!
193 * An accessor to the threading model base
194 */
get_threading_model()195 threading_model& get_threading_model() BOOST_NOEXCEPT { return *this; }
196 /*!
197 * An accessor to the threading model base
198 */
get_threading_model() const199 threading_model const& get_threading_model() const BOOST_NOEXCEPT { return *this; }
200 /*!
201 * An accessor to the final logger
202 */
final_this()203 final_type* final_this() BOOST_NOEXCEPT
204 {
205 BOOST_LOG_ASSUME(this != NULL);
206 return static_cast< final_type* >(this);
207 }
208 /*!
209 * An accessor to the final logger
210 */
final_this() const211 final_type const* final_this() const BOOST_NOEXCEPT
212 {
213 BOOST_LOG_ASSUME(this != NULL);
214 return static_cast< final_type const* >(this);
215 }
216
217 /*!
218 * Unlocked \c swap
219 */
swap_unlocked(basic_logger & that)220 void swap_unlocked(basic_logger& that)
221 {
222 get_threading_model().swap(that.get_threading_model());
223 m_Attributes.swap(that.m_Attributes);
224 }
225
226 /*!
227 * Unlocked \c add_attribute
228 */
add_attribute_unlocked(attribute_name const & name,attribute const & attr)229 std::pair< attribute_set::iterator, bool > add_attribute_unlocked(attribute_name const& name, attribute const& attr)
230 {
231 return m_Attributes.insert(name, attr);
232 }
233
234 /*!
235 * Unlocked \c remove_attribute
236 */
remove_attribute_unlocked(attribute_set::iterator it)237 void remove_attribute_unlocked(attribute_set::iterator it)
238 {
239 m_Attributes.erase(it);
240 }
241
242 /*!
243 * Unlocked \c remove_all_attributes
244 */
remove_all_attributes_unlocked()245 void remove_all_attributes_unlocked()
246 {
247 m_Attributes.clear();
248 }
249
250 /*!
251 * Unlocked \c open_record
252 */
open_record_unlocked()253 record open_record_unlocked()
254 {
255 return m_pCore->open_record(m_Attributes);
256 }
257 /*!
258 * Unlocked \c open_record
259 */
260 template< typename ArgsT >
open_record_unlocked(ArgsT const &)261 record open_record_unlocked(ArgsT const&)
262 {
263 return m_pCore->open_record(m_Attributes);
264 }
265
266 /*!
267 * Unlocked \c push_record
268 */
push_record_unlocked(BOOST_RV_REF (record)rec)269 void push_record_unlocked(BOOST_RV_REF(record) rec)
270 {
271 m_pCore->push_record(boost::move(rec));
272 }
273
274 /*!
275 * Unlocked \c get_attributes
276 */
get_attributes_unlocked() const277 attribute_set get_attributes_unlocked() const
278 {
279 return m_Attributes;
280 }
281
282 /*!
283 * Unlocked \c set_attributes
284 */
set_attributes_unlocked(attribute_set const & attrs)285 void set_attributes_unlocked(attribute_set const& attrs)
286 {
287 m_Attributes = attrs;
288 }
289
290 //! Assignment is closed (should be implemented through copy and swap in the final class)
291 BOOST_DELETED_FUNCTION(basic_logger& operator= (basic_logger const&))
292 };
293
294 /*!
295 * Free-standing swap for all loggers
296 */
297 template< typename CharT, typename FinalT, typename ThreadingModelT >
swap(basic_logger<CharT,FinalT,ThreadingModelT> & left,basic_logger<CharT,FinalT,ThreadingModelT> & right)298 inline void swap(
299 basic_logger< CharT, FinalT, ThreadingModelT >& left,
300 basic_logger< CharT, FinalT, ThreadingModelT >& right) BOOST_NOEXCEPT_IF(boost::is_nothrow_swappable< FinalT >::value)
301 {
302 static_cast< FinalT& >(left).swap(static_cast< FinalT& >(right));
303 }
304
305 /*!
306 * \brief A composite logger that inherits a number of features
307 *
308 * The composite logger is a helper class that simplifies feature composition into the final logger.
309 * The user's logger class is expected to derive from the composite logger class, instantiated with
310 * the character type, the user's logger class, the threading model and the list of the required features.
311 * The former three parameters are passed to the \c basic_logger class template. The feature list
312 * must be an MPL type sequence, where each element is a unary MPL metafunction class, that upon
313 * applying on its argument results in a logging feature class that derives from the argument.
314 * Every logger feature provided by the library can participate in the feature list.
315 */
316 template< typename CharT, typename FinalT, typename ThreadingModelT, typename FeaturesT >
317 class basic_composite_logger :
318 public boost::log::sources::aux::inherit_features<
319 basic_logger< CharT, FinalT, ThreadingModelT >,
320 FeaturesT
321 >::type
322 {
323 private:
324 //! Base type (the hierarchy of features)
325 typedef typename boost::log::sources::aux::inherit_features<
326 basic_logger< CharT, FinalT, ThreadingModelT >,
327 FeaturesT
328 >::type base_type;
329
330 protected:
331 //! The composite logger type (for use in the user's logger class)
332 typedef basic_composite_logger logger_base;
333 BOOST_COPYABLE_AND_MOVABLE_ALT(logger_base)
334
335 public:
336 //! Threading model being used
337 typedef typename base_type::threading_model threading_model;
338
339 //! Lock requirement for the swap_unlocked method
340 typedef typename base_type::swap_lock swap_lock;
341
342 #if !defined(BOOST_LOG_NO_THREADS)
343
344 public:
345 /*!
346 * Default constructor (default-constructs all features)
347 */
basic_composite_logger()348 basic_composite_logger() {}
349 /*!
350 * Copy constructor
351 */
basic_composite_logger(basic_composite_logger const & that)352 basic_composite_logger(basic_composite_logger const& that) :
353 base_type
354 ((
355 boost::log::aux::shared_lock_guard< const threading_model >(that.get_threading_model()),
356 static_cast< base_type const& >(that)
357 ))
358 {
359 }
360 /*!
361 * Move constructor
362 */
BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<base_type>::value)363 basic_composite_logger(BOOST_RV_REF(logger_base) that) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible< base_type >::value) :
364 base_type(boost::move(static_cast< base_type& >(that)))
365 {
366 }
367 /*!
368 * Constructor with named parameters
369 */
370 template< typename ArgsT >
basic_composite_logger(ArgsT const & args)371 explicit basic_composite_logger(ArgsT const& args) : base_type(args)
372 {
373 }
374
375 /*!
376 * The method adds an attribute to the source-specific attribute set. The attribute will be implicitly added to
377 * every log record made with the current logger.
378 *
379 * \param name The attribute name.
380 * \param attr The attribute factory.
381 * \return A pair of values. If the second member is \c true, then the attribute is added and the first member points to the
382 * attribute. Otherwise the attribute was not added and the first member points to the attribute that prevents
383 * addition.
384 */
add_attribute(attribute_name const & name,attribute const & attr)385 std::pair< attribute_set::iterator, bool > add_attribute(attribute_name const& name, attribute const& attr)
386 {
387 typename base_type::add_attribute_lock lock(base_type::get_threading_model());
388 return base_type::add_attribute_unlocked(name, attr);
389 }
390 /*!
391 * The method removes an attribute from the source-specific attribute set.
392 *
393 * \pre The attribute was added with the add_attribute call for this instance of the logger.
394 * \post The attribute is no longer registered as a source-specific attribute for this logger. The iterator is invalidated after removal.
395 *
396 * \param it Iterator to the previously added attribute.
397 */
remove_attribute(attribute_set::iterator it)398 void remove_attribute(attribute_set::iterator it)
399 {
400 typename base_type::remove_attribute_lock lock(base_type::get_threading_model());
401 base_type::remove_attribute_unlocked(it);
402 }
403
404 /*!
405 * The method removes all attributes from the logger. All iterators and references to the removed attributes are invalidated.
406 */
remove_all_attributes()407 void remove_all_attributes()
408 {
409 typename base_type::remove_all_attributes_lock lock(base_type::get_threading_model());
410 base_type::remove_all_attributes_unlocked();
411 }
412
413 /*!
414 * The method retrieves a copy of a set with all attributes from the logger.
415 *
416 * \return The copy of the attribute set. Attributes are shallow-copied.
417 */
get_attributes() const418 attribute_set get_attributes() const
419 {
420 typename base_type::get_attributes_lock lock(base_type::get_threading_model());
421 return base_type::get_attributes_unlocked();
422 }
423
424 /*!
425 * The method installs the whole attribute set into the logger. All iterators and references to elements of
426 * the previous set are invalidated. Iterators to the \a attrs set are not valid to be used with the logger (that is,
427 * the logger owns a copy of \a attrs after completion).
428 *
429 * \param attrs The set of attributes to install into the logger. Attributes are shallow-copied.
430 */
set_attributes(attribute_set const & attrs)431 void set_attributes(attribute_set const& attrs)
432 {
433 typename base_type::set_attributes_lock lock(base_type::get_threading_model());
434 base_type::set_attributes_unlocked(attrs);
435 }
436
437 /*!
438 * The method opens a new log record in the logging core.
439 *
440 * \return A valid record handle if the logging record is opened successfully, an invalid handle otherwise.
441 */
open_record()442 record open_record()
443 {
444 // Perform a quick check first
445 if (this->core()->get_logging_enabled())
446 {
447 typename base_type::open_record_lock lock(base_type::get_threading_model());
448 return base_type::open_record_unlocked(boost::log::aux::empty_arg_list());
449 }
450 else
451 return record();
452 }
453 /*!
454 * The method opens a new log record in the logging core.
455 *
456 * \param args A set of additional named arguments. The parameter is ignored.
457 * \return A valid record handle if the logging record is opened successfully, an invalid handle otherwise.
458 */
459 template< typename ArgsT >
open_record(ArgsT const & args)460 record open_record(ArgsT const& args)
461 {
462 // Perform a quick check first
463 if (this->core()->get_logging_enabled())
464 {
465 typename base_type::open_record_lock lock(base_type::get_threading_model());
466 return base_type::open_record_unlocked(args);
467 }
468 else
469 return record();
470 }
471 /*!
472 * The method pushes the constructed message to the logging core
473 *
474 * \param rec The log record with the formatted message
475 */
push_record(BOOST_RV_REF (record)rec)476 void push_record(BOOST_RV_REF(record) rec)
477 {
478 typename base_type::push_record_lock lock(base_type::get_threading_model());
479 base_type::push_record_unlocked(boost::move(rec));
480 }
481 /*!
482 * Thread-safe implementation of swap
483 */
swap(basic_composite_logger & that)484 void swap(basic_composite_logger& that)
485 {
486 swap_lock lock(base_type::get_threading_model(), that.get_threading_model());
487 base_type::swap_unlocked(static_cast< base_type& >(that));
488 }
489
490 protected:
491 /*!
492 * Assignment for the final class. Threadsafe, provides strong exception guarantee.
493 */
assign(FinalT const & that)494 FinalT& assign(FinalT const& that)
495 {
496 BOOST_LOG_ASSUME(this != NULL);
497 if (static_cast< FinalT* >(this) != boost::addressof(that))
498 {
499 // We'll have to explicitly create the copy in order to make sure it's unlocked when we attempt to lock *this
500 FinalT tmp(that);
501 boost::log::aux::exclusive_lock_guard< threading_model > lock(base_type::get_threading_model());
502 base_type::swap_unlocked(tmp);
503 }
504 return static_cast< FinalT& >(*this);
505 }
506 };
507
508 //! An optimized composite logger version with no multithreading support
509 template< typename CharT, typename FinalT, typename FeaturesT >
510 class basic_composite_logger< CharT, FinalT, single_thread_model, FeaturesT > :
511 public boost::log::sources::aux::inherit_features<
512 basic_logger< CharT, FinalT, single_thread_model >,
513 FeaturesT
514 >::type
515 {
516 private:
517 typedef typename boost::log::sources::aux::inherit_features<
518 basic_logger< CharT, FinalT, single_thread_model >,
519 FeaturesT
520 >::type base_type;
521
522 protected:
523 typedef basic_composite_logger logger_base;
524 BOOST_COPYABLE_AND_MOVABLE_ALT(logger_base)
525
526 public:
527 typedef typename base_type::threading_model threading_model;
528
529 #endif // !defined(BOOST_LOG_NO_THREADS)
530
531 public:
basic_composite_logger()532 basic_composite_logger() {}
basic_composite_logger(basic_composite_logger const & that)533 basic_composite_logger(basic_composite_logger const& that) :
534 base_type(static_cast< base_type const& >(that))
535 {
536 }
BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<base_type>::value)537 basic_composite_logger(BOOST_RV_REF(logger_base) that) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible< base_type >::value) :
538 base_type(boost::move(static_cast< base_type& >(that)))
539 {
540 }
541 template< typename ArgsT >
basic_composite_logger(ArgsT const & args)542 explicit basic_composite_logger(ArgsT const& args) : base_type(args)
543 {
544 }
545
add_attribute(attribute_name const & name,attribute const & attr)546 std::pair< attribute_set::iterator, bool > add_attribute(attribute_name const& name, attribute const& attr)
547 {
548 return base_type::add_attribute_unlocked(name, attr);
549 }
remove_attribute(attribute_set::iterator it)550 void remove_attribute(attribute_set::iterator it)
551 {
552 base_type::remove_attribute_unlocked(it);
553 }
remove_all_attributes()554 void remove_all_attributes()
555 {
556 base_type::remove_all_attributes_unlocked();
557 }
get_attributes() const558 attribute_set get_attributes() const
559 {
560 return base_type::get_attributes_unlocked();
561 }
set_attributes(attribute_set const & attrs)562 void set_attributes(attribute_set const& attrs)
563 {
564 base_type::set_attributes_unlocked(attrs);
565 }
open_record()566 record open_record()
567 {
568 // Perform a quick check first
569 if (this->core()->get_logging_enabled())
570 return base_type::open_record_unlocked(boost::log::aux::empty_arg_list());
571 else
572 return record();
573 }
574 template< typename ArgsT >
open_record(ArgsT const & args)575 record open_record(ArgsT const& args)
576 {
577 // Perform a quick check first
578 if (this->core()->get_logging_enabled())
579 return base_type::open_record_unlocked(args);
580 else
581 return record();
582 }
push_record(BOOST_RV_REF (record)rec)583 void push_record(BOOST_RV_REF(record) rec)
584 {
585 base_type::push_record_unlocked(boost::move(rec));
586 }
swap(basic_composite_logger & that)587 void swap(basic_composite_logger& that)
588 {
589 base_type::swap_unlocked(static_cast< base_type& >(that));
590 }
591
592 protected:
assign(FinalT that)593 FinalT& assign(FinalT that)
594 {
595 base_type::swap_unlocked(that);
596 return static_cast< FinalT& >(*this);
597 }
598 };
599
600
601 #ifndef BOOST_LOG_DOXYGEN_PASS
602
603 #define BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS_IMPL(class_type, typename_keyword)\
604 public:\
605 BOOST_DEFAULTED_FUNCTION(class_type(), {})\
606 class_type(class_type const& that) : class_type::logger_base(\
607 static_cast< typename_keyword() class_type::logger_base const& >(that)) {}\
608 class_type(BOOST_RV_REF(class_type) that) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible< typename_keyword() class_type::logger_base >::value) : class_type::logger_base(\
609 ::boost::move(static_cast< typename_keyword() class_type::logger_base& >(that))) {}\
610 BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_FORWARD(class_type, class_type::logger_base)\
611
612 #endif // BOOST_LOG_DOXYGEN_PASS
613
614 #define BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS(class_type)\
615 BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS_IMPL(class_type, BOOST_PP_EMPTY)
616
617 #define BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS_TEMPLATE(class_type)\
618 BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS_IMPL(class_type, BOOST_PP_IDENTITY(typename))
619
620 #define BOOST_LOG_FORWARD_LOGGER_ASSIGNMENT(class_type)\
621 public:\
622 class_type& operator= (BOOST_COPY_ASSIGN_REF(class_type) that)\
623 {\
624 return class_type::logger_base::assign(static_cast< class_type const& >(that));\
625 }\
626 class_type& operator= (BOOST_RV_REF(class_type) that)\
627 {\
628 BOOST_LOG_EXPR_IF_MT(::boost::log::aux::exclusive_lock_guard< class_type::threading_model > lock(this->get_threading_model());)\
629 this->swap_unlocked(that);\
630 return *this;\
631 }
632
633 #define BOOST_LOG_FORWARD_LOGGER_ASSIGNMENT_TEMPLATE(class_type)\
634 public:\
635 class_type& operator= (BOOST_COPY_ASSIGN_REF(class_type) that)\
636 {\
637 return class_type::logger_base::assign(static_cast< class_type const& >(that));\
638 }\
639 class_type& operator= (BOOST_RV_REF(class_type) that)\
640 {\
641 BOOST_LOG_EXPR_IF_MT(::boost::log::aux::exclusive_lock_guard< typename class_type::threading_model > lock(this->get_threading_model());)\
642 this->swap_unlocked(that);\
643 return *this;\
644 }
645
646 #define BOOST_LOG_FORWARD_LOGGER_MEMBERS(class_type)\
647 BOOST_COPYABLE_AND_MOVABLE(class_type)\
648 BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS(class_type)\
649 BOOST_LOG_FORWARD_LOGGER_ASSIGNMENT(class_type)
650
651 #define BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(class_type)\
652 BOOST_COPYABLE_AND_MOVABLE(class_type)\
653 BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS_TEMPLATE(class_type)\
654 BOOST_LOG_FORWARD_LOGGER_ASSIGNMENT_TEMPLATE(class_type)
655
656 } // namespace sources
657
658 BOOST_LOG_CLOSE_NAMESPACE // namespace log
659
660 } // namespace boost
661
662 /*!
663 * \brief The macro declares a logger class that inherits a number of base classes
664 *
665 * \param type_name The name of the logger class to declare
666 * \param char_type The character type of the logger. Either char or wchar_t expected.
667 * \param base_seq A Boost.Preprocessor sequence of type identifiers of the base classes templates
668 * \param threading A threading model class
669 */
670 #define BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, char_type, base_seq, threading)\
671 class type_name :\
672 public ::boost::log::sources::basic_composite_logger<\
673 char_type,\
674 type_name,\
675 threading,\
676 ::boost::log::sources::features< BOOST_PP_SEQ_ENUM(base_seq) >\
677 >\
678 {\
679 BOOST_LOG_FORWARD_LOGGER_MEMBERS(type_name)\
680 }
681
682
683
684 #ifdef BOOST_LOG_USE_CHAR
685
686 /*!
687 * \brief The macro declares a narrow-char logger class that inherits a number of base classes
688 *
689 * Equivalent to BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, char, base_seq, single_thread_model)
690 *
691 * \param type_name The name of the logger class to declare
692 * \param base_seq A Boost.Preprocessor sequence of type identifiers of the base classes templates
693 */
694 #define BOOST_LOG_DECLARE_LOGGER(type_name, base_seq)\
695 BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, char, base_seq, ::boost::log::sources::single_thread_model)
696
697 #if !defined(BOOST_LOG_NO_THREADS)
698
699 /*!
700 * \brief The macro declares a narrow-char thread-safe logger class that inherits a number of base classes
701 *
702 * Equivalent to <tt>BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, char, base_seq, multi_thread_model< shared_mutex >)</tt>
703 *
704 * \param type_name The name of the logger class to declare
705 * \param base_seq A Boost.Preprocessor sequence of type identifiers of the base classes templates
706 */
707 #define BOOST_LOG_DECLARE_LOGGER_MT(type_name, base_seq)\
708 BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, char, base_seq,\
709 ::boost::log::sources::multi_thread_model< ::boost::shared_mutex >)
710
711 #endif // !defined(BOOST_LOG_NO_THREADS)
712 #endif // BOOST_LOG_USE_CHAR
713
714 #ifdef BOOST_LOG_USE_WCHAR_T
715
716 /*!
717 * \brief The macro declares a wide-char logger class that inherits a number of base classes
718 *
719 * Equivalent to BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, wchar_t, base_seq, single_thread_model)
720 *
721 * \param type_name The name of the logger class to declare
722 * \param base_seq A Boost.Preprocessor sequence of type identifiers of the base classes templates
723 */
724 #define BOOST_LOG_DECLARE_WLOGGER(type_name, base_seq)\
725 BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, wchar_t, base_seq, ::boost::log::sources::single_thread_model)
726
727 #if !defined(BOOST_LOG_NO_THREADS)
728
729 /*!
730 * \brief The macro declares a wide-char thread-safe logger class that inherits a number of base classes
731 *
732 * Equivalent to <tt>BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, wchar_t, base_seq, multi_thread_model< shared_mutex >)</tt>
733 *
734 * \param type_name The name of the logger class to declare
735 * \param base_seq A Boost.Preprocessor sequence of type identifiers of the base classes templates
736 */
737 #define BOOST_LOG_DECLARE_WLOGGER_MT(type_name, base_seq)\
738 BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, wchar_t, base_seq,\
739 ::boost::log::sources::multi_thread_model< ::boost::shared_mutex >)
740
741 #endif // !defined(BOOST_LOG_NO_THREADS)
742 #endif // BOOST_LOG_USE_WCHAR_T
743
744 #include <boost/log/detail/footer.hpp>
745
746 #endif // BOOST_LOG_SOURCES_BASIC_LOGGER_HPP_INCLUDED_
747