summaryrefslogtreecommitdiff
path: root/boost/log
diff options
context:
space:
mode:
Diffstat (limited to 'boost/log')
-rw-r--r--boost/log/attributes.hpp38
-rw-r--r--boost/log/attributes/attribute.hpp191
-rw-r--r--boost/log/attributes/attribute_cast.hpp74
-rw-r--r--boost/log/attributes/attribute_name.hpp185
-rw-r--r--boost/log/attributes/attribute_set.hpp507
-rw-r--r--boost/log/attributes/attribute_value.hpp380
-rw-r--r--boost/log/attributes/attribute_value_impl.hpp136
-rw-r--r--boost/log/attributes/attribute_value_set.hpp480
-rw-r--r--boost/log/attributes/clock.hpp95
-rw-r--r--boost/log/attributes/constant.hpp122
-rw-r--r--boost/log/attributes/counter.hpp218
-rw-r--r--boost/log/attributes/current_process_id.hpp67
-rw-r--r--boost/log/attributes/current_process_name.hpp71
-rw-r--r--boost/log/attributes/current_thread_id.hpp109
-rw-r--r--boost/log/attributes/fallback_policy.hpp186
-rw-r--r--boost/log/attributes/fallback_policy_fwd.hpp48
-rw-r--r--boost/log/attributes/function.hpp170
-rw-r--r--boost/log/attributes/mutable_constant.hpp332
-rw-r--r--boost/log/attributes/named_scope.hpp474
-rw-r--r--boost/log/attributes/scoped_attribute.hpp253
-rw-r--r--boost/log/attributes/time_traits.hpp81
-rw-r--r--boost/log/attributes/timer.hpp83
-rw-r--r--boost/log/attributes/value_extraction.hpp816
-rw-r--r--boost/log/attributes/value_extraction_fwd.hpp62
-rw-r--r--boost/log/attributes/value_visitation.hpp372
-rw-r--r--boost/log/attributes/value_visitation_fwd.hpp45
-rw-r--r--boost/log/common.hpp41
-rw-r--r--boost/log/core.hpp28
-rw-r--r--boost/log/core/core.hpp329
-rw-r--r--boost/log/core/record.hpp207
-rw-r--r--boost/log/core/record_view.hpp260
-rw-r--r--boost/log/detail/asio_fwd.hpp43
-rw-r--r--boost/log/detail/attachable_sstream_buf.hpp172
-rw-r--r--boost/log/detail/attr_output_impl.hpp111
-rw-r--r--boost/log/detail/attr_output_terminal.hpp162
-rw-r--r--boost/log/detail/attribute_get_value_impl.hpp43
-rw-r--r--boost/log/detail/attribute_predicate.hpp116
-rw-r--r--boost/log/detail/cleanup_scope_guard.hpp55
-rw-r--r--boost/log/detail/code_conversion.hpp119
-rw-r--r--boost/log/detail/config.hpp351
-rw-r--r--boost/log/detail/copy_cv.hpp64
-rw-r--r--boost/log/detail/custom_terminal_spec.hpp70
-rw-r--r--boost/log/detail/date_time_fmt_gen_traits_fwd.hpp44
-rw-r--r--boost/log/detail/date_time_format_parser.hpp486
-rw-r--r--boost/log/detail/decomposed_time.hpp440
-rw-r--r--boost/log/detail/deduce_char_type.hpp108
-rw-r--r--boost/log/detail/default_attribute_names.hpp53
-rw-r--r--boost/log/detail/embedded_string_type.hpp125
-rw-r--r--boost/log/detail/enqueued_record.hpp103
-rw-r--r--boost/log/detail/event.hpp142
-rw-r--r--boost/log/detail/fake_mutex.hpp56
-rw-r--r--boost/log/detail/footer.hpp22
-rw-r--r--boost/log/detail/format.hpp336
-rw-r--r--boost/log/detail/function_traits.hpp236
-rw-r--r--boost/log/detail/generate_overloads.hpp30
-rw-r--r--boost/log/detail/header.hpp64
-rw-r--r--boost/log/detail/id.hpp84
-rw-r--r--boost/log/detail/light_function.hpp521
-rw-r--r--boost/log/detail/light_function_pp.hpp424
-rw-r--r--boost/log/detail/light_rw_mutex.hpp208
-rw-r--r--boost/log/detail/locking_ptr.hpp148
-rw-r--r--boost/log/detail/locks.hpp180
-rw-r--r--boost/log/detail/named_scope_fmt_pp.hpp82
-rw-r--r--boost/log/detail/native_typeof.hpp63
-rw-r--r--boost/log/detail/parameter_tools.hpp114
-rw-r--r--boost/log/detail/pp_identity.hpp27
-rw-r--r--boost/log/detail/process_id.hpp60
-rw-r--r--boost/log/detail/setup_config.hpp61
-rw-r--r--boost/log/detail/singleton.hpp89
-rw-r--r--boost/log/detail/sink_init_helpers.hpp118
-rw-r--r--boost/log/detail/snprintf.hpp106
-rw-r--r--boost/log/detail/spin_mutex.hpp319
-rw-r--r--boost/log/detail/tagged_integer.hpp147
-rw-r--r--boost/log/detail/thread_id.hpp65
-rw-r--r--boost/log/detail/thread_specific.hpp116
-rw-r--r--boost/log/detail/threadsafe_queue.hpp277
-rw-r--r--boost/log/detail/timestamp.hpp99
-rw-r--r--boost/log/detail/trivial_keyword.hpp43
-rw-r--r--boost/log/detail/unary_function_terminal.hpp142
-rw-r--r--boost/log/detail/unhandled_exception_count.hpp40
-rw-r--r--boost/log/detail/value_ref_visitation.hpp107
-rw-r--r--boost/log/detail/visible_type.hpp48
-rw-r--r--boost/log/exceptions.hpp387
-rw-r--r--boost/log/expressions.hpp38
-rw-r--r--boost/log/expressions/attr.hpp276
-rw-r--r--boost/log/expressions/attr_fwd.hpp69
-rw-r--r--boost/log/expressions/filter.hpp183
-rw-r--r--boost/log/expressions/formatter.hpp257
-rw-r--r--boost/log/expressions/formatters.hpp38
-rw-r--r--boost/log/expressions/formatters/c_decorator.hpp281
-rw-r--r--boost/log/expressions/formatters/char_decorator.hpp639
-rw-r--r--boost/log/expressions/formatters/csv_decorator.hpp140
-rw-r--r--boost/log/expressions/formatters/date_time.hpp343
-rw-r--r--boost/log/expressions/formatters/format.hpp128
-rw-r--r--boost/log/expressions/formatters/if.hpp315
-rw-r--r--boost/log/expressions/formatters/named_scope.hpp653
-rw-r--r--boost/log/expressions/formatters/stream.hpp53
-rw-r--r--boost/log/expressions/formatters/wrap_formatter.hpp338
-rw-r--r--boost/log/expressions/formatters/xml_decorator.hpp138
-rw-r--r--boost/log/expressions/is_keyword_descriptor.hpp67
-rw-r--r--boost/log/expressions/keyword.hpp258
-rw-r--r--boost/log/expressions/keyword_fwd.hpp53
-rw-r--r--boost/log/expressions/message.hpp130
-rw-r--r--boost/log/expressions/predicates.hpp34
-rw-r--r--boost/log/expressions/predicates/begins_with.hpp129
-rw-r--r--boost/log/expressions/predicates/channel_severity_filter.hpp572
-rw-r--r--boost/log/expressions/predicates/contains.hpp129
-rw-r--r--boost/log/expressions/predicates/ends_with.hpp129
-rw-r--r--boost/log/expressions/predicates/has_attr.hpp172
-rw-r--r--boost/log/expressions/predicates/is_debugger_present.hpp107
-rw-r--r--boost/log/expressions/predicates/is_in_range.hpp133
-rw-r--r--boost/log/expressions/predicates/matches.hpp119
-rw-r--r--boost/log/expressions/record.hpp50
-rw-r--r--boost/log/keywords/auto_flush.hpp40
-rw-r--r--boost/log/keywords/channel.hpp40
-rw-r--r--boost/log/keywords/delimiter.hpp40
-rw-r--r--boost/log/keywords/depth.hpp40
-rw-r--r--boost/log/keywords/empty_marker.hpp40
-rw-r--r--boost/log/keywords/facility.hpp40
-rw-r--r--boost/log/keywords/file_name.hpp40
-rw-r--r--boost/log/keywords/filter.hpp40
-rw-r--r--boost/log/keywords/format.hpp40
-rw-r--r--boost/log/keywords/ident.hpp40
-rw-r--r--boost/log/keywords/incomplete_marker.hpp40
-rw-r--r--boost/log/keywords/ip_version.hpp40
-rw-r--r--boost/log/keywords/iteration.hpp40
-rw-r--r--boost/log/keywords/log_name.hpp40
-rw-r--r--boost/log/keywords/log_source.hpp40
-rw-r--r--boost/log/keywords/max_size.hpp40
-rw-r--r--boost/log/keywords/message_file.hpp40
-rw-r--r--boost/log/keywords/min_free_space.hpp40
-rw-r--r--boost/log/keywords/open_mode.hpp40
-rw-r--r--boost/log/keywords/order.hpp40
-rw-r--r--boost/log/keywords/ordering_window.hpp40
-rw-r--r--boost/log/keywords/registration.hpp40
-rw-r--r--boost/log/keywords/rotation_size.hpp40
-rw-r--r--boost/log/keywords/scan_method.hpp40
-rw-r--r--boost/log/keywords/severity.hpp40
-rw-r--r--boost/log/keywords/start_thread.hpp40
-rw-r--r--boost/log/keywords/target.hpp40
-rw-r--r--boost/log/keywords/time_based_rotation.hpp40
-rw-r--r--boost/log/keywords/use_impl.hpp40
-rw-r--r--boost/log/sinks.hpp47
-rw-r--r--boost/log/sinks/async_frontend.hpp462
-rw-r--r--boost/log/sinks/attribute_mapping.hpp290
-rw-r--r--boost/log/sinks/basic_sink_backend.hpp97
-rw-r--r--boost/log/sinks/basic_sink_frontend.hpp524
-rw-r--r--boost/log/sinks/block_on_overflow.hpp147
-rw-r--r--boost/log/sinks/bounded_fifo_queue.hpp192
-rw-r--r--boost/log/sinks/bounded_ordering_queue.hpp262
-rw-r--r--boost/log/sinks/debug_output_backend.hpp93
-rw-r--r--boost/log/sinks/drop_on_overflow.hpp80
-rw-r--r--boost/log/sinks/event_log_backend.hpp662
-rw-r--r--boost/log/sinks/event_log_constants.hpp88
-rw-r--r--boost/log/sinks/frontend_requirements.hpp119
-rw-r--r--boost/log/sinks/sink.hpp115
-rw-r--r--boost/log/sinks/sync_frontend.hpp166
-rw-r--r--boost/log/sinks/syslog_backend.hpp288
-rw-r--r--boost/log/sinks/syslog_constants.hpp101
-rw-r--r--boost/log/sinks/text_file_backend.hpp539
-rw-r--r--boost/log/sinks/text_multifile_backend.hpp201
-rw-r--r--boost/log/sinks/text_ostream_backend.hpp124
-rw-r--r--boost/log/sinks/unbounded_fifo_queue.hpp142
-rw-r--r--boost/log/sinks/unbounded_ordering_queue.hpp245
-rw-r--r--boost/log/sinks/unlocked_frontend.hpp142
-rw-r--r--boost/log/sources/basic_logger.hpp742
-rw-r--r--boost/log/sources/channel_feature.hpp242
-rw-r--r--boost/log/sources/channel_logger.hpp325
-rw-r--r--boost/log/sources/exception_handler_feature.hpp253
-rw-r--r--boost/log/sources/features.hpp150
-rw-r--r--boost/log/sources/global_logger_storage.hpp206
-rw-r--r--boost/log/sources/logger.hpp103
-rw-r--r--boost/log/sources/record_ostream.hpp335
-rw-r--r--boost/log/sources/severity_channel_logger.hpp309
-rw-r--r--boost/log/sources/severity_feature.hpp310
-rw-r--r--boost/log/sources/severity_logger.hpp325
-rw-r--r--boost/log/sources/threading_models.hpp125
-rw-r--r--boost/log/support/date_time.hpp548
-rw-r--r--boost/log/support/exception.hpp72
-rw-r--r--boost/log/support/regex.hpp76
-rw-r--r--boost/log/support/spirit_classic.hpp112
-rw-r--r--boost/log/support/spirit_qi.hpp92
-rw-r--r--boost/log/support/std_regex.hpp86
-rw-r--r--boost/log/support/xpressive.hpp75
-rw-r--r--boost/log/trivial.hpp127
-rw-r--r--boost/log/utility/empty_deleter.hpp42
-rw-r--r--boost/log/utility/exception_handler.hpp354
-rw-r--r--boost/log/utility/explicit_operator_bool.hpp42
-rw-r--r--boost/log/utility/formatting_ostream.hpp748
-rw-r--r--boost/log/utility/formatting_ostream_fwd.hpp51
-rw-r--r--boost/log/utility/functional.hpp40
-rw-r--r--boost/log/utility/functional/as_action.hpp60
-rw-r--r--boost/log/utility/functional/begins_with.hpp57
-rw-r--r--boost/log/utility/functional/bind.hpp237
-rw-r--r--boost/log/utility/functional/bind_assign.hpp55
-rw-r--r--boost/log/utility/functional/bind_output.hpp55
-rw-r--r--boost/log/utility/functional/bind_to_log.hpp76
-rw-r--r--boost/log/utility/functional/contains.hpp69
-rw-r--r--boost/log/utility/functional/ends_with.hpp57
-rw-r--r--boost/log/utility/functional/fun_ref.hpp79
-rw-r--r--boost/log/utility/functional/in_range.hpp63
-rw-r--r--boost/log/utility/functional/logical.hpp225
-rw-r--r--boost/log/utility/functional/matches.hpp66
-rw-r--r--boost/log/utility/functional/nop.hpp55
-rw-r--r--boost/log/utility/functional/save_result.hpp60
-rw-r--r--boost/log/utility/intrusive_ref_counter.hpp55
-rw-r--r--boost/log/utility/manipulators.hpp28
-rw-r--r--boost/log/utility/manipulators/add_value.hpp165
-rw-r--r--boost/log/utility/manipulators/dump.hpp231
-rw-r--r--boost/log/utility/manipulators/to_log.hpp87
-rw-r--r--boost/log/utility/once_block.hpp196
-rw-r--r--boost/log/utility/record_ordering.hpp229
-rw-r--r--boost/log/utility/setup.hpp37
-rw-r--r--boost/log/utility/setup/common_attributes.hpp76
-rw-r--r--boost/log/utility/setup/console.hpp243
-rw-r--r--boost/log/utility/setup/file.hpp166
-rw-r--r--boost/log/utility/setup/filter_parser.hpp346
-rw-r--r--boost/log/utility/setup/formatter_parser.hpp216
-rw-r--r--boost/log/utility/setup/from_settings.hpp164
-rw-r--r--boost/log/utility/setup/from_stream.hpp47
-rw-r--r--boost/log/utility/setup/settings.hpp643
-rw-r--r--boost/log/utility/setup/settings_parser.hpp47
-rw-r--r--boost/log/utility/strictest_lock.hpp214
-rw-r--r--boost/log/utility/string_literal.hpp617
-rw-r--r--boost/log/utility/string_literal_fwd.hpp55
-rw-r--r--boost/log/utility/type_dispatch/date_time_types.hpp138
-rw-r--r--boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp154
-rw-r--r--boost/log/utility/type_dispatch/standard_types.hpp105
-rw-r--r--boost/log/utility/type_dispatch/static_type_dispatcher.hpp319
-rw-r--r--boost/log/utility/type_dispatch/type_dispatcher.hpp189
-rw-r--r--boost/log/utility/type_info_wrapper.hpp188
-rw-r--r--boost/log/utility/unique_identifier_name.hpp51
-rw-r--r--boost/log/utility/unused_variable.hpp51
-rw-r--r--boost/log/utility/value_ref.hpp630
-rw-r--r--boost/log/utility/value_ref_fwd.hpp38
235 files changed, 39172 insertions, 0 deletions
diff --git a/boost/log/attributes.hpp b/boost/log/attributes.hpp
new file mode 100644
index 0000000000..92b9c259cc
--- /dev/null
+++ b/boost/log/attributes.hpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file attributes.hpp
+ * \author Andrey Semashev
+ * \date 13.07.2009
+ *
+ * This header includes other Boost.Log headers with all attributes.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTES_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTES_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/attributes/clock.hpp>
+#include <boost/log/attributes/constant.hpp>
+#include <boost/log/attributes/counter.hpp>
+#include <boost/log/attributes/function.hpp>
+#include <boost/log/attributes/mutable_constant.hpp>
+#include <boost/log/attributes/named_scope.hpp>
+#include <boost/log/attributes/timer.hpp>
+#include <boost/log/attributes/current_process_name.hpp>
+#include <boost/log/attributes/current_process_id.hpp>
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/log/attributes/current_thread_id.hpp>
+#endif
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#endif // BOOST_LOG_ATTRIBUTES_HPP_INCLUDED_
diff --git a/boost/log/attributes/attribute.hpp b/boost/log/attributes/attribute.hpp
new file mode 100644
index 0000000000..0d6ba64a17
--- /dev/null
+++ b/boost/log/attributes/attribute.hpp
@@ -0,0 +1,191 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file attribute.hpp
+ * \author Andrey Semashev
+ * \date 15.04.2007
+ *
+ * The header contains attribute interface definition.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTES_ATTRIBUTE_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTES_ATTRIBUTE_HPP_INCLUDED_
+
+#include <new>
+#include <boost/move/core.hpp>
+#include <boost/smart_ptr/intrusive_ptr.hpp>
+#include <boost/smart_ptr/intrusive_ref_counter.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/utility/explicit_operator_bool.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+class attribute_value;
+
+namespace aux {
+
+//! Reference proxy object to implement \c operator[]
+class attribute_set_reference_proxy;
+
+} // namespace aux
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * \brief A base class for an attribute value factory
+ *
+ * Every attribute is represented with a factory that is basically an attribute value generator.
+ * The sole purpose of an attribute is to return an actual value when requested. A simplest attribute
+ * can always return the same value that it stores internally, but more complex ones can
+ * perform a considerable amount of work to return a value, and the returned values may differ
+ * each time requested.
+ *
+ * A word about thread safety. An attribute should be prepared to be requested a value from
+ * multiple threads concurrently.
+ */
+class attribute
+{
+ BOOST_COPYABLE_AND_MOVABLE(attribute)
+
+public:
+ /*!
+ * \brief A base class for an attribute value factory
+ *
+ * All attributes must derive their implementation from this class.
+ */
+ struct BOOST_LOG_NO_VTABLE BOOST_SYMBOL_VISIBLE impl :
+ public boost::intrusive_ref_counter< impl >
+ {
+ /*!
+ * \brief Virtual destructor
+ */
+ virtual ~impl() {}
+
+ /*!
+ * \return The actual attribute value. It shall not return empty values (exceptions
+ * shall be used to indicate errors).
+ */
+ virtual attribute_value get_value() = 0;
+
+ BOOST_LOG_API static void* operator new (std::size_t size);
+ BOOST_LOG_API static void operator delete (void* p, std::size_t size) BOOST_NOEXCEPT;
+ };
+
+private:
+ //! Pointer to the attribute factory implementation
+ intrusive_ptr< impl > m_pImpl;
+
+public:
+ /*!
+ * Default constructor. Creates an empty attribute value factory, which is not usable until
+ * \c set_impl is called.
+ */
+ BOOST_DEFAULTED_FUNCTION(attribute(), {})
+
+ /*!
+ * Copy constructor
+ */
+ attribute(attribute const& that) BOOST_NOEXCEPT : m_pImpl(that.m_pImpl) {}
+
+ /*!
+ * Move constructor
+ */
+ attribute(BOOST_RV_REF(attribute) that) BOOST_NOEXCEPT { m_pImpl.swap(that.m_pImpl); }
+
+ /*!
+ * Initializing constructor
+ *
+ * \param p Pointer to the implementation. Must not be \c NULL.
+ */
+ explicit attribute(intrusive_ptr< impl > p) BOOST_NOEXCEPT { m_pImpl.swap(p); }
+
+ /*!
+ * Copy assignment
+ */
+ attribute& operator= (BOOST_COPY_ASSIGN_REF(attribute) that) BOOST_NOEXCEPT
+ {
+ m_pImpl = that.m_pImpl;
+ return *this;
+ }
+
+ /*!
+ * Move assignment
+ */
+ attribute& operator= (BOOST_RV_REF(attribute) that) BOOST_NOEXCEPT
+ {
+ m_pImpl.swap(that.m_pImpl);
+ return *this;
+ }
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ attribute& operator= (aux::attribute_set_reference_proxy const& that) BOOST_NOEXCEPT;
+#endif
+
+ /*!
+ * Verifies that the factory is not in empty state
+ */
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+
+ /*!
+ * Verifies that the factory is in empty state
+ */
+ bool operator! () const BOOST_NOEXCEPT { return !m_pImpl; }
+
+ /*!
+ * \return The actual attribute value. It shall not return empty values (exceptions
+ * shall be used to indicate errors).
+ */
+ attribute_value get_value() const;
+
+ /*!
+ * The method swaps two factories (i.e. their implementations).
+ */
+ void swap(attribute& that) BOOST_NOEXCEPT { m_pImpl.swap(that.m_pImpl); }
+
+protected:
+ /*!
+ * \returns The pointer to the implementation
+ */
+ impl* get_impl() const BOOST_NOEXCEPT { return m_pImpl.get(); }
+ /*!
+ * Sets the pointer to the factory implementation.
+ *
+ * \param p Pointer to the implementation. Must not be \c NULL.
+ */
+ void set_impl(intrusive_ptr< impl > p) BOOST_NOEXCEPT { m_pImpl.swap(p); }
+
+ template< typename T >
+ friend T attribute_cast(attribute const&);
+};
+
+/*!
+ * The function swaps two attribute value factories
+ */
+inline void swap(attribute& left, attribute& right) BOOST_NOEXCEPT
+{
+ left.swap(right);
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+#if defined(BOOST_LOG_ATTRIBUTES_ATTRIBUTE_VALUE_HPP_INCLUDED_)
+#include <boost/log/detail/attribute_get_value_impl.hpp>
+#endif
+
+#endif // BOOST_LOG_ATTRIBUTES_ATTRIBUTE_HPP_INCLUDED_
diff --git a/boost/log/attributes/attribute_cast.hpp b/boost/log/attributes/attribute_cast.hpp
new file mode 100644
index 0000000000..7ae1c92cf4
--- /dev/null
+++ b/boost/log/attributes/attribute_cast.hpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file attribute_cast.hpp
+ * \author Andrey Semashev
+ * \date 06.08.2010
+ *
+ * The header contains utilities for casting between attribute factories.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTES_ATTRIBUTE_CAST_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTES_ATTRIBUTE_CAST_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace attributes {
+
+/*!
+ * The class holds a reference to the attribute factory implementation being casted
+ */
+class cast_source
+{
+private:
+ attribute::impl* m_pImpl;
+
+public:
+ /*!
+ * Initializing constructor. Creates a source that refers to the specified factory implementation.
+ */
+ explicit cast_source(attribute::impl* p) : m_pImpl(p)
+ {
+ }
+
+ /*!
+ * The function attempts to cast the aggregated pointer to the implementation to the specified type.
+ *
+ * \return The converted pointer or \c NULL, if the conversion fails.
+ */
+ template< typename T >
+ T* as() const { return dynamic_cast< T* >(m_pImpl); }
+};
+
+} // namespace attributes
+
+/*!
+ * The function casts one attribute factory to another
+ */
+template< typename T >
+inline T attribute_cast(attribute const& attr)
+{
+ return T(attributes::cast_source(attr.get_impl()));
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTRIBUTES_ATTRIBUTE_CAST_HPP_INCLUDED_
diff --git a/boost/log/attributes/attribute_name.hpp b/boost/log/attributes/attribute_name.hpp
new file mode 100644
index 0000000000..4e283e6a28
--- /dev/null
+++ b/boost/log/attributes/attribute_name.hpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file attribute_name.hpp
+ * \author Andrey Semashev
+ * \date 28.06.2010
+ *
+ * The header contains attribute name interface definition.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTE_NAME_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTE_NAME_HPP_INCLUDED_
+
+#include <iosfwd>
+#include <string>
+#include <boost/assert.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/utility/explicit_operator_bool.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * \brief The class represents an attribute name in containers used by the library
+ *
+ * The class mostly serves for optimization purposes. Each attribute name that is used
+ * with the library is automatically associated with a unique identifier, which is much
+ * lighter in terms of memory footprint and operations complexity. This is done
+ * transparently by this class, on object construction. Passing objects of this class
+ * to other library methods, such as attribute lookup functions, will not require
+ * this translation and/or string copying and thus will result in a more efficient code.
+ */
+class attribute_name
+{
+public:
+ //! String type
+ typedef std::string string_type;
+#ifdef BOOST_LOG_DOXYGEN_PASS
+ //! Associated identifier
+ typedef unspecified id_type;
+#else
+ typedef uint32_t id_type;
+
+private:
+ enum { uninitialized = 0xFFFFFFFFu };
+
+ class repository;
+ friend class repository;
+
+private:
+ //! Associated identifier
+ id_type m_id;
+#endif
+
+public:
+ /*!
+ * Default constructor. Creates an object that does not refer to any attribute name.
+ */
+ BOOST_CONSTEXPR attribute_name() BOOST_NOEXCEPT : m_id(static_cast< id_type >(uninitialized))
+ {
+ }
+ /*!
+ * Constructs an attribute name from the specified string
+ *
+ * \param name An attribute name
+ * \pre \a name is not NULL and points to a zero-terminated string
+ */
+ attribute_name(const char* name) :
+ m_id(get_id_from_string(name))
+ {
+ }
+ /*!
+ * Constructs an attribute name from the specified string
+ *
+ * \param name An attribute name
+ */
+ attribute_name(string_type const& name) :
+ m_id(get_id_from_string(name.c_str()))
+ {
+ }
+
+ /*!
+ * Compares the attribute names
+ *
+ * \return \c true if <tt>*this</tt> and \c that refer to the same attribute name,
+ * and \c false otherwise.
+ */
+ bool operator== (attribute_name const& that) const BOOST_NOEXCEPT { return m_id == that.m_id; }
+ /*!
+ * Compares the attribute names
+ *
+ * \return \c true if <tt>*this</tt> and \c that refer to different attribute names,
+ * and \c false otherwise.
+ */
+ bool operator!= (attribute_name const& that) const BOOST_NOEXCEPT { return m_id != that.m_id; }
+
+ /*!
+ * Compares the attribute names
+ *
+ * \return \c true if <tt>*this</tt> and \c that refer to the same attribute name,
+ * and \c false otherwise.
+ */
+ bool operator== (const char* that) const { return (m_id != static_cast< id_type >(uninitialized)) && (this->string() == that); }
+ /*!
+ * Compares the attribute names
+ *
+ * \return \c true if <tt>*this</tt> and \c that refer to different attribute names,
+ * and \c false otherwise.
+ */
+ bool operator!= (const char* that) const { return !operator== (that); }
+
+ /*!
+ * Compares the attribute names
+ *
+ * \return \c true if <tt>*this</tt> and \c that refer to the same attribute name,
+ * and \c false otherwise.
+ */
+ bool operator== (string_type const& that) const { return (m_id != static_cast< id_type >(uninitialized)) && (this->string() == that); }
+ /*!
+ * Compares the attribute names
+ *
+ * \return \c true if <tt>*this</tt> and \c that refer to different attribute names,
+ * and \c false otherwise.
+ */
+ bool operator!= (string_type const& that) const { return !operator== (that); }
+
+ /*!
+ * Checks if the object was default-constructed
+ *
+ * \return \c true if <tt>*this</tt> was constructed with an attribute name, \c false otherwise
+ */
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+ /*!
+ * Checks if the object was default-constructed
+ *
+ * \return \c true if <tt>*this</tt> was default-constructed and does not refer to any attribute name,
+ * \c false otherwise
+ */
+ bool operator! () const BOOST_NOEXCEPT { return (m_id == static_cast< id_type >(uninitialized)); }
+
+ /*!
+ * \return The associated id value
+ * \pre <tt>(!*this) == false</tt>
+ */
+ id_type id() const BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT(m_id != static_cast< id_type >(uninitialized));
+ return m_id;
+ }
+ /*!
+ * \return The attribute name string that was used during the object construction
+ * \pre <tt>(!*this) == false</tt>
+ */
+ string_type const& string() const { return get_string_from_id(m_id); }
+
+private:
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ static BOOST_LOG_API id_type get_id_from_string(const char* name);
+ static BOOST_LOG_API string_type const& get_string_from_id(id_type id);
+#endif
+};
+
+template< typename CharT, typename TraitsT >
+BOOST_LOG_API std::basic_ostream< CharT, TraitsT >& operator<< (
+ std::basic_ostream< CharT, TraitsT >& strm,
+ attribute_name const& name);
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTRIBUTE_NAME_HPP_INCLUDED_
diff --git a/boost/log/attributes/attribute_set.hpp b/boost/log/attributes/attribute_set.hpp
new file mode 100644
index 0000000000..5481c095f4
--- /dev/null
+++ b/boost/log/attributes/attribute_set.hpp
@@ -0,0 +1,507 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file attribute_set.hpp
+ * \author Andrey Semashev
+ * \date 08.03.2007
+ *
+ * This header contains definition of the attribute set container.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTE_SET_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTE_SET_HPP_INCLUDED_
+
+#include <cstddef>
+#include <utility>
+#include <iterator>
+#include <boost/mpl/if.hpp>
+#include <boost/move/core.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+class attribute_set;
+class attribute_value_set;
+
+namespace aux {
+
+//! Reference proxy object to implement \c operator[]
+class attribute_set_reference_proxy
+{
+private:
+ //! Key type
+ typedef attribute_name key_type;
+ //! Mapped attribute type
+ typedef attribute mapped_type;
+
+private:
+ attribute_set* const m_pContainer;
+ const key_type m_key;
+
+public:
+ //! Constructor
+ explicit attribute_set_reference_proxy(attribute_set* pContainer, key_type const& key) BOOST_NOEXCEPT :
+ m_pContainer(pContainer),
+ m_key(key)
+ {
+ }
+
+ //! Conversion operator (would be invoked in case of reading from the container)
+ operator mapped_type() const BOOST_NOEXCEPT;
+ //! Assignment operator (would be invoked in case of writing to the container)
+ mapped_type& operator= (mapped_type const& val) const;
+};
+
+} // namespace aux
+
+/*!
+ * \brief An attribute set class.
+ *
+ * An attribute set is an associative container with attribute name as a key and
+ * pointer to the attribute as a mapped value. The container allows storing only one element for each distinct
+ * key value. In most regards attribute set container provides interface similar to \c std::unordered_map.
+ * However, there are differences in \c operator[] semantics and a number of optimizations with regard to iteration.
+ * Besides, attribute names are stored as a read-only <tt>attribute_name</tt>'s instead of \c std::string,
+ * which saves memory and CPU time.
+ */
+class attribute_set
+{
+ BOOST_COPYABLE_AND_MOVABLE_ALT(attribute_set)
+
+ friend class attribute_value_set;
+ friend class aux::attribute_set_reference_proxy;
+
+public:
+ //! Key type
+ typedef attribute_name key_type;
+ //! Mapped attribute type
+ typedef attribute mapped_type;
+
+ //! Value type
+ typedef std::pair< const key_type, mapped_type > value_type;
+ //! Reference type
+ typedef value_type& reference;
+ //! Const reference type
+ typedef value_type const& const_reference;
+ //! Pointer type
+ typedef value_type* pointer;
+ //! Const pointer type
+ typedef value_type const* const_pointer;
+ //! Size type
+ typedef std::size_t size_type;
+ //! Difference type
+ typedef std::ptrdiff_t difference_type;
+
+private:
+ //! \cond
+
+ //! Implementation
+ struct implementation;
+ friend struct implementation;
+
+ //! A base class for the container nodes
+ struct node_base
+ {
+ node_base* m_pPrev;
+ node_base* m_pNext;
+
+ node_base();
+
+ BOOST_DELETED_FUNCTION(node_base(node_base const&))
+ BOOST_DELETED_FUNCTION(node_base& operator= (node_base const&))
+ };
+
+ //! Container elements
+ struct node;
+ friend struct node;
+ struct node :
+ public node_base
+ {
+ value_type m_Value;
+
+ node(key_type const& key, mapped_type const& data);
+ };
+
+ //! Iterator class
+#ifndef BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS
+ template< bool fConstV > class iter;
+ template< bool fConstV > friend class iter;
+#endif
+ template< bool fConstV >
+ class iter
+ {
+ friend class iter< !fConstV >;
+ friend class attribute_set;
+
+ public:
+ // Standard typedefs
+ typedef attribute_set::difference_type difference_type;
+ typedef attribute_set::value_type value_type;
+ typedef typename mpl::if_c<
+ fConstV,
+ attribute_set::const_reference,
+ attribute_set::reference
+ >::type reference;
+ typedef typename mpl::if_c<
+ fConstV,
+ attribute_set::const_pointer,
+ attribute_set::pointer
+ >::type pointer;
+ typedef std::bidirectional_iterator_tag iterator_category;
+
+ public:
+ // Constructors
+ BOOST_CONSTEXPR iter() : m_pNode(NULL) {}
+ explicit iter(node_base* pNode) BOOST_NOEXCEPT : m_pNode(pNode) {}
+ iter(iter< false > const& that) BOOST_NOEXCEPT : m_pNode(that.m_pNode) {}
+
+ //! Assignment
+ template< bool f >
+ iter& operator= (iter< f > const& that) BOOST_NOEXCEPT
+ {
+ m_pNode = that.m_pNode;
+ return *this;
+ }
+
+ // Comparison
+ template< bool f >
+ bool operator== (iter< f > const& that) const BOOST_NOEXCEPT { return (m_pNode == that.m_pNode); }
+ template< bool f >
+ bool operator!= (iter< f > const& that) const BOOST_NOEXCEPT { return (m_pNode != that.m_pNode); }
+
+ // Modification
+ iter& operator++ () BOOST_NOEXCEPT
+ {
+ m_pNode = m_pNode->m_pNext;
+ return *this;
+ }
+ iter& operator-- () BOOST_NOEXCEPT
+ {
+ m_pNode = m_pNode->m_pPrev;
+ return *this;
+ }
+ iter operator++ (int) BOOST_NOEXCEPT
+ {
+ iter tmp(*this);
+ m_pNode = m_pNode->m_pNext;
+ return tmp;
+ }
+ iter operator-- (int) BOOST_NOEXCEPT
+ {
+ iter tmp(*this);
+ m_pNode = m_pNode->m_pPrev;
+ return tmp;
+ }
+
+ // Dereferencing
+ pointer operator-> () const BOOST_NOEXCEPT { return &(static_cast< node* >(m_pNode)->m_Value); }
+ reference operator* () const BOOST_NOEXCEPT { return static_cast< node* >(m_pNode)->m_Value; }
+
+ node_base* base() const BOOST_NOEXCEPT { return m_pNode; }
+
+ private:
+ node_base* m_pNode;
+ };
+
+ //! \endcond
+
+public:
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ //! Iterator type
+ typedef iter< false > iterator;
+ //! Const iterator type
+ typedef iter< true > const_iterator;
+#else
+ /*!
+ * Iterator type. The iterator complies to the bidirectional iterator requirements.
+ */
+ typedef implementation_defined iterator;
+ /*!
+ * Constant iterator type. The iterator complies to the bidirectional iterator requirements with read-only capabilities.
+ */
+ typedef implementation_defined const_iterator;
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+private:
+ //! Pointer to implementation
+ implementation* m_pImpl;
+
+public:
+ /*!
+ * Default constructor.
+ *
+ * \post <tt>empty() == true</tt>
+ */
+ BOOST_LOG_API attribute_set();
+
+ /*!
+ * Copy constructor.
+ *
+ * \post <tt>size() == that.size() && std::equal(begin(), end(), that.begin()) == true</tt>
+ */
+ BOOST_LOG_API attribute_set(attribute_set const& that);
+
+ /*!
+ * Move constructor
+ */
+ attribute_set(BOOST_RV_REF(attribute_set) that) BOOST_NOEXCEPT : m_pImpl(that.m_pImpl)
+ {
+ that.m_pImpl = NULL;
+ }
+
+ /*!
+ * Destructor. All stored references to attributes are released.
+ */
+ BOOST_LOG_API ~attribute_set() BOOST_NOEXCEPT;
+
+ /*!
+ * Copy assignment operator.
+ *
+ * \post <tt>size() == that.size() && std::equal(begin(), end(), that.begin()) == true</tt>
+ */
+ attribute_set& operator= (attribute_set that) BOOST_NOEXCEPT
+ {
+ this->swap(that);
+ return *this;
+ }
+
+ /*!
+ * Swaps two instances of the container.
+ *
+ * \b Throws: Nothing.
+ */
+ void swap(attribute_set& that) BOOST_NOEXCEPT
+ {
+ implementation* const p = m_pImpl;
+ m_pImpl = that.m_pImpl;
+ that.m_pImpl = p;
+ }
+
+ /*!
+ * \return Iterator to the first element of the container.
+ */
+ BOOST_LOG_API iterator begin() BOOST_NOEXCEPT;
+ /*!
+ * \return Iterator to the after-the-last element of the container.
+ */
+ BOOST_LOG_API iterator end() BOOST_NOEXCEPT;
+ /*!
+ * \return Constant iterator to the first element of the container.
+ */
+ BOOST_LOG_API const_iterator begin() const BOOST_NOEXCEPT;
+ /*!
+ * \return Constant iterator to the after-the-last element of the container.
+ */
+ BOOST_LOG_API const_iterator end() const BOOST_NOEXCEPT;
+
+ /*!
+ * \return Number of elements in the container.
+ */
+ BOOST_LOG_API size_type size() const BOOST_NOEXCEPT;
+ /*!
+ * \return true if there are no elements in the container, false otherwise.
+ */
+ bool empty() const BOOST_NOEXCEPT { return (this->size() == 0); }
+
+ /*!
+ * The method finds the attribute by name.
+ *
+ * \param key Attribute name.
+ * \return Iterator to the found element or end() if the attribute with such name is not found.
+ */
+ BOOST_LOG_API iterator find(key_type key) BOOST_NOEXCEPT;
+ /*!
+ * The method finds the attribute by name.
+ *
+ * \param key Attribute name.
+ * \return Iterator to the found element or \c end() if the attribute with such name is not found.
+ */
+ const_iterator find(key_type key) const BOOST_NOEXCEPT
+ {
+ return const_iterator(const_cast< attribute_set* >(this)->find(key));
+ }
+ /*!
+ * The method counts the number of the attribute occurrences in the container. Since there can be only one
+ * attribute with a particular key, the method always return 0 or 1.
+ *
+ * \param key Attribute name.
+ * \return The number of times the attribute is found in the container.
+ */
+ size_type count(key_type key) const BOOST_NOEXCEPT { return size_type(this->find(key) != this->end()); }
+
+ /*!
+ * Combined lookup/insertion operator. The operator semantics depends on the further usage of the returned reference.
+ * \li If the reference is used as an assignment target, the assignment expression is equivalent to element insertion,
+ * where the element is composed of the second argument of the \c operator[] as a key and the second argument of assignment
+ * as a mapped value.
+ * \li If the returned reference is used in context where a conversion to the mapped type is required,
+ * the result of the conversion is equivalent to the mapped value found with the second argument of the \c operator[] as a key,
+ * if such an element exists in the container, or a default-constructed mapped value, if an element does not exist in the
+ * container.
+ *
+ * \param key Attribute name.
+ * \return A smart reference object of unspecified type.
+ */
+ aux::attribute_set_reference_proxy operator[] (key_type key) BOOST_NOEXCEPT
+ {
+ return aux::attribute_set_reference_proxy(this, key);
+ }
+ /*!
+ * Lookup operator
+ *
+ * \param key Attribute name.
+ * \return If an element with the corresponding attribute name is found in the container, its mapped value
+ * is returned. Otherwise a default-constructed mapped value is returned.
+ */
+ mapped_type operator[] (key_type key) const BOOST_NOEXCEPT
+ {
+ const_iterator it = this->find(key);
+ if (it != end())
+ return it->second;
+ else
+ return mapped_type();
+ }
+
+ /*!
+ * Insertion method
+ *
+ * \param key Attribute name.
+ * \param data Pointer to the attribute. Must not be NULL.
+ * \returns A pair of values. If second is true, the insertion succeeded and the first component points to the
+ * inserted element. Otherwise the first component points to the element that prevents insertion.
+ */
+ BOOST_LOG_API std::pair< iterator, bool > insert(key_type key, mapped_type const& data);
+
+ /*!
+ * Insertion method
+ *
+ * \param value An element to be inserted.
+ * \returns A pair of values. If second is true, the insertion succeeded and the first component points to the
+ * inserted element. Otherwise the first component points to the element that prevents insertion.
+ */
+ std::pair< iterator, bool > insert(const_reference value)
+ {
+ return this->insert(value.first, value.second);
+ }
+
+ /*!
+ * Mass insertion method.
+ *
+ * \param begin A forward iterator that points to the first element to be inserted.
+ * \param end A forward iterator that points to the after-the-last element to be inserted.
+ */
+ template< typename FwdIteratorT >
+ void insert(FwdIteratorT begin, FwdIteratorT end)
+ {
+ for (; begin != end; ++begin)
+ this->insert(*begin);
+ }
+
+ /*!
+ * Mass insertion method with ability to acquire iterators to the inserted elements.
+ *
+ * \param begin A forward iterator that points to the first element to be inserted.
+ * \param end A forward iterator that points to the after-the-last element to be inserted.
+ * \param out An output iterator that receives results of insertion of the elements
+ */
+ template< typename FwdIteratorT, typename OutputIteratorT >
+ void insert(FwdIteratorT begin, FwdIteratorT end, OutputIteratorT out)
+ {
+ for (; begin != end; ++begin, ++out)
+ *out = this->insert(*begin);
+ }
+
+ /*!
+ * The method erases all attributes with the specified name
+ *
+ * \post All iterators to the erased elements become invalid.
+ * \param key Attribute name.
+ * \return Tne number of erased elements
+ */
+ BOOST_LOG_API size_type erase(key_type key) BOOST_NOEXCEPT;
+ /*!
+ * The method erases the specified attribute
+ *
+ * \post All iterators to the erased element become invalid.
+ * \param it A valid iterator to the element to be erased.
+ * \return Tne number of erased elements
+ */
+ BOOST_LOG_API void erase(iterator it) BOOST_NOEXCEPT;
+ /*!
+ * The method erases all attributes within the specified range
+ *
+ * \pre \a end is reachable from \a begin with a finite number of increments.
+ * \post All iterators to the erased elements become invalid.
+ * \param begin An iterator that points to the first element to be erased.
+ * \param end An iterator that points to the after-the-last element to be erased.
+ */
+ BOOST_LOG_API void erase(iterator begin, iterator end) BOOST_NOEXCEPT;
+
+ /*!
+ * The method removes all elements from the container
+ *
+ * \post <tt>empty() == true</tt>
+ */
+ BOOST_LOG_API void clear() BOOST_NOEXCEPT;
+};
+
+/*!
+ * Free swap overload
+ */
+inline void swap(attribute_set& left, attribute_set& right) BOOST_NOEXCEPT
+{
+ left.swap(right);
+}
+
+namespace aux {
+
+//! Conversion operator (would be invoked in case of reading from the container)
+inline attribute_set_reference_proxy::operator mapped_type() const BOOST_NOEXCEPT
+{
+ attribute_set::iterator it = m_pContainer->find(m_key);
+ if (it != m_pContainer->end())
+ return it->second;
+ else
+ return mapped_type();
+}
+
+//! Assignment operator (would be invoked in case of writing to the container)
+inline attribute_set_reference_proxy::mapped_type& attribute_set_reference_proxy::operator= (mapped_type const& val) const
+{
+ std::pair< attribute_set::iterator, bool > res = m_pContainer->insert(m_key, val);
+ if (!res.second)
+ res.first->second = val;
+ return res.first->second;
+}
+
+} // namespace aux
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+inline attribute& attribute::operator= (aux::attribute_set_reference_proxy const& that) BOOST_NOEXCEPT
+{
+ attribute attr = that;
+ this->swap(attr);
+ return *this;
+}
+#endif
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTRIBUTE_SET_HPP_INCLUDED_
diff --git a/boost/log/attributes/attribute_value.hpp b/boost/log/attributes/attribute_value.hpp
new file mode 100644
index 0000000000..972093d9b7
--- /dev/null
+++ b/boost/log/attributes/attribute_value.hpp
@@ -0,0 +1,380 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file attribute_value.hpp
+ * \author Andrey Semashev
+ * \date 21.05.2010
+ *
+ * The header contains \c attribute_value class definition.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTE_VALUE_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTE_VALUE_HPP_INCLUDED_
+
+#include <boost/move/core.hpp>
+#include <boost/smart_ptr/intrusive_ptr.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/utility/explicit_operator_bool.hpp>
+#include <boost/log/utility/type_info_wrapper.hpp>
+#include <boost/log/utility/type_dispatch/type_dispatcher.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/attributes/value_extraction_fwd.hpp>
+#include <boost/log/attributes/value_visitation_fwd.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * \brief An attribute value class
+ *
+ * An attribute value is an object that contains a piece of data that represents an attribute state
+ * at the point of the value acquisition. All major operations with log records, such as filtering and
+ * formatting, involve attribute values contained in a single view. Most likely an attribute value is
+ * implemented as a simple holder of some typed value. This holder implements the
+ * \c attribute_value::implementation interface and acts as a pimpl for the \c attribute_value
+ * object. The \c attribute_value class provides type dispatching support in order to allow
+ * to extract the value from the holder.
+ *
+ * Normally, attributes and their values shall be designed in order to exclude as much interference as
+ * reasonable. Such approach allows to have more than one attribute value simultaneously, which improves
+ * scalability and allows to implement generating attributes.
+ *
+ * However, there are cases when this approach does not help to achieve the required level of independency
+ * of attribute values and attribute itself from each other at a reasonable performance tradeoff.
+ * For example, an attribute or its values may use thread-specific data, which is global and shared
+ * between all the instances of the attribute/value. Passing such an attribute value to another thread
+ * would be a disaster. To solve this the library defines an additional method for attribute values,
+ * namely \c detach_from_thread. The \c attribute_value class forwards the call to its pimpl,
+ * which is supposed to ensure that it no longer refers to any thread-specific data after the call.
+ * The pimpl can create a new holder as a result of this method and return it to the \c attribute_value
+ * wrapper, which will keep the returned reference for any further calls.
+ * This method is called for all attribute values that are passed to another thread.
+ */
+class attribute_value
+{
+ BOOST_COPYABLE_AND_MOVABLE(attribute_value)
+
+public:
+ /*!
+ * \brief A base class for an attribute value implementation
+ *
+ * All attribute value holders should derive from this interface.
+ */
+ struct BOOST_LOG_NO_VTABLE impl :
+ public attribute::impl
+ {
+ public:
+ /*!
+ * The method dispatches the value to the given object.
+ *
+ * \param dispatcher The object that attempts to dispatch the stored value.
+ * \return true if \a dispatcher was capable to consume the real attribute value type and false otherwise.
+ */
+ virtual bool dispatch(type_dispatcher& dispatcher) = 0;
+
+ /*!
+ * The method is called when the attribute value is passed to another thread (e.g.
+ * in case of asynchronous logging). The value should ensure it properly owns all thread-specific data.
+ *
+ * \return An actual pointer to the attribute value. It may either point to this object or another.
+ * In the latter case the returned pointer replaces the pointer used by caller to invoke this
+ * method and is considered to be a functional equivalent to the previous pointer.
+ */
+ virtual intrusive_ptr< impl > detach_from_thread()
+ {
+ return this;
+ }
+
+ /*!
+ * \return The attribute value that refers to self implementation.
+ */
+ virtual attribute_value get_value() { return attribute_value(this); }
+
+ /*!
+ * \return The attribute value type
+ */
+ virtual type_info_wrapper get_type() const { return type_info_wrapper(); }
+ };
+
+private:
+ //! Pointer to the value implementation
+ intrusive_ptr< impl > m_pImpl;
+
+public:
+ /*!
+ * Default constructor. Creates an empty (absent) attribute value.
+ */
+ BOOST_DEFAULTED_FUNCTION(attribute_value(), {})
+
+ /*!
+ * Copy constructor
+ */
+ attribute_value(attribute_value const& that) BOOST_NOEXCEPT : m_pImpl(that.m_pImpl) {}
+
+ /*!
+ * Move constructor
+ */
+ attribute_value(BOOST_RV_REF(attribute_value) that) BOOST_NOEXCEPT { m_pImpl.swap(that.m_pImpl); }
+
+ /*!
+ * Initializing constructor. Creates an attribute value that refers to the specified holder.
+ *
+ * \param p A pointer to the attribute value holder.
+ */
+ explicit attribute_value(intrusive_ptr< impl > p) BOOST_NOEXCEPT { m_pImpl.swap(p); }
+
+ /*!
+ * Copy assignment
+ */
+ attribute_value& operator= (BOOST_COPY_ASSIGN_REF(attribute_value) that) BOOST_NOEXCEPT
+ {
+ m_pImpl = that.m_pImpl;
+ return *this;
+ }
+
+ /*!
+ * Move assignment
+ */
+ attribute_value& operator= (BOOST_RV_REF(attribute_value) that) BOOST_NOEXCEPT
+ {
+ m_pImpl.swap(that.m_pImpl);
+ return *this;
+ }
+
+ /*!
+ * The operator checks if the attribute value is empty
+ */
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+ /*!
+ * The operator checks if the attribute value is empty
+ */
+ bool operator! () const BOOST_NOEXCEPT { return !m_pImpl; }
+
+ /*!
+ * The method returns the type information of the stored value of the attribute.
+ * The returned type info wrapper may be empty if the attribute value is empty or
+ * the information cannot be provided. If the returned value is not empty, the type
+ * can be used for value extraction.
+ */
+ type_info_wrapper get_type() const
+ {
+ if (m_pImpl.get())
+ return m_pImpl->get_type();
+ else
+ return type_info_wrapper();
+ }
+
+ /*!
+ * The method is called when the attribute value is passed to another thread (e.g.
+ * in case of asynchronous logging). The value should ensure it properly owns all thread-specific data.
+ *
+ * \post The attribute value no longer refers to any thread-specific resources.
+ */
+ void detach_from_thread()
+ {
+ if (m_pImpl.get())
+ m_pImpl->detach_from_thread().swap(m_pImpl);
+ }
+
+ /*!
+ * The method dispatches the value to the given object. This method is a low level interface for
+ * attribute value visitation and extraction. For typical usage these interfaces may be more convenient.
+ *
+ * \param dispatcher The object that attempts to dispatch the stored value.
+ * \return \c true if the value is not empty and the \a dispatcher was capable to consume
+ * the real attribute value type and \c false otherwise.
+ */
+ bool dispatch(type_dispatcher& dispatcher) const
+ {
+ if (m_pImpl.get())
+ return m_pImpl->dispatch(dispatcher);
+ else
+ return false;
+ }
+
+#if !defined(BOOST_LOG_DOXYGEN_PASS)
+#if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
+#define BOOST_LOG_AUX_VOID_DEFAULT = void
+#else
+#define BOOST_LOG_AUX_VOID_DEFAULT
+#endif
+#endif // !defined(BOOST_LOG_DOXYGEN_PASS)
+
+ /*!
+ * The method attempts to extract the stored value, assuming the value has the specified type.
+ * One can specify either a single type or an MPL type sequence, in which case the stored value
+ * is checked against every type in the sequence.
+ *
+ * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
+ *
+ * \return The extracted value, if the attribute value is not empty and the value is the same
+ * as specified. Otherwise returns an empty value. See description of the \c result_of::extract
+ * metafunction for information on the nature of the result value.
+ */
+ template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT >
+ typename result_of::extract< T, TagT >::type extract() const;
+
+ /*!
+ * The method attempts to extract the stored value, assuming the value has the specified type.
+ * One can specify either a single type or an MPL type sequence, in which case the stored value
+ * is checked against every type in the sequence.
+ *
+ * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
+ *
+ * \return The extracted value, if the attribute value is not empty and the value is the same
+ * as specified. Otherwise an exception is thrown. See description of the \c result_of::extract_or_throw
+ * metafunction for information on the nature of the result value.
+ */
+ template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT >
+ typename result_of::extract_or_throw< T, TagT >::type extract_or_throw() const;
+
+ /*!
+ * The method attempts to extract the stored value, assuming the value has the specified type.
+ * One can specify either a single type or an MPL type sequence, in which case the stored value
+ * is checked against every type in the sequence. If extraction fails, the default value is returned.
+ *
+ * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
+ *
+ * \param def_value Default value.
+ *
+ * \return The extracted value, if the attribute value is not empty and the value is the same
+ * as specified. Otherwise returns the default value. See description of the \c result_of::extract_or_default
+ * metafunction for information on the nature of the result value.
+ */
+ template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT >
+ typename result_of::extract_or_default< T, T, TagT >::type extract_or_default(T const& def_value) const;
+
+ /*!
+ * The method attempts to extract the stored value, assuming the value has the specified type.
+ * One can specify either a single type or an MPL type sequence, in which case the stored value
+ * is checked against every type in the sequence. If extraction fails, the default value is returned.
+ *
+ * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
+ *
+ * \param def_value Default value.
+ *
+ * \return The extracted value, if the attribute value is not empty and the value is the same
+ * as specified. Otherwise returns the default value. See description of the \c result_of::extract_or_default
+ * metafunction for information on the nature of the result value.
+ */
+ template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT, typename DefaultT >
+ typename result_of::extract_or_default< T, DefaultT, TagT >::type extract_or_default(DefaultT const& def_value) const;
+
+#if defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
+ /*!
+ * The method attempts to extract the stored value, assuming the value has the specified type.
+ * One can specify either a single type or an MPL type sequence, in which case the stored value
+ * is checked against every type in the sequence.
+ *
+ * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
+ *
+ * \return The extracted value, if the attribute value is not empty and the value is the same
+ * as specified. Otherwise returns an empty value. See description of the \c result_of::extract
+ * metafunction for information on the nature of the result value.
+ */
+ template< typename T >
+ typename result_of::extract< T >::type extract() const;
+
+ /*!
+ * The method attempts to extract the stored value, assuming the value has the specified type.
+ * One can specify either a single type or an MPL type sequence, in which case the stored value
+ * is checked against every type in the sequence.
+ *
+ * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
+ *
+ * \return The extracted value, if the attribute value is not empty and the value is the same
+ * as specified. Otherwise an exception is thrown. See description of the \c result_of::extract_or_throw
+ * metafunction for information on the nature of the result value.
+ */
+ template< typename T >
+ typename result_of::extract_or_throw< T >::type extract_or_throw() const;
+
+ /*!
+ * The method attempts to extract the stored value, assuming the value has the specified type.
+ * One can specify either a single type or an MPL type sequence, in which case the stored value
+ * is checked against every type in the sequence. If extraction fails, the default value is returned.
+ *
+ * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
+ *
+ * \param def_value Default value.
+ *
+ * \return The extracted value, if the attribute value is not empty and the value is the same
+ * as specified. Otherwise returns the default value. See description of the \c result_of::extract_or_default
+ * metafunction for information on the nature of the result value.
+ */
+ template< typename T >
+ typename result_of::extract_or_default< T, T >::type extract_or_default(T const& def_value) const;
+
+ /*!
+ * The method attempts to extract the stored value, assuming the value has the specified type.
+ * One can specify either a single type or an MPL type sequence, in which case the stored value
+ * is checked against every type in the sequence. If extraction fails, the default value is returned.
+ *
+ * \note Include <tt>value_extraction.hpp</tt> prior to using this method.
+ *
+ * \param def_value Default value.
+ *
+ * \return The extracted value, if the attribute value is not empty and the value is the same
+ * as specified. Otherwise returns the default value. See description of the \c result_of::extract_or_default
+ * metafunction for information on the nature of the result value.
+ */
+ template< typename T, typename DefaultT >
+ typename result_of::extract_or_default< T, DefaultT >::type extract_or_default(DefaultT const& def_value) const;
+#endif // defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
+
+#undef BOOST_LOG_AUX_VOID_DEFAULT
+
+ /*!
+ * The method attempts to extract the stored value, assuming the value has the specified type,
+ * and pass it to the \a visitor function object.
+ * One can specify either a single type or an MPL type sequence, in which case the stored value
+ * is checked against every type in the sequence.
+ *
+ * \note Include <tt>value_visitation.hpp</tt> prior to using this method.
+ *
+ * \param visitor A function object that will be invoked on the extracted attribute value.
+ * The visitor should be capable to be called with a single argument of
+ * any type of the specified types in \c T.
+ *
+ * \return The result of visitation.
+ */
+ template< typename T, typename VisitorT >
+ visitation_result visit(VisitorT visitor) const;
+
+ /*!
+ * The method swaps two attribute values
+ */
+ void swap(attribute_value& that) BOOST_NOEXCEPT
+ {
+ m_pImpl.swap(that.m_pImpl);
+ }
+};
+
+/*!
+ * The function swaps two attribute values
+ */
+inline void swap(attribute_value& left, attribute_value& right) BOOST_NOEXCEPT
+{
+ left.swap(right);
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+#if defined(BOOST_LOG_ATTRIBUTES_ATTRIBUTE_HPP_INCLUDED_)
+#include <boost/log/detail/attribute_get_value_impl.hpp>
+#endif
+
+#endif // BOOST_LOG_ATTRIBUTE_VALUE_HPP_INCLUDED_
diff --git a/boost/log/attributes/attribute_value_impl.hpp b/boost/log/attributes/attribute_value_impl.hpp
new file mode 100644
index 0000000000..405c346861
--- /dev/null
+++ b/boost/log/attributes/attribute_value_impl.hpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file attribute_value_impl.hpp
+ * \author Andrey Semashev
+ * \date 24.06.2007
+ *
+ * The header contains an implementation of a basic attribute value implementation class.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTES_ATTRIBUTE_VALUE_IMPL_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTES_ATTRIBUTE_VALUE_IMPL_HPP_INCLUDED_
+
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/attributes/attribute_value.hpp>
+#include <boost/log/utility/type_dispatch/type_dispatcher.hpp>
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+#include <boost/type_traits/remove_reference.hpp>
+#endif
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace attributes {
+
+/*!
+ * \brief Basic attribute value implementation class
+ *
+ * This class can be used as a boilerplate for simple attribute values. The class implements all needed
+ * interfaces of attribute values and allows to store a single value of the type specified as a template parameter.
+ * The stored value can be dispatched with type dispatching mechanism.
+ */
+template< typename T >
+class attribute_value_impl :
+ public attribute_value::impl
+{
+public:
+ //! Value type
+ typedef T value_type;
+
+private:
+ //! Attribute value
+ const value_type m_value;
+
+public:
+ /*!
+ * Constructor with initialization of the stored value
+ */
+ explicit attribute_value_impl(value_type const& v) : m_value(v) {}
+ /*!
+ * Constructor with initialization of the stored value
+ */
+ explicit attribute_value_impl(BOOST_RV_REF(value_type) v) : m_value(v) {}
+
+ /*!
+ * Attribute value dispatching method.
+ *
+ * \param dispatcher The dispatcher that receives the stored value
+ *
+ * \return \c true if the value has been dispatched, \c false otherwise
+ */
+ virtual bool dispatch(type_dispatcher& dispatcher)
+ {
+ type_dispatcher::callback< value_type > callback = dispatcher.get_callback< value_type >();
+ if (callback)
+ {
+ callback(m_value);
+ return true;
+ }
+ else
+ return false;
+ }
+
+ /*!
+ * \return The attribute value type
+ */
+ type_info_wrapper get_type() const { return type_info_wrapper(typeid(value_type)); }
+
+ /*!
+ * \return Reference to the contained value.
+ */
+ value_type const& get() const { return m_value; }
+};
+
+/*!
+ * The function creates an attribute value from the specified object.
+ */
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+template< typename T >
+inline attribute_value make_attribute_value(T&& v)
+{
+ typedef typename remove_cv< typename remove_reference< T >::type >::type value_type;
+ return attribute_value(new attribute_value_impl< value_type >(boost::forward< T >(v)));
+}
+
+#else // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+template< typename T >
+inline attribute_value make_attribute_value(T const& v)
+{
+ typedef typename remove_cv< T >::type value_type;
+ return attribute_value(new attribute_value_impl< value_type >(v));
+}
+
+template< typename T >
+inline attribute_value make_attribute_value(rv< T > const& v)
+{
+ typedef typename remove_cv< T >::type value_type;
+ return attribute_value(new attribute_value_impl< value_type >(v));
+}
+
+#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+} // namespace attributes
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTRIBUTES_ATTRIBUTE_VALUE_IMPL_HPP_INCLUDED_
diff --git a/boost/log/attributes/attribute_value_set.hpp b/boost/log/attributes/attribute_value_set.hpp
new file mode 100644
index 0000000000..0ca635909c
--- /dev/null
+++ b/boost/log/attributes/attribute_value_set.hpp
@@ -0,0 +1,480 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file attribute_value_set.hpp
+ * \author Andrey Semashev
+ * \date 21.04.2007
+ *
+ * This header file contains definition of attribute value set. The set is constructed from
+ * three attribute sets (global, thread-specific and source-specific) and contains attribute
+ * values.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTE_VALUE_SET_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTE_VALUE_SET_HPP_INCLUDED_
+
+#include <cstddef>
+#include <utility>
+#include <iterator>
+#include <boost/move/core.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/attributes/attribute_value.hpp>
+#include <boost/log/attributes/attribute_set.hpp>
+#include <boost/log/expressions/keyword_fwd.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * \brief A set of attribute values
+ *
+ * The set of attribute values is an associative container with attribute name as a key and
+ * a pointer to attribute value object as a mapped type. This is a collection of elements with unique
+ * keys, that is, there can be only one attribute value with a given name in the set. With respect to
+ * read-only capabilities, the set interface is close to \c std::unordered_map.
+ *
+ * The set is designed to be only capable of adding elements to it. Once added, the attribute value
+ * cannot be removed from the set.
+ *
+ * An instance of attribute value set can be constructed from three attribute sets. The constructor attempts to
+ * accommodate values of all attributes from the sets. The situation when a same-named attribute is found
+ * in more than one attribute set is possible. This problem is solved on construction of the value set: the three
+ * attribute sets have different priorities when it comes to solving conflicts.
+ *
+ * From the library perspective the three source attribute sets are global, thread-specific and source-specific
+ * attributes, with the latter having the highest priority. This feature allows to override attributes of wider scopes
+ * with the more specific ones.
+ *
+ * For sake of performance, the attribute values are not immediately acquired from attribute sets at construction.
+ * Instead, on-demand acquisition is performed either on iterator dereferencing or on call to the \c freeze method.
+ * Once acquired, the attribute value stays within the set until its destruction. This nuance does not affect
+ * other set properties, such as size or lookup ability. The logging core automatically freezes the set
+ * at the right point, so users should not be bothered unless they manually create attribute value sets.
+ *
+ * \note The attribute sets that were used for the value set construction must not be modified or destroyed
+ * until the value set is frozen. Otherwise the behavior is undefined.
+ */
+class attribute_value_set
+{
+ BOOST_COPYABLE_AND_MOVABLE_ALT(attribute_value_set)
+
+public:
+ //! Key type
+ typedef attribute_name key_type;
+ //! Mapped attribute type
+ typedef attribute_value mapped_type;
+
+ //! Value type
+ typedef std::pair< const key_type, mapped_type > value_type;
+ //! Reference type
+ typedef value_type& reference;
+ //! Const reference type
+ typedef value_type const& const_reference;
+ //! Pointer type
+ typedef value_type* pointer;
+ //! Const pointer type
+ typedef value_type const* const_pointer;
+ //! Size type
+ typedef std::size_t size_type;
+ //! Pointer difference type
+ typedef std::ptrdiff_t difference_type;
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+private:
+ struct implementation;
+ friend struct implementation;
+
+ //! A base class for the container nodes
+ struct node_base
+ {
+ node_base* m_pPrev;
+ node_base* m_pNext;
+
+ node_base();
+
+ BOOST_DELETED_FUNCTION(node_base(node_base const&))
+ BOOST_DELETED_FUNCTION(node_base& operator= (node_base const&))
+ };
+
+ //! Container elements
+ struct node;
+ friend struct node;
+ struct node :
+ public node_base
+ {
+ value_type m_Value;
+ bool m_DynamicallyAllocated;
+
+ node(key_type const& key, mapped_type& data, bool dynamic);
+ };
+
+public:
+ class const_iterator;
+ friend class const_iterator;
+ class const_iterator
+ {
+ public:
+ // Standard typedefs
+ typedef attribute_value_set::difference_type difference_type;
+ typedef attribute_value_set::value_type value_type;
+ typedef attribute_value_set::const_reference reference;
+ typedef attribute_value_set::const_pointer pointer;
+ typedef std::bidirectional_iterator_tag iterator_category;
+
+ public:
+ // Constructors
+ BOOST_CONSTEXPR const_iterator() : m_pNode(NULL), m_pContainer(NULL) {}
+ explicit const_iterator(node_base* n, attribute_value_set* cont) BOOST_NOEXCEPT :
+ m_pNode(n),
+ m_pContainer(cont)
+ {
+ }
+
+ // Comparison
+ bool operator== (const_iterator const& that) const BOOST_NOEXCEPT
+ {
+ return (m_pNode == that.m_pNode);
+ }
+ bool operator!= (const_iterator const& that) const BOOST_NOEXCEPT
+ {
+ return (m_pNode != that.m_pNode);
+ }
+
+ // Modification
+ const_iterator& operator++ ()
+ {
+ m_pContainer->freeze();
+ m_pNode = m_pNode->m_pNext;
+ return *this;
+ }
+ const_iterator& operator-- ()
+ {
+ m_pContainer->freeze();
+ m_pNode = m_pNode->m_pPrev;
+ return *this;
+ }
+ const_iterator operator++ (int)
+ {
+ const_iterator tmp(*this);
+ m_pContainer->freeze();
+ m_pNode = m_pNode->m_pNext;
+ return tmp;
+ }
+ const_iterator operator-- (int)
+ {
+ const_iterator tmp(*this);
+ m_pContainer->freeze();
+ m_pNode = m_pNode->m_pPrev;
+ return tmp;
+ }
+
+ // Dereferencing
+ pointer operator-> () const BOOST_NOEXCEPT { return &(static_cast< node* >(m_pNode)->m_Value); }
+ reference operator* () const BOOST_NOEXCEPT { return static_cast< node* >(m_pNode)->m_Value; }
+
+ private:
+ node_base* m_pNode;
+ attribute_value_set* m_pContainer;
+ };
+
+#else
+
+ /*!
+ * Constant iterator type with bidirectional capabilities.
+ */
+ typedef implementation_defined const_iterator;
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+private:
+ //! Pointer to the container implementation
+ implementation* m_pImpl;
+
+public:
+ /*!
+ * Default constructor
+ *
+ * The constructor creates an empty set which can be filled later by subsequent
+ * calls of \c insert method. Optionally, the amount of storage reserved for elements
+ * to be inserted may be passed to the constructor.
+ * The constructed set is frozen.
+ *
+ * \param reserve_count Number of elements to reserve space for.
+ */
+ BOOST_LOG_API explicit attribute_value_set(size_type reserve_count = 8);
+
+ /*!
+ * Move constructor
+ */
+ attribute_value_set(BOOST_RV_REF(attribute_value_set) that) BOOST_NOEXCEPT : m_pImpl(that.m_pImpl)
+ {
+ that.m_pImpl = NULL;
+ }
+
+ /*!
+ * The constructor adopts three attribute sets into the value set.
+ * The \a source_attrs attributes have the greatest preference when a same-named
+ * attribute is found in several sets, \a global_attrs has the least.
+ * The constructed set is not frozen.
+ *
+ * \param source_attrs A set of source-specific attributes.
+ * \param thread_attrs A set of thread-specific attributes.
+ * \param global_attrs A set of global attributes.
+ * \param reserve_count Amount of elements to reserve space for, in addition to the elements in the three attribute sets provided.
+ */
+ BOOST_LOG_API attribute_value_set(
+ attribute_set const& source_attrs,
+ attribute_set const& thread_attrs,
+ attribute_set const& global_attrs,
+ size_type reserve_count = 8);
+
+ /*!
+ * The constructor adopts three attribute sets into the value set.
+ * The \a source_attrs attributes have the greatest preference when a same-named
+ * attribute is found in several sets, \a global_attrs has the least.
+ * The constructed set is not frozen.
+ *
+ * \pre The \a source_attrs set is frozen.
+ *
+ * \param source_attrs A set of source-specific attributes.
+ * \param thread_attrs A set of thread-specific attributes.
+ * \param global_attrs A set of global attributes.
+ * \param reserve_count Amount of elements to reserve space for, in addition to the elements in the three attribute sets provided.
+ */
+ BOOST_LOG_API attribute_value_set(
+ attribute_value_set const& source_attrs,
+ attribute_set const& thread_attrs,
+ attribute_set const& global_attrs,
+ size_type reserve_count = 8);
+
+ /*!
+ * The constructor adopts three attribute sets into the value set.
+ * The \a source_attrs attributes have the greatest preference when a same-named
+ * attribute is found in several sets, \a global_attrs has the least.
+ * The constructed set is not frozen.
+ *
+ * \pre The \a source_attrs set is frozen.
+ *
+ * \param source_attrs A set of source-specific attributes.
+ * \param thread_attrs A set of thread-specific attributes.
+ * \param global_attrs A set of global attributes.
+ * \param reserve_count Amount of elements to reserve space for, in addition to the elements in the three attribute sets provided.
+ */
+ attribute_value_set(
+ BOOST_RV_REF(attribute_value_set) source_attrs,
+ attribute_set const& thread_attrs,
+ attribute_set const& global_attrs,
+ size_type reserve_count = 8) : m_pImpl(NULL)
+ {
+ construct(static_cast< attribute_value_set& >(source_attrs), thread_attrs, global_attrs, reserve_count);
+ }
+
+ /*!
+ * Copy constructor.
+ *
+ * \pre The original set is frozen.
+ * \post The constructed set is frozen, <tt>std::equal(begin(), end(), that.begin()) == true</tt>
+ */
+ BOOST_LOG_API attribute_value_set(attribute_value_set const& that);
+
+ /*!
+ * Destructor. Releases all referenced attribute values.
+ */
+ BOOST_LOG_API ~attribute_value_set() BOOST_NOEXCEPT;
+
+ /*!
+ * Assignment operator
+ */
+ attribute_value_set& operator= (attribute_value_set that) BOOST_NOEXCEPT
+ {
+ this->swap(that);
+ return *this;
+ }
+
+ /*!
+ * Swaps two sets
+ *
+ * \b Throws: Nothing.
+ */
+ void swap(attribute_value_set& that) BOOST_NOEXCEPT
+ {
+ implementation* const p = m_pImpl;
+ m_pImpl = that.m_pImpl;
+ that.m_pImpl = p;
+ }
+
+ /*!
+ * \return Iterator to the first element of the set.
+ */
+ BOOST_LOG_API const_iterator begin() const;
+ /*!
+ * \return Iterator to the after-the-last element of the set.
+ */
+ BOOST_LOG_API const_iterator end() const;
+
+ /*!
+ * \return Number of elements in the set.
+ */
+ BOOST_LOG_API size_type size() const;
+ /*!
+ * \return true if there are no elements in the container, false otherwise.
+ */
+ bool empty() const { return (this->size() == 0); }
+
+ /*!
+ * The method finds the attribute value by name.
+ *
+ * \param key Attribute name.
+ * \return Iterator to the found element or \c end() if the attribute with such name is not found.
+ */
+ BOOST_LOG_API const_iterator find(key_type key) const;
+
+ /*!
+ * Alternative lookup syntax.
+ *
+ * \param key Attribute name.
+ * \return A pointer to the attribute value if it is found with \a key, default-constructed mapped value otherwise.
+ */
+ mapped_type operator[] (key_type key) const
+ {
+ const_iterator it = this->find(key);
+ if (it != this->end())
+ return it->second;
+ else
+ return mapped_type();
+ }
+
+ /*!
+ * Alternative lookup syntax.
+ *
+ * \param keyword Attribute keyword.
+ * \return A \c value_ref with extracted attribute value if it is found, empty \c value_ref otherwise.
+ */
+ template< typename DescriptorT, template< typename > class ActorT >
+ typename result_of::extract< typename expressions::attribute_keyword< DescriptorT, ActorT >::value_type, DescriptorT >::type
+ operator[] (expressions::attribute_keyword< DescriptorT, ActorT > const& keyword) const
+ {
+ typedef typename expressions::attribute_keyword< DescriptorT, ActorT >::value_type attr_value_type;
+ typedef typename result_of::extract< attr_value_type, DescriptorT >::type result_type;
+ const_iterator it = this->find(keyword.get_name());
+ if (it != this->end())
+ return it->second.extract< attr_value_type, DescriptorT >();
+ else
+ return result_type();
+ }
+
+ /*!
+ * The method counts the number of the attribute value occurrences in the set. Since there can be only one
+ * attribute value with a particular key, the method always return 0 or 1.
+ *
+ * \param key Attribute name.
+ * \return The number of times the attribute value is found in the container.
+ */
+ size_type count(key_type key) const { return size_type(this->find(key) != this->end()); }
+
+ /*!
+ * The method acquires values of all adopted attributes.
+ *
+ * \post The set is frozen.
+ */
+ BOOST_LOG_API void freeze();
+
+ /*!
+ * Inserts an element into the set. The complexity of the operation is amortized constant.
+ *
+ * \pre The set is frozen.
+ *
+ * \param key The attribute name.
+ * \param mapped The attribute value.
+ *
+ * \returns An iterator to the inserted element and \c true if insertion succeeded. Otherwise,
+ * if the set already contains a same-named attribute value, iterator to the
+ * existing element and \c false.
+ */
+ BOOST_LOG_API std::pair< const_iterator, bool > insert(key_type key, mapped_type const& mapped);
+
+ /*!
+ * Inserts an element into the set. The complexity of the operation is amortized constant.
+ *
+ * \pre The set is frozen.
+ *
+ * \param value The attribute name and value.
+ *
+ * \returns An iterator to the inserted element and \c true if insertion succeeded. Otherwise,
+ * if the set already contains a same-named attribute value, iterator to the
+ * existing element and \c false.
+ */
+ std::pair< const_iterator, bool > insert(const_reference value) { return this->insert(value.first, value.second); }
+
+ /*!
+ * Mass insertion method. The complexity of the operation is linear to the number of elements inserted.
+ *
+ * \pre The set is frozen.
+ *
+ * \param begin A forward iterator that points to the first element to be inserted.
+ * \param end A forward iterator that points to the after-the-last element to be inserted.
+ */
+ template< typename FwdIteratorT >
+ void insert(FwdIteratorT begin, FwdIteratorT end)
+ {
+ for (; begin != end; ++begin)
+ this->insert(*begin);
+ }
+
+ /*!
+ * Mass insertion method with ability to acquire iterators to the inserted elements.
+ * The complexity of the operation is linear to the number of elements inserted times the complexity
+ * of filling the \a out iterator.
+ *
+ * \pre The set is frozen.
+ *
+ * \param begin A forward iterator that points to the first element to be inserted.
+ * \param end A forward iterator that points to the after-the-last element to be inserted.
+ * \param out An output iterator that receives results of insertion of the elements.
+ */
+ template< typename FwdIteratorT, typename OutputIteratorT >
+ void insert(FwdIteratorT begin, FwdIteratorT end, OutputIteratorT out)
+ {
+ for (; begin != end; ++begin, ++out)
+ *out = this->insert(*begin);
+ }
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+private:
+ //! Constructs the object by moving from \a source_attrs. This function is mostly needed to maintain ABI stable between C++03 and C++11.
+ BOOST_LOG_API void construct(
+ attribute_value_set& source_attrs,
+ attribute_set const& thread_attrs,
+ attribute_set const& global_attrs,
+ size_type reserve_count);
+#endif // BOOST_LOG_DOXYGEN_PASS
+};
+
+/*!
+ * Free swap overload
+ */
+inline void swap(attribute_value_set& left, attribute_value_set& right) BOOST_NOEXCEPT
+{
+ left.swap(right);
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTRIBUTE_VALUE_SET_HPP_INCLUDED_
diff --git a/boost/log/attributes/clock.hpp b/boost/log/attributes/clock.hpp
new file mode 100644
index 0000000000..c28da5a877
--- /dev/null
+++ b/boost/log/attributes/clock.hpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file clock.hpp
+ * \author Andrey Semashev
+ * \date 01.12.2007
+ *
+ * The header contains wall clock attribute implementation and typedefs.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTES_CLOCK_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTES_CLOCK_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/attributes/attribute_value.hpp>
+#include <boost/log/attributes/attribute_cast.hpp>
+#include <boost/log/attributes/attribute_value_impl.hpp>
+#include <boost/log/attributes/time_traits.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace attributes {
+
+/*!
+ * \brief A class of an attribute that makes an attribute value of the current date and time
+ *
+ * The attribute generates current time stamp as a value. The type of the attribute value
+ * is determined with time traits passed to the class template as a template parameter.
+ * The time traits provided by the library use \c boost::posix_time::ptime as the time type.
+ *
+ * Time traits also determine the way time is acquired. There are two types of time traits
+ * provided by the library: \c utc_time_traits and \c local_time_traits. The first returns UTC time,
+ * the second returns local time.
+ */
+template< typename TimeTraitsT >
+class basic_clock :
+ public attribute
+{
+public:
+ //! Generated value type
+ typedef typename TimeTraitsT::time_type value_type;
+
+protected:
+ //! Attribute factory implementation
+ struct BOOST_SYMBOL_VISIBLE impl :
+ public attribute::impl
+ {
+ attribute_value get_value()
+ {
+ typedef attribute_value_impl< value_type > result_value;
+ return attribute_value(new result_value(TimeTraitsT::get_clock()));
+ }
+ };
+
+public:
+ /*!
+ * Default constructor
+ */
+ basic_clock() : attribute(new impl())
+ {
+ }
+ /*!
+ * Constructor for casting support
+ */
+ explicit basic_clock(cast_source const& source) : attribute(source.as< impl >())
+ {
+ }
+};
+
+//! Attribute that returns current UTC time
+typedef basic_clock< utc_time_traits > utc_clock;
+//! Attribute that returns current local time
+typedef basic_clock< local_time_traits > local_clock;
+
+} // namespace attributes
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTRIBUTES_CLOCK_HPP_INCLUDED_
diff --git a/boost/log/attributes/constant.hpp b/boost/log/attributes/constant.hpp
new file mode 100644
index 0000000000..f2ae0a7847
--- /dev/null
+++ b/boost/log/attributes/constant.hpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file constant.hpp
+ * \author Andrey Semashev
+ * \date 15.04.2007
+ *
+ * The header contains implementation of a constant attribute.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTES_CONSTANT_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTES_CONSTANT_HPP_INCLUDED_
+
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/embedded_string_type.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/attributes/attribute_cast.hpp>
+#include <boost/log/attributes/attribute_value_impl.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace attributes {
+
+/*!
+ * \brief A class of an attribute that holds a single constant value
+ *
+ * The constant is a simplest and one of the most frequently used types of attributes.
+ * It stores a constant value, which it eventually returns as its value each time
+ * requested.
+ */
+template< typename T >
+class constant :
+ public attribute
+{
+public:
+ //! Attribute value type
+ typedef T value_type;
+
+protected:
+ //! Factory implementation
+ class BOOST_SYMBOL_VISIBLE impl :
+ public attribute_value_impl< value_type >
+ {
+ //! Base type
+ typedef attribute_value_impl< value_type > base_type;
+
+ public:
+ /*!
+ * Constructor with the stored value initialization
+ */
+ explicit impl(value_type const& value) : base_type(value) {}
+ /*!
+ * Constructor with the stored value initialization
+ */
+ explicit impl(BOOST_RV_REF(value_type) value) : base_type(boost::move(value)) {}
+ };
+
+public:
+ /*!
+ * Constructor with the stored value initialization
+ */
+ explicit constant(value_type const& value) : attribute(new impl(value)) {}
+ /*!
+ * Constructor with the stored value initialization
+ */
+ explicit constant(BOOST_RV_REF(value_type) value) : attribute(new impl(boost::move(value))) {}
+ /*!
+ * Constructor for casting support
+ */
+ explicit constant(cast_source const& source) : attribute(source.as< impl >())
+ {
+ }
+
+ /*!
+ * \return Reference to the contained value.
+ */
+ value_type const& get() const
+ {
+ return static_cast< impl* >(this->get_impl())->get();
+ }
+};
+
+/*!
+ * The function constructs a \c constant attribute containing the provided value.
+ * The function automatically converts C string arguments to \c std::basic_string objects.
+ */
+template< typename T >
+inline constant<
+ typename boost::log::aux::make_embedded_string_type<
+ typename remove_reference< T >::type
+ >::type
+> make_constant(BOOST_FWD_REF(T) val)
+{
+ typedef typename boost::log::aux::make_embedded_string_type<
+ typename remove_reference< T >::type
+ >::type value_type;
+ return constant< value_type >(boost::forward< T >(val));
+}
+
+} // namespace attributes
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTRIBUTES_CONSTANT_HPP_INCLUDED_
diff --git a/boost/log/attributes/counter.hpp b/boost/log/attributes/counter.hpp
new file mode 100644
index 0000000000..a4722714c9
--- /dev/null
+++ b/boost/log/attributes/counter.hpp
@@ -0,0 +1,218 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file counter.hpp
+ * \author Andrey Semashev
+ * \date 01.05.2007
+ *
+ * The header contains implementation of the counter attribute.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTES_COUNTER_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTES_COUNTER_HPP_INCLUDED_
+
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/attributes/attribute_cast.hpp>
+#include <boost/log/attributes/attribute_value_impl.hpp>
+#ifndef BOOST_LOG_NO_THREADS
+#include <boost/detail/atomic_count.hpp>
+#endif // BOOST_LOG_NO_THREADS
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace attributes {
+
+/*!
+ * \brief A class of an attribute that counts an integral value
+ *
+ * This type of attribute acts as a counter, that is, it returns a monotonously
+ * changing value each time requested. The attribute value type can be specified
+ * as a template parameter. However, the type must be an integral type of size no
+ * more than <tt>sizeof(long)</tt>.
+ */
+template< typename T >
+class counter :
+ public attribute
+{
+ // For now only integral types up to long are supported
+ BOOST_STATIC_ASSERT_MSG(is_integral< T >::value && sizeof(T) <= sizeof(long), "Boost.Log: Only integral types up to long are supported by counter attribute");
+
+public:
+ //! A counter value type
+ typedef T value_type;
+
+protected:
+ //! Base class for factory implementation
+ class BOOST_LOG_NO_VTABLE BOOST_SYMBOL_VISIBLE impl :
+ public attribute::impl
+ {
+ };
+
+ //! Generic factory implementation
+ class impl_generic;
+#ifndef BOOST_LOG_NO_THREADS
+ //! Increment-by-one factory implementation
+ class impl_inc;
+ //! Decrement-by-one factory implementation
+ class impl_dec;
+#endif
+
+public:
+ /*!
+ * Constructor
+ *
+ * \param initial Initial value of the counter
+ * \param step Changing step of the counter. Each value acquired from the attribute
+ * will be greater than the previous one to this amount.
+ */
+ explicit counter(value_type initial = (value_type)0, long step = 1) :
+#ifndef BOOST_LOG_NO_THREADS
+ attribute()
+ {
+ if (step == 1)
+ this->set_impl(new impl_inc(initial));
+ else if (step == -1)
+ this->set_impl(new impl_dec(initial));
+ else
+ this->set_impl(new impl_generic(initial, step));
+ }
+#else
+ attribute(new impl_generic(initial, step))
+ {
+ }
+#endif
+ /*!
+ * Constructor for casting support
+ */
+ explicit counter(cast_source const& source) :
+ attribute(source.as< impl >())
+ {
+ }
+};
+
+#ifndef BOOST_LOG_NO_THREADS
+
+template< typename T >
+class counter< T >::impl_generic :
+ public impl
+{
+private:
+ //! Initial value
+ const value_type m_Initial;
+ //! Step value
+ const long m_Step;
+ //! The counter
+ boost::detail::atomic_count m_Counter;
+
+public:
+ /*!
+ * Initializing constructor
+ */
+ impl_generic(value_type initial, long step) : m_Initial(initial), m_Step(step), m_Counter(-1)
+ {
+ }
+
+ attribute_value get_value()
+ {
+ const unsigned long next_counter = static_cast< unsigned long >(++m_Counter);
+ value_type next = static_cast< value_type >(m_Initial + (next_counter * m_Step));
+ return make_attribute_value(next);
+ }
+};
+
+template< typename T >
+class counter< T >::impl_inc :
+ public impl
+{
+private:
+ //! The counter
+ boost::detail::atomic_count m_Counter;
+
+public:
+ /*!
+ * Initializing constructor
+ */
+ explicit impl_inc(value_type initial) : m_Counter(initial - 1)
+ {
+ }
+
+ attribute_value get_value()
+ {
+ return make_attribute_value(static_cast< value_type >(++m_Counter));
+ }
+};
+
+template< typename T >
+class counter< T >::impl_dec :
+ public impl
+{
+private:
+ //! The counter
+ boost::detail::atomic_count m_Counter;
+
+public:
+ /*!
+ * Initializing constructor
+ */
+ explicit impl_dec(value_type initial) : m_Counter(initial + 1)
+ {
+ }
+
+ attribute_value get_value()
+ {
+ return make_attribute_value(static_cast< value_type >(--m_Counter));
+ }
+};
+
+#else // BOOST_LOG_NO_THREADS
+
+template< typename T >
+class counter< T >::impl_generic :
+ public impl
+{
+private:
+ //! Step value
+ const long m_Step;
+ //! The counter
+ value_type m_Counter;
+
+public:
+ /*!
+ * Initializing constructor
+ */
+ impl_generic(value_type initial, long step) : m_Step(step), m_Counter(initial - step)
+ {
+ }
+
+ attribute_value get_value()
+ {
+ m_Counter += m_Step;
+ return make_attribute_value(m_Counter);
+ }
+};
+
+#endif // BOOST_LOG_NO_THREADS
+
+} // namespace attributes
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTRIBUTES_COUNTER_HPP_INCLUDED_
diff --git a/boost/log/attributes/current_process_id.hpp b/boost/log/attributes/current_process_id.hpp
new file mode 100644
index 0000000000..d528b7d8f4
--- /dev/null
+++ b/boost/log/attributes/current_process_id.hpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file current_process_id.hpp
+ * \author Andrey Semashev
+ * \date 12.09.2009
+ *
+ * The header contains implementation of a current process id attribute
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTES_CURRENT_PROCESS_ID_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTES_CURRENT_PROCESS_ID_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/process_id.hpp>
+#include <boost/log/attributes/constant.hpp>
+#include <boost/log/attributes/attribute_cast.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+//! Process identifier type used by the library
+typedef boost::log::aux::process::id process_id;
+
+namespace attributes {
+
+/*!
+ * \brief A class of an attribute that holds the current process identifier
+ */
+class current_process_id :
+ public constant< process_id >
+{
+ typedef constant< process_id > base_type;
+
+public:
+ /*!
+ * Constructor. Initializes the attribute with the current process identifier.
+ */
+ current_process_id() : base_type(boost::log::aux::this_process::get_id()) {}
+ /*!
+ * Constructor for casting support
+ */
+ explicit current_process_id(cast_source const& source) :
+ base_type(source)
+ {
+ }
+};
+
+} // namespace attributes
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTRIBUTES_CURRENT_PROCESS_ID_HPP_INCLUDED_
diff --git a/boost/log/attributes/current_process_name.hpp b/boost/log/attributes/current_process_name.hpp
new file mode 100644
index 0000000000..92e78592ba
--- /dev/null
+++ b/boost/log/attributes/current_process_name.hpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file current_process_name.hpp
+ * \author Andrey Semashev
+ * \date 29.07.2012
+ *
+ * The header contains implementation of a current process name attribute
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTES_CURRENT_PROCESS_NAME_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTES_CURRENT_PROCESS_NAME_HPP_INCLUDED_
+
+#include <string>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/attributes/constant.hpp>
+#include <boost/log/attributes/attribute_cast.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! The function returns the current process name
+BOOST_LOG_API std::string get_process_name();
+
+} // namespace aux
+
+namespace attributes {
+
+/*!
+ * \brief A class of an attribute that holds the current process name
+ */
+class current_process_name :
+ public constant< std::string >
+{
+ typedef constant< std::string > base_type;
+
+public:
+ /*!
+ * Constructor. Initializes the attribute with the current process name.
+ */
+ current_process_name() : base_type(boost::log::aux::get_process_name()) {}
+ /*!
+ * Constructor for casting support
+ */
+ explicit current_process_name(cast_source const& source) :
+ base_type(source)
+ {
+ }
+};
+
+} // namespace attributes
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTRIBUTES_CURRENT_PROCESS_NAME_HPP_INCLUDED_
diff --git a/boost/log/attributes/current_thread_id.hpp b/boost/log/attributes/current_thread_id.hpp
new file mode 100644
index 0000000000..6b8488f5f5
--- /dev/null
+++ b/boost/log/attributes/current_thread_id.hpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file current_thread_id.hpp
+ * \author Andrey Semashev
+ * \date 12.09.2009
+ *
+ * The header contains implementation of a current thread id attribute
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTES_CURRENT_THREAD_ID_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTES_CURRENT_THREAD_ID_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(BOOST_LOG_NO_THREADS)
+#error Boost.Log: The current_thread_id attribute is only available in multithreaded builds
+#endif
+
+#include <boost/smart_ptr/intrusive_ptr.hpp>
+#include <boost/log/detail/thread_id.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/attributes/attribute_cast.hpp>
+#include <boost/log/attributes/attribute_value_impl.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+//! Thread identifier type
+typedef boost::log::aux::thread::id thread_id;
+
+namespace attributes {
+
+/*!
+ * \brief A class of an attribute that always returns the current thread identifier
+ *
+ * \note This attribute can be registered globally, it will still return the correct
+ * thread identifier, no matter which thread emits the log record.
+ */
+class current_thread_id :
+ public attribute
+{
+public:
+ //! A held attribute value type
+ typedef thread_id value_type;
+
+protected:
+ //! Factory implementation
+ class BOOST_SYMBOL_VISIBLE impl :
+ public attribute_value::impl
+ {
+ public:
+ bool dispatch(type_dispatcher& dispatcher)
+ {
+ type_dispatcher::callback< value_type > callback =
+ dispatcher.get_callback< value_type >();
+ if (callback)
+ {
+ callback(boost::log::aux::this_thread::get_id());
+ return true;
+ }
+ else
+ return false;
+ }
+
+ intrusive_ptr< attribute_value::impl > detach_from_thread()
+ {
+ typedef attribute_value_impl< value_type > detached_value;
+ return new detached_value(boost::log::aux::this_thread::get_id());
+ }
+
+ type_info_wrapper get_type() const { return type_info_wrapper(typeid(value_type)); }
+ };
+
+public:
+ /*!
+ * Default constructor
+ */
+ current_thread_id() : attribute(new impl())
+ {
+ }
+ /*!
+ * Constructor for casting support
+ */
+ explicit current_thread_id(cast_source const& source) :
+ attribute(source.as< impl >())
+ {
+ }
+};
+
+} // namespace attributes
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTRIBUTES_CURRENT_THREAD_ID_HPP_INCLUDED_
diff --git a/boost/log/attributes/fallback_policy.hpp b/boost/log/attributes/fallback_policy.hpp
new file mode 100644
index 0000000000..8a3c648001
--- /dev/null
+++ b/boost/log/attributes/fallback_policy.hpp
@@ -0,0 +1,186 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file fallback_policy.hpp
+ * \author Andrey Semashev
+ * \date 18.08.2012
+ *
+ * The header contains definition of fallback policies when attribute value visitation or extraction fails.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTES_FALLBACK_POLICY_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTES_FALLBACK_POLICY_HPP_INCLUDED_
+
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/exceptions.hpp>
+#include <boost/log/utility/type_info_wrapper.hpp>
+#include <boost/log/attributes/fallback_policy_fwd.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * The \c fallback_to_none policy results in returning an empty value reference if the attribute value cannot be extracted.
+ */
+struct fallback_to_none
+{
+ enum { guaranteed_result = false };
+
+ /*!
+ * The method is called in order to apply a function object to the default value.
+ */
+ template< typename FunT >
+ static bool apply_default(FunT&)
+ {
+ return false;
+ }
+
+ /*!
+ * The method is called in order to apply a function object to the default value.
+ */
+ template< typename FunT >
+ static bool apply_default(FunT const&)
+ {
+ return false;
+ }
+
+ /*!
+ * The method is called when value extraction failed because the attribute value has different type than requested.
+ */
+ static void on_invalid_type(type_info_wrapper const&)
+ {
+ }
+
+ /*!
+ * The method is called when value extraction failed because the attribute value was not found.
+ */
+ static void on_missing_value()
+ {
+ }
+};
+
+/*!
+ * The \c fallback_to_throw policy results in throwing an exception if the attribute value cannot be extracted.
+ */
+struct fallback_to_throw
+{
+ enum { guaranteed_result = true };
+
+ /*!
+ * The method is called in order to apply a function object to the default value.
+ */
+ template< typename FunT >
+ static bool apply_default(FunT&)
+ {
+ return false;
+ }
+
+ /*!
+ * The method is called in order to apply a function object to the default value.
+ */
+ template< typename FunT >
+ static bool apply_default(FunT const&)
+ {
+ return false;
+ }
+
+ /*!
+ * The method is called when value extraction failed because the attribute value has different type than requested.
+ */
+ static void on_invalid_type(type_info_wrapper const& t)
+ {
+ BOOST_LOG_THROW_DESCR_PARAMS(invalid_type, "Attribute value has incompatible type", (t));
+ }
+
+ /*!
+ * The method is called when value extraction failed because the attribute value was not found.
+ */
+ static void on_missing_value()
+ {
+ BOOST_LOG_THROW_DESCR(missing_value, "Attribute value not found");
+ }
+};
+
+/*!
+ * The \c fallback_to_default policy results in a default value if the attribute value cannot be extracted.
+ */
+template< typename DefaultT >
+struct fallback_to_default
+{
+ enum { guaranteed_result = true };
+
+ //! Default value type
+ typedef typename remove_cv< typename remove_reference< DefaultT >::type >::type default_type;
+
+ /*!
+ * Default constructor.
+ */
+ fallback_to_default() : m_default()
+ {
+ }
+
+ /*!
+ * Initializing constructor.
+ */
+ explicit fallback_to_default(default_type const& def_val) : m_default(def_val)
+ {
+ }
+
+ /*!
+ * The method is called in order to apply a function object to the default value.
+ */
+ template< typename FunT >
+ bool apply_default(FunT& fun) const
+ {
+ fun(m_default);
+ return true;
+ }
+
+ /*!
+ * The method is called in order to apply a function object to the default value.
+ */
+ template< typename FunT >
+ bool apply_default(FunT const& fun) const
+ {
+ fun(m_default);
+ return true;
+ }
+
+ /*!
+ * The method is called when value extraction failed because the attribute value has different type than requested.
+ */
+ static void on_invalid_type(type_info_wrapper const&)
+ {
+ }
+
+ /*!
+ * The method is called when value extraction failed because the attribute value was not found.
+ */
+ static void on_missing_value()
+ {
+ }
+
+private:
+ //! Default value
+ DefaultT m_default;
+};
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTRIBUTES_FALLBACK_POLICY_HPP_INCLUDED_
diff --git a/boost/log/attributes/fallback_policy_fwd.hpp b/boost/log/attributes/fallback_policy_fwd.hpp
new file mode 100644
index 0000000000..b6b01e3f4f
--- /dev/null
+++ b/boost/log/attributes/fallback_policy_fwd.hpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file fallback_policy_fwd.hpp
+ * \author Andrey Semashev
+ * \date 18.08.2012
+ *
+ * The header contains forward declaration of fallback policies when attribute value visitation or extraction fails.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTES_FALLBACK_POLICY_FWD_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTES_FALLBACK_POLICY_FWD_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * The \c fallback_to_none policy results in returning an empty value reference if the attribute value cannot be extracted.
+ */
+struct fallback_to_none;
+
+/*!
+ * The \c fallback_to_throw policy results in throwing an exception if the attribute value cannot be extracted.
+ */
+struct fallback_to_throw;
+
+/*!
+ * The \c fallback_to_default policy results in a default value if the attribute value cannot be extracted.
+ */
+template< typename DefaultT >
+struct fallback_to_default;
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_ATTRIBUTES_FALLBACK_POLICY_FWD_HPP_INCLUDED_
diff --git a/boost/log/attributes/function.hpp b/boost/log/attributes/function.hpp
new file mode 100644
index 0000000000..4333e321ce
--- /dev/null
+++ b/boost/log/attributes/function.hpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file function.hpp
+ * \author Andrey Semashev
+ * \date 24.06.2007
+ *
+ * The header contains implementation of an attribute that calls a third-party function on value acquisition.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTES_FUNCTION_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTES_FUNCTION_HPP_INCLUDED_
+
+#include <boost/static_assert.hpp>
+#include <boost/utility/result_of.hpp>
+#include <boost/type_traits/is_void.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/attributes/attribute_cast.hpp>
+#include <boost/log/attributes/attribute_value_impl.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace attributes {
+
+/*!
+ * \brief A class of an attribute that acquires its value from a third-party function object
+ *
+ * The attribute calls a stored nullary function object to acquire each value.
+ * The result type of the function object is the attribute value type.
+ *
+ * It is not recommended to use this class directly. Use \c make_function convenience functions
+ * to construct the attribute instead.
+ */
+template< typename R >
+class function :
+ public attribute
+{
+ BOOST_STATIC_ASSERT_MSG(!is_void< R >::value, "Boost.Log: Function object return type must not be void");
+
+public:
+ //! The attribute value type
+ typedef R value_type;
+
+protected:
+ //! Base class for factory implementation
+ class BOOST_LOG_NO_VTABLE BOOST_SYMBOL_VISIBLE impl :
+ public attribute::impl
+ {
+ };
+
+ //! Factory implementation
+ template< typename T >
+ class impl_template :
+ public impl
+ {
+ private:
+ //! Functor that returns attribute values
+ /*!
+ * \note The constness signifies that the function object should avoid
+ * modifying its state since it's not protected against concurrent calls.
+ */
+ const T m_Functor;
+
+ public:
+ /*!
+ * Constructor with the stored delegate initialization
+ */
+ explicit impl_template(T const& fun) : m_Functor(fun) {}
+
+ attribute_value get_value()
+ {
+ return attributes::make_attribute_value(m_Functor());
+ }
+ };
+
+public:
+ /*!
+ * Initializing constructor
+ */
+ template< typename T >
+ explicit function(T const& fun) : attribute(new impl_template< T >(fun))
+ {
+ }
+ /*!
+ * Constructor for casting support
+ */
+ explicit function(cast_source const& source) :
+ attribute(source.as< impl >())
+ {
+ }
+};
+
+#ifndef BOOST_NO_RESULT_OF
+
+/*!
+ * The function constructs \c function attribute instance with the provided function object.
+ *
+ * \param fun Nullary functional object that returns an actual stored value for an attribute value.
+ * \return Pointer to the attribute instance
+ */
+template< typename T >
+inline function<
+ typename remove_cv<
+ typename remove_reference<
+ typename boost::result_of< T() >::type
+ >::type
+ >::type
+> make_function(T const& fun)
+{
+ typedef typename remove_cv<
+ typename remove_reference<
+ typename boost::result_of< T() >::type
+ >::type
+ >::type result_type;
+
+ typedef function< result_type > function_type;
+ return function_type(fun);
+}
+
+#endif // BOOST_NO_RESULT_OF
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * The function constructs \c function attribute instance with the provided function object.
+ * Use this version if your compiler fails to determine the result type of the function object.
+ *
+ * \param fun Nullary functional object that returns an actual stored value for an attribute value.
+ * \return Pointer to the attribute instance
+ */
+template< typename R, typename T >
+inline function<
+ typename remove_cv<
+ typename remove_reference< R >::type
+ >::type
+> make_function(T const& fun)
+{
+ typedef typename remove_cv<
+ typename remove_reference< R >::type
+ >::type result_type;
+
+ typedef function< result_type > function_type;
+ return function_type(fun);
+}
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+} // namespace attributes
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTRIBUTES_FUNCTOR_HPP_INCLUDED_
diff --git a/boost/log/attributes/mutable_constant.hpp b/boost/log/attributes/mutable_constant.hpp
new file mode 100644
index 0000000000..a668256f6a
--- /dev/null
+++ b/boost/log/attributes/mutable_constant.hpp
@@ -0,0 +1,332 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file mutable_constant.hpp
+ * \author Andrey Semashev
+ * \date 06.11.2007
+ *
+ * The header contains implementation of a mutable constant attribute.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTES_MUTABLE_CONSTANT_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTES_MUTABLE_CONSTANT_HPP_INCLUDED_
+
+#include <boost/static_assert.hpp>
+#include <boost/smart_ptr/intrusive_ptr.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/type_traits/is_void.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/locks.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/attributes/attribute_cast.hpp>
+#include <boost/log/attributes/attribute_value_impl.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace attributes {
+
+/*!
+ * \brief A class of an attribute that holds a single constant value with ability to change it
+ *
+ * The mutable_constant attribute stores a single value of type, specified as the first template argument.
+ * This value is returned on each attribute value acquisition.
+ *
+ * The attribute also allows to modify the stored value, even if the attribute is registered in an attribute set.
+ * In order to ensure thread safety of such modifications the \c mutable_constant class is also parametrized
+ * with three additional template arguments: mutex type, scoped write and scoped read lock types. If not specified,
+ * the lock types are automatically deduced based on the mutex type.
+ *
+ * The implementation may avoid using these types to actually create and use the mutex, if a more efficient synchronization method is
+ * available (such as atomic operations on the value type). By default no synchronization is done.
+ */
+#ifdef BOOST_LOG_DOXYGEN_PASS
+template< typename T, typename MutexT = void, typename ScopedWriteLockT = auto, typename ScopedReadLockT = auto >
+#else // BOOST_LOG_DOXYGEN_PASS
+template<
+ typename T,
+ typename MutexT = void,
+ typename ScopedWriteLockT =
+#ifndef BOOST_LOG_NO_THREADS
+ typename mpl::if_c<
+ boost::log::aux::is_exclusively_lockable< MutexT >::value,
+ boost::log::aux::exclusive_lock_guard< MutexT >,
+ void
+ >::type,
+#else
+ void,
+#endif // BOOST_LOG_NO_THREADS
+ typename ScopedReadLockT =
+#ifndef BOOST_LOG_NO_THREADS
+ typename mpl::if_c<
+ boost::log::aux::is_shared_lockable< MutexT >::value,
+ boost::log::aux::shared_lock_guard< MutexT >,
+ ScopedWriteLockT
+ >::type
+#else
+ ScopedWriteLockT
+#endif // BOOST_LOG_NO_THREADS
+#endif // BOOST_LOG_DOXYGEN_PASS
+>
+class mutable_constant :
+ public attribute
+{
+public:
+ //! The attribute value type
+ typedef T value_type;
+
+protected:
+ //! Factory implementation
+ class BOOST_SYMBOL_VISIBLE impl :
+ public attribute::impl
+ {
+ private:
+ //! Mutex type
+ typedef MutexT mutex_type;
+ //! Shared lock type
+ typedef ScopedReadLockT scoped_read_lock;
+ //! Exclusive lock type
+ typedef ScopedWriteLockT scoped_write_lock;
+ BOOST_STATIC_ASSERT_MSG(!(is_void< mutex_type >::value || is_void< scoped_read_lock >::value || is_void< scoped_write_lock >::value), "Boost.Log: Mutex and both lock types either must not be void or must all be void");
+ //! Attribute value wrapper
+ typedef attribute_value_impl< value_type > attr_value;
+
+ private:
+ //! Thread protection mutex
+ mutable mutex_type m_Mutex;
+ //! Pointer to the actual attribute value
+ intrusive_ptr< attr_value > m_Value;
+
+ public:
+ /*!
+ * Initializing constructor
+ */
+ explicit impl(value_type const& value) : m_Value(new attr_value(value))
+ {
+ }
+ /*!
+ * Initializing constructor
+ */
+ explicit impl(BOOST_RV_REF(value_type) value) : m_Value(new attr_value(boost::move(value)))
+ {
+ }
+
+ attribute_value get_value()
+ {
+ scoped_read_lock lock(m_Mutex);
+ return attribute_value(m_Value);
+ }
+
+ void set(value_type const& value)
+ {
+ intrusive_ptr< attr_value > p = new attr_value(value);
+ scoped_write_lock lock(m_Mutex);
+ m_Value.swap(p);
+ }
+
+ void set(BOOST_RV_REF(value_type) value)
+ {
+ intrusive_ptr< attr_value > p = new attr_value(boost::move(value));
+ scoped_write_lock lock(m_Mutex);
+ m_Value.swap(p);
+ }
+
+ value_type get() const
+ {
+ scoped_read_lock lock(m_Mutex);
+ return m_Value->get();
+ }
+ };
+
+public:
+ /*!
+ * Constructor with the stored value initialization
+ */
+ explicit mutable_constant(value_type const& value) : attribute(new impl(value))
+ {
+ }
+ /*!
+ * Constructor with the stored value initialization
+ */
+ explicit mutable_constant(BOOST_RV_REF(value_type) value) : attribute(new impl(boost::move(value)))
+ {
+ }
+ /*!
+ * Constructor for casting support
+ */
+ explicit mutable_constant(cast_source const& source) : attribute(source.as< impl >())
+ {
+ }
+
+ /*!
+ * The method sets a new attribute value. The implementation exclusively locks the mutex in order
+ * to protect the value assignment.
+ */
+ void set(value_type const& value)
+ {
+ get_impl()->set(value);
+ }
+
+ /*!
+ * The method sets a new attribute value.
+ */
+ void set(BOOST_RV_REF(value_type) value)
+ {
+ get_impl()->set(boost::move(value));
+ }
+
+ /*!
+ * The method acquires the current attribute value. The implementation non-exclusively locks the mutex in order
+ * to protect the value acquisition.
+ */
+ value_type get() const
+ {
+ return get_impl()->get();
+ }
+
+protected:
+ /*!
+ * \returns Pointer to the factory implementation
+ */
+ impl* get_impl() const
+ {
+ return static_cast< impl* >(attribute::get_impl());
+ }
+};
+
+
+/*!
+ * \brief Specialization for unlocked case
+ *
+ * This version of attribute does not perform thread synchronization to access the stored value.
+ */
+template< typename T >
+class mutable_constant< T, void, void, void > :
+ public attribute
+{
+public:
+ //! The attribute value type
+ typedef T value_type;
+
+protected:
+ //! Factory implementation
+ class BOOST_SYMBOL_VISIBLE impl :
+ public attribute::impl
+ {
+ private:
+ //! Attribute value wrapper
+ typedef attribute_value_impl< value_type > attr_value;
+
+ private:
+ //! The actual value
+ intrusive_ptr< attr_value > m_Value;
+
+ public:
+ /*!
+ * Initializing constructor
+ */
+ explicit impl(value_type const& value) : m_Value(new attr_value(value))
+ {
+ }
+ /*!
+ * Initializing constructor
+ */
+ explicit impl(BOOST_RV_REF(value_type) value) : m_Value(new attr_value(boost::move(value)))
+ {
+ }
+
+ attribute_value get_value()
+ {
+ return attribute_value(m_Value);
+ }
+
+ void set(value_type const& value)
+ {
+ m_Value = new attr_value(value);
+ }
+ void set(BOOST_RV_REF(value_type) value)
+ {
+ m_Value = new attr_value(boost::move(value));
+ }
+
+ value_type get() const
+ {
+ return m_Value->get();
+ }
+ };
+
+public:
+ /*!
+ * Constructor with the stored value initialization
+ */
+ explicit mutable_constant(value_type const& value) : attribute(new impl(value))
+ {
+ }
+ /*!
+ * Constructor with the stored value initialization
+ */
+ explicit mutable_constant(BOOST_RV_REF(value_type) value) : attribute(new impl(boost::move(value)))
+ {
+ }
+ /*!
+ * Constructor for casting support
+ */
+ explicit mutable_constant(cast_source const& source) : attribute(source.as< impl >())
+ {
+ }
+
+ /*!
+ * The method sets a new attribute value.
+ */
+ void set(value_type const& value)
+ {
+ get_impl()->set(value);
+ }
+
+ /*!
+ * The method sets a new attribute value.
+ */
+ void set(BOOST_RV_REF(value_type) value)
+ {
+ get_impl()->set(boost::move(value));
+ }
+
+ /*!
+ * The method acquires the current attribute value.
+ */
+ value_type get() const
+ {
+ return get_impl()->get();
+ }
+
+protected:
+ /*!
+ * \returns Pointer to the factory implementation
+ */
+ impl* get_impl() const
+ {
+ return static_cast< impl* >(attribute::get_impl());
+ }
+};
+
+} // namespace attributes
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTRIBUTES_MUTABLE_CONSTANT_HPP_INCLUDED_
diff --git a/boost/log/attributes/named_scope.hpp b/boost/log/attributes/named_scope.hpp
new file mode 100644
index 0000000000..7b75c3d73c
--- /dev/null
+++ b/boost/log/attributes/named_scope.hpp
@@ -0,0 +1,474 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file
+ * \author Andrey Semashev
+ * \date 24.06.2007
+ *
+ * The header contains implementation of named scope container and an attribute that allows to
+ * put the named scope to log. A number of convenience macros are also provided.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTES_NAMED_SCOPE_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTES_NAMED_SCOPE_HPP_INCLUDED_
+
+#include <ostream>
+#include <memory>
+#include <iterator>
+#include <cstddef>
+#include <boost/log/detail/config.hpp>
+#include <boost/current_function.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/log/utility/string_literal.hpp>
+#include <boost/log/utility/unique_identifier_name.hpp>
+#include <boost/log/utility/unused_variable.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/attributes/attribute_cast.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace attributes {
+
+namespace aux {
+
+ //! Double-linked list node
+ struct named_scope_list_node
+ {
+ mutable named_scope_list_node* _m_pPrev;
+ mutable named_scope_list_node* _m_pNext;
+
+ named_scope_list_node() BOOST_NOEXCEPT { _m_pPrev = _m_pNext = this; }
+ };
+
+} // namespace aux
+
+/*!
+ * \brief The structure contains all information about a named scope
+ *
+ * The named scope entries are stored as elements of \c basic_named_scope_list container, which
+ * in turn can be acquired either from the \c basic_named_scope attribute value or from a thread-local
+ * instance.
+ */
+struct named_scope_entry
+ //! \cond
+ : public aux::named_scope_list_node
+ //! \endcond
+{
+ /*!
+ * \brief Scope entry type
+ *
+ * Describes scope name specifics
+ */
+ enum scope_name_type
+ {
+ general, //!< The scope name contains some unstructured string that should not be interpreted by the library
+ function //!< The scope name contains a function signature
+ };
+
+ /*!
+ * The scope name (e.g. a function signature)
+ */
+ string_literal scope_name;
+ /*!
+ * The source file name
+ */
+ string_literal file_name;
+ /*!
+ * The line number in the source file
+ */
+ unsigned int line;
+ /*!
+ * The scope name type
+ */
+ scope_name_type type;
+
+ /*!
+ * Initializing constructor
+ *
+ * \post <tt>scope_name == sn && file_name == fn && line == ln</tt>
+ *
+ * \b Throws: Nothing.
+ */
+ named_scope_entry(string_literal const& sn, string_literal const& fn, unsigned int ln, scope_name_type t = general) BOOST_NOEXCEPT :
+ scope_name(sn),
+ file_name(fn),
+ line(ln),
+ type(t)
+ {
+ }
+};
+
+/*!
+ * \brief The class implements the list of scopes
+ *
+ * The scope list provides a read-only access to a doubly-linked list of scopes.
+ */
+class named_scope_list
+ //! \cond
+ : protected std::allocator< named_scope_entry >
+ //! \endcond
+{
+public:
+ //! Allocator type
+ typedef std::allocator< named_scope_entry > allocator_type;
+
+ // Standard types
+ typedef allocator_type::value_type value_type;
+ typedef allocator_type::reference reference;
+ typedef allocator_type::const_reference const_reference;
+ typedef allocator_type::pointer pointer;
+ typedef allocator_type::const_pointer const_pointer;
+ typedef allocator_type::size_type size_type;
+ typedef allocator_type::difference_type difference_type;
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+protected:
+ //! Iterator class
+#ifndef BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS
+ template< bool fConstV > class iter;
+ template< bool fConstV > friend class iter;
+#endif
+ template< bool fConstV >
+ class iter
+ {
+ friend class iter< !fConstV >;
+
+ public:
+ // Standard typedefs
+ typedef named_scope_list::difference_type difference_type;
+ typedef named_scope_list::value_type value_type;
+ typedef typename mpl::if_c<
+ fConstV,
+ named_scope_list::const_reference,
+ named_scope_list::reference
+ >::type reference;
+ typedef typename mpl::if_c<
+ fConstV,
+ named_scope_list::const_pointer,
+ named_scope_list::pointer
+ >::type pointer;
+ typedef std::bidirectional_iterator_tag iterator_category;
+
+ public:
+ // Constructors
+ iter() : m_pNode(NULL) {}
+ explicit iter(aux::named_scope_list_node* pNode) : m_pNode(pNode) {}
+ iter(iter< false > const& that) : m_pNode(that.m_pNode) {}
+
+ //! Assignment
+ template< bool f >
+ iter& operator= (iter< f > const& that)
+ {
+ m_pNode = that.m_pNode;
+ return *this;
+ }
+
+ // Comparison
+ template< bool f >
+ bool operator== (iter< f > const& that) const { return (m_pNode == that.m_pNode); }
+ template< bool f >
+ bool operator!= (iter< f > const& that) const { return (m_pNode != that.m_pNode); }
+
+ // Modification
+ iter& operator++ ()
+ {
+ m_pNode = m_pNode->_m_pNext;
+ return *this;
+ }
+ iter& operator-- ()
+ {
+ m_pNode = m_pNode->_m_pPrev;
+ return *this;
+ }
+ iter operator++ (int)
+ {
+ iter tmp(*this);
+ m_pNode = m_pNode->_m_pNext;
+ return tmp;
+ }
+ iter operator-- (int)
+ {
+ iter tmp(*this);
+ m_pNode = m_pNode->_m_pPrev;
+ return tmp;
+ }
+
+ // Dereferencing
+ pointer operator-> () const { return static_cast< pointer >(m_pNode); }
+ reference operator* () const { return *static_cast< pointer >(m_pNode); }
+
+ private:
+ aux::named_scope_list_node* m_pNode;
+ };
+
+public:
+ typedef iter< true > const_iterator;
+ typedef iter< false > iterator;
+ typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
+ typedef std::reverse_iterator< iterator > reverse_iterator;
+
+protected:
+ //! The root node of the container
+ aux::named_scope_list_node m_RootNode;
+ //! The size of the container
+ size_type m_Size;
+ //! The flag shows if the contained elements are dynamically allocated
+ bool m_fNeedToDeallocate;
+
+#else // BOOST_LOG_DOXYGEN_PASS
+
+ /*!
+ * A constant iterator to the sequence of scopes. Complies to bidirectional iterator requirements.
+ */
+ typedef implementation_defined const_iterator;
+ /*!
+ * An iterator to the sequence of scopes. Complies to bidirectional iterator requirements.
+ */
+ typedef implementation_defined iterator;
+ /*!
+ * A constant reverse iterator to the sequence of scopes. Complies to bidirectional iterator requirements.
+ */
+ typedef implementation_defined const_reverse_iterator;
+ /*!
+ * A reverse iterator to the sequence of scopes. Complies to bidirectional iterator requirements.
+ */
+ typedef implementation_defined reverse_iterator;
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+public:
+ /*!
+ * Default constructor
+ *
+ * \post <tt>empty() == true</tt>
+ */
+ named_scope_list() : m_Size(0), m_fNeedToDeallocate(false) {}
+ /*!
+ * Copy constructor
+ *
+ * \post <tt>std::equal(begin(), end(), that.begin()) == true</tt>
+ */
+ BOOST_LOG_API named_scope_list(named_scope_list const& that);
+ /*!
+ * Destructor. Destroys the stored entries.
+ */
+ BOOST_LOG_API ~named_scope_list();
+
+ /*!
+ * Assignment operator
+ *
+ * \post <tt>std::equal(begin(), end(), that.begin()) == true</tt>
+ */
+ named_scope_list& operator= (named_scope_list const& that)
+ {
+ if (this != &that)
+ {
+ named_scope_list tmp(that);
+ swap(tmp);
+ }
+ return *this;
+ }
+
+ /*!
+ * \return Constant iterator to the first element of the container.
+ */
+ const_iterator begin() const { return const_iterator(m_RootNode._m_pNext); }
+ /*!
+ * \return Constant iterator to the after-the-last element of the container.
+ */
+ const_iterator end() const { return const_iterator(const_cast< aux::named_scope_list_node* >(&m_RootNode)); }
+ /*!
+ * \return Constant iterator to the last element of the container.
+ */
+ const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
+ /*!
+ * \return Constant iterator to the before-the-first element of the container.
+ */
+ const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
+
+ /*!
+ * \return The number of elements in the container
+ */
+ size_type size() const { return m_Size; }
+ /*!
+ * \return true if the container is empty and false otherwise
+ */
+ bool empty() const { return (m_Size == 0); }
+
+ /*!
+ * Swaps two instances of the container
+ */
+ BOOST_LOG_API void swap(named_scope_list& that);
+
+ /*!
+ * \return Last pushed scope entry
+ */
+ const_reference back() const { return *rbegin(); }
+ /*!
+ * \return First pushed scope entry
+ */
+ const_reference front() const { return *begin(); }
+};
+
+//! Stream output operator
+template< typename CharT, typename TraitsT >
+inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, named_scope_list const& sl)
+{
+ if (strm.good())
+ {
+ named_scope_list::const_iterator it = sl.begin(), end = sl.end();
+ if (it != end)
+ {
+ strm << it->scope_name.c_str();
+ for (++it; it != end; ++it)
+ strm << "->" << it->scope_name.c_str();
+ }
+ }
+ return strm;
+}
+
+/*!
+ * \brief A class of an attribute that holds stack of named scopes of the current thread
+ *
+ * The basic_named_scope attribute is essentially a hook to the thread-specific instance of
+ * scope list. This means that the attribute will generate different values if get_value is
+ * called in different threads. The attribute generates value with stored type
+ * <tt>basic_named_scope_list< CharT ></tt>.
+ *
+ * The attribute class can also be used to gain access to the scope stack instance, e.g. to
+ * get its copy or to push or pop a scope entry. However, it is highly not recommended to
+ * maintain scope list manually. Use \c BOOST_LOG_NAMED_SCOPE or \c BOOST_LOG_FUNCTION macros instead.
+ */
+class BOOST_LOG_API named_scope :
+ public attribute
+{
+public:
+ //! Scope names stack (the attribute value type)
+ typedef named_scope_list value_type;
+ //! Scope entry
+ typedef value_type::value_type scope_entry;
+
+ //! Sentry object class to automatically push and pop scopes
+ struct sentry
+ {
+ /*!
+ * Constructor. Pushes the specified scope to the end of the thread-local list of scopes.
+ *
+ * \param sn Scope name.
+ * \param fn File name, in which the scope is located.
+ * \param ln Line number in the file.
+ */
+ sentry(string_literal const& sn, string_literal const& fn, unsigned int ln, scope_entry::scope_name_type t = scope_entry::general) BOOST_NOEXCEPT :
+ m_Entry(sn, fn, ln, t)
+ {
+ named_scope::push_scope(m_Entry);
+ }
+
+ /*!
+ * Destructor. Removes the last pushed scope from the thread-local list of scopes.
+ */
+ ~sentry() BOOST_NOEXCEPT
+ {
+ named_scope::pop_scope();
+ }
+
+ BOOST_DELETED_FUNCTION(sentry(sentry const&))
+ BOOST_DELETED_FUNCTION(sentry& operator= (sentry const&))
+
+ private:
+ scope_entry m_Entry;
+ };
+
+private:
+ //! Attribute implementation class
+ struct BOOST_SYMBOL_VISIBLE impl;
+
+public:
+ /*!
+ * Constructor. Creates an attribute.
+ */
+ named_scope();
+ /*!
+ * Constructor for casting support
+ */
+ explicit named_scope(cast_source const& source);
+
+ /*!
+ * The method pushes the scope to the back of the current thread's scope list
+ *
+ * \b Throws: Nothing.
+ */
+ static void push_scope(scope_entry const& entry) BOOST_NOEXCEPT;
+ /*!
+ * The method pops the last pushed scope from the current thread's scope list
+ *
+ * \b Throws: Nothing.
+ */
+ static void pop_scope() BOOST_NOEXCEPT;
+
+ /*!
+ * \return The current thread's list of scopes
+ *
+ * \note The returned reference is only valid until the current thread ends. The scopes in the
+ * returned container may change if the execution scope is changed (i.e. either \c push_scope
+ * or \c pop_scope is called). User has to copy the stack if he wants to keep it intact regardless
+ * of the execution scope.
+ */
+ static value_type const& get_scopes();
+};
+
+} // namespace attributes
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#define BOOST_LOG_NAMED_SCOPE_INTERNAL(var, name, file, line, type)\
+ BOOST_LOG_UNUSED_VARIABLE(::boost::log::attributes::named_scope::sentry, var, (name, file, line, type));
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * Macro for scope markup. The specified scope name is pushed to the end of the current thread scope list.
+ */
+#define BOOST_LOG_NAMED_SCOPE(name)\
+ BOOST_LOG_NAMED_SCOPE_INTERNAL(BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_named_scope_sentry_), name, __FILE__, __LINE__, ::boost::log::attributes::named_scope_entry::general)
+
+/*!
+ * Macro for function scope markup. The scope name is constructed with help of compiler and contains the current function signature.
+ * The scope name is pushed to the end of the current thread scope list.
+ *
+ * Not all compilers have support for this macro. The exact form of the scope name may vary from one compiler to another.
+ */
+#define BOOST_LOG_FUNCTION()\
+ BOOST_LOG_NAMED_SCOPE_INTERNAL(BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_named_scope_sentry_), BOOST_CURRENT_FUNCTION, __FILE__, __LINE__, ::boost::log::attributes::named_scope_entry::function)
+
+/*!
+ * Macro for function scope markup. The scope name is constructed with help of compiler and contains the current function name. It may be shorter than what \c BOOST_LOG_FUNCTION macro produces.
+ * The scope name is pushed to the end of the current thread scope list.
+ *
+ * Not all compilers have support for this macro. The exact form of the scope name may vary from one compiler to another.
+ */
+#if defined(_MSC_VER) || defined(__GNUC__)
+#define BOOST_LOG_FUNC() BOOST_LOG_NAMED_SCOPE(__FUNCTION__)
+#else
+#define BOOST_LOG_FUNC() BOOST_LOG_FUNCTION()
+#endif
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTRIBUTES_NAMED_SCOPE_HPP_INCLUDED_
diff --git a/boost/log/attributes/scoped_attribute.hpp b/boost/log/attributes/scoped_attribute.hpp
new file mode 100644
index 0000000000..33b1c395fe
--- /dev/null
+++ b/boost/log/attributes/scoped_attribute.hpp
@@ -0,0 +1,253 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file scoped_attribute.hpp
+ * \author Andrey Semashev
+ * \date 13.05.2007
+ *
+ * The header contains definition of facilities to define scoped attributes.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTES_SCOPED_ATTRIBUTE_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTES_SCOPED_ATTRIBUTE_HPP_INCLUDED_
+
+#include <utility>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/core/core.hpp>
+#include <boost/log/sources/basic_logger.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/attributes/attribute_set.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/constant.hpp>
+#include <boost/log/utility/unused_variable.hpp>
+#include <boost/log/utility/unique_identifier_name.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! A base class for all scoped attribute guards
+class attribute_scope_guard
+{
+};
+
+} // namespace aux
+
+//! Scoped attribute guard type
+typedef aux::attribute_scope_guard const& scoped_attribute;
+
+namespace aux {
+
+//! A scoped logger attribute guard
+template< typename LoggerT >
+class scoped_logger_attribute :
+ public attribute_scope_guard
+{
+ BOOST_COPYABLE_AND_MOVABLE_ALT(scoped_logger_attribute)
+
+private:
+ //! Logger type
+ typedef LoggerT logger_type;
+
+private:
+ //! A reference to the logger
+ logger_type* m_pLogger;
+ //! An iterator to the added attribute
+ attribute_set::iterator m_itAttribute;
+
+public:
+ //! Constructor
+ scoped_logger_attribute(logger_type& l, attribute_name const& name, attribute const& attr) :
+ m_pLogger(boost::addressof(l))
+ {
+ std::pair<
+ attribute_set::iterator,
+ bool
+ > res = l.add_attribute(name, attr);
+ if (res.second)
+ m_itAttribute = res.first;
+ else
+ m_pLogger = 0; // if there already is a same-named attribute, don't register anything
+ }
+ //! Move constructor
+ scoped_logger_attribute(BOOST_RV_REF(scoped_logger_attribute) that) :
+ m_pLogger(that.m_pLogger),
+ m_itAttribute(that.m_itAttribute)
+ {
+ that.m_pLogger = 0;
+ }
+
+ //! Destructor
+ ~scoped_logger_attribute()
+ {
+ if (m_pLogger)
+ m_pLogger->remove_attribute(m_itAttribute);
+ }
+
+#ifndef BOOST_LOG_BROKEN_REFERENCE_FROM_RVALUE_INIT
+ BOOST_DELETED_FUNCTION(scoped_logger_attribute(scoped_logger_attribute const&))
+#else // BOOST_LOG_BROKEN_REFERENCE_FROM_RVALUE_INIT
+ scoped_logger_attribute(scoped_logger_attribute const& that) : m_pLogger(that.m_pLogger), m_itAttribute(that.m_itAttribute)
+ {
+ const_cast< scoped_logger_attribute& >(that).m_pLogger = 0;
+ }
+#endif // BOOST_LOG_BROKEN_REFERENCE_FROM_RVALUE_INIT
+
+ BOOST_DELETED_FUNCTION(scoped_logger_attribute& operator= (scoped_logger_attribute const&))
+};
+
+} // namespace aux
+
+// Generator helper functions
+/*!
+ * Registers an attribute in the logger
+ *
+ * \param l Logger to register the attribute in
+ * \param name Attribute name
+ * \param attr The attribute. Must not be NULL.
+ * \return An unspecified guard object which may be used to initialize a \c scoped_attribute variable.
+ */
+template< typename LoggerT >
+BOOST_FORCEINLINE aux::scoped_logger_attribute< LoggerT > add_scoped_logger_attribute(LoggerT& l, attribute_name const& name, attribute const& attr)
+{
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ return aux::scoped_logger_attribute< LoggerT >(l, name, attr);
+#else
+ aux::scoped_logger_attribute< LoggerT > guard(l, name, attr);
+ return boost::move(guard);
+#endif
+}
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#define BOOST_LOG_SCOPED_LOGGER_ATTR_INTERNAL(logger, attr_name, attr, sentry_var_name)\
+ BOOST_LOG_UNUSED_VARIABLE(::boost::log::scoped_attribute, sentry_var_name,\
+ = ::boost::log::add_scoped_logger_attribute(logger, attr_name, (attr)));
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+//! The macro sets a scoped logger-wide attribute in a more compact way
+#define BOOST_LOG_SCOPED_LOGGER_ATTR(logger, attr_name, attr)\
+ BOOST_LOG_SCOPED_LOGGER_ATTR_INTERNAL(\
+ logger,\
+ attr_name,\
+ attr,\
+ BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_scoped_logger_attr_sentry_))
+
+//! The macro sets a scoped logger-wide tag in a more compact way
+#define BOOST_LOG_SCOPED_LOGGER_TAG(logger, attr_name, attr_value)\
+ BOOST_LOG_SCOPED_LOGGER_ATTR(logger, attr_name, ::boost::log::attributes::make_constant(attr_value))
+
+namespace aux {
+
+//! A scoped thread-specific attribute guard
+class scoped_thread_attribute :
+ public attribute_scope_guard
+{
+ BOOST_COPYABLE_AND_MOVABLE_ALT(scoped_thread_attribute)
+
+private:
+ //! A pointer to the logging core
+ core_ptr m_pCore;
+ //! An iterator to the added attribute
+ attribute_set::iterator m_itAttribute;
+
+public:
+ //! Constructor
+ scoped_thread_attribute(attribute_name const& name, attribute const& attr) :
+ m_pCore(core::get())
+ {
+ std::pair<
+ attribute_set::iterator,
+ bool
+ > res = m_pCore->add_thread_attribute(name, attr);
+ if (res.second)
+ m_itAttribute = res.first;
+ else
+ m_pCore.reset(); // if there already is a same-named attribute, don't register anything
+ }
+ //! Move constructor
+ scoped_thread_attribute(BOOST_RV_REF(scoped_thread_attribute) that) : m_itAttribute(that.m_itAttribute)
+ {
+ m_pCore.swap(that.m_pCore);
+ }
+
+ //! Destructor
+ ~scoped_thread_attribute()
+ {
+ if (!!m_pCore)
+ m_pCore->remove_thread_attribute(m_itAttribute);
+ }
+
+#ifndef BOOST_LOG_BROKEN_REFERENCE_FROM_RVALUE_INIT
+ BOOST_DELETED_FUNCTION(scoped_thread_attribute(scoped_thread_attribute const&))
+#else // BOOST_LOG_BROKEN_REFERENCE_FROM_RVALUE_INIT
+ scoped_thread_attribute(scoped_thread_attribute const& that) : m_itAttribute(that.m_itAttribute)
+ {
+ m_pCore.swap(const_cast< scoped_thread_attribute& >(that).m_pCore);
+ }
+#endif // BOOST_LOG_BROKEN_REFERENCE_FROM_RVALUE_INIT
+
+ BOOST_DELETED_FUNCTION(scoped_thread_attribute& operator= (scoped_thread_attribute const&))
+};
+
+} // namespace aux
+
+// Generator helper functions
+/*!
+ * Registers a thread-specific attribute
+ *
+ * \param name Attribute name
+ * \param attr The attribute. Must not be NULL.
+ * \return An unspecified guard object which may be used to initialize a \c scoped_attribute variable.
+ */
+BOOST_FORCEINLINE aux::scoped_thread_attribute add_scoped_thread_attribute(attribute_name const& name, attribute const& attr)
+{
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ return aux::scoped_thread_attribute(name, attr);
+#else
+ aux::scoped_thread_attribute guard(name, attr);
+ return boost::move(guard);
+#endif
+}
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#define BOOST_LOG_SCOPED_THREAD_ATTR_INTERNAL(attr_name, attr, sentry_var_name)\
+ BOOST_LOG_UNUSED_VARIABLE(::boost::log::scoped_attribute, sentry_var_name,\
+ = ::boost::log::add_scoped_thread_attribute(attr_name, (attr)));
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+//! The macro sets a scoped thread-wide attribute in a more compact way
+#define BOOST_LOG_SCOPED_THREAD_ATTR(attr_name, attr)\
+ BOOST_LOG_SCOPED_THREAD_ATTR_INTERNAL(\
+ attr_name,\
+ attr,\
+ BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_scoped_thread_attr_sentry_))
+
+//! The macro sets a scoped thread-wide tag in a more compact way
+#define BOOST_LOG_SCOPED_THREAD_TAG(attr_name, attr_value)\
+ BOOST_LOG_SCOPED_THREAD_ATTR(attr_name, ::boost::log::attributes::make_constant(attr_value))
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTRIBUTES_SCOPED_ATTRIBUTE_HPP_INCLUDED_
diff --git a/boost/log/attributes/time_traits.hpp b/boost/log/attributes/time_traits.hpp
new file mode 100644
index 0000000000..9a967f8cb8
--- /dev/null
+++ b/boost/log/attributes/time_traits.hpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file time_traits.hpp
+ * \author Andrey Semashev
+ * \date 01.12.2007
+ *
+ * The header contains implementation of time traits that are used in various parts of the
+ * library to acquire current time.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTES_TIME_TRAITS_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTES_TIME_TRAITS_HPP_INCLUDED_
+
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace attributes {
+
+//! Base class for time traits involving Boost.DateTime.
+struct basic_time_traits
+{
+ //! Time type
+ typedef posix_time::ptime time_type;
+
+ //! Current time source
+#if defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)
+ typedef posix_time::microsec_clock clock_source;
+#else
+ typedef posix_time::second_clock clock_source;
+#endif // defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)
+};
+
+//! Time traits that describes UTC time acquirement via Boost.DateTime facilities
+struct utc_time_traits :
+ public basic_time_traits
+{
+ /*!
+ * \return Current time stamp
+ */
+ static time_type get_clock()
+ {
+ return clock_source::universal_time();
+ }
+};
+
+//! Time traits that describes local time acquirement via Boost.DateTime facilities
+struct local_time_traits :
+ public basic_time_traits
+{
+ /*!
+ * \return Current time stamp
+ */
+ static time_type get_clock()
+ {
+ return clock_source::local_time();
+ }
+};
+
+} // namespace attributes
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTRIBUTES_TIME_TRAITS_HPP_INCLUDED_
diff --git a/boost/log/attributes/timer.hpp b/boost/log/attributes/timer.hpp
new file mode 100644
index 0000000000..ae7d65ebfd
--- /dev/null
+++ b/boost/log/attributes/timer.hpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file timer.hpp
+ * \author Andrey Semashev
+ * \date 02.12.2007
+ *
+ * The header contains implementation of a stop watch attribute.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTES_TIMER_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTES_TIMER_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/attributes/attribute_cast.hpp>
+#include <boost/log/attributes/time_traits.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace attributes {
+
+/*!
+ * \brief A class of an attribute that makes an attribute value of the time interval since construction
+ *
+ * The timer attribute calculates the time passed since its construction and returns it on value acquisition.
+ * The attribute value type is <tt>boost::posix_time::time_duration</tt>.
+ *
+ * On Windows platform there are two implementations of the attribute. The default one is more precise but
+ * a bit slower. This version uses <tt>QueryPerformanceFrequence</tt>/<tt>QueryPerformanceCounter</tt> API
+ * to calculate elapsed time.
+ *
+ * There are known problems with these functions when used with some CPUs, notably AMD Athlon with
+ * Cool'n'Quiet technology enabled. See the following links for more information and possible resolutions:
+ *
+ * http://support.microsoft.com/?scid=kb;en-us;895980
+ * http://support.microsoft.com/?id=896256
+ *
+ * In case if none of these solutions apply, you are free to define <tt>BOOST_LOG_NO_QUERY_PERFORMANCE_COUNTER</tt> macro to
+ * fall back to another implementation based on Boost.DateTime.
+ */
+class BOOST_LOG_API timer :
+ public attribute
+{
+public:
+ //! Attribute value type
+ typedef utc_time_traits::time_type::time_duration_type value_type;
+
+private:
+ //! Factory implementation
+ class BOOST_SYMBOL_VISIBLE impl;
+
+public:
+ /*!
+ * Constructor. Starts time counting.
+ */
+ timer();
+ /*!
+ * Constructor for casting support
+ */
+ explicit timer(cast_source const& source);
+};
+
+} // namespace attributes
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTRIBUTES_TIMER_HPP_INCLUDED_
diff --git a/boost/log/attributes/value_extraction.hpp b/boost/log/attributes/value_extraction.hpp
new file mode 100644
index 0000000000..84ee3ddf8d
--- /dev/null
+++ b/boost/log/attributes/value_extraction.hpp
@@ -0,0 +1,816 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file value_extraction.hpp
+ * \author Andrey Semashev
+ * \date 01.03.2008
+ *
+ * The header contains implementation of tools for extracting an attribute value
+ * from the view.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTES_VALUE_EXTRACTION_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTES_VALUE_EXTRACTION_HPP_INCLUDED_
+
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/joint_view.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/mpl/is_sequence.hpp>
+#include <boost/mpl/contains.hpp>
+#include <boost/mpl/push_back.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/exceptions.hpp>
+#include <boost/log/core/record.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/attribute_value.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include <boost/log/attributes/value_extraction_fwd.hpp>
+#include <boost/log/attributes/fallback_policy.hpp>
+#include <boost/log/expressions/keyword_fwd.hpp>
+#include <boost/log/utility/value_ref.hpp>
+#include <boost/log/utility/type_dispatch/static_type_dispatcher.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace result_of {
+
+/*!
+ * \brief A metafunction that allows to acquire the result of the value extraction
+ *
+ * The metafunction results in a type that is in form of <tt>T const&</tt>, if \c T is
+ * not an MPL type sequence and <tt>DefaultT</tt> is the same as <tt>T</tt>,
+ * or <tt>value_ref< TypesT, TagT ></tt> otherwise, with
+ * \c TypesT being a type sequence comprising the types from sequence \c T and \c DefaultT,
+ * if it is not present in \c T already.
+ */
+template< typename T, typename DefaultT, typename TagT >
+struct extract_or_default
+{
+ typedef typename mpl::eval_if<
+ mpl::is_sequence< T >,
+ mpl::eval_if<
+ mpl::contains< T, DefaultT >,
+ mpl::identity< T >,
+ mpl::push_back< T, DefaultT >
+ >,
+ mpl::if_<
+ is_same< T, DefaultT >,
+ T,
+ mpl::vector2< T, DefaultT >
+ >
+ >::type extracted_type;
+
+ typedef typename mpl::if_<
+ mpl::is_sequence< extracted_type >,
+ value_ref< extracted_type, TagT >,
+ extracted_type const&
+ >::type type;
+};
+
+/*!
+ * \brief A metafunction that allows to acquire the result of the value extraction
+ *
+ * The metafunction results in a type that is in form of <tt>T const&</tt>, if \c T is
+ * not an MPL type sequence, or <tt>value_ref< T, TagT ></tt> otherwise. In the latter
+ * case the value reference shall never be empty.
+ */
+template< typename T, typename TagT >
+struct extract_or_throw
+{
+ typedef typename mpl::if_<
+ mpl::is_sequence< T >,
+ value_ref< T, TagT >,
+ T const&
+ >::type type;
+};
+
+/*!
+ * \brief A metafunction that allows to acquire the result of the value extraction
+ *
+ * The metafunction results in a type that is in form of <tt>value_ref< T, TagT ></tt>.
+ */
+template< typename T, typename TagT >
+struct extract
+{
+ typedef value_ref< T, TagT > type;
+};
+
+} // namespace result_of
+
+namespace aux {
+
+//! The function object initializes the value reference
+template< typename RefT >
+struct value_ref_initializer
+{
+ typedef void result_type;
+
+ value_ref_initializer(RefT& ref) : m_ref(ref)
+ {
+ }
+
+ template< typename ArgT >
+ result_type operator() (ArgT const& arg) const
+ {
+ m_ref = RefT(arg);
+ }
+
+private:
+ RefT& m_ref;
+};
+
+//! The function unwraps \c value_ref, if possible
+template< typename T, typename TagT >
+BOOST_FORCEINLINE typename enable_if< mpl::is_sequence< T >, value_ref< T, TagT > >::type
+unwrap_value_ref(value_ref< T, TagT > const& r)
+{
+ return r;
+}
+
+template< typename T, typename TagT >
+BOOST_FORCEINLINE typename disable_if< mpl::is_sequence< T >, T const& >::type
+unwrap_value_ref(value_ref< T, TagT > const& r)
+{
+ return r.get();
+}
+
+} // namespace aux
+
+/*!
+ * \brief Generic attribute value extractor
+ *
+ * Attribute value extractor is a functional object that attempts to find and extract the stored
+ * attribute value from the attribute values view or a log record. The extracted value is returned
+ * from the extractor.
+ */
+template< typename T, typename FallbackPolicyT, typename TagT >
+class value_extractor :
+ private FallbackPolicyT
+{
+public:
+ //! Fallback policy
+ typedef FallbackPolicyT fallback_policy;
+ //! Attribute value types
+ typedef T value_type;
+ //! Function object result type
+ typedef value_ref< value_type, TagT > result_type;
+
+public:
+ /*!
+ * Default constructor
+ */
+ BOOST_DEFAULTED_FUNCTION(value_extractor(), {})
+
+ /*!
+ * Copy constructor
+ */
+ value_extractor(value_extractor const& that) : fallback_policy(static_cast< fallback_policy const& >(that))
+ {
+ }
+
+ /*!
+ * Constructor
+ *
+ * \param arg Fallback policy constructor argument
+ */
+ template< typename U >
+ explicit value_extractor(U const& arg) : fallback_policy(arg) {}
+
+ /*!
+ * Extraction operator. Attempts to acquire the stored value of one of the supported types. If extraction succeeds,
+ * the extracted value is returned.
+ *
+ * \param attr The attribute value to extract from.
+ * \return The extracted value, if extraction succeeded, an empty value otherwise.
+ */
+ result_type operator() (attribute_value const& attr) const
+ {
+ result_type res;
+ aux::value_ref_initializer< result_type > initializer(res);
+ if (!!attr)
+ {
+ static_type_dispatcher< value_type > disp(initializer);
+ if (!attr.dispatch(disp) && !fallback_policy::apply_default(initializer))
+ fallback_policy::on_invalid_type(attr.get_type());
+ }
+ else if (!fallback_policy::apply_default(initializer))
+ {
+ fallback_policy::on_missing_value();
+ }
+ return res;
+ }
+
+ /*!
+ * Extraction operator. Looks for an attribute value with the specified name
+ * and tries to acquire the stored value of one of the supported types. If extraction succeeds,
+ * the extracted value is returned.
+ *
+ * \param name Attribute value name.
+ * \param attrs A set of attribute values in which to look for the specified attribute value.
+ * \return The extracted value, if extraction succeeded, an empty value otherwise.
+ */
+ result_type operator() (attribute_name const& name, attribute_value_set const& attrs) const
+ {
+ try
+ {
+ attribute_value_set::const_iterator it = attrs.find(name);
+ if (it != attrs.end())
+ return operator() (it->second);
+ else
+ return operator() (attribute_value());
+ }
+ catch (exception& e)
+ {
+ // Attach the attribute name to the exception
+ boost::log::aux::attach_attribute_name_info(e, name);
+ throw;
+ }
+ }
+
+ /*!
+ * Extraction operator. Looks for an attribute value with the specified name
+ * and tries to acquire the stored value of one of the supported types. If extraction succeeds,
+ * the extracted value is returned.
+ *
+ * \param name Attribute value name.
+ * \param rec A log record. The attribute value will be sought among those associated with the record.
+ * \return The extracted value, if extraction succeeded, an empty value otherwise.
+ */
+ result_type operator() (attribute_name const& name, record const& rec) const
+ {
+ return operator() (name, rec.attribute_values());
+ }
+
+ /*!
+ * Extraction operator. Looks for an attribute value with the specified name
+ * and tries to acquire the stored value of one of the supported types. If extraction succeeds,
+ * the extracted value is returned.
+ *
+ * \param name Attribute value name.
+ * \param rec A log record view. The attribute value will be sought among those associated with the record.
+ * \return The extracted value, if extraction succeeded, an empty value otherwise.
+ */
+ result_type operator() (attribute_name const& name, record_view const& rec) const
+ {
+ return operator() (name, rec.attribute_values());
+ }
+
+ /*!
+ * \returns Fallback policy
+ */
+ fallback_policy const& get_fallback_policy() const
+ {
+ return *static_cast< fallback_policy const* >(this);
+ }
+};
+
+#if !defined(BOOST_LOG_DOXYGEN_PASS)
+#if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
+#define BOOST_LOG_AUX_VOID_DEFAULT = void
+#else
+#define BOOST_LOG_AUX_VOID_DEFAULT
+#endif
+#endif // !defined(BOOST_LOG_DOXYGEN_PASS)
+
+/*!
+ * The function extracts an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be extracted.
+ *
+ * \param name The name of the attribute value to extract.
+ * \param attrs A set of attribute values in which to look for the specified attribute value.
+ * \return A \c value_ref that refers to the extracted value, if found. An empty value otherwise.
+ */
+template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT >
+inline typename result_of::extract< T, TagT >::type extract(attribute_name const& name, attribute_value_set const& attrs)
+{
+ value_extractor< T, fallback_to_none, TagT > extractor;
+ return extractor(name, attrs);
+}
+
+/*!
+ * The function extracts an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be extracted.
+ *
+ * \param name The name of the attribute value to extract.
+ * \param rec A log record. The attribute value will be sought among those associated with the record.
+ * \return A \c value_ref that refers to the extracted value, if found. An empty value otherwise.
+ */
+template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT >
+inline typename result_of::extract< T, TagT >::type extract(attribute_name const& name, record const& rec)
+{
+ value_extractor< T, fallback_to_none, TagT > extractor;
+ return extractor(name, rec);
+}
+
+/*!
+ * The function extracts an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be extracted.
+ *
+ * \param name The name of the attribute value to extract.
+ * \param rec A log record view. The attribute value will be sought among those associated with the record.
+ * \return A \c value_ref that refers to the extracted value, if found. An empty value otherwise.
+ */
+template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT >
+inline typename result_of::extract< T, TagT >::type extract(attribute_name const& name, record_view const& rec)
+{
+ value_extractor< T, fallback_to_none, TagT > extractor;
+ return extractor(name, rec);
+}
+
+/*!
+ * The function extracts an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be extracted.
+ *
+ * \param value Attribute value.
+ * \return A \c value_ref that refers to the extracted value, if found. An empty value otherwise.
+ */
+template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT >
+inline typename result_of::extract< T, TagT >::type extract(attribute_value const& value)
+{
+ value_extractor< T, fallback_to_none, TagT > extractor;
+ return extractor(value);
+}
+
+/*!
+ * The function extracts an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be extracted.
+ *
+ * \param name The name of the attribute value to extract.
+ * \param attrs A set of attribute values in which to look for the specified attribute value.
+ * \return The extracted value or a non-empty \c value_ref that refers to the value.
+ * \throws An exception is thrown if the requested value cannot be extracted.
+ */
+template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT >
+inline typename result_of::extract_or_throw< T, TagT >::type extract_or_throw(attribute_name const& name, attribute_value_set const& attrs)
+{
+ value_extractor< T, fallback_to_throw, TagT > extractor;
+ return aux::unwrap_value_ref(extractor(name, attrs));
+}
+
+/*!
+ * The function extracts an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be extracted.
+ *
+ * \param name The name of the attribute value to extract.
+ * \param rec A log record. The attribute value will be sought among those associated with the record.
+ * \return The extracted value or a non-empty \c value_ref that refers to the value.
+ * \throws An exception is thrown if the requested value cannot be extracted.
+ */
+template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT >
+inline typename result_of::extract_or_throw< T, TagT >::type extract_or_throw(attribute_name const& name, record const& rec)
+{
+ value_extractor< T, fallback_to_throw, TagT > extractor;
+ return aux::unwrap_value_ref(extractor(name, rec));
+}
+
+/*!
+ * The function extracts an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be extracted.
+ *
+ * \param name The name of the attribute value to extract.
+ * \param rec A log record view. The attribute value will be sought among those associated with the record.
+ * \return The extracted value or a non-empty \c value_ref that refers to the value.
+ * \throws An exception is thrown if the requested value cannot be extracted.
+ */
+template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT >
+inline typename result_of::extract_or_throw< T, TagT >::type extract_or_throw(attribute_name const& name, record_view const& rec)
+{
+ value_extractor< T, fallback_to_throw, TagT > extractor;
+ return aux::unwrap_value_ref(extractor(name, rec));
+}
+
+/*!
+ * The function extracts an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be extracted.
+ *
+ * \param value Attribute value.
+ * \return The extracted value or a non-empty \c value_ref that refers to the value.
+ * \throws An exception is thrown if the requested value cannot be extracted.
+ */
+template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT >
+inline typename result_of::extract_or_throw< T, TagT >::type extract_or_throw(attribute_value const& value)
+{
+ value_extractor< T, fallback_to_throw, TagT > extractor;
+ return aux::unwrap_value_ref(extractor(value));
+}
+
+/*!
+ * The function extracts an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be extracted.
+ *
+ * \note Caution must be exercised if the default value is a temporary object. Because the function returns
+ * a reference, if the temporary object is destroyed, the reference may become dangling.
+ *
+ * \param name The name of the attribute value to extract.
+ * \param attrs A set of attribute values in which to look for the specified attribute value.
+ * \param def_val The default value
+ * \return The extracted value, if found. The default value otherwise.
+ */
+template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT, typename DefaultT >
+inline typename result_of::extract_or_default< T, DefaultT, TagT >::type
+extract_or_default(attribute_name const& name, attribute_value_set const& attrs, DefaultT const& def_val)
+{
+ typedef typename result_of::extract_or_default< T, DefaultT, TagT >::extracted_type extracted_type;
+ value_extractor< extracted_type, fallback_to_default< DefaultT const& >, TagT > extractor(def_val);
+ return aux::unwrap_value_ref(extractor(name, attrs));
+}
+
+/*!
+ * The function extracts an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be visited.
+ *
+ * \note Caution must be exercised if the default value is a temporary object. Because the function returns
+ * a reference, if the temporary object is destroyed, the reference may become dangling.
+ *
+ * \param name The name of the attribute value to extract.
+ * \param rec A log record. The attribute value will be sought among those associated with the record.
+ * \param def_val The default value
+ * \return The extracted value, if found. The default value otherwise.
+ */
+template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT, typename DefaultT >
+inline typename result_of::extract_or_default< T, DefaultT, TagT >::type
+extract_or_default(attribute_name const& name, record const& rec, DefaultT const& def_val)
+{
+ typedef typename result_of::extract_or_default< T, DefaultT, TagT >::extracted_type extracted_type;
+ value_extractor< extracted_type, fallback_to_default< DefaultT const& >, TagT > extractor(def_val);
+ return aux::unwrap_value_ref(extractor(name, rec));
+}
+
+/*!
+ * The function extracts an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be visited.
+ *
+ * \note Caution must be exercised if the default value is a temporary object. Because the function returns
+ * a reference, if the temporary object is destroyed, the reference may become dangling.
+ *
+ * \param name The name of the attribute value to extract.
+ * \param rec A log record view. The attribute value will be sought among those associated with the record.
+ * \param def_val The default value
+ * \return The extracted value, if found. The default value otherwise.
+ */
+template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT, typename DefaultT >
+inline typename result_of::extract_or_default< T, DefaultT, TagT >::type
+extract_or_default(attribute_name const& name, record_view const& rec, DefaultT const& def_val)
+{
+ typedef typename result_of::extract_or_default< T, DefaultT, TagT >::extracted_type extracted_type;
+ value_extractor< extracted_type, fallback_to_default< DefaultT const& >, TagT > extractor(def_val);
+ return aux::unwrap_value_ref(extractor(name, rec));
+}
+
+/*!
+ * The function extracts an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be visited.
+ *
+ * \note Caution must be exercised if the default value is a temporary object. Because the function returns
+ * a reference, if the temporary object is destroyed, the reference may become dangling.
+ *
+ * \param value Attribute value.
+ * \param def_val The default value
+ * \return The extracted value, if found. The default value otherwise.
+ */
+template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT, typename DefaultT >
+inline typename result_of::extract_or_default< T, DefaultT, TagT >::type extract_or_default(attribute_value const& value, DefaultT const& def_val)
+{
+ typedef typename result_of::extract_or_default< T, DefaultT, TagT >::extracted_type extracted_type;
+ value_extractor< extracted_type, fallback_to_default< DefaultT const& >, TagT > extractor(def_val);
+ return aux::unwrap_value_ref(extractor(value));
+}
+
+#if defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
+
+template< typename T >
+inline typename result_of::extract< T >::type extract(attribute_name const& name, attribute_value_set const& attrs)
+{
+ value_extractor< T, fallback_to_none > extractor;
+ return extractor(name, attrs);
+}
+
+template< typename T >
+inline typename result_of::extract< T >::type extract(attribute_name const& name, record const& rec)
+{
+ value_extractor< T, fallback_to_none > extractor;
+ return extractor(name, rec);
+}
+
+template< typename T >
+inline typename result_of::extract< T >::type extract(attribute_name const& name, record_view const& rec)
+{
+ value_extractor< T, fallback_to_none > extractor;
+ return extractor(name, rec);
+}
+
+template< typename T >
+inline typename result_of::extract< T >::type extract(attribute_value const& value)
+{
+ value_extractor< T, fallback_to_none > extractor;
+ return extractor(value);
+}
+
+template< typename T >
+inline typename result_of::extract_or_throw< T >::type extract_or_throw(attribute_name const& name, attribute_value_set const& attrs)
+{
+ value_extractor< T, fallback_to_throw > extractor;
+ return aux::unwrap_value_ref(extractor(name, attrs));
+}
+
+template< typename T >
+inline typename result_of::extract_or_throw< T >::type extract_or_throw(attribute_name const& name, record const& rec)
+{
+ value_extractor< T, fallback_to_throw > extractor;
+ return aux::unwrap_value_ref(extractor(name, rec));
+}
+
+template< typename T >
+inline typename result_of::extract_or_throw< T >::type extract_or_throw(attribute_name const& name, record_view const& rec)
+{
+ value_extractor< T, fallback_to_throw > extractor;
+ return aux::unwrap_value_ref(extractor(name, rec));
+}
+
+template< typename T >
+inline typename result_of::extract_or_throw< T >::type extract_or_throw(attribute_value const& value)
+{
+ value_extractor< T, fallback_to_throw > extractor;
+ return aux::unwrap_value_ref(extractor(value));
+}
+
+template< typename T, typename DefaultT >
+inline typename result_of::extract_or_default< T, DefaultT >::type extract_or_default(
+ attribute_name const& name, attribute_value_set const& attrs, DefaultT const& def_val)
+{
+ typedef typename result_of::extract_or_default< T, DefaultT >::extracted_type extracted_type;
+ value_extractor< extracted_type, fallback_to_default< DefaultT const& > > extractor(def_val);
+ return aux::unwrap_value_ref(extractor(name, attrs));
+}
+
+template< typename T, typename DefaultT >
+inline typename result_of::extract_or_default< T, DefaultT >::type extract_or_default(
+ attribute_name const& name, record const& rec, DefaultT const& def_val)
+{
+ typedef typename result_of::extract_or_default< T, DefaultT >::extracted_type extracted_type;
+ value_extractor< extracted_type, fallback_to_default< DefaultT const& > > extractor(def_val);
+ return aux::unwrap_value_ref(extractor(name, rec));
+}
+
+template< typename T, typename DefaultT >
+inline typename result_of::extract_or_default< T, DefaultT >::type extract_or_default(
+ attribute_name const& name, record_view const& rec, DefaultT const& def_val)
+{
+ typedef typename result_of::extract_or_default< T, DefaultT >::extracted_type extracted_type;
+ value_extractor< extracted_type, fallback_to_default< DefaultT const& > > extractor(def_val);
+ return aux::unwrap_value_ref(extractor(name, rec));
+}
+
+template< typename T, typename DefaultT >
+inline typename result_of::extract_or_default< T, DefaultT >::type extract_or_default(attribute_value const& value, DefaultT const& def_val)
+{
+ typedef typename result_of::extract_or_default< T, DefaultT >::extracted_type extracted_type;
+ value_extractor< extracted_type, fallback_to_default< DefaultT const& > > extractor(def_val);
+ return aux::unwrap_value_ref(extractor(value));
+}
+
+#endif // defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
+
+/*!
+ * The function extracts an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be extracted.
+ *
+ * \param keyword The keyword of the attribute value to extract.
+ * \param attrs A set of attribute values in which to look for the specified attribute value.
+ * \return A \c value_ref that refers to the extracted value, if found. An empty value otherwise.
+ */
+template< typename DescriptorT, template< typename > class ActorT >
+inline typename result_of::extract< typename DescriptorT::value_type, DescriptorT >::type
+extract(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, attribute_value_set const& attrs)
+{
+ value_extractor< typename DescriptorT::value_type, fallback_to_none, DescriptorT > extractor;
+ return extractor(keyword.get_name(), attrs);
+}
+
+/*!
+ * The function extracts an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be extracted.
+ *
+ * \param keyword The keyword of the attribute value to extract.
+ * \param rec A log record. The attribute value will be sought among those associated with the record.
+ * \return A \c value_ref that refers to the extracted value, if found. An empty value otherwise.
+ */
+template< typename DescriptorT, template< typename > class ActorT >
+inline typename result_of::extract< typename DescriptorT::value_type, DescriptorT >::type
+extract(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, record const& rec)
+{
+ value_extractor< typename DescriptorT::value_type, fallback_to_none, DescriptorT > extractor;
+ return extractor(keyword.get_name(), rec);
+}
+
+/*!
+ * The function extracts an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be extracted.
+ *
+ * \param keyword The keyword of the attribute value to extract.
+ * \param rec A log record view. The attribute value will be sought among those associated with the record.
+ * \return A \c value_ref that refers to the extracted value, if found. An empty value otherwise.
+ */
+template< typename DescriptorT, template< typename > class ActorT >
+inline typename result_of::extract< typename DescriptorT::value_type, DescriptorT >::type
+extract(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, record_view const& rec)
+{
+ value_extractor< typename DescriptorT::value_type, fallback_to_none, DescriptorT > extractor;
+ return extractor(keyword.get_name(), rec);
+}
+
+/*!
+ * The function extracts an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be extracted.
+ *
+ * \param keyword The keyword of the attribute value to extract.
+ * \param attrs A set of attribute values in which to look for the specified attribute value.
+ * \return The extracted value or a non-empty \c value_ref that refers to the value.
+ * \throws An exception is thrown if the requested value cannot be extracted.
+ */
+template< typename DescriptorT, template< typename > class ActorT >
+inline typename result_of::extract_or_throw< typename DescriptorT::value_type, DescriptorT >::type
+extract_or_throw(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, attribute_value_set const& attrs)
+{
+ value_extractor< typename DescriptorT::value_type, fallback_to_throw, DescriptorT > extractor;
+ return aux::unwrap_value_ref(extractor(keyword.get_name(), attrs));
+}
+
+/*!
+ * The function extracts an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be extracted.
+ *
+ * \param keyword The keyword of the attribute value to extract.
+ * \param rec A log record. The attribute value will be sought among those associated with the record.
+ * \return The extracted value or a non-empty \c value_ref that refers to the value.
+ * \throws An exception is thrown if the requested value cannot be extracted.
+ */
+template< typename DescriptorT, template< typename > class ActorT >
+inline typename result_of::extract_or_throw< typename DescriptorT::value_type, DescriptorT >::type
+extract_or_throw(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, record const& rec)
+{
+ value_extractor< typename DescriptorT::value_type, fallback_to_throw, DescriptorT > extractor;
+ return aux::unwrap_value_ref(extractor(keyword.get_name(), rec));
+}
+
+/*!
+ * The function extracts an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be extracted.
+ *
+ * \param keyword The keyword of the attribute value to extract.
+ * \param rec A log record view. The attribute value will be sought among those associated with the record.
+ * \return The extracted value or a non-empty \c value_ref that refers to the value.
+ * \throws An exception is thrown if the requested value cannot be extracted.
+ */
+template< typename DescriptorT, template< typename > class ActorT >
+inline typename result_of::extract_or_throw< typename DescriptorT::value_type, DescriptorT >::type
+extract_or_throw(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, record_view const& rec)
+{
+ value_extractor< typename DescriptorT::value_type, fallback_to_throw, DescriptorT > extractor;
+ return aux::unwrap_value_ref(extractor(keyword.get_name(), rec));
+}
+
+/*!
+ * The function extracts an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be extracted.
+ *
+ * \note Caution must be exercised if the default value is a temporary object. Because the function returns
+ * a reference, if the temporary object is destroyed, the reference may become dangling.
+ *
+ * \param keyword The keyword of the attribute value to extract.
+ * \param attrs A set of attribute values in which to look for the specified attribute value.
+ * \param def_val The default value
+ * \return The extracted value, if found. The default value otherwise.
+ */
+template< typename DescriptorT, template< typename > class ActorT, typename DefaultT >
+inline typename result_of::extract_or_default< typename DescriptorT::value_type, DefaultT, DescriptorT >::type
+extract_or_default(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, attribute_value_set const& attrs, DefaultT const& def_val)
+{
+ typedef typename result_of::extract_or_default< typename DescriptorT::value_type, DefaultT, DescriptorT >::extracted_type extracted_type;
+ value_extractor< extracted_type, fallback_to_default< DefaultT const& >, DescriptorT > extractor(def_val);
+ return aux::unwrap_value_ref(extractor(keyword.get_name(), attrs));
+}
+
+/*!
+ * The function extracts an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be visited.
+ *
+ * \note Caution must be exercised if the default value is a temporary object. Because the function returns
+ * a reference, if the temporary object is destroyed, the reference may become dangling.
+ *
+ * \param keyword The keyword of the attribute value to extract.
+ * \param rec A log record. The attribute value will be sought among those associated with the record.
+ * \param def_val The default value
+ * \return The extracted value, if found. The default value otherwise.
+ */
+template< typename DescriptorT, template< typename > class ActorT, typename DefaultT >
+inline typename result_of::extract_or_default< typename DescriptorT::value_type, DefaultT, DescriptorT >::type
+extract_or_default(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, record const& rec, DefaultT const& def_val)
+{
+ typedef typename result_of::extract_or_default< typename DescriptorT::value_type, DefaultT, DescriptorT >::extracted_type extracted_type;
+ value_extractor< extracted_type, fallback_to_default< DefaultT const& >, DescriptorT > extractor(def_val);
+ return aux::unwrap_value_ref(extractor(keyword.get_name(), rec));
+}
+
+/*!
+ * The function extracts an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be visited.
+ *
+ * \note Caution must be exercised if the default value is a temporary object. Because the function returns
+ * a reference, if the temporary object is destroyed, the reference may become dangling.
+ *
+ * \param keyword The keyword of the attribute value to extract.
+ * \param rec A log record view. The attribute value will be sought among those associated with the record.
+ * \param def_val The default value
+ * \return The extracted value, if found. The default value otherwise.
+ */
+template< typename DescriptorT, template< typename > class ActorT, typename DefaultT >
+inline typename result_of::extract_or_default< typename DescriptorT::value_type, DefaultT, DescriptorT >::type
+extract_or_default(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, record_view const& rec, DefaultT const& def_val)
+{
+ typedef typename result_of::extract_or_default< typename DescriptorT::value_type, DefaultT, DescriptorT >::extracted_type extracted_type;
+ value_extractor< extracted_type, fallback_to_default< DefaultT const& >, DescriptorT > extractor(def_val);
+ return aux::unwrap_value_ref(extractor(keyword.get_name(), rec));
+}
+
+#if !defined(BOOST_LOG_DOXYGEN_PASS)
+
+template< typename T, typename TagT >
+inline typename result_of::extract< T, TagT >::type attribute_value::extract() const
+{
+ return boost::log::extract< T, TagT >(*this);
+}
+
+template< typename T, typename TagT >
+inline typename result_of::extract_or_throw< T, TagT >::type attribute_value::extract_or_throw() const
+{
+ return boost::log::extract_or_throw< T, TagT >(*this);
+}
+
+template< typename T, typename TagT >
+inline typename result_of::extract_or_default< T, T, TagT >::type attribute_value::extract_or_default(T const& def_value) const
+{
+ return boost::log::extract_or_default< T, TagT >(*this, def_value);
+}
+
+template< typename T, typename TagT, typename DefaultT >
+inline typename result_of::extract_or_default< T, DefaultT, TagT >::type attribute_value::extract_or_default(DefaultT const& def_value) const
+{
+ return boost::log::extract_or_default< T, TagT >(*this, def_value);
+}
+
+#if defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
+
+template< typename T >
+inline typename result_of::extract< T >::type attribute_value::extract() const
+{
+ return boost::log::extract< T >(*this);
+}
+
+template< typename T >
+inline typename result_of::extract_or_throw< T >::type attribute_value::extract_or_throw() const
+{
+ return boost::log::extract_or_throw< T >(*this);
+}
+
+template< typename T >
+inline typename result_of::extract_or_default< T, T >::type attribute_value::extract_or_default(T const& def_value) const
+{
+ return boost::log::extract_or_default< T >(*this, def_value);
+}
+
+template< typename T, typename DefaultT >
+inline typename result_of::extract_or_default< T, DefaultT >::type attribute_value::extract_or_default(DefaultT const& def_value) const
+{
+ return boost::log::extract_or_default< T >(*this, def_value);
+}
+
+#endif // defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
+
+#endif // !defined(BOOST_LOG_DOXYGEN_PASS)
+
+#undef BOOST_LOG_AUX_VOID_DEFAULT
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTRIBUTES_VALUE_EXTRACTION_HPP_INCLUDED_
diff --git a/boost/log/attributes/value_extraction_fwd.hpp b/boost/log/attributes/value_extraction_fwd.hpp
new file mode 100644
index 0000000000..2cc5583019
--- /dev/null
+++ b/boost/log/attributes/value_extraction_fwd.hpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file value_extraction_fwd.hpp
+ * \author Andrey Semashev
+ * \date 01.03.2008
+ *
+ * The header contains forward declaration of tools for extracting attribute values
+ * from the view.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTES_VALUE_EXTRACTION_FWD_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTES_VALUE_EXTRACTION_FWD_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/attributes/fallback_policy_fwd.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace result_of {
+
+/*!
+ * \brief A metafunction that allows to acquire the result of the value extraction
+ */
+template< typename T, typename DefaultT = T, typename TagT = void >
+struct extract_or_default;
+
+/*!
+ * \brief A metafunction that allows to acquire the result of the value extraction
+ */
+template< typename T, typename TagT = void >
+struct extract_or_throw;
+
+/*!
+ * \brief A metafunction that allows to acquire the result of the value extraction
+ */
+template< typename T, typename TagT = void >
+struct extract;
+
+} // namespace result_of
+
+/*!
+ * \brief Generic attribute value extractor
+ */
+template< typename T, typename FallbackPolicyT = fallback_to_none, typename TagT = void >
+class value_extractor;
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_ATTRIBUTES_VALUE_EXTRACTION_FWD_HPP_INCLUDED_
diff --git a/boost/log/attributes/value_visitation.hpp b/boost/log/attributes/value_visitation.hpp
new file mode 100644
index 0000000000..6a8205fcf3
--- /dev/null
+++ b/boost/log/attributes/value_visitation.hpp
@@ -0,0 +1,372 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file value_visitation.hpp
+ * \author Andrey Semashev
+ * \date 01.03.2008
+ *
+ * The header contains implementation of convenience tools to apply visitors to an attribute value
+ * in the view.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTES_VALUE_VISITATION_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTES_VALUE_VISITATION_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/exceptions.hpp>
+#include <boost/log/core/record.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/attribute_value.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include <boost/log/attributes/value_visitation_fwd.hpp>
+#include <boost/log/attributes/fallback_policy.hpp>
+#include <boost/log/expressions/keyword_fwd.hpp>
+#include <boost/utility/explicit_operator_bool.hpp>
+#include <boost/log/utility/type_dispatch/static_type_dispatcher.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * \brief The class represents attribute value visitation result
+ *
+ * The main purpose of this class is to provide a convenient interface for checking
+ * whether the attribute value visitation succeeded or not. It also allows to discover
+ * the actual cause of failure, should the operation fail.
+ */
+class visitation_result
+{
+public:
+ //! Error codes for attribute value visitation
+ enum error_code
+ {
+ ok, //!< The attribute value has been visited successfully
+ value_not_found, //!< The attribute value is not present in the view
+ value_has_invalid_type //!< The attribute value is present in the view, but has an unexpected type
+ };
+
+private:
+ error_code m_code;
+
+public:
+ /*!
+ * Initializing constructor. Creates the result that is equivalent to the
+ * specified error code.
+ */
+ BOOST_CONSTEXPR visitation_result(error_code code = ok) BOOST_NOEXCEPT : m_code(code) {}
+
+ /*!
+ * Checks if the visitation was successful.
+ *
+ * \return \c true if the value was visited successfully, \c false otherwise.
+ */
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+ /*!
+ * Checks if the visitation was unsuccessful.
+ *
+ * \return \c false if the value was visited successfully, \c true otherwise.
+ */
+ bool operator! () const BOOST_NOEXCEPT { return (m_code != ok); }
+
+ /*!
+ * \return The actual result code of value visitation
+ */
+ error_code code() const BOOST_NOEXCEPT { return m_code; }
+};
+
+/*!
+ * \brief Generic attribute value visitor invoker
+ *
+ * Attribute value invoker is a functional object that attempts to find and extract the stored
+ * attribute value from the attribute value view or a log record. The extracted value is passed to
+ * a unary function object (the visitor) provided by user.
+ *
+ * The invoker can be specialized on one or several attribute value types that should be
+ * specified in the second template argument.
+ */
+template< typename T, typename FallbackPolicyT >
+class value_visitor_invoker :
+ private FallbackPolicyT
+{
+ typedef value_visitor_invoker< T, FallbackPolicyT > this_type;
+
+public:
+ //! Attribute value types
+ typedef T value_type;
+
+ //! Fallback policy
+ typedef FallbackPolicyT fallback_policy;
+
+ //! Function object result type
+ typedef visitation_result result_type;
+
+public:
+ /*!
+ * Default constructor
+ */
+ BOOST_DEFAULTED_FUNCTION(value_visitor_invoker(), {})
+
+ /*!
+ * Copy constructor
+ */
+ value_visitor_invoker(value_visitor_invoker const& that) : fallback_policy(static_cast< fallback_policy const& >(that))
+ {
+ }
+
+ /*!
+ * Initializing constructor
+ *
+ * \param arg Fallback policy argument
+ */
+ template< typename U >
+ explicit value_visitor_invoker(U const& arg) : fallback_policy(arg) {}
+
+ /*!
+ * Visitation operator. Attempts to acquire the stored value of one of the supported types. If acquisition succeeds,
+ * the value is passed to \a visitor.
+ *
+ * \param attr An attribute value to apply the visitor to.
+ * \param visitor A receiving function object to pass the attribute value to.
+ * \return The result of visitation.
+ */
+ template< typename VisitorT >
+ result_type operator() (attribute_value const& attr, VisitorT visitor) const
+ {
+ if (!!attr)
+ {
+ static_type_dispatcher< value_type > disp(visitor);
+ if (attr.dispatch(disp) || fallback_policy::apply_default(visitor))
+ {
+ return visitation_result::ok;
+ }
+ else
+ {
+ fallback_policy::on_invalid_type(attr.get_type());
+ return visitation_result::value_has_invalid_type;
+ }
+ }
+
+ if (fallback_policy::apply_default(visitor))
+ return visitation_result::ok;
+
+ fallback_policy::on_missing_value();
+ return visitation_result::value_not_found;
+ }
+
+ /*!
+ * Visitation operator. Looks for an attribute value with the specified name
+ * and tries to acquire the stored value of one of the supported types. If acquisition succeeds,
+ * the value is passed to \a visitor.
+ *
+ * \param name Attribute value name.
+ * \param attrs A set of attribute values in which to look for the specified attribute value.
+ * \param visitor A receiving function object to pass the attribute value to.
+ * \return The result of visitation.
+ */
+ template< typename VisitorT >
+ result_type operator() (attribute_name const& name, attribute_value_set const& attrs, VisitorT visitor) const
+ {
+ try
+ {
+ attribute_value_set::const_iterator it = attrs.find(name);
+ if (it != attrs.end())
+ return operator() (it->second, visitor);
+ else
+ return operator() (attribute_value(), visitor);
+ }
+ catch (exception& e)
+ {
+ // Attach the attribute name to the exception
+ boost::log::aux::attach_attribute_name_info(e, name);
+ throw;
+ }
+ }
+
+ /*!
+ * Visitation operator. Looks for an attribute value with the specified name
+ * and tries to acquire the stored value of one of the supported types. If acquisition succeeds,
+ * the value is passed to \a visitor.
+ *
+ * \param name Attribute value name.
+ * \param rec A log record. The attribute value will be sought among those associated with the record.
+ * \param visitor A receiving function object to pass the attribute value to.
+ * \return The result of visitation.
+ */
+ template< typename VisitorT >
+ result_type operator() (attribute_name const& name, record const& rec, VisitorT visitor) const
+ {
+ return operator() (name, rec.attribute_values(), visitor);
+ }
+
+ /*!
+ * Visitation operator. Looks for an attribute value with the specified name
+ * and tries to acquire the stored value of one of the supported types. If acquisition succeeds,
+ * the value is passed to \a visitor.
+ *
+ * \param name Attribute value name.
+ * \param rec A log record view. The attribute value will be sought among those associated with the record.
+ * \param visitor A receiving function object to pass the attribute value to.
+ * \return The result of visitation.
+ */
+ template< typename VisitorT >
+ result_type operator() (attribute_name const& name, record_view const& rec, VisitorT visitor) const
+ {
+ return operator() (name, rec.attribute_values(), visitor);
+ }
+
+ /*!
+ * \returns Fallback policy
+ */
+ fallback_policy const& get_fallback_policy() const
+ {
+ return *static_cast< fallback_policy const* >(this);
+ }
+};
+
+/*!
+ * The function applies a visitor to an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be visited.
+ *
+ * \param name The name of the attribute value to visit.
+ * \param attrs A set of attribute values in which to look for the specified attribute value.
+ * \param visitor A receiving function object to pass the attribute value to.
+ * \return The result of visitation.
+ */
+template< typename T, typename VisitorT >
+inline visitation_result
+visit(attribute_name const& name, attribute_value_set const& attrs, VisitorT visitor)
+{
+ value_visitor_invoker< T > invoker;
+ return invoker(name, attrs, visitor);
+}
+
+/*!
+ * The function applies a visitor to an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be visited.
+ *
+ * \param name The name of the attribute value to visit.
+ * \param rec A log record. The attribute value will be sought among those associated with the record.
+ * \param visitor A receiving function object to pass the attribute value to.
+ * \return The result of visitation.
+ */
+template< typename T, typename VisitorT >
+inline visitation_result
+visit(attribute_name const& name, record const& rec, VisitorT visitor)
+{
+ value_visitor_invoker< T > invoker;
+ return invoker(name, rec, visitor);
+}
+
+/*!
+ * The function applies a visitor to an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be visited.
+ *
+ * \param name The name of the attribute value to visit.
+ * \param rec A log record view. The attribute value will be sought among those associated with the record.
+ * \param visitor A receiving function object to pass the attribute value to.
+ * \return The result of visitation.
+ */
+template< typename T, typename VisitorT >
+inline visitation_result
+visit(attribute_name const& name, record_view const& rec, VisitorT visitor)
+{
+ value_visitor_invoker< T > invoker;
+ return invoker(name, rec, visitor);
+}
+
+/*!
+ * The function applies a visitor to an attribute value. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be visited.
+ *
+ * \param value The attribute value to visit.
+ * \param visitor A receiving function object to pass the attribute value to.
+ * \return The result of visitation.
+ */
+template< typename T, typename VisitorT >
+inline visitation_result
+visit(attribute_value const& value, VisitorT visitor)
+{
+ value_visitor_invoker< T > invoker;
+ return invoker(value, visitor);
+}
+
+/*!
+ * The function applies a visitor to an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be visited.
+ *
+ * \param keyword The keyword of the attribute value to visit.
+ * \param attrs A set of attribute values in which to look for the specified attribute value.
+ * \param visitor A receiving function object to pass the attribute value to.
+ * \return The result of visitation.
+ */
+template< typename DescriptorT, template< typename > class ActorT, typename VisitorT >
+inline visitation_result
+visit(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, attribute_value_set const& attrs, VisitorT visitor)
+{
+ value_visitor_invoker< typename DescriptorT::value_type > invoker;
+ return invoker(keyword.get_name(), attrs, visitor);
+}
+
+/*!
+ * The function applies a visitor to an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be visited.
+ *
+ * \param keyword The keyword of the attribute value to visit.
+ * \param rec A log record. The attribute value will be sought among those associated with the record.
+ * \param visitor A receiving function object to pass the attribute value to.
+ * \return The result of visitation.
+ */
+template< typename DescriptorT, template< typename > class ActorT, typename VisitorT >
+inline visitation_result
+visit(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, record const& rec, VisitorT visitor)
+{
+ value_visitor_invoker< typename DescriptorT::value_type > invoker;
+ return invoker(keyword.get_name(), rec, visitor);
+}
+
+/*!
+ * The function applies a visitor to an attribute value from the view. The user has to explicitly specify the
+ * type or set of possible types of the attribute value to be visited.
+ *
+ * \param keyword The keyword of the attribute value to visit.
+ * \param rec A log record view. The attribute value will be sought among those associated with the record.
+ * \param visitor A receiving function object to pass the attribute value to.
+ * \return The result of visitation.
+ */
+template< typename DescriptorT, template< typename > class ActorT, typename VisitorT >
+inline visitation_result
+visit(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, record_view const& rec, VisitorT visitor)
+{
+ value_visitor_invoker< typename DescriptorT::value_type > invoker;
+ return invoker(keyword.get_name(), rec, visitor);
+}
+
+
+#if !defined(BOOST_LOG_DOXYGEN_PASS)
+
+template< typename T, typename VisitorT >
+inline visitation_result attribute_value::visit(VisitorT visitor) const
+{
+ return boost::log::visit< T >(*this, visitor);
+}
+
+#endif // !defined(BOOST_LOG_DOXYGEN_PASS)
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTRIBUTES_VALUE_VISITATION_HPP_INCLUDED_
diff --git a/boost/log/attributes/value_visitation_fwd.hpp b/boost/log/attributes/value_visitation_fwd.hpp
new file mode 100644
index 0000000000..5917c22a95
--- /dev/null
+++ b/boost/log/attributes/value_visitation_fwd.hpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file value_visitation_fwd.hpp
+ * \author Andrey Semashev
+ * \date 01.03.2008
+ *
+ * The header contains forward declaration of convenience tools to apply visitors to an attribute value
+ * in the view.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTES_VALUE_VISITATION_FWD_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTES_VALUE_VISITATION_FWD_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/attributes/fallback_policy_fwd.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * \brief The class represents attribute value visitation result
+ */
+class visitation_result;
+
+/*!
+ * \brief Generic attribute value visitor invoker
+ */
+template< typename T, typename FallbackPolicyT = fallback_to_none >
+class value_visitor_invoker;
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_ATTRIBUTES_VALUE_VISITATION_FWD_HPP_INCLUDED_
diff --git a/boost/log/common.hpp b/boost/log/common.hpp
new file mode 100644
index 0000000000..bc62893d8b
--- /dev/null
+++ b/boost/log/common.hpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file common.hpp
+ * \author Andrey Semashev
+ * \date 14.03.2009
+ *
+ * This header includes other Boost.Log headers that are commonly used in logging applications.
+ * Note that the header does not include any headers required to setup the library, as usually
+ * they aren't needed in more than one translation unit of the application.
+ */
+
+#ifndef BOOST_LOG_COMMON_HPP_INCLUDED_
+#define BOOST_LOG_COMMON_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#include <boost/log/core.hpp>
+
+#include <boost/log/sources/global_logger_storage.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+
+#include <boost/log/sources/basic_logger.hpp>
+#include <boost/log/sources/severity_logger.hpp>
+#include <boost/log/sources/channel_logger.hpp>
+#include <boost/log/sources/severity_channel_logger.hpp>
+#include <boost/log/sources/exception_handler_feature.hpp>
+
+#include <boost/log/attributes/constant.hpp>
+#include <boost/log/attributes/named_scope.hpp>
+#include <boost/log/attributes/scoped_attribute.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#endif // BOOST_LOG_COMMON_HPP_INCLUDED_
diff --git a/boost/log/core.hpp b/boost/log/core.hpp
new file mode 100644
index 0000000000..159e5b9177
--- /dev/null
+++ b/boost/log/core.hpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file log/core.hpp
+ * \author Andrey Semashev
+ * \date 19.04.2007
+ *
+ * This header includes Boost.Log headers related to the logging core.
+ */
+
+#ifndef BOOST_LOG_CORE_HPP_INCLUDED_
+#define BOOST_LOG_CORE_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#include <boost/log/core/core.hpp>
+#include <boost/log/core/record.hpp>
+#include <boost/log/core/record_view.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#endif // BOOST_LOG_CORE_HPP_INCLUDED_
diff --git a/boost/log/core/core.hpp b/boost/log/core/core.hpp
new file mode 100644
index 0000000000..e3475299c4
--- /dev/null
+++ b/boost/log/core/core.hpp
@@ -0,0 +1,329 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file core/core.hpp
+ * \author Andrey Semashev
+ * \date 19.04.2007
+ *
+ * This header contains logging core class definition.
+ */
+
+#ifndef BOOST_LOG_CORE_CORE_HPP_INCLUDED_
+#define BOOST_LOG_CORE_CORE_HPP_INCLUDED_
+
+#include <utility>
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/move/core.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/light_function.hpp>
+#include <boost/log/core/record.hpp>
+#include <boost/log/attributes/attribute_set.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include <boost/log/expressions/filter.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+namespace sinks {
+
+class sink;
+
+} // namespace sinks
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+class core;
+
+typedef shared_ptr< core > core_ptr;
+
+/*!
+ * \brief Logging library core class
+ *
+ * The logging core is used to interconnect log sources and sinks. It also provides
+ * a number of basic features, like global filtering and global and thread-specific attribute storage.
+ *
+ * The logging core is a singleton. Users can acquire the core instance by calling the static method <tt>get</tt>.
+ */
+class core
+{
+public:
+ //! Exception handler function type
+ typedef boost::log::aux::light_function< void () > exception_handler_type;
+
+private:
+ //! Implementation type
+ struct implementation;
+ friend struct implementation;
+
+private:
+ //! A pointer to the implementation
+ implementation* m_impl;
+
+private:
+ //! \cond
+ core();
+ //! \endcond
+
+public:
+ /*!
+ * Destructor. Destroys the core, releases any sinks and attributes that were registered.
+ */
+ ~core();
+
+ /*!
+ * \return The method returns a pointer to the logging core singleton instance.
+ */
+ BOOST_LOG_API static core_ptr get();
+
+ /*!
+ * The method enables or disables logging.
+ *
+ * Setting this status to \c false allows you to completely wipe out any logging activity, including
+ * filtering and generation of attribute values. It is useful if you want to completely disable logging
+ * in a running application. The state of logging does not alter any other properties of the logging
+ * library, such as filters or sinks, so you can enable logging with the very same settings that you had
+ * when the logging was disabled.
+ * This feature may also be useful if you want to perform major changes to logging configuration and
+ * don't want your application to block on opening or pushing a log record.
+ *
+ * By default logging is enabled.
+ *
+ * \param enabled The actual flag of logging activity.
+ * \return The previous value of enabled/disabled logging flag
+ */
+ BOOST_LOG_API bool set_logging_enabled(bool enabled = true);
+ /*!
+ * The method allows to detect if logging is enabled. See the comment for \c set_logging_enabled.
+ */
+ BOOST_LOG_API bool get_logging_enabled() const;
+
+ /*!
+ * The method sets the global logging filter. The filter is applied to every log record that is processed.
+ *
+ * \param filter The filter function object to be installed.
+ */
+ BOOST_LOG_API void set_filter(filter const& filter);
+ /*!
+ * The method removes the global logging filter. All log records are passed to sinks without global filtering applied.
+ */
+ BOOST_LOG_API void reset_filter();
+
+ /*!
+ * The method adds a new sink. The sink is included into logging process immediately after being added and until being removed.
+ * No sink can be added more than once at the same time. If the sink is already registered, the call is ignored.
+ *
+ * \param s The sink to be registered.
+ */
+ BOOST_LOG_API void add_sink(shared_ptr< sinks::sink > const& s);
+ /*!
+ * The method removes the sink from the output. The sink will not receive any log records after removal.
+ * The call has no effect if the sink is not registered.
+ *
+ * \param s The sink to be unregistered.
+ */
+ BOOST_LOG_API void remove_sink(shared_ptr< sinks::sink > const& s);
+ /*!
+ * The method removes all registered sinks from the output. The sinks will not receive any log records after removal.
+ */
+ BOOST_LOG_API void remove_all_sinks();
+
+ /*!
+ * The method performs flush on all registered sinks.
+ *
+ * \note This method may take long time to complete as it may block until all sinks manage to process all buffered log records.
+ * The call will also block all logging attempts until the operation completes.
+ */
+ BOOST_LOG_API void flush();
+
+ /*!
+ * The method adds an attribute to the global attribute set. The attribute will be implicitly added to every log record.
+ *
+ * \param name The attribute name.
+ * \param attr The attribute factory.
+ * \return A pair of values. If the second member is \c true, then the attribute is added and the first member points to the
+ * attribute. Otherwise the attribute was not added and the first member points to the attribute that prevents
+ * addition.
+ */
+ BOOST_LOG_API std::pair< attribute_set::iterator, bool > add_global_attribute(attribute_name const& name, attribute const& attr);
+ /*!
+ * The method removes an attribute from the global attribute set.
+ *
+ * \pre The attribute was added with the \c add_global_attribute call.
+ * \post The attribute is no longer registered as a global attribute. The iterator is invalidated after removal.
+ *
+ * \param it Iterator to the previously added attribute.
+ */
+ BOOST_LOG_API void remove_global_attribute(attribute_set::iterator it);
+
+ /*!
+ * The method returns a copy of the complete set of currently registered global attributes.
+ */
+ BOOST_LOG_API attribute_set get_global_attributes() const;
+ /*!
+ * The method replaces the complete set of currently registered global attributes with the provided set.
+ *
+ * \note The method invalidates all iterators and references that may have been returned
+ * from the \c add_global_attribute method.
+ *
+ * \param attrs The set of attributes to be installed.
+ */
+ BOOST_LOG_API void set_global_attributes(attribute_set const& attrs);
+
+ /*!
+ * The method adds an attribute to the thread-specific attribute set. The attribute will be implicitly added to
+ * every log record made in the current thread.
+ *
+ * \note In single-threaded build the effect is the same as adding the attribute globally. This, however, does
+ * not imply that iterators to thread-specific and global attributes are interchangeable.
+ *
+ * \param name The attribute name.
+ * \param attr The attribute factory.
+ * \return A pair of values. If the second member is \c true, then the attribute is added and the first member points to the
+ * attribute. Otherwise the attribute was not added and the first member points to the attribute that prevents
+ * addition.
+ */
+ BOOST_LOG_API std::pair< attribute_set::iterator, bool > add_thread_attribute(attribute_name const& name, attribute const& attr);
+ /*!
+ * The method removes an attribute from the thread-specific attribute set.
+ *
+ * \pre The attribute was added with the \c add_thread_attribute call.
+ * \post The attribute is no longer registered as a thread-specific attribute. The iterator is invalidated after removal.
+ *
+ * \param it Iterator to the previously added attribute.
+ */
+ BOOST_LOG_API void remove_thread_attribute(attribute_set::iterator it);
+
+ /*!
+ * The method returns a copy of the complete set of currently registered thread-specific attributes.
+ */
+ BOOST_LOG_API attribute_set get_thread_attributes() const;
+ /*!
+ * The method replaces the complete set of currently registered thread-specific attributes with the provided set.
+ *
+ * \note The method invalidates all iterators and references that may have been returned
+ * from the \c add_thread_attribute method.
+ *
+ * \param attrs The set of attributes to be installed.
+ */
+ BOOST_LOG_API void set_thread_attributes(attribute_set const& attrs);
+
+ /*!
+ * The method sets exception handler function. The function will be called with no arguments
+ * in case if an exception occurs during either \c open_record or \c push_record method
+ * execution. Since exception handler is called from a \c catch statement, the exception
+ * can be rethrown in order to determine its type.
+ *
+ * By default no handler is installed, thus any exception is propagated as usual.
+ *
+ * \sa See also: <tt>utility/exception_handler.hpp</tt>
+ * \param handler Exception handling function
+ *
+ * \note The exception handler can be invoked in several threads concurrently.
+ * Thread interruptions are not affected by exception handlers.
+ */
+ BOOST_LOG_API void set_exception_handler(exception_handler_type const& handler);
+
+ /*!
+ * The method attempts to open a new record to be written. While attempting to open a log record all filtering is applied.
+ * A successfully opened record can be pushed further to sinks by calling the \c push_record method or simply destroyed by
+ * destroying the returned object.
+ *
+ * More than one open records are allowed, such records exist independently. All attribute values are acquired during opening
+ * the record and do not interact between records.
+ *
+ * The returned records can be copied, however, they must not be passed between different threads.
+ *
+ * \param source_attributes The set of source-specific attributes to be attached to the record to be opened.
+ * \return A valid log record if the record is opened, an invalid record object if not (e.g. because it didn't pass filtering).
+ *
+ * \b Throws: If an exception handler is installed, only throws if the handler throws. Otherwise may
+ * throw if one of the sinks throws, or some system resource limitation is reached.
+ */
+ BOOST_LOG_API record open_record(attribute_set const& source_attributes);
+ /*!
+ * The method attempts to open a new record to be written. While attempting to open a log record all filtering is applied.
+ * A successfully opened record can be pushed further to sinks by calling the \c push_record method or simply destroyed by
+ * destroying the returned object.
+ *
+ * More than one open records are allowed, such records exist independently. All attribute values are acquired during opening
+ * the record and do not interact between records.
+ *
+ * The returned records can be copied, however, they must not be passed between different threads.
+ *
+ * \param source_attributes The set of source-specific attribute values to be attached to the record to be opened.
+ * \return A valid log record if the record is opened, an invalid record object if not (e.g. because it didn't pass filtering).
+ *
+ * \b Throws: If an exception handler is installed, only throws if the handler throws. Otherwise may
+ * throw if one of the sinks throws, or some system resource limitation is reached.
+ */
+ BOOST_LOG_API record open_record(attribute_value_set const& source_attributes);
+ /*!
+ * The method attempts to open a new record to be written. While attempting to open a log record all filtering is applied.
+ * A successfully opened record can be pushed further to sinks by calling the \c push_record method or simply destroyed by
+ * destroying the returned object.
+ *
+ * More than one open records are allowed, such records exist independently. All attribute values are acquired during opening
+ * the record and do not interact between records.
+ *
+ * The returned records can be copied, however, they must not be passed between different threads.
+ *
+ * \param source_attributes The set of source-specific attribute values to be attached to the record to be opened. The contents
+ * of this container are unspecified after this call.
+ * \return A valid log record if the record is opened, an invalid record object if not (e.g. because it didn't pass filtering).
+ *
+ * \b Throws: If an exception handler is installed, only throws if the handler throws. Otherwise may
+ * throw if one of the sinks throws, or some system resource limitation is reached.
+ */
+ BOOST_FORCEINLINE record open_record(BOOST_RV_REF(attribute_value_set) source_attributes)
+ {
+ return open_record_move(static_cast< attribute_value_set& >(source_attributes));
+ }
+
+ /*!
+ * The method pushes the record to sinks. The record is moved from in the process.
+ *
+ * \pre <tt>!!rec == true</tt>
+ * \post <tt>!rec == true</tt>
+ * \param rec A previously successfully opened log record.
+ *
+ * \b Throws: If an exception handler is installed, only throws if the handler throws. Otherwise may
+ * throw if one of the sinks throws.
+ */
+ BOOST_FORCEINLINE void push_record(BOOST_RV_REF(record) rec)
+ {
+ push_record_move(static_cast< record& >(rec));
+ }
+
+ BOOST_DELETED_FUNCTION(core(core const&))
+ BOOST_DELETED_FUNCTION(core& operator= (core const&))
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+private:
+ //! Opens log record. This function is mostly needed to maintain ABI stable between C++03 and C++11.
+ BOOST_LOG_API record open_record_move(attribute_value_set& source_attributes);
+ //! The method pushes the record to sinks.
+ BOOST_LOG_API void push_record_move(record& rec);
+#endif // BOOST_LOG_DOXYGEN_PASS
+};
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_CORE_CORE_HPP_INCLUDED_
diff --git a/boost/log/core/record.hpp b/boost/log/core/record.hpp
new file mode 100644
index 0000000000..758e44aadb
--- /dev/null
+++ b/boost/log/core/record.hpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file record.hpp
+ * \author Andrey Semashev
+ * \date 09.03.2009
+ *
+ * This header contains a logging record class definition.
+ */
+
+#ifndef BOOST_LOG_CORE_RECORD_HPP_INCLUDED_
+#define BOOST_LOG_CORE_RECORD_HPP_INCLUDED_
+
+#include <boost/move/core.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/utility/explicit_operator_bool.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include <boost/log/expressions/keyword_fwd.hpp>
+#include <boost/log/core/record_view.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+class core;
+
+/*!
+ * \brief Logging record class
+ *
+ * The logging record encapsulates all information related to a single logging statement,
+ * in particular, attribute values view and the log message string. The record can be updated before pushing
+ * for further processing to the logging core.
+ */
+class record
+{
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(record)
+
+ friend class core;
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+private:
+ //! Private data
+ typedef record_view::public_data public_data;
+
+private:
+ //! A pointer to the log record implementation
+ public_data* m_impl;
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+public:
+ /*!
+ * Default constructor. Creates an empty record that is equivalent to the invalid record handle.
+ *
+ * \post <tt>!*this == true</tt>
+ */
+ record() : m_impl(NULL) {}
+
+ /*!
+ * Move constructor. Source record contents unspecified after the operation.
+ */
+ record(BOOST_RV_REF(record) that) BOOST_NOEXCEPT : m_impl(that.m_impl)
+ {
+ that.m_impl = NULL;
+ }
+
+ /*!
+ * Destructor. Destroys the record, releases any sinks and attribute values that were involved in processing this record.
+ */
+ ~record() BOOST_NOEXCEPT
+ {
+ reset();
+ }
+
+ /*!
+ * Move assignment. Source record contents unspecified after the operation.
+ */
+ record& operator= (BOOST_RV_REF(record) that) BOOST_NOEXCEPT
+ {
+ swap(static_cast< record& >(that));
+ return *this;
+ }
+
+ /*!
+ * \return A reference to the set of attribute values attached to this record
+ *
+ * \pre <tt>!!*this</tt>
+ */
+ attribute_value_set& attribute_values() BOOST_NOEXCEPT
+ {
+ return m_impl->m_attribute_values;
+ }
+
+ /*!
+ * \return A reference to the set of attribute values attached to this record
+ *
+ * \pre <tt>!!*this</tt>
+ */
+ attribute_value_set const& attribute_values() const BOOST_NOEXCEPT
+ {
+ return m_impl->m_attribute_values;
+ }
+
+ /*!
+ * Conversion to an unspecified boolean type
+ *
+ * \return \c true, if the <tt>*this</tt> identifies a log record, \c false, if the <tt>*this</tt> is not valid
+ */
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+
+ /*!
+ * Inverted conversion to an unspecified boolean type
+ *
+ * \return \c false, if the <tt>*this</tt> identifies a log record, \c true, if the <tt>*this</tt> is not valid
+ */
+ bool operator! () const BOOST_NOEXCEPT
+ {
+ return !m_impl;
+ }
+
+ /*!
+ * Swaps two handles
+ *
+ * \param that Another record to swap with
+ * <b>Throws:</b> Nothing
+ */
+ void swap(record& that) BOOST_NOEXCEPT
+ {
+ public_data* p = m_impl;
+ m_impl = that.m_impl;
+ that.m_impl = p;
+ }
+
+ /*!
+ * Resets the log record handle. If there are no other handles left, the log record is closed
+ * and all resources referenced by the record are released.
+ *
+ * \post <tt>!*this == true</tt>
+ */
+ void reset() BOOST_NOEXCEPT
+ {
+ if (m_impl)
+ {
+ public_data::destroy(m_impl);
+ m_impl = NULL;
+ }
+ }
+
+ /*!
+ * Attribute value lookup.
+ *
+ * \param name Attribute name.
+ * \return An \c attribute_value, non-empty if it is found, empty otherwise.
+ */
+ attribute_value_set::mapped_type operator[] (attribute_value_set::key_type name) const
+ {
+ return m_impl->m_attribute_values[name];
+ }
+
+ /*!
+ * Attribute value lookup.
+ *
+ * \param keyword Attribute keyword.
+ * \return A \c value_ref with extracted attribute value if it is found, empty \c value_ref otherwise.
+ */
+ template< typename DescriptorT, template< typename > class ActorT >
+ typename result_of::extract< typename expressions::attribute_keyword< DescriptorT, ActorT >::value_type, DescriptorT >::type
+ operator[] (expressions::attribute_keyword< DescriptorT, ActorT > const& keyword) const
+ {
+ return m_impl->m_attribute_values[keyword];
+ }
+
+ /*!
+ * The function ensures that the log record does not depend on any thread-specific data. Then the record contents
+ * are used to construct a \c record_view which is returned from the function. The record is no longer valid after the call.
+ *
+ * \pre <tt>!!*this</tt>
+ * \post <tt>!*this</tt>
+ * \returns The record view that contains all attribute values from the original record.
+ */
+ BOOST_LOG_API record_view lock();
+};
+
+/*!
+ * A free-standing swap function overload for \c record
+ */
+inline void swap(record& left, record& right) BOOST_NOEXCEPT
+{
+ left.swap(right);
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_CORE_RECORD_HPP_INCLUDED_
diff --git a/boost/log/core/record_view.hpp b/boost/log/core/record_view.hpp
new file mode 100644
index 0000000000..58f2a1b778
--- /dev/null
+++ b/boost/log/core/record_view.hpp
@@ -0,0 +1,260 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file record_view.hpp
+ * \author Andrey Semashev
+ * \date 09.03.2009
+ *
+ * This header contains a logging record view class definition.
+ */
+
+#ifndef BOOST_LOG_CORE_RECORD_VIEW_HPP_INCLUDED_
+#define BOOST_LOG_CORE_RECORD_VIEW_HPP_INCLUDED_
+
+#include <boost/smart_ptr/intrusive_ptr.hpp>
+#include <boost/move/core.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/utility/explicit_operator_bool.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include <boost/log/expressions/keyword_fwd.hpp>
+#ifndef BOOST_LOG_NO_THREADS
+#include <boost/detail/atomic_count.hpp>
+#endif // BOOST_LOG_NO_THREADS
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+class core;
+class record;
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * \brief Logging record view class
+ *
+ * The logging record encapsulates all information related to a single logging statement,
+ * in particular, attribute values view and the log message string. The view is immutable,
+ * it is implemented as a wrapper around a reference-counted implementation.
+ */
+class record_view
+{
+ BOOST_COPYABLE_AND_MOVABLE(record_view)
+
+ friend class core;
+ friend class record;
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+private:
+ //! Private data
+ struct private_data;
+ friend struct private_data;
+
+ //! Publicly available record data
+ struct public_data
+ {
+ //! Reference counter
+#ifndef BOOST_LOG_NO_THREADS
+ mutable boost::detail::atomic_count m_ref_counter;
+#else
+ mutable unsigned int m_ref_counter;
+#endif // BOOST_LOG_NO_THREADS
+
+ //! Attribute values view
+ attribute_value_set m_attribute_values;
+
+ //! Constructor from the attribute sets
+ explicit public_data(BOOST_RV_REF(attribute_value_set) values) :
+ m_ref_counter(1),
+ m_attribute_values(values)
+ {
+ }
+
+ //! Destructor
+ BOOST_LOG_API static void destroy(const public_data* p) BOOST_NOEXCEPT;
+
+ protected:
+ ~public_data() {}
+
+ BOOST_DELETED_FUNCTION(public_data(public_data const&))
+ BOOST_DELETED_FUNCTION(public_data& operator= (public_data const&))
+
+ friend void intrusive_ptr_add_ref(const public_data* p) { ++p->m_ref_counter; }
+ friend void intrusive_ptr_release(const public_data* p) { if (--p->m_ref_counter == 0) public_data::destroy(p); }
+ };
+
+private:
+ //! A pointer to the log record implementation
+ intrusive_ptr< public_data > m_impl;
+
+private:
+ // A private constructor, accessible from record
+ explicit record_view(public_data* impl) : m_impl(impl, false) {}
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+public:
+ /*!
+ * Default constructor. Creates an empty record view that is equivalent to the invalid record handle.
+ *
+ * \post <tt>!*this == true</tt>
+ */
+ BOOST_DEFAULTED_FUNCTION(record_view(), {})
+
+ /*!
+ * Copy constructor
+ */
+ record_view(record_view const& that) BOOST_NOEXCEPT : m_impl(that.m_impl) {}
+
+ /*!
+ * Move constructor. Source record contents unspecified after the operation.
+ */
+ record_view(BOOST_RV_REF(record_view) that) BOOST_NOEXCEPT
+ {
+ m_impl.swap(that.m_impl);
+ }
+
+ /*!
+ * Destructor. Destroys the record, releases any sinks and attribute values that were involved in processing this record.
+ */
+ ~record_view() BOOST_NOEXCEPT {}
+
+ /*!
+ * Copy assignment
+ */
+ record_view& operator= (BOOST_COPY_ASSIGN_REF(record_view) that) BOOST_NOEXCEPT
+ {
+ m_impl = that.m_impl;
+ return *this;
+ }
+
+ /*!
+ * Move assignment. Source record contents unspecified after the operation.
+ */
+ record_view& operator= (BOOST_RV_REF(record_view) that) BOOST_NOEXCEPT
+ {
+ m_impl.swap(that.m_impl);
+ return *this;
+ }
+
+ /*!
+ * \return A reference to the set of attribute values attached to this record
+ *
+ * \pre <tt>!!*this</tt>
+ */
+ attribute_value_set const& attribute_values() const BOOST_NOEXCEPT
+ {
+ return m_impl->m_attribute_values;
+ }
+
+ /*!
+ * Equality comparison
+ *
+ * \param that Comparand
+ * \return \c true if both <tt>*this</tt> and \a that identify the same log record or both do not
+ * identify any record, \c false otherwise.
+ */
+ bool operator== (record_view const& that) const BOOST_NOEXCEPT
+ {
+ return m_impl == that.m_impl;
+ }
+
+ /*!
+ * Inequality comparison
+ *
+ * \param that Comparand
+ * \return <tt>!(*this == that)</tt>
+ */
+ bool operator!= (record_view const& that) const BOOST_NOEXCEPT
+ {
+ return !operator== (that);
+ }
+
+ /*!
+ * Conversion to an unspecified boolean type
+ *
+ * \return \c true, if the <tt>*this</tt> identifies a log record, \c false, if the <tt>*this</tt> is not valid
+ */
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+
+ /*!
+ * Inverted conversion to an unspecified boolean type
+ *
+ * \return \c false, if the <tt>*this</tt> identifies a log record, \c true, if the <tt>*this</tt> is not valid
+ */
+ bool operator! () const BOOST_NOEXCEPT
+ {
+ return !m_impl;
+ }
+
+ /*!
+ * Swaps two handles
+ *
+ * \param that Another record to swap with
+ * <b>Throws:</b> Nothing
+ */
+ void swap(record_view& that) BOOST_NOEXCEPT
+ {
+ m_impl.swap(that.m_impl);
+ }
+
+ /*!
+ * Resets the log record handle. If there are no other handles left, the log record is closed
+ * and all resources referenced by the record are released.
+ *
+ * \post <tt>!*this == true</tt>
+ */
+ void reset() BOOST_NOEXCEPT
+ {
+ m_impl.reset();
+ }
+
+ /*!
+ * Attribute value lookup.
+ *
+ * \param name Attribute name.
+ * \return An \c attribute_value, non-empty if it is found, empty otherwise.
+ */
+ attribute_value_set::mapped_type operator[] (attribute_value_set::key_type name) const
+ {
+ return m_impl->m_attribute_values[name];
+ }
+
+ /*!
+ * Attribute value lookup.
+ *
+ * \param keyword Attribute keyword.
+ * \return A \c value_ref with extracted attribute value if it is found, empty \c value_ref otherwise.
+ */
+ template< typename DescriptorT, template< typename > class ActorT >
+ typename result_of::extract< typename expressions::attribute_keyword< DescriptorT, ActorT >::value_type, DescriptorT >::type
+ operator[] (expressions::attribute_keyword< DescriptorT, ActorT > const& keyword) const
+ {
+ return m_impl->m_attribute_values[keyword];
+ }
+};
+
+/*!
+ * A free-standing swap function overload for \c record_view
+ */
+inline void swap(record_view& left, record_view& right) BOOST_NOEXCEPT
+{
+ left.swap(right);
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_CORE_RECORD_VIEW_HPP_INCLUDED_
diff --git a/boost/log/detail/asio_fwd.hpp b/boost/log/detail/asio_fwd.hpp
new file mode 100644
index 0000000000..e284c24eed
--- /dev/null
+++ b/boost/log/detail/asio_fwd.hpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file asio_fwd.hpp
+ * \author Andrey Semashev
+ * \date 20.04.2008
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ *
+ * The header provides forward declarations of Boost.ASIO that are required for the user's
+ * code to compile with Boost.Log. The forward declarations allow to avoid including the major
+ * part of Boost.ASIO and system headers into user's code.
+ */
+
+#ifndef BOOST_LOG_DETAIL_ASIO_FWD_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_ASIO_FWD_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+namespace asio {
+
+namespace ip {
+
+class address;
+
+} // namespace ip
+
+} // namespace asio
+
+} // namespace boost
+
+#endif // BOOST_LOG_DETAIL_ASIO_FWD_HPP_INCLUDED_
diff --git a/boost/log/detail/attachable_sstream_buf.hpp b/boost/log/detail/attachable_sstream_buf.hpp
new file mode 100644
index 0000000000..9b0a05316d
--- /dev/null
+++ b/boost/log/detail/attachable_sstream_buf.hpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file attachable_sstream_buf.hpp
+ * \author Andrey Semashev
+ * \date 29.07.2007
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_
+#define BOOST_LOG_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_
+
+#include <memory>
+#include <string>
+#include <streambuf>
+#include <boost/assert.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! A streambuf that puts the formatted data to an external string
+template<
+ typename CharT,
+ typename TraitsT = std::char_traits< CharT >,
+ typename AllocatorT = std::allocator< CharT >
+>
+class basic_ostringstreambuf :
+ public std::basic_streambuf< CharT, TraitsT >
+{
+ //! Self type
+ typedef basic_ostringstreambuf< CharT, TraitsT, AllocatorT > this_type;
+ //! Base type
+ typedef std::basic_streambuf< CharT, TraitsT > base_type;
+
+ //! Buffer size
+ enum { buffer_size = 16 };
+
+public:
+ //! Character type
+ typedef typename base_type::char_type char_type;
+ //! Traits type
+ typedef typename base_type::traits_type traits_type;
+ //! String type
+ typedef std::basic_string< char_type, traits_type, AllocatorT > string_type;
+ //! Int type
+ typedef typename base_type::int_type int_type;
+
+private:
+ //! A reference to the string that will be filled
+ string_type* m_Storage;
+ //! A buffer used to temporarily store output
+ char_type m_Buffer[buffer_size];
+
+public:
+ //! Constructor
+ explicit basic_ostringstreambuf() : m_Storage(0)
+ {
+ base_type::setp(m_Buffer, m_Buffer + (sizeof(m_Buffer) / sizeof(*m_Buffer)));
+ }
+ //! Constructor
+ explicit basic_ostringstreambuf(string_type& storage) : m_Storage(boost::addressof(storage))
+ {
+ base_type::setp(m_Buffer, m_Buffer + (sizeof(m_Buffer) / sizeof(*m_Buffer)));
+ }
+
+ //! Clears the buffer to the initial state
+ void clear()
+ {
+ char_type* pBase = this->pbase();
+ char_type* pPtr = this->pptr();
+ if (pBase != pPtr)
+ this->pbump(static_cast< int >(pBase - pPtr));
+ }
+
+ //! Detaches the buffer from the string
+ void detach()
+ {
+ if (m_Storage)
+ {
+ this_type::sync();
+ m_Storage = 0;
+ }
+ }
+
+ //! Attaches the buffer to another string
+ void attach(string_type& storage)
+ {
+ detach();
+ m_Storage = boost::addressof(storage);
+ }
+
+ //! Returns a pointer to the attached string
+ string_type* storage() const { return m_Storage; }
+
+protected:
+ //! Puts all buffered data to the string
+ int sync()
+ {
+ BOOST_ASSERT(m_Storage != 0);
+ char_type* pBase = this->pbase();
+ char_type* pPtr = this->pptr();
+ if (pBase != pPtr)
+ {
+ m_Storage->append(pBase, pPtr);
+ this->pbump(static_cast< int >(pBase - pPtr));
+ }
+ return 0;
+ }
+ //! Puts an unbuffered character to the string
+ int_type overflow(int_type c)
+ {
+ BOOST_ASSERT(m_Storage != 0);
+ basic_ostringstreambuf::sync();
+ if (!traits_type::eq_int_type(c, traits_type::eof()))
+ {
+ m_Storage->push_back(traits_type::to_char_type(c));
+ return c;
+ }
+ else
+ return traits_type::not_eof(c);
+ }
+ //! Puts a character sequence to the string
+ std::streamsize xsputn(const char_type* s, std::streamsize n)
+ {
+ BOOST_ASSERT(m_Storage != 0);
+ basic_ostringstreambuf::sync();
+ typedef typename string_type::size_type string_size_type;
+ const string_size_type max_storage_left =
+ m_Storage->max_size() - m_Storage->size();
+ if (static_cast< string_size_type >(n) < max_storage_left)
+ {
+ m_Storage->append(s, static_cast< string_size_type >(n));
+ return n;
+ }
+ else
+ {
+ m_Storage->append(s, max_storage_left);
+ return static_cast< std::streamsize >(max_storage_left);
+ }
+ }
+
+ //! Copy constructor (closed)
+ BOOST_DELETED_FUNCTION(basic_ostringstreambuf(basic_ostringstreambuf const& that))
+ //! Assignment (closed)
+ BOOST_DELETED_FUNCTION(basic_ostringstreambuf& operator= (basic_ostringstreambuf const& that))
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_
diff --git a/boost/log/detail/attr_output_impl.hpp b/boost/log/detail/attr_output_impl.hpp
new file mode 100644
index 0000000000..8f00736c5f
--- /dev/null
+++ b/boost/log/detail/attr_output_impl.hpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file attr_output_impl.hpp
+ * \author Andrey Semashev
+ * \date 12.08.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_ATTR_OUTPUT_IMPL_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_ATTR_OUTPUT_IMPL_HPP_INCLUDED_
+
+#include <boost/mpl/is_sequence.hpp>
+#include <boost/phoenix/core/actor.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/expressions/attr.hpp>
+#include <boost/log/utility/functional/bind_to_log.hpp>
+#include <boost/log/detail/attr_output_terminal.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+namespace aux {
+
+template< typename LeftT, typename T, typename FallbackPolicyT, typename TagT >
+struct make_output_expression
+{
+ //! Resulting expression
+ typedef attribute_output_terminal< LeftT, T, FallbackPolicyT, to_log_fun< TagT > > type;
+
+ //! Creates the output expression
+ template< typename RightT >
+ static BOOST_FORCEINLINE type make(LeftT const& left, RightT const& right)
+ {
+ return type(left, right.get_name(), to_log_fun< TagT >(), right.get_fallback_policy());
+ }
+};
+
+template< typename LeftT, typename RightT, typename ValueT = typename RightT::value_type, bool IsSequenceV = mpl::is_sequence< ValueT >::value >
+struct make_output_actor;
+
+template< template< typename > class ActorT, typename LeftExprT, typename RightT, typename ValueT >
+struct make_output_actor< ActorT< LeftExprT >, RightT, ValueT, false >
+{
+ typedef make_output_expression<
+ ActorT< LeftExprT >,
+ ValueT,
+ typename RightT::fallback_policy,
+ typename RightT::tag_type
+ > make_expression;
+
+ typedef ActorT< typename make_expression::type > type;
+
+ static BOOST_FORCEINLINE type make(ActorT< LeftExprT > const& left, RightT const& right)
+ {
+ type res = {{ make_expression::make(left, right) }};
+ return res;
+ }
+};
+
+template< template< typename > class ActorT, typename LeftExprT, typename RightT, typename ValueT >
+struct make_output_actor< ActorT< LeftExprT >, RightT, ValueT, true >
+{
+ typedef attribute_output_terminal< ActorT< LeftExprT >, ValueT, typename RightT::fallback_policy, to_log_fun< typename RightT::tag_type > > expression_type;
+
+ typedef ActorT< expression_type > type;
+
+ static BOOST_FORCEINLINE type make(ActorT< LeftExprT > const& left, RightT const& right)
+ {
+ type res = {{ expression_type(left, right.get_name(), to_log_fun< typename RightT::tag_type >(), right.get_fallback_policy()) }};
+ return res;
+ }
+};
+
+} // namespace aux
+
+#define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\
+ template< typename LeftExprT, typename T, typename FallbackPolicyT, typename TagT >\
+ BOOST_FORCEINLINE typename aux::make_output_actor< phoenix::actor< LeftExprT >, attribute_actor< T, FallbackPolicyT, TagT, phoenix::actor > >::type\
+ operator<< (phoenix::actor< LeftExprT > left_ref left, attribute_actor< T, FallbackPolicyT, TagT, phoenix::actor > right_ref right)\
+ {\
+ return aux::make_output_actor< phoenix::actor< LeftExprT >, attribute_actor< T, FallbackPolicyT, TagT, phoenix::actor > >::make(left, right);\
+ }
+
+#include <boost/log/detail/generate_overloads.hpp>
+
+#undef BOOST_LOG_AUX_OVERLOAD
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_ATTR_OUTPUT_IMPL_HPP_INCLUDED_
diff --git a/boost/log/detail/attr_output_terminal.hpp b/boost/log/detail/attr_output_terminal.hpp
new file mode 100644
index 0000000000..574993aace
--- /dev/null
+++ b/boost/log/detail/attr_output_terminal.hpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file attribute_output_terminal.hpp
+ * \author Andrey Semashev
+ * \date 06.11.2012
+ *
+ * The header contains implementation of a generic output manipulator in template expressions.
+ */
+
+#ifndef BOOST_LOG_DETAIL_ATTR_OUTPUT_TERMINAL_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_ATTR_OUTPUT_TERMINAL_HPP_INCLUDED_
+
+#include <boost/mpl/bool.hpp>
+#include <boost/phoenix/core/actor.hpp>
+#include <boost/phoenix/core/meta_grammar.hpp>
+#include <boost/phoenix/core/environment.hpp>
+#include <boost/phoenix/core/terminal_fwd.hpp>
+#include <boost/phoenix/core/is_nullary.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/fusion/sequence/intrinsic/at.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/custom_terminal_spec.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/value_visitation.hpp>
+#include <boost/log/utility/functional/bind.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+namespace aux {
+
+//! Attribute stream output expression
+template< typename LeftT, typename T, typename FallbackPolicyT, typename ImplT >
+class attribute_output_terminal
+{
+private:
+ //! Self type
+ typedef attribute_output_terminal< LeftT, T, FallbackPolicyT, ImplT > this_type;
+ //! Attribute value visitor invoker
+ typedef value_visitor_invoker< T, FallbackPolicyT > visitor_invoker_type;
+ //! Manipulator implementation
+ typedef ImplT impl_type;
+
+public:
+ //! Internal typedef for type categorization
+ typedef void _is_boost_log_terminal;
+
+ //! Result type definition
+ template< typename >
+ struct result;
+
+ template< typename ThisT, typename ContextT >
+ struct result< ThisT(ContextT) >
+ {
+ typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type;
+ typedef typename phoenix::evaluator::impl<
+ typename LeftT::proto_base_expr&,
+ context_type,
+ phoenix::unused
+ >::result_type type;
+ };
+
+private:
+ //! Left argument actor
+ LeftT m_left;
+ //! Attribute name
+ const attribute_name m_name;
+ //! Attribute value visitor invoker
+ visitor_invoker_type m_visitor_invoker;
+ //! Manipulator implementation
+ impl_type m_impl;
+
+public:
+ //! Initializing constructor
+ attribute_output_terminal(LeftT const& left, attribute_name const& name) : m_left(left), m_name(name)
+ {
+ }
+
+ //! Initializing constructor
+ attribute_output_terminal(LeftT const& left, attribute_name const& name, impl_type const& impl) : m_left(left), m_name(name), m_impl(impl)
+ {
+ }
+
+ //! Initializing constructor
+ template< typename U >
+ attribute_output_terminal(LeftT const& left, attribute_name const& name, impl_type const& impl, U const& arg) :
+ m_left(left), m_name(name), m_visitor_invoker(arg), m_impl(impl)
+ {
+ }
+
+ //! Copy constructor
+ attribute_output_terminal(attribute_output_terminal const& that) :
+ m_left(that.m_left), m_name(that.m_name), m_visitor_invoker(that.m_visitor_invoker), m_impl(that.m_impl)
+ {
+ }
+
+ //! Invokation operator
+ template< typename ContextT >
+ typename result< this_type(ContextT const&) >::type operator() (ContextT const& ctx)
+ {
+ typedef typename result< this_type(ContextT const&) >::type result_type;
+ result_type strm = phoenix::eval(m_left, ctx);
+ m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< impl_type&, result_type >(m_impl, strm));
+ return strm;
+ }
+
+ //! Invokation operator
+ template< typename ContextT >
+ typename result< const this_type(ContextT const&) >::type operator() (ContextT const& ctx) const
+ {
+ typedef typename result< const this_type(ContextT const&) >::type result_type;
+ result_type strm = phoenix::eval(m_left, ctx);
+ m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< impl_type const&, result_type >(m_impl, strm));
+ return strm;
+ }
+
+ BOOST_DELETED_FUNCTION(attribute_output_terminal())
+};
+
+} // namespace aux
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+namespace phoenix {
+
+namespace result_of {
+
+template< typename LeftT, typename T, typename FallbackPolicyT, typename ImplT >
+struct is_nullary< custom_terminal< boost::log::expressions::aux::attribute_output_terminal< LeftT, T, FallbackPolicyT, ImplT > > > :
+ public mpl::false_
+{
+};
+
+} // namespace result_of
+
+} // namespace phoenix
+
+#endif // !defined(BOOST_LOG_DOXYGEN_PASS)
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_ATTR_OUTPUT_TERMINAL_HPP_INCLUDED_
diff --git a/boost/log/detail/attribute_get_value_impl.hpp b/boost/log/detail/attribute_get_value_impl.hpp
new file mode 100644
index 0000000000..2058d65242
--- /dev/null
+++ b/boost/log/detail/attribute_get_value_impl.hpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file attribute_get_value_impl.hpp
+ * \author Andrey Semashev
+ * \date 04.08.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_ATTRIBUTE_GET_VALUE_IMPL_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_ATTRIBUTE_GET_VALUE_IMPL_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/attributes/attribute_value.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+inline attribute_value attribute::get_value() const
+{
+ return m_pImpl->get_value();
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_ATTRIBUTE_GET_VALUE_IMPL_HPP_INCLUDED_
diff --git a/boost/log/detail/attribute_predicate.hpp b/boost/log/detail/attribute_predicate.hpp
new file mode 100644
index 0000000000..a0978632a2
--- /dev/null
+++ b/boost/log/detail/attribute_predicate.hpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file attribute_predicate.hpp
+ * \author Andrey Semashev
+ * \date 02.09.2012
+ *
+ * The header contains implementation of a generic predicate in template expressions.
+ */
+
+#ifndef BOOST_LOG_DETAIL_ATTRIBUTE_PREDICATE_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_ATTRIBUTE_PREDICATE_HPP_INCLUDED_
+
+#include <boost/phoenix/core/actor.hpp>
+#include <boost/utility/result_of.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/value_visitation.hpp>
+#include <boost/log/attributes/fallback_policy.hpp>
+#include <boost/log/utility/functional/bind.hpp>
+#include <boost/log/utility/functional/save_result.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+namespace aux {
+
+/*!
+ * The predicate checks if the attribute value satisfies a predicate.
+ */
+template< typename T, typename ArgT, typename PredicateT, typename FallbackPolicyT = fallback_to_none >
+class attribute_predicate
+{
+public:
+ //! Function result_type
+ typedef bool result_type;
+ //! Expected attribute value type
+ typedef T value_type;
+ //! Predicate type
+ typedef PredicateT predicate_type;
+ //! Argument type for the predicate
+ typedef ArgT argument_type;
+ //! Fallback policy
+ typedef FallbackPolicyT fallback_policy;
+
+private:
+ //! Argument for the predicate
+ const argument_type m_arg;
+ //! Attribute value name
+ const attribute_name m_name;
+ //! Visitor invoker
+ value_visitor_invoker< value_type, fallback_policy > m_visitor_invoker;
+
+public:
+ /*!
+ * Initializing constructor
+ *
+ * \param name Attribute name
+ * \param pred_arg The predicate argument
+ */
+ attribute_predicate(attribute_name const& name, argument_type const& pred_arg) : m_arg(pred_arg), m_name(name)
+ {
+ }
+
+ /*!
+ * Initializing constructor
+ *
+ * \param name Attribute name
+ * \param pred_arg The predicate argument
+ * \param arg Additional parameter for the fallback policy
+ */
+ template< typename U >
+ attribute_predicate(attribute_name const& name, argument_type const& pred_arg, U const& arg) : m_arg(pred_arg), m_name(name), m_visitor_invoker(arg)
+ {
+ }
+
+ /*!
+ * Checking operator
+ *
+ * \param arg A set of attribute values or a log record
+ * \return \c true if the log record contains the sought attribute value, \c false otherwise
+ */
+ template< typename ArgumentT >
+ result_type operator() (ArgumentT const& arg) const
+ {
+ typedef binder2nd< predicate_type, argument_type const& > visitor_type;
+
+ bool res = false;
+ m_visitor_invoker(m_name, arg, boost::log::save_result(visitor_type(predicate_type(), m_arg), res));
+ return res;
+ }
+};
+
+} // namespace aux
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_ATTRIBUTE_PREDICATE_HPP_INCLUDED_
diff --git a/boost/log/detail/cleanup_scope_guard.hpp b/boost/log/detail/cleanup_scope_guard.hpp
new file mode 100644
index 0000000000..dd2c0e170a
--- /dev/null
+++ b/boost/log/detail/cleanup_scope_guard.hpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file cleanup_scope_guard.hpp
+ * \author Andrey Semashev
+ * \date 11.03.2008
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_CLEANUP_SCOPE_GUARD_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_CLEANUP_SCOPE_GUARD_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! Cleanup scope guard
+template< typename T >
+struct cleanup_guard
+{
+ explicit cleanup_guard(T& obj) : m_Obj(obj) {}
+ ~cleanup_guard() { m_Obj.clear(); }
+
+ // Copying prohibited
+ BOOST_DELETED_FUNCTION(cleanup_guard(cleanup_guard const&))
+ BOOST_DELETED_FUNCTION(cleanup_guard& operator= (cleanup_guard const&))
+
+private:
+ T& m_Obj;
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_CLEANUP_SCOPE_GUARD_HPP_INCLUDED_
diff --git a/boost/log/detail/code_conversion.hpp b/boost/log/detail/code_conversion.hpp
new file mode 100644
index 0000000000..d49988bc21
--- /dev/null
+++ b/boost/log/detail/code_conversion.hpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file code_conversion.hpp
+ * \author Andrey Semashev
+ * \date 08.11.2008
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_CODE_CONVERSION_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_CODE_CONVERSION_HPP_INCLUDED_
+
+#include <locale>
+#include <string>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! The function converts one string to the character type of another
+BOOST_LOG_API void code_convert(const wchar_t* str1, std::size_t len, std::string& str2, std::locale const& loc = std::locale());
+//! The function converts one string to the character type of another
+BOOST_LOG_API void code_convert(const char* str1, std::size_t len, std::wstring& str2, std::locale const& loc = std::locale());
+#if !defined(BOOST_NO_CXX11_CHAR16_T)
+//! The function converts one string to the character type of another
+BOOST_LOG_API void code_convert(const char16_t* str1, std::size_t len, std::string& str2, std::locale const& loc = std::locale());
+//! The function converts one string to the character type of another
+BOOST_LOG_API void code_convert(const char* str1, std::size_t len, std::u16string& str2, std::locale const& loc = std::locale());
+#endif
+#if !defined(BOOST_NO_CXX11_CHAR32_T)
+//! The function converts one string to the character type of another
+BOOST_LOG_API void code_convert(const char32_t* str1, std::size_t len, std::string& str2, std::locale const& loc = std::locale());
+//! The function converts one string to the character type of another
+BOOST_LOG_API void code_convert(const char* str1, std::size_t len, std::u32string& str2, std::locale const& loc = std::locale());
+#endif
+
+//! The function converts one string to the character type of another
+template< typename CharT, typename SourceTraitsT, typename SourceAllocatorT, typename TargetTraitsT, typename TargetAllocatorT >
+inline void code_convert(std::basic_string< CharT, SourceTraitsT, SourceAllocatorT > const& str1, std::basic_string< CharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& = std::locale())
+{
+ str2.append(str1.c_str(), str1.size());
+}
+//! The function converts one string to the character type of another
+template< typename CharT, typename TargetTraitsT, typename TargetAllocatorT >
+inline void code_convert(const CharT* str1, std::size_t len, std::basic_string< CharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& = std::locale())
+{
+ str2.append(str1, len);
+}
+
+//! The function converts one string to the character type of another
+template< typename SourceCharT, typename SourceTraitsT, typename SourceAllocatorT, typename TargetCharT, typename TargetTraitsT, typename TargetAllocatorT >
+inline void code_convert(std::basic_string< SourceCharT, SourceTraitsT, SourceAllocatorT > const& str1, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& loc = std::locale())
+{
+ aux::code_convert(str1.c_str(), str1.size(), str2, loc);
+}
+
+//! The function converts the passed string to the narrow-character encoding
+inline std::string const& to_narrow(std::string const& str)
+{
+ return str;
+}
+
+//! The function converts the passed string to the narrow-character encoding
+inline std::string const& to_narrow(std::string const& str, std::locale const&)
+{
+ return str;
+}
+
+//! The function converts the passed string to the narrow-character encoding
+inline std::string to_narrow(std::wstring const& str, std::locale const& loc = std::locale())
+{
+ std::string res;
+ aux::code_convert(str, res, loc);
+ return res;
+}
+
+//! The function converts the passed string to the wide-character encoding
+inline std::wstring const& to_wide(std::wstring const& str)
+{
+ return str;
+}
+
+//! The function converts the passed string to the wide-character encoding
+inline std::wstring const& to_wide(std::wstring const& str, std::locale const&)
+{
+ return str;
+}
+
+//! The function converts the passed string to the wide-character encoding
+inline std::wstring to_wide(std::string const& str, std::locale const& loc = std::locale())
+{
+ std::wstring res;
+ aux::code_convert(str, res, loc);
+ return res;
+}
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_CODE_CONVERSION_HPP_INCLUDED_
diff --git a/boost/log/detail/config.hpp b/boost/log/detail/config.hpp
new file mode 100644
index 0000000000..4d1e66b73c
--- /dev/null
+++ b/boost/log/detail/config.hpp
@@ -0,0 +1,351 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file config.hpp
+ * \author Andrey Semashev
+ * \date 08.03.2007
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. In this file
+ * internal configuration macros are defined.
+ */
+
+#ifndef BOOST_LOG_DETAIL_CONFIG_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_CONFIG_HPP_INCLUDED_
+
+// This check must be before any system headers are included, or __MSVCRT_VERSION__ may get defined to 0x0600
+#if defined(__MINGW32__) && !defined(__MSVCRT_VERSION__)
+// Target MinGW headers to at least MSVC 7.0 runtime by default. This will enable some useful functions.
+#define __MSVCRT_VERSION__ 0x0700
+#endif
+
+#include <limits.h> // To bring in libc macros
+#include <boost/config.hpp>
+
+#if defined(BOOST_NO_RTTI)
+# error Boost.Log: RTTI is required by the library
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER >= 1600
+# define BOOST_LOG_HAS_PRAGMA_DETECT_MISMATCH
+#endif
+
+#if defined(BOOST_LOG_HAS_PRAGMA_DETECT_MISMATCH)
+#include <boost/preprocessor/stringize.hpp>
+#endif
+
+#if !defined(BOOST_WINDOWS)
+# ifndef BOOST_LOG_WITHOUT_DEBUG_OUTPUT
+# define BOOST_LOG_WITHOUT_DEBUG_OUTPUT
+# endif
+# ifndef BOOST_LOG_WITHOUT_EVENT_LOG
+# define BOOST_LOG_WITHOUT_EVENT_LOG
+# endif
+#endif
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(BOOST_MSVC)
+ // For some reason MSVC 9.0 fails to link the library if static integral constants are defined in cpp
+# define BOOST_LOG_BROKEN_STATIC_CONSTANTS_LINKAGE
+# if _MSC_VER <= 1310
+ // MSVC 7.1 sometimes fails to match out-of-class template function definitions with
+ // their declarations if the return type or arguments of the functions involve typename keyword
+ // and depend on the template parameters.
+# define BOOST_LOG_BROKEN_TEMPLATE_DEFINITION_MATCHING
+# endif
+# if _MSC_VER <= 1400
+ // Older MSVC versions reject friend declarations for class template specializations
+# define BOOST_LOG_BROKEN_FRIEND_TEMPLATE_SPECIALIZATIONS
+# endif
+# if _MSC_VER <= 1600
+ // MSVC up to 10.0 attempts to invoke copy constructor when initializing a const reference from rvalue returned from a function.
+ // This fails when the returned value cannot be copied (only moved):
+ //
+ // class base {};
+ // class derived : public base { BOOST_MOVABLE_BUT_NOT_COPYABLE(derived) };
+ // derived foo();
+ // base const& var = foo(); // attempts to call copy constructor of derived
+# define BOOST_LOG_BROKEN_REFERENCE_FROM_RVALUE_INIT
+# endif
+# if !defined(_STLPORT_VERSION)
+ // MSVC 9.0 mandates packaging of STL classes, which apparently affects alignment and
+ // makes alignment_of< T >::value no longer be a power of 2 for types that derive from STL classes.
+ // This breaks type_with_alignment and everything that relies on it.
+ // This doesn't happen with non-native STLs, such as STLPort. Strangely, this doesn't show with
+ // STL classes themselves or most of the user-defined derived classes.
+ // Not sure if that happens with other MSVC versions.
+ // See: http://svn.boost.org/trac/boost/ticket/1946
+# define BOOST_LOG_BROKEN_STL_ALIGNMENT
+# endif
+#endif
+
+#if defined(BOOST_INTEL) || defined(__SUNPRO_CC)
+ // Intel compiler and Sun Studio 12.3 have problems with friend declarations for nested class templates
+# define BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS
+#endif
+
+#if defined(BOOST_MSVC) && BOOST_MSVC <= 1600
+ // MSVC cannot interpret constant expressions in certain contexts, such as non-type template parameters
+# define BOOST_LOG_BROKEN_CONSTANT_EXPRESSIONS
+#endif
+
+#if defined(__CYGWIN__)
+ // Boost.ASIO is broken on Cygwin
+# define BOOST_LOG_NO_ASIO
+#endif
+
+#if !defined(BOOST_LOG_USE_NATIVE_SYSLOG) && defined(BOOST_LOG_NO_ASIO)
+# ifndef BOOST_LOG_WITHOUT_SYSLOG
+# define BOOST_LOG_WITHOUT_SYSLOG
+# endif
+#endif
+
+#if defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ <= 2)
+ // GCC 4.1 and 4.2 have buggy anonymous namespaces support, which interferes with symbol linkage
+# define BOOST_LOG_ANONYMOUS_NAMESPACE namespace anonymous {} using namespace anonymous; namespace anonymous
+#else
+# define BOOST_LOG_ANONYMOUS_NAMESPACE namespace
+#endif
+
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || (defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ <= 6))
+// GCC up to 4.6 (inclusively) did not support expanding template argument packs into non-variadic template arguments
+#define BOOST_LOG_NO_CXX11_ARG_PACKS_TO_NON_VARIADIC_ARGS_EXPANSION
+#endif
+
+#if defined(_MSC_VER)
+# define BOOST_LOG_NO_VTABLE __declspec(novtable)
+#elif defined(__GNUC__)
+# define BOOST_LOG_NO_VTABLE
+#else
+# define BOOST_LOG_NO_VTABLE
+#endif
+
+// An MS-like compilers' extension that allows to optimize away the needless code
+#if defined(_MSC_VER)
+# define BOOST_LOG_ASSUME(expr) __assume(expr)
+#else
+# define BOOST_LOG_ASSUME(expr)
+#endif
+
+// The statement marking unreachable branches of code to avoid warnings
+#if defined(BOOST_CLANG)
+# if __has_builtin(__builtin_unreachable)
+# define BOOST_LOG_UNREACHABLE() __builtin_unreachable()
+# endif
+#elif defined(__GNUC__)
+# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
+# define BOOST_LOG_UNREACHABLE() __builtin_unreachable()
+# endif
+#elif defined(_MSC_VER)
+# define BOOST_LOG_UNREACHABLE() __assume(0)
+#endif
+#if !defined(BOOST_LOG_UNREACHABLE)
+# define BOOST_LOG_UNREACHABLE()
+# define BOOST_LOG_UNREACHABLE_RETURN(r) return r
+#else
+# define BOOST_LOG_UNREACHABLE_RETURN(r) BOOST_LOG_UNREACHABLE()
+#endif
+
+// Some compilers support a special attribute that shows that a function won't return
+#if defined(__GNUC__) || (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x590)
+ // GCC and Sun Studio 12 support attribute syntax
+# define BOOST_LOG_NORETURN __attribute__((noreturn))
+#elif defined (_MSC_VER)
+ // Microsoft-compatible compilers go here
+# define BOOST_LOG_NORETURN __declspec(noreturn)
+#else
+ // The rest compilers might emit bogus warnings about missing return statements
+ // in functions with non-void return types when throw_exception is used.
+# define BOOST_LOG_NORETURN
+#endif
+
+#if !defined(BOOST_LOG_BUILDING_THE_LIB)
+
+// Detect if we're dealing with dll
+# if defined(BOOST_LOG_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)
+# define BOOST_LOG_DLL
+# endif
+
+# if defined(BOOST_LOG_DLL)
+# if defined(BOOST_SYMBOL_IMPORT)
+# define BOOST_LOG_API BOOST_SYMBOL_IMPORT
+# elif defined(BOOST_HAS_DECLSPEC)
+# define BOOST_LOG_API __declspec(dllimport)
+# endif
+# endif
+# ifndef BOOST_LOG_API
+# define BOOST_LOG_API
+# endif
+//
+// Automatically link to the correct build variant where possible.
+//
+# if !defined(BOOST_ALL_NO_LIB)
+# if !defined(BOOST_LOG_NO_LIB)
+# define BOOST_LIB_NAME boost_log
+# if defined(BOOST_LOG_DLL)
+# define BOOST_DYN_LINK
+# endif
+# include <boost/config/auto_link.hpp>
+# endif
+ // In static-library builds compilers ignore auto-link comments from Boost.Log binary to
+ // other Boost libraries. We explicitly add comments here for other libraries.
+ // In dynamic-library builds this is not needed.
+# if !defined(BOOST_LOG_DLL)
+# include <boost/system/config.hpp>
+# include <boost/filesystem/config.hpp>
+# if !defined(BOOST_DATE_TIME_NO_LIB) && !defined(BOOST_DATE_TIME_SOURCE)
+# define BOOST_LIB_NAME boost_date_time
+# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_DATE_TIME_DYN_LINK)
+# define BOOST_DYN_LINK
+# endif
+# include <boost/config/auto_link.hpp>
+# endif
+ // Boost.Thread's config is included below, if needed
+# endif
+# endif // auto-linking disabled
+
+#else // !defined(BOOST_LOG_BUILDING_THE_LIB)
+
+# if defined(BOOST_LOG_DLL)
+# if defined(BOOST_SYMBOL_EXPORT)
+# define BOOST_LOG_API BOOST_SYMBOL_EXPORT
+# elif defined(BOOST_HAS_DECLSPEC)
+# define BOOST_LOG_API __declspec(dllexport)
+# endif
+# endif
+# ifndef BOOST_LOG_API
+# define BOOST_LOG_API BOOST_SYMBOL_VISIBLE
+# endif
+
+#endif // !defined(BOOST_LOG_BUILDING_THE_LIB)
+
+// By default we provide support for both char and wchar_t
+#if !defined(BOOST_LOG_WITHOUT_CHAR)
+# define BOOST_LOG_USE_CHAR
+#endif
+#if !defined(BOOST_LOG_WITHOUT_WCHAR_T)
+# define BOOST_LOG_USE_WCHAR_T
+#endif
+
+#if !defined(BOOST_LOG_DOXYGEN_PASS)
+ // Check if multithreading is supported
+# if !defined(BOOST_LOG_NO_THREADS) && !defined(BOOST_HAS_THREADS)
+# define BOOST_LOG_NO_THREADS
+# endif // !defined(BOOST_LOG_NO_THREADS) && !defined(BOOST_HAS_THREADS)
+#endif // !defined(BOOST_LOG_DOXYGEN_PASS)
+
+#if !defined(BOOST_LOG_NO_THREADS)
+ // We need this header to (i) enable auto-linking with Boost.Thread and
+ // (ii) to bring in configuration macros of Boost.Thread.
+# include <boost/thread/detail/config.hpp>
+#endif // !defined(BOOST_LOG_NO_THREADS)
+
+#if !defined(BOOST_LOG_NO_THREADS)
+# define BOOST_LOG_EXPR_IF_MT(expr) expr
+#else
+# undef BOOST_LOG_USE_COMPILER_TLS
+# define BOOST_LOG_EXPR_IF_MT(expr)
+#endif // !defined(BOOST_LOG_NO_THREADS)
+
+#if defined(BOOST_LOG_USE_COMPILER_TLS)
+# if defined(__GNUC__) || defined(__SUNPRO_CC)
+# define BOOST_LOG_TLS __thread
+# elif defined(BOOST_MSVC)
+# define BOOST_LOG_TLS __declspec(thread)
+# else
+# undef BOOST_LOG_USE_COMPILER_TLS
+# endif
+#endif // defined(BOOST_LOG_USE_COMPILER_TLS)
+
+#ifndef BOOST_LOG_CPU_CACHE_LINE_SIZE
+//! The macro defines the CPU cache line size for the target architecture. This is mostly used for optimization.
+#define BOOST_LOG_CPU_CACHE_LINE_SIZE 64
+#endif
+
+namespace boost {
+
+// Setup namespace name
+#if !defined(BOOST_LOG_DOXYGEN_PASS)
+# if defined(BOOST_LOG_DLL)
+# if defined(BOOST_LOG_NO_THREADS)
+# define BOOST_LOG_VERSION_NAMESPACE v2_st
+# else
+# if defined(BOOST_THREAD_PLATFORM_PTHREAD)
+# define BOOST_LOG_VERSION_NAMESPACE v2_mt_posix
+# elif defined(BOOST_THREAD_PLATFORM_WIN32)
+# if defined(BOOST_LOG_USE_WINNT6_API)
+# define BOOST_LOG_VERSION_NAMESPACE v2_mt_nt6
+# else
+# define BOOST_LOG_VERSION_NAMESPACE v2_mt_nt5
+# endif // defined(BOOST_LOG_USE_WINNT6_API)
+# else
+# define BOOST_LOG_VERSION_NAMESPACE v2_mt
+# endif
+# endif // defined(BOOST_LOG_NO_THREADS)
+# else
+# if defined(BOOST_LOG_NO_THREADS)
+# define BOOST_LOG_VERSION_NAMESPACE v2s_st
+# else
+# if defined(BOOST_THREAD_PLATFORM_PTHREAD)
+# define BOOST_LOG_VERSION_NAMESPACE v2s_mt_posix
+# elif defined(BOOST_THREAD_PLATFORM_WIN32)
+# if defined(BOOST_LOG_USE_WINNT6_API)
+# define BOOST_LOG_VERSION_NAMESPACE v2s_mt_nt6
+# else
+# define BOOST_LOG_VERSION_NAMESPACE v2s_mt_nt5
+# endif // defined(BOOST_LOG_USE_WINNT6_API)
+# else
+# define BOOST_LOG_VERSION_NAMESPACE v2s_mt
+# endif
+# endif // defined(BOOST_LOG_NO_THREADS)
+# endif // defined(BOOST_LOG_DLL)
+
+
+namespace log {
+
+# if !defined(BOOST_NO_CXX11_INLINE_NAMESPACES)
+
+inline namespace BOOST_LOG_VERSION_NAMESPACE {}
+}
+
+# define BOOST_LOG_OPEN_NAMESPACE namespace log { inline namespace BOOST_LOG_VERSION_NAMESPACE {
+# define BOOST_LOG_CLOSE_NAMESPACE }}
+
+# else
+
+namespace BOOST_LOG_VERSION_NAMESPACE {}
+
+using namespace BOOST_LOG_VERSION_NAMESPACE
+# if defined(__GNUC__) && (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) && !defined(__clang__)
+__attribute__((__strong__))
+# endif
+;
+
+}
+
+# define BOOST_LOG_OPEN_NAMESPACE namespace log { namespace BOOST_LOG_VERSION_NAMESPACE {
+# define BOOST_LOG_CLOSE_NAMESPACE }}
+# endif
+
+#else // !defined(BOOST_LOG_DOXYGEN_PASS)
+
+namespace log {}
+# define BOOST_LOG_OPEN_NAMESPACE namespace log {
+# define BOOST_LOG_CLOSE_NAMESPACE }
+
+#endif // !defined(BOOST_LOG_DOXYGEN_PASS)
+
+#if defined(BOOST_LOG_HAS_PRAGMA_DETECT_MISMATCH)
+#pragma detect_mismatch("boost_log_abi", BOOST_PP_STRINGIZE(BOOST_LOG_VERSION_NAMESPACE))
+#endif
+
+} // namespace boost
+
+#endif // BOOST_LOG_DETAIL_CONFIG_HPP_INCLUDED_
diff --git a/boost/log/detail/copy_cv.hpp b/boost/log/detail/copy_cv.hpp
new file mode 100644
index 0000000000..a6a4ebae04
--- /dev/null
+++ b/boost/log/detail/copy_cv.hpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file copy_cv.hpp
+ * \author Andrey Semashev
+ * \date 16.03.2014
+ *
+ * The header defines \c copy_cv type trait which copies const/volatile qualifiers from one type to another
+ */
+
+#ifndef BOOST_LOG_DETAIL_COPY_CV_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_COPY_CV_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! The type trait copies top level const/volatile qualifiers from \c FromT to \c ToT
+template< typename FromT, typename ToT >
+struct copy_cv
+{
+ typedef ToT type;
+};
+
+template< typename FromT, typename ToT >
+struct copy_cv< const FromT, ToT >
+{
+ typedef const ToT type;
+};
+
+template< typename FromT, typename ToT >
+struct copy_cv< volatile FromT, ToT >
+{
+ typedef volatile ToT type;
+};
+
+template< typename FromT, typename ToT >
+struct copy_cv< const volatile FromT, ToT >
+{
+ typedef const volatile ToT type;
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_COPY_CV_HPP_INCLUDED_
diff --git a/boost/log/detail/custom_terminal_spec.hpp b/boost/log/detail/custom_terminal_spec.hpp
new file mode 100644
index 0000000000..fb43357b00
--- /dev/null
+++ b/boost/log/detail/custom_terminal_spec.hpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file custom_terminal_spec.hpp
+ * \author Andrey Semashev
+ * \date 29.01.2012
+ *
+ * The header contains Boost.Phoenix custom terminal specialization for Boost.Log terminals.
+ */
+
+#ifndef BOOST_LOG_DETAIL_CUSTOM_TERMINAL_SPEC_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_CUSTOM_TERMINAL_SPEC_HPP_INCLUDED_
+
+#include <boost/mpl/bool.hpp>
+#include <boost/phoenix/core/terminal_fwd.hpp>
+#include <boost/phoenix/core/is_nullary.hpp>
+#include <boost/phoenix/core/terminal.hpp> // needed for terminal-related part of the grammar
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/utility/result_of.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+namespace phoenix {
+
+template< typename T >
+struct is_custom_terminal< T, typename T::_is_boost_log_terminal > :
+ public mpl::true_
+{
+};
+
+template< typename T >
+struct custom_terminal< T, typename T::_is_boost_log_terminal >
+{
+ typedef custom_terminal< T, typename T::_is_boost_log_terminal > this_type;
+
+ template< typename >
+ struct result;
+
+ template< typename ThisT, typename TermT, typename ContextT >
+ struct result< ThisT(TermT, ContextT) >
+ {
+ typedef typename remove_cv< typename remove_reference< TermT >::type >::type term;
+ typedef typename boost::result_of< const term(ContextT) >::type type;
+ };
+
+ template< typename ContextT >
+ typename result< const this_type(T const&, ContextT&) >::type operator() (T const& term, ContextT& ctx) const
+ {
+ return term(ctx);
+ }
+};
+
+} // namespace phoenix
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_CUSTOM_TERMINAL_SPEC_HPP_INCLUDED_
diff --git a/boost/log/detail/date_time_fmt_gen_traits_fwd.hpp b/boost/log/detail/date_time_fmt_gen_traits_fwd.hpp
new file mode 100644
index 0000000000..a80930b2ae
--- /dev/null
+++ b/boost/log/detail/date_time_fmt_gen_traits_fwd.hpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file date_time_fmt_gen_traits_fwd.hpp
+ * \author Andrey Semashev
+ * \date 07.11.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_DATE_TIME_FMT_GEN_TRAITS_FWD_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_DATE_TIME_FMT_GEN_TRAITS_FWD_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+namespace aux {
+
+template< typename T, typename CharT, typename VoidT = void >
+struct date_time_formatter_generator_traits;
+
+} // namespace aux
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_DETAIL_DATE_TIME_FMT_GEN_TRAITS_FWD_HPP_INCLUDED_
diff --git a/boost/log/detail/date_time_format_parser.hpp b/boost/log/detail/date_time_format_parser.hpp
new file mode 100644
index 0000000000..7b82d5556a
--- /dev/null
+++ b/boost/log/detail/date_time_format_parser.hpp
@@ -0,0 +1,486 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file date_time_format_parser.hpp
+ * \author Andrey Semashev
+ * \date 16.09.2012
+ *
+ * The header contains a parser for date and time format strings.
+ */
+
+#ifndef BOOST_LOG_DETAIL_DATE_TIME_FORMAT_PARSER_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_DATE_TIME_FORMAT_PARSER_HPP_INCLUDED_
+
+#include <string>
+#include <boost/range/as_literal.hpp>
+#include <boost/range/iterator_range_core.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+/*!
+ * This is the interface the parser will use to notify the caller about various components of date in the format string.
+ */
+template< typename CharT >
+struct date_format_parser_callback
+{
+ //! Character type used by the parser
+ typedef CharT char_type;
+
+ //! Destructor
+ virtual ~date_format_parser_callback() {}
+
+ /*!
+ * \brief The function is called when the parser discovers a string literal in the format string
+ *
+ * \param lit The string of characters not interpreted as a placeholder
+ */
+ virtual void on_literal(iterator_range< const char_type* > const& lit) = 0;
+
+ /*!
+ * \brief The method is called when an unknown placeholder is found in the format string
+ *
+ * \param ph The placeholder with the leading percent sign
+ */
+ virtual void on_placeholder(iterator_range< const char_type* > const& ph)
+ {
+ // By default interpret all unrecognized placeholders as literals
+ on_literal(ph);
+ }
+
+ /*!
+ * \brief The function is called when the short year placeholder is found in the format string
+ */
+ virtual void on_short_year()
+ {
+ const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('y'), static_cast< char_type >('\0') };
+ on_placeholder(boost::as_literal(placeholder));
+ }
+
+ /*!
+ * \brief The function is called when the full year placeholder is found in the format string
+ */
+ virtual void on_full_year()
+ {
+ const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('Y'), static_cast< char_type >('\0') };
+ on_placeholder(boost::as_literal(placeholder));
+ }
+
+ /*!
+ * \brief The function is called when the numeric month placeholder is found in the format string
+ */
+ virtual void on_numeric_month()
+ {
+ const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('m'), static_cast< char_type >('\0') };
+ on_placeholder(boost::as_literal(placeholder));
+ }
+
+ /*!
+ * \brief The function is called when the short alphabetic month placeholder is found in the format string
+ */
+ virtual void on_short_month()
+ {
+ const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('b'), static_cast< char_type >('\0') };
+ on_placeholder(boost::as_literal(placeholder));
+ }
+
+ /*!
+ * \brief The function is called when the full alphabetic month placeholder is found in the format string
+ */
+ virtual void on_full_month()
+ {
+ const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('B'), static_cast< char_type >('\0') };
+ on_placeholder(boost::as_literal(placeholder));
+ }
+
+ /*!
+ * \brief The function is called when the numeric day of month placeholder is found in the format string
+ *
+ * \param leading_zero If \c true, the day should be formatted with leading zero, otherwise with leading space
+ */
+ virtual void on_month_day(bool leading_zero)
+ {
+ const char_type placeholder[3] = { static_cast< char_type >('%'), (leading_zero ? static_cast< char_type >('d') : static_cast< char_type >('e')), static_cast< char_type >('\0') };
+ on_placeholder(boost::as_literal(placeholder));
+ }
+
+ /*!
+ * \brief The function is called when the numeric day of week placeholder is found in the format string
+ */
+ virtual void on_numeric_week_day()
+ {
+ const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('w'), static_cast< char_type >('\0') };
+ on_placeholder(boost::as_literal(placeholder));
+ }
+
+ /*!
+ * \brief The function is called when the short alphabetic day of week placeholder is found in the format string
+ */
+ virtual void on_short_week_day()
+ {
+ const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('a'), static_cast< char_type >('\0') };
+ on_placeholder(boost::as_literal(placeholder));
+ }
+
+ /*!
+ * \brief The function is called when the full alphabetic day of week placeholder is found in the format string
+ */
+ virtual void on_full_week_day()
+ {
+ const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('A'), static_cast< char_type >('\0') };
+ on_placeholder(boost::as_literal(placeholder));
+ }
+
+ /*!
+ * \brief The function is called when the ISO-formatted date is found in the format string
+ */
+ virtual void on_iso_date()
+ {
+ on_full_year();
+ on_numeric_month();
+ on_month_day(true);
+ }
+
+ /*!
+ * \brief The function is called when the extended ISO-formatted date is found in the format string
+ */
+ virtual void on_extended_iso_date()
+ {
+ const char_type delimiter[2] = { static_cast< char_type >('-'), static_cast< char_type >('\0') };
+ on_full_year();
+ on_literal(boost::as_literal(delimiter));
+ on_numeric_month();
+ on_literal(boost::as_literal(delimiter));
+ on_month_day(true);
+ }
+};
+
+/*!
+ * This is the interface the parser will use to notify the caller about various components of date in the format string.
+ */
+template< typename CharT >
+struct time_format_parser_callback
+{
+ //! Character type used by the parser
+ typedef CharT char_type;
+
+ //! Destructor
+ virtual ~time_format_parser_callback() {}
+
+ /*!
+ * \brief The function is called when the parser discovers a string literal in the format string
+ *
+ * \param lit The string of characters not interpreted as a placeholder
+ */
+ virtual void on_literal(iterator_range< const char_type* > const& lit) = 0;
+
+ /*!
+ * \brief The method is called when an unknown placeholder is found in the format string
+ *
+ * \param ph The placeholder with the leading percent sign
+ */
+ virtual void on_placeholder(iterator_range< const char_type* > const& ph)
+ {
+ // By default interpret all unrecognized placeholders as literals
+ on_literal(ph);
+ }
+
+ /*!
+ * \brief The function is called when the hours placeholder is found in the format string
+ *
+ * The placeholder is used for 24-hour clock and duration formatting.
+ *
+ * \param leading_zero If \c true, the one-digit number of hours should be formatted with leading zero, otherwise with leading space
+ */
+ virtual void on_hours(bool leading_zero)
+ {
+ const char_type placeholder[3] = { static_cast< char_type >('%'), (leading_zero ? static_cast< char_type >('O') : static_cast< char_type >('k')), static_cast< char_type >('\0') };
+ on_placeholder(boost::as_literal(placeholder));
+ }
+
+ /*!
+ * \brief The function is called when the hours placeholder is found in the format string
+ *
+ * The placeholder is used for 12-hour clock formatting. It should not be used for duration formatting.
+ *
+ * \param leading_zero If \c true, the one-digit number of hours should be formatted with leading zero, otherwise with leading space
+ */
+ virtual void on_hours_12(bool leading_zero)
+ {
+ const char_type placeholder[3] = { static_cast< char_type >('%'), (leading_zero ? static_cast< char_type >('I') : static_cast< char_type >('l')), static_cast< char_type >('\0') };
+ on_placeholder(boost::as_literal(placeholder));
+ }
+
+ /*!
+ * \brief The function is called when the minutes placeholder is found in the format string
+ */
+ virtual void on_minutes()
+ {
+ const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('M'), static_cast< char_type >('\0') };
+ on_placeholder(boost::as_literal(placeholder));
+ }
+
+ /*!
+ * \brief The function is called when the seconds placeholder is found in the format string
+ */
+ virtual void on_seconds()
+ {
+ const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('S'), static_cast< char_type >('\0') };
+ on_placeholder(boost::as_literal(placeholder));
+ }
+
+ /*!
+ * \brief The function is called when the fractional seconds placeholder is found in the format string
+ */
+ virtual void on_fractional_seconds()
+ {
+ const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('f'), static_cast< char_type >('\0') };
+ on_placeholder(boost::as_literal(placeholder));
+ }
+
+ /*!
+ * \brief The function is called when the day period (AM/PM) placeholder is found in the format string
+ *
+ * The placeholder is used for 12-hour clock formatting. It should not be used for duration formatting.
+ *
+ * \param upper_case If \c true, the day period will be upper case, and lower case otherwise
+ */
+ virtual void on_am_pm(bool upper_case)
+ {
+ const char_type placeholder[3] = { static_cast< char_type >('%'), (upper_case ? static_cast< char_type >('p') : static_cast< char_type >('P')), static_cast< char_type >('\0') };
+ on_placeholder(boost::as_literal(placeholder));
+ }
+
+ /*!
+ * \brief The function is called when the time duration sign placeholder is found in the format string
+ *
+ * The placeholder is used for duration formatting. It should not be used for time point formatting.
+ *
+ * \param display_positive If \c true, the positive sign will be explicitly displayed, otherwise only negative sign will be displayed
+ */
+ virtual void on_duration_sign(bool display_positive)
+ {
+ const char_type placeholder[3] = { static_cast< char_type >('%'), (display_positive ? static_cast< char_type >('+') : static_cast< char_type >('-')), static_cast< char_type >('\0') };
+ on_placeholder(boost::as_literal(placeholder));
+ }
+
+ /*!
+ * \brief The function is called when the ISO time zone placeholder is found in the format string
+ */
+ virtual void on_iso_time_zone()
+ {
+ const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('q'), static_cast< char_type >('\0') };
+ on_placeholder(boost::as_literal(placeholder));
+ }
+
+ /*!
+ * \brief The function is called when the extended ISO time zone placeholder is found in the format string
+ */
+ virtual void on_extended_iso_time_zone()
+ {
+ const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('Q'), static_cast< char_type >('\0') };
+ on_placeholder(boost::as_literal(placeholder));
+ }
+
+ /*!
+ * \brief The function is called when the ISO-formatted time is found in the format string
+ */
+ virtual void on_iso_time()
+ {
+ on_hours(true);
+ on_minutes();
+ on_seconds();
+ }
+
+ /*!
+ * \brief The function is called when the extended ISO-formatted time is found in the format string
+ */
+ virtual void on_extended_iso_time()
+ {
+ const char_type delimiter[2] = { static_cast< char_type >(':'), static_cast< char_type >('\0') };
+ on_hours(true);
+ on_literal(boost::as_literal(delimiter));
+ on_minutes();
+ on_literal(boost::as_literal(delimiter));
+ on_seconds();
+ }
+
+ /*!
+ * \brief The function is called when the extended ISO-formatted time with fractional seconds is found in the format string
+ */
+ virtual void on_default_time()
+ {
+ on_extended_iso_time();
+
+ const char_type delimiter[2] = { static_cast< char_type >('.'), static_cast< char_type >('\0') };
+ on_literal(boost::as_literal(delimiter));
+ on_fractional_seconds();
+ }
+};
+
+/*!
+ * This is the interface the parser will use to notify the caller about various components of date in the format string.
+ */
+template< typename CharT >
+struct date_time_format_parser_callback :
+ public date_format_parser_callback< CharT >,
+ public time_format_parser_callback< CharT >
+{
+ //! Character type used by the parser
+ typedef CharT char_type;
+
+ //! Destructor
+ virtual ~date_time_format_parser_callback() {}
+
+ /*!
+ * \brief The function is called when the parser discovers a string literal in the format string
+ *
+ * \param lit The string of characters not interpreted as a placeholder
+ */
+ virtual void on_literal(iterator_range< const char_type* > const& lit) = 0;
+
+ /*!
+ * \brief The method is called when an unknown placeholder is found in the format string
+ *
+ * \param ph The placeholder with the leading percent sign
+ */
+ virtual void on_placeholder(iterator_range< const char_type* > const& ph)
+ {
+ // By default interpret all unrecognized placeholders as literals
+ on_literal(ph);
+ }
+};
+
+/*!
+ * \brief Parses the date format string and invokes the callback object
+ *
+ * \pre <tt>begin <= end</tt>, both pointers must not be \c NULL
+ * \param begin Pointer to the first character of the sequence
+ * \param end Pointer to the after-the-last character of the sequence
+ * \param callback Reference to the callback object that will be invoked by the parser as it processes the input
+ */
+template< typename CharT >
+BOOST_LOG_API void parse_date_format(const CharT* begin, const CharT* end, date_format_parser_callback< CharT >& callback);
+
+/*!
+ * \brief Parses the date format string and invokes the callback object
+ *
+ * \param str The format string to parse
+ * \param callback Reference to the callback object that will be invoked by the parser as it processes the input
+ */
+template< typename CharT, typename TraitsT, typename AllocatorT >
+inline void parse_date_format(std::basic_string< CharT, TraitsT, AllocatorT > const& str, date_format_parser_callback< CharT >& callback)
+{
+ const CharT* p = str.c_str();
+ return parse_date_format(p, p + str.size(), callback);
+}
+
+/*!
+ * \brief Parses the date format string and invokes the callback object
+ *
+ * \pre <tt>str != NULL</tt>, <tt>str</tt> points to a zero-terminated string.
+ * \param str The format string to parse
+ * \param callback Reference to the callback object that will be invoked by the parser as it processes the input
+ */
+template< typename CharT >
+inline void parse_date_format(const CharT* str, date_format_parser_callback< CharT >& callback)
+{
+ return parse_date_format(str, str + std::char_traits< CharT >::length(str), callback);
+}
+
+/*!
+ * \brief Parses the time format string and invokes the callback object
+ *
+ * \pre <tt>begin <= end</tt>, both pointers must not be \c NULL
+ * \param begin Pointer to the first character of the sequence
+ * \param end Pointer to the after-the-last character of the sequence
+ * \param callback Reference to the callback object that will be invoked by the parser as it processes the input
+ */
+template< typename CharT >
+BOOST_LOG_API void parse_time_format(const CharT* begin, const CharT* end, time_format_parser_callback< CharT >& callback);
+
+/*!
+ * \brief Parses the time format string and invokes the callback object
+ *
+ * \param str The format string to parse
+ * \param callback Reference to the callback object that will be invoked by the parser as it processes the input
+ */
+template< typename CharT, typename TraitsT, typename AllocatorT >
+inline void parse_time_format(std::basic_string< CharT, TraitsT, AllocatorT > const& str, time_format_parser_callback< CharT >& callback)
+{
+ const CharT* p = str.c_str();
+ return parse_time_format(p, p + str.size(), callback);
+}
+
+/*!
+ * \brief Parses the time format string and invokes the callback object
+ *
+ * \pre <tt>str != NULL</tt>, <tt>str</tt> points to a zero-terminated string.
+ * \param str The format string to parse
+ * \param callback Reference to the callback object that will be invoked by the parser as it processes the input
+ */
+template< typename CharT >
+inline void parse_time_format(const CharT* str, time_format_parser_callback< CharT >& callback)
+{
+ return parse_time_format(str, str + std::char_traits< CharT >::length(str), callback);
+}
+
+/*!
+ * \brief Parses the date and time format string and invokes the callback object
+ *
+ * \pre <tt>begin <= end</tt>, both pointers must not be \c NULL
+ * \param begin Pointer to the first character of the sequence
+ * \param end Pointer to the after-the-last character of the sequence
+ * \param callback Reference to the callback object that will be invoked by the parser as it processes the input
+ */
+template< typename CharT >
+BOOST_LOG_API void parse_date_time_format(const CharT* begin, const CharT* end, date_time_format_parser_callback< CharT >& callback);
+
+/*!
+ * \brief Parses the date and time format string and invokes the callback object
+ *
+ * \param str The format string to parse
+ * \param callback Reference to the callback object that will be invoked by the parser as it processes the input
+ */
+template< typename CharT, typename TraitsT, typename AllocatorT >
+inline void parse_date_time_format(std::basic_string< CharT, TraitsT, AllocatorT > const& str, date_time_format_parser_callback< CharT >& callback)
+{
+ const CharT* p = str.c_str();
+ return parse_date_time_format(p, p + str.size(), callback);
+}
+
+/*!
+ * \brief Parses the date and time format string and invokes the callback object
+ *
+ * \pre <tt>str != NULL</tt>, <tt>str</tt> points to a zero-terminated string.
+ * \param str The format string to parse
+ * \param callback Reference to the callback object that will be invoked by the parser as it processes the input
+ */
+template< typename CharT >
+inline void parse_date_time_format(const CharT* str, date_time_format_parser_callback< CharT >& callback)
+{
+ return parse_date_time_format(str, str + std::char_traits< CharT >::length(str), callback);
+}
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_DATE_TIME_FORMAT_PARSER_HPP_INCLUDED_
diff --git a/boost/log/detail/decomposed_time.hpp b/boost/log/detail/decomposed_time.hpp
new file mode 100644
index 0000000000..24f7546533
--- /dev/null
+++ b/boost/log/detail/decomposed_time.hpp
@@ -0,0 +1,440 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file decomposed_time.hpp
+ * \author Andrey Semashev
+ * \date 07.11.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_DECOMPOSED_TIME_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_DECOMPOSED_TIME_HPP_INCLUDED_
+
+#include <ctime>
+#include <string>
+#include <vector>
+#include <locale>
+#include <boost/cstdint.hpp>
+#include <boost/move/core.hpp>
+#include <boost/range/iterator_range_core.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/date_time_format_parser.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! Date and time suitable for formatting
+struct decomposed_time
+{
+ // Subseconds are microseconds
+ enum _
+ {
+ subseconds_per_second = 1000000,
+ subseconds_digits10 = 6
+ };
+
+ uint32_t year, month, day, hours, minutes, seconds, subseconds;
+ bool negative;
+
+ decomposed_time() : year(0), month(1), day(1), hours(0), minutes(0), seconds(0), subseconds(0), negative(false)
+ {
+ }
+
+ decomposed_time(uint32_t y, uint32_t mo, uint32_t d, uint32_t h, uint32_t mi, uint32_t s, uint32_t ss = 0, bool neg = false) :
+ year(y), month(mo), day(d), hours(h), minutes(mi), seconds(s), subseconds(ss), negative(neg)
+ {
+ }
+
+ unsigned int week_day() const
+ {
+ unsigned int a = (14u - month) / 12u;
+ unsigned int y = year - a;
+ unsigned int m = month + 12u * a - 2u;
+ return (day + y + (y / 4u) - (y / 100u) + (y / 400u) + (31u * m) / 12u) % 7u;
+ }
+
+ unsigned int year_day() const
+ {
+ bool is_leap_year = (!(year % 4u)) && ((year % 100u) || (!(year % 400u)));
+ static const unsigned int first_day_offset[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+ return first_day_offset[month - 1] + day + (month > 2 && is_leap_year);
+ }
+};
+
+inline std::tm to_tm(decomposed_time const& t)
+{
+ std::tm res = {};
+ res.tm_year = static_cast< int >(t.year) - 1900;
+ res.tm_mon = t.month - 1;
+ res.tm_mday = t.day;
+ res.tm_hour = t.hours;
+ res.tm_min = t.minutes;
+ res.tm_sec = t.seconds;
+ res.tm_wday = t.week_day();
+ res.tm_yday = t.year_day();
+ res.tm_isdst = -1;
+
+ return res;
+}
+
+template< typename T >
+struct decomposed_time_wrapper :
+ public boost::log::aux::decomposed_time
+{
+ typedef boost::log::aux::decomposed_time base_type;
+ typedef T value_type;
+ value_type m_time;
+
+ BOOST_DEFAULTED_FUNCTION(decomposed_time_wrapper(), {})
+
+ explicit decomposed_time_wrapper(value_type const& time) : m_time(time)
+ {
+ }
+};
+
+template< typename CharT >
+BOOST_LOG_API void put_integer(std::basic_string< CharT >& str, uint32_t value, unsigned int width, CharT fill_char);
+
+template< typename T, typename CharT >
+class date_time_formatter
+{
+ BOOST_COPYABLE_AND_MOVABLE_ALT(date_time_formatter)
+
+protected:
+ // Note: This typedef is needed to work around MSVC 2012 crappy name lookup in the derived classes
+ typedef date_time_formatter date_time_formatter_;
+
+public:
+ typedef void result_type;
+ typedef T value_type;
+ typedef CharT char_type;
+ typedef std::basic_string< char_type > string_type;
+ typedef basic_formatting_ostream< char_type > stream_type;
+
+ struct context
+ {
+ date_time_formatter const& self;
+ stream_type& strm;
+ string_type& str;
+ value_type const& value;
+ unsigned int literal_index, literal_pos;
+
+ context(date_time_formatter const& self_, stream_type& strm_, value_type const& value_) :
+ self(self_),
+ strm(strm_),
+ str(*strm_.rdbuf()->storage()),
+ value(value_),
+ literal_index(0),
+ literal_pos(0)
+ {
+ }
+
+ BOOST_DELETED_FUNCTION(context(context const&))
+ BOOST_DELETED_FUNCTION(context& operator=(context const&))
+ };
+
+private:
+ typedef void (*formatter_type)(context&);
+ typedef std::vector< formatter_type > formatters;
+ typedef std::vector< unsigned int > literal_lens;
+
+protected:
+ formatters m_formatters;
+ literal_lens m_literal_lens;
+ string_type m_literal_chars;
+
+public:
+ BOOST_DEFAULTED_FUNCTION(date_time_formatter(), {})
+ date_time_formatter(date_time_formatter const& that) :
+ m_formatters(that.m_formatters),
+ m_literal_lens(that.m_literal_lens),
+ m_literal_chars(that.m_literal_chars)
+ {
+ }
+ date_time_formatter(BOOST_RV_REF(date_time_formatter) that)
+ {
+ this->swap(static_cast< date_time_formatter& >(that));
+ }
+
+ date_time_formatter& operator= (date_time_formatter that)
+ {
+ this->swap(that);
+ return *this;
+ }
+
+ result_type operator() (stream_type& strm, value_type const& value) const
+ {
+ // Some formatters will put characters directly to the underlying string, so we have to flush stream buffers before formatting
+ strm.flush();
+ context ctx(*this, strm, value);
+ for (typename formatters::const_iterator it = m_formatters.begin(), end = m_formatters.end(); strm.good() && it != end; ++it)
+ {
+ (*it)(ctx);
+ }
+ }
+
+ void add_formatter(formatter_type fun)
+ {
+ m_formatters.push_back(fun);
+ }
+
+ void add_literal(iterator_range< const char_type* > const& lit)
+ {
+ m_literal_chars.append(lit.begin(), lit.end());
+ m_literal_lens.push_back(static_cast< unsigned int >(lit.size()));
+ m_formatters.push_back(&date_time_formatter_::format_literal);
+ }
+
+ void swap(date_time_formatter& that)
+ {
+ m_formatters.swap(that.m_formatters);
+ m_literal_lens.swap(that.m_literal_lens);
+ m_literal_chars.swap(that.m_literal_chars);
+ }
+
+public:
+ template< char FormatCharV >
+ static void format_through_locale(context& ctx)
+ {
+ typedef std::time_put< char_type > facet_type;
+ typedef typename facet_type::iter_type iter_type;
+ std::tm t = to_tm(static_cast< decomposed_time const& >(ctx.value));
+ std::use_facet< facet_type >(ctx.strm.getloc()).put(iter_type(ctx.strm.stream()), ctx.strm.stream(), ' ', &t, FormatCharV);
+ ctx.strm.flush();
+ }
+
+ static void format_full_year(context& ctx)
+ {
+ (put_integer)(ctx.str, ctx.value.year, 4, static_cast< char_type >('0'));
+ }
+
+ static void format_short_year(context& ctx)
+ {
+ (put_integer)(ctx.str, ctx.value.year % 100u, 2, static_cast< char_type >('0'));
+ }
+
+ static void format_numeric_month(context& ctx)
+ {
+ (put_integer)(ctx.str, ctx.value.month, 2, static_cast< char_type >('0'));
+ }
+
+ template< char_type FillCharV >
+ static void format_month_day(context& ctx)
+ {
+ (put_integer)(ctx.str, ctx.value.day, 2, static_cast< char_type >(FillCharV));
+ }
+
+ static void format_week_day(context& ctx)
+ {
+ (put_integer)(ctx.str, static_cast< decomposed_time const& >(ctx.value).week_day(), 1, static_cast< char_type >('0'));
+ }
+
+ template< char_type FillCharV >
+ static void format_hours(context& ctx)
+ {
+ (put_integer)(ctx.str, ctx.value.hours, 2, static_cast< char_type >(FillCharV));
+ }
+
+ template< char_type FillCharV >
+ static void format_hours_12(context& ctx)
+ {
+ (put_integer)(ctx.str, ctx.value.hours % 12u + 1u, 2, static_cast< char_type >(FillCharV));
+ }
+
+ static void format_minutes(context& ctx)
+ {
+ (put_integer)(ctx.str, ctx.value.minutes, 2, static_cast< char_type >('0'));
+ }
+
+ static void format_seconds(context& ctx)
+ {
+ (put_integer)(ctx.str, ctx.value.seconds, 2, static_cast< char_type >('0'));
+ }
+
+ static void format_fractional_seconds(context& ctx)
+ {
+ (put_integer)(ctx.str, ctx.value.subseconds, decomposed_time::subseconds_digits10, static_cast< char_type >('0'));
+ }
+
+ template< bool UpperCaseV >
+ static void format_am_pm(context& ctx)
+ {
+ static const char_type am[] = { static_cast< char_type >(UpperCaseV ? 'A' : 'a'), static_cast< char_type >(UpperCaseV ? 'M' : 'm'), static_cast< char_type >(0) };
+ static const char_type pm[] = { static_cast< char_type >(UpperCaseV ? 'P' : 'p'), static_cast< char_type >(UpperCaseV ? 'M' : 'm'), static_cast< char_type >(0) };
+
+ ctx.str.append(((static_cast< decomposed_time const& >(ctx.value).hours > 11) ? pm : am), 2u);
+ }
+
+ template< bool DisplayPositiveV >
+ static void format_sign(context& ctx)
+ {
+ if (static_cast< decomposed_time const& >(ctx.value).negative)
+ ctx.str.push_back('-');
+ else if (DisplayPositiveV)
+ ctx.str.push_back('+');
+ }
+
+private:
+ static void format_literal(context& ctx)
+ {
+ unsigned int len = ctx.self.m_literal_lens[ctx.literal_index], pos = ctx.literal_pos;
+ ++ctx.literal_index;
+ ctx.literal_pos += len;
+ const char_type* lit = ctx.self.m_literal_chars.c_str();
+ ctx.str.append(lit + pos, len);
+ }
+};
+
+template< typename FormatterT, typename CharT >
+class decomposed_time_formatter_builder :
+ public date_time_format_parser_callback< CharT >
+{
+public:
+ typedef date_time_format_parser_callback< CharT > base_type;
+ typedef typename base_type::char_type char_type;
+ typedef FormatterT formatter_type;
+ typedef typename formatter_type::value_type value_type;
+ typedef typename formatter_type::stream_type stream_type;
+ typedef typename stream_type::string_type string_type;
+
+protected:
+ formatter_type& m_formatter;
+
+public:
+ explicit decomposed_time_formatter_builder(formatter_type& fmt) : m_formatter(fmt)
+ {
+ }
+
+ void on_literal(iterator_range< const char_type* > const& lit)
+ {
+ m_formatter.add_literal(lit);
+ }
+
+ void on_short_year()
+ {
+ m_formatter.add_formatter(&formatter_type::format_short_year);
+ }
+
+ void on_full_year()
+ {
+ m_formatter.add_formatter(&formatter_type::format_full_year);
+ }
+
+ void on_numeric_month()
+ {
+ m_formatter.add_formatter(&formatter_type::format_numeric_month);
+ }
+
+ void on_short_month()
+ {
+ m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_through_locale< 'b' >);
+ }
+
+ void on_full_month()
+ {
+ m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_through_locale< 'B' >);
+ }
+
+ void on_month_day(bool leading_zero)
+ {
+ if (leading_zero)
+ m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_month_day< '0' >);
+ else
+ m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_month_day< ' ' >);
+ }
+
+ void on_numeric_week_day()
+ {
+ m_formatter.add_formatter(&formatter_type::format_week_day);
+ }
+
+ void on_short_week_day()
+ {
+ m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_through_locale< 'a' >);
+ }
+
+ void on_full_week_day()
+ {
+ m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_through_locale< 'A' >);
+ }
+
+ void on_hours(bool leading_zero)
+ {
+ if (leading_zero)
+ m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_hours< '0' >);
+ else
+ m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_hours< ' ' >);
+ }
+
+ void on_hours_12(bool leading_zero)
+ {
+ if (leading_zero)
+ m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_hours_12< '0' >);
+ else
+ m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_hours_12< ' ' >);
+ }
+
+ void on_minutes()
+ {
+ m_formatter.add_formatter(&formatter_type::format_minutes);
+ }
+
+ void on_seconds()
+ {
+ m_formatter.add_formatter(&formatter_type::format_seconds);
+ }
+
+ void on_fractional_seconds()
+ {
+ m_formatter.add_formatter(&formatter_type::format_fractional_seconds);
+ }
+
+ void on_am_pm(bool upper_case)
+ {
+ if (upper_case)
+ m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_am_pm< true >);
+ else
+ m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_am_pm< false >);
+ }
+
+ void on_duration_sign(bool display_positive)
+ {
+ if (display_positive)
+ m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_sign< true >);
+ else
+ m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_sign< false >);
+ }
+
+ void on_iso_time_zone()
+ {
+ }
+
+ void on_extended_iso_time_zone()
+ {
+ }
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_DECOMPOSED_TIME_HPP_INCLUDED_
diff --git a/boost/log/detail/deduce_char_type.hpp b/boost/log/detail/deduce_char_type.hpp
new file mode 100644
index 0000000000..cb024609e9
--- /dev/null
+++ b/boost/log/detail/deduce_char_type.hpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file deduce_char_type.hpp
+ * \author Andrey Semashev
+ * \date 17.11.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_DEDUCE_CHAR_TYPE_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_DEDUCE_CHAR_TYPE_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+template< typename T >
+struct deduced_char_type;
+
+template< >
+struct deduced_char_type< char >
+{
+ typedef char type;
+};
+
+template< >
+struct deduced_char_type< const char >
+{
+ typedef char type;
+};
+
+template< >
+struct deduced_char_type< wchar_t >
+{
+ typedef wchar_t type;
+};
+
+template< >
+struct deduced_char_type< const wchar_t >
+{
+ typedef wchar_t type;
+};
+
+//! Auxiliary traits to detect character type from a string
+template< typename RangeT >
+struct deduce_char_type :
+ public deduced_char_type< typename RangeT::value_type >
+{
+};
+
+template< typename T >
+struct deduce_char_type< T* > :
+ public deduced_char_type< T >
+{
+};
+
+template< typename T >
+struct deduce_char_type< T* const > :
+ public deduced_char_type< T >
+{
+};
+
+template< typename T, unsigned int CountV >
+struct deduce_char_type< T[CountV] > :
+ public deduced_char_type< T >
+{
+};
+
+template< typename T >
+struct deduce_char_type< T& > :
+ public deduce_char_type< T >
+{
+};
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+template< typename T >
+struct deduce_char_type< T&& > :
+ public deduce_char_type< T >
+{
+};
+
+#endif
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_DEDUCE_CHAR_TYPE_HPP_INCLUDED_
diff --git a/boost/log/detail/default_attribute_names.hpp b/boost/log/detail/default_attribute_names.hpp
new file mode 100644
index 0000000000..c1fddd36e3
--- /dev/null
+++ b/boost/log/detail/default_attribute_names.hpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file default_attribute_names.hpp
+ * \author Andrey Semashev
+ * \date 15.01.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_DEFAULT_ATTRIBUTE_NAMES_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_DEFAULT_ATTRIBUTE_NAMES_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+namespace default_attribute_names {
+
+BOOST_LOG_API attribute_name severity();
+BOOST_LOG_API attribute_name channel();
+BOOST_LOG_API attribute_name message();
+BOOST_LOG_API attribute_name line_id();
+BOOST_LOG_API attribute_name timestamp();
+BOOST_LOG_API attribute_name process_id();
+BOOST_LOG_API attribute_name thread_id();
+
+} // namespace default_attribute_names
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_DEFAULT_ATTRIBUTE_NAMES_HPP_INCLUDED_
diff --git a/boost/log/detail/embedded_string_type.hpp b/boost/log/detail/embedded_string_type.hpp
new file mode 100644
index 0000000000..091dce205b
--- /dev/null
+++ b/boost/log/detail/embedded_string_type.hpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file embedded_string_type.hpp
+ * \author Andrey Semashev
+ * \date 16.08.2009
+ *
+ * This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_EMBEDDED_STRING_TYPE_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_EMBEDDED_STRING_TYPE_HPP_INCLUDED_
+
+#include <string>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+template< typename T, typename ArgT >
+struct make_embedded_string_type_impl
+{
+ typedef ArgT type;
+};
+
+template< typename ArgT >
+struct make_embedded_string_type_impl< char, ArgT >
+{
+ typedef std::basic_string< char > type;
+};
+
+template< typename ArgT >
+struct make_embedded_string_type_impl< const char, ArgT >
+{
+ typedef std::basic_string< char > type;
+};
+
+template< typename ArgT >
+struct make_embedded_string_type_impl< wchar_t, ArgT >
+{
+ typedef std::basic_string< wchar_t > type;
+};
+
+template< typename ArgT >
+struct make_embedded_string_type_impl< const wchar_t, ArgT >
+{
+ typedef std::basic_string< wchar_t > type;
+};
+
+#if !defined(BOOST_NO_CXX11_CHAR16_T)
+template< typename ArgT >
+struct make_embedded_string_type_impl< char16_t, ArgT >
+{
+ typedef std::basic_string< char16_t > type;
+};
+
+template< typename ArgT >
+struct make_embedded_string_type_impl< const char16_t, ArgT >
+{
+ typedef std::basic_string< char16_t > type;
+};
+#endif
+
+#if !defined(BOOST_NO_CXX11_CHAR32_T)
+template< typename ArgT >
+struct make_embedded_string_type_impl< char32_t, ArgT >
+{
+ typedef std::basic_string< char32_t > type;
+};
+
+template< typename ArgT >
+struct make_embedded_string_type_impl< const char32_t, ArgT >
+{
+ typedef std::basic_string< char32_t > type;
+};
+#endif
+
+//! An auxiliary type translator to store strings by value in function objects and attribute values
+template< typename ArgT >
+struct make_embedded_string_type :
+ public remove_cv< ArgT >
+{
+};
+
+template< typename ArgT >
+struct make_embedded_string_type< ArgT* > :
+ public make_embedded_string_type_impl< ArgT, ArgT* >
+{
+};
+
+template< typename ArgT, unsigned int CountV >
+struct make_embedded_string_type< ArgT[CountV] > :
+ public make_embedded_string_type_impl< ArgT, ArgT[CountV] >
+{
+};
+
+template< typename ArgT, unsigned int CountV >
+struct make_embedded_string_type< ArgT(&)[CountV] > :
+ public make_embedded_string_type_impl< ArgT, ArgT(&)[CountV] >
+{
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_EMBEDDED_STRING_TYPE_HPP_INCLUDED_
diff --git a/boost/log/detail/enqueued_record.hpp b/boost/log/detail/enqueued_record.hpp
new file mode 100644
index 0000000000..11aaf186f5
--- /dev/null
+++ b/boost/log/detail/enqueued_record.hpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file enqueued_record.hpp
+ * \author Andrey Semashev
+ * \date 01.04.2014
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. In this file
+ * internal configuration macros are defined.
+ */
+
+#ifndef BOOST_LOG_DETAIL_ENQUEUED_RECORD_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_ENQUEUED_RECORD_HPP_INCLUDED_
+
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/timestamp.hpp>
+#include <boost/log/core/record_view.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+namespace aux {
+
+//! Log record with enqueueing timestamp
+class enqueued_record
+{
+ BOOST_COPYABLE_AND_MOVABLE(enqueued_record)
+
+public:
+ //! Ordering predicate
+ template< typename OrderT >
+ struct order :
+ public OrderT
+ {
+ typedef typename OrderT::result_type result_type;
+
+ order() {}
+ order(order const& that) : OrderT(static_cast< OrderT const& >(that)) {}
+ order(OrderT const& that) : OrderT(that) {}
+
+ result_type operator() (enqueued_record const& left, enqueued_record const& right) const
+ {
+ // std::priority_queue requires ordering with semantics of std::greater, so we swap arguments
+ return OrderT::operator() (right.m_record, left.m_record);
+ }
+ };
+
+ boost::log::aux::timestamp m_timestamp;
+ record_view m_record;
+
+ enqueued_record(enqueued_record const& that) : m_timestamp(that.m_timestamp), m_record(that.m_record)
+ {
+ }
+ enqueued_record(BOOST_RV_REF(enqueued_record) that) :
+ m_timestamp(that.m_timestamp),
+ m_record(boost::move(that.m_record))
+ {
+ }
+ explicit enqueued_record(record_view const& rec) :
+ m_timestamp(boost::log::aux::get_timestamp()),
+ m_record(rec)
+ {
+ }
+ enqueued_record& operator= (BOOST_COPY_ASSIGN_REF(enqueued_record) that)
+ {
+ m_timestamp = that.m_timestamp;
+ m_record = that.m_record;
+ return *this;
+ }
+ enqueued_record& operator= (BOOST_RV_REF(enqueued_record) that)
+ {
+ m_timestamp = that.m_timestamp;
+ m_record = boost::move(that.m_record);
+ return *this;
+ }
+};
+
+} // namespace aux
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_ENQUEUED_RECORD_HPP_INCLUDED_
diff --git a/boost/log/detail/event.hpp b/boost/log/detail/event.hpp
new file mode 100644
index 0000000000..741ab3c9bd
--- /dev/null
+++ b/boost/log/detail/event.hpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file detail/event.hpp
+ * \author Andrey Semashev
+ * \date 24.07.2011
+ */
+
+#ifndef BOOST_LOG_DETAIL_EVENT_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_EVENT_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifndef BOOST_LOG_NO_THREADS
+
+#if defined(BOOST_THREAD_PLATFORM_PTHREAD)
+# if defined(_POSIX_SEMAPHORES) && (_POSIX_SEMAPHORES + 0) > 0
+# if defined(__GNUC__) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
+# include <semaphore.h>
+# include <boost/cstdint.hpp>
+# define BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE
+# endif
+# endif
+#elif defined(BOOST_THREAD_PLATFORM_WIN32)
+# include <boost/cstdint.hpp>
+# define BOOST_LOG_EVENT_USE_WINAPI
+#endif
+
+#if !defined(BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE) && !defined(BOOST_LOG_EVENT_USE_WINAPI)
+# include <boost/thread/mutex.hpp>
+# include <boost/thread/condition_variable.hpp>
+# define BOOST_LOG_EVENT_USE_BOOST_CONDITION
+#endif
+
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+#if defined(BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE)
+
+class sem_based_event
+{
+private:
+ boost::uint32_t m_state;
+ sem_t m_semaphore;
+
+public:
+ //! Default constructor
+ BOOST_LOG_API sem_based_event();
+ //! Destructor
+ BOOST_LOG_API ~sem_based_event();
+
+ //! Waits for the object to become signalled
+ BOOST_LOG_API void wait();
+ //! Sets the object to a signalled state
+ BOOST_LOG_API void set_signalled();
+
+ // Copying prohibited
+ BOOST_DELETED_FUNCTION(sem_based_event(sem_based_event const&))
+ BOOST_DELETED_FUNCTION(sem_based_event& operator= (sem_based_event const&))
+};
+
+typedef sem_based_event event;
+
+#elif defined(BOOST_LOG_EVENT_USE_WINAPI)
+
+class winapi_based_event
+{
+private:
+ boost::uint32_t m_state;
+ void* m_event;
+
+public:
+ //! Default constructor
+ BOOST_LOG_API winapi_based_event();
+ //! Destructor
+ BOOST_LOG_API ~winapi_based_event();
+
+ //! Waits for the object to become signalled
+ BOOST_LOG_API void wait();
+ //! Sets the object to a signalled state
+ BOOST_LOG_API void set_signalled();
+
+ // Copying prohibited
+ BOOST_DELETED_FUNCTION(winapi_based_event(winapi_based_event const&))
+ BOOST_DELETED_FUNCTION(winapi_based_event& operator= (winapi_based_event const&))
+};
+
+typedef winapi_based_event event;
+
+#else
+
+class generic_event
+{
+private:
+ boost::mutex m_mutex;
+ boost::condition_variable m_cond;
+ bool m_state;
+
+public:
+ //! Default constructor
+ BOOST_LOG_API generic_event();
+ //! Destructor
+ BOOST_LOG_API ~generic_event();
+
+ //! Waits for the object to become signalled
+ BOOST_LOG_API void wait();
+ //! Sets the object to a signalled state
+ BOOST_LOG_API void set_signalled();
+
+ // Copying prohibited
+ BOOST_DELETED_FUNCTION(generic_event(generic_event const&))
+ BOOST_DELETED_FUNCTION(generic_event& operator= (generic_event const&))
+};
+
+typedef generic_event event;
+
+#endif
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_NO_THREADS
+
+#endif // BOOST_LOG_DETAIL_EVENT_HPP_INCLUDED_
diff --git a/boost/log/detail/fake_mutex.hpp b/boost/log/detail/fake_mutex.hpp
new file mode 100644
index 0000000000..f21f961538
--- /dev/null
+++ b/boost/log/detail/fake_mutex.hpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file fake_mutex.hpp
+ * \author Andrey Semashev
+ * \date 31.07.2011
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_FAKE_MUTEX_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_FAKE_MUTEX_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! Fake mutex that doesn't do anything. Note: we're not using \c null_mutex from Boost.Thread in order not to introduce false dependencies on Boost.Thread and Boost.Chrono.
+class fake_mutex
+{
+public:
+ BOOST_DEFAULTED_FUNCTION(fake_mutex(), {})
+ void lock() {}
+ bool try_lock() { return true; }
+ template< typename T >
+ bool timed_lock(T const&) { return true; }
+ void unlock() {}
+
+ // Copying prohibited
+ BOOST_DELETED_FUNCTION(fake_mutex(fake_mutex const&))
+ BOOST_DELETED_FUNCTION(fake_mutex& operator=(fake_mutex const&))
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_FAKE_MUTEX_HPP_INCLUDED_
diff --git a/boost/log/detail/footer.hpp b/boost/log/detail/footer.hpp
new file mode 100644
index 0000000000..8208ebd33a
--- /dev/null
+++ b/boost/log/detail/footer.hpp
@@ -0,0 +1,22 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#if !defined(BOOST_LOG_ENABLE_WARNINGS)
+
+#if defined(_MSC_VER)
+
+#pragma warning(pop)
+
+#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 406
+
+#pragma GCC diagnostic pop
+
+#endif
+
+#endif // !defined(BOOST_LOG_ENABLE_WARNINGS)
+
+#include <boost/config/abi_suffix.hpp>
diff --git a/boost/log/detail/format.hpp b/boost/log/detail/format.hpp
new file mode 100644
index 0000000000..d383aba717
--- /dev/null
+++ b/boost/log/detail/format.hpp
@@ -0,0 +1,336 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file format.hpp
+ * \author Andrey Semashev
+ * \date 15.11.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_FORMAT_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_FORMAT_HPP_INCLUDED_
+
+#include <string>
+#include <vector>
+#include <iosfwd>
+#include <boost/assert.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/unhandled_exception_count.hpp>
+#include <boost/log/detail/cleanup_scope_guard.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! An element (either literal or placeholder) of the format string
+struct format_element
+{
+ //! Argument placeholder number or -1 if it's not a placeholder (i.e. a literal)
+ int arg_number;
+ //! If the element describes a constant literal, the starting character and length of the literal
+ unsigned int literal_start_pos, literal_len;
+
+ format_element() : arg_number(0), literal_start_pos(0), literal_len(0)
+ {
+ }
+
+ static format_element literal(unsigned int start_pos, unsigned int len)
+ {
+ format_element el;
+ el.arg_number = -1;
+ el.literal_start_pos = start_pos;
+ el.literal_len = len;
+ return el;
+ }
+
+ static format_element positional_argument(unsigned int arg_n)
+ {
+ format_element el;
+ el.arg_number = arg_n;
+ return el;
+ }
+};
+
+//! Parsed format string description
+template< typename CharT >
+struct format_description
+{
+ BOOST_COPYABLE_AND_MOVABLE_ALT(format_description)
+
+public:
+ //! Character type
+ typedef CharT char_type;
+ //! String type
+ typedef std::basic_string< char_type > string_type;
+
+ //! Array of format element descriptors
+ typedef std::vector< format_element > format_element_list;
+
+ //! Characters of all literal parts of the format string
+ string_type literal_chars;
+ //! Format element descriptors
+ format_element_list format_elements;
+
+ BOOST_DEFAULTED_FUNCTION(format_description(), {})
+
+ format_description(format_description const& that) : literal_chars(that.literal_chars), format_elements(that.format_elements)
+ {
+ }
+
+ format_description(BOOST_RV_REF(format_description) that)
+ {
+ literal_chars.swap(that.literal_chars);
+ format_elements.swap(that.format_elements);
+ }
+
+ format_description& operator= (format_description that)
+ {
+ literal_chars.swap(that.literal_chars);
+ format_elements.swap(that.format_elements);
+ return *this;
+ }
+};
+
+//! Parses format string
+template< typename CharT >
+BOOST_LOG_API format_description< CharT > parse_format(const CharT* begin, const CharT* end);
+
+//! Parses format string
+template< typename CharT >
+BOOST_FORCEINLINE format_description< CharT > parse_format(const CharT* begin)
+{
+ return parse_format(begin, begin + std::char_traits< CharT >::length(begin));
+}
+
+//! Parses format string
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_FORCEINLINE format_description< CharT > parse_format(std::basic_string< CharT, TraitsT, AllocatorT > const& fmt)
+{
+ const CharT* begin = fmt.c_str();
+ return parse_format(begin, begin + fmt.size());
+}
+
+//! Formatter object
+template< typename CharT >
+class basic_format
+{
+public:
+ //! Character type
+ typedef CharT char_type;
+ //! String type
+ typedef std::basic_string< char_type > string_type;
+ //! Stream type
+ typedef basic_formatting_ostream< char_type > stream_type;
+ //! Format description type
+ typedef format_description< char_type > format_description_type;
+
+ //! The pump receives arguments and formats them into strings. At destruction the pump composes the final string in the attached stream.
+ class pump;
+ friend class pump;
+
+private:
+ //! Formatting params for a single placeholder in the format string
+ struct formatting_params
+ {
+ //! Formatting element index in the format description
+ unsigned int element_idx;
+ //! Formatting result
+ string_type target;
+
+ formatting_params() : element_idx(~0u) {}
+ };
+ typedef std::vector< formatting_params > formatting_params_list;
+
+private:
+ //! Format string description
+ format_description_type m_format;
+ //! Formatting parameters for all placeholders
+ formatting_params_list m_formatting_params;
+ //! Current formatting position
+ unsigned int m_current_idx;
+
+public:
+ //! Initializing constructor
+ explicit basic_format(string_type const& fmt) : m_format(aux::parse_format(fmt)), m_current_idx(0)
+ {
+ init_params();
+ }
+ //! Initializing constructor
+ explicit basic_format(const char_type* fmt) : m_format(aux::parse_format(fmt)), m_current_idx(0)
+ {
+ init_params();
+ }
+
+ //! Clears all formatted strings and resets the current formatting position
+ void clear() BOOST_NOEXCEPT
+ {
+ for (typename formatting_params_list::iterator it = m_formatting_params.begin(), end = m_formatting_params.end(); it != end; ++it)
+ {
+ it->target.clear();
+ }
+ m_current_idx = 0;
+ }
+
+ //! Creates a pump that will receive all format arguments and put the formatted string into the stream
+ pump make_pump(stream_type& strm) BOOST_NOEXCEPT
+ {
+ return pump(*this, strm);
+ }
+
+ //! Composes the final string from the formatted pieces
+ void compose(string_type& str) const
+ {
+ typename format_description_type::format_element_list::const_iterator it = m_format.format_elements.begin(), end = m_format.format_elements.end();
+ for (; it != end; ++it)
+ {
+ if (it->arg_number >= 0)
+ {
+ // This is a placeholder
+ str.append(m_formatting_params[it->arg_number].target);
+ }
+ else
+ {
+ // This is a literal
+ const char_type* p = m_format.literal_chars.c_str() + it->literal_start_pos;
+ str.append(p, it->literal_len);
+ }
+ }
+ }
+
+ //! Composes the final string from the formatted pieces
+ string_type str() const
+ {
+ string_type result;
+ compose(result);
+ return boost::move(result);
+ }
+
+private:
+ //! Initializes the formatting params
+ void init_params()
+ {
+ typename format_description_type::format_element_list::const_iterator it = m_format.format_elements.begin(), end = m_format.format_elements.end();
+ for (; it != end; ++it)
+ {
+ if (it->arg_number >= 0)
+ {
+ if (static_cast< unsigned int >(it->arg_number) >= m_formatting_params.size())
+ m_formatting_params.resize(it->arg_number + 1);
+ m_formatting_params[it->arg_number].element_idx = static_cast< unsigned int >(it - m_format.format_elements.begin());
+ }
+ }
+ }
+};
+
+//! The pump receives arguments and formats them into strings. At destruction the pump composes the final string in the attached stream.
+template< typename CharT >
+class basic_format< CharT >::pump
+{
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(pump)
+
+private:
+ //! The guard temporarily replaces storage string in the specified stream
+ struct scoped_storage
+ {
+ scoped_storage(stream_type& strm, string_type& storage) : m_stream(strm), m_storage_backup(*strm.rdbuf()->storage())
+ {
+ strm.attach(storage);
+ }
+ ~scoped_storage()
+ {
+ m_stream.attach(m_storage_backup);
+ }
+
+ private:
+ stream_type& m_stream;
+ string_type& m_storage_backup;
+ };
+
+private:
+ //! Reference to the owner
+ basic_format* m_owner;
+ //! Reference to the stream
+ stream_type* m_stream;
+ //! Unhandled exception count
+ const unsigned int m_exception_count;
+
+public:
+ //! Initializing constructor
+ pump(basic_format& owner, stream_type& strm) BOOST_NOEXCEPT : m_owner(&owner), m_stream(&strm), m_exception_count(unhandled_exception_count())
+ {
+ }
+
+ //! Move constructor
+ pump(BOOST_RV_REF(pump) that) BOOST_NOEXCEPT : m_owner(that.m_owner), m_stream(that.m_stream), m_exception_count(that.m_exception_count)
+ {
+ that.m_owner = NULL;
+ that.m_stream = NULL;
+ }
+
+ //! Destructor
+ ~pump() BOOST_NOEXCEPT_IF(false)
+ {
+ if (m_owner)
+ {
+ // Whether or not the destructor is called because of an exception, the format object has to be cleared
+ boost::log::aux::cleanup_guard< basic_format< char_type > > cleanup1(*m_owner);
+
+ BOOST_ASSERT(m_stream != NULL);
+ if (m_exception_count >= unhandled_exception_count())
+ {
+ // Compose the final string in the stream buffer
+ m_stream->flush();
+ m_owner->compose(*m_stream->rdbuf()->storage());
+ }
+ }
+ }
+
+ /*!
+ * Puts an argument to the formatter. Note the pump has to be returned by value and not by reference in order this to
+ * work with Boost.Phoenix expressions. Otherwise the pump that is returned from \c basic_format::make_pump is
+ * destroyed after the first call to \c operator%, and the returned reference becomes dangling.
+ */
+ template< typename T >
+ pump operator% (T const& val)
+ {
+ BOOST_ASSERT_MSG(m_owner != NULL && m_stream != NULL, "Boost.Log: This basic_format::pump has already been moved from");
+
+ if (m_owner->m_current_idx < m_owner->m_formatting_params.size())
+ {
+ scoped_storage storage_guard(*m_stream, m_owner->m_formatting_params[m_owner->m_current_idx].target);
+
+ *m_stream << val;
+ m_stream->flush();
+
+ ++m_owner->m_current_idx;
+ }
+
+ return boost::move(*this);
+ }
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_FORMAT_HPP_INCLUDED_
diff --git a/boost/log/detail/function_traits.hpp b/boost/log/detail/function_traits.hpp
new file mode 100644
index 0000000000..bd298fca30
--- /dev/null
+++ b/boost/log/detail/function_traits.hpp
@@ -0,0 +1,236 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file function_traits.hpp
+ * \author Andrey Semashev
+ * \date 30.08.2009
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED_
+
+#include <boost/mpl/has_xxx.hpp>
+#include <boost/log/detail/config.hpp>
+
+#if defined(BOOST_NO_SFINAE) || defined(BOOST_MPL_CFG_NO_HAS_XXX)
+# if !defined(BOOST_LOG_NO_FUNCTION_TRAITS)
+# define BOOST_LOG_NO_FUNCTION_TRAITS
+# endif
+#else
+
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/front.hpp>
+#include <boost/mpl/pop_front.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/function_types/function_arity.hpp>
+#include <boost/function_types/parameter_types.hpp>
+#include <boost/function_types/is_nonmember_callable_builtin.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+ // A number of traits to deal with functors
+ BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_argument_type, argument_type, false)
+ BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_first_argument_type, first_argument_type, false)
+ BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_second_argument_type, second_argument_type, false)
+ BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_arg1_type, arg1_type, false)
+ BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_arg2_type, arg2_type, false)
+
+ namespace has_arity_no_adl {
+
+ typedef char yes_type;
+ struct no_type
+ {
+ char dummy[2];
+ };
+
+ template< typename FunT, int ArityV = FunT::arity >
+ struct checker
+ {
+ };
+
+ template< typename FunT >
+ yes_type has_arity_impl(FunT const&, checker< FunT >*);
+ template< typename FunT >
+ no_type has_arity_impl(FunT const&, ...);
+
+ } // namespace has_arity_no_adl
+
+ //! The metafunction detects if the type has an arity static constant member
+ template< typename FunT >
+ struct has_arity
+ {
+ static FunT const& get_FunT();
+
+ enum value_t { value = (sizeof(has_arity_no_adl::has_arity_impl(get_FunT(), 0)) == sizeof(has_arity_no_adl::yes_type)) };
+ typedef mpl::bool_< value > type;
+ };
+
+ //! The metafunction results in an unqualified type with removed reference
+ template< typename T >
+ struct root_type :
+ public remove_cv<
+ typename remove_reference<
+ T
+ >::type
+ >
+ {
+ };
+
+ template<
+ typename FunT,
+ bool = function_types::is_nonmember_callable_builtin< FunT >::value,
+ bool = has_argument_type< FunT >::value,
+ bool = has_first_argument_type< FunT >::value,
+ bool = has_arg1_type< FunT >::value
+ >
+ struct first_argument_type_of_impl
+ {
+ };
+ template< typename FunT >
+ struct first_argument_type_of_impl< FunT, true, false, false, false >
+ {
+ typedef typename root_type<
+ typename mpl::front<
+ typename function_types::parameter_types< FunT >::type
+ >::type
+ >::type type;
+ };
+ template< typename FunT, bool HasFirstArgumentV, bool HasArg1V >
+ struct first_argument_type_of_impl< FunT, false, true, HasFirstArgumentV, HasArg1V >
+ {
+ typedef typename root_type<
+ typename FunT::argument_type
+ >::type type;
+ };
+ template< typename FunT, bool HasArg1V >
+ struct first_argument_type_of_impl< FunT, false, false, true, HasArg1V >
+ {
+ typedef typename root_type<
+ typename FunT::first_argument_type
+ >::type type;
+ };
+ template< typename FunT >
+ struct first_argument_type_of_impl< FunT, false, false, false, true >
+ {
+ typedef typename root_type<
+ typename FunT::arg1_type
+ >::type type;
+ };
+
+ //! The metafunction returns the first argument type of a function
+ template< typename FunT >
+ struct first_argument_type_of :
+ public first_argument_type_of_impl< FunT >
+ {
+ };
+
+
+ template<
+ typename FunT,
+ bool = function_types::is_nonmember_callable_builtin< FunT >::value,
+ bool = has_second_argument_type< FunT >::value,
+ bool = has_arg2_type< FunT >::value
+ >
+ struct second_argument_type_of_impl
+ {
+ };
+ template< typename FunT >
+ struct second_argument_type_of_impl< FunT, true, false, false >
+ {
+ typedef typename root_type<
+ typename mpl::front<
+ typename mpl::pop_front<
+ typename function_types::parameter_types< FunT >::type
+ >::type
+ >::type
+ >::type type;
+ };
+ template< typename FunT, bool HasArg2V >
+ struct second_argument_type_of_impl< FunT, false, true, HasArg2V >
+ {
+ typedef typename root_type<
+ typename FunT::second_argument_type
+ >::type type;
+ };
+ template< typename FunT >
+ struct second_argument_type_of_impl< FunT, false, false, true >
+ {
+ typedef typename root_type<
+ typename FunT::arg2_type
+ >::type type;
+ };
+
+ //! The metafunction returns the second argument type of a function
+ template< typename FunT >
+ struct second_argument_type_of :
+ public second_argument_type_of_impl< FunT >
+ {
+ };
+
+
+ template<
+ typename FunT,
+ bool = function_types::is_nonmember_callable_builtin< FunT >::value,
+ bool = has_arity< FunT >::value,
+ bool = has_argument_type< FunT >::value,
+ bool = has_second_argument_type< FunT >::value
+ >
+ struct arity_of_impl
+ {
+ };
+ template< typename FunT >
+ struct arity_of_impl< FunT, true, false, false, false > :
+ public function_types::function_arity< FunT >
+ {
+ };
+ template< typename FunT, bool HasArgumentTypeV, bool HasSecondArgumentTypeV >
+ struct arity_of_impl< FunT, false, true, HasArgumentTypeV, HasSecondArgumentTypeV > :
+ public mpl::int_< FunT::arity >
+ {
+ };
+ template< typename FunT, bool HasArgumentTypeV >
+ struct arity_of_impl< FunT, false, false, HasArgumentTypeV, true > :
+ public mpl::int_< 2 >
+ {
+ };
+ template< typename FunT >
+ struct arity_of_impl< FunT, false, false, true, false > :
+ public mpl::int_< 1 >
+ {
+ };
+
+ //! The metafunction returns the arity of a function
+ template< typename FunT >
+ struct arity_of :
+ public arity_of_impl< FunT >
+ {
+ };
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // defined(BOOST_NO_SFINAE) || defined(BOOST_MPL_CFG_NO_HAS_XXX)
+
+#endif // BOOST_LOG_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED_
diff --git a/boost/log/detail/generate_overloads.hpp b/boost/log/detail/generate_overloads.hpp
new file mode 100644
index 0000000000..63b9edf081
--- /dev/null
+++ b/boost/log/detail/generate_overloads.hpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+BOOST_LOG_AUX_OVERLOAD(const&, const&)
+BOOST_LOG_AUX_OVERLOAD(&, const&)
+BOOST_LOG_AUX_OVERLOAD(const&, &)
+BOOST_LOG_AUX_OVERLOAD(&, &)
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+BOOST_LOG_AUX_OVERLOAD(const&&, const&&)
+BOOST_LOG_AUX_OVERLOAD(&&, const&&)
+BOOST_LOG_AUX_OVERLOAD(const&&, &&)
+BOOST_LOG_AUX_OVERLOAD(&&, &&)
+
+BOOST_LOG_AUX_OVERLOAD(const&&, const&)
+BOOST_LOG_AUX_OVERLOAD(&&, const&)
+BOOST_LOG_AUX_OVERLOAD(const&&, &)
+BOOST_LOG_AUX_OVERLOAD(&&, &)
+
+BOOST_LOG_AUX_OVERLOAD(const&, const&&)
+BOOST_LOG_AUX_OVERLOAD(&, const&&)
+BOOST_LOG_AUX_OVERLOAD(const&, &&)
+BOOST_LOG_AUX_OVERLOAD(&, &&)
+
+#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
diff --git a/boost/log/detail/header.hpp b/boost/log/detail/header.hpp
new file mode 100644
index 0000000000..f7cf75d557
--- /dev/null
+++ b/boost/log/detail/header.hpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#include <boost/config/abi_prefix.hpp>
+
+#if !defined(BOOST_LOG_ENABLE_WARNINGS)
+
+#if defined(_MSC_VER)
+
+#pragma warning(push, 3)
+// 'm_A' : class 'A' needs to have dll-interface to be used by clients of class 'B'
+#pragma warning(disable: 4251)
+// non dll-interface class 'A' used as base for dll-interface class 'B'
+#pragma warning(disable: 4275)
+// switch statement contains 'default' but no 'case' labels
+#pragma warning(disable: 4065)
+// 'this' : used in base member initializer list
+#pragma warning(disable: 4355)
+// 'int' : forcing value to bool 'true' or 'false' (performance warning)
+#pragma warning(disable: 4800)
+// unreferenced formal parameter
+#pragma warning(disable: 4100)
+// conditional expression is constant
+#pragma warning(disable: 4127)
+// default constructor could not be generated
+#pragma warning(disable: 4510)
+// copy constructor could not be generated
+#pragma warning(disable: 4511)
+// assignment operator could not be generated
+#pragma warning(disable: 4512)
+// struct 'A' can never be instantiated - user defined constructor required
+#pragma warning(disable: 4610)
+// function marked as __forceinline not inlined
+#pragma warning(disable: 4714)
+// decorated name length exceeded, name was truncated
+#pragma warning(disable: 4503)
+// declaration of 'A' hides previous local declaration
+#pragma warning(disable: 4456)
+// declaration of 'A' hides global declaration
+#pragma warning(disable: 4459)
+
+#elif defined(__GNUC__) && !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) \
+ && (__GNUC__ * 100 + __GNUC_MINOR__) >= 406
+
+#pragma GCC diagnostic push
+// 'var' defined but not used
+#pragma GCC diagnostic ignored "-Wunused-variable"
+// unused parameter 'arg'
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+// missing initializer for member var
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+
+#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407
+// typedef 'foo' locally defined but not used
+#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
+#endif
+
+#endif
+
+#endif // !defined(BOOST_LOG_ENABLE_WARNINGS)
diff --git a/boost/log/detail/id.hpp b/boost/log/detail/id.hpp
new file mode 100644
index 0000000000..2ca1e1e30d
--- /dev/null
+++ b/boost/log/detail/id.hpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file id.hpp
+ * \author Andrey Semashev
+ * \date 08.01.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_ID_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_ID_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! Generic identifier class
+template< typename DescriptorT >
+class id
+{
+public:
+ //! Native type of the process id
+ typedef typename DescriptorT::native_type native_type;
+
+private:
+ native_type m_NativeID;
+
+public:
+ BOOST_CONSTEXPR id() BOOST_NOEXCEPT : m_NativeID(0) {}
+
+ explicit id(native_type native) BOOST_NOEXCEPT : m_NativeID(native) {}
+
+ native_type native_id() const BOOST_NOEXCEPT { return m_NativeID; }
+
+ bool operator== (id const& that) const BOOST_NOEXCEPT
+ {
+ return (m_NativeID == that.m_NativeID);
+ }
+ bool operator!= (id const& that) const BOOST_NOEXCEPT
+ {
+ return (m_NativeID != that.m_NativeID);
+ }
+ bool operator< (id const& that) const BOOST_NOEXCEPT
+ {
+ return (m_NativeID < that.m_NativeID);
+ }
+ bool operator> (id const& that) const BOOST_NOEXCEPT
+ {
+ return (m_NativeID > that.m_NativeID);
+ }
+ bool operator<= (id const& that) const BOOST_NOEXCEPT
+ {
+ return (m_NativeID <= that.m_NativeID);
+ }
+ bool operator>= (id const& that) const BOOST_NOEXCEPT
+ {
+ return (m_NativeID >= that.m_NativeID);
+ }
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_ID_HPP_INCLUDED_
diff --git a/boost/log/detail/light_function.hpp b/boost/log/detail/light_function.hpp
new file mode 100644
index 0000000000..b673359e63
--- /dev/null
+++ b/boost/log/detail/light_function.hpp
@@ -0,0 +1,521 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file light_function.hpp
+ * \author Andrey Semashev
+ * \date 20.06.2010
+ *
+ * \brief This header is the Boost.Log library impl, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ *
+ * The file contains a lightweight alternative of Boost.Function. It does not provide all
+ * features of Boost.Function but doesn't introduce dependency on Boost.Bind.
+ */
+
+#ifndef BOOST_LOG_DETAIL_LIGHT_FUNCTION_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_LIGHT_FUNCTION_HPP_INCLUDED_
+
+#include <cstddef>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/utility/explicit_operator_bool.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/preprocessor/iteration/iterate.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
+#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
+#endif
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+#include <boost/utility/enable_if.hpp>
+#else
+#include <boost/type_traits/remove_reference.hpp>
+#endif
+#if defined(BOOST_NO_CXX11_NULLPTR)
+#include <boost/assert.hpp>
+#endif
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifndef BOOST_LOG_LIGHT_FUNCTION_LIMIT
+#define BOOST_LOG_LIGHT_FUNCTION_LIMIT 2
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+template< typename T, typename ThisT >
+struct is_cv_same { enum _ { value = false }; };
+template< typename T >
+struct is_cv_same< T, T > { enum _ { value = true }; };
+template< typename T >
+struct is_cv_same< T, const T > { enum _ { value = true }; };
+template< typename T >
+struct is_cv_same< T, volatile T > { enum _ { value = true }; };
+template< typename T >
+struct is_cv_same< T, const volatile T > { enum _ { value = true }; };
+
+template< typename T, typename ThisT >
+struct is_rv_or_same { enum _ { value = false }; };
+template< typename T >
+struct is_rv_or_same< T, T > { enum _ { value = true }; };
+template< typename T, typename ThisT >
+struct is_rv_or_same< boost::rv< T >, ThisT > { enum _ { value = true }; };
+
+#endif
+
+template< typename SignatureT >
+class light_function;
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+template< typename ResultT, typename... ArgsT >
+class light_function< ResultT (ArgsT...) >
+{
+ typedef light_function this_type;
+ BOOST_COPYABLE_AND_MOVABLE(this_type)
+
+public:
+ typedef ResultT result_type;
+
+private:
+ struct impl_base
+ {
+ typedef result_type (*invoke_type)(void*, ArgsT...);
+ const invoke_type invoke;
+
+ typedef impl_base* (*clone_type)(const void*);
+ const clone_type clone;
+
+ typedef void (*destroy_type)(void*);
+ const destroy_type destroy;
+
+ impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr)
+ {
+ }
+
+ BOOST_DELETED_FUNCTION(impl_base(impl_base const&))
+ BOOST_DELETED_FUNCTION(impl_base& operator= (impl_base const&))
+ };
+
+#if !defined(BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS)
+ template< typename FunT >
+ class impl;
+ template< typename FunT >
+ friend class impl;
+#endif
+
+ template< typename FunT >
+ class impl :
+ public impl_base
+ {
+ typedef impl< FunT > this_type;
+
+ FunT m_Function;
+
+ public:
+ explicit impl(FunT const& fun) :
+ impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl),
+ m_Function(fun)
+ {
+ }
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ explicit impl(FunT&& fun) :
+ impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl),
+ m_Function(boost::move(fun))
+ {
+ }
+#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+ static void destroy_impl(void* self)
+ {
+ delete static_cast< impl* >(static_cast< impl_base* >(self));
+ }
+ static impl_base* clone_impl(const void* self)
+ {
+ return new impl(static_cast< const impl* >(static_cast< const impl_base* >(self))->m_Function);
+ }
+ static result_type invoke_impl(void* self, ArgsT... args)
+ {
+ return static_cast< impl* >(static_cast< impl_base* >(self))->m_Function(args...);
+ }
+
+ BOOST_DELETED_FUNCTION(impl(impl const&))
+ BOOST_DELETED_FUNCTION(impl& operator= (impl const&))
+ };
+
+private:
+ impl_base* m_pImpl;
+
+public:
+ BOOST_CONSTEXPR light_function() BOOST_NOEXCEPT : m_pImpl(NULL)
+ {
+ }
+ light_function(this_type const& that)
+ {
+ if (that.m_pImpl)
+ m_pImpl = that.m_pImpl->clone(that.m_pImpl);
+ else
+ m_pImpl = NULL;
+ }
+
+ light_function(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
+ {
+ m_pImpl = that.m_pImpl;
+ that.m_pImpl = NULL;
+ }
+
+ light_function(BOOST_RV_REF(const this_type) that) BOOST_NOEXCEPT
+ {
+ m_pImpl = that.m_pImpl;
+ ((this_type&)that).m_pImpl = NULL;
+ }
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template< typename FunT >
+ light_function(FunT&& fun) :
+ m_pImpl(new impl< typename remove_cv< typename remove_reference< FunT >::type >::type >(boost::forward< FunT >(fun)))
+ {
+ }
+#else
+ template< typename FunT >
+ light_function(FunT const& fun, typename disable_if_c< is_rv_or_same< FunT, this_type >::value, int >::type = 0) :
+ m_pImpl(new impl< FunT >(fun))
+ {
+ }
+ template< typename FunT >
+ light_function(BOOST_RV_REF(FunT) fun, typename disable_if_c< is_cv_same< FunT, this_type >::value, int >::type = 0) :
+ m_pImpl(new impl< typename remove_cv< FunT >::type >(fun))
+ {
+ }
+#endif
+
+ //! Constructor from NULL
+#if !defined(BOOST_NO_CXX11_NULLPTR)
+ BOOST_CONSTEXPR light_function(std::nullptr_t) BOOST_NOEXCEPT
+#else
+ BOOST_CONSTEXPR light_function(int p) BOOST_NOEXCEPT
+#endif
+ : m_pImpl(NULL)
+ {
+#if defined(BOOST_NO_CXX11_NULLPTR)
+ BOOST_ASSERT(p == 0);
+#endif
+ }
+ ~light_function()
+ {
+ clear();
+ }
+
+ light_function& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
+ {
+ this->swap(that);
+ return *this;
+ }
+ light_function& operator= (BOOST_COPY_ASSIGN_REF(this_type) that)
+ {
+ light_function tmp = static_cast< this_type const& >(that);
+ this->swap(tmp);
+ return *this;
+ }
+ //! Assignment of NULL
+#if !defined(BOOST_NO_CXX11_NULLPTR)
+ light_function& operator= (std::nullptr_t)
+#else
+ light_function& operator= (int p)
+#endif
+ {
+#if defined(BOOST_NO_CXX11_NULLPTR)
+ BOOST_ASSERT(p == 0);
+#endif
+ clear();
+ return *this;
+ }
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template< typename FunT >
+ light_function& operator= (FunT&& fun)
+ {
+ light_function tmp(boost::forward< FunT >(fun));
+ this->swap(tmp);
+ return *this;
+ }
+#else
+ template< typename FunT >
+ typename disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type
+ operator= (FunT const& fun)
+ {
+ light_function tmp(fun);
+ this->swap(tmp);
+ return *this;
+ }
+#endif
+
+ result_type operator() (ArgsT... args) const
+ {
+ return m_pImpl->invoke(m_pImpl, args...);
+ }
+
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+ bool operator! () const BOOST_NOEXCEPT { return (m_pImpl == NULL); }
+ bool empty() const BOOST_NOEXCEPT { return (m_pImpl == NULL); }
+ void clear() BOOST_NOEXCEPT
+ {
+ if (m_pImpl)
+ {
+ m_pImpl->destroy(m_pImpl);
+ m_pImpl = NULL;
+ }
+ }
+
+ void swap(this_type& that) BOOST_NOEXCEPT
+ {
+ impl_base* p = m_pImpl;
+ m_pImpl = that.m_pImpl;
+ that.m_pImpl = p;
+ }
+};
+
+template< typename... ArgsT >
+class light_function< void (ArgsT...) >
+{
+ typedef light_function this_type;
+ BOOST_COPYABLE_AND_MOVABLE(this_type)
+
+public:
+ typedef void result_type;
+
+private:
+ struct impl_base
+ {
+ typedef void (*invoke_type)(void*, ArgsT...);
+ const invoke_type invoke;
+
+ typedef impl_base* (*clone_type)(const void*);
+ const clone_type clone;
+
+ typedef void (*destroy_type)(void*);
+ const destroy_type destroy;
+
+ impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr)
+ {
+ }
+
+ BOOST_DELETED_FUNCTION(impl_base(impl_base const&))
+ BOOST_DELETED_FUNCTION(impl_base& operator= (impl_base const&))
+ };
+
+#if !defined(BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS)
+ template< typename FunT >
+ class impl;
+ template< typename FunT >
+ friend class impl;
+#endif
+
+ template< typename FunT >
+ class impl :
+ public impl_base
+ {
+ typedef impl< FunT > this_type;
+
+ FunT m_Function;
+
+ public:
+ explicit impl(FunT const& fun) :
+ impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl),
+ m_Function(fun)
+ {
+ }
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ explicit impl(FunT&& fun) :
+ impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl),
+ m_Function(boost::move(fun))
+ {
+ }
+#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+ static void destroy_impl(void* self)
+ {
+ delete static_cast< impl* >(static_cast< impl_base* >(self));
+ }
+ static impl_base* clone_impl(const void* self)
+ {
+ return new impl(static_cast< const impl* >(static_cast< const impl_base* >(self))->m_Function);
+ }
+ static result_type invoke_impl(void* self, ArgsT... args)
+ {
+ static_cast< impl* >(static_cast< impl_base* >(self))->m_Function(args...);
+ }
+
+ BOOST_DELETED_FUNCTION(impl(impl const&))
+ BOOST_DELETED_FUNCTION(impl& operator= (impl const&))
+ };
+
+private:
+ impl_base* m_pImpl;
+
+public:
+ BOOST_CONSTEXPR light_function() BOOST_NOEXCEPT : m_pImpl(NULL)
+ {
+ }
+ light_function(this_type const& that)
+ {
+ if (that.m_pImpl)
+ m_pImpl = that.m_pImpl->clone(that.m_pImpl);
+ else
+ m_pImpl = NULL;
+ }
+ light_function(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
+ {
+ m_pImpl = that.m_pImpl;
+ that.m_pImpl = NULL;
+ }
+
+ light_function(BOOST_RV_REF(const this_type) that) BOOST_NOEXCEPT
+ {
+ m_pImpl = that.m_pImpl;
+ ((this_type&)that).m_pImpl = NULL;
+ }
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template< typename FunT >
+ light_function(FunT&& fun) :
+ m_pImpl(new impl< typename remove_cv< typename remove_reference< FunT >::type >::type >(boost::forward< FunT >(fun)))
+ {
+ }
+#else
+ template< typename FunT >
+ light_function(FunT const& fun, typename disable_if_c< is_rv_or_same< FunT, this_type >::value, int >::type = 0) :
+ m_pImpl(new impl< FunT >(fun))
+ {
+ }
+ template< typename FunT >
+ light_function(BOOST_RV_REF(FunT) fun, typename disable_if_c< is_cv_same< FunT, this_type >::value, int >::type = 0) :
+ m_pImpl(new impl< typename remove_cv< FunT >::type >(fun))
+ {
+ }
+#endif
+
+ //! Constructor from NULL
+#if !defined(BOOST_NO_CXX11_NULLPTR)
+ BOOST_CONSTEXPR light_function(std::nullptr_t) BOOST_NOEXCEPT
+#else
+ BOOST_CONSTEXPR light_function(int p) BOOST_NOEXCEPT
+#endif
+ : m_pImpl(NULL)
+ {
+#if defined(BOOST_NO_CXX11_NULLPTR)
+ BOOST_ASSERT(p == 0);
+#endif
+ }
+ ~light_function()
+ {
+ clear();
+ }
+
+ light_function& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
+ {
+ this->swap(that);
+ return *this;
+ }
+ light_function& operator= (BOOST_COPY_ASSIGN_REF(this_type) that)
+ {
+ light_function tmp = static_cast< this_type const& >(that);
+ this->swap(tmp);
+ return *this;
+ }
+ //! Assignment of NULL
+#if !defined(BOOST_NO_CXX11_NULLPTR)
+ light_function& operator= (std::nullptr_t)
+#else
+ light_function& operator= (int p)
+#endif
+ {
+#if defined(BOOST_NO_CXX11_NULLPTR)
+ BOOST_ASSERT(p == 0);
+#endif
+ clear();
+ return *this;
+ }
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template< typename FunT >
+ light_function& operator= (FunT&& fun)
+ {
+ light_function tmp(boost::forward< FunT >(fun));
+ this->swap(tmp);
+ return *this;
+ }
+#else
+ template< typename FunT >
+ typename disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type
+ operator= (FunT const& fun)
+ {
+ light_function tmp(fun);
+ this->swap(tmp);
+ return *this;
+ }
+#endif
+
+ result_type operator() (ArgsT... args) const
+ {
+ m_pImpl->invoke(m_pImpl, args...);
+ }
+
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+ bool operator! () const BOOST_NOEXCEPT { return (m_pImpl == NULL); }
+ bool empty() const BOOST_NOEXCEPT { return (m_pImpl == NULL); }
+ void clear() BOOST_NOEXCEPT
+ {
+ if (m_pImpl)
+ {
+ m_pImpl->destroy(m_pImpl);
+ m_pImpl = NULL;
+ }
+ }
+
+ void swap(this_type& that) BOOST_NOEXCEPT
+ {
+ impl_base* p = m_pImpl;
+ m_pImpl = that.m_pImpl;
+ that.m_pImpl = p;
+ }
+};
+
+#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+#define BOOST_PP_FILENAME_1 <boost/log/detail/light_function_pp.hpp>
+#define BOOST_PP_ITERATION_LIMITS (0, BOOST_LOG_LIGHT_FUNCTION_LIMIT)
+#include BOOST_PP_ITERATE()
+
+#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+template< typename SignatureT >
+inline void swap(light_function< SignatureT >& left, light_function< SignatureT >& right)
+{
+ left.swap(right);
+}
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_LIGHT_FUNCTION_HPP_INCLUDED_
diff --git a/boost/log/detail/light_function_pp.hpp b/boost/log/detail/light_function_pp.hpp
new file mode 100644
index 0000000000..55eca7cdd8
--- /dev/null
+++ b/boost/log/detail/light_function_pp.hpp
@@ -0,0 +1,424 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+template<
+ typename ResultT
+ BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), typename ArgT)
+>
+class light_function< ResultT (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT)) >
+{
+ typedef light_function this_type;
+ BOOST_COPYABLE_AND_MOVABLE(this_type)
+
+public:
+ typedef ResultT result_type;
+
+private:
+ struct impl_base
+ {
+ typedef result_type (*invoke_type)(void* BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), ArgT));
+ const invoke_type invoke;
+
+ typedef impl_base* (*clone_type)(const void*);
+ const clone_type clone;
+
+ typedef void (*destroy_type)(void*);
+ const destroy_type destroy;
+
+ impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr)
+ {
+ }
+
+ BOOST_DELETED_FUNCTION(impl_base(impl_base const&))
+ BOOST_DELETED_FUNCTION(impl_base& operator= (impl_base const&))
+ };
+
+#if !defined(BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS)
+ template< typename FunT >
+ class impl;
+ template< typename FunT >
+ friend class impl;
+#endif
+
+ template< typename FunT >
+ class impl :
+ public impl_base
+ {
+ typedef impl< FunT > this_type;
+
+ FunT m_Function;
+
+ public:
+ explicit impl(FunT const& fun) :
+ impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl),
+ m_Function(fun)
+ {
+ }
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ explicit impl(FunT&& fun) :
+ impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl),
+ m_Function(boost::move(fun))
+ {
+ }
+#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+ static void destroy_impl(void* self)
+ {
+ delete static_cast< impl* >(static_cast< impl_base* >(self));
+ }
+ static impl_base* clone_impl(const void* self)
+ {
+ return new impl(static_cast< const impl* >(static_cast< const impl_base* >(self))->m_Function);
+ }
+ static result_type invoke_impl(void* self BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg))
+ {
+ return static_cast< impl* >(static_cast< impl_base* >(self))->m_Function(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg));
+ }
+
+ BOOST_DELETED_FUNCTION(impl(impl const&))
+ BOOST_DELETED_FUNCTION(impl& operator= (impl const&))
+ };
+
+private:
+ impl_base* m_pImpl;
+
+public:
+ BOOST_CONSTEXPR light_function() BOOST_NOEXCEPT : m_pImpl(NULL)
+ {
+ }
+ light_function(this_type const& that)
+ {
+ if (that.m_pImpl)
+ m_pImpl = that.m_pImpl->clone(that.m_pImpl);
+ else
+ m_pImpl = NULL;
+ }
+
+ light_function(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
+ {
+ m_pImpl = that.m_pImpl;
+ that.m_pImpl = NULL;
+ }
+
+ light_function(BOOST_RV_REF(const this_type) that) BOOST_NOEXCEPT
+ {
+ m_pImpl = that.m_pImpl;
+ ((this_type&)that).m_pImpl = NULL;
+ }
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template< typename FunT >
+ light_function(FunT&& fun) :
+ m_pImpl(new impl< typename remove_cv< typename remove_reference< FunT >::type >::type >(boost::forward< FunT >(fun)))
+ {
+ }
+#else
+ template< typename FunT >
+ light_function(FunT const& fun, typename disable_if_c< is_rv_or_same< FunT, this_type >::value, int >::type = 0) :
+ m_pImpl(new impl< FunT >(fun))
+ {
+ }
+ template< typename FunT >
+ light_function(BOOST_RV_REF(FunT) fun, typename disable_if_c< is_cv_same< FunT, this_type >::value, int >::type = 0) :
+ m_pImpl(new impl< typename remove_cv< FunT >::type >(fun))
+ {
+ }
+#endif
+
+ //! Constructor from NULL
+#if !defined(BOOST_NO_CXX11_NULLPTR)
+ BOOST_CONSTEXPR light_function(std::nullptr_t) BOOST_NOEXCEPT
+#else
+ BOOST_CONSTEXPR light_function(int p) BOOST_NOEXCEPT
+#endif
+ : m_pImpl(NULL)
+ {
+#if defined(BOOST_NO_CXX11_NULLPTR)
+ BOOST_ASSERT(p == 0);
+#endif
+ }
+ ~light_function()
+ {
+ clear();
+ }
+
+ light_function& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
+ {
+ this->swap(that);
+ return *this;
+ }
+ light_function& operator= (BOOST_COPY_ASSIGN_REF(this_type) that)
+ {
+ light_function tmp = static_cast< this_type const& >(that);
+ this->swap(tmp);
+ return *this;
+ }
+ //! Assignment of NULL
+#if !defined(BOOST_NO_CXX11_NULLPTR)
+ light_function& operator= (std::nullptr_t)
+#else
+ light_function& operator= (int p)
+#endif
+ {
+#if defined(BOOST_NO_CXX11_NULLPTR)
+ BOOST_ASSERT(p == 0);
+#endif
+ clear();
+ return *this;
+ }
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template< typename FunT >
+ light_function& operator= (FunT&& fun)
+ {
+ light_function tmp(boost::forward< FunT >(fun));
+ this->swap(tmp);
+ return *this;
+ }
+#else
+ template< typename FunT >
+ typename disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type
+ operator= (FunT const& fun)
+ {
+ light_function tmp(fun);
+ this->swap(tmp);
+ return *this;
+ }
+#endif
+
+ result_type operator() (BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg)) const
+ {
+ return m_pImpl->invoke(m_pImpl BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), arg));
+ }
+
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+ bool operator! () const BOOST_NOEXCEPT { return (m_pImpl == NULL); }
+ bool empty() const BOOST_NOEXCEPT { return (m_pImpl == NULL); }
+ void clear() BOOST_NOEXCEPT
+ {
+ if (m_pImpl)
+ {
+ m_pImpl->destroy(m_pImpl);
+ m_pImpl = NULL;
+ }
+ }
+
+ void swap(this_type& that) BOOST_NOEXCEPT
+ {
+ impl_base* p = m_pImpl;
+ m_pImpl = that.m_pImpl;
+ that.m_pImpl = p;
+ }
+};
+
+template<
+ BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), typename ArgT)
+>
+class light_function< void (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT)) >
+{
+ typedef light_function this_type;
+ BOOST_COPYABLE_AND_MOVABLE(this_type)
+
+public:
+ typedef void result_type;
+
+private:
+ struct impl_base
+ {
+ typedef void (*invoke_type)(void* BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), ArgT));
+ const invoke_type invoke;
+
+ typedef impl_base* (*clone_type)(const void*);
+ const clone_type clone;
+
+ typedef void (*destroy_type)(void*);
+ const destroy_type destroy;
+
+ impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr)
+ {
+ }
+
+ BOOST_DELETED_FUNCTION(impl_base(impl_base const&))
+ BOOST_DELETED_FUNCTION(impl_base& operator= (impl_base const&))
+ };
+
+#if !defined(BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS)
+ template< typename FunT >
+ class impl;
+ template< typename FunT >
+ friend class impl;
+#endif
+
+ template< typename FunT >
+ class impl :
+ public impl_base
+ {
+ typedef impl< FunT > this_type;
+
+ FunT m_Function;
+
+ public:
+ explicit impl(FunT const& fun) :
+ impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl),
+ m_Function(fun)
+ {
+ }
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ explicit impl(FunT&& fun) :
+ impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl),
+ m_Function(boost::move(fun))
+ {
+ }
+#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+ static void destroy_impl(void* self)
+ {
+ delete static_cast< impl* >(static_cast< impl_base* >(self));
+ }
+ static impl_base* clone_impl(const void* self)
+ {
+ return new impl(static_cast< const impl* >(static_cast< const impl_base* >(self))->m_Function);
+ }
+ static result_type invoke_impl(void* self BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg))
+ {
+ static_cast< impl* >(static_cast< impl_base* >(self))->m_Function(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg));
+ }
+
+ BOOST_DELETED_FUNCTION(impl(impl const&))
+ BOOST_DELETED_FUNCTION(impl& operator= (impl const&))
+ };
+
+private:
+ impl_base* m_pImpl;
+
+public:
+ BOOST_CONSTEXPR light_function() BOOST_NOEXCEPT : m_pImpl(NULL)
+ {
+ }
+ light_function(this_type const& that)
+ {
+ if (that.m_pImpl)
+ m_pImpl = that.m_pImpl->clone(that.m_pImpl);
+ else
+ m_pImpl = NULL;
+ }
+ light_function(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
+ {
+ m_pImpl = that.m_pImpl;
+ that.m_pImpl = NULL;
+ }
+
+ light_function(BOOST_RV_REF(const this_type) that) BOOST_NOEXCEPT
+ {
+ m_pImpl = that.m_pImpl;
+ ((this_type&)that).m_pImpl = NULL;
+ }
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template< typename FunT >
+ light_function(FunT&& fun) :
+ m_pImpl(new impl< typename remove_cv< typename remove_reference< FunT >::type >::type >(boost::forward< FunT >(fun)))
+ {
+ }
+#else
+ template< typename FunT >
+ light_function(FunT const& fun, typename disable_if_c< is_rv_or_same< FunT, this_type >::value, int >::type = 0) :
+ m_pImpl(new impl< FunT >(fun))
+ {
+ }
+ template< typename FunT >
+ light_function(BOOST_RV_REF(FunT) fun, typename disable_if_c< is_cv_same< FunT, this_type >::value, int >::type = 0) :
+ m_pImpl(new impl< typename remove_cv< FunT >::type >(fun))
+ {
+ }
+#endif
+
+ //! Constructor from NULL
+#if !defined(BOOST_NO_CXX11_NULLPTR)
+ BOOST_CONSTEXPR light_function(std::nullptr_t) BOOST_NOEXCEPT
+#else
+ BOOST_CONSTEXPR light_function(int p) BOOST_NOEXCEPT
+#endif
+ : m_pImpl(NULL)
+ {
+#if defined(BOOST_NO_CXX11_NULLPTR)
+ BOOST_ASSERT(p == 0);
+#endif
+ }
+ ~light_function()
+ {
+ clear();
+ }
+
+ light_function& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
+ {
+ this->swap(that);
+ return *this;
+ }
+ light_function& operator= (BOOST_COPY_ASSIGN_REF(this_type) that)
+ {
+ light_function tmp = static_cast< this_type const& >(that);
+ this->swap(tmp);
+ return *this;
+ }
+ //! Assignment of NULL
+#if !defined(BOOST_NO_CXX11_NULLPTR)
+ light_function& operator= (std::nullptr_t)
+#else
+ light_function& operator= (int p)
+#endif
+ {
+#if defined(BOOST_NO_CXX11_NULLPTR)
+ BOOST_ASSERT(p == 0);
+#endif
+ clear();
+ return *this;
+ }
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template< typename FunT >
+ light_function& operator= (FunT&& fun)
+ {
+ light_function tmp(boost::forward< FunT >(fun));
+ this->swap(tmp);
+ return *this;
+ }
+#else
+ template< typename FunT >
+ typename disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type
+ operator= (FunT const& fun)
+ {
+ light_function tmp(fun);
+ this->swap(tmp);
+ return *this;
+ }
+#endif
+
+ result_type operator() (BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg)) const
+ {
+ m_pImpl->invoke(m_pImpl BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), arg));
+ }
+
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+ bool operator! () const BOOST_NOEXCEPT { return (m_pImpl == NULL); }
+ bool empty() const BOOST_NOEXCEPT { return (m_pImpl == NULL); }
+ void clear() BOOST_NOEXCEPT
+ {
+ if (m_pImpl)
+ {
+ m_pImpl->destroy(m_pImpl);
+ m_pImpl = NULL;
+ }
+ }
+
+ void swap(this_type& that) BOOST_NOEXCEPT
+ {
+ impl_base* p = m_pImpl;
+ m_pImpl = that.m_pImpl;
+ that.m_pImpl = p;
+ }
+};
diff --git a/boost/log/detail/light_rw_mutex.hpp b/boost/log/detail/light_rw_mutex.hpp
new file mode 100644
index 0000000000..abfef13972
--- /dev/null
+++ b/boost/log/detail/light_rw_mutex.hpp
@@ -0,0 +1,208 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file light_rw_mutex.hpp
+ * \author Andrey Semashev
+ * \date 24.03.2009
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_LIGHT_RW_MUTEX_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_LIGHT_RW_MUTEX_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifndef BOOST_LOG_NO_THREADS
+
+#include <boost/log/detail/header.hpp>
+
+#if defined(BOOST_THREAD_POSIX) // This one can be defined by users, so it should go first
+#define BOOST_LOG_LWRWMUTEX_USE_PTHREAD
+#elif defined(BOOST_WINDOWS) && defined(BOOST_LOG_USE_WINNT6_API)
+#define BOOST_LOG_LWRWMUTEX_USE_SRWLOCK
+#elif defined(BOOST_HAS_PTHREADS)
+#define BOOST_LOG_LWRWMUTEX_USE_PTHREAD
+#endif
+
+#if defined(BOOST_LOG_LWRWMUTEX_USE_SRWLOCK)
+
+#if defined(BOOST_USE_WINDOWS_H)
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0600 // _WIN32_WINNT_LONGHORN
+#endif
+
+#include <windows.h>
+
+#else // defined(BOOST_USE_WINDOWS_H)
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+extern "C" {
+
+struct SRWLOCK { void* p; };
+__declspec(dllimport) void __stdcall InitializeSRWLock(SRWLOCK*);
+__declspec(dllimport) void __stdcall ReleaseSRWLockExclusive(SRWLOCK*);
+__declspec(dllimport) void __stdcall ReleaseSRWLockShared(SRWLOCK*);
+__declspec(dllimport) void __stdcall AcquireSRWLockExclusive(SRWLOCK*);
+__declspec(dllimport) void __stdcall AcquireSRWLockShared(SRWLOCK*);
+
+} // extern "C"
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_USE_WINDOWS_H
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! A light read/write mutex that uses WinNT 6 and later APIs
+class light_rw_mutex
+{
+ SRWLOCK m_Mutex;
+
+public:
+ light_rw_mutex()
+ {
+ InitializeSRWLock(&m_Mutex);
+ }
+ void lock_shared()
+ {
+ AcquireSRWLockShared(&m_Mutex);
+ }
+ void unlock_shared()
+ {
+ ReleaseSRWLockShared(&m_Mutex);
+ }
+ void lock()
+ {
+ AcquireSRWLockExclusive(&m_Mutex);
+ }
+ void unlock()
+ {
+ ReleaseSRWLockExclusive(&m_Mutex);
+ }
+
+ // Noncopyable
+ BOOST_DELETED_FUNCTION(light_rw_mutex(light_rw_mutex const&))
+ BOOST_DELETED_FUNCTION(light_rw_mutex& operator= (light_rw_mutex const&))
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#elif defined(BOOST_LOG_LWRWMUTEX_USE_PTHREAD)
+
+#include <pthread.h>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! A light read/write mutex that maps directly onto POSIX threading library
+class light_rw_mutex
+{
+ pthread_rwlock_t m_Mutex;
+
+public:
+ light_rw_mutex()
+ {
+ pthread_rwlock_init(&m_Mutex, NULL);
+ }
+ ~light_rw_mutex()
+ {
+ pthread_rwlock_destroy(&m_Mutex);
+ }
+ void lock_shared()
+ {
+ pthread_rwlock_rdlock(&m_Mutex);
+ }
+ void unlock_shared()
+ {
+ pthread_rwlock_unlock(&m_Mutex);
+ }
+ void lock()
+ {
+ pthread_rwlock_wrlock(&m_Mutex);
+ }
+ void unlock()
+ {
+ pthread_rwlock_unlock(&m_Mutex);
+ }
+
+ // Noncopyable
+ BOOST_DELETED_FUNCTION(light_rw_mutex(light_rw_mutex const&))
+ BOOST_DELETED_FUNCTION(light_rw_mutex& operator= (light_rw_mutex const&))
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#else
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! A light read/write mutex
+class light_rw_mutex
+{
+ struct { void* p; } m_Mutex;
+
+public:
+ BOOST_LOG_API light_rw_mutex();
+ BOOST_LOG_API ~light_rw_mutex();
+ BOOST_LOG_API void lock_shared();
+ BOOST_LOG_API void unlock_shared();
+ BOOST_LOG_API void lock();
+ BOOST_LOG_API void unlock();
+
+ // Noncopyable
+ BOOST_DELETED_FUNCTION(light_rw_mutex(light_rw_mutex const&))
+ BOOST_DELETED_FUNCTION(light_rw_mutex& operator= (light_rw_mutex const&))
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_NO_THREADS
+
+#endif // BOOST_LOG_DETAIL_LIGHT_RW_MUTEX_HPP_INCLUDED_
diff --git a/boost/log/detail/locking_ptr.hpp b/boost/log/detail/locking_ptr.hpp
new file mode 100644
index 0000000000..913780e98e
--- /dev/null
+++ b/boost/log/detail/locking_ptr.hpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file locking_ptr.hpp
+ * \author Andrey Semashev
+ * \date 15.07.2009
+ *
+ * This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_
+
+#include <cstddef>
+#include <boost/move/core.hpp>
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/thread/lock_options.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/utility/explicit_operator_bool.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! A pointer type that locks the backend until it's destroyed
+template< typename T, typename LockableT >
+class locking_ptr
+{
+ typedef locking_ptr this_type;
+ BOOST_COPYABLE_AND_MOVABLE_ALT(this_type)
+
+public:
+ //! Pointed type
+ typedef T element_type;
+
+private:
+ //! Lockable type
+ typedef LockableT lockable_type;
+
+private:
+ //! The pointer to the backend
+ shared_ptr< element_type > m_pElement;
+ //! Reference to the shared lock control object
+ lockable_type* m_pLock;
+
+public:
+ //! Default constructor
+ locking_ptr() BOOST_NOEXCEPT : m_pLock(NULL)
+ {
+ }
+ //! Constructor
+ locking_ptr(shared_ptr< element_type > const& p, lockable_type& l) : m_pElement(p), m_pLock(&l)
+ {
+ m_pLock->lock();
+ }
+ //! Constructor
+ locking_ptr(shared_ptr< element_type > const& p, lockable_type& l, try_to_lock_t const&) : m_pElement(p), m_pLock(&l)
+ {
+ if (!m_pLock->try_lock())
+ {
+ m_pElement.reset();
+ m_pLock = NULL;
+ }
+ }
+ //! Copy constructor
+ locking_ptr(locking_ptr const& that) : m_pElement(that.m_pElement), m_pLock(that.m_pLock)
+ {
+ if (m_pLock)
+ m_pLock->lock();
+ }
+ //! Move constructor
+ locking_ptr(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT : m_pLock(that.m_pLock)
+ {
+ m_pElement.swap(that.m_pElement);
+ that.m_pLock = NULL;
+ }
+
+ //! Destructor
+ ~locking_ptr()
+ {
+ if (m_pLock)
+ m_pLock->unlock();
+ }
+
+ //! Assignment
+ locking_ptr& operator= (locking_ptr that) BOOST_NOEXCEPT
+ {
+ this->swap(that);
+ return *this;
+ }
+
+ //! Indirection
+ element_type* operator-> () const BOOST_NOEXCEPT { return m_pElement.get(); }
+ //! Dereferencing
+ element_type& operator* () const BOOST_NOEXCEPT { return *m_pElement; }
+
+ //! Accessor to the raw pointer
+ element_type* get() const BOOST_NOEXCEPT { return m_pElement.get(); }
+
+ //! Checks for null pointer
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+ //! Checks for null pointer
+ bool operator! () const BOOST_NOEXCEPT { return !m_pElement; }
+
+ //! Swaps two pointers
+ void swap(locking_ptr& that) BOOST_NOEXCEPT
+ {
+ m_pElement.swap(that.m_pElement);
+ lockable_type* p = m_pLock;
+ m_pLock = that.m_pLock;
+ that.m_pLock = p;
+ }
+};
+
+//! Free raw pointer getter to assist generic programming
+template< typename T, typename LockableT >
+inline T* get_pointer(locking_ptr< T, LockableT > const& p) BOOST_NOEXCEPT
+{
+ return p.get();
+}
+//! Free swap operation
+template< typename T, typename LockableT >
+inline void swap(locking_ptr< T, LockableT >& left, locking_ptr< T, LockableT >& right) BOOST_NOEXCEPT
+{
+ left.swap(right);
+}
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_
diff --git a/boost/log/detail/locks.hpp b/boost/log/detail/locks.hpp
new file mode 100644
index 0000000000..72b8945b26
--- /dev/null
+++ b/boost/log/detail/locks.hpp
@@ -0,0 +1,180 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file locks.hpp
+ * \author Andrey Semashev
+ * \date 30.05.2010
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_LOCKS_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_LOCKS_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+#ifndef BOOST_LOG_NO_THREADS
+
+// Forward declaration of Boost.Thread locks. Specified here to avoid including Boost.Thread,
+// which would bring in many dependent headers, including a great deal of Boost.DateTime.
+template< typename >
+class lock_guard;
+template< typename >
+class shared_lock;
+template< typename >
+class upgrade_lock;
+template< typename >
+class unique_lock;
+
+template< typename >
+struct is_mutex_type;
+
+#endif // BOOST_LOG_NO_THREADS
+
+BOOST_LOG_OPEN_NAMESPACE
+
+//! An auxiliary pseudo-lock to express no locking requirements in logger features
+template< typename MutexT >
+class no_lock
+{
+public:
+ /*!
+ * Constructs the pseudo-lock. The mutex is not affected during the construction.
+ */
+ explicit no_lock(MutexT&) {}
+
+private:
+ no_lock(no_lock const&);
+ no_lock& operator= (no_lock const&);
+};
+
+namespace aux {
+
+#ifndef BOOST_LOG_NO_THREADS
+
+//! A trait to detect if the mutex supports exclusive locking
+template< typename MutexT >
+struct is_exclusively_lockable
+{
+ typedef char true_type;
+ struct false_type { char t[2]; };
+
+ template< typename T >
+ static true_type check_lockable(T*, void (T::*)() = &T::lock, void (T::*)() = &T::unlock);
+ static false_type check_lockable(void*);
+
+ enum value_t { value = sizeof(check_lockable((MutexT*)NULL)) == sizeof(true_type) };
+};
+
+//! A trait to detect if the mutex supports shared locking
+template< typename MutexT >
+struct is_shared_lockable
+{
+ typedef char true_type;
+ struct false_type { char t[2]; };
+
+ template< typename T >
+ static true_type check_shared_lockable(T*, void (T::*)() = &T::lock_shared, void (T::*)() = &T::unlock_shared);
+ static false_type check_shared_lockable(void*);
+
+ enum value_t { value = sizeof(check_shared_lockable((MutexT*)NULL)) == sizeof(true_type) };
+};
+
+//! An analogue to the minimalistic \c lock_guard template. Defined here to avoid including Boost.Thread.
+template< typename MutexT >
+struct exclusive_lock_guard
+{
+ explicit exclusive_lock_guard(MutexT& m) : m_Mutex(m)
+ {
+ m.lock();
+ }
+ ~exclusive_lock_guard()
+ {
+ m_Mutex.unlock();
+ }
+
+private:
+ exclusive_lock_guard(exclusive_lock_guard const&);
+ exclusive_lock_guard& operator= (exclusive_lock_guard const&);
+
+private:
+ MutexT& m_Mutex;
+};
+
+//! An analogue to the minimalistic \c lock_guard template that locks \c shared_mutex with shared ownership.
+template< typename MutexT >
+struct shared_lock_guard
+{
+ explicit shared_lock_guard(MutexT& m) : m_Mutex(m)
+ {
+ m.lock_shared();
+ }
+ ~shared_lock_guard()
+ {
+ m_Mutex.unlock_shared();
+ }
+
+private:
+ shared_lock_guard(shared_lock_guard const&);
+ shared_lock_guard& operator= (shared_lock_guard const&);
+
+private:
+ MutexT& m_Mutex;
+};
+
+//! A deadlock-safe lock type that exclusively locks two mutexes
+template< typename MutexT1, typename MutexT2 >
+class multiple_unique_lock2
+{
+public:
+ multiple_unique_lock2(MutexT1& m1, MutexT2& m2) :
+ m_p1(&m1),
+ m_p2(&m2)
+ {
+ // Yes, it's not conforming, but it works
+ // and it doesn't require to #include <functional>
+ if (static_cast< void* >(m_p1) < static_cast< void* >(m_p2))
+ {
+ m_p1->lock();
+ m_p2->lock();
+ }
+ else
+ {
+ m_p2->lock();
+ m_p1->lock();
+ }
+ }
+ ~multiple_unique_lock2()
+ {
+ m_p2->unlock();
+ m_p1->unlock();
+ }
+
+private:
+ MutexT1* m_p1;
+ MutexT2* m_p2;
+};
+
+#endif // BOOST_LOG_NO_THREADS
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_LOCKS_HPP_INCLUDED_
diff --git a/boost/log/detail/named_scope_fmt_pp.hpp b/boost/log/detail/named_scope_fmt_pp.hpp
new file mode 100644
index 0000000000..d9f0027f86
--- /dev/null
+++ b/boost/log/detail/named_scope_fmt_pp.hpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+template< BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), typename ArgT) >
+BOOST_FORCEINLINE format_named_scope_actor<
+ fallback_to_none,
+ typename boost::log::aux::deduce_char_type<
+ typename parameter::binding<
+ typename boost::log::aux::make_arg_list< BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT) >::type,
+ keywords::tag::format,
+ void
+ >::type
+ >::type
+> format_named_scope(attribute_name const& name, BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, const& arg))
+{
+ typedef typename boost::log::aux::deduce_char_type<
+ typename parameter::binding<
+ typename boost::log::aux::make_arg_list< BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT) >::type,
+ keywords::tag::format,
+ void
+ >::type
+ >::type char_type;
+ return aux::format_named_scope< char_type, phoenix::actor >(name, fallback_to_none(), (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg)));
+}
+
+template< typename DescriptorT, template< typename > class ActorT, BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), typename ArgT) >
+BOOST_FORCEINLINE format_named_scope_actor<
+ fallback_to_none,
+ typename boost::log::aux::deduce_char_type<
+ typename parameter::binding<
+ typename boost::log::aux::make_arg_list< BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT) >::type,
+ keywords::tag::format,
+ void
+ >::type
+ >::type,
+ ActorT
+>
+format_named_scope(attribute_keyword< DescriptorT, ActorT > const& keyword, BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, const& arg))
+{
+ BOOST_STATIC_ASSERT_MSG((is_same< typename DescriptorT::value_type, attributes::named_scope::value_type >::value),\
+ "Boost.Log: Named scope formatter only accepts attribute values of type attributes::named_scope::value_type.");
+
+ typedef typename boost::log::aux::deduce_char_type<
+ typename parameter::binding<
+ typename boost::log::aux::make_arg_list< BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT) >::type,
+ keywords::tag::format,
+ void
+ >::type
+ >::type char_type;
+ return aux::format_named_scope< char_type, ActorT >(keyword.get_name(), fallback_to_none(), (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg)));
+}
+
+template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), typename ArgT) >
+BOOST_FORCEINLINE format_named_scope_actor<
+ FallbackPolicyT,
+ typename boost::log::aux::deduce_char_type<
+ typename parameter::binding<
+ typename boost::log::aux::make_arg_list< BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT) >::type,
+ keywords::tag::format,
+ void
+ >::type
+ >::type,
+ ActorT
+>
+format_named_scope(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& placeholder, BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, const& arg))
+{
+ BOOST_STATIC_ASSERT_MSG((is_same< T, attributes::named_scope::value_type >::value),\
+ "Boost.Log: Named scope formatter only accepts attribute values of type attributes::named_scope::value_type.");
+
+ typedef typename boost::log::aux::deduce_char_type<
+ typename parameter::binding<
+ typename boost::log::aux::make_arg_list< BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT) >::type,
+ keywords::tag::format,
+ void
+ >::type
+ >::type char_type;
+ return aux::format_named_scope< char_type, ActorT >(placeholder.get_name(), placeholder.get_fallback_policy(), (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg)));
+}
diff --git a/boost/log/detail/native_typeof.hpp b/boost/log/detail/native_typeof.hpp
new file mode 100644
index 0000000000..276b2942e8
--- /dev/null
+++ b/boost/log/detail/native_typeof.hpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file native_typeof.hpp
+ * \author Andrey Semashev
+ * \date 08.03.2009
+ *
+ * This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_NATIVE_TYPEOF_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_NATIVE_TYPEOF_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if !defined(BOOST_NO_CXX11_DECLTYPE)
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+template< typename T >
+T get_root_type(T const&);
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#define BOOST_LOG_TYPEOF(x) decltype(::boost::log::aux::get_root_type(x))
+
+#elif defined(__COMO__) && defined(__GNUG__)
+
+#define BOOST_LOG_TYPEOF(x) typeof(x)
+
+#elif defined(__GNUC__) || defined(__MWERKS__)
+
+#define BOOST_LOG_TYPEOF(x) __typeof__(x)
+
+#endif
+
+
+#if !defined(BOOST_NO_CXX11_AUTO_DECLARATIONS)
+#define BOOST_LOG_AUTO(var, expr) auto var = (expr)
+#endif
+
+#if !defined(BOOST_LOG_AUTO) && defined(BOOST_LOG_TYPEOF)
+#define BOOST_LOG_AUTO(var, expr) BOOST_LOG_TYPEOF((expr)) var = (expr)
+#endif
+
+#endif // BOOST_LOG_DETAIL_NATIVE_TYPEOF_HPP_INCLUDED_
diff --git a/boost/log/detail/parameter_tools.hpp b/boost/log/detail/parameter_tools.hpp
new file mode 100644
index 0000000000..692a3377d3
--- /dev/null
+++ b/boost/log/detail/parameter_tools.hpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file parameter_tools.hpp
+ * \author Andrey Semashev
+ * \date 28.06.2009
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_PARAMETER_TOOLS_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_PARAMETER_TOOLS_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+#include <boost/preprocessor/facilities/intercept.hpp>
+#include <boost/preprocessor/arithmetic/dec.hpp>
+#include <boost/preprocessor/tuple/elem.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifndef BOOST_LOG_MAX_PARAMETER_ARGS
+//! The maximum number of named arguments that are accepted by constructors and functions
+#define BOOST_LOG_MAX_PARAMETER_ARGS 16
+#endif
+
+// The macro applies the passed macro with the specified arguments BOOST_LOG_MAX_PARAMETER_ARGS times
+#define BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(macro, args)\
+ public:\
+ BOOST_PP_REPEAT_FROM_TO(1, BOOST_LOG_MAX_PARAMETER_ARGS, macro, args)
+
+
+#define BOOST_LOG_CTOR_FORWARD(z, n, types)\
+ template< BOOST_PP_ENUM_PARAMS(n, typename T) >\
+ explicit BOOST_PP_TUPLE_ELEM(2, 0, types)(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg)) :\
+ BOOST_PP_TUPLE_ELEM(2, 1, types)((BOOST_PP_ENUM_PARAMS(n, arg))) {}
+
+// The macro expands to a number of templated constructors that aggregate their named arguments
+// into an ArgumentsPack and pass it to the base class constructor.
+#define BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_FORWARD(class_type, base_type)\
+ BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(BOOST_LOG_CTOR_FORWARD, (class_type, base_type))
+
+
+#define BOOST_LOG_CTOR_CALL(z, n, types)\
+ template< BOOST_PP_ENUM_PARAMS(n, typename T) >\
+ explicit BOOST_PP_TUPLE_ELEM(2, 0, types)(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg))\
+ { BOOST_PP_TUPLE_ELEM(2, 1, types)((BOOST_PP_ENUM_PARAMS(n, arg))); }
+
+// The macro expands to a number of templated constructors that aggregate their named arguments
+// into an ArgumentsPack and pass it to a function call.
+#define BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_CALL(class_type, fun)\
+ BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(BOOST_LOG_CTOR_CALL, (class_type, fun))
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+// Yeah, not too cute. The empty_arg_list class should really be public.
+typedef boost::parameter::aux::empty_arg_list empty_arg_list;
+
+#if !(defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_LOG_NO_CXX11_ARG_PACKS_TO_NON_VARIADIC_ARGS_EXPANSION))
+
+//! The metafunction generates argument pack
+template< typename ArgT0, typename... ArgsT >
+struct make_arg_list
+{
+ typedef boost::parameter::aux::arg_list< ArgT0, typename make_arg_list< ArgsT... >::type > type;
+};
+
+template< typename ArgT0 >
+struct make_arg_list< ArgT0 >
+{
+ typedef boost::parameter::aux::arg_list< ArgT0 > type;
+};
+
+#else
+
+//! The metafunction generates argument pack
+template< typename ArgT0, BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_DEC(BOOST_LOG_MAX_PARAMETER_ARGS), typename T, = void BOOST_PP_INTERCEPT) >
+struct make_arg_list
+{
+ typedef boost::parameter::aux::arg_list< ArgT0, typename make_arg_list< BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(BOOST_LOG_MAX_PARAMETER_ARGS), T) >::type > type;
+};
+
+template< typename ArgT0 >
+struct make_arg_list< ArgT0, BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(BOOST_LOG_MAX_PARAMETER_ARGS), void BOOST_PP_INTERCEPT) >
+{
+ typedef boost::parameter::aux::arg_list< ArgT0 > type;
+};
+
+#endif
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_PARAMETER_TOOLS_HPP_INCLUDED_
diff --git a/boost/log/detail/pp_identity.hpp b/boost/log/detail/pp_identity.hpp
new file mode 100644
index 0000000000..8daaf951b8
--- /dev/null
+++ b/boost/log/detail/pp_identity.hpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file pp_identity.hpp
+ * \author Andrey Semashev
+ * \date 12.02.2011
+ *
+ * This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_PP_IDENTITY_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_PP_IDENTITY_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#define BOOST_LOG_PP_IDENTITY(z, n, data) data
+
+#endif // BOOST_LOG_DETAIL_PP_IDENTITY_HPP_INCLUDED_
diff --git a/boost/log/detail/process_id.hpp b/boost/log/detail/process_id.hpp
new file mode 100644
index 0000000000..3532506c2a
--- /dev/null
+++ b/boost/log/detail/process_id.hpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file process_id.hpp
+ * \author Andrey Semashev
+ * \date 12.09.2009
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_PROCESS_ID_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_PROCESS_ID_HPP_INCLUDED_
+
+#include <iosfwd>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/id.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! The process id descriptor
+struct process
+{
+ typedef unsigned long native_type;
+ typedef boost::log::aux::id< process > id;
+};
+
+namespace this_process {
+
+//! The function returns current process identifier
+BOOST_LOG_API process::id get_id();
+
+} // namespace this_process
+
+template< typename CharT, typename TraitsT >
+BOOST_LOG_API std::basic_ostream< CharT, TraitsT >&
+operator<< (std::basic_ostream< CharT, TraitsT >& strm, process::id const& pid);
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_PROCESS_ID_HPP_INCLUDED_
diff --git a/boost/log/detail/setup_config.hpp b/boost/log/detail/setup_config.hpp
new file mode 100644
index 0000000000..11239592af
--- /dev/null
+++ b/boost/log/detail/setup_config.hpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file setup_config.hpp
+ * \author Andrey Semashev
+ * \date 14.09.2009
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. In this file
+ * internal configuration macros are defined.
+ */
+
+#ifndef BOOST_LOG_DETAIL_SETUP_CONFIG_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_SETUP_CONFIG_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if !defined(BOOST_LOG_SETUP_BUILDING_THE_LIB)
+
+// Detect if we're dealing with dll
+# if defined(BOOST_LOG_SETUP_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)
+# define BOOST_LOG_SETUP_DLL
+# endif
+
+# if defined(BOOST_HAS_DECLSPEC) && defined(BOOST_LOG_SETUP_DLL)
+# define BOOST_LOG_SETUP_API __declspec(dllimport)
+# else
+# define BOOST_LOG_SETUP_API
+# endif // defined(BOOST_HAS_DECLSPEC)
+//
+// Automatically link to the correct build variant where possible.
+//
+# if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_LOG_SETUP_NO_LIB)
+# define BOOST_LIB_NAME boost_log_setup
+# if defined(BOOST_LOG_SETUP_DLL)
+# define BOOST_DYN_LINK
+# endif
+# include <boost/config/auto_link.hpp>
+# endif // auto-linking disabled
+
+#else // !defined(BOOST_LOG_SETUP_BUILDING_THE_LIB)
+
+# if defined(BOOST_HAS_DECLSPEC) && defined(BOOST_LOG_SETUP_DLL)
+# define BOOST_LOG_SETUP_API __declspec(dllexport)
+# elif defined(__GNUC__) && __GNUC__ >= 4 && (defined(linux) || defined(__linux) || defined(__linux__))
+# define BOOST_LOG_SETUP_API __attribute__((visibility("default")))
+# else
+# define BOOST_LOG_SETUP_API
+# endif
+
+#endif // !defined(BOOST_LOG_SETUP_BUILDING_THE_LIB)
+
+#endif // BOOST_LOG_DETAIL_SETUP_CONFIG_HPP_INCLUDED_
diff --git a/boost/log/detail/singleton.hpp b/boost/log/detail/singleton.hpp
new file mode 100644
index 0000000000..ac1ac1afe0
--- /dev/null
+++ b/boost/log/detail/singleton.hpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file singleton.hpp
+ * \author Andrey Semashev
+ * \date 20.04.2008
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_SINGLETON_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_SINGLETON_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/utility/once_block.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! A base class for singletons, constructed on-demand
+template< typename DerivedT, typename StorageT = DerivedT >
+class lazy_singleton
+{
+public:
+ BOOST_DEFAULTED_FUNCTION(lazy_singleton(), {})
+
+ //! Returns the singleton instance
+ static StorageT& get()
+ {
+ BOOST_LOG_ONCE_BLOCK()
+ {
+ DerivedT::init_instance();
+ }
+ return get_instance();
+ }
+
+ //! Initializes the singleton instance
+ static void init_instance()
+ {
+ get_instance();
+ }
+
+ BOOST_DELETED_FUNCTION(lazy_singleton(lazy_singleton const&))
+ BOOST_DELETED_FUNCTION(lazy_singleton& operator= (lazy_singleton const&))
+
+protected:
+ //! Returns the singleton instance (not thread-safe)
+ static StorageT& get_instance()
+ {
+ static StorageT instance;
+ return instance;
+ }
+};
+
+//! A base class for singletons, constructed on namespace scope initialization stage
+template< typename DerivedT, typename StorageT = DerivedT >
+class singleton :
+ public lazy_singleton< DerivedT, StorageT >
+{
+public:
+ static StorageT& instance;
+};
+
+template< typename DerivedT, typename StorageT >
+StorageT& singleton< DerivedT, StorageT >::instance =
+ lazy_singleton< DerivedT, StorageT >::get();
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_SINGLETON_HPP_INCLUDED_
diff --git a/boost/log/detail/sink_init_helpers.hpp b/boost/log/detail/sink_init_helpers.hpp
new file mode 100644
index 0000000000..060aab7fc8
--- /dev/null
+++ b/boost/log/detail/sink_init_helpers.hpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file sink_init_helpers.hpp
+ * \author Andrey Semashev
+ * \date 14.03.2009
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_SINK_INIT_HELPERS_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_SINK_INIT_HELPERS_HPP_INCLUDED_
+
+#include <string>
+#include <boost/mpl/bool.hpp>
+#include <boost/parameter/binding.hpp>
+#include <boost/type_traits/is_void.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/phoenix/core/is_actor.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/core/core.hpp>
+#include <boost/log/expressions/filter.hpp>
+#include <boost/log/expressions/formatter.hpp>
+#include <boost/log/utility/setup/filter_parser.hpp>
+#include <boost/log/utility/setup/formatter_parser.hpp>
+#include <boost/log/keywords/filter.hpp>
+#include <boost/log/keywords/format.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+// The function creates a filter functional object from the provided argument
+template< typename CharT >
+inline filter acquire_filter(const CharT* filter)
+{
+ return boost::log::parse_filter(filter);
+}
+template< typename CharT, typename TraitsT, typename AllocatorT >
+inline filter acquire_filter(std::basic_string< CharT, TraitsT, AllocatorT > const& filter)
+{
+ return boost::log::parse_filter(filter);
+}
+template< typename FilterT >
+inline typename enable_if<
+ phoenix::is_actor< FilterT >,
+ FilterT const&
+>::type acquire_filter(FilterT const& filter)
+{
+ return filter;
+}
+
+// The function installs filter into the sink, if provided in the arguments pack
+template< typename SinkT, typename ArgsT >
+inline void setup_filter(SinkT&, ArgsT const&, mpl::true_)
+{
+}
+
+template< typename SinkT, typename ArgsT >
+inline void setup_filter(SinkT& s, ArgsT const& args, mpl::false_)
+{
+ s.set_filter(aux::acquire_filter(args[keywords::filter]));
+}
+
+
+// The function creates a filter functional object from the provided argument
+template< typename CharT >
+inline basic_formatter< CharT > acquire_formatter(const CharT* formatter)
+{
+ return boost::log::parse_formatter(formatter);
+}
+template< typename CharT, typename TraitsT, typename AllocatorT >
+inline basic_formatter< CharT > acquire_formatter(std::basic_string< CharT, TraitsT, AllocatorT > const& formatter)
+{
+ return boost::log::parse_formatter(formatter);
+}
+template< typename FormatterT >
+inline typename enable_if<
+ phoenix::is_actor< FormatterT >,
+ FormatterT const&
+>::type acquire_formatter(FormatterT const& formatter)
+{
+ return formatter;
+}
+
+// The function installs filter into the sink, if provided in the arguments pack
+template< typename SinkT, typename ArgsT >
+inline void setup_formatter(SinkT&, ArgsT const&, mpl::true_)
+{
+}
+
+template< typename SinkT, typename ArgsT >
+inline void setup_formatter(SinkT& s, ArgsT const& args, mpl::false_)
+{
+ s.set_formatter(aux::acquire_formatter(args[keywords::format]));
+}
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_SINK_INIT_HELPERS_HPP_INCLUDED_
diff --git a/boost/log/detail/snprintf.hpp b/boost/log/detail/snprintf.hpp
new file mode 100644
index 0000000000..ced0cd593a
--- /dev/null
+++ b/boost/log/detail/snprintf.hpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file snprintf.hpp
+ * \author Andrey Semashev
+ * \date 20.02.2009
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_SNPRINTF_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_SNPRINTF_HPP_INCLUDED_
+
+#include <stdio.h>
+#include <cstddef>
+#include <cstdarg>
+#include <boost/log/detail/config.hpp>
+#ifdef BOOST_LOG_USE_WCHAR_T
+#include <wchar.h>
+#endif // BOOST_LOG_USE_WCHAR_T
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+#if !defined(_MSC_VER)
+
+// Standard-conforming compilers already have the correct snprintfs
+using ::snprintf;
+using ::vsnprintf;
+
+# ifdef BOOST_LOG_USE_WCHAR_T
+using ::swprintf;
+using ::vswprintf;
+# endif // BOOST_LOG_USE_WCHAR_T
+
+#else // !defined(_MSC_VER)
+
+// MSVC snprintfs are not conforming but they are good enough for our cases
+inline int vsnprintf(char* buf, std::size_t size, const char* format, std::va_list args)
+{
+ int n = _vsnprintf(buf, size, format, args);
+ if (static_cast< unsigned int >(n) >= size)
+ {
+ n = static_cast< int >(size);
+ buf[size - 1] = '\0';
+ }
+ return n;
+}
+
+# ifdef BOOST_LOG_USE_WCHAR_T
+inline int vswprintf(wchar_t* buf, std::size_t size, const wchar_t* format, std::va_list args)
+{
+ int n = _vsnwprintf(buf, size, format, args);
+ if (static_cast< unsigned int >(n) >= size)
+ {
+ n = static_cast< int >(size);
+ buf[size - 1] = L'\0';
+ }
+ return n;
+}
+# endif // BOOST_LOG_USE_WCHAR_T
+
+inline int snprintf(char* buf, std::size_t size, const char* format, ...)
+{
+ std::va_list args;
+ va_start(args, format);
+ int n = vsnprintf(buf, size, format, args);
+ va_end(args);
+ return n;
+}
+
+# ifdef BOOST_LOG_USE_WCHAR_T
+inline int swprintf(wchar_t* buf, std::size_t size, const wchar_t* format, ...)
+{
+ std::va_list args;
+ va_start(args, format);
+ int n = vswprintf(buf, size, format, args);
+ va_end(args);
+ return n;
+}
+# endif // BOOST_LOG_USE_WCHAR_T
+
+#endif // !defined(_MSC_VER)
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_SNPRINTF_HPP_INCLUDED_
diff --git a/boost/log/detail/spin_mutex.hpp b/boost/log/detail/spin_mutex.hpp
new file mode 100644
index 0000000000..727d6d1ade
--- /dev/null
+++ b/boost/log/detail/spin_mutex.hpp
@@ -0,0 +1,319 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file spin_mutex.hpp
+ * \author Andrey Semashev
+ * \date 01.08.2010
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_SPIN_MUTEX_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_SPIN_MUTEX_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifndef BOOST_LOG_NO_THREADS
+
+#include <boost/throw_exception.hpp>
+#include <boost/thread/exceptions.hpp>
+
+#if defined(BOOST_THREAD_POSIX) // This one can be defined by users, so it should go first
+#define BOOST_LOG_SPIN_MUTEX_USE_PTHREAD
+#elif defined(BOOST_WINDOWS)
+#define BOOST_LOG_SPIN_MUTEX_USE_WINAPI
+#elif defined(BOOST_HAS_PTHREADS)
+#define BOOST_LOG_SPIN_MUTEX_USE_PTHREAD
+#endif
+
+#if defined(BOOST_LOG_SPIN_MUTEX_USE_WINAPI)
+
+#include <boost/detail/interlocked.hpp>
+
+#if defined(BOOST_USE_WINDOWS_H)
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0500
+#endif
+
+#include <windows.h>
+
+#else // defined(BOOST_USE_WINDOWS_H)
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+extern "C" {
+
+__declspec(dllimport) int __stdcall SwitchToThread();
+
+} // extern "C"
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_USE_WINDOWS_H
+
+#if defined(__INTEL_COMPILER) || defined(_MSC_VER)
+# if defined(_M_IX86)
+# define BOOST_LOG_PAUSE_OP __asm { pause }
+# elif defined(_M_AMD64)
+extern "C" void _mm_pause(void);
+#pragma intrinsic(_mm_pause)
+# define BOOST_LOG_PAUSE_OP _mm_pause()
+# endif
+# if defined(__INTEL_COMPILER)
+# define BOOST_LOG_COMPILER_BARRIER __memory_barrier()
+# else
+extern "C" void _ReadWriteBarrier(void);
+#pragma intrinsic(_ReadWriteBarrier)
+# define BOOST_LOG_COMPILER_BARRIER _ReadWriteBarrier()
+# endif
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+# define BOOST_LOG_PAUSE_OP __asm__ __volatile__("pause;")
+# define BOOST_LOG_COMPILER_BARRIER __asm__ __volatile__("" : : : "memory")
+#endif
+
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! A simple spinning mutex
+class spin_mutex
+{
+private:
+ enum state
+ {
+ initial_pause = 2,
+ max_pause = 16
+ };
+
+ long m_State;
+
+public:
+ spin_mutex() : m_State(0) {}
+
+ bool try_lock()
+ {
+ return (BOOST_INTERLOCKED_COMPARE_EXCHANGE(&m_State, 1L, 0L) == 0L);
+ }
+
+ void lock()
+ {
+#if defined(BOOST_LOG_PAUSE_OP)
+ unsigned int pause_count = initial_pause;
+#endif
+ while (!try_lock())
+ {
+#if defined(BOOST_LOG_PAUSE_OP)
+ if (pause_count < max_pause)
+ {
+ for (unsigned int i = 0; i < pause_count; ++i)
+ {
+ BOOST_LOG_PAUSE_OP;
+ }
+ pause_count += pause_count;
+ }
+ else
+ {
+ // Restart spinning after waking up this thread
+ pause_count = initial_pause;
+ SwitchToThread();
+ }
+#else
+ SwitchToThread();
+#endif
+ }
+ }
+
+ void unlock()
+ {
+#if (defined(_M_IX86) || defined(_M_AMD64)) && defined(BOOST_LOG_COMPILER_BARRIER)
+ BOOST_LOG_COMPILER_BARRIER;
+ m_State = 0L;
+ BOOST_LOG_COMPILER_BARRIER;
+#else
+ BOOST_INTERLOCKED_EXCHANGE(&m_State, 0L);
+#endif
+ }
+
+ // Non-copyable
+ BOOST_DELETED_FUNCTION(spin_mutex(spin_mutex const&))
+ BOOST_DELETED_FUNCTION(spin_mutex& operator= (spin_mutex const&))
+};
+
+#undef BOOST_LOG_PAUSE_OP
+#undef BOOST_LOG_COMPILER_BARRIER
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#elif defined(BOOST_LOG_SPIN_MUTEX_USE_PTHREAD)
+
+#include <pthread.h>
+#include <boost/assert.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+#if defined(_POSIX_SPIN_LOCKS) && _POSIX_SPIN_LOCKS > 0
+
+//! A simple spinning mutex
+class spin_mutex
+{
+private:
+ pthread_spinlock_t m_State;
+
+public:
+ spin_mutex()
+ {
+ const int err = pthread_spin_init(&m_State, PTHREAD_PROCESS_PRIVATE);
+ if (err != 0)
+ throw_exception< thread_resource_error >(err, "failed to initialize a spin mutex", "spin_mutex::spin_mutex()", __FILE__, __LINE__);
+ }
+
+ ~spin_mutex()
+ {
+ BOOST_VERIFY(pthread_spin_destroy(&m_State) == 0);
+ }
+
+ bool try_lock()
+ {
+ const int err = pthread_spin_trylock(&m_State);
+ if (err == 0)
+ return true;
+ if (err != EBUSY)
+ throw_exception< lock_error >(err, "failed to lock a spin mutex", "spin_mutex::try_lock()", __FILE__, __LINE__);
+ return false;
+ }
+
+ void lock()
+ {
+ const int err = pthread_spin_lock(&m_State);
+ if (err != 0)
+ throw_exception< lock_error >(err, "failed to lock a spin mutex", "spin_mutex::lock()", __FILE__, __LINE__);
+ }
+
+ void unlock()
+ {
+ BOOST_VERIFY(pthread_spin_unlock(&m_State) == 0);
+ }
+
+ // Non-copyable
+ BOOST_DELETED_FUNCTION(spin_mutex(spin_mutex const&))
+ BOOST_DELETED_FUNCTION(spin_mutex& operator= (spin_mutex const&))
+
+private:
+ template< typename ExceptionT >
+ static BOOST_NOINLINE BOOST_LOG_NORETURN void throw_exception(int err, const char* descr, const char* func, const char* file, int line)
+ {
+#if !defined(BOOST_EXCEPTION_DISABLE)
+ boost::exception_detail::throw_exception_(ExceptionT(err, descr), func, file, line);
+#else
+ boost::throw_exception(ExceptionT(err, descr));
+#endif
+ }
+};
+
+#else // defined(_POSIX_SPIN_LOCKS)
+
+//! Backup implementation in case if pthreads don't support spin locks
+class spin_mutex
+{
+private:
+ pthread_mutex_t m_State;
+
+public:
+ spin_mutex()
+ {
+ const int err = pthread_mutex_init(&m_State, NULL);
+ if (err != 0)
+ throw_exception< thread_resource_error >(err, "failed to initialize a spin mutex", "spin_mutex::spin_mutex()", __FILE__, __LINE__);
+ }
+
+ ~spin_mutex()
+ {
+ BOOST_VERIFY(pthread_mutex_destroy(&m_State) == 0);
+ }
+
+ bool try_lock()
+ {
+ const int err = pthread_mutex_trylock(&m_State);
+ if (err == 0)
+ return true;
+ if (err != EBUSY)
+ throw_exception< lock_error >(err, "failed to lock a spin mutex", "spin_mutex::try_lock()", __FILE__, __LINE__);
+ return false;
+ }
+
+ void lock()
+ {
+ const int err = pthread_mutex_lock(&m_State);
+ if (err != 0)
+ throw_exception< lock_error >(err, "failed to lock a spin mutex", "spin_mutex::lock()", __FILE__, __LINE__);
+ }
+
+ void unlock()
+ {
+ BOOST_VERIFY(pthread_mutex_unlock(&m_State) == 0);
+ }
+
+ // Non-copyable
+ BOOST_DELETED_FUNCTION(spin_mutex(spin_mutex const&))
+ BOOST_DELETED_FUNCTION(spin_mutex& operator= (spin_mutex const&))
+
+private:
+ template< typename ExceptionT >
+ static BOOST_NOINLINE BOOST_LOG_NORETURN void throw_exception(int err, const char* descr, const char* func, const char* file, int line)
+ {
+#if !defined(BOOST_EXCEPTION_DISABLE)
+ boost::exception_detail::throw_exception_(ExceptionT(err, descr), func, file, line);
+#else
+ boost::throw_exception(ExceptionT(err, descr));
+#endif
+ }
+};
+
+#endif // defined(_POSIX_SPIN_LOCKS)
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif
+
+#endif // BOOST_LOG_NO_THREADS
+
+#endif // BOOST_LOG_DETAIL_SPIN_MUTEX_HPP_INCLUDED_
diff --git a/boost/log/detail/tagged_integer.hpp b/boost/log/detail/tagged_integer.hpp
new file mode 100644
index 0000000000..5aef5bbfcc
--- /dev/null
+++ b/boost/log/detail/tagged_integer.hpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file tagged_integer.hpp
+ * \author Andrey Semashev
+ * \date 11.01.2008
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_TAGGED_INTEGER_HPP_INCLUDED_
+#define BOOST_LOG_TAGGED_INTEGER_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! A tagged integer wrapper for type safety
+template< typename IntT, typename TagT >
+struct tagged_integer
+{
+ //! Contained value type
+ typedef IntT integer_type;
+ //! Tag
+ typedef TagT tag;
+
+ //! Contained value
+ integer_type value;
+
+ //! Conversion operator
+ operator integer_type() const { return value; }
+
+ // Increment
+ tagged_integer& operator++ () { ++value; return *this; }
+ tagged_integer operator++ (int) { tagged_integer temp = *this; ++value; return temp; }
+ // Decrement
+ tagged_integer& operator-- () { --value; return *this; }
+ tagged_integer operator-- (int) { tagged_integer temp = *this; --value; return temp; }
+
+#define BOOST_LOG_TAGGED_INTEGER_OP(op)\
+ tagged_integer& operator op (tagged_integer const& that) { value op that.value; return *this; }
+
+ BOOST_LOG_TAGGED_INTEGER_OP(|=)
+ BOOST_LOG_TAGGED_INTEGER_OP(&=)
+ BOOST_LOG_TAGGED_INTEGER_OP(^=)
+ BOOST_LOG_TAGGED_INTEGER_OP(+=)
+ BOOST_LOG_TAGGED_INTEGER_OP(-=)
+ BOOST_LOG_TAGGED_INTEGER_OP(*=)
+ BOOST_LOG_TAGGED_INTEGER_OP(/=)
+ BOOST_LOG_TAGGED_INTEGER_OP(%=)
+
+#undef BOOST_LOG_TAGGED_INTEGER_OP
+
+ //! Inversion operator
+ tagged_integer& operator~ () { ~value; return *this; }
+
+ // Shift operators
+ template< typename T >
+ tagged_integer& operator<<= (T const& that) { value <<= that; return *this; }
+ template< typename T >
+ tagged_integer& operator>>= (T const& that) { value >>= that; return *this; }
+
+private:
+ // Protection against improper usage
+ template< typename T1, typename T2 >
+ tagged_integer& operator<<= (tagged_integer< T1, T2 > const&);
+ template< typename T1, typename T2 >
+ tagged_integer& operator>>= (tagged_integer< T1, T2 > const&);
+};
+
+ // Relational operators
+#define BOOST_LOG_TAGGED_INTEGER_OP(op)\
+ template< typename IntT, typename TagT >\
+ inline bool operator op (\
+ tagged_integer< IntT, TagT > const& left, tagged_integer< IntT, TagT > const& right)\
+ {\
+ return (left.value op right.value);\
+ }
+
+BOOST_LOG_TAGGED_INTEGER_OP(==)
+BOOST_LOG_TAGGED_INTEGER_OP(!=)
+BOOST_LOG_TAGGED_INTEGER_OP(<)
+BOOST_LOG_TAGGED_INTEGER_OP(>)
+BOOST_LOG_TAGGED_INTEGER_OP(<=)
+BOOST_LOG_TAGGED_INTEGER_OP(>=)
+
+#undef BOOST_LOG_TAGGED_INTEGER_OP
+
+#define BOOST_LOG_TAGGED_INTEGER_OP(op)\
+ template< typename IntT, typename TagT >\
+ inline tagged_integer< IntT, TagT > operator op (\
+ tagged_integer< IntT, TagT > const& left, tagged_integer< IntT, TagT > const& right)\
+ {\
+ tagged_integer< IntT, TagT > temp = left;\
+ temp op##= right;\
+ return temp;\
+ }
+
+BOOST_LOG_TAGGED_INTEGER_OP(|)
+BOOST_LOG_TAGGED_INTEGER_OP(&)
+BOOST_LOG_TAGGED_INTEGER_OP(^)
+BOOST_LOG_TAGGED_INTEGER_OP(+)
+BOOST_LOG_TAGGED_INTEGER_OP(-)
+BOOST_LOG_TAGGED_INTEGER_OP(*)
+BOOST_LOG_TAGGED_INTEGER_OP(/)
+BOOST_LOG_TAGGED_INTEGER_OP(%)
+
+#undef BOOST_LOG_TAGGED_INTEGER_OP
+
+#define BOOST_LOG_TAGGED_INTEGER_OP(op)\
+ template< typename IntT, typename TagT, typename T >\
+ inline tagged_integer< IntT, TagT > operator op (\
+ tagged_integer< IntT, TagT > const& left, T const& right)\
+ {\
+ tagged_integer< IntT, TagT > temp = left;\
+ temp op##= right;\
+ return temp;\
+ }
+
+BOOST_LOG_TAGGED_INTEGER_OP(<<)
+BOOST_LOG_TAGGED_INTEGER_OP(>>)
+
+#undef BOOST_LOG_TAGGED_INTEGER_OP
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_TAGGED_INTEGER_HPP_INCLUDED_
diff --git a/boost/log/detail/thread_id.hpp b/boost/log/detail/thread_id.hpp
new file mode 100644
index 0000000000..3b592c2c25
--- /dev/null
+++ b/boost/log/detail/thread_id.hpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file thread_id.hpp
+ * \author Andrey Semashev
+ * \date 08.01.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_THREAD_ID_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_THREAD_ID_HPP_INCLUDED_
+
+#include <iosfwd>
+#include <boost/cstdint.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/id.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! The thread id descriptor
+struct thread
+{
+#if defined(BOOST_WINDOWS)
+ typedef uint32_t native_type;
+#else
+ typedef uintmax_t native_type;
+#endif
+ typedef boost::log::aux::id< thread > id;
+};
+
+namespace this_thread {
+
+//! The function returns current thread identifier
+BOOST_LOG_API thread::id const& get_id();
+
+} // namespace this_thread
+
+template< typename CharT, typename TraitsT >
+BOOST_LOG_API std::basic_ostream< CharT, TraitsT >&
+operator<< (std::basic_ostream< CharT, TraitsT >& strm, thread::id const& tid);
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_THREAD_ID_HPP_INCLUDED_
diff --git a/boost/log/detail/thread_specific.hpp b/boost/log/detail/thread_specific.hpp
new file mode 100644
index 0000000000..72d2a3b22e
--- /dev/null
+++ b/boost/log/detail/thread_specific.hpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file thread_specific.hpp
+ * \author Andrey Semashev
+ * \date 01.03.2008
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_THREAD_SPECIFIC_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_THREAD_SPECIFIC_HPP_INCLUDED_
+
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_pod.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if !defined(BOOST_LOG_NO_THREADS)
+
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! Base class for TLS to hide platform-specific storage management
+class thread_specific_base
+{
+private:
+ union key_storage
+ {
+ void* as_pointer;
+ unsigned int as_dword;
+ };
+
+ key_storage m_Key;
+
+protected:
+ BOOST_LOG_API thread_specific_base();
+ BOOST_LOG_API ~thread_specific_base();
+ BOOST_LOG_API void* get_content() const;
+ BOOST_LOG_API void set_content(void* value) const;
+
+ // Copying prohibited
+ BOOST_DELETED_FUNCTION(thread_specific_base(thread_specific_base const&))
+ BOOST_DELETED_FUNCTION(thread_specific_base& operator= (thread_specific_base const&))
+};
+
+//! A TLS wrapper for small POD types with least possible overhead
+template< typename T >
+class thread_specific :
+ public thread_specific_base
+{
+ BOOST_STATIC_ASSERT_MSG(sizeof(T) <= sizeof(void*) && is_pod< T >::value, "Boost.Log: Thread-specific values must be PODs and must not exceed the size of a pointer");
+
+ //! Union to perform type casting
+ union value_storage
+ {
+ void* as_pointer;
+ T as_value;
+ };
+
+public:
+ //! Default constructor
+ BOOST_DEFAULTED_FUNCTION(thread_specific(), {})
+ //! Initializing constructor
+ thread_specific(T const& value)
+ {
+ set(value);
+ }
+ //! Assignment
+ thread_specific& operator= (T const& value)
+ {
+ set(value);
+ return *this;
+ }
+
+ //! Accessor
+ T get() const
+ {
+ value_storage cast = {};
+ cast.as_pointer = thread_specific_base::get_content();
+ return cast.as_value;
+ }
+
+ //! Setter
+ void set(T const& value)
+ {
+ value_storage cast = {};
+ cast.as_value = value;
+ thread_specific_base::set_content(cast.as_pointer);
+ }
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // !defined(BOOST_LOG_NO_THREADS)
+
+#endif // BOOST_LOG_DETAIL_THREAD_SPECIFIC_HPP_INCLUDED_
diff --git a/boost/log/detail/threadsafe_queue.hpp b/boost/log/detail/threadsafe_queue.hpp
new file mode 100644
index 0000000000..a1e78249f0
--- /dev/null
+++ b/boost/log/detail/threadsafe_queue.hpp
@@ -0,0 +1,277 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file threadsafe_queue.hpp
+ * \author Andrey Semashev
+ * \date 05.11.2010
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_THREADSAFE_QUEUE_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_THREADSAFE_QUEUE_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifndef BOOST_LOG_NO_THREADS
+
+#include <new>
+#include <memory>
+#include <cstddef>
+#include <boost/aligned_storage.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/type_traits/type_with_alignment.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! Base class for the thread-safe queue implementation
+struct threadsafe_queue_impl
+{
+ struct
+#if defined(__GNUC__)
+ // Explicitly mark the type so that it may alias other types
+ __attribute__ ((__may_alias__))
+#endif
+ pointer_storage
+ {
+ union
+ {
+ void* data[2];
+ type_with_alignment< 2 * sizeof(void*) >::type alignment;
+ };
+ };
+
+ struct node_base
+ {
+ pointer_storage next;
+ };
+
+ static BOOST_LOG_API threadsafe_queue_impl* create(node_base* first_node);
+
+ static BOOST_LOG_API void* operator new (std::size_t size);
+ static BOOST_LOG_API void operator delete (void* p, std::size_t);
+
+ virtual ~threadsafe_queue_impl() {}
+ virtual node_base* reset_last_node() = 0;
+ virtual bool unsafe_empty() = 0;
+ virtual void push(node_base* p) = 0;
+ virtual bool try_pop(node_base*& node_to_free, node_base*& node_with_value) = 0;
+};
+
+//! A helper class to compose some of the types used by the queue
+template< typename T, typename AllocatorT >
+struct threadsafe_queue_types
+{
+ struct node :
+ public threadsafe_queue_impl::node_base
+ {
+ typedef typename aligned_storage< sizeof(T), alignment_of< T >::value >::type storage_type;
+ storage_type storage;
+
+ node() {}
+ explicit node(T const& val) { new (storage.address()) T(val); }
+ T& value() { return *static_cast< T* >(storage.address()); }
+ void destroy() { static_cast< T* >(storage.address())->~T(); }
+ };
+
+ typedef typename AllocatorT::BOOST_NESTED_TEMPLATE rebind< node >::other allocator_type;
+};
+
+/*!
+ * \brief An unbounded thread-safe queue
+ *
+ * The implementation is based on algorithms published in the "Simple, Fast,
+ * and Practical Non-Blocking and Blocking Concurrent Queue Algorithms" article
+ * in PODC96 by Maged M. Michael and Michael L. Scott. Pseudocode is available here:
+ * http://www.cs.rochester.edu/research/synchronization/pseudocode/queues.html
+ *
+ * The implementation provides thread-safe \c push and \c try_pop operations, as well as
+ * a thread-unsafe \c empty operation. The queue imposes the following requirements
+ * on the element type:
+ *
+ * \li Default constructible, the default constructor must not throw.
+ * \li Copy constructible.
+ * \li Movable (i.e. there should be an efficient move assignment for this type).
+ *
+ * The last requirement is not mandatory but is crucial for decent performance.
+ */
+template< typename T, typename AllocatorT = std::allocator< void > >
+class threadsafe_queue :
+ private threadsafe_queue_types< T, AllocatorT >::allocator_type
+{
+private:
+ typedef typename threadsafe_queue_types< T, AllocatorT >::allocator_type base_type;
+ typedef typename threadsafe_queue_types< T, AllocatorT >::node node;
+
+ //! A simple scope guard to automate memory reclaiming
+ struct auto_deallocate;
+ friend struct auto_deallocate;
+ struct auto_deallocate
+ {
+ auto_deallocate(base_type* alloc, node* dealloc, node* destr) :
+ m_pAllocator(alloc),
+ m_pDeallocate(dealloc),
+ m_pDestroy(destr)
+ {
+ }
+ ~auto_deallocate()
+ {
+ m_pAllocator->deallocate(m_pDeallocate, 1);
+ m_pDestroy->destroy();
+ }
+
+ private:
+ base_type* m_pAllocator;
+ node* m_pDeallocate;
+ node* m_pDestroy;
+ };
+
+public:
+ typedef T value_type;
+ typedef T& reference;
+ typedef T const& const_reference;
+ typedef T* pointer;
+ typedef T const* const_pointer;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::size_t size_type;
+ typedef AllocatorT allocator_type;
+
+public:
+ /*!
+ * Default constructor, creates an empty queue. Unlike most containers,
+ * the constructor requires memory allocation.
+ *
+ * \throw std::bad_alloc if there is not sufficient memory
+ */
+ threadsafe_queue(base_type const& alloc = base_type()) :
+ base_type(alloc)
+ {
+ node* p = base_type::allocate(1);
+ if (p)
+ {
+ try
+ {
+ new (p) node();
+ try
+ {
+ m_pImpl = threadsafe_queue_impl::create(p);
+ }
+ catch (...)
+ {
+ p->~node();
+ throw;
+ }
+ }
+ catch (...)
+ {
+ base_type::deallocate(p, 1);
+ throw;
+ }
+ }
+ else
+ throw std::bad_alloc();
+ }
+ /*!
+ * Destructor
+ */
+ ~threadsafe_queue()
+ {
+ // Clear the queue
+ if (!unsafe_empty())
+ {
+ value_type value;
+ while (try_pop(value));
+ }
+
+ // Remove the last dummy node
+ node* p = static_cast< node* >(m_pImpl->reset_last_node());
+ p->~node();
+ base_type::deallocate(p, 1);
+
+ delete m_pImpl;
+ }
+
+ /*!
+ * Checks if the queue is empty. Not thread-safe, the returned result may not be actual.
+ */
+ bool unsafe_empty() const { return m_pImpl->unsafe_empty(); }
+
+ /*!
+ * Puts a new element to the end of the queue. Thread-safe, can be called
+ * concurrently by several threads, and concurrently with the \c pop operation.
+ */
+ void push(const_reference value)
+ {
+ node* p = base_type::allocate(1);
+ if (p)
+ {
+ try
+ {
+ new (p) node(value);
+ }
+ catch (...)
+ {
+ base_type::deallocate(p, 1);
+ throw;
+ }
+ m_pImpl->push(p);
+ }
+ else
+ throw std::bad_alloc();
+ }
+
+ /*!
+ * Attempts to pop an element from the beginning of the queue. Thread-safe, can
+ * be called concurrently with the \c push operation. Should not be called by
+ * several threads concurrently.
+ */
+ bool try_pop(reference value)
+ {
+ threadsafe_queue_impl::node_base *dealloc, *destr;
+ if (m_pImpl->try_pop(dealloc, destr))
+ {
+ node* p = static_cast< node* >(destr);
+ auto_deallocate guard(static_cast< base_type* >(this), static_cast< node* >(dealloc), p);
+ value = boost::move(p->value());
+ return true;
+ }
+ else
+ return false;
+ }
+
+ // Copying and assignment is prohibited
+ BOOST_DELETED_FUNCTION(threadsafe_queue(threadsafe_queue const&))
+ BOOST_DELETED_FUNCTION(threadsafe_queue& operator= (threadsafe_queue const&))
+
+private:
+ //! Pointer to the implementation
+ threadsafe_queue_impl* m_pImpl;
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_NO_THREADS
+
+#endif // BOOST_LOG_DETAIL_THREADSAFE_QUEUE_HPP_INCLUDED_
diff --git a/boost/log/detail/timestamp.hpp b/boost/log/detail/timestamp.hpp
new file mode 100644
index 0000000000..719061fb01
--- /dev/null
+++ b/boost/log/detail/timestamp.hpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file timestamp.hpp
+ * \author Andrey Semashev
+ * \date 31.07.2011
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_TIMESTAMP_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_TIMESTAMP_HPP_INCLUDED_
+
+#include <boost/cstdint.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+/*!
+ * Duration between two timestamps
+ */
+class duration
+{
+ int64_t m_ticks;
+
+public:
+ explicit duration(int64_t ticks = 0) : m_ticks(ticks) {}
+
+#if defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+ int64_t milliseconds() const { return m_ticks; }
+#else
+ BOOST_LOG_API int64_t milliseconds() const;
+#endif
+};
+
+/*!
+ * Opaque timestamp class
+ */
+class timestamp
+{
+ uint64_t m_ticks;
+
+public:
+ explicit timestamp(uint64_t ticks = 0) : m_ticks(ticks) {}
+
+ duration operator- (timestamp that) const
+ {
+ return duration(m_ticks - that.m_ticks);
+ }
+};
+
+/*!
+ * \fn get_timestamp
+ *
+ * The function returns a timestamp, in opaque units since an unspecified
+ * time point. This timer is guaranteed to be monotonic, it should not
+ * be affected by clock changes, either manual or seasonal. Also, it
+ * should be as fast as possible.
+ */
+#if defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+typedef uint64_t (__stdcall* get_tick_count_t)();
+extern BOOST_LOG_API get_tick_count_t get_tick_count;
+
+inline timestamp get_timestamp()
+{
+ return timestamp(get_tick_count());
+}
+
+#else
+
+typedef timestamp (*get_timestamp_t)();
+extern BOOST_LOG_API get_timestamp_t get_timestamp;
+
+#endif
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_TIMESTAMP_HPP_INCLUDED_
diff --git a/boost/log/detail/trivial_keyword.hpp b/boost/log/detail/trivial_keyword.hpp
new file mode 100644
index 0000000000..d0e4f60713
--- /dev/null
+++ b/boost/log/detail/trivial_keyword.hpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file trivial_keyword.hpp
+ * \author Andrey Semashev
+ * \date 02.12.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_TRIVIAL_KEYWORD_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_TRIVIAL_KEYWORD_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace trivial {
+
+//! Trivial severity keyword
+BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", severity_level)
+
+} // namespace trivial
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_TRIVIAL_KEYWORD_HPP_INCLUDED_
diff --git a/boost/log/detail/unary_function_terminal.hpp b/boost/log/detail/unary_function_terminal.hpp
new file mode 100644
index 0000000000..f9a3412acf
--- /dev/null
+++ b/boost/log/detail/unary_function_terminal.hpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file unary_function_terminal.hpp
+ * \author Andrey Semashev
+ * \date 21.07.2012
+ *
+ * The header contains attribute value extractor adapter for constructing expression template terminals.
+ */
+
+#ifndef BOOST_LOG_DETAIL_UNARY_FUNCTION_TERMINAL_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_UNARY_FUNCTION_TERMINAL_HPP_INCLUDED_
+
+#include <boost/mpl/bool.hpp>
+#include <boost/utility/result_of.hpp>
+#include <boost/fusion/sequence/intrinsic/at_c.hpp>
+#include <boost/phoenix/core/is_nullary.hpp>
+#include <boost/phoenix/core/environment.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/copy_cv.hpp>
+#include <boost/log/detail/custom_terminal_spec.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+namespace aux {
+
+/*!
+ * \brief An adapter for a unary function to be used as a terminal in a Boost.Phoenix expression
+ *
+ * This class is an adapter between Boost.Phoenix expression invocation protocol and
+ * a unary function. It forwards the call to the base function, passing only the first argument
+ * from the original call. This allows to embed value extractors in template expressions.
+ */
+template< typename FunT >
+class unary_function_terminal
+{
+private:
+ //! Adopted function type
+ typedef FunT function_type;
+ //! Self type
+ typedef unary_function_terminal< function_type > this_type;
+
+public:
+ //! Internal typedef for type categorization
+ typedef void _is_boost_log_terminal;
+
+ //! Function result type
+ template< typename >
+ struct result;
+
+ template< typename ThisT, typename ContextT >
+ struct result< ThisT(ContextT) >
+ {
+ typedef typename remove_cv<
+ typename remove_reference< typename phoenix::result_of::env< ContextT >::type >::type
+ >::type env_type;
+ typedef typename env_type::args_type args_type;
+ typedef typename boost::log::aux::copy_cv< ThisT, function_type >::type cv_function_type;
+
+ typedef typename boost::result_of< cv_function_type(typename fusion::result_of::at_c< args_type, 0 >::type) >::type type;
+ };
+
+private:
+ //! Adopted function
+ function_type m_fun;
+
+public:
+ //! Default constructor
+ BOOST_DEFAULTED_FUNCTION(unary_function_terminal(), {})
+ //! Copy constructor
+ unary_function_terminal(unary_function_terminal const& that) : m_fun(that.m_fun) {}
+ //! Initializing constructor
+ template< typename ArgT1 >
+ explicit unary_function_terminal(ArgT1 const& arg1) : m_fun(arg1) {}
+ //! Initializing constructor
+ template< typename ArgT1, typename ArgT2 >
+ unary_function_terminal(ArgT1 const& arg1, ArgT2 const& arg2) : m_fun(arg1, arg2) {}
+ //! Initializing constructor
+ template< typename ArgT1, typename ArgT2, typename ArgT3 >
+ unary_function_terminal(ArgT1 const& arg1, ArgT2 const& arg2, ArgT3 const& arg3) : m_fun(arg1, arg2, arg3) {}
+
+ //! The operator forwards the call to the base function
+ template< typename ContextT >
+ typename result< this_type(ContextT const&) >::type
+ operator() (ContextT const& ctx)
+ {
+ return m_fun(fusion::at_c< 0 >(phoenix::env(ctx).args()));
+ }
+
+ //! The operator forwards the call to the base function
+ template< typename ContextT >
+ typename result< const this_type(ContextT const&) >::type
+ operator() (ContextT const& ctx) const
+ {
+ return m_fun(fusion::at_c< 0 >(phoenix::env(ctx).args()));
+ }
+};
+
+} // namespace aux
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+namespace phoenix {
+
+namespace result_of {
+
+template< typename FunT >
+struct is_nullary< custom_terminal< boost::log::expressions::aux::unary_function_terminal< FunT > > > :
+ public mpl::false_
+{
+};
+
+} // namespace result_of
+
+} // namespace phoenix
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_UNARY_FUNCTION_TERMINAL_HPP_INCLUDED_
diff --git a/boost/log/detail/unhandled_exception_count.hpp b/boost/log/detail/unhandled_exception_count.hpp
new file mode 100644
index 0000000000..17866c3b36
--- /dev/null
+++ b/boost/log/detail/unhandled_exception_count.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file unhandled_exception_count.hpp
+ * \author Andrey Semashev
+ * \date 05.11.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_UNHANDLED_EXCEPTION_COUNT_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_UNHANDLED_EXCEPTION_COUNT_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! Returns the number of currently pending exceptions
+BOOST_LOG_API unsigned int unhandled_exception_count() BOOST_NOEXCEPT;
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_DETAIL_UNHANDLED_EXCEPTION_COUNT_HPP_INCLUDED_
diff --git a/boost/log/detail/value_ref_visitation.hpp b/boost/log/detail/value_ref_visitation.hpp
new file mode 100644
index 0000000000..795069d150
--- /dev/null
+++ b/boost/log/detail/value_ref_visitation.hpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file value_ref_visitation.hpp
+ * \author Andrey Semashev
+ * \date 28.07.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. In this file
+ * internal configuration macros are defined.
+ */
+
+#ifndef BOOST_LOG_DETAIL_VALUE_REF_VISITATION_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_VALUE_REF_VISITATION_HPP_INCLUDED_
+
+#include <boost/mpl/at.hpp>
+#include <boost/mpl/begin.hpp>
+#include <boost/mpl/end.hpp>
+#include <boost/mpl/advance.hpp>
+#include <boost/mpl/erase.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/preprocessor/arithmetic/inc.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+#include <boost/preprocessor/iteration/iterate.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifndef BOOST_LOG_VALUE_REF_VISITATION_UNROLL_COUNT
+#define BOOST_LOG_VALUE_REF_VISITATION_UNROLL_COUNT 8
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+template< typename SequenceT, typename VisitorT, unsigned int SizeV = mpl::size< SequenceT >::value >
+struct apply_visitor_dispatch
+{
+ typedef typename VisitorT::result_type result_type;
+
+ static BOOST_FORCEINLINE result_type call(const void* p, unsigned int type_index, VisitorT& visitor)
+ {
+ typedef typename mpl::begin< SequenceT >::type begin_type;
+ typedef typename mpl::advance_c< begin_type, SizeV / 2u >::type middle_type;
+ if (type_index < (SizeV / 2u))
+ {
+ typedef typename mpl::erase< SequenceT, middle_type, typename mpl::end< SequenceT >::type >::type new_sequence;
+ typedef apply_visitor_dispatch< new_sequence, VisitorT > new_dispatch;
+ return new_dispatch::call(p, type_index, visitor);
+ }
+ else
+ {
+ typedef typename mpl::erase< SequenceT, begin_type, middle_type >::type new_sequence;
+ typedef apply_visitor_dispatch< new_sequence, VisitorT > new_dispatch;
+ return new_dispatch::call(p, type_index - (SizeV / 2u), visitor);
+ }
+ }
+};
+
+#define BOOST_LOG_AUX_CASE_ENTRY(z, i, data)\
+ case i: return visitor(*static_cast< typename mpl::at_c< SequenceT, i >::type const* >(p));
+
+#define BOOST_PP_FILENAME_1 <boost/log/detail/value_ref_visitation.hpp>
+#define BOOST_PP_ITERATION_LIMITS (1, BOOST_PP_INC(BOOST_LOG_VALUE_REF_VISITATION_VTABLE_SIZE))
+#include BOOST_PP_ITERATE()
+
+#undef BOOST_LOG_AUX_CASE_ENTRY
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_VALUE_REF_VISITATION_HPP_INCLUDED_
+
+#ifdef BOOST_PP_IS_ITERATING
+
+#define BOOST_LOG_AUX_SWITCH_SIZE BOOST_PP_ITERATION()
+
+template< typename SequenceT, typename VisitorT >
+struct apply_visitor_dispatch< SequenceT, VisitorT, BOOST_LOG_AUX_SWITCH_SIZE >
+{
+ typedef typename VisitorT::result_type result_type;
+
+ static BOOST_FORCEINLINE result_type call(const void* p, unsigned int type_index, VisitorT& visitor)
+ {
+ switch (type_index)
+ {
+ BOOST_PP_REPEAT_FROM_TO(1, BOOST_LOG_AUX_SWITCH_SIZE, BOOST_LOG_AUX_CASE_ENTRY, ~)
+ default:
+ return visitor(*static_cast< typename mpl::at_c< SequenceT, 0 >::type const* >(p));
+ }
+ }
+};
+
+#undef BOOST_LOG_AUX_SWITCH_SIZE
+
+#endif // BOOST_PP_IS_ITERATING
diff --git a/boost/log/detail/visible_type.hpp b/boost/log/detail/visible_type.hpp
new file mode 100644
index 0000000000..2086278d42
--- /dev/null
+++ b/boost/log/detail/visible_type.hpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file visible_type.hpp
+ * \author Andrey Semashev
+ * \date 08.03.2007
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. In this file
+ * internal configuration macros are defined.
+ */
+
+#ifndef BOOST_LOG_DETAIL_VISIBLE_TYPE_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_VISIBLE_TYPE_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! The wrapper type whose type_info is always visible
+template< typename T >
+struct BOOST_SYMBOL_VISIBLE visible_type
+{
+ typedef T wrapped_type;
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_VISIBLE_TYPE_HPP_INCLUDED_
diff --git a/boost/log/exceptions.hpp b/boost/log/exceptions.hpp
new file mode 100644
index 0000000000..8171d0a3f0
--- /dev/null
+++ b/boost/log/exceptions.hpp
@@ -0,0 +1,387 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file
+ * \author Andrey Semashev
+ * \date 31.10.2009
+ *
+ * The header contains exception classes declarations.
+ */
+
+#ifndef BOOST_LOG_EXCEPTIONS_HPP_INCLUDED_
+#define BOOST_LOG_EXCEPTIONS_HPP_INCLUDED_
+
+#include <cstddef>
+#include <string>
+#include <stdexcept>
+#include <boost/preprocessor/seq/enum.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/utility/type_info_wrapper.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+// Forward-declaration of an exception base class from Boost.Exception
+#if defined(__GNUC__)
+# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+# pragma GCC visibility push (default)
+
+class exception;
+
+# pragma GCC visibility pop
+# else
+
+class exception;
+
+# endif
+#else
+
+class BOOST_SYMBOL_VISIBLE exception;
+
+#endif
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! Attaches attribute name exception information
+BOOST_LOG_API void attach_attribute_name_info(exception& e, attribute_name const& name);
+
+} // namespace aux
+
+/*!
+ * \brief Base class for runtime exceptions from the logging library
+ *
+ * Exceptions derived from this class indicate a problem that may not directly
+ * be caused by the user's code that interacts with the library, such as
+ * errors caused by input data.
+ */
+class BOOST_LOG_API runtime_error :
+ public std::runtime_error
+{
+protected:
+ /*!
+ * Initializing constructor. Creates an exception with the specified error message.
+ */
+ explicit runtime_error(std::string const& descr);
+ /*!
+ * Destructor
+ */
+ ~runtime_error() throw();
+};
+
+/*!
+ * \brief Exception class that is used to indicate errors of missing values
+ */
+class BOOST_LOG_API missing_value :
+ public runtime_error
+{
+public:
+ /*!
+ * Default constructor. Creates an exception with the default error message.
+ */
+ missing_value();
+ /*!
+ * Initializing constructor. Creates an exception with the specified error message.
+ */
+ explicit missing_value(std::string const& descr);
+ /*!
+ * Destructor
+ */
+ ~missing_value() throw();
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, attribute_name const& name);
+#endif
+};
+
+/*!
+ * \brief Exception class that is used to indicate errors of incorrect type of an object
+ */
+class BOOST_LOG_API invalid_type :
+ public runtime_error
+{
+public:
+ /*!
+ * Default constructor. Creates an exception with the default error message.
+ */
+ invalid_type();
+ /*!
+ * Initializing constructor. Creates an exception with the specified error message.
+ */
+ explicit invalid_type(std::string const& descr);
+ /*!
+ * Destructor
+ */
+ ~invalid_type() throw();
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, attribute_name const& name);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, type_info_wrapper const& type);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, attribute_name const& name, type_info_wrapper const& type);
+#endif
+};
+
+/*!
+ * \brief Exception class that is used to indicate errors of incorrect value of an object
+ */
+class BOOST_LOG_API invalid_value :
+ public runtime_error
+{
+public:
+ /*!
+ * Default constructor. Creates an exception with the default error message.
+ */
+ invalid_value();
+ /*!
+ * Initializing constructor. Creates an exception with the specified error message.
+ */
+ explicit invalid_value(std::string const& descr);
+ /*!
+ * Destructor
+ */
+ ~invalid_value() throw();
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr);
+#endif
+};
+
+/*!
+ * \brief Exception class that is used to indicate parsing errors
+ */
+class BOOST_LOG_API parse_error :
+ public runtime_error
+{
+public:
+ /*!
+ * Default constructor. Creates an exception with the default error message.
+ */
+ parse_error();
+ /*!
+ * Initializing constructor. Creates an exception with the specified error message.
+ */
+ explicit parse_error(std::string const& descr);
+ /*!
+ * Destructor
+ */
+ ~parse_error() throw();
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, std::size_t content_line);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, attribute_name const& name);
+#endif
+};
+
+/*!
+ * \brief Exception class that is used to indicate conversion errors
+ */
+class BOOST_LOG_API conversion_error :
+ public runtime_error
+{
+public:
+ /*!
+ * Default constructor. Creates an exception with the default error message.
+ */
+ conversion_error();
+ /*!
+ * Initializing constructor. Creates an exception with the specified error message.
+ */
+ explicit conversion_error(std::string const& descr);
+ /*!
+ * Destructor
+ */
+ ~conversion_error() throw();
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr);
+#endif
+};
+
+/*!
+ * \brief Exception class that is used to indicate underlying OS API errors
+ */
+class BOOST_LOG_API system_error :
+ public runtime_error
+{
+public:
+ /*!
+ * Default constructor. Creates an exception with the default error message.
+ */
+ system_error();
+ /*!
+ * Initializing constructor. Creates an exception with the specified error message.
+ */
+ explicit system_error(std::string const& descr);
+ /*!
+ * Destructor
+ */
+ ~system_error() throw();
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr);
+#endif
+};
+
+/*!
+ * \brief Base class for logic exceptions from the logging library
+ *
+ * Exceptions derived from this class usually indicate errors on the user's side, such as
+ * incorrect library usage.
+ */
+class BOOST_LOG_API logic_error :
+ public std::logic_error
+{
+protected:
+ /*!
+ * Initializing constructor. Creates an exception with the specified error message.
+ */
+ explicit logic_error(std::string const& descr);
+ /*!
+ * Destructor
+ */
+ ~logic_error() throw();
+};
+
+/*!
+ * \brief Exception class that is used to indicate ODR violation
+ */
+class BOOST_LOG_API odr_violation :
+ public logic_error
+{
+public:
+ /*!
+ * Default constructor. Creates an exception with the default error message.
+ */
+ odr_violation();
+ /*!
+ * Initializing constructor. Creates an exception with the specified error message.
+ */
+ explicit odr_violation(std::string const& descr);
+ /*!
+ * Destructor
+ */
+ ~odr_violation() throw();
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr);
+#endif
+};
+
+/*!
+ * \brief Exception class that is used to indicate invalid call sequence
+ */
+class BOOST_LOG_API unexpected_call :
+ public logic_error
+{
+public:
+ /*!
+ * Default constructor. Creates an exception with the default error message.
+ */
+ unexpected_call();
+ /*!
+ * Initializing constructor. Creates an exception with the specified error message.
+ */
+ explicit unexpected_call(std::string const& descr);
+ /*!
+ * Destructor
+ */
+ ~unexpected_call() throw();
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr);
+#endif
+};
+
+/*!
+ * \brief Exception class that is used to indicate invalid library setup
+ */
+class BOOST_LOG_API setup_error :
+ public logic_error
+{
+public:
+ /*!
+ * Default constructor. Creates an exception with the default error message.
+ */
+ setup_error();
+ /*!
+ * Initializing constructor. Creates an exception with the specified error message.
+ */
+ explicit setup_error(std::string const& descr);
+ /*!
+ * Destructor
+ */
+ ~setup_error() throw();
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr);
+#endif
+};
+
+/*!
+ * \brief Exception class that is used to indicate library limitation
+ */
+class BOOST_LOG_API limitation_error :
+ public logic_error
+{
+public:
+ /*!
+ * Default constructor. Creates an exception with the default error message.
+ */
+ limitation_error();
+ /*!
+ * Initializing constructor. Creates an exception with the specified error message.
+ */
+ explicit limitation_error(std::string const& descr);
+ /*!
+ * Destructor
+ */
+ ~limitation_error() throw();
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr);
+#endif
+};
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#define BOOST_LOG_THROW(ex)\
+ ex::throw_(__FILE__, static_cast< std::size_t >(__LINE__))
+
+#define BOOST_LOG_THROW_DESCR(ex, descr)\
+ ex::throw_(__FILE__, static_cast< std::size_t >(__LINE__), descr)
+
+#define BOOST_LOG_THROW_DESCR_PARAMS(ex, descr, params)\
+ ex::throw_(__FILE__, static_cast< std::size_t >(__LINE__), descr, BOOST_PP_SEQ_ENUM(params))
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXCEPTIONS_HPP_INCLUDED_
diff --git a/boost/log/expressions.hpp b/boost/log/expressions.hpp
new file mode 100644
index 0000000000..990981a233
--- /dev/null
+++ b/boost/log/expressions.hpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file expressions.hpp
+ * \author Andrey Semashev
+ * \date 10.11.2012
+ *
+ * This header includes other Boost.Log headers with all template expression tools.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#include <boost/log/expressions/attr.hpp>
+#include <boost/log/expressions/keyword.hpp>
+#include <boost/log/expressions/message.hpp>
+#include <boost/log/expressions/record.hpp>
+
+#include <boost/log/expressions/predicates.hpp>
+#include <boost/log/expressions/formatters.hpp>
+
+#include <boost/log/expressions/filter.hpp>
+#include <boost/log/expressions/formatter.hpp>
+
+// Boost.Phoenix operators are likely to be used with Boost.Log expression nodes anyway
+#include <boost/phoenix/operator.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#endif // BOOST_LOG_EXPRESSIONS_HPP_INCLUDED_
diff --git a/boost/log/expressions/attr.hpp b/boost/log/expressions/attr.hpp
new file mode 100644
index 0000000000..31deefc0a9
--- /dev/null
+++ b/boost/log/expressions/attr.hpp
@@ -0,0 +1,276 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file attr.hpp
+ * \author Andrey Semashev
+ * \date 21.07.2012
+ *
+ * The header contains implementation of a generic attribute placeholder in template expressions.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_ATTR_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_ATTR_HPP_INCLUDED_
+
+#include <boost/mpl/bool.hpp>
+#include <boost/utility/result_of.hpp>
+#include <boost/phoenix/core/actor.hpp>
+#include <boost/phoenix/core/terminal_fwd.hpp>
+#include <boost/phoenix/core/is_nullary.hpp>
+#include <boost/phoenix/core/environment.hpp>
+#include <boost/fusion/sequence/intrinsic/at_c.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/copy_cv.hpp>
+#include <boost/log/detail/custom_terminal_spec.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/value_extraction.hpp>
+#include <boost/log/attributes/fallback_policy.hpp>
+#include <boost/log/expressions/attr_fwd.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+/*!
+ * An attribute value extraction terminal
+ */
+template< typename T, typename FallbackPolicyT, typename TagT >
+class attribute_terminal
+{
+private:
+ //! Value extractor type
+ typedef value_extractor< T, FallbackPolicyT, TagT > value_extractor_type;
+ //! Self type
+ typedef attribute_terminal< T, FallbackPolicyT, TagT > this_type;
+
+public:
+ //! Internal typedef for type categorization
+ typedef void _is_boost_log_terminal;
+
+ //! Attribute tag type
+ typedef TagT tag_type;
+ //! Attribute value type
+ typedef typename value_extractor_type::value_type value_type;
+ //! Fallback policy type
+ typedef typename value_extractor_type::fallback_policy fallback_policy;
+
+ //! Function result type
+ template< typename >
+ struct result;
+
+ template< typename ThisT, typename ContextT >
+ struct result< ThisT(ContextT) >
+ {
+ typedef typename remove_cv<
+ typename remove_reference< typename phoenix::result_of::env< ContextT >::type >::type
+ >::type env_type;
+ typedef typename env_type::args_type args_type;
+ typedef typename boost::log::aux::copy_cv< ThisT, value_extractor_type >::type cv_value_extractor_type;
+
+ typedef typename boost::result_of< cv_value_extractor_type(attribute_name const&, typename fusion::result_of::at_c< args_type, 0 >::type) >::type type;
+ };
+
+private:
+ //! Attribute value name
+ const attribute_name m_name;
+ //! Attribute value extractor
+ value_extractor_type m_value_extractor;
+
+public:
+ /*!
+ * Initializing constructor
+ */
+ explicit attribute_terminal(attribute_name const& name) : m_name(name)
+ {
+ }
+
+ /*!
+ * Initializing constructor
+ */
+ template< typename U >
+ attribute_terminal(attribute_name const& name, U const& arg) : m_name(name), m_value_extractor(arg)
+ {
+ }
+
+ /*!
+ * \returns Attribute value name
+ */
+ attribute_name get_name() const
+ {
+ return m_name;
+ }
+
+ /*!
+ * \returns Fallback policy
+ */
+ fallback_policy const& get_fallback_policy() const
+ {
+ return m_value_extractor.get_fallback_policy();
+ }
+
+ /*!
+ * The operator extracts attribute value
+ */
+ template< typename ContextT >
+ typename result< this_type(ContextT const&) >::type
+ operator() (ContextT const& ctx)
+ {
+ return m_value_extractor(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()));
+ }
+
+ /*!
+ * The operator extracts attribute value
+ */
+ template< typename ContextT >
+ typename result< const this_type(ContextT const&) >::type
+ operator() (ContextT const& ctx) const
+ {
+ return m_value_extractor(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()));
+ }
+
+ BOOST_DELETED_FUNCTION(attribute_terminal())
+};
+
+/*!
+ * An attribute value extraction terminal actor
+ */
+template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT >
+class attribute_actor :
+ public ActorT< attribute_terminal< T, FallbackPolicyT, TagT > >
+{
+public:
+ //! Attribute tag type
+ typedef TagT tag_type;
+ //! Fallback policy
+ typedef FallbackPolicyT fallback_policy;
+ //! Base terminal type
+ typedef attribute_terminal< T, fallback_policy, tag_type > terminal_type;
+ //! Attribute value type
+ typedef typename terminal_type::value_type value_type;
+
+ //! Base actor type
+ typedef ActorT< terminal_type > base_type;
+
+public:
+ //! Initializing constructor
+ explicit attribute_actor(base_type const& act) : base_type(act)
+ {
+ }
+
+ /*!
+ * \returns The attribute name
+ */
+ attribute_name get_name() const
+ {
+ return this->proto_expr_.child0.get_name();
+ }
+
+ /*!
+ * \returns Fallback policy
+ */
+ fallback_policy const& get_fallback_policy() const
+ {
+ return this->proto_expr_.child0.get_fallback_policy();
+ }
+
+ //! Expression with cached attribute name
+ typedef attribute_actor< value_type, fallback_to_none, tag_type, ActorT > or_none_result_type;
+
+ //! Generates an expression that extracts the attribute value or a default value
+ or_none_result_type or_none() const
+ {
+ typedef typename or_none_result_type::terminal_type result_terminal;
+ typename or_none_result_type::base_type act = {{ result_terminal(get_name()) }};
+ return or_none_result_type(act);
+ }
+
+ //! Expression with cached attribute name
+ typedef attribute_actor< value_type, fallback_to_throw, tag_type, ActorT > or_throw_result_type;
+
+ //! Generates an expression that extracts the attribute value or throws an exception
+ or_throw_result_type or_throw() const
+ {
+ typedef typename or_throw_result_type::terminal_type result_terminal;
+ typename or_throw_result_type::base_type act = {{ result_terminal(get_name()) }};
+ return or_throw_result_type(act);
+ }
+
+ //! Generates an expression that extracts the attribute value or a default value
+ template< typename DefaultT >
+ attribute_actor< value_type, fallback_to_default< DefaultT >, tag_type, ActorT > or_default(DefaultT const& def_val) const
+ {
+ typedef attribute_actor< value_type, fallback_to_default< DefaultT >, tag_type, ActorT > or_default_result_type;
+ typedef typename or_default_result_type::terminal_type result_terminal;
+ typename or_default_result_type::base_type act = {{ result_terminal(get_name(), def_val) }};
+ return or_default_result_type(act);
+ }
+};
+
+/*!
+ * The function generates a terminal node in a template expression. The node will extract the value of the attribute
+ * with the specified name and type.
+ */
+template< typename AttributeValueT >
+BOOST_FORCEINLINE attribute_actor< AttributeValueT > attr(attribute_name const& name)
+{
+ typedef attribute_actor< AttributeValueT > result_type;
+ typedef typename result_type::terminal_type result_terminal;
+ typename result_type::base_type act = {{ result_terminal(name) }};
+ return result_type(act);
+}
+
+/*!
+ * The function generates a terminal node in a template expression. The node will extract the value of the attribute
+ * with the specified name and type.
+ */
+template< typename AttributeValueT, typename TagT >
+BOOST_FORCEINLINE attribute_actor< AttributeValueT, fallback_to_none, TagT > attr(attribute_name const& name)
+{
+ typedef attribute_actor< AttributeValueT, fallback_to_none, TagT > result_type;
+ typedef typename result_type::terminal_type result_terminal;
+ typename result_type::base_type act = {{ result_terminal(name) }};
+ return result_type(act);
+}
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+namespace phoenix {
+
+namespace result_of {
+
+template< typename T, typename FallbackPolicyT, typename TagT >
+struct is_nullary< custom_terminal< boost::log::expressions::attribute_terminal< T, FallbackPolicyT, TagT > > > :
+ public mpl::false_
+{
+};
+
+} // namespace result_of
+
+} // namespace phoenix
+
+#endif
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+#if defined(BOOST_LOG_EXPRESSIONS_FORMATTERS_STREAM_HPP_INCLUDED_)
+#include <boost/log/detail/attr_output_impl.hpp>
+#endif
+
+#endif // BOOST_LOG_EXPRESSIONS_ATTR_HPP_INCLUDED_
diff --git a/boost/log/expressions/attr_fwd.hpp b/boost/log/expressions/attr_fwd.hpp
new file mode 100644
index 0000000000..a8e7b92a81
--- /dev/null
+++ b/boost/log/expressions/attr_fwd.hpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file attr_fwd.hpp
+ * \author Andrey Semashev
+ * \date 21.07.2012
+ *
+ * The header contains forward declaration of a generic attribute placeholder in template expressions.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_ATTR_FWD_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_ATTR_FWD_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/attributes/fallback_policy_fwd.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+namespace phoenix {
+
+template< typename >
+struct actor;
+
+} // namespace phoenix
+
+#endif
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+/*!
+ * An attribute value extraction terminal
+ */
+template<
+ typename T,
+ typename FallbackPolicyT = fallback_to_none,
+ typename TagT = void
+>
+class attribute_terminal;
+
+/*!
+ * An attribute value extraction terminal actor
+ */
+template<
+ typename T,
+ typename FallbackPolicyT = fallback_to_none,
+ typename TagT = void,
+ template< typename > class ActorT = phoenix::actor
+>
+class attribute_actor;
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_EXPRESSIONS_ATTR_FWD_HPP_INCLUDED_
diff --git a/boost/log/expressions/filter.hpp b/boost/log/expressions/filter.hpp
new file mode 100644
index 0000000000..dcf7d59cde
--- /dev/null
+++ b/boost/log/expressions/filter.hpp
@@ -0,0 +1,183 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file filter.hpp
+ * \author Andrey Semashev
+ * \date 13.07.2012
+ *
+ * The header contains a filter function object definition.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_FILTER_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_FILTER_HPP_INCLUDED_
+
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include <boost/log/detail/light_function.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * Log record filter function wrapper.
+ */
+class filter
+{
+ BOOST_COPYABLE_AND_MOVABLE(filter)
+
+public:
+ //! Result type
+ typedef bool result_type;
+
+private:
+ //! Filter function type
+ typedef boost::log::aux::light_function< bool (attribute_value_set const&) > filter_type;
+
+ //! Default filter, always returns \c true
+ struct default_filter
+ {
+ typedef bool result_type;
+ result_type operator() (attribute_value_set const&) const { return true; }
+ };
+
+private:
+ //! Filter function
+ filter_type m_Filter;
+
+public:
+ /*!
+ * Default constructor. Creates a filter that always returns \c true.
+ */
+ filter() : m_Filter(default_filter())
+ {
+ }
+ /*!
+ * Copy constructor
+ */
+ filter(filter const& that) : m_Filter(that.m_Filter)
+ {
+ }
+ /*!
+ * Move constructor. The moved-from filter is left in an unspecified state.
+ */
+ filter(BOOST_RV_REF(filter) that) BOOST_NOEXCEPT : m_Filter(boost::move(that.m_Filter))
+ {
+ }
+
+ /*!
+ * Initializing constructor. Creates a filter which will invoke the specified function object.
+ */
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template< typename FunT >
+ filter(FunT&& fun) : m_Filter(boost::forward< FunT >(fun))
+ {
+ }
+#elif !defined(BOOST_MSVC) || BOOST_MSVC > 1400
+ template< typename FunT >
+ filter(FunT const& fun, typename disable_if_c< move_detail::is_rv< FunT >::value, int >::type = 0) : m_Filter(fun)
+ {
+ }
+#else
+ // MSVC 8 blows up in unexpected ways if we use SFINAE to disable constructor instantiation
+ template< typename FunT >
+ filter(FunT const& fun) : m_Filter(fun)
+ {
+ }
+ template< typename FunT >
+ filter(rv< FunT >& fun) : m_Filter(fun)
+ {
+ }
+ template< typename FunT >
+ filter(rv< FunT > const& fun) : m_Filter(static_cast< FunT const& >(fun))
+ {
+ }
+ filter(rv< filter > const& that) : m_Filter(that.m_Filter)
+ {
+ }
+#endif
+
+ /*!
+ * Move assignment. The moved-from filter is left in an unspecified state.
+ */
+ filter& operator= (BOOST_RV_REF(filter) that) BOOST_NOEXCEPT
+ {
+ m_Filter.swap(that.m_Filter);
+ return *this;
+ }
+ /*!
+ * Copy assignment.
+ */
+ filter& operator= (BOOST_COPY_ASSIGN_REF(filter) that)
+ {
+ m_Filter = that.m_Filter;
+ return *this;
+ }
+ /*!
+ * Initializing assignment. Sets the specified function object to the filter.
+ */
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template< typename FunT >
+ filter& operator= (FunT const& fun)
+#else
+ template< typename FunT >
+ typename disable_if< is_same< typename remove_cv< FunT >::type, filter >, filter& >::type
+ operator= (FunT const& fun)
+#endif
+ {
+ filter(fun).swap(*this);
+ return *this;
+ }
+
+ /*!
+ * Filtering operator.
+ *
+ * \param values Attribute values of the log record.
+ * \return \c true if the log record passes the filter, \c false otherwise.
+ */
+ result_type operator() (attribute_value_set const& values) const
+ {
+ return m_Filter(values);
+ }
+
+ /*!
+ * Resets the filter to the default. The default filter always returns \c true.
+ */
+ void reset()
+ {
+ m_Filter = default_filter();
+ }
+
+ /*!
+ * Swaps two filters
+ */
+ void swap(filter& that) BOOST_NOEXCEPT
+ {
+ m_Filter.swap(that.m_Filter);
+ }
+};
+
+inline void swap(filter& left, filter& right) BOOST_NOEXCEPT
+{
+ left.swap(right);
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_FILTER_HPP_INCLUDED_
diff --git a/boost/log/expressions/formatter.hpp b/boost/log/expressions/formatter.hpp
new file mode 100644
index 0000000000..05692ec287
--- /dev/null
+++ b/boost/log/expressions/formatter.hpp
@@ -0,0 +1,257 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file formatter.hpp
+ * \author Andrey Semashev
+ * \date 13.07.2012
+ *
+ * The header contains a formatter function object definition.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_FORMATTER_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_FORMATTER_HPP_INCLUDED_
+
+#include <boost/ref.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/light_function.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include <boost/log/attributes/value_visitation.hpp>
+#include <boost/log/core/record_view.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/utility/functional/bind_output.hpp>
+#include <boost/log/expressions/message.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+namespace aux {
+
+// This reference class is a workaround for a Boost.Phoenix bug: https://svn.boost.org/trac/boost/ticket/9363
+// It is needed to pass output streams by non-const reference to function objects wrapped in phoenix::bind and phoenix::function.
+// It's an implementation detail and will be removed when Boost.Phoenix is fixed.
+template< typename StreamT >
+class stream_ref :
+ public reference_wrapper< StreamT >
+{
+public:
+ BOOST_FORCEINLINE explicit stream_ref(StreamT& strm) : reference_wrapper< StreamT >(strm)
+ {
+ }
+
+ template< typename T >
+ BOOST_FORCEINLINE StreamT& operator<< (T& val) const
+ {
+ StreamT& strm = this->get();
+ strm << val;
+ return strm;
+ }
+
+ template< typename T >
+ BOOST_FORCEINLINE StreamT& operator<< (T const& val) const
+ {
+ StreamT& strm = this->get();
+ strm << val;
+ return strm;
+ }
+};
+
+//! Default log record message formatter
+struct message_formatter
+{
+ typedef void result_type;
+
+ message_formatter() : m_MessageName(expressions::tag::message::get_name())
+ {
+ }
+
+ template< typename StreamT >
+ result_type operator() (record_view const& rec, StreamT& strm) const
+ {
+ boost::log::visit< expressions::tag::message::value_type >(m_MessageName, rec, boost::log::bind_output(strm));
+ }
+
+private:
+ const attribute_name m_MessageName;
+};
+
+} // namespace aux
+
+} // namespace expressions
+
+/*!
+ * Log record formatter function wrapper.
+ */
+template< typename CharT >
+class basic_formatter
+{
+ typedef basic_formatter this_type;
+ BOOST_COPYABLE_AND_MOVABLE(this_type)
+
+public:
+ //! Result type
+ typedef void result_type;
+
+ //! Character type
+ typedef CharT char_type;
+ //! Output stream type
+ typedef basic_formatting_ostream< char_type > stream_type;
+
+private:
+ //! Filter function type
+ typedef boost::log::aux::light_function< void (record_view const&, expressions::aux::stream_ref< stream_type >) > formatter_type;
+
+private:
+ //! Formatter function
+ formatter_type m_Formatter;
+
+public:
+ /*!
+ * Default constructor. Creates a formatter that only outputs log message.
+ */
+ basic_formatter() : m_Formatter(expressions::aux::message_formatter())
+ {
+ }
+ /*!
+ * Copy constructor
+ */
+ basic_formatter(basic_formatter const& that) : m_Formatter(that.m_Formatter)
+ {
+ }
+ /*!
+ * Move constructor. The moved-from formatter is left in an unspecified state.
+ */
+ basic_formatter(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT : m_Formatter(boost::move(that.m_Formatter))
+ {
+ }
+
+ /*!
+ * Initializing constructor. Creates a formatter which will invoke the specified function object.
+ */
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template< typename FunT >
+ basic_formatter(FunT&& fun) : m_Formatter(boost::forward< FunT >(fun))
+ {
+ }
+#elif !defined(BOOST_MSVC) || BOOST_MSVC > 1400
+ template< typename FunT >
+ basic_formatter(FunT const& fun, typename disable_if_c< move_detail::is_rv< FunT >::value, int >::type = 0) : m_Formatter(fun)
+ {
+ }
+#else
+ // MSVC 8 blows up in unexpected ways if we use SFINAE to disable constructor instantiation
+ template< typename FunT >
+ basic_formatter(FunT const& fun) : m_Formatter(fun)
+ {
+ }
+ template< typename FunT >
+ basic_formatter(rv< FunT >& fun) : m_Formatter(fun)
+ {
+ }
+ template< typename FunT >
+ basic_formatter(rv< FunT > const& fun) : m_Formatter(static_cast< FunT const& >(fun))
+ {
+ }
+ basic_formatter(rv< this_type > const& that) : m_Formatter(that.m_Formatter)
+ {
+ }
+#endif
+
+ /*!
+ * Move assignment. The moved-from formatter is left in an unspecified state.
+ */
+ basic_formatter& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
+ {
+ m_Formatter.swap(that.m_Formatter);
+ return *this;
+ }
+ /*!
+ * Copy assignment.
+ */
+ basic_formatter& operator= (BOOST_COPY_ASSIGN_REF(this_type) that)
+ {
+ m_Formatter = that.m_Formatter;
+ return *this;
+ }
+ /*!
+ * Initializing assignment. Sets the specified function object to the formatter.
+ */
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template< typename FunT >
+ basic_formatter& operator= (FunT&& fun)
+ {
+ this_type(boost::forward< FunT >(fun)).swap(*this);
+ return *this;
+ }
+#else
+ template< typename FunT >
+ typename disable_if< is_same< typename remove_cv< FunT >::type, this_type >, this_type& >::type
+ operator= (FunT const& fun)
+ {
+ this_type(fun).swap(*this);
+ return *this;
+ }
+#endif
+
+ /*!
+ * Formatting operator.
+ *
+ * \param rec A log record to format.
+ * \param strm A stream to put the formatted characters to.
+ */
+ result_type operator() (record_view const& rec, stream_type& strm) const
+ {
+ m_Formatter(rec, expressions::aux::stream_ref< stream_type >(strm));
+ }
+
+ /*!
+ * Resets the formatter to the default. The default formatter only outputs message text.
+ */
+ void reset()
+ {
+ m_Formatter = expressions::aux::message_formatter();
+ }
+
+ /*!
+ * Swaps two formatters
+ */
+ void swap(basic_formatter& that) BOOST_NOEXCEPT
+ {
+ m_Formatter.swap(that.m_Formatter);
+ }
+};
+
+template< typename CharT >
+inline void swap(basic_formatter< CharT >& left, basic_formatter< CharT >& right) BOOST_NOEXCEPT
+{
+ left.swap(right);
+}
+
+#ifdef BOOST_LOG_USE_CHAR
+typedef basic_formatter< char > formatter;
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+typedef basic_formatter< wchar_t > wformatter;
+#endif
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_FORMATTER_HPP_INCLUDED_
diff --git a/boost/log/expressions/formatters.hpp b/boost/log/expressions/formatters.hpp
new file mode 100644
index 0000000000..47f84a516f
--- /dev/null
+++ b/boost/log/expressions/formatters.hpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file formatters.hpp
+ * \author Andrey Semashev
+ * \date 10.11.2012
+ *
+ * The header includes all template expression formatters.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_FORMATTERS_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#include <boost/log/expressions/formatters/stream.hpp>
+#include <boost/log/expressions/formatters/format.hpp>
+
+#include <boost/log/expressions/formatters/date_time.hpp>
+#include <boost/log/expressions/formatters/named_scope.hpp>
+
+#include <boost/log/expressions/formatters/char_decorator.hpp>
+#include <boost/log/expressions/formatters/xml_decorator.hpp>
+#include <boost/log/expressions/formatters/csv_decorator.hpp>
+#include <boost/log/expressions/formatters/c_decorator.hpp>
+
+#include <boost/log/expressions/formatters/if.hpp>
+#include <boost/log/expressions/formatters/wrap_formatter.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_HPP_INCLUDED_
diff --git a/boost/log/expressions/formatters/c_decorator.hpp b/boost/log/expressions/formatters/c_decorator.hpp
new file mode 100644
index 0000000000..a793b52bfe
--- /dev/null
+++ b/boost/log/expressions/formatters/c_decorator.hpp
@@ -0,0 +1,281 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file formatters/c_decorator.hpp
+ * \author Andrey Semashev
+ * \date 18.11.2012
+ *
+ * The header contains implementation of C-style character decorators.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_C_DECORATOR_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_FORMATTERS_C_DECORATOR_HPP_INCLUDED_
+
+#include <limits>
+#include <boost/range/iterator_range_core.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/snprintf.hpp>
+#include <boost/log/expressions/formatters/char_decorator.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+namespace aux {
+
+template< typename >
+struct c_decorator_traits;
+
+#ifdef BOOST_LOG_USE_CHAR
+template< >
+struct c_decorator_traits< char >
+{
+ static boost::iterator_range< const char* const* > get_patterns()
+ {
+ static const char* const patterns[] =
+ {
+ "\\", "\a", "\b", "\f", "\n", "\r", "\t", "\v", "'", "\"", "?"
+ };
+ return boost::make_iterator_range(patterns);
+ }
+ static boost::iterator_range< const char* const* > get_replacements()
+ {
+ static const char* const replacements[] =
+ {
+ "\\\\", "\\a", "\\b", "\\f", "\\n", "\\r", "\\t", "\\v", "\\'", "\\\"", "\\?"
+ };
+ return boost::make_iterator_range(replacements);
+ }
+ template< unsigned int N >
+ static std::size_t print_escaped(char (&buf)[N], char c)
+ {
+ int n = boost::log::aux::snprintf(buf, N, "\\x%0.2X", static_cast< unsigned int >(static_cast< uint8_t >(c)));
+ if (n < 0)
+ {
+ n = 0;
+ buf[0] = '\0';
+ }
+ return static_cast< unsigned int >(n) >= N ? N - 1 : static_cast< unsigned int >(n);
+ }
+};
+#endif // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+template< >
+struct c_decorator_traits< wchar_t >
+{
+ static boost::iterator_range< const wchar_t* const* > get_patterns()
+ {
+ static const wchar_t* const patterns[] =
+ {
+ L"\\", L"\a", L"\b", L"\f", L"\n", L"\r", L"\t", L"\v", L"'", L"\"", L"?"
+ };
+ return boost::make_iterator_range(patterns);
+ }
+ static boost::iterator_range< const wchar_t* const* > get_replacements()
+ {
+ static const wchar_t* const replacements[] =
+ {
+ L"\\\\", L"\\a", L"\\b", L"\\f", L"\\n", L"\\r", L"\\t", L"\\v", L"\\'", L"\\\"", L"\\?"
+ };
+ return boost::make_iterator_range(replacements);
+ }
+ template< unsigned int N >
+ static std::size_t print_escaped(wchar_t (&buf)[N], wchar_t c)
+ {
+ const wchar_t* format;
+ unsigned int val;
+ if (sizeof(wchar_t) == 1)
+ {
+ format = L"\\x%0.2X";
+ val = static_cast< uint8_t >(c);
+ }
+ else if (sizeof(wchar_t) == 2)
+ {
+ format = L"\\x%0.4X";
+ val = static_cast< uint16_t >(c);
+ }
+ else
+ {
+ format = L"\\x%0.8X";
+ val = static_cast< uint32_t >(c);
+ }
+
+ int n = boost::log::aux::swprintf(buf, N, format, val);
+ if (n < 0)
+ {
+ n = 0;
+ buf[0] = L'\0';
+ }
+ return static_cast< unsigned int >(n) >= N ? N - 1 : static_cast< unsigned int >(n);
+ }
+};
+#endif // BOOST_LOG_USE_WCHAR_T
+
+template< typename CharT >
+struct c_decorator_gen
+{
+ typedef CharT char_type;
+
+ template< typename SubactorT >
+ BOOST_FORCEINLINE char_decorator_actor< SubactorT, pattern_replacer< char_type > > operator[] (SubactorT const& subactor) const
+ {
+ typedef c_decorator_traits< char_type > traits_type;
+ typedef pattern_replacer< char_type > replacer_type;
+ typedef char_decorator_actor< SubactorT, replacer_type > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(subactor, replacer_type(traits_type::get_patterns(), traits_type::get_replacements())) }};
+ return result_type(act);
+ }
+};
+
+} // namespace aux
+
+/*!
+ * C-style decorator generator object. The decorator replaces characters with specific meaning in C
+ * language with the corresponding escape sequences. The generator provides <tt>operator[]</tt> that
+ * can be used to construct the actual decorator. For example:
+ *
+ * <code>
+ * c_decor[ attr< std::string >("MyAttr") ]
+ * </code>
+ *
+ * For wide-character formatting there is the similar \c wc_decor decorator generator object.
+ */
+#ifdef BOOST_LOG_USE_CHAR
+const aux::c_decorator_gen< char > c_decor = {};
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+const aux::c_decorator_gen< wchar_t > wc_decor = {};
+#endif
+
+/*!
+ * The function creates a C-style decorator generator for arbitrary character type.
+ */
+template< typename CharT >
+BOOST_FORCEINLINE aux::c_decorator_gen< CharT > make_c_decor()
+{
+ return aux::c_decorator_gen< CharT >();
+}
+
+/*!
+ * A character decorator implementation that escapes all non-prontable and non-ASCII characters
+ * in the output with C-style escape sequences.
+ */
+template< typename CharT >
+class c_ascii_pattern_replacer :
+ public pattern_replacer< CharT >
+{
+private:
+ //! Base type
+ typedef pattern_replacer< CharT > base_type;
+
+public:
+ //! Result type
+ typedef typename base_type::result_type result_type;
+ //! Character type
+ typedef typename base_type::char_type char_type;
+ //! String type
+ typedef typename base_type::string_type string_type;
+
+private:
+ //! Traits type
+ typedef aux::c_decorator_traits< char_type > traits_type;
+
+public:
+ //! Default constructor
+ c_ascii_pattern_replacer() : base_type(traits_type::get_patterns(), traits_type::get_replacements())
+ {
+ }
+
+ //! Applies string replacements starting from the specified position
+ result_type operator() (string_type& str, typename string_type::size_type start_pos = 0) const
+ {
+ base_type::operator() (str, start_pos);
+
+ typedef typename string_type::iterator string_iterator;
+ for (string_iterator it = str.begin() + start_pos, end = str.end(); it != end; ++it)
+ {
+ char_type c = *it;
+ if (c < 0x20 || c > 0x7e)
+ {
+ char_type buf[(std::numeric_limits< char_type >::digits + 3) / 4 + 3];
+ std::size_t n = traits_type::print_escaped(buf, c);
+ std::size_t pos = it - str.begin();
+ str.replace(pos, 1, buf, n);
+ it = str.begin() + n - 1;
+ end = str.end();
+ }
+ }
+ }
+};
+
+namespace aux {
+
+template< typename CharT >
+struct c_ascii_decorator_gen
+{
+ typedef CharT char_type;
+
+ template< typename SubactorT >
+ BOOST_FORCEINLINE char_decorator_actor< SubactorT, c_ascii_pattern_replacer< char_type > > operator[] (SubactorT const& subactor) const
+ {
+ typedef c_decorator_traits< char_type > traits_type;
+ typedef c_ascii_pattern_replacer< char_type > replacer_type;
+ typedef char_decorator_actor< SubactorT, replacer_type > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(subactor, replacer_type()) }};
+ return result_type(act);
+ }
+};
+
+} // namespace aux
+
+/*!
+ * C-style decorator generator object. Acts similarly to \c c_decor, except that \c c_ascii_decor also
+ * converts all non-ASCII and non-printable ASCII characters, except for space character, into
+ * C-style hexadecimal escape sequences. The generator provides <tt>operator[]</tt> that
+ * can be used to construct the actual decorator. For example:
+ *
+ * <code>
+ * c_ascii_decor[ attr< std::string >("MyAttr") ]
+ * </code>
+ *
+ * For wide-character formatting there is the similar \c wc_ascii_decor decorator generator object.
+ */
+#ifdef BOOST_LOG_USE_CHAR
+const aux::c_ascii_decorator_gen< char > c_ascii_decor = {};
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+const aux::c_ascii_decorator_gen< wchar_t > wc_ascii_decor = {};
+#endif
+
+/*!
+ * The function creates a C-style decorator generator for arbitrary character type.
+ */
+template< typename CharT >
+BOOST_FORCEINLINE aux::c_ascii_decorator_gen< CharT > make_c_ascii_decor()
+{
+ return aux::c_ascii_decorator_gen< CharT >();
+}
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_C_DECORATOR_HPP_INCLUDED_
diff --git a/boost/log/expressions/formatters/char_decorator.hpp b/boost/log/expressions/formatters/char_decorator.hpp
new file mode 100644
index 0000000000..ca24c0d486
--- /dev/null
+++ b/boost/log/expressions/formatters/char_decorator.hpp
@@ -0,0 +1,639 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file formatters/char_decorator.hpp
+ * \author Andrey Semashev
+ * \date 17.11.2012
+ *
+ * The header contains implementation of a character decorator.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_CHAR_DECORATOR_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_FORMATTERS_CHAR_DECORATOR_HPP_INCLUDED_
+
+#include <vector>
+#include <string>
+#include <iterator>
+#include <boost/assert.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/size.hpp>
+#include <boost/range/const_iterator.hpp>
+#include <boost/range/value_type.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/phoenix/core/actor.hpp>
+#include <boost/phoenix/core/meta_grammar.hpp>
+#include <boost/phoenix/core/terminal_fwd.hpp>
+#include <boost/phoenix/core/is_nullary.hpp>
+#include <boost/phoenix/core/environment.hpp>
+#include <boost/phoenix/support/vector.hpp>
+#include <boost/fusion/sequence/intrinsic/at_c.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/custom_terminal_spec.hpp>
+#include <boost/log/detail/deduce_char_type.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+namespace aux {
+
+template< typename RangeT >
+struct string_const_iterator : range_const_iterator< RangeT > {};
+template< >
+struct string_const_iterator< char* > { typedef char* type; };
+template< >
+struct string_const_iterator< const char* > { typedef const char* type; };
+template< >
+struct string_const_iterator< wchar_t* > { typedef wchar_t* type; };
+template< >
+struct string_const_iterator< const wchar_t* > { typedef const wchar_t* type; };
+
+} // namespace aux
+
+/*!
+ * A simple character decorator implementation. This implementation replaces string patterns in the source string with
+ * the fixed replacements. Source patterns and replacements can be specified at the object construction.
+ */
+template< typename CharT >
+class pattern_replacer
+{
+public:
+ //! Result type
+ typedef void result_type;
+
+ //! Character type
+ typedef CharT char_type;
+ //! String type
+ typedef std::basic_string< char_type > string_type;
+
+private:
+ //! Lengths of source pattern and replacement
+ struct string_lengths
+ {
+ unsigned int from_len, to_len;
+ };
+
+ //! List of the decorations to apply
+ typedef std::vector< string_lengths > string_lengths_list;
+
+private:
+ //! Characters of the interleaved source patterns and replacements
+ string_type m_decoration_chars;
+ //! List of the decorations to apply
+ string_lengths_list m_string_lengths;
+
+public:
+ /*!
+ * Initializing constructor. Creates a pattern replacer with the specified \a decorations.
+ * The provided decorations must be a sequence of \c std::pair of strings. The first element
+ * of each pair is the source pattern, and the second one is the corresponding replacement.
+ */
+ template< typename RangeT >
+ explicit pattern_replacer(RangeT const& decorations)
+ {
+ typedef typename range_const_iterator< RangeT >::type iterator;
+ for (iterator it = begin(decorations), end_ = end(decorations); it != end_; ++it)
+ {
+ string_lengths lens;
+ {
+ typedef typename aux::string_const_iterator< typename range_value< RangeT >::type::first_type >::type first_iterator;
+ first_iterator b = string_begin(it->first), e = string_end(it->first);
+ lens.from_len = static_cast< unsigned int >(std::distance(b, e));
+ m_decoration_chars.append(b, e);
+ }
+ {
+ typedef typename aux::string_const_iterator< typename range_value< RangeT >::type::second_type >::type second_iterator;
+ second_iterator b = string_begin(it->second), e = string_end(it->second);
+ lens.to_len = static_cast< unsigned int >(std::distance(b, e));
+ m_decoration_chars.append(b, e);
+ }
+ m_string_lengths.push_back(lens);
+ }
+ }
+ /*!
+ * Initializing constructor. Creates a pattern replacer with decorations specified
+ * in form of two same-sized string sequences. Each <tt>i</tt>'th decoration will be
+ * <tt>from[i]</tt> -> <tt>to[i]</tt>.
+ */
+ template< typename FromRangeT, typename ToRangeT >
+ pattern_replacer(FromRangeT const& from, ToRangeT const& to)
+ {
+ typedef typename range_const_iterator< FromRangeT >::type iterator1;
+ typedef typename range_const_iterator< ToRangeT >::type iterator2;
+ iterator1 it1 = begin(from), end1 = end(from);
+ iterator2 it2 = begin(to), end2 = end(to);
+ for (; it1 != end1 && it2 != end2; ++it1, ++it2)
+ {
+ string_lengths lens;
+ {
+ typedef typename aux::string_const_iterator< typename range_value< FromRangeT >::type >::type from_iterator;
+ from_iterator b = string_begin(*it1), e = string_end(*it1);
+ lens.from_len = static_cast< unsigned int >(std::distance(b, e));
+ m_decoration_chars.append(b, e);
+ }
+ {
+ typedef typename aux::string_const_iterator< typename range_value< ToRangeT >::type >::type to_iterator;
+ to_iterator b = string_begin(*it2), e = string_end(*it2);
+ lens.to_len = static_cast< unsigned int >(std::distance(b, e));
+ m_decoration_chars.append(b, e);
+ }
+ m_string_lengths.push_back(lens);
+ }
+
+ // Both sequences should be of the same size
+ BOOST_ASSERT(it1 == end1);
+ BOOST_ASSERT(it2 == end2);
+ }
+ //! Copy constructor
+ pattern_replacer(pattern_replacer const& that) : m_decoration_chars(that.m_decoration_chars), m_string_lengths(that.m_string_lengths)
+ {
+ }
+
+ //! Applies string replacements starting from the specified position
+ result_type operator() (string_type& str, typename string_type::size_type start_pos = 0) const
+ {
+ typedef typename string_type::size_type size_type;
+
+ const char_type* from_chars = m_decoration_chars.c_str();
+ for (typename string_lengths_list::const_iterator it = m_string_lengths.begin(), end = m_string_lengths.end(); it != end; ++it)
+ {
+ const unsigned int from_len = it->from_len, to_len = it->to_len;
+ const char_type* const to_chars = from_chars + from_len;
+ for (size_type pos = str.find(from_chars, start_pos, from_len); pos != string_type::npos; pos = str.find(from_chars, pos, from_len))
+ {
+ str.replace(pos, from_len, to_chars, to_len);
+ pos += to_len;
+ }
+ from_chars = to_chars + to_len;
+ }
+ }
+
+private:
+ static char_type* string_begin(char_type* p)
+ {
+ return p;
+ }
+ static const char_type* string_begin(const char_type* p)
+ {
+ return p;
+ }
+ template< typename RangeT >
+ static typename range_const_iterator< RangeT >::type string_begin(RangeT const& r)
+ {
+ return begin(r);
+ }
+
+ static char_type* string_end(char_type* p)
+ {
+ while (*p)
+ ++p;
+ return p;
+ }
+ static const char_type* string_end(const char_type* p)
+ {
+ while (*p)
+ ++p;
+ return p;
+ }
+ template< typename RangeT >
+ static typename range_const_iterator< RangeT >::type string_end(RangeT const& r)
+ {
+ return end(r);
+ }
+};
+
+namespace aux {
+
+//! Character decorator stream output terminal
+template< typename LeftT, typename SubactorT, typename ImplT >
+class char_decorator_output_terminal
+{
+private:
+ //! Self type
+ typedef char_decorator_output_terminal< LeftT, SubactorT, ImplT > this_type;
+
+public:
+ //! Internal typedef for type categorization
+ typedef void _is_boost_log_terminal;
+
+ //! Implementation type
+ typedef ImplT impl_type;
+
+ //! Character type
+ typedef typename impl_type::char_type char_type;
+ //! String type
+ typedef typename impl_type::string_type string_type;
+ //! Adopted actor type
+ typedef SubactorT subactor_type;
+
+ //! Result type definition
+ template< typename >
+ struct result;
+
+ template< typename ThisT, typename ContextT >
+ struct result< ThisT(ContextT) >
+ {
+ typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type;
+ typedef typename phoenix::evaluator::impl<
+ typename LeftT::proto_base_expr&,
+ context_type,
+ phoenix::unused
+ >::result_type type;
+ };
+
+private:
+ //! Left argument actor
+ LeftT m_left;
+ //! Adopted formatter actor
+ subactor_type m_subactor;
+ //! Implementation type
+ impl_type m_impl;
+
+public:
+ /*!
+ * Initializing constructor. Creates decorator of the \a fmt formatter with the specified \a decorations.
+ */
+ char_decorator_output_terminal(LeftT const& left, subactor_type const& sub, impl_type const& impl) :
+ m_left(left), m_subactor(sub), m_impl(impl)
+ {
+ }
+ /*!
+ * Copy constructor
+ */
+ char_decorator_output_terminal(char_decorator_output_terminal const& that) :
+ m_left(that.m_left), m_subactor(that.m_subactor), m_impl(that.m_impl)
+ {
+ }
+
+ /*!
+ * Invokation operator
+ */
+ template< typename ContextT >
+ typename result< this_type(ContextT const&) >::type operator() (ContextT const& ctx)
+ {
+ // Flush the stream and keep the current write position in the target string
+ typedef typename result< this_type(ContextT const&) >::type result_type;
+ result_type strm = phoenix::eval(m_left, ctx);
+ strm.flush();
+ typename string_type::size_type const start_pos = strm.rdbuf()->storage()->size();
+
+ // Invoke the adopted formatter
+ typedef typename result< this_type(ContextT const&) >::type result_type;
+ phoenix::eval(m_subactor, ctx);
+
+ // Flush the buffered characters and apply decorations
+ strm.flush();
+ m_impl(*strm.rdbuf()->storage(), start_pos);
+
+ return strm;
+ }
+
+ /*!
+ * Invokation operator
+ */
+ template< typename ContextT >
+ typename result< const this_type(ContextT const&) >::type operator() (ContextT const& ctx) const
+ {
+ // Flush the stream and keep the current write position in the target string
+ typedef typename result< const this_type(ContextT const&) >::type result_type;
+ result_type strm = phoenix::eval(m_left, ctx);
+ strm.flush();
+ typename string_type::size_type const start_pos = strm.rdbuf()->storage()->size();
+
+ // Invoke the adopted formatter
+ typedef typename result< const this_type(ContextT const&) >::type result_type;
+ phoenix::eval(m_subactor, ctx);
+
+ // Flush the buffered characters and apply decorations
+ strm.flush();
+ m_impl(*strm.rdbuf()->storage(), start_pos);
+
+ return strm;
+ }
+
+ BOOST_DELETED_FUNCTION(char_decorator_output_terminal())
+};
+
+} // namespace aux
+
+/*!
+ * Character decorator terminal class. This formatter allows to modify strings generated by other
+ * formatters on character level. The most obvious application of decorators is replacing
+ * a certain set of characters with decorated equivalents to satisfy requirements of
+ * text-based sinks.
+ *
+ * The \c char_decorator_terminal class aggregates the formatter being decorated, and a set
+ * of string pairs that are used as decorations. All decorations are applied sequentially.
+ * The \c char_decorator_terminal class is a formatter itself, so it can be used to construct
+ * more complex formatters, including nesting decorators.
+ */
+template< typename SubactorT, typename ImplT >
+class char_decorator_terminal
+{
+private:
+ //! Self type
+ typedef char_decorator_terminal< SubactorT, ImplT > this_type;
+
+public:
+ //! Internal typedef for type categorization
+ typedef void _is_boost_log_terminal;
+
+ //! Implementation type
+ typedef ImplT impl_type;
+ //! Character type
+ typedef typename impl_type::char_type char_type;
+ //! String type
+ typedef typename impl_type::string_type string_type;
+ //! Stream type
+ typedef basic_formatting_ostream< char_type > stream_type;
+ //! Adopted actor type
+ typedef SubactorT subactor_type;
+
+ //! Result type definition
+ typedef string_type result_type;
+
+private:
+ //! Adopted formatter actor
+ subactor_type m_subactor;
+ //! Implementation
+ impl_type m_impl;
+
+public:
+ /*!
+ * Initializing constructor.
+ */
+ char_decorator_terminal(subactor_type const& sub, impl_type const& impl) : m_subactor(sub), m_impl(impl)
+ {
+ }
+ /*!
+ * Copy constructor
+ */
+ char_decorator_terminal(char_decorator_terminal const& that) : m_subactor(that.m_subactor), m_impl(that.m_impl)
+ {
+ }
+
+ /*!
+ * \returns Adopted subactor
+ */
+ subactor_type const& get_subactor() const
+ {
+ return m_subactor;
+ }
+
+ /*!
+ * \returns Implementation
+ */
+ impl_type const& get_impl() const
+ {
+ return m_impl;
+ }
+
+ /*!
+ * Invokation operator
+ */
+ template< typename ContextT >
+ result_type operator() (ContextT const& ctx)
+ {
+ string_type str;
+ stream_type strm(str);
+
+ // Invoke the adopted formatter
+ typedef phoenix::vector3<
+ subactor_type*,
+ typename fusion::result_of::at_c<
+ typename remove_cv<
+ typename remove_reference<
+ typename phoenix::result_of::env< ContextT const& >::type
+ >::type
+ >::type::args_type,
+ 0
+ >::type,
+ stream_type&
+ > env_type;
+ env_type env = { boost::addressof(m_subactor), fusion::at_c< 0 >(phoenix::env(ctx).args()), strm };
+ phoenix::eval(m_subactor, phoenix::make_context(env, phoenix::actions(ctx)));
+
+ // Flush the buffered characters and apply decorations
+ strm.flush();
+ m_impl(*strm.rdbuf()->storage());
+
+ return boost::move(str);
+ }
+
+ /*!
+ * Invokation operator
+ */
+ template< typename ContextT >
+ result_type operator() (ContextT const& ctx) const
+ {
+ string_type str;
+ stream_type strm(str);
+
+ // Invoke the adopted formatter
+ typedef phoenix::vector3<
+ const subactor_type*,
+ typename fusion::result_of::at_c<
+ typename remove_cv<
+ typename remove_reference<
+ typename phoenix::result_of::env< ContextT const& >::type
+ >::type
+ >::type::args_type,
+ 0
+ >::type,
+ stream_type&
+ > env_type;
+ env_type env = { boost::addressof(m_subactor), fusion::at_c< 0 >(phoenix::env(ctx).args()), strm };
+ phoenix::eval(m_subactor, phoenix::make_context(env, phoenix::actions(ctx)));
+
+ // Flush the buffered characters and apply decorations
+ strm.flush();
+ m_impl(*strm.rdbuf()->storage());
+
+ return boost::move(str);
+ }
+
+ BOOST_DELETED_FUNCTION(char_decorator_terminal())
+};
+
+/*!
+ * Character decorator actor
+ */
+template< typename SubactorT, typename ImplT, template< typename > class ActorT = phoenix::actor >
+class char_decorator_actor :
+ public ActorT< char_decorator_terminal< SubactorT, ImplT > >
+{
+public:
+ //! Base terminal type
+ typedef char_decorator_terminal< SubactorT, ImplT > terminal_type;
+ //! Character type
+ typedef typename terminal_type::char_type char_type;
+
+ //! Base actor type
+ typedef ActorT< terminal_type > base_type;
+
+public:
+ //! Initializing constructor
+ explicit char_decorator_actor(base_type const& act) : base_type(act)
+ {
+ }
+
+ //! Returns reference to the terminal
+ terminal_type const& get_terminal() const
+ {
+ return this->proto_expr_.child0;
+ }
+};
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\
+ template< typename LeftExprT, typename SubactorT, typename ImplT, template< typename > class ActorT >\
+ BOOST_FORCEINLINE phoenix::actor< aux::char_decorator_output_terminal< phoenix::actor< LeftExprT >, SubactorT, ImplT > >\
+ operator<< (phoenix::actor< LeftExprT > left_ref left, char_decorator_actor< SubactorT, ImplT, ActorT > right_ref right)\
+ {\
+ typedef aux::char_decorator_output_terminal< phoenix::actor< LeftExprT >, SubactorT, ImplT > terminal_type;\
+ phoenix::actor< terminal_type > actor = {{ terminal_type(left, right.get_terminal().get_subactor(), right.get_terminal().get_impl()) }};\
+ return actor;\
+ }
+
+#include <boost/log/detail/generate_overloads.hpp>
+
+#undef BOOST_LOG_AUX_OVERLOAD
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+namespace aux {
+
+template< typename RangeT >
+class char_decorator_gen1
+{
+ RangeT const& m_decorations;
+
+ typedef typename boost::log::aux::deduce_char_type< typename range_value< RangeT >::type::first_type >::type char_type;
+
+public:
+ explicit char_decorator_gen1(RangeT const& decorations) : m_decorations(decorations)
+ {
+ }
+
+ template< typename SubactorT >
+ BOOST_FORCEINLINE char_decorator_actor< SubactorT, pattern_replacer< char_type > > operator[] (SubactorT const& subactor) const
+ {
+ typedef pattern_replacer< char_type > replacer_type;
+ typedef char_decorator_actor< SubactorT, replacer_type > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(subactor, replacer_type(m_decorations)) }};
+ return result_type(act);
+ }
+};
+
+template< typename FromRangeT, typename ToRangeT >
+class char_decorator_gen2
+{
+ FromRangeT const& m_from;
+ ToRangeT const& m_to;
+
+ typedef typename boost::log::aux::deduce_char_type< typename range_value< FromRangeT >::type >::type from_char_type;
+ typedef typename boost::log::aux::deduce_char_type< typename range_value< ToRangeT >::type >::type to_char_type;
+ BOOST_STATIC_ASSERT_MSG((is_same< from_char_type, to_char_type >::value), "Boost.Log: character decorator cannot be instantiated with different character types for source and replacement strings");
+
+public:
+ char_decorator_gen2(FromRangeT const& from, ToRangeT const& to) : m_from(from), m_to(to)
+ {
+ }
+
+ template< typename SubactorT >
+ BOOST_FORCEINLINE char_decorator_actor< SubactorT, pattern_replacer< from_char_type > > operator[] (SubactorT const& subactor) const
+ {
+ typedef pattern_replacer< from_char_type > replacer_type;
+ typedef char_decorator_actor< SubactorT, replacer_type > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(subactor, replacer_type(m_from, m_to)) }};
+ return result_type(act);
+ }
+};
+
+} // namespace aux
+
+/*!
+ * The function returns a decorator generator object. The generator provides <tt>operator[]</tt> that can be used
+ * to construct the actual decorator.
+ *
+ * \param decorations A sequence of string pairs that will be used as decorations. Every <tt>decorations[i].first</tt>
+ * substring occurrence in the output will be replaced with <tt>decorations[i].second</tt>.
+ */
+template< typename RangeT >
+BOOST_FORCEINLINE aux::char_decorator_gen1< RangeT > char_decor(RangeT const& decorations)
+{
+ return aux::char_decorator_gen1< RangeT >(decorations);
+}
+
+/*!
+ * The function returns a decorator generator object. The generator provides <tt>operator[]</tt> that can be used
+ * to construct the actual decorator.
+ *
+ * \param from A sequence of strings that will be sought in the output.
+ * \param to A sequence of strings that will be used as replacements.
+ *
+ * \note The \a from and \a to sequences mush be of the same size. Every <tt>from[i]</tt>
+ * substring occurrence in the output will be replaced with <tt>to[i]</tt>.
+ */
+template< typename FromRangeT, typename ToRangeT >
+BOOST_FORCEINLINE aux::char_decorator_gen2< FromRangeT, ToRangeT > char_decor(FromRangeT const& from, ToRangeT const& to)
+{
+ return aux::char_decorator_gen2< FromRangeT, ToRangeT >(from, to);
+}
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+namespace phoenix {
+
+namespace result_of {
+
+template< typename SubactorT, typename ImplT >
+struct is_nullary< custom_terminal< boost::log::expressions::char_decorator_terminal< SubactorT, ImplT > > > :
+ public mpl::false_
+{
+};
+
+template< typename LeftT, typename SubactorT, typename ImplT >
+struct is_nullary< custom_terminal< boost::log::expressions::aux::char_decorator_output_terminal< LeftT, SubactorT, ImplT > > > :
+ public mpl::false_
+{
+};
+
+} // namespace result_of
+
+} // namespace phoenix
+
+#endif
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_CHAR_DECORATOR_HPP_INCLUDED_
diff --git a/boost/log/expressions/formatters/csv_decorator.hpp b/boost/log/expressions/formatters/csv_decorator.hpp
new file mode 100644
index 0000000000..8c964a0d13
--- /dev/null
+++ b/boost/log/expressions/formatters/csv_decorator.hpp
@@ -0,0 +1,140 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file formatters/csv_decorator.hpp
+ * \author Andrey Semashev
+ * \date 18.11.2012
+ *
+ * The header contains implementation of a CSV-style character decorator.
+ * See: http://en.wikipedia.org/wiki/Comma-separated_values
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_CSV_DECORATOR_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_FORMATTERS_CSV_DECORATOR_HPP_INCLUDED_
+
+#include <boost/range/iterator_range_core.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/expressions/formatters/char_decorator.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+namespace aux {
+
+template< typename >
+struct csv_decorator_traits;
+
+#ifdef BOOST_LOG_USE_CHAR
+template< >
+struct csv_decorator_traits< char >
+{
+ static boost::iterator_range< const char* const* > get_patterns()
+ {
+ static const char* const patterns[] =
+ {
+ "\""
+ };
+ return boost::make_iterator_range(patterns);
+ }
+ static boost::iterator_range< const char* const* > get_replacements()
+ {
+ static const char* const replacements[] =
+ {
+ "\"\""
+ };
+ return boost::make_iterator_range(replacements);
+ }
+};
+#endif // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+template< >
+struct csv_decorator_traits< wchar_t >
+{
+ static boost::iterator_range< const wchar_t* const* > get_patterns()
+ {
+ static const wchar_t* const patterns[] =
+ {
+ L"\""
+ };
+ return boost::make_iterator_range(patterns);
+ }
+ static boost::iterator_range< const wchar_t* const* > get_replacements()
+ {
+ static const wchar_t* const replacements[] =
+ {
+ L"\"\""
+ };
+ return boost::make_iterator_range(replacements);
+ }
+};
+#endif // BOOST_LOG_USE_WCHAR_T
+
+template< typename CharT >
+struct csv_decorator_gen
+{
+ typedef CharT char_type;
+
+ template< typename SubactorT >
+ BOOST_FORCEINLINE char_decorator_actor< SubactorT, pattern_replacer< char_type > > operator[] (SubactorT const& subactor) const
+ {
+ typedef csv_decorator_traits< char_type > traits_type;
+ typedef pattern_replacer< char_type > replacer_type;
+ typedef char_decorator_actor< SubactorT, replacer_type > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(subactor, replacer_type(traits_type::get_patterns(), traits_type::get_replacements())) }};
+ return result_type(act);
+ }
+};
+
+} // namespace aux
+
+/*!
+ * CSV-style decorator generator object. The decorator doubles double quotes that may be found
+ * in the output. See http://en.wikipedia.org/wiki/Comma-separated_values for more information on
+ * the CSV format. The generator provides <tt>operator[]</tt> that can be used to construct
+ * the actual decorator. For example:
+ *
+ * <code>
+ * csv_decor[ attr< std::string >("MyAttr") ]
+ * </code>
+ *
+ * For wide-character formatting there is the similar \c wcsv_decor decorator generator object.
+ */
+#ifdef BOOST_LOG_USE_CHAR
+const aux::csv_decorator_gen< char > csv_decor = {};
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+const aux::csv_decorator_gen< wchar_t > wcsv_decor = {};
+#endif
+
+/*!
+ * The function creates an CSV-style decorator generator for arbitrary character type.
+ */
+template< typename CharT >
+BOOST_FORCEINLINE aux::csv_decorator_gen< CharT > make_csv_decor()
+{
+ return aux::csv_decorator_gen< CharT >();
+}
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_CSV_DECORATOR_HPP_INCLUDED_
diff --git a/boost/log/expressions/formatters/date_time.hpp b/boost/log/expressions/formatters/date_time.hpp
new file mode 100644
index 0000000000..0ff6b680e6
--- /dev/null
+++ b/boost/log/expressions/formatters/date_time.hpp
@@ -0,0 +1,343 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file formatters/date_time.hpp
+ * \author Andrey Semashev
+ * \date 16.09.2012
+ *
+ * The header contains a formatter function for date and time attribute values.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_DATE_TIME_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_FORMATTERS_DATE_TIME_HPP_INCLUDED_
+
+#include <string>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/phoenix/core/actor.hpp>
+#include <boost/phoenix/core/terminal_fwd.hpp>
+#include <boost/phoenix/core/is_nullary.hpp>
+#include <boost/phoenix/core/environment.hpp>
+#include <boost/fusion/sequence/intrinsic/at_c.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/fallback_policy.hpp>
+#include <boost/log/attributes/value_visitation.hpp>
+#include <boost/log/detail/light_function.hpp>
+#include <boost/log/detail/date_time_fmt_gen_traits_fwd.hpp>
+#include <boost/log/detail/custom_terminal_spec.hpp>
+#include <boost/log/detail/attr_output_terminal.hpp>
+#include <boost/log/expressions/attr_fwd.hpp>
+#include <boost/log/expressions/keyword_fwd.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/utility/functional/bind.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+/*!
+ * Date and time formatter terminal.
+ */
+template< typename T, typename FallbackPolicyT, typename CharT >
+class format_date_time_terminal
+{
+public:
+ //! Internal typedef for type categorization
+ typedef void _is_boost_log_terminal;
+
+ //! Attribute value type
+ typedef T value_type;
+ //! Fallback policy
+ typedef FallbackPolicyT fallback_policy;
+ //! Character type
+ typedef CharT char_type;
+ //! String type
+ typedef std::basic_string< char_type > string_type;
+ //! Formatting stream type
+ typedef basic_formatting_ostream< char_type > stream_type;
+
+ //! Formatter function
+ typedef boost::log::aux::light_function< void (stream_type&, value_type const&) > formatter_function_type;
+
+ //! Function result type
+ typedef string_type result_type;
+
+private:
+ //! Formatter generator traits
+ typedef aux::date_time_formatter_generator_traits< value_type, char_type > formatter_generator;
+ //! Attribute value visitor invoker
+ typedef value_visitor_invoker< value_type, fallback_policy > visitor_invoker_type;
+
+private:
+ //! Attribute name
+ attribute_name m_name;
+ //! Formattr function
+ formatter_function_type m_formatter;
+ //! Attribute value visitor invoker
+ visitor_invoker_type m_visitor_invoker;
+
+public:
+ //! Initializing constructor
+ format_date_time_terminal(attribute_name const& name, fallback_policy const& fallback, string_type const& format) :
+ m_name(name), m_formatter(formatter_generator::parse(format)), m_visitor_invoker(fallback)
+ {
+ }
+ //! Copy constructor
+ format_date_time_terminal(format_date_time_terminal const& that) :
+ m_name(that.m_name), m_formatter(that.m_formatter), m_visitor_invoker(that.m_visitor_invoker)
+ {
+ }
+
+ //! Returns attribute name
+ attribute_name get_name() const
+ {
+ return m_name;
+ }
+
+ //! Returns fallback policy
+ fallback_policy const& get_fallback_policy() const
+ {
+ return m_visitor_invoker.get_fallback_policy();
+ }
+
+ //! Retruns formatter function
+ formatter_function_type const& get_formatter_function() const
+ {
+ return m_formatter;
+ }
+
+ //! Invokation operator
+ template< typename ContextT >
+ result_type operator() (ContextT const& ctx)
+ {
+ string_type str;
+ stream_type strm(str);
+ m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< formatter_function_type&, stream_type& >(m_formatter, strm));
+ strm.flush();
+ return boost::move(str);
+ }
+
+ //! Invokation operator
+ template< typename ContextT >
+ result_type operator() (ContextT const& ctx) const
+ {
+ string_type str;
+ stream_type strm(str);
+ m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< formatter_function_type const&, stream_type& >(m_formatter, strm));
+ strm.flush();
+ return boost::move(str);
+ }
+
+ BOOST_DELETED_FUNCTION(format_date_time_terminal())
+};
+
+/*!
+ * Date and time formatter actor.
+ */
+template< typename T, typename FallbackPolicyT, typename CharT, template< typename > class ActorT = phoenix::actor >
+class format_date_time_actor :
+ public ActorT< format_date_time_terminal< T, FallbackPolicyT, CharT > >
+{
+public:
+ //! Attribute value type
+ typedef T value_type;
+ //! Character type
+ typedef CharT char_type;
+ //! Fallback policy
+ typedef FallbackPolicyT fallback_policy;
+ //! Base terminal type
+ typedef format_date_time_terminal< value_type, fallback_policy, char_type > terminal_type;
+ //! Formatter function
+ typedef typename terminal_type::formatter_function_type formatter_function_type;
+
+ //! Base actor type
+ typedef ActorT< terminal_type > base_type;
+
+public:
+ //! Initializing constructor
+ explicit format_date_time_actor(base_type const& act) : base_type(act)
+ {
+ }
+
+ /*!
+ * \returns The attribute name
+ */
+ attribute_name get_name() const
+ {
+ return this->proto_expr_.child0.get_name();
+ }
+
+ /*!
+ * \returns Fallback policy
+ */
+ fallback_policy const& get_fallback_policy() const
+ {
+ return this->proto_expr_.child0.get_fallback_policy();
+ }
+
+ /*!
+ * \returns Formatter function
+ */
+ formatter_function_type const& get_formatter_function() const
+ {
+ return this->proto_expr_.child0.get_formatter_function();
+ }
+};
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\
+ template< typename LeftExprT, typename T, typename FallbackPolicyT, typename CharT >\
+ BOOST_FORCEINLINE phoenix::actor< aux::attribute_output_terminal< phoenix::actor< LeftExprT >, T, FallbackPolicyT, typename format_date_time_actor< T, FallbackPolicyT, CharT >::formatter_function_type > >\
+ operator<< (phoenix::actor< LeftExprT > left_ref left, format_date_time_actor< T, FallbackPolicyT, CharT > right_ref right)\
+ {\
+ typedef aux::attribute_output_terminal< phoenix::actor< LeftExprT >, T, FallbackPolicyT, typename format_date_time_actor< T, FallbackPolicyT, CharT >::formatter_function_type > terminal_type;\
+ phoenix::actor< terminal_type > actor = {{ terminal_type(left, right.get_name(), right.get_formatter_function(), right.get_fallback_policy()) }};\
+ return actor;\
+ }
+
+#include <boost/log/detail/generate_overloads.hpp>
+
+#undef BOOST_LOG_AUX_OVERLOAD
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting
+ * expression (stream output or \c format placeholder filler).
+ *
+ * \param name Attribute name
+ * \param format Format string
+ */
+template< typename AttributeValueT, typename CharT >
+BOOST_FORCEINLINE format_date_time_actor< AttributeValueT, fallback_to_none, CharT > format_date_time(attribute_name const& name, const CharT* format)
+{
+ typedef format_date_time_actor< AttributeValueT, fallback_to_none, CharT > actor_type;
+ typedef typename actor_type::terminal_type terminal_type;
+ typename actor_type::base_type act = {{ terminal_type(name, fallback_to_none(), format) }};
+ return actor_type(act);
+}
+
+/*!
+ * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting
+ * expression (stream output or \c format placeholder filler).
+ *
+ * \param name Attribute name
+ * \param format Format string
+ */
+template< typename AttributeValueT, typename CharT >
+BOOST_FORCEINLINE format_date_time_actor< AttributeValueT, fallback_to_none, CharT > format_date_time(attribute_name const& name, std::basic_string< CharT > const& format)
+{
+ typedef format_date_time_actor< AttributeValueT, fallback_to_none, CharT > actor_type;
+ typedef typename actor_type::terminal_type terminal_type;
+ typename actor_type::base_type act = {{ terminal_type(name, fallback_to_none(), format) }};
+ return actor_type(act);
+}
+
+/*!
+ * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting
+ * expression (stream output or \c format placeholder filler).
+ *
+ * \param keyword Attribute keyword
+ * \param format Format string
+ */
+template< typename DescriptorT, template< typename > class ActorT, typename CharT >
+BOOST_FORCEINLINE format_date_time_actor< typename DescriptorT::value_type, fallback_to_none, CharT, ActorT >
+format_date_time(attribute_keyword< DescriptorT, ActorT > const& keyword, const CharT* format)
+{
+ typedef format_date_time_actor< typename DescriptorT::value_type, fallback_to_none, CharT, ActorT > actor_type;
+ typedef typename actor_type::terminal_type terminal_type;
+ typename actor_type::base_type act = {{ terminal_type(keyword.get_name(), fallback_to_none(), format) }};
+ return actor_type(act);
+}
+
+/*!
+ * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting
+ * expression (stream output or \c format placeholder filler).
+ *
+ * \param keyword Attribute keyword
+ * \param format Format string
+ */
+template< typename DescriptorT, template< typename > class ActorT, typename CharT >
+BOOST_FORCEINLINE format_date_time_actor< typename DescriptorT::value_type, fallback_to_none, CharT, ActorT >
+format_date_time(attribute_keyword< DescriptorT, ActorT > const& keyword, std::basic_string< CharT > const& format)
+{
+ typedef format_date_time_actor< typename DescriptorT::value_type, fallback_to_none, CharT, ActorT > actor_type;
+ typedef typename actor_type::terminal_type terminal_type;
+ typename actor_type::base_type act = {{ terminal_type(keyword.get_name(), fallback_to_none(), format) }};
+ return actor_type(act);
+}
+
+/*!
+ * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting
+ * expression (stream output or \c format placeholder filler).
+ *
+ * \param placeholder Attribute placeholder
+ * \param format Format string
+ */
+template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename CharT >
+BOOST_FORCEINLINE format_date_time_actor< T, FallbackPolicyT, CharT, ActorT >
+format_date_time(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& placeholder, const CharT* format)
+{
+ typedef format_date_time_actor< T, FallbackPolicyT, CharT, ActorT > actor_type;
+ typedef typename actor_type::terminal_type terminal_type;
+ typename actor_type::base_type act = {{ terminal_type(placeholder.get_name(), placeholder.get_fallback_policy(), format) }};
+ return actor_type(act);
+}
+
+/*!
+ * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting
+ * expression (stream output or \c format placeholder filler).
+ *
+ * \param placeholder Attribute placeholder
+ * \param format Format string
+ */
+template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename CharT >
+BOOST_FORCEINLINE format_date_time_actor< T, FallbackPolicyT, CharT, ActorT >
+format_date_time(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& placeholder, std::basic_string< CharT > const& format)
+{
+ typedef format_date_time_actor< T, FallbackPolicyT, CharT, ActorT > actor_type;
+ typedef typename actor_type::terminal_type terminal_type;
+ typename actor_type::base_type act = {{ terminal_type(placeholder.get_name(), placeholder.get_fallback_policy(), format) }};
+ return actor_type(act);
+}
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+namespace phoenix {
+
+namespace result_of {
+
+template< typename T, typename FallbackPolicyT, typename CharT >
+struct is_nullary< custom_terminal< boost::log::expressions::format_date_time_terminal< T, FallbackPolicyT, CharT > > > :
+ public mpl::false_
+{
+};
+
+} // namespace result_of
+
+} // namespace phoenix
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_DATE_TIME_HPP_INCLUDED_
diff --git a/boost/log/expressions/formatters/format.hpp b/boost/log/expressions/formatters/format.hpp
new file mode 100644
index 0000000000..c5d7917453
--- /dev/null
+++ b/boost/log/expressions/formatters/format.hpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file formatters/format.hpp
+ * \author Andrey Semashev
+ * \date 15.11.2012
+ *
+ * The header contains a generic log record formatter function.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_FORMAT_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_FORMATTERS_FORMAT_HPP_INCLUDED_
+
+#include <string>
+#include <boost/mpl/bool.hpp>
+#include <boost/phoenix/core/actor.hpp>
+#include <boost/phoenix/core/terminal_fwd.hpp>
+#include <boost/phoenix/core/is_nullary.hpp>
+#include <boost/phoenix/core/environment.hpp>
+#include <boost/fusion/sequence/intrinsic/at_c.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/format.hpp>
+#include <boost/log/detail/custom_terminal_spec.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+/*!
+ * \brief Template expressions terminal node with Boost.Format-like formatter
+ */
+template< typename CharT >
+class format_terminal
+{
+public:
+ //! Internal typedef for type categorization
+ typedef void _is_boost_log_terminal;
+
+ //! Character type
+ typedef CharT char_type;
+ //! Boost.Format formatter type
+ typedef boost::log::aux::basic_format< char_type > format_type;
+ //! String type
+ typedef std::basic_string< char_type > string_type;
+
+ //! Terminal result type
+ typedef typename format_type::pump result_type;
+
+private:
+ //! Formatter object
+ mutable format_type m_format;
+
+public:
+ //! Initializing constructor
+ explicit format_terminal(const char_type* format) : m_format(format) {}
+
+ //! Invokation operator
+ template< typename ContextT >
+ result_type operator() (ContextT const& ctx) const
+ {
+ return m_format.make_pump(fusion::at_c< 1 >(phoenix::env(ctx).args()));
+ }
+
+ BOOST_DELETED_FUNCTION(format_terminal())
+};
+
+/*!
+ * The function generates a terminal node in a template expression. The node will perform log record formatting
+ * according to the provided format string.
+ */
+template< typename CharT >
+BOOST_FORCEINLINE phoenix::actor< format_terminal< CharT > > format(const CharT* fmt)
+{
+ typedef format_terminal< CharT > terminal_type;
+ phoenix::actor< terminal_type > act = {{ terminal_type(fmt) }};
+ return act;
+}
+
+/*!
+ * The function generates a terminal node in a template expression. The node will perform log record formatting
+ * according to the provided format string.
+ */
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_FORCEINLINE phoenix::actor< format_terminal< CharT > > format(std::basic_string< CharT, TraitsT, AllocatorT > const& fmt)
+{
+ typedef format_terminal< CharT > terminal_type;
+ phoenix::actor< terminal_type > act = {{ terminal_type(fmt.c_str()) }};
+ return act;
+}
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+namespace phoenix {
+
+namespace result_of {
+
+template< typename CharT >
+struct is_nullary< custom_terminal< boost::log::expressions::format_terminal< CharT > > > :
+ public mpl::false_
+{
+};
+
+} // namespace result_of
+
+} // namespace phoenix
+
+#endif
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_FORMAT_HPP_INCLUDED_
diff --git a/boost/log/expressions/formatters/if.hpp b/boost/log/expressions/formatters/if.hpp
new file mode 100644
index 0000000000..0985439761
--- /dev/null
+++ b/boost/log/expressions/formatters/if.hpp
@@ -0,0 +1,315 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file formatters/if.hpp
+ * \author Andrey Semashev
+ * \date 17.11.2012
+ *
+ * The header contains implementation of a conditional formatter.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_IF_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_FORMATTERS_IF_HPP_INCLUDED_
+
+#include <boost/mpl/bool.hpp>
+#include <boost/phoenix/core/actor.hpp>
+#include <boost/phoenix/core/meta_grammar.hpp>
+#include <boost/phoenix/core/terminal_fwd.hpp>
+#include <boost/phoenix/core/is_nullary.hpp>
+#include <boost/phoenix/core/environment.hpp>
+#include <boost/fusion/sequence/intrinsic/at_c.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/custom_terminal_spec.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+namespace aux {
+
+template< typename LeftT, typename CondT, typename ThenT >
+class if_output_terminal
+{
+private:
+ //! Self type
+ typedef if_output_terminal this_type;
+
+public:
+ //! Internal typedef for type categorization
+ typedef void _is_boost_log_terminal;
+
+ //! Result type definition
+ template< typename >
+ struct result;
+
+ template< typename ThisT, typename ContextT >
+ struct result< ThisT(ContextT) >
+ {
+ typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type;
+ typedef typename phoenix::evaluator::impl<
+ typename LeftT::proto_base_expr&,
+ context_type,
+ phoenix::unused
+ >::result_type type;
+ };
+
+private:
+ //! Left argument actor
+ LeftT m_left;
+ //! Condition expression
+ CondT m_cond;
+ //! Positive branch
+ ThenT m_then;
+
+public:
+ //! Initializing constructor
+ if_output_terminal(LeftT const& left, CondT const& cond, ThenT const& then_) : m_left(left), m_cond(cond), m_then(then_)
+ {
+ }
+
+ //! Invokation operator
+ template< typename ContextT >
+ typename result< this_type(ContextT const&) >::type operator() (ContextT const& ctx)
+ {
+ typedef typename result< this_type(ContextT const&) >::type result_type;
+ result_type strm = phoenix::eval(m_left, ctx);
+ if (phoenix::eval(m_cond, ctx))
+ phoenix::eval(m_then, ctx);
+ return strm;
+ }
+
+ //! Invokation operator
+ template< typename ContextT >
+ typename result< const this_type(ContextT const&) >::type operator() (ContextT const& ctx) const
+ {
+ typedef typename result< const this_type(ContextT const&) >::type result_type;
+ result_type strm = phoenix::eval(m_left, ctx);
+ if (phoenix::eval(m_cond, ctx))
+ phoenix::eval(m_then, ctx);
+ return strm;
+ }
+
+ BOOST_DELETED_FUNCTION(if_output_terminal())
+};
+
+template< typename LeftT, typename CondT, typename ThenT, typename ElseT >
+class if_else_output_terminal
+{
+private:
+ //! Self type
+ typedef if_else_output_terminal this_type;
+
+public:
+ //! Internal typedef for type categorization
+ typedef void _is_boost_log_terminal;
+
+ //! Result type definition
+ template< typename >
+ struct result;
+
+ template< typename ThisT, typename ContextT >
+ struct result< ThisT(ContextT) >
+ {
+ typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type;
+ typedef typename phoenix::evaluator::impl<
+ typename LeftT::proto_base_expr&,
+ context_type,
+ phoenix::unused
+ >::result_type type;
+ };
+
+private:
+ //! Left argument actor
+ LeftT m_left;
+ //! Condition expression
+ CondT m_cond;
+ //! Positive branch
+ ThenT m_then;
+ //! Negative branch
+ ElseT m_else;
+
+public:
+ //! Initializing constructor
+ if_else_output_terminal(LeftT const& left, CondT const& cond, ThenT const& then_, ElseT const& else_) : m_left(left), m_cond(cond), m_then(then_), m_else(else_)
+ {
+ }
+
+ //! Invokation operator
+ template< typename ContextT >
+ typename result< this_type(ContextT const&) >::type operator() (ContextT const& ctx)
+ {
+ typedef typename result< this_type(ContextT const&) >::type result_type;
+ result_type strm = phoenix::eval(m_left, ctx);
+ if (phoenix::eval(m_cond, ctx))
+ phoenix::eval(m_then, ctx);
+ else
+ phoenix::eval(m_else, ctx);
+ return strm;
+ }
+
+ //! Invokation operator
+ template< typename ContextT >
+ typename result< const this_type(ContextT const&) >::type operator() (ContextT const& ctx) const
+ {
+ typedef typename result< const this_type(ContextT const&) >::type result_type;
+ result_type strm = phoenix::eval(m_left, ctx);
+ if (phoenix::eval(m_cond, ctx))
+ phoenix::eval(m_then, ctx);
+ else
+ phoenix::eval(m_else, ctx);
+ return strm;
+ }
+
+ BOOST_DELETED_FUNCTION(if_else_output_terminal())
+};
+
+
+template< typename CondT, typename ThenT, typename ElseT >
+struct if_then_else_gen
+{
+ CondT m_cond;
+ ThenT m_then;
+ ElseT m_else;
+
+ if_then_else_gen(CondT const& cond, ThenT const& then_, ElseT const& else_) : m_cond(cond), m_then(then_), m_else(else_)
+ {
+ }
+};
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\
+ template< typename LeftExprT, typename CondT, typename ThenT, typename ElseT >\
+ BOOST_FORCEINLINE phoenix::actor< if_else_output_terminal< phoenix::actor< LeftExprT >, CondT, ThenT, ElseT > >\
+ operator<< (phoenix::actor< LeftExprT > left_ref left, if_then_else_gen< CondT, ThenT, ElseT > right_ref right)\
+ {\
+ typedef if_else_output_terminal< phoenix::actor< LeftExprT >, CondT, ThenT, ElseT > terminal_type;\
+ phoenix::actor< terminal_type > actor = {{ terminal_type(left, right.m_cond, right.m_then, right.m_else) }};\
+ return actor;\
+ }
+
+#include <boost/log/detail/generate_overloads.hpp>
+
+#undef BOOST_LOG_AUX_OVERLOAD
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+template< typename CondT, typename ThenT >
+struct if_then_gen
+{
+ struct else_gen
+ {
+ CondT m_cond;
+ ThenT m_then;
+
+ else_gen(CondT const& cond, ThenT const& then_) : m_cond(cond), m_then(then_)
+ {
+ }
+
+ template< typename ElseT >
+ BOOST_FORCEINLINE if_then_else_gen< CondT, ThenT, ElseT > operator[] (ElseT const& el)
+ {
+ return if_then_else_gen< CondT, ThenT, ElseT >(m_cond, m_then, el);
+ }
+ }
+ else_;
+
+ if_then_gen(CondT const& cond, ThenT const& then_) : else_(cond, then_) {}
+};
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\
+ template< typename LeftExprT, typename CondT, typename ThenT >\
+ BOOST_FORCEINLINE phoenix::actor< if_output_terminal< phoenix::actor< LeftExprT >, CondT, ThenT > >\
+ operator<< (phoenix::actor< LeftExprT > left_ref left, if_then_gen< CondT, ThenT > right_ref right)\
+ {\
+ typedef if_output_terminal< phoenix::actor< LeftExprT >, CondT, ThenT > terminal_type;\
+ phoenix::actor< terminal_type > actor = {{ terminal_type(left, right.else_.m_cond, right.else_.m_then) }};\
+ return actor;\
+ }
+
+#include <boost/log/detail/generate_overloads.hpp>
+
+#undef BOOST_LOG_AUX_OVERLOAD
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+template< typename CondT >
+class if_gen
+{
+private:
+ CondT const& m_cond;
+
+public:
+ explicit if_gen(CondT const& cond) : m_cond(cond)
+ {
+ }
+
+ template< typename ThenT >
+ BOOST_FORCEINLINE if_then_gen< CondT, ThenT > operator[] (ThenT const& then_) const
+ {
+ return if_then_gen< CondT, ThenT >(m_cond, then_);
+ }
+};
+
+} // namespace aux
+
+/*!
+ * The function returns a conditional formatter generator object. The generator provides <tt>operator[]</tt> that can be used
+ * to construct the actual formatter. The formatter must participate in a streaming expression.
+ *
+ * \param cond A filter expression that will be used as the condition
+ */
+template< typename CondT >
+BOOST_FORCEINLINE aux::if_gen< CondT > if_(CondT const& cond)
+{
+ return aux::if_gen< CondT >(cond);
+}
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+namespace phoenix {
+
+namespace result_of {
+
+template< typename LeftT, typename CondT, typename ThenT >
+struct is_nullary< custom_terminal< boost::log::expressions::aux::if_output_terminal< LeftT, CondT, ThenT > > > :
+ public mpl::false_
+{
+};
+
+template< typename LeftT, typename CondT, typename ThenT, typename ElseT >
+struct is_nullary< custom_terminal< boost::log::expressions::aux::if_else_output_terminal< LeftT, CondT, ThenT, ElseT > > > :
+ public mpl::false_
+{
+};
+
+} // namespace result_of
+
+} // namespace phoenix
+
+#endif
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_IF_HPP_INCLUDED_
diff --git a/boost/log/expressions/formatters/named_scope.hpp b/boost/log/expressions/formatters/named_scope.hpp
new file mode 100644
index 0000000000..2225e00ec9
--- /dev/null
+++ b/boost/log/expressions/formatters/named_scope.hpp
@@ -0,0 +1,653 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file formatters/named_scope.hpp
+ * \author Andrey Semashev
+ * \date 11.11.2012
+ *
+ * The header contains a formatter function for named scope attribute values.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_NAMED_SCOPE_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_FORMATTERS_NAMED_SCOPE_HPP_INCLUDED_
+
+#include <string>
+#include <iterator>
+#include <utility>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/parameter/binding.hpp>
+#include <boost/preprocessor/iteration/iterate.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#include <boost/phoenix/core/actor.hpp>
+#include <boost/phoenix/core/terminal_fwd.hpp>
+#include <boost/phoenix/core/is_nullary.hpp>
+#include <boost/phoenix/core/environment.hpp>
+#include <boost/fusion/sequence/intrinsic/at_c.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/fallback_policy.hpp>
+#include <boost/log/attributes/named_scope.hpp>
+#include <boost/log/attributes/value_visitation.hpp>
+#include <boost/log/detail/light_function.hpp>
+#include <boost/log/detail/parameter_tools.hpp>
+#include <boost/log/detail/custom_terminal_spec.hpp>
+#include <boost/log/detail/deduce_char_type.hpp>
+#include <boost/log/detail/attr_output_terminal.hpp>
+#include <boost/log/expressions/attr_fwd.hpp>
+#include <boost/log/expressions/keyword_fwd.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/utility/string_literal_fwd.hpp>
+#include <boost/log/utility/functional/bind.hpp>
+#include <boost/log/keywords/format.hpp>
+#include <boost/log/keywords/delimiter.hpp>
+#include <boost/log/keywords/depth.hpp>
+#include <boost/log/keywords/iteration.hpp>
+#include <boost/log/keywords/empty_marker.hpp>
+#include <boost/log/keywords/incomplete_marker.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+//! Scope iteration directions
+enum scope_iteration_direction
+{
+ forward, //!< Iterate through scopes from outermost to innermost
+ reverse //!< Iterate through scopes from innermost to outermost
+};
+
+namespace aux {
+
+#ifdef BOOST_LOG_USE_CHAR
+//! Parses the named scope format string and constructs the formatter function
+BOOST_LOG_API boost::log::aux::light_function< void (basic_formatting_ostream< char >&, attributes::named_scope::value_type::value_type const&) >
+parse_named_scope_format(const char* begin, const char* end);
+#endif
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+//! Parses the named scope format string and constructs the formatter function
+BOOST_LOG_API boost::log::aux::light_function< void (basic_formatting_ostream< wchar_t >&, attributes::named_scope::value_type::value_type const&) >
+parse_named_scope_format(const wchar_t* begin, const wchar_t* end);
+#endif
+
+//! Parses the named scope format string and constructs the formatter function
+template< typename CharT >
+inline boost::log::aux::light_function< void (basic_formatting_ostream< CharT >&, attributes::named_scope::value_type::value_type const&) >
+parse_named_scope_format(const CharT* format)
+{
+ return parse_named_scope_format(format, format + std::char_traits< CharT >::length(format));
+}
+
+//! Parses the named scope format string and constructs the formatter function
+template< typename CharT, typename TraitsT, typename AllocatorT >
+inline boost::log::aux::light_function< void (basic_formatting_ostream< CharT >&, attributes::named_scope::value_type::value_type const&) >
+parse_named_scope_format(std::basic_string< CharT, TraitsT, AllocatorT > const& format)
+{
+ const CharT* p = format.c_str();
+ return parse_named_scope_format(p, p + format.size());
+}
+
+//! Parses the named scope format string and constructs the formatter function
+template< typename CharT, typename TraitsT >
+inline boost::log::aux::light_function< void (basic_formatting_ostream< CharT >&, attributes::named_scope::value_type::value_type const&) >
+parse_named_scope_format(basic_string_literal< CharT, TraitsT > const& format)
+{
+ const CharT* p = format.c_str();
+ return parse_named_scope_format(p, p + format.size());
+}
+
+template< typename CharT >
+class format_named_scope_impl
+{
+public:
+ //! Function result type
+ typedef void result_type;
+
+ //! Character type
+ typedef CharT char_type;
+ //! String type
+ typedef std::basic_string< char_type > string_type;
+ //! Formatting stream type
+ typedef basic_formatting_ostream< char_type > stream_type;
+ //! Attribute value type
+ typedef attributes::named_scope::value_type value_type;
+ //! Named scope formatter
+ typedef boost::log::aux::light_function< void (stream_type&, value_type::value_type const&) > element_formatter_type;
+
+private:
+ //! Element formatting function
+ element_formatter_type m_element_formatter;
+ //! Element delimiter
+ string_type m_delimiter;
+ //! Incomplete list marker
+ string_type m_incomplete_marker;
+ //! Empty list marker
+ string_type m_empty_marker;
+ //! Maximum number of elements to output
+ value_type::size_type m_depth;
+ //! Iteration direction
+ scope_iteration_direction m_direction;
+
+public:
+ //! Initializing constructor
+ format_named_scope_impl
+ (
+ element_formatter_type const& element_formatter,
+ string_type const& delimiter,
+ string_type const& incomplete_marker,
+ string_type const& empty_marker,
+ value_type::size_type depth,
+ scope_iteration_direction direction
+ ) :
+ m_element_formatter(element_formatter),
+ m_delimiter(delimiter),
+ m_incomplete_marker(incomplete_marker),
+ m_empty_marker(empty_marker),
+ m_depth(depth),
+ m_direction(direction)
+ {
+ }
+ //! Copy constructor
+ format_named_scope_impl(format_named_scope_impl const& that) :
+ m_element_formatter(that.m_element_formatter),
+ m_delimiter(that.m_delimiter),
+ m_incomplete_marker(that.m_incomplete_marker),
+ m_empty_marker(that.m_empty_marker),
+ m_depth(that.m_depth),
+ m_direction(that.m_direction)
+ {
+ }
+
+ //! Formatting operator
+ result_type operator() (stream_type& strm, value_type const& scopes) const
+ {
+ if (!scopes.empty())
+ {
+ if (m_direction == expressions::forward)
+ format_forward(strm, scopes);
+ else
+ format_reverse(strm, scopes);
+ }
+ else
+ {
+ strm << m_empty_marker;
+ }
+ }
+
+private:
+ //! The function performs formatting of the extracted scope stack in forward direction
+ void format_forward(stream_type& strm, value_type const& scopes) const
+ {
+ value_type::const_iterator it, end = scopes.end();
+ if (m_depth > 0)
+ {
+ value_type::size_type const scopes_to_iterate = (std::min)(m_depth, scopes.size());
+ it = scopes.end();
+ std::advance(it, -static_cast< value_type::difference_type >(scopes_to_iterate));
+ }
+ else
+ {
+ it = scopes.begin();
+ }
+
+ if (it != end)
+ {
+ if (it != scopes.begin())
+ strm << m_incomplete_marker;
+
+ m_element_formatter(strm, *it);
+ for (++it; it != end; ++it)
+ {
+ strm << m_delimiter;
+ m_element_formatter(strm, *it);
+ }
+ }
+ }
+ //! The function performs formatting of the extracted scope stack in reverse direction
+ void format_reverse(stream_type& strm, value_type const& scopes) const
+ {
+ value_type::const_reverse_iterator it = scopes.rbegin(), end;
+ if (m_depth > 0)
+ {
+ value_type::size_type const scopes_to_iterate = (std::min)(m_depth, scopes.size());
+ end = it;
+ std::advance(end, static_cast< value_type::difference_type >(scopes_to_iterate));
+ }
+ else
+ {
+ end = scopes.rend();
+ }
+
+ if (it != end)
+ {
+ m_element_formatter(strm, *it);
+ for (++it; it != end; ++it)
+ {
+ strm << m_delimiter;
+ m_element_formatter(strm, *it);
+ }
+
+ if (it != scopes.rend())
+ strm << m_incomplete_marker;
+ }
+ }
+};
+
+} // namespace aux
+
+/*!
+ * Named scope formatter terminal.
+ */
+template< typename FallbackPolicyT, typename CharT >
+class format_named_scope_terminal
+{
+public:
+ //! Internal typedef for type categorization
+ typedef void _is_boost_log_terminal;
+
+ //! Attribute value type
+ typedef attributes::named_scope::value_type value_type;
+ //! Fallback policy
+ typedef FallbackPolicyT fallback_policy;
+ //! Character type
+ typedef CharT char_type;
+ //! String type
+ typedef std::basic_string< char_type > string_type;
+ //! Formatting stream type
+ typedef basic_formatting_ostream< char_type > stream_type;
+ //! Formatter function
+ typedef aux::format_named_scope_impl< char_type > formatter_function_type;
+
+ //! Function result type
+ typedef string_type result_type;
+
+private:
+ //! Attribute value visitor invoker
+ typedef value_visitor_invoker< value_type, fallback_policy > visitor_invoker_type;
+
+private:
+ //! Attribute name
+ attribute_name m_name;
+ //! Formatter function
+ formatter_function_type m_formatter;
+ //! Attribute value visitor invoker
+ visitor_invoker_type m_visitor_invoker;
+
+public:
+ //! Initializing constructor
+ template< typename FormatT >
+ format_named_scope_terminal
+ (
+ attribute_name const& name,
+ fallback_policy const& fallback,
+ FormatT const& element_format,
+ string_type const& delimiter,
+ string_type const& incomplete_marker,
+ string_type const& empty_marker,
+ value_type::size_type depth,
+ scope_iteration_direction direction
+ ) :
+ m_name(name), m_formatter(aux::parse_named_scope_format(element_format), delimiter, incomplete_marker, empty_marker, depth, direction), m_visitor_invoker(fallback)
+ {
+ }
+ //! Copy constructor
+ format_named_scope_terminal(format_named_scope_terminal const& that) :
+ m_name(that.m_name), m_formatter(that.m_formatter), m_visitor_invoker(that.m_visitor_invoker)
+ {
+ }
+
+ //! Returns attribute name
+ attribute_name get_name() const
+ {
+ return m_name;
+ }
+
+ //! Returns fallback policy
+ fallback_policy const& get_fallback_policy() const
+ {
+ return m_visitor_invoker.get_fallback_policy();
+ }
+
+ //! Retruns formatter function
+ formatter_function_type const& get_formatter_function() const
+ {
+ return m_formatter;
+ }
+
+ //! Invokation operator
+ template< typename ContextT >
+ result_type operator() (ContextT const& ctx)
+ {
+ string_type str;
+ stream_type strm(str);
+ m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< formatter_function_type&, stream_type& >(m_formatter, strm));
+ strm.flush();
+ return boost::move(str);
+ }
+
+ //! Invokation operator
+ template< typename ContextT >
+ result_type operator() (ContextT const& ctx) const
+ {
+ string_type str;
+ stream_type strm(str);
+ m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< formatter_function_type const&, stream_type& >(m_formatter, strm));
+ strm.flush();
+ return boost::move(str);
+ }
+
+ BOOST_DELETED_FUNCTION(format_named_scope_terminal())
+};
+
+/*!
+ * Named scope formatter actor.
+ */
+template< typename FallbackPolicyT, typename CharT, template< typename > class ActorT = phoenix::actor >
+class format_named_scope_actor :
+ public ActorT< format_named_scope_terminal< FallbackPolicyT, CharT > >
+{
+public:
+ //! Character type
+ typedef CharT char_type;
+ //! Fallback policy
+ typedef FallbackPolicyT fallback_policy;
+ //! Base terminal type
+ typedef format_named_scope_terminal< fallback_policy, char_type > terminal_type;
+ //! Attribute value type
+ typedef typename terminal_type::value_type value_type;
+ //! Formatter function
+ typedef typename terminal_type::formatter_function_type formatter_function_type;
+
+ //! Base actor type
+ typedef ActorT< terminal_type > base_type;
+
+public:
+ //! Initializing constructor
+ explicit format_named_scope_actor(base_type const& act) : base_type(act)
+ {
+ }
+
+ /*!
+ * \returns The attribute name
+ */
+ attribute_name get_name() const
+ {
+ return this->proto_expr_.child0.get_name();
+ }
+
+ /*!
+ * \returns Fallback policy
+ */
+ fallback_policy const& get_fallback_policy() const
+ {
+ return this->proto_expr_.child0.get_fallback_policy();
+ }
+
+ /*!
+ * \returns Formatter function
+ */
+ formatter_function_type const& get_formatter_function() const
+ {
+ return this->proto_expr_.child0.get_formatter_function();
+ }
+};
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\
+ template< typename LeftExprT, typename FallbackPolicyT, typename CharT >\
+ BOOST_FORCEINLINE phoenix::actor< aux::attribute_output_terminal< phoenix::actor< LeftExprT >, attributes::named_scope::value_type, FallbackPolicyT, typename format_named_scope_actor< FallbackPolicyT, CharT >::formatter_function_type > >\
+ operator<< (phoenix::actor< LeftExprT > left_ref left, format_named_scope_actor< FallbackPolicyT, CharT > right_ref right)\
+ {\
+ typedef aux::attribute_output_terminal< phoenix::actor< LeftExprT >, attributes::named_scope::value_type, FallbackPolicyT, typename format_named_scope_actor< FallbackPolicyT, CharT >::formatter_function_type > terminal_type;\
+ phoenix::actor< terminal_type > actor = {{ terminal_type(left, right.get_name(), right.get_formatter_function(), right.get_fallback_policy()) }};\
+ return actor;\
+ }
+
+#include <boost/log/detail/generate_overloads.hpp>
+
+#undef BOOST_LOG_AUX_OVERLOAD
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+namespace aux {
+
+//! Auxiliary traits to acquire default formatter parameters depending on the character type
+template< typename CharT >
+struct default_named_scope_params;
+
+#ifdef BOOST_LOG_USE_CHAR
+template< >
+struct default_named_scope_params< char >
+{
+ static const char* forward_delimiter() { return "->"; }
+ static const char* reverse_delimiter() { return "<-"; }
+ static const char* incomplete_marker() { return "..."; }
+ static const char* empty_marker() { return ""; }
+};
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+template< >
+struct default_named_scope_params< wchar_t >
+{
+ static const wchar_t* forward_delimiter() { return L"->"; }
+ static const wchar_t* reverse_delimiter() { return L"<-"; }
+ static const wchar_t* incomplete_marker() { return L"..."; }
+ static const wchar_t* empty_marker() { return L""; }
+};
+#endif
+
+template< typename CharT, template< typename > class ActorT, typename FallbackPolicyT, typename ArgsT >
+BOOST_FORCEINLINE format_named_scope_actor< FallbackPolicyT, CharT, ActorT > format_named_scope(attribute_name const& name, FallbackPolicyT const& fallback, ArgsT const& args)
+{
+ typedef format_named_scope_actor< FallbackPolicyT, CharT, ActorT > actor_type;
+ typedef typename actor_type::terminal_type terminal_type;
+ typedef default_named_scope_params< CharT > default_params;
+ scope_iteration_direction dir = args[keywords::iteration | expressions::forward];
+ const CharT* default_delimiter = (dir == expressions::forward ? default_params::forward_delimiter() : default_params::reverse_delimiter());
+ typename actor_type::base_type act =
+ {{
+ terminal_type
+ (
+ name,
+ fallback,
+ args[keywords::format],
+ args[keywords::delimiter | default_delimiter],
+ args[keywords::incomplete_marker | default_params::incomplete_marker()],
+ args[keywords::empty_marker | default_params::empty_marker()],
+ args[keywords::depth | static_cast< attributes::named_scope::value_type::size_type >(0)],
+ dir
+ )
+ }};
+ return actor_type(act);
+}
+
+} // namespace aux
+
+/*!
+ * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting
+ * expression (stream output or \c format placeholder filler).
+ *
+ * \param name Attribute name
+ * \param element_format Format string for a single named scope
+ */
+template< typename CharT >
+BOOST_FORCEINLINE format_named_scope_actor< fallback_to_none, CharT > format_named_scope(attribute_name const& name, const CharT* element_format)
+{
+ typedef format_named_scope_actor< fallback_to_none, CharT > actor_type;
+ typedef typename actor_type::terminal_type terminal_type;
+ typename actor_type::base_type act = {{ terminal_type(name, fallback_to_none(), element_format) }};
+ return actor_type(act);
+}
+
+/*!
+ * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting
+ * expression (stream output or \c format placeholder filler).
+ *
+ * \param name Attribute name
+ * \param element_format Format string for a single named scope
+ */
+template< typename CharT >
+BOOST_FORCEINLINE format_named_scope_actor< fallback_to_none, CharT > format_named_scope(attribute_name const& name, std::basic_string< CharT > const& element_format)
+{
+ typedef format_named_scope_actor< fallback_to_none, CharT > actor_type;
+ typedef typename actor_type::terminal_type terminal_type;
+ typename actor_type::base_type act = {{ terminal_type(name, fallback_to_none(), element_format) }};
+ return actor_type(act);
+}
+
+/*!
+ * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting
+ * expression (stream output or \c format placeholder filler).
+ *
+ * \param keyword Attribute keyword
+ * \param element_format Format string for a single named scope
+ */
+template< typename DescriptorT, template< typename > class ActorT, typename CharT >
+BOOST_FORCEINLINE format_named_scope_actor< fallback_to_none, CharT, ActorT >
+format_named_scope(attribute_keyword< DescriptorT, ActorT > const& keyword, const CharT* element_format)
+{
+ BOOST_STATIC_ASSERT_MSG((is_same< typename DescriptorT::value_type, attributes::named_scope::value_type >::value),\
+ "Boost.Log: Named scope formatter only accepts attribute values of type attributes::named_scope::value_type.");
+
+ typedef format_named_scope_actor< fallback_to_none, CharT, ActorT > actor_type;
+ typedef typename actor_type::terminal_type terminal_type;
+ typename actor_type::base_type act = {{ terminal_type(keyword.get_name(), fallback_to_none(), element_format) }};
+ return actor_type(act);
+}
+
+/*!
+ * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting
+ * expression (stream output or \c format placeholder filler).
+ *
+ * \param keyword Attribute keyword
+ * \param element_format Format string for a single named scope
+ */
+template< typename DescriptorT, template< typename > class ActorT, typename CharT >
+BOOST_FORCEINLINE format_named_scope_actor< fallback_to_none, CharT, ActorT >
+format_named_scope(attribute_keyword< DescriptorT, ActorT > const& keyword, std::basic_string< CharT > const& element_format)
+{
+ BOOST_STATIC_ASSERT_MSG((is_same< typename DescriptorT::value_type, attributes::named_scope::value_type >::value),\
+ "Boost.Log: Named scope formatter only accepts attribute values of type attributes::named_scope::value_type.");
+
+ typedef format_named_scope_actor< fallback_to_none, CharT, ActorT > actor_type;
+ typedef typename actor_type::terminal_type terminal_type;
+ typename actor_type::base_type act = {{ terminal_type(keyword.get_name(), fallback_to_none(), element_format) }};
+ return actor_type(act);
+}
+
+/*!
+ * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting
+ * expression (stream output or \c format placeholder filler).
+ *
+ * \param placeholder Attribute placeholder
+ * \param element_format Format string for a single named scope
+ */
+template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename CharT >
+BOOST_FORCEINLINE format_named_scope_actor< FallbackPolicyT, CharT, ActorT >
+format_named_scope(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& placeholder, const CharT* element_format)
+{
+ BOOST_STATIC_ASSERT_MSG((is_same< T, attributes::named_scope::value_type >::value),\
+ "Boost.Log: Named scope formatter only accepts attribute values of type attributes::named_scope::value_type.");
+
+ typedef format_named_scope_actor< FallbackPolicyT, CharT, ActorT > actor_type;
+ typedef typename actor_type::terminal_type terminal_type;
+ typename actor_type::base_type act = {{ terminal_type(placeholder.get_name(), placeholder.get_fallback_policy(), element_format) }};
+ return actor_type(act);
+}
+
+/*!
+ * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting
+ * expression (stream output or \c format placeholder filler).
+ *
+ * \param placeholder Attribute placeholder
+ * \param element_format Format string for a single named scope
+ */
+template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename CharT >
+BOOST_FORCEINLINE format_named_scope_actor< FallbackPolicyT, CharT, ActorT >
+format_named_scope(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& placeholder, std::basic_string< CharT > const& element_format)
+{
+ BOOST_STATIC_ASSERT_MSG((is_same< T, attributes::named_scope::value_type >::value),\
+ "Boost.Log: Named scope formatter only accepts attribute values of type attributes::named_scope::value_type.");
+
+ typedef format_named_scope_actor< FallbackPolicyT, CharT, ActorT > actor_type;
+ typedef typename actor_type::terminal_type terminal_type;
+ typename actor_type::base_type act = {{ terminal_type(placeholder.get_name(), placeholder.get_fallback_policy(), element_format) }};
+ return actor_type(act);
+}
+
+#if !defined(BOOST_LOG_DOXYGEN_PASS)
+
+# define BOOST_PP_FILENAME_1 <boost/log/detail/named_scope_fmt_pp.hpp>
+# define BOOST_PP_ITERATION_LIMITS (1, 6)
+# include BOOST_PP_ITERATE()
+
+#else // BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * Formatter generator. Construct the named scope formatter with the specified formatting parameters.
+ *
+ * \param name Attribute name
+ * \param args An set of named parameters. Supported parameters:
+ * \li \c format - A format string for named scopes. The string can contain "%n", "%f" and "%l" placeholders for the scope name, file and line number, respectively. This parameter is mandatory.
+ * \li \c delimiter - A string that is used to delimit the formatted scope names. Default: "->" or "<-", depending on the iteration direction.
+ * \li \c incomplete_marker - A string that is used to indicate that the list was printed incomplete because of depth limitation. Default: "...".
+ * \li \c empty_marker - A string that is output in case if the scope list is empty. Default: "", i.e. nothing is output.
+ * \li \c iteration - Iteration direction, see \c scope_iteration_direction enumeration. Default: forward.
+ * \li \c depth - Iteration depth. Default: unlimited.
+ */
+template< typename... ArgsT >
+unspecified format_named_scope(attribute_name const& name, ArgsT... const& args);
+
+/*! \overload */
+template< typename DescriptorT, template< typename > class ActorT, typename... ArgsT >
+unspecified format_named_scope(attribute_keyword< DescriptorT, ActorT > const& keyword, ArgsT... const& args);
+
+/*! \overload */
+template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename... ArgsT >
+unspecified format_named_scope(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& placeholder, ArgsT... const& args);
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+namespace phoenix {
+
+namespace result_of {
+
+template< typename FallbackPolicyT, typename CharT >
+struct is_nullary< custom_terminal< boost::log::expressions::format_named_scope_terminal< FallbackPolicyT, CharT > > > :
+ public mpl::false_
+{
+};
+
+} // namespace result_of
+
+} // namespace phoenix
+
+#endif
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_NAMED_SCOPE_HPP_INCLUDED_
diff --git a/boost/log/expressions/formatters/stream.hpp b/boost/log/expressions/formatters/stream.hpp
new file mode 100644
index 0000000000..cd5f1d36c3
--- /dev/null
+++ b/boost/log/expressions/formatters/stream.hpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file stream.hpp
+ * \author Andrey Semashev
+ * \date 24.07.2012
+ *
+ * The header contains implementation of a stream placeholder in template expressions.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_STREAM_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_FORMATTERS_STREAM_HPP_INCLUDED_
+
+#include <boost/phoenix/core/argument.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+/*!
+ * Stream placeholder type in formatter template expressions.
+ */
+typedef phoenix::expression::argument< 2 >::type stream_type;
+
+/*!
+ * Stream placeholder in formatter template expressions.
+ */
+const stream_type stream = {};
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+#if defined(BOOST_LOG_EXPRESSIONS_ATTR_HPP_INCLUDED_)
+#include <boost/log/detail/attr_output_impl.hpp>
+#endif
+
+#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_STREAM_HPP_INCLUDED_
diff --git a/boost/log/expressions/formatters/wrap_formatter.hpp b/boost/log/expressions/formatters/wrap_formatter.hpp
new file mode 100644
index 0000000000..7d8a22c4fc
--- /dev/null
+++ b/boost/log/expressions/formatters/wrap_formatter.hpp
@@ -0,0 +1,338 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file formatters/wrap_formatter.hpp
+ * \author Andrey Semashev
+ * \date 24.11.2012
+ *
+ * The header contains a formatter function wrapper that enables third-party functions to participate in formatting expressions.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_WRAP_FORMATTER_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_FORMATTERS_WRAP_FORMATTER_HPP_INCLUDED_
+
+#include <string>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/mpl/has_xxx.hpp>
+#include <boost/phoenix/core/actor.hpp>
+#include <boost/phoenix/core/terminal_fwd.hpp>
+#include <boost/phoenix/core/is_nullary.hpp>
+#include <boost/phoenix/core/environment.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/fusion/sequence/intrinsic/at_c.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/custom_terminal_spec.hpp>
+#include <boost/log/detail/function_traits.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+namespace aux {
+
+//! Wrapped formatter stream output terminal
+template< typename LeftT, typename FunT >
+class wrapped_formatter_output_terminal
+{
+private:
+ //! Self type
+ typedef wrapped_formatter_output_terminal< LeftT, FunT > this_type;
+
+public:
+ //! Internal typedef for type categorization
+ typedef void _is_boost_log_terminal;
+
+ //! Wrapped function type
+ typedef FunT function_type;
+
+ //! Result type definition
+ template< typename >
+ struct result;
+
+ template< typename ThisT, typename ContextT >
+ struct result< ThisT(ContextT) >
+ {
+ typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type;
+ typedef typename phoenix::evaluator::impl<
+ typename LeftT::proto_base_expr&,
+ context_type,
+ phoenix::unused
+ >::result_type type;
+ };
+
+private:
+ //! Left argument actor
+ LeftT m_left;
+ //! Wrapped function
+ function_type m_fun;
+
+public:
+ //! Initializing constructor
+ wrapped_formatter_output_terminal(LeftT const& left, function_type const& fun) : m_left(left), m_fun(fun)
+ {
+ }
+ //! Copy constructor
+ wrapped_formatter_output_terminal(wrapped_formatter_output_terminal const& that) : m_left(that.m_left), m_fun(that.m_fun)
+ {
+ }
+
+ //! Invokation operator
+ template< typename ContextT >
+ typename result< this_type(ContextT const&) >::type operator() (ContextT const& ctx)
+ {
+ typedef typename result< this_type(ContextT const&) >::type result_type;
+ result_type strm = phoenix::eval(m_left, ctx);
+ m_fun(fusion::at_c< 0 >(phoenix::env(ctx).args()), strm);
+ return strm;
+ }
+
+ //! Invokation operator
+ template< typename ContextT >
+ typename result< const this_type(ContextT const&) >::type operator() (ContextT const& ctx) const
+ {
+ typedef typename result< const this_type(ContextT const&) >::type result_type;
+ result_type strm = phoenix::eval(m_left, ctx);
+ m_fun(fusion::at_c< 0 >(phoenix::env(ctx).args()), strm);
+ return strm;
+ }
+
+ BOOST_DELETED_FUNCTION(wrapped_formatter_output_terminal())
+};
+
+BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_char_type, char_type, false)
+
+template<
+ typename FunT,
+ bool HasCharTypeV = has_char_type< FunT >::value,
+ bool HasSecondArgumentV = boost::log::aux::has_second_argument_type< FunT >::value,
+ bool HasArg2V = boost::log::aux::has_arg2_type< FunT >::value
+>
+struct default_char_type
+{
+ // Use this char type if all detection fails
+ typedef char type;
+};
+
+template< typename FunT, bool HasSecondArgumentV, bool HasArg2V >
+struct default_char_type< FunT, true, HasSecondArgumentV, HasArg2V >
+{
+ typedef typename FunT::char_type type;
+};
+
+template< typename FunT, bool HasArg2V >
+struct default_char_type< FunT, false, true, HasArg2V >
+{
+ typedef typename remove_cv< typename remove_reference< typename FunT::second_argument_type >::type >::type argument_type;
+ typedef typename argument_type::char_type type;
+};
+
+template< typename FunT >
+struct default_char_type< FunT, false, false, true >
+{
+ typedef typename remove_cv< typename remove_reference< typename FunT::arg2_type >::type >::type argument_type;
+ typedef typename argument_type::char_type type;
+};
+
+} // namespace aux
+
+/*!
+ * Formatter function wrapper terminal.
+ */
+template< typename FunT, typename CharT >
+class wrapped_formatter_terminal
+{
+public:
+ //! Internal typedef for type categorization
+ typedef void _is_boost_log_terminal;
+
+ //! Character type
+ typedef CharT char_type;
+ //! String type
+ typedef std::basic_string< char_type > string_type;
+ //! Formatting stream type
+ typedef basic_formatting_ostream< char_type > stream_type;
+ //! Wrapped function type
+ typedef FunT function_type;
+
+ //! Formatter result type
+ typedef string_type result_type;
+
+private:
+ //! Wrapped function
+ function_type m_fun;
+
+public:
+ //! Initializing construction
+ explicit wrapped_formatter_terminal(function_type const& fun) : m_fun(fun)
+ {
+ }
+ //! Copy constructor
+ wrapped_formatter_terminal(wrapped_formatter_terminal const& that) : m_fun(that.m_fun)
+ {
+ }
+
+ //! Returns the wrapped function
+ function_type const& get_function() const
+ {
+ return m_fun;
+ }
+
+ //! Invokation operator
+ template< typename ContextT >
+ result_type operator() (ContextT const& ctx)
+ {
+ string_type str;
+ stream_type strm(str);
+ m_fun(fusion::at_c< 0 >(phoenix::env(ctx).args()), strm);
+ strm.flush();
+ return boost::move(str);
+ }
+
+ //! Invokation operator
+ template< typename ContextT >
+ result_type operator() (ContextT const& ctx) const
+ {
+ string_type str;
+ stream_type strm(str);
+ m_fun(fusion::at_c< 0 >(phoenix::env(ctx).args()), strm);
+ strm.flush();
+ return boost::move(str);
+ }
+};
+
+/*!
+ * Wrapped formatter function actor.
+ */
+template< typename FunT, typename CharT, template< typename > class ActorT = phoenix::actor >
+class wrapped_formatter_actor :
+ public ActorT< wrapped_formatter_terminal< FunT, CharT > >
+{
+public:
+ //! Character type
+ typedef CharT char_type;
+ //! Wrapped function type
+ typedef FunT function_type;
+ //! Base terminal type
+ typedef wrapped_formatter_terminal< function_type, char_type > terminal_type;
+
+ //! Base actor type
+ typedef ActorT< terminal_type > base_type;
+
+public:
+ //! Initializing constructor
+ explicit wrapped_formatter_actor(base_type const& act) : base_type(act)
+ {
+ }
+
+ /*!
+ * \returns The wrapped function
+ */
+ function_type const& get_function() const
+ {
+ return this->proto_expr_.child0.get_function();
+ }
+};
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\
+ template< typename LeftExprT, typename FunT, typename CharT >\
+ BOOST_FORCEINLINE phoenix::actor< aux::wrapped_formatter_output_terminal< phoenix::actor< LeftExprT >, FunT > >\
+ operator<< (phoenix::actor< LeftExprT > left_ref left, wrapped_formatter_actor< FunT, CharT > right_ref right)\
+ {\
+ typedef aux::wrapped_formatter_output_terminal< phoenix::actor< LeftExprT >, FunT > terminal_type;\
+ phoenix::actor< terminal_type > actor = {{ terminal_type(left, right.get_function()) }};\
+ return actor;\
+ }
+
+#include <boost/log/detail/generate_overloads.hpp>
+
+#undef BOOST_LOG_AUX_OVERLOAD
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * The function wraps a function object in order it to be able to participate in formatting expressions. The wrapped
+ * function object must be compatible with the following signature:
+ *
+ * <pre>
+ * void (record_view const&, basic_formatting_ostream< CharT >&)
+ * </pre>
+ *
+ * where \c CharT is the character type of the formatting expression.
+ */
+template< typename FunT >
+BOOST_FORCEINLINE wrapped_formatter_actor< FunT, typename aux::default_char_type< FunT >::type > wrap_formatter(FunT const& fun)
+{
+ typedef wrapped_formatter_actor< FunT, typename aux::default_char_type< FunT >::type > actor_type;
+ typedef typename actor_type::terminal_type terminal_type;
+ typename actor_type::base_type act = {{ terminal_type(fun) }};
+ return actor_type(act);
+}
+
+/*!
+ * The function wraps a function object in order it to be able to participate in formatting expressions. The wrapped
+ * function object must be compatible with the following signature:
+ *
+ * <pre>
+ * void (record_view const&, basic_formatting_ostream< CharT >&)
+ * </pre>
+ *
+ * where \c CharT is the character type of the formatting expression.
+ */
+template< typename CharT, typename FunT >
+BOOST_FORCEINLINE wrapped_formatter_actor< FunT, CharT > wrap_formatter(FunT const& fun)
+{
+ typedef wrapped_formatter_actor< FunT, CharT > actor_type;
+ typedef typename actor_type::terminal_type terminal_type;
+ typename actor_type::base_type act = {{ terminal_type(fun) }};
+ return actor_type(act);
+}
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+namespace phoenix {
+
+namespace result_of {
+
+template< typename LeftT, typename FunT >
+struct is_nullary< custom_terminal< boost::log::expressions::aux::wrapped_formatter_output_terminal< LeftT, FunT > > > :
+ public mpl::false_
+{
+};
+
+template< typename FunT, typename CharT >
+struct is_nullary< custom_terminal< boost::log::expressions::wrapped_formatter_terminal< FunT, CharT > > > :
+ public mpl::false_
+{
+};
+
+} // namespace result_of
+
+} // namespace phoenix
+
+#endif
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_WRAP_FORMATTER_HPP_INCLUDED_
diff --git a/boost/log/expressions/formatters/xml_decorator.hpp b/boost/log/expressions/formatters/xml_decorator.hpp
new file mode 100644
index 0000000000..021ed60bd4
--- /dev/null
+++ b/boost/log/expressions/formatters/xml_decorator.hpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file formatters/xml_decorator.hpp
+ * \author Andrey Semashev
+ * \date 18.11.2012
+ *
+ * The header contains implementation of a XML-style character decorator.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_XML_DECORATOR_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_FORMATTERS_XML_DECORATOR_HPP_INCLUDED_
+
+#include <boost/range/iterator_range_core.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/expressions/formatters/char_decorator.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+namespace aux {
+
+template< typename >
+struct xml_decorator_traits;
+
+#ifdef BOOST_LOG_USE_CHAR
+template< >
+struct xml_decorator_traits< char >
+{
+ static boost::iterator_range< const char* const* > get_patterns()
+ {
+ static const char* const patterns[] =
+ {
+ "&", "<", ">", "\"", "'"
+ };
+ return boost::make_iterator_range(patterns);
+ }
+ static boost::iterator_range< const char* const* > get_replacements()
+ {
+ static const char* const replacements[] =
+ {
+ "&amp;", "&lt;", "&gt;", "&quot;", "&apos;"
+ };
+ return boost::make_iterator_range(replacements);
+ }
+};
+#endif // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+template< >
+struct xml_decorator_traits< wchar_t >
+{
+ static boost::iterator_range< const wchar_t* const* > get_patterns()
+ {
+ static const wchar_t* const patterns[] =
+ {
+ L"&", L"<", L">", L"\"", L"'"
+ };
+ return boost::make_iterator_range(patterns);
+ }
+ static boost::iterator_range< const wchar_t* const* > get_replacements()
+ {
+ static const wchar_t* const replacements[] =
+ {
+ L"&amp;", L"&lt;", L"&gt;", L"&quot;", L"&apos;"
+ };
+ return boost::make_iterator_range(replacements);
+ }
+};
+#endif // BOOST_LOG_USE_WCHAR_T
+
+template< typename CharT >
+struct xml_decorator_gen
+{
+ typedef CharT char_type;
+
+ template< typename SubactorT >
+ BOOST_FORCEINLINE char_decorator_actor< SubactorT, pattern_replacer< char_type > > operator[] (SubactorT const& subactor) const
+ {
+ typedef xml_decorator_traits< char_type > traits_type;
+ typedef pattern_replacer< char_type > replacer_type;
+ typedef char_decorator_actor< SubactorT, replacer_type > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(subactor, replacer_type(traits_type::get_patterns(), traits_type::get_replacements())) }};
+ return result_type(act);
+ }
+};
+
+} // namespace aux
+
+/*!
+ * XML-style decorator generator object. The decorator replaces characters that have special meaning
+ * in XML documents with the corresponding decorated counterparts. The generator provides
+ * <tt>operator[]</tt> that can be used to construct the actual decorator. For example:
+ *
+ * <code>
+ * xml_decor[ attr< std::string >("MyAttr") ]
+ * </code>
+ *
+ * For wide-character formatting there is the similar \c wxml_decor decorator generator object.
+ */
+#ifdef BOOST_LOG_USE_CHAR
+const aux::xml_decorator_gen< char > xml_decor = {};
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+const aux::xml_decorator_gen< wchar_t > wxml_decor = {};
+#endif
+
+/*!
+ * The function creates an XML-style decorator generator for arbitrary character type.
+ */
+template< typename CharT >
+BOOST_FORCEINLINE aux::xml_decorator_gen< CharT > make_xml_decor()
+{
+ return aux::xml_decorator_gen< CharT >();
+}
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_XML_DECORATOR_HPP_INCLUDED_
diff --git a/boost/log/expressions/is_keyword_descriptor.hpp b/boost/log/expressions/is_keyword_descriptor.hpp
new file mode 100644
index 0000000000..9899e228e7
--- /dev/null
+++ b/boost/log/expressions/is_keyword_descriptor.hpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file is_keyword_descriptor.hpp
+ * \author Andrey Semashev
+ * \date 14.07.2012
+ *
+ * The header contains attribute keyword descriptor detection trait.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_IS_KEYWORD_DESCRIPTOR_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_IS_KEYWORD_DESCRIPTOR_HPP_INCLUDED_
+
+#include <boost/mpl/bool.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+/*!
+ * Base class for keyword descriptors. All keyword descriptors must derive from this class to support the \c is_keyword_descriptor trait.
+ */
+struct keyword_descriptor
+{
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ typedef void _is_boost_log_keyword_descriptor;
+#endif // BOOST_LOG_DOXYGEN_PASS
+};
+
+/*!
+ * The metafunction detects if the type \c T is a keyword descriptor
+ */
+template< typename T, typename VoidT = void >
+struct is_keyword_descriptor :
+ public mpl::false_
+{
+};
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+template< typename T >
+struct is_keyword_descriptor< T, typename T::_is_boost_log_keyword_descriptor > :
+ public mpl::true_
+{
+};
+#endif
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_IS_KEYWORD_DESCRIPTOR_HPP_INCLUDED_
diff --git a/boost/log/expressions/keyword.hpp b/boost/log/expressions/keyword.hpp
new file mode 100644
index 0000000000..434247be91
--- /dev/null
+++ b/boost/log/expressions/keyword.hpp
@@ -0,0 +1,258 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keyword.hpp
+ * \author Andrey Semashev
+ * \date 29.01.2012
+ *
+ * The header contains attribute keyword declaration.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_KEYWORD_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_KEYWORD_HPP_INCLUDED_
+
+#include <boost/ref.hpp>
+#include <boost/proto/extends.hpp>
+#include <boost/proto/make_expr.hpp>
+#include <boost/phoenix/core/actor.hpp>
+#include <boost/phoenix/core/domain.hpp>
+#include <boost/phoenix/core/environment.hpp>
+#include <boost/fusion/sequence/intrinsic/at.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/custom_terminal_spec.hpp>
+#include <boost/log/expressions/keyword_fwd.hpp>
+#include <boost/log/expressions/is_keyword_descriptor.hpp>
+#include <boost/log/expressions/attr.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/value_extraction.hpp>
+#include <boost/log/attributes/fallback_policy.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+/*!
+ * This class implements an expression template keyword. It is used to start template expressions involving attribute values.
+ */
+template< typename DescriptorT, template< typename > class ActorT >
+struct attribute_keyword
+{
+ //! Self type
+ typedef attribute_keyword this_type;
+ //! Attribute descriptor type
+ typedef DescriptorT descriptor_type;
+
+ BOOST_PROTO_BASIC_EXTENDS(typename proto::terminal< descriptor_type >::type, this_type, phoenix::phoenix_domain)
+
+ //! Attribute value type
+ typedef typename descriptor_type::value_type value_type;
+
+ //! Returns attribute name
+ static attribute_name get_name() { return descriptor_type::get_name(); }
+
+ //! Expression with cached attribute name
+ typedef attribute_actor<
+ value_type,
+ fallback_to_none,
+ descriptor_type,
+ ActorT
+ > or_none_result_type;
+
+ //! Generates an expression that extracts the attribute value or a default value
+ static or_none_result_type or_none()
+ {
+ typedef typename or_none_result_type::terminal_type result_terminal;
+ typename or_none_result_type::base_type act = {{ result_terminal(get_name()) }};
+ return or_none_result_type(act);
+ }
+
+ //! Expression with cached attribute name
+ typedef attribute_actor<
+ value_type,
+ fallback_to_throw,
+ descriptor_type,
+ ActorT
+ > or_throw_result_type;
+
+ //! Generates an expression that extracts the attribute value or throws an exception
+ static or_throw_result_type or_throw()
+ {
+ typedef typename or_throw_result_type::terminal_type result_terminal;
+ typename or_throw_result_type::base_type act = {{ result_terminal(get_name()) }};
+ return or_throw_result_type(act);
+ }
+
+ //! Generates an expression that extracts the attribute value or a default value
+ template< typename DefaultT >
+ static attribute_actor<
+ value_type,
+ fallback_to_default< DefaultT >,
+ descriptor_type,
+ ActorT
+ > or_default(DefaultT const& def_val)
+ {
+ typedef attribute_actor<
+ value_type,
+ fallback_to_default< DefaultT >,
+ descriptor_type,
+ ActorT
+ > or_default_result_type;
+ typedef typename or_default_result_type::terminal_type result_terminal;
+ typename or_default_result_type::base_type act = {{ result_terminal(get_name(), def_val) }};
+ return or_default_result_type(act);
+ }
+};
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+namespace proto {
+
+namespace detail {
+
+// This hack is needed in order to cache attribute name into the expression terminal when the template
+// expression is constructed. The standard way through a custom domain doesn't work because phoenix::actor
+// is bound to phoenix_domain.
+template< typename DescriptorT, template< typename > class ActorT, typename DomainT >
+struct protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT >
+{
+ typedef boost::log::expressions::attribute_keyword< DescriptorT, ActorT > keyword_type;
+ typedef typename keyword_type::or_none_result_type result_type;
+
+ result_type operator() (keyword_type const& keyword) const
+ {
+ return keyword.or_none();
+ }
+};
+
+template< typename DescriptorT, template< typename > class ActorT, typename DomainT >
+struct protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >&, DomainT > :
+ public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT >
+{
+};
+
+template< typename DescriptorT, template< typename > class ActorT, typename DomainT >
+struct protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT > const&, DomainT > :
+ public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT >
+{
+};
+
+template< typename DescriptorT, template< typename > class ActorT, typename DomainT >
+struct protoify< boost::reference_wrapper< boost::log::expressions::attribute_keyword< DescriptorT, ActorT > >, DomainT > :
+ public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT >
+{
+};
+
+template< typename DescriptorT, template< typename > class ActorT, typename DomainT >
+struct protoify< boost::reference_wrapper< boost::log::expressions::attribute_keyword< DescriptorT, ActorT > > const, DomainT > :
+ public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT >
+{
+};
+
+template< typename DescriptorT, template< typename > class ActorT, typename DomainT >
+struct protoify< boost::reference_wrapper< const boost::log::expressions::attribute_keyword< DescriptorT, ActorT > >, DomainT > :
+ public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT >
+{
+};
+
+template< typename DescriptorT, template< typename > class ActorT, typename DomainT >
+struct protoify< boost::reference_wrapper< const boost::log::expressions::attribute_keyword< DescriptorT, ActorT > > const, DomainT > :
+ public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT >
+{
+};
+
+} // namespace detail
+
+} // namespace proto
+
+#endif // !defined(BOOST_LOG_DOXYGEN_PASS)
+
+} // namespace boost
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#define BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE_IMPL(keyword_, name_, value_type_, tag_ns_)\
+ namespace tag_ns_\
+ {\
+ struct keyword_ :\
+ public ::boost::log::expressions::keyword_descriptor\
+ {\
+ typedef value_type_ value_type;\
+ static ::boost::log::attribute_name get_name() { return ::boost::log::attribute_name(name_); }\
+ };\
+ }\
+ typedef ::boost::log::expressions::attribute_keyword< tag_ns_::keyword_ > BOOST_PP_CAT(keyword_, _type);
+
+#define BOOST_LOG_ATTRIBUTE_KEYWORD_IMPL(keyword_, name_, value_type_, tag_ns_)\
+ BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE_IMPL(keyword_, name_, value_type_, tag_ns_)\
+ const BOOST_PP_CAT(keyword_, _type) keyword_ = {};
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * \brief The macro declares an attribute keyword type
+ *
+ * The macro should be used at a namespace scope. It expands into an attribute keyword type definition, including the
+ * \c tag namespace and the keyword tag type within which has the following layout:
+ *
+ * \code
+ * namespace tag
+ * {
+ * struct keyword_ :
+ * public boost::log::expressions::keyword_descriptor
+ * {
+ * typedef value_type_ value_type;
+ * static boost::log::attribute_name get_name();
+ * };
+ * }
+ *
+ * typedef boost::log::expressions::attribute_keyword< tag::keyword_ > keyword_type;
+ * \endcode
+ *
+ * The \c get_name method returns the attribute name.
+ *
+ * \note This macro only defines the type of the keyword. To also define the keyword object, use
+ * the \c BOOST_LOG_ATTRIBUTE_KEYWORD macro instead.
+ *
+ * \param keyword_ Keyword name
+ * \param name_ Attribute name string
+ * \param value_type_ Attribute value type
+ */
+#define BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE(keyword_, name_, value_type_)\
+ BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE_IMPL(keyword_, name_, value_type_, tag)
+
+/*!
+ * \brief The macro declares an attribute keyword
+ *
+ * The macro provides definitions similar to \c BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE and additionally
+ * defines the keyword object.
+ *
+ * \param keyword_ Keyword name
+ * \param name_ Attribute name string
+ * \param value_type_ Attribute value type
+ */
+#define BOOST_LOG_ATTRIBUTE_KEYWORD(keyword_, name_, value_type_)\
+ BOOST_LOG_ATTRIBUTE_KEYWORD_IMPL(keyword_, name_, value_type_, tag)
+
+#include <boost/log/detail/footer.hpp>
+
+#if defined(BOOST_LOG_TRIVIAL_HPP_INCLUDED_)
+#include <boost/log/detail/trivial_keyword.hpp>
+#endif
+
+#endif // BOOST_LOG_EXPRESSIONS_KEYWORD_HPP_INCLUDED_
diff --git a/boost/log/expressions/keyword_fwd.hpp b/boost/log/expressions/keyword_fwd.hpp
new file mode 100644
index 0000000000..a2671e9f61
--- /dev/null
+++ b/boost/log/expressions/keyword_fwd.hpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keyword_fwd.hpp
+ * \author Andrey Semashev
+ * \date 29.01.2012
+ *
+ * The header contains attribute keyword forward declaration.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_KEYWORD_FWD_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_KEYWORD_FWD_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+namespace phoenix {
+
+template< typename >
+struct actor;
+
+} // namespace phoenix
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+/*!
+ * \brief This class implements an expression template keyword
+ */
+template< typename DescriptorT, template< typename > class ActorT = phoenix::actor >
+struct attribute_keyword;
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_EXPRESSIONS_KEYWORD_FWD_HPP_INCLUDED_
diff --git a/boost/log/expressions/message.hpp b/boost/log/expressions/message.hpp
new file mode 100644
index 0000000000..79d826a992
--- /dev/null
+++ b/boost/log/expressions/message.hpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file message.hpp
+ * \author Andrey Semashev
+ * \date 13.07.2012
+ *
+ * The header contains log message keyword declaration.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_MESSAGE_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_MESSAGE_HPP_INCLUDED_
+
+#include <string>
+#include <boost/mpl/vector.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/default_attribute_names.hpp>
+#include <boost/log/expressions/keyword.hpp>
+#include <boost/log/expressions/is_keyword_descriptor.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+namespace tag {
+
+/*!
+ * Generic log message attribute descriptor.
+ */
+struct message :
+ public keyword_descriptor
+{
+ // The attribute value type here is not essential since message attributes are not intended to be created via the keyword
+ typedef void attribute_type;
+
+#if defined(BOOST_LOG_USE_CHAR) && defined(BOOST_LOG_USE_WCHAR_T)
+ typedef mpl::vector2< std::string, std::wstring > value_type;
+#elif defined(BOOST_LOG_USE_CHAR)
+ typedef std::string value_type;
+#elif defined(BOOST_LOG_USE_WCHAR_T)
+ typedef std::wstring value_type;
+#endif
+
+ static attribute_name get_name() { return boost::log::aux::default_attribute_names::message(); }
+};
+
+#if defined(BOOST_LOG_USE_CHAR)
+/*!
+ * Narrow character log message attribute descriptor.
+ */
+struct smessage :
+ public keyword_descriptor
+{
+ // The attribute value type here is not essential since message attributes are not intended to be created via the keyword
+ typedef void attribute_type;
+ typedef std::string value_type;
+
+ static attribute_name get_name() { return boost::log::aux::default_attribute_names::message(); }
+};
+#endif
+
+#if defined(BOOST_LOG_USE_WCHAR_T)
+/*!
+ * Wide character log message attribute descriptor.
+ */
+struct wmessage :
+ public keyword_descriptor
+{
+ // The attribute value type here is not essential since message attributes are not intended to be created via the keyword
+ typedef void attribute_type;
+ typedef std::wstring value_type;
+
+ static attribute_name get_name() { return boost::log::aux::default_attribute_names::message(); }
+};
+#endif
+
+} // namespace tag
+
+/*!
+ * Generic message keyword type.
+ */
+typedef attribute_keyword< tag::message > message_type;
+/*!
+ * Generic message keyword.
+ */
+const message_type message = {};
+
+#if defined(BOOST_LOG_USE_CHAR)
+/*!
+ * Narrow message keyword type.
+ */
+typedef attribute_keyword< tag::smessage > smessage_type;
+/*!
+ * Narrow message keyword.
+ */
+const smessage_type smessage = {};
+#endif
+
+#if defined(BOOST_LOG_USE_WCHAR_T)
+/*!
+ * Wide message keyword type.
+ */
+typedef attribute_keyword< tag::wmessage > wmessage_type;
+/*!
+ * Wide message keyword.
+ */
+const wmessage_type wmessage = {};
+#endif
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_MESSAGE_HPP_INCLUDED_
diff --git a/boost/log/expressions/predicates.hpp b/boost/log/expressions/predicates.hpp
new file mode 100644
index 0000000000..297b51b9d2
--- /dev/null
+++ b/boost/log/expressions/predicates.hpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file predicates.hpp
+ * \author Andrey Semashev
+ * \date 29.01.2012
+ *
+ * The header includes all template expression predicates.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_PREDICATES_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_PREDICATES_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#include <boost/log/expressions/predicates/has_attr.hpp>
+#include <boost/log/expressions/predicates/begins_with.hpp>
+#include <boost/log/expressions/predicates/ends_with.hpp>
+#include <boost/log/expressions/predicates/contains.hpp>
+#include <boost/log/expressions/predicates/matches.hpp>
+#include <boost/log/expressions/predicates/is_in_range.hpp>
+
+#include <boost/log/expressions/predicates/is_debugger_present.hpp>
+#include <boost/log/expressions/predicates/channel_severity_filter.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#endif // BOOST_LOG_EXPRESSIONS_PREDICATES_HPP_INCLUDED_
diff --git a/boost/log/expressions/predicates/begins_with.hpp b/boost/log/expressions/predicates/begins_with.hpp
new file mode 100644
index 0000000000..e837a4ac7e
--- /dev/null
+++ b/boost/log/expressions/predicates/begins_with.hpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file begins_with.hpp
+ * \author Andrey Semashev
+ * \date 02.09.2012
+ *
+ * The header contains implementation of a \c begins_with predicate in template expressions.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_PREDICATES_BEGINS_WITH_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_PREDICATES_BEGINS_WITH_HPP_INCLUDED_
+
+#include <boost/phoenix/core/actor.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/embedded_string_type.hpp>
+#include <boost/log/detail/unary_function_terminal.hpp>
+#include <boost/log/detail/attribute_predicate.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/fallback_policy.hpp>
+#include <boost/log/expressions/attr_fwd.hpp>
+#include <boost/log/expressions/keyword_fwd.hpp>
+#include <boost/log/utility/functional/begins_with.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+/*!
+ * The predicate checks if the attribute value begins with a substring. The attribute value is assumed to be of a string type.
+ */
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template< typename T, typename SubstringT, typename FallbackPolicyT = fallback_to_none >
+using attribute_begins_with = aux::attribute_predicate< T, SubstringT, begins_with_fun, FallbackPolicyT >;
+
+#else // !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template< typename T, typename SubstringT, typename FallbackPolicyT = fallback_to_none >
+class attribute_begins_with :
+ public aux::attribute_predicate< T, SubstringT, begins_with_fun, FallbackPolicyT >
+{
+ typedef aux::attribute_predicate< T, SubstringT, begins_with_fun, FallbackPolicyT > base_type;
+
+public:
+ /*!
+ * Initializing constructor
+ *
+ * \param name Attribute name
+ * \param substring The expected attribute value beginning
+ */
+ attribute_begins_with(attribute_name const& name, SubstringT const& substring) : base_type(name, substring)
+ {
+ }
+
+ /*!
+ * Initializing constructor
+ *
+ * \param name Attribute name
+ * \param substring The expected attribute value beginning
+ * \param arg Additional parameter for the fallback policy
+ */
+ template< typename U >
+ attribute_begins_with(attribute_name const& name, SubstringT const& substring, U const& arg) : base_type(name, substring, arg)
+ {
+ }
+};
+
+#endif // !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+/*!
+ * The function generates a terminal node in a template expression. The node will check if the attribute value,
+ * which is assumed to be a string, begins with the specified substring.
+ */
+template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename SubstringT >
+BOOST_FORCEINLINE ActorT< aux::unary_function_terminal< attribute_begins_with< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type, FallbackPolicyT > > >
+begins_with(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& attr, SubstringT const& substring)
+{
+ typedef aux::unary_function_terminal< attribute_begins_with< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type, FallbackPolicyT > > terminal_type;
+ ActorT< terminal_type > act = {{ terminal_type(attr.get_name(), substring, attr.get_fallback_policy()) }};
+ return act;
+}
+
+/*!
+ * The function generates a terminal node in a template expression. The node will check if the attribute value,
+ * which is assumed to be a string, begins with the specified substring.
+ */
+template< typename DescriptorT, template< typename > class ActorT, typename SubstringT >
+BOOST_FORCEINLINE ActorT< aux::unary_function_terminal< attribute_begins_with< typename DescriptorT::value_type, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > >
+begins_with(attribute_keyword< DescriptorT, ActorT > const&, SubstringT const& substring)
+{
+ typedef aux::unary_function_terminal< attribute_begins_with< typename DescriptorT::value_type, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > terminal_type;
+ ActorT< terminal_type > act = {{ terminal_type(DescriptorT::get_name(), substring) }};
+ return act;
+}
+
+/*!
+ * The function generates a terminal node in a template expression. The node will check if the attribute value,
+ * which is assumed to be a string, begins with the specified substring.
+ */
+template< typename T, typename SubstringT >
+BOOST_FORCEINLINE phoenix::actor< aux::unary_function_terminal< attribute_begins_with< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > >
+begins_with(attribute_name const& name, SubstringT const& substring)
+{
+ typedef aux::unary_function_terminal< attribute_begins_with< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > terminal_type;
+ phoenix::actor< terminal_type > act = {{ terminal_type(name, substring) }};
+ return act;
+}
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_PREDICATES_BEGINS_WITH_HPP_INCLUDED_
diff --git a/boost/log/expressions/predicates/channel_severity_filter.hpp b/boost/log/expressions/predicates/channel_severity_filter.hpp
new file mode 100644
index 0000000000..f0ddfb564c
--- /dev/null
+++ b/boost/log/expressions/predicates/channel_severity_filter.hpp
@@ -0,0 +1,572 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file channel_severity_filter.hpp
+ * \author Andrey Semashev
+ * \date 25.11.2012
+ *
+ * The header contains implementation of a minimal severity per channel filter.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_PREDICATES_CHANNEL_SEVERITY_FILTER_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_PREDICATES_CHANNEL_SEVERITY_FILTER_HPP_INCLUDED_
+
+#include <map>
+#include <memory>
+#include <utility>
+#include <boost/phoenix/core/actor.hpp>
+#include <boost/phoenix/core/terminal_fwd.hpp>
+#include <boost/phoenix/core/is_nullary.hpp>
+#include <boost/phoenix/core/environment.hpp>
+#include <boost/fusion/sequence/intrinsic/at_c.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/custom_terminal_spec.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/fallback_policy.hpp>
+#include <boost/log/attributes/value_visitation.hpp>
+#include <boost/log/utility/functional/logical.hpp>
+#include <boost/log/expressions/attr_fwd.hpp>
+#include <boost/log/expressions/keyword_fwd.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+template<
+ typename ChannelT,
+ typename SeverityT,
+ typename ChannelFallbackT = fallback_to_none,
+ typename SeverityFallbackT = fallback_to_none,
+ typename ChannelOrderT = less,
+ typename SeverityCompareT = greater_equal,
+ typename AllocatorT = std::allocator< void >
+>
+class channel_severity_filter_terminal
+{
+public:
+ //! Internal typedef for type categorization
+ typedef void _is_boost_log_terminal;
+
+ //! Function result type
+ typedef bool result_type;
+
+ //! Channel attribute value type
+ typedef ChannelT channel_value_type;
+ //! Channel fallback policy
+ typedef ChannelFallbackT channel_fallback_policy;
+ //! Severity level attribute value type
+ typedef SeverityT severity_value_type;
+ //! Severity level fallback policy
+ typedef SeverityFallbackT severity_fallback_policy;
+
+private:
+ //! Channel to severity mapping type
+ typedef std::map<
+ channel_value_type,
+ severity_value_type,
+ ChannelOrderT,
+ typename AllocatorT::BOOST_NESTED_TEMPLATE rebind< std::pair< const channel_value_type, severity_value_type > >::other
+ > mapping_type;
+ //! Attribute value visitor invoker for channel
+ typedef value_visitor_invoker< channel_value_type, channel_fallback_policy > channel_visitor_invoker_type;
+ //! Attribute value visitor invoker for severity level
+ typedef value_visitor_invoker< severity_value_type, severity_fallback_policy > severity_visitor_invoker_type;
+
+ //! Channel visitor
+ template< typename ArgT >
+ struct channel_visitor
+ {
+ typedef void result_type;
+
+ channel_visitor(channel_severity_filter_terminal const& self, ArgT arg, bool& res) : m_self(self), m_arg(arg), m_res(res)
+ {
+ }
+
+ result_type operator() (channel_value_type const& channel) const
+ {
+ m_self.visit_channel(channel, m_arg, m_res);
+ }
+
+ private:
+ channel_severity_filter_terminal const& m_self;
+ ArgT m_arg;
+ bool& m_res;
+ };
+
+ //! Severity level visitor
+ struct severity_visitor
+ {
+ typedef void result_type;
+
+ severity_visitor(channel_severity_filter_terminal const& self, severity_value_type const& severity, bool& res) : m_self(self), m_severity(severity), m_res(res)
+ {
+ }
+
+ result_type operator() (severity_value_type const& severity) const
+ {
+ m_self.visit_severity(severity, m_severity, m_res);
+ }
+
+ private:
+ channel_severity_filter_terminal const& m_self;
+ severity_value_type const& m_severity;
+ bool& m_res;
+ };
+
+private:
+ //! Channel attribute name
+ attribute_name m_channel_name;
+ //! Severity level attribute name
+ attribute_name m_severity_name;
+ //! Channel value visitor invoker
+ channel_visitor_invoker_type m_channel_visitor_invoker;
+ //! Severity level value visitor invoker
+ severity_visitor_invoker_type m_severity_visitor_invoker;
+
+ //! Channel to severity level mapping
+ mapping_type m_mapping;
+ //! Severity checking predicate
+ SeverityCompareT m_severity_compare;
+
+ //! Default result
+ bool m_default;
+
+public:
+ //! Initializing constructor
+ channel_severity_filter_terminal
+ (
+ attribute_name const& channel_name,
+ attribute_name const& severity_name,
+ channel_fallback_policy const& channel_fallback = channel_fallback_policy(),
+ severity_fallback_policy const& severity_fallback = severity_fallback_policy(),
+ ChannelOrderT const& channel_order = ChannelOrderT(),
+ SeverityCompareT const& severity_compare = SeverityCompareT()
+ ) :
+ m_channel_name(channel_name),
+ m_severity_name(severity_name),
+ m_channel_visitor_invoker(channel_fallback),
+ m_severity_visitor_invoker(severity_fallback),
+ m_mapping(channel_order),
+ m_severity_compare(severity_compare),
+ m_default(false)
+ {
+ }
+
+ //! Adds a new element to the mapping
+ void add(channel_value_type const& channel, severity_value_type const& severity)
+ {
+ typedef typename mapping_type::iterator iterator;
+ std::pair< iterator, bool > res = m_mapping.insert(typename mapping_type::value_type(channel, severity));
+ if (!res.second)
+ res.first->second = severity;
+ }
+
+ //! Sets the default result of the predicate
+ void set_default(bool def)
+ {
+ m_default = def;
+ }
+
+ //! Invokation operator
+ template< typename ContextT >
+ result_type operator() (ContextT const& ctx) const
+ {
+ result_type res = m_default;
+
+ typedef typename remove_cv<
+ typename remove_reference< typename phoenix::result_of::env< ContextT >::type >::type
+ >::type env_type;
+ typedef typename env_type::args_type args_type;
+ typedef typename fusion::result_of::at_c< args_type, 0 >::type arg_type;
+ arg_type arg = fusion::at_c< 0 >(phoenix::env(ctx).args());
+
+ m_channel_visitor_invoker(m_channel_name, arg, channel_visitor< arg_type >(*this, arg, res));
+
+ return res;
+ }
+
+private:
+ //! Visits channel name
+ template< typename ArgT >
+ void visit_channel(channel_value_type const& channel, ArgT const& arg, bool& res) const
+ {
+ typename mapping_type::const_iterator it = m_mapping.find(channel);
+ if (it != m_mapping.end())
+ {
+ m_severity_visitor_invoker(m_severity_name, arg, severity_visitor(*this, it->second, res));
+ }
+ }
+
+ //! Visits severity level
+ void visit_severity(severity_value_type const& left, severity_value_type const& right, bool& res) const
+ {
+ res = m_severity_compare(left, right);
+ }
+};
+
+template<
+ typename ChannelT,
+ typename SeverityT,
+ typename ChannelFallbackT = fallback_to_none,
+ typename SeverityFallbackT = fallback_to_none,
+ typename ChannelOrderT = less,
+ typename SeverityCompareT = greater_equal,
+ typename AllocatorT = std::allocator< void >,
+ template< typename > class ActorT = phoenix::actor
+>
+class channel_severity_filter_actor :
+ public ActorT< channel_severity_filter_terminal< ChannelT, SeverityT, ChannelFallbackT, SeverityFallbackT, ChannelOrderT, SeverityCompareT, AllocatorT > >
+{
+private:
+ //! Self type
+ typedef channel_severity_filter_actor this_type;
+
+public:
+ //! Terminal type
+ typedef channel_severity_filter_terminal< ChannelT, SeverityT, ChannelFallbackT, SeverityFallbackT, ChannelOrderT, SeverityCompareT, AllocatorT > terminal_type;
+ //! Base actor type
+ typedef ActorT< terminal_type > base_type;
+
+ //! Channel attribute value type
+ typedef typename terminal_type::channel_value_type channel_value_type;
+ //! Channel fallback policy
+ typedef typename terminal_type::channel_fallback_policy channel_fallback_policy;
+ //! Severity level attribute value type
+ typedef typename terminal_type::severity_value_type severity_value_type;
+ //! Severity level fallback policy
+ typedef typename terminal_type::severity_fallback_policy severity_fallback_policy;
+
+private:
+ //! An auxiliary pseudo-reference to implement insertion through subscript operator
+ class subscript_result
+ {
+ private:
+ channel_severity_filter_actor& m_owner;
+ channel_value_type const& m_channel;
+
+ public:
+ subscript_result(channel_severity_filter_actor& owner, channel_value_type const& channel) : m_owner(owner), m_channel(channel)
+ {
+ }
+
+ void operator= (severity_value_type const& severity)
+ {
+ m_owner.add(m_channel, severity);
+ }
+ };
+
+public:
+ //! Initializing constructor
+ explicit channel_severity_filter_actor(base_type const& act) : base_type(act)
+ {
+ }
+ //! Copy constructor
+ channel_severity_filter_actor(channel_severity_filter_actor const& that) : base_type(static_cast< base_type const& >(that))
+ {
+ }
+
+ //! Sets the default function result
+ this_type& set_default(bool def)
+ {
+ this->proto_expr_.child0.set_default(def);
+ return *this;
+ }
+
+ //! Adds a new element to the mapping
+ this_type& add(channel_value_type const& channel, severity_value_type const& severity)
+ {
+ this->proto_expr_.child0.add(channel, severity);
+ return *this;
+ }
+
+ //! Alternative interface for adding a new element to the mapping
+ subscript_result operator[] (channel_value_type const& channel)
+ {
+ return subscript_result(*this, channel);
+ }
+};
+
+/*!
+ * The function generates a filtering predicate that checks the severity levels of log records in different channels. The predicate will return \c true
+ * if the record severity level is not less than the threshold for the channel the record belongs to.
+ */
+template< typename ChannelT, typename SeverityT >
+BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT >
+channel_severity_filter(attribute_name const& channel_name, attribute_name const& severity_name)
+{
+ typedef channel_severity_filter_actor< ChannelT, SeverityT > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(channel_name, severity_name) }};
+ return result_type(act);
+}
+
+//! \overload
+template< typename SeverityT, typename ChannelDescriptorT, template< typename > class ActorT >
+BOOST_FORCEINLINE channel_severity_filter_actor< typename ChannelDescriptorT::value_type, SeverityT, fallback_to_none, fallback_to_none, less, greater_equal, std::allocator< void >, ActorT >
+channel_severity_filter(attribute_keyword< ChannelDescriptorT, ActorT > const& channel_keyword, attribute_name const& severity_name)
+{
+ typedef channel_severity_filter_actor< typename ChannelDescriptorT::value_type, SeverityT, fallback_to_none, fallback_to_none, less, greater_equal, std::allocator< void >, ActorT > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(channel_keyword.get_name(), severity_name) }};
+ return result_type(act);
+}
+
+//! \overload
+template< typename ChannelT, typename SeverityDescriptorT, template< typename > class ActorT >
+BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, less, greater_equal, std::allocator< void >, ActorT >
+channel_severity_filter(attribute_name const& channel_name, attribute_keyword< SeverityDescriptorT, ActorT > const& severity_keyword)
+{
+ typedef channel_severity_filter_actor< ChannelT, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, less, greater_equal, std::allocator< void >, ActorT > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(channel_name, severity_keyword.get_name()) }};
+ return result_type(act);
+}
+
+//! \overload
+template< typename ChannelDescriptorT, typename SeverityDescriptorT, template< typename > class ActorT >
+BOOST_FORCEINLINE channel_severity_filter_actor< typename ChannelDescriptorT::value_type, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, less, greater_equal, std::allocator< void >, ActorT >
+channel_severity_filter(attribute_keyword< ChannelDescriptorT, ActorT > const& channel_keyword, attribute_keyword< SeverityDescriptorT, ActorT > const& severity_keyword)
+{
+ typedef channel_severity_filter_actor< typename ChannelDescriptorT::value_type, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, less, greater_equal, std::allocator< void >, ActorT > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(channel_keyword.get_name(), severity_keyword.get_name()) }};
+ return result_type(act);
+}
+
+//! \overload
+template< typename SeverityT, typename ChannelT, typename ChannelFallbackT, typename ChannelTagT, template< typename > class ActorT >
+BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, fallback_to_none, less, greater_equal, std::allocator< void >, ActorT >
+channel_severity_filter(attribute_actor< ChannelT, ChannelFallbackT, ChannelTagT, ActorT > const& channel_placeholder, attribute_name const& severity_name)
+{
+ typedef channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, fallback_to_none, less, greater_equal, std::allocator< void >, ActorT > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(channel_placeholder.get_name(), severity_name, channel_placeholder.get_fallback_policy()) }};
+ return result_type(act);
+}
+
+//! \overload
+template< typename ChannelT, typename SeverityT, typename SeverityFallbackT, typename SeverityTagT, template< typename > class ActorT >
+BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT, fallback_to_none, SeverityFallbackT, less, greater_equal, std::allocator< void >, ActorT >
+channel_severity_filter(attribute_name const& channel_name, attribute_actor< SeverityT, SeverityFallbackT, SeverityTagT, ActorT > const& severity_placeholder)
+{
+ typedef channel_severity_filter_actor< ChannelT, SeverityT, fallback_to_none, SeverityFallbackT, less, greater_equal, std::allocator< void >, ActorT > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(channel_name, severity_placeholder.get_name(), fallback_to_none(), severity_placeholder.get_fallback_policy()) }};
+ return result_type(act);
+}
+
+//! \overload
+template< typename ChannelT, typename ChannelFallbackT, typename ChannelTagT, typename SeverityT, typename SeverityFallbackT, typename SeverityTagT, template< typename > class ActorT >
+BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, SeverityFallbackT, less, greater_equal, std::allocator< void >, ActorT >
+channel_severity_filter(attribute_actor< ChannelT, ChannelFallbackT, ChannelTagT, ActorT > const& channel_placeholder, attribute_actor< SeverityT, SeverityFallbackT, SeverityTagT, ActorT > const& severity_placeholder)
+{
+ typedef channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, SeverityFallbackT, less, greater_equal, std::allocator< void >, ActorT > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(channel_placeholder.get_name(), severity_placeholder.get_name(), channel_placeholder.get_fallback_policy(), severity_placeholder.get_fallback_policy()) }};
+ return result_type(act);
+}
+
+
+//! \overload
+template< typename ChannelT, typename SeverityT, typename SeverityCompareT >
+BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT, fallback_to_none, fallback_to_none, less, SeverityCompareT >
+channel_severity_filter(attribute_name const& channel_name, attribute_name const& severity_name, SeverityCompareT const& severity_compare)
+{
+ typedef channel_severity_filter_actor< ChannelT, SeverityT, fallback_to_none, fallback_to_none, less, SeverityCompareT > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(channel_name, severity_name, fallback_to_none(), fallback_to_none(), less(), severity_compare) }};
+ return result_type(act);
+}
+
+//! \overload
+template< typename SeverityT, typename ChannelDescriptorT, template< typename > class ActorT, typename SeverityCompareT >
+BOOST_FORCEINLINE channel_severity_filter_actor< typename ChannelDescriptorT::value_type, SeverityT, fallback_to_none, fallback_to_none, less, SeverityCompareT, std::allocator< void >, ActorT >
+channel_severity_filter(attribute_keyword< ChannelDescriptorT, ActorT > const& channel_keyword, attribute_name const& severity_name, SeverityCompareT const& severity_compare)
+{
+ typedef channel_severity_filter_actor< typename ChannelDescriptorT::value_type, SeverityT, fallback_to_none, fallback_to_none, less, SeverityCompareT, std::allocator< void >, ActorT > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(channel_keyword.get_name(), severity_name, fallback_to_none(), fallback_to_none(), less(), severity_compare) }};
+ return result_type(act);
+}
+
+//! \overload
+template< typename ChannelT, typename SeverityDescriptorT, template< typename > class ActorT, typename SeverityCompareT >
+BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, less, SeverityCompareT, std::allocator< void >, ActorT >
+channel_severity_filter(attribute_name const& channel_name, attribute_keyword< SeverityDescriptorT, ActorT > const& severity_keyword, SeverityCompareT const& severity_compare)
+{
+ typedef channel_severity_filter_actor< ChannelT, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, less, SeverityCompareT, std::allocator< void >, ActorT > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(channel_name, severity_keyword.get_name(), fallback_to_none(), fallback_to_none(), less(), severity_compare) }};
+ return result_type(act);
+}
+
+//! \overload
+template< typename ChannelDescriptorT, typename SeverityDescriptorT, template< typename > class ActorT, typename SeverityCompareT >
+BOOST_FORCEINLINE channel_severity_filter_actor< typename ChannelDescriptorT::value_type, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, less, SeverityCompareT, std::allocator< void >, ActorT >
+channel_severity_filter(attribute_keyword< ChannelDescriptorT, ActorT > const& channel_keyword, attribute_keyword< SeverityDescriptorT, ActorT > const& severity_keyword, SeverityCompareT const& severity_compare)
+{
+ typedef channel_severity_filter_actor< typename ChannelDescriptorT::value_type, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, less, SeverityCompareT, std::allocator< void >, ActorT > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(channel_keyword.get_name(), severity_keyword.get_name(), fallback_to_none(), fallback_to_none(), less(), severity_compare) }};
+ return result_type(act);
+}
+
+//! \overload
+template< typename SeverityT, typename ChannelT, typename ChannelFallbackT, typename ChannelTagT, template< typename > class ActorT, typename SeverityCompareT >
+BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, fallback_to_none, less, SeverityCompareT, std::allocator< void >, ActorT >
+channel_severity_filter(attribute_actor< ChannelT, ChannelFallbackT, ChannelTagT, ActorT > const& channel_placeholder, attribute_name const& severity_name, SeverityCompareT const& severity_compare)
+{
+ typedef channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, fallback_to_none, less, SeverityCompareT, std::allocator< void >, ActorT > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(channel_placeholder.get_name(), severity_name, channel_placeholder.get_fallback_policy(), fallback_to_none(), less(), severity_compare) }};
+ return result_type(act);
+}
+
+//! \overload
+template< typename ChannelT, typename SeverityT, typename SeverityFallbackT, typename SeverityTagT, template< typename > class ActorT, typename SeverityCompareT >
+BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT, fallback_to_none, SeverityFallbackT, less, SeverityCompareT, std::allocator< void >, ActorT >
+channel_severity_filter(attribute_name const& channel_name, attribute_actor< SeverityT, SeverityFallbackT, SeverityTagT, ActorT > const& severity_placeholder, SeverityCompareT const& severity_compare)
+{
+ typedef channel_severity_filter_actor< ChannelT, SeverityT, fallback_to_none, SeverityFallbackT, less, SeverityCompareT, std::allocator< void >, ActorT > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(channel_name, severity_placeholder.get_name(), fallback_to_none(), severity_placeholder.get_fallback_policy(), less(), severity_compare) }};
+ return result_type(act);
+}
+
+//! \overload
+template< typename ChannelT, typename ChannelFallbackT, typename ChannelTagT, typename SeverityT, typename SeverityFallbackT, typename SeverityTagT, template< typename > class ActorT, typename SeverityCompareT >
+BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, SeverityFallbackT, less, SeverityCompareT, std::allocator< void >, ActorT >
+channel_severity_filter(attribute_actor< ChannelT, ChannelFallbackT, ChannelTagT, ActorT > const& channel_placeholder, attribute_actor< SeverityT, SeverityFallbackT, SeverityTagT, ActorT > const& severity_placeholder, SeverityCompareT const& severity_compare)
+{
+ typedef channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, SeverityFallbackT, less, SeverityCompareT, std::allocator< void >, ActorT > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(channel_placeholder.get_name(), severity_placeholder.get_name(), channel_placeholder.get_fallback_policy(), severity_placeholder.get_fallback_policy(), less(), severity_compare) }};
+ return result_type(act);
+}
+
+
+//! \overload
+template< typename ChannelT, typename SeverityT, typename SeverityCompareT, typename ChannelOrderT >
+BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT, fallback_to_none, fallback_to_none, ChannelOrderT, SeverityCompareT >
+channel_severity_filter(attribute_name const& channel_name, attribute_name const& severity_name, SeverityCompareT const& severity_compare, ChannelOrderT const& channel_order)
+{
+ typedef channel_severity_filter_actor< ChannelT, SeverityT, fallback_to_none, fallback_to_none, ChannelOrderT, SeverityCompareT > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(channel_name, severity_name, fallback_to_none(), fallback_to_none(), channel_order, severity_compare) }};
+ return result_type(act);
+}
+
+//! \overload
+template< typename SeverityT, typename ChannelDescriptorT, template< typename > class ActorT, typename SeverityCompareT, typename ChannelOrderT >
+BOOST_FORCEINLINE channel_severity_filter_actor< typename ChannelDescriptorT::value_type, SeverityT, fallback_to_none, fallback_to_none, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT >
+channel_severity_filter(attribute_keyword< ChannelDescriptorT, ActorT > const& channel_keyword, attribute_name const& severity_name, SeverityCompareT const& severity_compare, ChannelOrderT const& channel_order)
+{
+ typedef channel_severity_filter_actor< typename ChannelDescriptorT::value_type, SeverityT, fallback_to_none, fallback_to_none, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(channel_keyword.get_name(), severity_name, fallback_to_none(), fallback_to_none(), channel_order, severity_compare) }};
+ return result_type(act);
+}
+
+//! \overload
+template< typename ChannelT, typename SeverityDescriptorT, template< typename > class ActorT, typename SeverityCompareT, typename ChannelOrderT >
+BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT >
+channel_severity_filter(attribute_name const& channel_name, attribute_keyword< SeverityDescriptorT, ActorT > const& severity_keyword, SeverityCompareT const& severity_compare, ChannelOrderT const& channel_order)
+{
+ typedef channel_severity_filter_actor< ChannelT, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(channel_name, severity_keyword.get_name(), fallback_to_none(), fallback_to_none(), channel_order, severity_compare) }};
+ return result_type(act);
+}
+
+//! \overload
+template< typename ChannelDescriptorT, typename SeverityDescriptorT, template< typename > class ActorT, typename SeverityCompareT, typename ChannelOrderT >
+BOOST_FORCEINLINE channel_severity_filter_actor< typename ChannelDescriptorT::value_type, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT >
+channel_severity_filter(attribute_keyword< ChannelDescriptorT, ActorT > const& channel_keyword, attribute_keyword< SeverityDescriptorT, ActorT > const& severity_keyword, SeverityCompareT const& severity_compare, ChannelOrderT const& channel_order)
+{
+ typedef channel_severity_filter_actor< typename ChannelDescriptorT::value_type, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(channel_keyword.get_name(), severity_keyword.get_name(), fallback_to_none(), fallback_to_none(), channel_order, severity_compare) }};
+ return result_type(act);
+}
+
+//! \overload
+template< typename SeverityT, typename ChannelT, typename ChannelFallbackT, typename ChannelTagT, template< typename > class ActorT, typename SeverityCompareT, typename ChannelOrderT >
+BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, fallback_to_none, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT >
+channel_severity_filter(attribute_actor< ChannelT, ChannelFallbackT, ChannelTagT, ActorT > const& channel_placeholder, attribute_name const& severity_name, SeverityCompareT const& severity_compare, ChannelOrderT const& channel_order)
+{
+ typedef channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, fallback_to_none, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(channel_placeholder.get_name(), severity_name, channel_placeholder.get_fallback_policy(), fallback_to_none(), channel_order, severity_compare) }};
+ return result_type(act);
+}
+
+//! \overload
+template< typename ChannelT, typename SeverityT, typename SeverityFallbackT, typename SeverityTagT, template< typename > class ActorT, typename SeverityCompareT, typename ChannelOrderT >
+BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT, fallback_to_none, SeverityFallbackT, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT >
+channel_severity_filter(attribute_name const& channel_name, attribute_actor< SeverityT, SeverityFallbackT, SeverityTagT, ActorT > const& severity_placeholder, SeverityCompareT const& severity_compare, ChannelOrderT const& channel_order)
+{
+ typedef channel_severity_filter_actor< ChannelT, SeverityT, fallback_to_none, SeverityFallbackT, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(channel_name, severity_placeholder.get_name(), fallback_to_none(), severity_placeholder.get_fallback_policy(), channel_order, severity_compare) }};
+ return result_type(act);
+}
+
+//! \overload
+template< typename ChannelT, typename ChannelFallbackT, typename ChannelTagT, typename SeverityT, typename SeverityFallbackT, typename SeverityTagT, template< typename > class ActorT, typename SeverityCompareT, typename ChannelOrderT >
+BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, SeverityFallbackT, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT >
+channel_severity_filter(attribute_actor< ChannelT, ChannelFallbackT, ChannelTagT, ActorT > const& channel_placeholder, attribute_actor< SeverityT, SeverityFallbackT, SeverityTagT, ActorT > const& severity_placeholder, SeverityCompareT const& severity_compare, ChannelOrderT const& channel_order)
+{
+ typedef channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, SeverityFallbackT, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(channel_placeholder.get_name(), severity_placeholder.get_name(), channel_placeholder.get_fallback_policy(), severity_placeholder.get_fallback_policy(), channel_order, severity_compare) }};
+ return result_type(act);
+}
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+namespace phoenix {
+
+namespace result_of {
+
+template<
+ typename ChannelT,
+ typename SeverityT,
+ typename ChannelFallbackT,
+ typename SeverityFallbackT,
+ typename ChannelOrderT,
+ typename SeverityCompareT,
+ typename AllocatorT
+>
+struct is_nullary< custom_terminal< boost::log::expressions::channel_severity_filter_terminal< ChannelT, SeverityT, ChannelFallbackT, SeverityFallbackT, ChannelOrderT, SeverityCompareT, AllocatorT > > > :
+ public mpl::false_
+{
+};
+
+} // namespace result_of
+
+} // namespace phoenix
+
+#endif
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_PREDICATES_CHANNEL_SEVERITY_FILTER_HPP_INCLUDED_
diff --git a/boost/log/expressions/predicates/contains.hpp b/boost/log/expressions/predicates/contains.hpp
new file mode 100644
index 0000000000..633ba65e8e
--- /dev/null
+++ b/boost/log/expressions/predicates/contains.hpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file contains.hpp
+ * \author Andrey Semashev
+ * \date 02.09.2012
+ *
+ * The header contains implementation of a \c contains predicate in template expressions.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_PREDICATES_CONTAINS_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_PREDICATES_CONTAINS_HPP_INCLUDED_
+
+#include <boost/phoenix/core/actor.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/embedded_string_type.hpp>
+#include <boost/log/detail/unary_function_terminal.hpp>
+#include <boost/log/detail/attribute_predicate.hpp>
+#include <boost/log/expressions/attr_fwd.hpp>
+#include <boost/log/expressions/keyword_fwd.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/fallback_policy.hpp>
+#include <boost/log/utility/functional/contains.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+/*!
+ * The predicate checks if the attribute value contains a substring. The attribute value is assumed to be of a string type.
+ */
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template< typename T, typename SubstringT, typename FallbackPolicyT = fallback_to_none >
+using attribute_contains = aux::attribute_predicate< T, SubstringT, contains_fun, FallbackPolicyT >;
+
+#else // !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template< typename T, typename SubstringT, typename FallbackPolicyT = fallback_to_none >
+class attribute_contains :
+ public aux::attribute_predicate< T, SubstringT, contains_fun, FallbackPolicyT >
+{
+ typedef aux::attribute_predicate< T, SubstringT, contains_fun, FallbackPolicyT > base_type;
+
+public:
+ /*!
+ * Initializing constructor
+ *
+ * \param name Attribute name
+ * \param substring The expected attribute value substring
+ */
+ attribute_contains(attribute_name const& name, SubstringT const& substring) : base_type(name, substring)
+ {
+ }
+
+ /*!
+ * Initializing constructor
+ *
+ * \param name Attribute name
+ * \param substring The expected attribute value substring
+ * \param arg Additional parameter for the fallback policy
+ */
+ template< typename U >
+ attribute_contains(attribute_name const& name, SubstringT const& substring, U const& arg) : base_type(name, substring, arg)
+ {
+ }
+};
+
+#endif // !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+/*!
+ * The function generates a terminal node in a template expression. The node will check if the attribute value,
+ * which is assumed to be a string, contains the specified substring.
+ */
+template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename SubstringT >
+BOOST_FORCEINLINE ActorT< aux::unary_function_terminal< attribute_contains< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type, FallbackPolicyT > > >
+contains(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& attr, SubstringT const& substring)
+{
+ typedef aux::unary_function_terminal< attribute_contains< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type, FallbackPolicyT > > terminal_type;
+ ActorT< terminal_type > act = {{ terminal_type(attr.get_name(), substring, attr.get_fallback_policy()) }};
+ return act;
+}
+
+/*!
+ * The function generates a terminal node in a template expression. The node will check if the attribute value,
+ * which is assumed to be a string, contains the specified substring.
+ */
+template< typename DescriptorT, template< typename > class ActorT, typename SubstringT >
+BOOST_FORCEINLINE ActorT< aux::unary_function_terminal< attribute_contains< typename DescriptorT::value_type, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > >
+contains(attribute_keyword< DescriptorT, ActorT > const&, SubstringT const& substring)
+{
+ typedef aux::unary_function_terminal< attribute_contains< typename DescriptorT::value_type, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > terminal_type;
+ ActorT< terminal_type > act = {{ terminal_type(DescriptorT::get_name(), substring) }};
+ return act;
+}
+
+/*!
+ * The function generates a terminal node in a template expression. The node will check if the attribute value,
+ * which is assumed to be a string, contains the specified substring.
+ */
+template< typename T, typename SubstringT >
+BOOST_FORCEINLINE phoenix::actor< aux::unary_function_terminal< attribute_contains< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > >
+contains(attribute_name const& name, SubstringT const& substring)
+{
+ typedef aux::unary_function_terminal< attribute_contains< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > terminal_type;
+ phoenix::actor< terminal_type > act = {{ terminal_type(name, substring) }};
+ return act;
+}
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_PREDICATES_CONTAINS_HPP_INCLUDED_
diff --git a/boost/log/expressions/predicates/ends_with.hpp b/boost/log/expressions/predicates/ends_with.hpp
new file mode 100644
index 0000000000..1e8785dad0
--- /dev/null
+++ b/boost/log/expressions/predicates/ends_with.hpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file ends_with.hpp
+ * \author Andrey Semashev
+ * \date 02.09.2012
+ *
+ * The header contains implementation of a \c ends_with predicate in template expressions.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_PREDICATES_ENDS_WITH_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_PREDICATES_ENDS_WITH_HPP_INCLUDED_
+
+#include <boost/phoenix/core/actor.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/embedded_string_type.hpp>
+#include <boost/log/detail/unary_function_terminal.hpp>
+#include <boost/log/detail/attribute_predicate.hpp>
+#include <boost/log/expressions/attr_fwd.hpp>
+#include <boost/log/expressions/keyword_fwd.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/fallback_policy.hpp>
+#include <boost/log/utility/functional/ends_with.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+/*!
+ * The predicate checks if the attribute value ends with a substring. The attribute value is assumed to be of a string type.
+ */
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template< typename T, typename SubstringT, typename FallbackPolicyT = fallback_to_none >
+using attribute_ends_with = aux::attribute_predicate< T, SubstringT, ends_with_fun, FallbackPolicyT >;
+
+#else // !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template< typename T, typename SubstringT, typename FallbackPolicyT = fallback_to_none >
+class attribute_ends_with :
+ public aux::attribute_predicate< T, SubstringT, ends_with_fun, FallbackPolicyT >
+{
+ typedef aux::attribute_predicate< T, SubstringT, ends_with_fun, FallbackPolicyT > base_type;
+
+public:
+ /*!
+ * Initializing constructor
+ *
+ * \param name Attribute name
+ * \param substring The expected attribute value ending
+ */
+ attribute_ends_with(attribute_name const& name, SubstringT const& substring) : base_type(name, substring)
+ {
+ }
+
+ /*!
+ * Initializing constructor
+ *
+ * \param name Attribute name
+ * \param substring The expected attribute value ending
+ * \param arg Additional parameter for the fallback policy
+ */
+ template< typename U >
+ attribute_ends_with(attribute_name const& name, SubstringT const& substring, U const& arg) : base_type(name, substring, arg)
+ {
+ }
+};
+
+#endif // !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+/*!
+ * The function generates a terminal node in a template expression. The node will check if the attribute value,
+ * which is assumed to be a string, ends with the specified substring.
+ */
+template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename SubstringT >
+BOOST_FORCEINLINE ActorT< aux::unary_function_terminal< attribute_ends_with< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type, FallbackPolicyT > > >
+ends_with(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& attr, SubstringT const& substring)
+{
+ typedef aux::unary_function_terminal< attribute_ends_with< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type, FallbackPolicyT > > terminal_type;
+ ActorT< terminal_type > act = {{ terminal_type(attr.get_name(), substring, attr.get_fallback_policy()) }};
+ return act;
+}
+
+/*!
+ * The function generates a terminal node in a template expression. The node will check if the attribute value,
+ * which is assumed to be a string, ends with the specified substring.
+ */
+template< typename DescriptorT, template< typename > class ActorT, typename SubstringT >
+BOOST_FORCEINLINE ActorT< aux::unary_function_terminal< attribute_ends_with< typename DescriptorT::value_type, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > >
+ends_with(attribute_keyword< DescriptorT, ActorT > const&, SubstringT const& substring)
+{
+ typedef aux::unary_function_terminal< attribute_ends_with< typename DescriptorT::value_type, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > terminal_type;
+ ActorT< terminal_type > act = {{ terminal_type(DescriptorT::get_name(), substring) }};
+ return act;
+}
+
+/*!
+ * The function generates a terminal node in a template expression. The node will check if the attribute value,
+ * which is assumed to be a string, ends with the specified substring.
+ */
+template< typename T, typename SubstringT >
+BOOST_FORCEINLINE phoenix::actor< aux::unary_function_terminal< attribute_ends_with< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > >
+ends_with(attribute_name const& name, SubstringT const& substring)
+{
+ typedef aux::unary_function_terminal< attribute_ends_with< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > terminal_type;
+ phoenix::actor< terminal_type > act = {{ terminal_type(name, substring) }};
+ return act;
+}
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_PREDICATES_ENDS_WITH_HPP_INCLUDED_
diff --git a/boost/log/expressions/predicates/has_attr.hpp b/boost/log/expressions/predicates/has_attr.hpp
new file mode 100644
index 0000000000..e4eb72e683
--- /dev/null
+++ b/boost/log/expressions/predicates/has_attr.hpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file has_attr.hpp
+ * \author Andrey Semashev
+ * \date 23.07.2012
+ *
+ * The header contains implementation of a generic attribute presence checker in template expressions.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_PREDICATES_HAS_ATTR_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_PREDICATES_HAS_ATTR_HPP_INCLUDED_
+
+#include <boost/phoenix/core/actor.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/core/record_view.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include <boost/log/attributes/value_visitation.hpp>
+#include <boost/log/expressions/keyword_fwd.hpp>
+#include <boost/log/detail/unary_function_terminal.hpp>
+#include <boost/log/utility/functional/nop.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+/*!
+ * An attribute value presence checker.
+ */
+template< typename T >
+class has_attribute
+{
+public:
+ //! Function result_type
+ typedef bool result_type;
+ //! Expected attribute value type
+ typedef T value_type;
+
+private:
+ //! Attribute value name
+ const attribute_name m_name;
+ //! Visitor invoker
+ value_visitor_invoker< value_type > m_visitor_invoker;
+
+public:
+ /*!
+ * Initializing constructor
+ *
+ * \param name Attribute name
+ */
+ explicit has_attribute(attribute_name const& name) : m_name(name)
+ {
+ }
+
+ /*!
+ * Checking operator
+ *
+ * \param arg A set of attribute values or a log record
+ * \return \c true if the log record contains the sought attribute value, \c false otherwise
+ */
+ template< typename ArgT >
+ result_type operator() (ArgT const& arg) const
+ {
+ return m_visitor_invoker(m_name, arg, nop()).code() == visitation_result::ok;
+ }
+};
+
+/*!
+ * An attribute value presence checker. This specialization does not check the type of the attribute value.
+ */
+template< >
+class has_attribute< void >
+{
+public:
+ //! Function result_type
+ typedef bool result_type;
+ //! Expected attribute value type
+ typedef void value_type;
+
+private:
+ //! Attribute name
+ const attribute_name m_name;
+
+public:
+ /*!
+ * Initializing constructor
+ *
+ * \param name Attribute name
+ */
+ explicit has_attribute(attribute_name const& name) : m_name(name)
+ {
+ }
+
+ /*!
+ * Checking operator
+ *
+ * \param attrs A set of attribute values
+ * \return \c true if the log record contains the sought attribute value, \c false otherwise
+ */
+ result_type operator() (attribute_value_set const& attrs) const
+ {
+ return attrs.find(m_name) != attrs.end();
+ }
+
+ /*!
+ * Checking operator
+ *
+ * \param rec A log record
+ * \return \c true if the log record contains the sought attribute value, \c false otherwise
+ */
+ result_type operator() (boost::log::record_view const& rec) const
+ {
+ return operator()(rec.attribute_values());
+ }
+};
+
+/*!
+ * The function generates a terminal node in a template expression. The node will check for the attribute value
+ * presence in a log record. The node will also check that the attribute value has the specified type, if present.
+ */
+template< typename AttributeValueT >
+BOOST_FORCEINLINE phoenix::actor< aux::unary_function_terminal< has_attribute< AttributeValueT > > > has_attr(attribute_name const& name)
+{
+ typedef aux::unary_function_terminal< has_attribute< AttributeValueT > > terminal_type;
+ phoenix::actor< terminal_type > act = {{ terminal_type(name) }};
+ return act;
+}
+
+/*!
+ * The function generates a terminal node in a template expression. The node will check for the attribute value
+ * presence in a log record.
+ */
+BOOST_FORCEINLINE phoenix::actor< aux::unary_function_terminal< has_attribute< void > > > has_attr(attribute_name const& name)
+{
+ typedef aux::unary_function_terminal< has_attribute< void > > terminal_type;
+ phoenix::actor< terminal_type > act = {{ terminal_type(name) }};
+ return act;
+}
+
+/*!
+ * The function generates a terminal node in a template expression. The node will check for the attribute value
+ * presence in a log record. The node will also check that the attribute value has the specified type, if present.
+ */
+template< typename DescriptorT, template< typename > class ActorT >
+BOOST_FORCEINLINE ActorT< aux::unary_function_terminal< has_attribute< typename DescriptorT::value_type > > > has_attr(attribute_keyword< DescriptorT, ActorT > const&)
+{
+ typedef aux::unary_function_terminal< has_attribute< typename DescriptorT::value_type > > terminal_type;
+ ActorT< terminal_type > act = {{ terminal_type(DescriptorT::get_name()) }};
+ return act;
+}
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_PREDICATES_HAS_ATTR_HPP_INCLUDED_
diff --git a/boost/log/expressions/predicates/is_debugger_present.hpp b/boost/log/expressions/predicates/is_debugger_present.hpp
new file mode 100644
index 0000000000..f7427c8a90
--- /dev/null
+++ b/boost/log/expressions/predicates/is_debugger_present.hpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file is_debugger_present.hpp
+ * \author Andrey Semashev
+ * \date 05.12.2012
+ *
+ * The header contains implementation of the \c is_debugger_present predicate in template expressions.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_PREDICATES_IS_DEBUGGER_PRESENT_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_PREDICATES_IS_DEBUGGER_PRESENT_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(BOOST_WINDOWS)
+
+#include <boost/phoenix/core/terminal.hpp> // this is needed to be able to include this header alone, Boost.Phoenix blows up without it
+#include <boost/phoenix/function/adapt_callable.hpp>
+#include <boost/log/detail/header.hpp>
+
+#if defined(BOOST_USE_WINDOWS_H)
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0500
+#endif
+
+#include <windows.h>
+
+#else // defined(BOOST_USE_WINDOWS_H)
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+namespace aux {
+
+extern "C" {
+
+__declspec(dllimport) int __stdcall IsDebuggerPresent();
+
+} // extern "C"
+
+} // namespace aux
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_USE_WINDOWS_H
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+namespace aux {
+
+struct is_debugger_present
+{
+ typedef bool result_type;
+
+ result_type operator() () const
+ {
+ return IsDebuggerPresent() != 0;
+ }
+};
+
+} // namespace aux
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+BOOST_PHOENIX_ADAPT_CALLABLE_NULLARY(is_debugger_present, aux::is_debugger_present)
+
+#else
+
+/*!
+ * The function generates a filter that will check whether the logger is attached to the process
+ */
+unspecified is_debugger_present();
+
+#endif
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_WINDOWS
+
+#endif // BOOST_LOG_EXPRESSIONS_PREDICATES_IS_DEBUGGER_PRESENT_HPP_INCLUDED_
diff --git a/boost/log/expressions/predicates/is_in_range.hpp b/boost/log/expressions/predicates/is_in_range.hpp
new file mode 100644
index 0000000000..e819d2bfe2
--- /dev/null
+++ b/boost/log/expressions/predicates/is_in_range.hpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file is_in_range.hpp
+ * \author Andrey Semashev
+ * \date 02.09.2012
+ *
+ * The header contains implementation of an \c is_in_range predicate in template expressions.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_PREDICATES_IS_IN_RANGE_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_PREDICATES_IS_IN_RANGE_HPP_INCLUDED_
+
+#include <utility>
+#include <boost/phoenix/core/actor.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/embedded_string_type.hpp>
+#include <boost/log/detail/unary_function_terminal.hpp>
+#include <boost/log/detail/attribute_predicate.hpp>
+#include <boost/log/expressions/attr_fwd.hpp>
+#include <boost/log/expressions/keyword_fwd.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/fallback_policy.hpp>
+#include <boost/log/utility/functional/in_range.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+/*!
+ * The predicate checks if the attribute value contains a substring. The attribute value is assumed to be of a string type.
+ */
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template< typename T, typename BoundaryT, typename FallbackPolicyT = fallback_to_none >
+using attribute_is_in_range = aux::attribute_predicate< T, std::pair< BoundaryT, BoundaryT >, in_range_fun, FallbackPolicyT >;
+
+#else // !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template< typename T, typename BoundaryT, typename FallbackPolicyT = fallback_to_none >
+class attribute_is_in_range :
+ public aux::attribute_predicate< T, std::pair< BoundaryT, BoundaryT >, in_range_fun, FallbackPolicyT >
+{
+ typedef aux::attribute_predicate< T, std::pair< BoundaryT, BoundaryT >, in_range_fun, FallbackPolicyT > base_type;
+
+public:
+ /*!
+ * Initializing constructor
+ *
+ * \param name Attribute name
+ * \param boundaries The expected attribute value boundaries
+ */
+ attribute_is_in_range(attribute_name const& name, std::pair< BoundaryT, BoundaryT > const& boundaries) : base_type(name, boundaries)
+ {
+ }
+
+ /*!
+ * Initializing constructor
+ *
+ * \param name Attribute name
+ * \param boundaries The expected attribute value boundaries
+ * \param arg Additional parameter for the fallback policy
+ */
+ template< typename U >
+ attribute_is_in_range(attribute_name const& name, std::pair< BoundaryT, BoundaryT > const& boundaries, U const& arg) : base_type(name, boundaries, arg)
+ {
+ }
+};
+
+#endif // !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+/*!
+ * The function generates a terminal node in a template expression. The node will check if the attribute value
+ * is in the specified range. The range must be half-open, that is the predicate will be equivalent to <tt>least <= attr < most</tt>.
+ */
+template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename BoundaryT >
+BOOST_FORCEINLINE ActorT< aux::unary_function_terminal< attribute_is_in_range< T, typename boost::log::aux::make_embedded_string_type< BoundaryT >::type, FallbackPolicyT > > >
+is_in_range(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& attr, BoundaryT const& least, BoundaryT const& most)
+{
+ typedef typename boost::log::aux::make_embedded_string_type< BoundaryT >::type boundary_type;
+ typedef aux::unary_function_terminal< attribute_is_in_range< T, boundary_type, FallbackPolicyT > > terminal_type;
+ ActorT< terminal_type > act = {{ terminal_type(attr.get_name(), std::pair< boundary_type, boundary_type >(least, most), attr.get_fallback_policy()) }};
+ return act;
+}
+
+/*!
+ * The function generates a terminal node in a template expression. The node will check if the attribute value
+ * is in the specified range. The range must be half-open, that is the predicate will be equivalent to <tt>least <= attr < most</tt>.
+ */
+template< typename DescriptorT, template< typename > class ActorT, typename BoundaryT >
+BOOST_FORCEINLINE ActorT< aux::unary_function_terminal< attribute_is_in_range< typename DescriptorT::value_type, typename boost::log::aux::make_embedded_string_type< BoundaryT >::type > > >
+is_in_range(attribute_keyword< DescriptorT, ActorT > const&, BoundaryT const& least, BoundaryT const& most)
+{
+ typedef typename boost::log::aux::make_embedded_string_type< BoundaryT >::type boundary_type;
+ typedef aux::unary_function_terminal< attribute_is_in_range< typename DescriptorT::value_type, boundary_type > > terminal_type;
+ ActorT< terminal_type > act = {{ terminal_type(DescriptorT::get_name(), std::pair< boundary_type, boundary_type >(least, most)) }};
+ return act;
+}
+
+/*!
+ * The function generates a terminal node in a template expression. The node will check if the attribute value
+ * is in the specified range. The range must be half-open, that is the predicate will be equivalent to <tt>least <= attr < most</tt>.
+ */
+template< typename T, typename BoundaryT >
+BOOST_FORCEINLINE phoenix::actor< aux::unary_function_terminal< attribute_is_in_range< T, typename boost::log::aux::make_embedded_string_type< BoundaryT >::type > > >
+is_in_range(attribute_name const& name, BoundaryT const& least, BoundaryT const& most)
+{
+ typedef typename boost::log::aux::make_embedded_string_type< BoundaryT >::type boundary_type;
+ typedef aux::unary_function_terminal< attribute_is_in_range< T, boundary_type > > terminal_type;
+ phoenix::actor< terminal_type > act = {{ terminal_type(name, std::pair< boundary_type, boundary_type >(least, most)) }};
+ return act;
+}
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_PREDICATES_IS_IN_RANGE_HPP_INCLUDED_
diff --git a/boost/log/expressions/predicates/matches.hpp b/boost/log/expressions/predicates/matches.hpp
new file mode 100644
index 0000000000..798f2e7e4f
--- /dev/null
+++ b/boost/log/expressions/predicates/matches.hpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file matches.hpp
+ * \author Andrey Semashev
+ * \date 02.09.2012
+ *
+ * The header contains implementation of a \c matches predicate in template expressions.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_PREDICATES_MATCHES_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_PREDICATES_MATCHES_HPP_INCLUDED_
+
+#include <boost/phoenix/core/actor.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/unary_function_terminal.hpp>
+#include <boost/log/detail/attribute_predicate.hpp>
+#include <boost/log/expressions/attr_fwd.hpp>
+#include <boost/log/expressions/keyword_fwd.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/fallback_policy.hpp>
+#include <boost/log/utility/functional/matches.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+/*!
+ * The predicate checks if the attribute value matches a regular expression. The attribute value is assumed to be of a string type.
+ */
+template< typename T, typename RegexT, typename FallbackPolicyT = fallback_to_none >
+class attribute_matches :
+ public aux::attribute_predicate< T, typename boost::log::aux::match_traits< RegexT >::compiled_type, matches_fun, FallbackPolicyT >
+{
+ typedef aux::attribute_predicate< T, typename boost::log::aux::match_traits< RegexT >::compiled_type, matches_fun, FallbackPolicyT > base_type;
+
+public:
+ /*!
+ * Initializing constructor
+ *
+ * \param name Attribute name
+ * \param rex The regular expression to match the attribute value against
+ */
+ attribute_matches(attribute_name const& name, RegexT const& rex) : base_type(name, boost::log::aux::match_traits< RegexT >::compile(rex))
+ {
+ }
+
+ /*!
+ * Initializing constructor
+ *
+ * \param name Attribute name
+ * \param rex The regular expression to match the attribute value against
+ * \param arg Additional parameter for the fallback policy
+ */
+ template< typename U >
+ attribute_matches(attribute_name const& name, RegexT const& rex, U const& arg) : base_type(name, boost::log::aux::match_traits< RegexT >::compile(rex), arg)
+ {
+ }
+};
+
+/*!
+ * The function generates a terminal node in a template expression. The node will check if the attribute value,
+ * which is assumed to be a string, matches the specified regular expression.
+ */
+template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename RegexT >
+BOOST_FORCEINLINE ActorT< aux::unary_function_terminal< attribute_matches< T, RegexT, FallbackPolicyT > > >
+matches(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& attr, RegexT const& rex)
+{
+ typedef aux::unary_function_terminal< attribute_matches< T, RegexT, FallbackPolicyT > > terminal_type;
+ ActorT< terminal_type > act = {{ terminal_type(attr.get_name(), rex, attr.get_fallback_policy()) }};
+ return act;
+}
+
+/*!
+ * The function generates a terminal node in a template expression. The node will check if the attribute value,
+ * which is assumed to be a string, matches the specified regular expression.
+ */
+template< typename DescriptorT, template< typename > class ActorT, typename RegexT >
+BOOST_FORCEINLINE ActorT< aux::unary_function_terminal< attribute_matches< typename DescriptorT::value_type, RegexT > > >
+matches(attribute_keyword< DescriptorT, ActorT > const&, RegexT const& rex)
+{
+ typedef aux::unary_function_terminal< attribute_matches< typename DescriptorT::value_type, RegexT > > terminal_type;
+ ActorT< terminal_type > act = {{ terminal_type(DescriptorT::get_name(), rex) }};
+ return act;
+}
+
+/*!
+ * The function generates a terminal node in a template expression. The node will check if the attribute value,
+ * which is assumed to be a string, matches the specified regular expression.
+ */
+template< typename T, typename RegexT >
+BOOST_FORCEINLINE phoenix::actor< aux::unary_function_terminal< attribute_matches< T, RegexT > > >
+matches(attribute_name const& name, RegexT const& rex)
+{
+ typedef aux::unary_function_terminal< attribute_matches< T, RegexT > > terminal_type;
+ phoenix::actor< terminal_type > act = {{ terminal_type(name, rex) }};
+ return act;
+}
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_PREDICATES_MATCHES_HPP_INCLUDED_
diff --git a/boost/log/expressions/record.hpp b/boost/log/expressions/record.hpp
new file mode 100644
index 0000000000..d695c2aa65
--- /dev/null
+++ b/boost/log/expressions/record.hpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file record.hpp
+ * \author Andrey Semashev
+ * \date 25.07.2012
+ *
+ * The header contains implementation of a log record placeholder in template expressions.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_RECORD_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_RECORD_HPP_INCLUDED_
+
+#include <boost/phoenix/core/argument.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+/*!
+ * Log record placeholder type in formatter template expressions.
+ */
+typedef phoenix::expression::argument< 1 >::type record_type;
+
+/*!
+ * Log record placeholder in formatter template expressions.
+ */
+const record_type record = {};
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_RECORD_HPP_INCLUDED_
diff --git a/boost/log/keywords/auto_flush.hpp b/boost/log/keywords/auto_flush.hpp
new file mode 100644
index 0000000000..0c3b53a6a3
--- /dev/null
+++ b/boost/log/keywords/auto_flush.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/auto_flush.hpp
+ * \author Andrey Semashev
+ * \date 14.03.2009
+ *
+ * The header contains the \c auto_flush keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_AUTO_FLUSH_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_AUTO_FLUSH_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword for passing auto flush flag to a sink backend initialization
+BOOST_PARAMETER_KEYWORD(tag, auto_flush)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_AUTO_FLUSH_HPP_INCLUDED_
diff --git a/boost/log/keywords/channel.hpp b/boost/log/keywords/channel.hpp
new file mode 100644
index 0000000000..b4bbb17a8f
--- /dev/null
+++ b/boost/log/keywords/channel.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/channel.hpp
+ * \author Andrey Semashev
+ * \date 14.03.2009
+ *
+ * The header contains the \c channel keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_CHANNEL_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_CHANNEL_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword for passing channel name to the channel logger constructor
+BOOST_PARAMETER_KEYWORD(tag, channel)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_CHANNEL_HPP_INCLUDED_
diff --git a/boost/log/keywords/delimiter.hpp b/boost/log/keywords/delimiter.hpp
new file mode 100644
index 0000000000..80a2e70366
--- /dev/null
+++ b/boost/log/keywords/delimiter.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/delimiter.hpp
+ * \author Andrey Semashev
+ * \date 14.03.2009
+ *
+ * The header contains the \c delimiter keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_DELIMITER_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_DELIMITER_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword for passing delimiter between scopes to the \c named_scope formatter
+BOOST_PARAMETER_KEYWORD(tag, delimiter)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_DELIMITER_HPP_INCLUDED_
diff --git a/boost/log/keywords/depth.hpp b/boost/log/keywords/depth.hpp
new file mode 100644
index 0000000000..87ffcc98d4
--- /dev/null
+++ b/boost/log/keywords/depth.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/depth.hpp
+ * \author Andrey Semashev
+ * \date 14.03.2009
+ *
+ * The header contains the \c depth keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_DEPTH_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_DEPTH_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword for passing maximum scopes depth to the \c named_scope formatter
+BOOST_PARAMETER_KEYWORD(tag, depth)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_DEPTH_HPP_INCLUDED_
diff --git a/boost/log/keywords/empty_marker.hpp b/boost/log/keywords/empty_marker.hpp
new file mode 100644
index 0000000000..6108315be7
--- /dev/null
+++ b/boost/log/keywords/empty_marker.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/empty_marker.hpp
+ * \author Andrey Semashev
+ * \date 15.03.2014
+ *
+ * The header contains the \c empty_marker keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_EMPTY_MARKER_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_EMPTY_MARKER_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword for passing the marker for the empty list of scopes to the \c named_scope formatter
+BOOST_PARAMETER_KEYWORD(tag, empty_marker)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_EMPTY_MARKER_HPP_INCLUDED_
diff --git a/boost/log/keywords/facility.hpp b/boost/log/keywords/facility.hpp
new file mode 100644
index 0000000000..04d9b91b7b
--- /dev/null
+++ b/boost/log/keywords/facility.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/facility.hpp
+ * \author Andrey Semashev
+ * \date 14.03.2009
+ *
+ * The header contains the \c facility keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_FACILITY_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_FACILITY_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword is used to pass syslog facility that emits log records
+BOOST_PARAMETER_KEYWORD(tag, facility)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_FACILITY_HPP_INCLUDED_
diff --git a/boost/log/keywords/file_name.hpp b/boost/log/keywords/file_name.hpp
new file mode 100644
index 0000000000..ce70a54ccd
--- /dev/null
+++ b/boost/log/keywords/file_name.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/file_name.hpp
+ * \author Andrey Semashev
+ * \date 14.03.2009
+ *
+ * The header contains the \c file_name keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_FILE_NAME_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_FILE_NAME_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword allows to pass log file name the rotating file stream methods
+BOOST_PARAMETER_KEYWORD(tag, file_name)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_FILE_NAME_HPP_INCLUDED_
diff --git a/boost/log/keywords/filter.hpp b/boost/log/keywords/filter.hpp
new file mode 100644
index 0000000000..7b5ab06b5f
--- /dev/null
+++ b/boost/log/keywords/filter.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/filter.hpp
+ * \author Andrey Semashev
+ * \date 14.03.2009
+ *
+ * The header contains the \c filter keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_FILTER_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_FILTER_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword for passing filters to functions
+BOOST_PARAMETER_KEYWORD(tag, filter)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_FILTER_HPP_INCLUDED_
diff --git a/boost/log/keywords/format.hpp b/boost/log/keywords/format.hpp
new file mode 100644
index 0000000000..1e5c450203
--- /dev/null
+++ b/boost/log/keywords/format.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/format.hpp
+ * \author Andrey Semashev
+ * \date 14.03.2009
+ *
+ * The header contains the \c format keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_FORMAT_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_FORMAT_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword for passing format specifiers to functions
+BOOST_PARAMETER_KEYWORD(tag, format)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_FORMAT_HPP_INCLUDED_
diff --git a/boost/log/keywords/ident.hpp b/boost/log/keywords/ident.hpp
new file mode 100644
index 0000000000..4847cc1f4f
--- /dev/null
+++ b/boost/log/keywords/ident.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/ident.hpp
+ * \author Andrey Semashev
+ * \date 22.10.2012
+ *
+ * The header contains the \c ident keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_IDENT_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_IDENT_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword for passing process identification string to the \c openlog call
+BOOST_PARAMETER_KEYWORD(tag, ident)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_IDENT_HPP_INCLUDED_
diff --git a/boost/log/keywords/incomplete_marker.hpp b/boost/log/keywords/incomplete_marker.hpp
new file mode 100644
index 0000000000..1e6d3ab18e
--- /dev/null
+++ b/boost/log/keywords/incomplete_marker.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/incomplete_marker.hpp
+ * \author Andrey Semashev
+ * \date 15.03.2014
+ *
+ * The header contains the \c incomplete_marker keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_INCOMPLETE_MARKER_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_INCOMPLETE_MARKER_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword for passing incomplete marker for the list of scopes to the \c named_scope formatter
+BOOST_PARAMETER_KEYWORD(tag, incomplete_marker)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_INCOMPLETE_MARKER_HPP_INCLUDED_
diff --git a/boost/log/keywords/ip_version.hpp b/boost/log/keywords/ip_version.hpp
new file mode 100644
index 0000000000..c788e191e5
--- /dev/null
+++ b/boost/log/keywords/ip_version.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/ip_version.hpp
+ * \author Andrey Semashev
+ * \date 14.03.2009
+ *
+ * The header contains the \c ip_version keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_IP_VERSION_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_IP_VERSION_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword is used to indicate which version of IP protocol to use
+BOOST_PARAMETER_KEYWORD(tag, ip_version)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_IP_VERSION_HPP_INCLUDED_
diff --git a/boost/log/keywords/iteration.hpp b/boost/log/keywords/iteration.hpp
new file mode 100644
index 0000000000..6fee81ee95
--- /dev/null
+++ b/boost/log/keywords/iteration.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/iteration.hpp
+ * \author Andrey Semashev
+ * \date 14.03.2009
+ *
+ * The header contains the \c iteration keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_ITERATION_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_ITERATION_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword for passing scope iteration direction to the \c named_scope formatter
+BOOST_PARAMETER_KEYWORD(tag, iteration)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_ITERATION_HPP_INCLUDED_
diff --git a/boost/log/keywords/log_name.hpp b/boost/log/keywords/log_name.hpp
new file mode 100644
index 0000000000..e252d29722
--- /dev/null
+++ b/boost/log/keywords/log_name.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/log_name.hpp
+ * \author Andrey Semashev
+ * \date 14.03.2009
+ *
+ * The header contains the \c log_name keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_LOG_NAME_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_LOG_NAME_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword is used to pass event log name to a sink backend
+BOOST_PARAMETER_KEYWORD(tag, log_name)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_LOG_NAME_HPP_INCLUDED_
diff --git a/boost/log/keywords/log_source.hpp b/boost/log/keywords/log_source.hpp
new file mode 100644
index 0000000000..94f51efb12
--- /dev/null
+++ b/boost/log/keywords/log_source.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/log_source.hpp
+ * \author Andrey Semashev
+ * \date 14.03.2009
+ *
+ * The header contains the \c log_source keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_LOG_SOURCE_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_LOG_SOURCE_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword is used to pass event log source name to a sink backend
+BOOST_PARAMETER_KEYWORD(tag, log_source)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_LOG_SOURCE_HPP_INCLUDED_
diff --git a/boost/log/keywords/max_size.hpp b/boost/log/keywords/max_size.hpp
new file mode 100644
index 0000000000..5a91797fa9
--- /dev/null
+++ b/boost/log/keywords/max_size.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/max_size.hpp
+ * \author Andrey Semashev
+ * \date 30.06.2009
+ *
+ * The header contains the \c max_size keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_MAX_SIZE_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_MAX_SIZE_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword allows to specify maximum size of the log files
+BOOST_PARAMETER_KEYWORD(tag, max_size)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_MAX_SIZE_HPP_INCLUDED_
diff --git a/boost/log/keywords/message_file.hpp b/boost/log/keywords/message_file.hpp
new file mode 100644
index 0000000000..2f9c8f7f3c
--- /dev/null
+++ b/boost/log/keywords/message_file.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/message_file.hpp
+ * \author Andrey Semashev
+ * \date 14.03.2009
+ *
+ * The header contains the \c message_file keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_MESSAGE_FILE_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_MESSAGE_FILE_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword is used to pass the name of the file with event resources to the Windows Event Log backend constructor
+BOOST_PARAMETER_KEYWORD(tag, message_file)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_MESSAGE_FILE_HPP_INCLUDED_
diff --git a/boost/log/keywords/min_free_space.hpp b/boost/log/keywords/min_free_space.hpp
new file mode 100644
index 0000000000..dc6958c2b8
--- /dev/null
+++ b/boost/log/keywords/min_free_space.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/min_free_space.hpp
+ * \author Andrey Semashev
+ * \date 30.06.2009
+ *
+ * The header contains the \c min_free_space keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_MIN_FREE_SPACE_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_MIN_FREE_SPACE_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword allows to specify minimum free space on the drive
+BOOST_PARAMETER_KEYWORD(tag, min_free_space)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_MIN_FREE_SPACE_HPP_INCLUDED_
diff --git a/boost/log/keywords/open_mode.hpp b/boost/log/keywords/open_mode.hpp
new file mode 100644
index 0000000000..6456b42037
--- /dev/null
+++ b/boost/log/keywords/open_mode.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/open_mode.hpp
+ * \author Andrey Semashev
+ * \date 14.03.2009
+ *
+ * The header contains the \c open_mode keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_OPEN_MODE_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_OPEN_MODE_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword allows to pass log file opening parameters to the rotating file stream methods
+BOOST_PARAMETER_KEYWORD(tag, open_mode)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_OPEN_MODE_HPP_INCLUDED_
diff --git a/boost/log/keywords/order.hpp b/boost/log/keywords/order.hpp
new file mode 100644
index 0000000000..7e2cc10708
--- /dev/null
+++ b/boost/log/keywords/order.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/order.hpp
+ * \author Andrey Semashev
+ * \date 23.08.2009
+ *
+ * The header contains the \c order keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_ORDER_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_ORDER_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword allows to pass the ordering predicate to sink frontends
+BOOST_PARAMETER_KEYWORD(tag, order)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_ORDER_HPP_INCLUDED_
diff --git a/boost/log/keywords/ordering_window.hpp b/boost/log/keywords/ordering_window.hpp
new file mode 100644
index 0000000000..6458aba343
--- /dev/null
+++ b/boost/log/keywords/ordering_window.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/ordering_window.hpp
+ * \author Andrey Semashev
+ * \date 23.08.2009
+ *
+ * The header contains the \c ordering_window keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_ORDERING_WINDOW_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_ORDERING_WINDOW_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword allows to pass the ordering window to sink frontends
+BOOST_PARAMETER_KEYWORD(tag, ordering_window)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_ORDERING_WINDOW_HPP_INCLUDED_
diff --git a/boost/log/keywords/registration.hpp b/boost/log/keywords/registration.hpp
new file mode 100644
index 0000000000..41db2d1972
--- /dev/null
+++ b/boost/log/keywords/registration.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/registration.hpp
+ * \author Andrey Semashev
+ * \date 14.03.2009
+ *
+ * The header contains the \c registration keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_REGISTRATION_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_REGISTRATION_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword is used to pass event log source registration mode to a sink backend
+BOOST_PARAMETER_KEYWORD(tag, registration)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_REGISTRATION_HPP_INCLUDED_
diff --git a/boost/log/keywords/rotation_size.hpp b/boost/log/keywords/rotation_size.hpp
new file mode 100644
index 0000000000..f87841edbc
--- /dev/null
+++ b/boost/log/keywords/rotation_size.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/rotation_size.hpp
+ * \author Andrey Semashev
+ * \date 14.03.2009
+ *
+ * The header contains the \c rotation_size keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_ROTATION_SIZE_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_ROTATION_SIZE_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword allows to pass maximum log file size to the file sink
+BOOST_PARAMETER_KEYWORD(tag, rotation_size)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_ROTATION_SIZE_HPP_INCLUDED_
diff --git a/boost/log/keywords/scan_method.hpp b/boost/log/keywords/scan_method.hpp
new file mode 100644
index 0000000000..8a203de53e
--- /dev/null
+++ b/boost/log/keywords/scan_method.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/scan_method.hpp
+ * \author Andrey Semashev
+ * \date 30.06.2009
+ *
+ * The header contains the \c scan_method keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_SCAN_METHOD_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_SCAN_METHOD_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword allows to specify scanning method of the stored log files
+BOOST_PARAMETER_KEYWORD(tag, scan_method)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_SCAN_METHOD_HPP_INCLUDED_
diff --git a/boost/log/keywords/severity.hpp b/boost/log/keywords/severity.hpp
new file mode 100644
index 0000000000..cc40735b6b
--- /dev/null
+++ b/boost/log/keywords/severity.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/severity.hpp
+ * \author Andrey Semashev
+ * \date 14.03.2009
+ *
+ * The header contains the \c severity keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_SEVERITY_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_SEVERITY_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword is used to pass severity level to the severity logger methods
+BOOST_PARAMETER_KEYWORD(tag, severity)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_SEVERITY_HPP_INCLUDED_
diff --git a/boost/log/keywords/start_thread.hpp b/boost/log/keywords/start_thread.hpp
new file mode 100644
index 0000000000..bfe9d7cc19
--- /dev/null
+++ b/boost/log/keywords/start_thread.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/start_thread.hpp
+ * \author Andrey Semashev
+ * \date 14.07.2009
+ *
+ * The header contains the \c start_thread keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_START_THREAD_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_START_THREAD_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword allows enable/disable spawning a dedicated thread in the asynchronous sink frontend
+BOOST_PARAMETER_KEYWORD(tag, start_thread)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_START_THREAD_HPP_INCLUDED_
diff --git a/boost/log/keywords/target.hpp b/boost/log/keywords/target.hpp
new file mode 100644
index 0000000000..00e36fb1e5
--- /dev/null
+++ b/boost/log/keywords/target.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/target.hpp
+ * \author Andrey Semashev
+ * \date 21.03.2009
+ *
+ * The header contains the \c target keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_TARGET_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_TARGET_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword allows to pass the target address to send log records to
+BOOST_PARAMETER_KEYWORD(tag, target)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_TARGET_HPP_INCLUDED_
diff --git a/boost/log/keywords/time_based_rotation.hpp b/boost/log/keywords/time_based_rotation.hpp
new file mode 100644
index 0000000000..7e613dda11
--- /dev/null
+++ b/boost/log/keywords/time_based_rotation.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/time_based_rotation.hpp
+ * \author Andrey Semashev
+ * \date 14.03.2009
+ *
+ * The header contains the \c time_based_rotation keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_TIME_BASED_ROTATION_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_TIME_BASED_ROTATION_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword allows to pass time-based file rotation predicate to the file sink backend
+BOOST_PARAMETER_KEYWORD(tag, time_based_rotation)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_TIME_BASED_ROTATION_HPP_INCLUDED_
diff --git a/boost/log/keywords/use_impl.hpp b/boost/log/keywords/use_impl.hpp
new file mode 100644
index 0000000000..422e4b36ea
--- /dev/null
+++ b/boost/log/keywords/use_impl.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/use_impl.hpp
+ * \author Andrey Semashev
+ * \date 14.03.2009
+ *
+ * The header contains the \c use_impl keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_USE_IMPL_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_USE_IMPL_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword is used to pass the type of backend implementation to use
+BOOST_PARAMETER_KEYWORD(tag, use_impl)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_USE_IMPL_HPP_INCLUDED_
diff --git a/boost/log/sinks.hpp b/boost/log/sinks.hpp
new file mode 100644
index 0000000000..95a4131401
--- /dev/null
+++ b/boost/log/sinks.hpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file sinks.hpp
+ * \author Andrey Semashev
+ * \date 13.07.2009
+ *
+ * This header includes other Boost.Log headers with all sinks.
+ */
+
+#ifndef BOOST_LOG_SINKS_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#include <boost/log/sinks/sink.hpp>
+
+#include <boost/log/sinks/unlocked_frontend.hpp>
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/async_frontend.hpp>
+#include <boost/log/sinks/unbounded_fifo_queue.hpp>
+#include <boost/log/sinks/unbounded_ordering_queue.hpp>
+#include <boost/log/sinks/bounded_fifo_queue.hpp>
+#include <boost/log/sinks/bounded_ordering_queue.hpp>
+#include <boost/log/sinks/drop_on_overflow.hpp>
+#include <boost/log/sinks/block_on_overflow.hpp>
+#endif // !defined(BOOST_LOG_NO_THREADS)
+
+#include <boost/log/sinks/syslog_backend.hpp>
+#include <boost/log/sinks/text_file_backend.hpp>
+#include <boost/log/sinks/text_multifile_backend.hpp>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#ifdef BOOST_WINDOWS
+#include <boost/log/sinks/debug_output_backend.hpp>
+#include <boost/log/sinks/event_log_backend.hpp>
+#endif // BOOST_WINDOWS
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#endif // BOOST_LOG_SINKS_HPP_INCLUDED_
diff --git a/boost/log/sinks/async_frontend.hpp b/boost/log/sinks/async_frontend.hpp
new file mode 100644
index 0000000000..d85421e8a1
--- /dev/null
+++ b/boost/log/sinks/async_frontend.hpp
@@ -0,0 +1,462 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file async_frontend.hpp
+ * \author Andrey Semashev
+ * \date 14.07.2009
+ *
+ * The header contains implementation of asynchronous sink frontend.
+ */
+
+#ifndef BOOST_LOG_SINKS_ASYNC_FRONTEND_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_ASYNC_FRONTEND_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(BOOST_LOG_NO_THREADS)
+#error Boost.Log: Asynchronous sink frontend is only supported in multithreaded environment
+#endif
+
+#include <boost/bind.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared_object.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/recursive_mutex.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/condition_variable.hpp>
+#include <boost/log/exceptions.hpp>
+#include <boost/log/detail/locking_ptr.hpp>
+#include <boost/log/detail/parameter_tools.hpp>
+#include <boost/log/core/record_view.hpp>
+#include <boost/log/sinks/basic_sink_frontend.hpp>
+#include <boost/log/sinks/frontend_requirements.hpp>
+#include <boost/log/sinks/unbounded_fifo_queue.hpp>
+#include <boost/log/keywords/start_thread.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL(z, n, types)\
+ template< BOOST_PP_ENUM_PARAMS(n, typename T) >\
+ explicit asynchronous_sink(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg)) :\
+ base_type(true),\
+ queue_base_type((BOOST_PP_ENUM_PARAMS(n, arg))),\
+ m_pBackend(boost::make_shared< sink_backend_type >(BOOST_PP_ENUM_PARAMS(n, arg))),\
+ m_StopRequested(false),\
+ m_FlushRequested(false)\
+ {\
+ if ((BOOST_PP_ENUM_PARAMS(n, arg))[keywords::start_thread | true])\
+ start_feeding_thread();\
+ }\
+ template< BOOST_PP_ENUM_PARAMS(n, typename T) >\
+ explicit asynchronous_sink(shared_ptr< sink_backend_type > const& backend, BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg)) :\
+ base_type(true),\
+ queue_base_type((BOOST_PP_ENUM_PARAMS(n, arg))),\
+ m_pBackend(backend),\
+ m_StopRequested(false),\
+ m_FlushRequested(false)\
+ {\
+ if ((BOOST_PP_ENUM_PARAMS(n, arg))[keywords::start_thread | true])\
+ start_feeding_thread();\
+ }
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * \brief Asynchronous logging sink frontend
+ *
+ * The frontend starts a separate thread on construction. All logging records are passed
+ * to the backend in this dedicated thread only.
+ */
+template< typename SinkBackendT, typename QueueingStrategyT = unbounded_fifo_queue >
+class asynchronous_sink :
+ public aux::make_sink_frontend_base< SinkBackendT >::type,
+ public QueueingStrategyT
+{
+ typedef typename aux::make_sink_frontend_base< SinkBackendT >::type base_type;
+ typedef QueueingStrategyT queue_base_type;
+
+private:
+ //! Backend synchronization mutex type
+ typedef boost::recursive_mutex backend_mutex_type;
+ //! Frontend synchronization mutex type
+ typedef typename base_type::mutex_type frontend_mutex_type;
+
+ //! A scope guard that implements thread ID management
+ class scoped_thread_id
+ {
+ private:
+ frontend_mutex_type& m_Mutex;
+ condition_variable_any& m_Cond;
+ thread::id& m_ThreadID;
+ bool volatile& m_StopRequested;
+
+ public:
+ //! Initializing constructor
+ scoped_thread_id(frontend_mutex_type& mut, condition_variable_any& cond, thread::id& tid, bool volatile& sr)
+ : m_Mutex(mut), m_Cond(cond), m_ThreadID(tid), m_StopRequested(sr)
+ {
+ lock_guard< frontend_mutex_type > lock(m_Mutex);
+ if (m_ThreadID != thread::id())
+ BOOST_LOG_THROW_DESCR(unexpected_call, "Asynchronous sink frontend already runs a record feeding thread");
+ m_ThreadID = this_thread::get_id();
+ }
+ //! Initializing constructor
+ scoped_thread_id(unique_lock< frontend_mutex_type >& l, condition_variable_any& cond, thread::id& tid, bool volatile& sr)
+ : m_Mutex(*l.mutex()), m_Cond(cond), m_ThreadID(tid), m_StopRequested(sr)
+ {
+ unique_lock< frontend_mutex_type > lock(move(l));
+ if (m_ThreadID != thread::id())
+ BOOST_LOG_THROW_DESCR(unexpected_call, "Asynchronous sink frontend already runs a record feeding thread");
+ m_ThreadID = this_thread::get_id();
+ }
+ //! Destructor
+ ~scoped_thread_id()
+ {
+ try
+ {
+ lock_guard< frontend_mutex_type > lock(m_Mutex);
+ m_StopRequested = false;
+ m_ThreadID = thread::id();
+ m_Cond.notify_all();
+ }
+ catch (...)
+ {
+ }
+ }
+
+ private:
+ scoped_thread_id(scoped_thread_id const&);
+ scoped_thread_id& operator= (scoped_thread_id const&);
+ };
+
+ //! A scope guard that resets a flag on destructor
+ class scoped_flag
+ {
+ private:
+ frontend_mutex_type& m_Mutex;
+ condition_variable_any& m_Cond;
+ volatile bool& m_Flag;
+
+ public:
+ explicit scoped_flag(frontend_mutex_type& mut, condition_variable_any& cond, volatile bool& f) :
+ m_Mutex(mut), m_Cond(cond), m_Flag(f)
+ {
+ }
+ ~scoped_flag()
+ {
+ try
+ {
+ lock_guard< frontend_mutex_type > lock(m_Mutex);
+ m_Flag = false;
+ m_Cond.notify_all();
+ }
+ catch (...)
+ {
+ }
+ }
+
+ private:
+ scoped_flag(scoped_flag const&);
+ scoped_flag& operator= (scoped_flag const&);
+ };
+
+public:
+ //! Sink implementation type
+ typedef SinkBackendT sink_backend_type;
+ //! \cond
+ BOOST_STATIC_ASSERT_MSG((has_requirement< typename sink_backend_type::frontend_requirements, synchronized_feeding >::value), "Asynchronous sink frontend is incompatible with the specified backend: thread synchronization requirements are not met");
+ //! \endcond
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+ //! A pointer type that locks the backend until it's destroyed
+ typedef boost::log::aux::locking_ptr< sink_backend_type, backend_mutex_type > locked_backend_ptr;
+
+#else // BOOST_LOG_DOXYGEN_PASS
+
+ //! A pointer type that locks the backend until it's destroyed
+ typedef implementation_defined locked_backend_ptr;
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+private:
+ //! Synchronization mutex
+ backend_mutex_type m_BackendMutex;
+ //! Pointer to the backend
+ const shared_ptr< sink_backend_type > m_pBackend;
+
+ //! Dedicated record feeding thread
+ thread m_DedicatedFeedingThread;
+ //! Feeding thread ID
+ thread::id m_FeedingThreadID;
+ //! Condition variable to implement blocking operations
+ condition_variable_any m_BlockCond;
+
+ //! The flag indicates that the feeding loop has to be stopped
+ volatile bool m_StopRequested; // TODO: make it a real atomic
+ //! The flag indicates that queue flush has been requested
+ volatile bool m_FlushRequested; // TODO: make it a real atomic
+
+public:
+ /*!
+ * Default constructor. Constructs the sink backend instance.
+ * Requires the backend to be default-constructible.
+ *
+ * \param start_thread If \c true, the frontend creates a thread to feed
+ * log records to the backend. Otherwise no thread is
+ * started and it is assumed that the user will call
+ * either \c run or \c feed_records himself.
+ */
+ asynchronous_sink(bool start_thread = true) :
+ base_type(true),
+ m_pBackend(boost::make_shared< sink_backend_type >()),
+ m_StopRequested(false),
+ m_FlushRequested(false)
+ {
+ if (start_thread)
+ start_feeding_thread();
+ }
+ /*!
+ * Constructor attaches user-constructed backend instance
+ *
+ * \param backend Pointer to the backend instance.
+ * \param start_thread If \c true, the frontend creates a thread to feed
+ * log records to the backend. Otherwise no thread is
+ * started and it is assumed that the user will call
+ * either \c run or \c feed_records himself.
+ *
+ * \pre \a backend is not \c NULL.
+ */
+ explicit asynchronous_sink(shared_ptr< sink_backend_type > const& backend, bool start_thread = true) :
+ base_type(true),
+ m_pBackend(backend),
+ m_StopRequested(false),
+ m_FlushRequested(false)
+ {
+ if (start_thread)
+ start_feeding_thread();
+ }
+
+ // Constructors that pass arbitrary parameters to the backend constructor
+ BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL, ~)
+
+ /*!
+ * Destructor. Implicitly stops the dedicated feeding thread, if one is running.
+ */
+ ~asynchronous_sink()
+ {
+ boost::this_thread::disable_interruption no_interrupts;
+ stop();
+ }
+
+ /*!
+ * Locking accessor to the attached backend
+ */
+ locked_backend_ptr locked_backend()
+ {
+ return locked_backend_ptr(m_pBackend, m_BackendMutex);
+ }
+
+ /*!
+ * Enqueues the log record to the backend
+ */
+ void consume(record_view const& rec)
+ {
+ if (m_FlushRequested)
+ {
+ unique_lock< frontend_mutex_type > lock(base_type::frontend_mutex());
+ // Wait until flush is done
+ while (m_FlushRequested)
+ m_BlockCond.wait(lock);
+ }
+ queue_base_type::enqueue(rec);
+ }
+
+ /*!
+ * The method attempts to pass logging record to the backend
+ */
+ bool try_consume(record_view const& rec)
+ {
+ if (!m_FlushRequested)
+ {
+ return queue_base_type::try_enqueue(rec);
+ }
+ else
+ return false;
+ }
+
+ /*!
+ * The method starts record feeding loop and effectively blocks until either of this happens:
+ *
+ * \li the thread is interrupted due to either standard thread interruption or a call to \c stop
+ * \li an exception is thrown while processing a log record in the backend, and the exception is
+ * not terminated by the exception handler, if one is installed
+ *
+ * \pre The sink frontend must be constructed without spawning a dedicated thread
+ */
+ void run()
+ {
+ // First check that no other thread is running
+ scoped_thread_id guard(base_type::frontend_mutex(), m_BlockCond, m_FeedingThreadID, m_StopRequested);
+
+ // Now start the feeding loop
+ while (true)
+ {
+ do_feed_records();
+ if (!m_StopRequested)
+ {
+ // Block until new record is available
+ record_view rec;
+ if (queue_base_type::dequeue_ready(rec))
+ base_type::feed_record(rec, m_BackendMutex, *m_pBackend);
+ }
+ else
+ break;
+ }
+ }
+
+ /*!
+ * The method softly interrupts record feeding loop. This method must be called when the \c run
+ * method execution has to be interrupted. Unlike regular thread interruption, calling
+ * \c stop will not interrupt the record processing in the middle. Instead, the sink frontend
+ * will attempt to finish its business with the record in progress and return afterwards.
+ * This method can be called either if the sink was created with a dedicated thread,
+ * or if the feeding loop was initiated by user.
+ *
+ * \note Returning from this method does not guarantee that there are no records left buffered
+ * in the sink frontend. It is possible that log records keep coming during and after this
+ * method is called. At some point of execution of this method log records stop being processed,
+ * and all records that come after this point are put into the queue. These records will be
+ * processed upon further calls to \c run or \c feed_records.
+ */
+ void stop()
+ {
+ unique_lock< frontend_mutex_type > lock(base_type::frontend_mutex());
+ if (m_FeedingThreadID != thread::id() || m_DedicatedFeedingThread.joinable())
+ {
+ try
+ {
+ m_StopRequested = true;
+ queue_base_type::interrupt_dequeue();
+ while (m_StopRequested)
+ m_BlockCond.wait(lock);
+ }
+ catch (...)
+ {
+ m_StopRequested = false;
+ throw;
+ }
+
+ lock.unlock();
+ m_DedicatedFeedingThread.join();
+ }
+ }
+
+ /*!
+ * The method feeds log records that may have been buffered to the backend and returns
+ *
+ * \pre The sink frontend must be constructed without spawning a dedicated thread
+ */
+ void feed_records()
+ {
+ // First check that no other thread is running
+ scoped_thread_id guard(base_type::frontend_mutex(), m_BlockCond, m_FeedingThreadID, m_StopRequested);
+
+ // Now start the feeding loop
+ do_feed_records();
+ }
+
+ /*!
+ * The method feeds all log records that may have been buffered to the backend and returns.
+ * Unlike \c feed_records, in case of ordering queueing the method also feeds records
+ * that were enqueued during the ordering window, attempting to empty the queue completely.
+ *
+ * \pre The sink frontend must be constructed without spawning a dedicated thread
+ */
+ void flush()
+ {
+ unique_lock< frontend_mutex_type > lock(base_type::frontend_mutex());
+ if (m_FeedingThreadID != thread::id() || m_DedicatedFeedingThread.joinable())
+ {
+ // There is already a thread feeding records, let it do the job
+ m_FlushRequested = true;
+ queue_base_type::interrupt_dequeue();
+ while (!m_StopRequested && m_FlushRequested)
+ m_BlockCond.wait(lock);
+
+ // The condition may have been signalled when the feeding thread was finishing.
+ // In that case records may not have been flushed, and we do the flush ourselves.
+ if (m_FeedingThreadID != thread::id())
+ return;
+ }
+
+ m_FlushRequested = true;
+
+ // Flush records ourselves. The guard releases the lock.
+ scoped_thread_id guard(lock, m_BlockCond, m_FeedingThreadID, m_StopRequested);
+
+ do_feed_records();
+ }
+
+private:
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ //! The method spawns record feeding thread
+ void start_feeding_thread()
+ {
+ boost::thread(boost::bind(&asynchronous_sink::run, this)).swap(m_DedicatedFeedingThread);
+ }
+
+ //! The record feeding loop
+ void do_feed_records()
+ {
+ while (!m_StopRequested)
+ {
+ record_view rec;
+ bool dequeued = false;
+ if (!m_FlushRequested)
+ dequeued = queue_base_type::try_dequeue_ready(rec);
+ else
+ dequeued = queue_base_type::try_dequeue(rec);
+
+ if (dequeued)
+ base_type::feed_record(rec, m_BackendMutex, *m_pBackend);
+ else
+ break;
+ }
+
+ if (m_FlushRequested)
+ {
+ scoped_flag guard(base_type::frontend_mutex(), m_BlockCond, m_FlushRequested);
+ base_type::flush_backend(m_BackendMutex, *m_pBackend);
+ }
+ }
+#endif // BOOST_LOG_DOXYGEN_PASS
+};
+
+#undef BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SINKS_ASYNC_FRONTEND_HPP_INCLUDED_
diff --git a/boost/log/sinks/attribute_mapping.hpp b/boost/log/sinks/attribute_mapping.hpp
new file mode 100644
index 0000000000..a336265ff4
--- /dev/null
+++ b/boost/log/sinks/attribute_mapping.hpp
@@ -0,0 +1,290 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file attribute_mapping.hpp
+ * \author Andrey Semashev
+ * \date 07.11.2008
+ *
+ * The header contains facilities that are used in different sinks to map attribute values
+ * used throughout the application to values used with the specific native logging API.
+ * These tools are mostly needed to map application severity levels on native levels,
+ * required by OS-specific sink backends.
+ */
+
+#ifndef BOOST_LOG_SINKS_ATTRIBUTE_MAPPING_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_ATTRIBUTE_MAPPING_HPP_INCLUDED_
+
+#include <map>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/tagged_integer.hpp>
+#include <boost/log/core/record_view.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include <boost/log/attributes/value_visitation.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+//! Base class for attribute mapping function objects
+template< typename MappedT >
+struct basic_mapping
+{
+ //! Mapped value type
+ typedef MappedT mapped_type;
+ //! Result type
+ typedef mapped_type result_type;
+};
+
+namespace aux {
+
+ //! Attribute value visitor
+ template< typename MappedT >
+ struct direct_mapping_visitor
+ {
+ typedef void result_type;
+ typedef MappedT mapped_type;
+
+ explicit direct_mapping_visitor(mapped_type& extracted) :
+ m_Extracted(extracted)
+ {
+ }
+ template< typename T >
+ void operator() (T const& val) const
+ {
+ m_Extracted = mapped_type(val);
+ }
+
+ private:
+ mapped_type& m_Extracted;
+ };
+ // Specialization for the tagged integer
+ template< typename IntT, typename TagT >
+ struct direct_mapping_visitor< boost::log::aux::tagged_integer< IntT, TagT > >
+ {
+ typedef void result_type;
+ typedef boost::log::aux::tagged_integer< IntT, TagT > mapped_type;
+
+ explicit direct_mapping_visitor(mapped_type& extracted) :
+ m_Extracted(extracted)
+ {
+ }
+ template< typename T >
+ void operator() (T const& val) const
+ {
+ mapped_type v = { val };
+ m_Extracted = v;
+ }
+
+ private:
+ mapped_type& m_Extracted;
+ };
+
+} // namespace aux
+
+/*!
+ * \brief Straightforward mapping
+ *
+ * This type of mapping assumes that attribute with a particular name always
+ * provides values that map directly onto the native values. The mapping
+ * simply returns the extracted attribute value converted to the native value.
+ */
+template< typename MappedT, typename AttributeValueT = int >
+class basic_direct_mapping :
+ public basic_mapping< MappedT >
+{
+ //! Base type
+ typedef basic_direct_mapping< MappedT > base_type;
+
+public:
+ //! Attribute contained value type
+ typedef AttributeValueT attribute_value_type;
+ //! Mapped value type
+ typedef typename base_type::mapped_type mapped_type;
+
+private:
+ //! Attribute name
+ const attribute_name m_Name;
+ //! Visitor invoker for the attribute value
+ value_visitor_invoker< attribute_value_type > m_Invoker;
+ //! Default native value
+ mapped_type m_DefaultValue;
+
+public:
+ /*!
+ * Constructor
+ *
+ * \param name Attribute name
+ * \param default_value The default native value that is returned if the attribute value is not found
+ */
+ explicit basic_direct_mapping(attribute_name const& name, mapped_type const& default_value) :
+ m_Name(name),
+ m_DefaultValue(default_value)
+ {
+ }
+
+ /*!
+ * Extraction operator
+ *
+ * \param rec A log record to extract value from
+ * \return An extracted attribute value
+ */
+ mapped_type operator() (record_view const& rec) const
+ {
+ mapped_type res = m_DefaultValue;
+ aux::direct_mapping_visitor< mapped_type > vis(res);
+ m_Invoker(m_Name, rec.attribute_values(), vis);
+ return res;
+ }
+};
+
+/*!
+ * \brief Customizable mapping
+ *
+ * The class allows to setup a custom mapping between an attribute and native values.
+ * The mapping should be initialized similarly to the standard \c map container, by using
+ * indexing operator and assignment.
+ *
+ * \note Unlike many other components of the library, exact type of the attribute value
+ * must be specified in the template parameter \c AttributeValueT. Type sequences
+ * are not supported.
+ */
+template< typename MappedT, typename AttributeValueT = int >
+class basic_custom_mapping :
+ public basic_mapping< MappedT >
+{
+ //! Base type
+ typedef basic_mapping< MappedT > base_type;
+
+public:
+ //! Attribute contained value type
+ typedef AttributeValueT attribute_value_type;
+ //! Mapped value type
+ typedef typename base_type::mapped_type mapped_type;
+
+private:
+ //! \cond
+
+ //! Mapping type
+ typedef std::map< attribute_value_type, mapped_type > mapping_type;
+ //! Smart reference class for implementing insertion into the map
+ class reference_proxy;
+ friend class reference_proxy;
+ class reference_proxy
+ {
+ mapping_type& m_Mapping;
+ attribute_value_type m_Key;
+
+ public:
+ //! Constructor
+ reference_proxy(mapping_type& mapping, attribute_value_type const& key) : m_Mapping(mapping), m_Key(key) {}
+ //! Insertion
+ reference_proxy const& operator= (mapped_type const& val) const
+ {
+ m_Mapping[m_Key] = val;
+ return *this;
+ }
+ };
+
+ //! Attribute value visitor
+ struct visitor;
+ friend struct visitor;
+ struct visitor
+ {
+ typedef void result_type;
+
+ visitor(mapping_type const& mapping, mapped_type& extracted) :
+ m_Mapping(mapping),
+ m_Extracted(extracted)
+ {
+ }
+ template< typename T >
+ void operator() (T const& val) const
+ {
+ typename mapping_type::const_iterator it = m_Mapping.find(val);
+ if (it != m_Mapping.end())
+ m_Extracted = it->second;
+ }
+
+ private:
+ mapping_type const& m_Mapping;
+ mapped_type& m_Extracted;
+ };
+
+ //! \endcond
+
+private:
+ //! Attribute name
+ const attribute_name m_Name;
+ //! Visitor invoker for the attribute value
+ value_visitor_invoker< attribute_value_type > m_Invoker;
+ //! Default native value
+ mapped_type m_DefaultValue;
+ //! Conversion mapping
+ mapping_type m_Mapping;
+
+public:
+ /*!
+ * Constructor
+ *
+ * \param name Attribute name
+ * \param default_value The default native value that is returned if the conversion cannot be performed
+ */
+ explicit basic_custom_mapping(attribute_name const& name, mapped_type const& default_value) :
+ m_Name(name),
+ m_DefaultValue(default_value)
+ {
+ }
+ /*!
+ * Extraction operator. Extracts the attribute value and attempts to map it onto
+ * the native value.
+ *
+ * \param rec A log record to extract value from
+ * \return A mapped value, if mapping was successful, or the default value if
+ * mapping did not succeed.
+ */
+ mapped_type operator() (record_view const& rec) const
+ {
+ mapped_type res = m_DefaultValue;
+ visitor vis(m_Mapping, res);
+ m_Invoker(m_Name, rec.attribute_values(), vis);
+ return res;
+ }
+ /*!
+ * Insertion operator
+ *
+ * \param key Attribute value to be mapped
+ * \return An object of unspecified type that allows to insert a new mapping through assignment.
+ * The \a key argument becomes the key attribute value, and the assigned value becomes the
+ * mapped native value.
+ */
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ reference_proxy operator[] (attribute_value_type const& key)
+#else
+ implementation_defined operator[] (attribute_value_type const& key)
+#endif
+ {
+ return reference_proxy(m_Mapping, key);
+ }
+};
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SINKS_ATTRIBUTE_MAPPING_HPP_INCLUDED_
diff --git a/boost/log/sinks/basic_sink_backend.hpp b/boost/log/sinks/basic_sink_backend.hpp
new file mode 100644
index 0000000000..9517bd2803
--- /dev/null
+++ b/boost/log/sinks/basic_sink_backend.hpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file basic_sink_backend.hpp
+ * \author Andrey Semashev
+ * \date 04.11.2007
+ *
+ * The header contains implementation of base classes for sink backends.
+ */
+
+#ifndef BOOST_LOG_SINKS_BASIC_SINK_BACKEND_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_BASIC_SINK_BACKEND_HPP_INCLUDED_
+
+#include <string>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/sinks/frontend_requirements.hpp>
+#include <boost/log/core/record_view.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+/*!
+ * \brief Base class for a logging sink backend
+ *
+ * The \c basic_sink_backend class template defines a number of types that
+ * all sink backends are required to define. All sink backends have to derive from the class.
+ */
+template< typename FrontendRequirementsT >
+struct basic_sink_backend
+{
+ //! Frontend requirements tag
+ typedef FrontendRequirementsT frontend_requirements;
+
+ BOOST_DEFAULTED_FUNCTION(basic_sink_backend(), {})
+
+ BOOST_DELETED_FUNCTION(basic_sink_backend(basic_sink_backend const&))
+ BOOST_DELETED_FUNCTION(basic_sink_backend& operator= (basic_sink_backend const&))
+};
+
+/*!
+ * \brief A base class for a logging sink backend with message formatting support
+ *
+ * The \c basic_formatted_sink_backend class template indicates to the frontend that
+ * the backend requires logging record formatting.
+ *
+ * The class allows to request encoding conversion in case if the sink backend
+ * requires the formatted string in some particular encoding (e.g. if underlying API
+ * supports only narrow or wide characters). In order to perform conversion one
+ * should specify the desired final character type in the \c TargetCharT template
+ * parameter.
+ */
+template<
+ typename CharT,
+ typename FrontendRequirementsT = synchronized_feeding
+>
+struct basic_formatted_sink_backend :
+ public basic_sink_backend<
+ typename combine_requirements< FrontendRequirementsT, formatted_records >::type
+ >
+{
+private:
+ typedef basic_sink_backend<
+ typename combine_requirements< FrontendRequirementsT, formatted_records >::type
+ > base_type;
+
+public:
+ //! Character type
+ typedef CharT char_type;
+ //! Formatted string type
+ typedef std::basic_string< char_type > string_type;
+ //! Frontend requirements
+ typedef typename base_type::frontend_requirements frontend_requirements;
+};
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SINKS_BASIC_SINK_BACKEND_HPP_INCLUDED_
diff --git a/boost/log/sinks/basic_sink_frontend.hpp b/boost/log/sinks/basic_sink_frontend.hpp
new file mode 100644
index 0000000000..3072cae6dc
--- /dev/null
+++ b/boost/log/sinks/basic_sink_frontend.hpp
@@ -0,0 +1,524 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file basic_sink_frontend.hpp
+ * \author Andrey Semashev
+ * \date 14.07.2009
+ *
+ * The header contains implementation of a base class for sink frontends.
+ */
+
+#ifndef BOOST_LOG_SINKS_BASIC_SINK_FRONTEND_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_BASIC_SINK_FRONTEND_HPP_INCLUDED_
+
+#include <boost/mpl/bool.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/cleanup_scope_guard.hpp>
+#include <boost/log/detail/code_conversion.hpp>
+#include <boost/log/detail/attachable_sstream_buf.hpp>
+#include <boost/log/detail/fake_mutex.hpp>
+#include <boost/log/core/record_view.hpp>
+#include <boost/log/sinks/sink.hpp>
+#include <boost/log/sinks/frontend_requirements.hpp>
+#include <boost/log/expressions/filter.hpp>
+#include <boost/log/expressions/formatter.hpp>
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/thread/exceptions.hpp>
+#include <boost/thread/tss.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/log/detail/locks.hpp>
+#include <boost/log/detail/light_rw_mutex.hpp>
+#endif // !defined(BOOST_LOG_NO_THREADS)
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+//! A base class for a logging sink frontend
+class BOOST_LOG_NO_VTABLE basic_sink_frontend :
+ public sink
+{
+ //! Base type
+ typedef sink base_type;
+
+public:
+ //! An exception handler type
+ typedef base_type::exception_handler_type exception_handler_type;
+
+#if !defined(BOOST_LOG_NO_THREADS)
+protected:
+ //! Mutex type
+ typedef boost::log::aux::light_rw_mutex mutex_type;
+
+private:
+ //! Synchronization mutex
+ mutable mutex_type m_Mutex;
+#endif
+
+private:
+ //! Filter
+ filter m_Filter;
+ //! Exception handler
+ exception_handler_type m_ExceptionHandler;
+
+public:
+ /*!
+ * \brief Initializing constructor
+ *
+ * \param cross_thread The flag indicates whether the sink passes log records between different threads
+ */
+ explicit basic_sink_frontend(bool cross_thread) : sink(cross_thread)
+ {
+ }
+
+ /*!
+ * The method sets sink-specific filter functional object
+ */
+ template< typename FunT >
+ void set_filter(FunT const& filter)
+ {
+ BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< mutex_type > lock(m_Mutex);)
+ m_Filter = filter;
+ }
+ /*!
+ * The method resets the filter
+ */
+ void reset_filter()
+ {
+ BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< mutex_type > lock(m_Mutex);)
+ m_Filter.reset();
+ }
+
+ /*!
+ * The method sets an exception handler function
+ */
+ template< typename FunT >
+ void set_exception_handler(FunT const& handler)
+ {
+ BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< mutex_type > lock(m_Mutex);)
+ m_ExceptionHandler = handler;
+ }
+
+ /*!
+ * The method resets the exception handler function
+ */
+ void reset_exception_handler()
+ {
+ BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< mutex_type > lock(m_Mutex);)
+ m_ExceptionHandler.clear();
+ }
+
+ /*!
+ * The method returns \c true if no filter is set or the attribute values pass the filter
+ *
+ * \param attrs A set of attribute values of a logging record
+ */
+ bool will_consume(attribute_value_set const& attrs)
+ {
+ BOOST_LOG_EXPR_IF_MT(boost::log::aux::shared_lock_guard< mutex_type > lock(m_Mutex);)
+ try
+ {
+ return m_Filter(attrs);
+ }
+#if !defined(BOOST_LOG_NO_THREADS)
+ catch (thread_interrupted&)
+ {
+ throw;
+ }
+#endif
+ catch (...)
+ {
+ if (m_ExceptionHandler.empty())
+ throw;
+ m_ExceptionHandler();
+ return false;
+ }
+ }
+
+protected:
+#if !defined(BOOST_LOG_NO_THREADS)
+ //! Returns reference to the frontend mutex
+ mutex_type& frontend_mutex() const { return m_Mutex; }
+#endif
+
+ //! Returns reference to the exception handler
+ exception_handler_type& exception_handler() { return m_ExceptionHandler; }
+ //! Returns reference to the exception handler
+ exception_handler_type const& exception_handler() const { return m_ExceptionHandler; }
+
+ //! Feeds log record to the backend
+ template< typename BackendMutexT, typename BackendT >
+ void feed_record(record_view const& rec, BackendMutexT& backend_mutex, BackendT& backend)
+ {
+ try
+ {
+ BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< BackendMutexT > lock(backend_mutex);)
+ backend.consume(rec);
+ }
+#if !defined(BOOST_LOG_NO_THREADS)
+ catch (thread_interrupted&)
+ {
+ throw;
+ }
+#endif
+ catch (...)
+ {
+ BOOST_LOG_EXPR_IF_MT(boost::log::aux::shared_lock_guard< mutex_type > lock(m_Mutex);)
+ if (m_ExceptionHandler.empty())
+ throw;
+ m_ExceptionHandler();
+ }
+ }
+
+ //! Attempts to feeds log record to the backend, does not block if \a backend_mutex is locked
+ template< typename BackendMutexT, typename BackendT >
+ bool try_feed_record(record_view const& rec, BackendMutexT& backend_mutex, BackendT& backend)
+ {
+#if !defined(BOOST_LOG_NO_THREADS)
+ unique_lock< BackendMutexT > lock;
+ try
+ {
+ unique_lock< BackendMutexT > tmp_lock(backend_mutex, try_to_lock);
+ if (!tmp_lock.owns_lock())
+ return false;
+ lock.swap(tmp_lock);
+ }
+ catch (thread_interrupted&)
+ {
+ throw;
+ }
+ catch (...)
+ {
+ boost::log::aux::shared_lock_guard< mutex_type > frontend_lock(this->frontend_mutex());
+ if (this->exception_handler().empty())
+ throw;
+ this->exception_handler()();
+ return false;
+ }
+#endif
+ // No need to lock anything in the feed_record method
+ boost::log::aux::fake_mutex m;
+ feed_record(rec, m, backend);
+ return true;
+ }
+
+ //! Flushes record buffers in the backend, if one supports it
+ template< typename BackendMutexT, typename BackendT >
+ void flush_backend(BackendMutexT& backend_mutex, BackendT& backend)
+ {
+ typedef typename BackendT::frontend_requirements frontend_requirements;
+ flush_backend_impl(backend_mutex, backend,
+ typename has_requirement< frontend_requirements, flushing >::type());
+ }
+
+private:
+ //! Flushes record buffers in the backend (the actual implementation)
+ template< typename BackendMutexT, typename BackendT >
+ void flush_backend_impl(BackendMutexT& backend_mutex, BackendT& backend, mpl::true_)
+ {
+ try
+ {
+ BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< BackendMutexT > lock(backend_mutex);)
+ backend.flush();
+ }
+#if !defined(BOOST_LOG_NO_THREADS)
+ catch (thread_interrupted&)
+ {
+ throw;
+ }
+#endif
+ catch (...)
+ {
+ BOOST_LOG_EXPR_IF_MT(boost::log::aux::shared_lock_guard< mutex_type > lock(m_Mutex);)
+ if (m_ExceptionHandler.empty())
+ throw;
+ m_ExceptionHandler();
+ }
+ }
+ //! Flushes record buffers in the backend (stub for backends that don't support flushing)
+ template< typename BackendMutexT, typename BackendT >
+ void flush_backend_impl(BackendMutexT&, BackendT&, mpl::false_)
+ {
+ }
+};
+
+//! A base class for a logging sink frontend with formatting support
+template< typename CharT >
+class BOOST_LOG_NO_VTABLE basic_formatting_sink_frontend :
+ public basic_sink_frontend
+{
+ typedef basic_sink_frontend base_type;
+
+public:
+ //! Character type
+ typedef CharT char_type;
+ //! Formatted string type
+ typedef std::basic_string< char_type > string_type;
+
+ //! Formatter function object type
+ typedef basic_formatter< char_type > formatter_type;
+ //! Output stream type
+ typedef typename formatter_type::stream_type stream_type;
+
+#if !defined(BOOST_LOG_NO_THREADS)
+protected:
+ //! Mutex type
+ typedef typename base_type::mutex_type mutex_type;
+#endif
+
+private:
+ struct formatting_context
+ {
+#if !defined(BOOST_LOG_NO_THREADS)
+ //! Object version
+ const unsigned int m_Version;
+#endif
+ //! Formatted log record storage
+ string_type m_FormattedRecord;
+ //! Formatting stream
+ stream_type m_FormattingStream;
+ //! Formatter functor
+ formatter_type m_Formatter;
+
+ formatting_context() :
+#if !defined(BOOST_LOG_NO_THREADS)
+ m_Version(0),
+#endif
+ m_FormattingStream(m_FormattedRecord)
+ {
+ m_FormattingStream.exceptions(std::ios_base::badbit | std::ios_base::failbit);
+ }
+#if !defined(BOOST_LOG_NO_THREADS)
+ formatting_context(unsigned int version, std::locale const& loc, formatter_type const& formatter) :
+ m_Version(version),
+ m_FormattingStream(m_FormattedRecord),
+ m_Formatter(formatter)
+ {
+ m_FormattingStream.exceptions(std::ios_base::badbit | std::ios_base::failbit);
+ m_FormattingStream.imbue(loc);
+ }
+#endif
+ };
+
+private:
+#if !defined(BOOST_LOG_NO_THREADS)
+
+ //! State version
+ volatile unsigned int m_Version;
+
+ //! Formatter functor
+ formatter_type m_Formatter;
+ //! Locale to perform formatting
+ std::locale m_Locale;
+
+ //! Formatting state
+ thread_specific_ptr< formatting_context > m_pContext;
+
+#else
+
+ //! Formatting state
+ formatting_context m_Context;
+
+#endif // !defined(BOOST_LOG_NO_THREADS)
+
+public:
+ /*!
+ * \brief Initializing constructor
+ *
+ * \param cross_thread The flag indicates whether the sink passes log records between different threads
+ */
+ explicit basic_formatting_sink_frontend(bool cross_thread) :
+ basic_sink_frontend(cross_thread)
+#if !defined(BOOST_LOG_NO_THREADS)
+ , m_Version(0)
+#endif
+ {
+ }
+
+ /*!
+ * The method sets sink-specific formatter function object
+ */
+ template< typename FunT >
+ void set_formatter(FunT const& formatter)
+ {
+#if !defined(BOOST_LOG_NO_THREADS)
+ boost::log::aux::exclusive_lock_guard< mutex_type > lock(this->frontend_mutex());
+ m_Formatter = formatter;
+ ++m_Version;
+#else
+ m_Context.m_Formatter = formatter;
+#endif
+ }
+ /*!
+ * The method resets the formatter
+ */
+ void reset_formatter()
+ {
+#if !defined(BOOST_LOG_NO_THREADS)
+ boost::log::aux::exclusive_lock_guard< mutex_type > lock(this->frontend_mutex());
+ m_Formatter.reset();
+ ++m_Version;
+#else
+ m_Context.m_Formatter.reset();
+#endif
+ }
+
+ /*!
+ * The method returns the current locale used for formatting
+ */
+ std::locale getloc() const
+ {
+#if !defined(BOOST_LOG_NO_THREADS)
+ boost::log::aux::exclusive_lock_guard< mutex_type > lock(this->frontend_mutex());
+ return m_Locale;
+#else
+ return m_Context.m_FormattingStream.getloc();
+#endif
+ }
+ /*!
+ * The method sets the locale used for formatting
+ */
+ void imbue(std::locale const& loc)
+ {
+#if !defined(BOOST_LOG_NO_THREADS)
+ boost::log::aux::exclusive_lock_guard< mutex_type > lock(this->frontend_mutex());
+ m_Locale = loc;
+ ++m_Version;
+#else
+ m_Context.m_FormattingStream.imbue(loc);
+#endif
+ }
+
+protected:
+ //! Returns reference to the formatter
+ formatter_type& formatter()
+ {
+#if !defined(BOOST_LOG_NO_THREADS)
+ return m_Formatter;
+#else
+ return m_Context.m_Formatter;
+#endif
+ }
+
+ //! Feeds log record to the backend
+ template< typename BackendMutexT, typename BackendT >
+ void feed_record(record_view const& rec, BackendMutexT& backend_mutex, BackendT& backend)
+ {
+ formatting_context* context;
+
+#if !defined(BOOST_LOG_NO_THREADS)
+ context = m_pContext.get();
+ if (!context || context->m_Version != m_Version)
+ {
+ {
+ boost::log::aux::shared_lock_guard< mutex_type > lock(this->frontend_mutex());
+ context = new formatting_context(m_Version, m_Locale, m_Formatter);
+ }
+ m_pContext.reset(context);
+ }
+#else
+ context = &m_Context;
+#endif
+
+ boost::log::aux::cleanup_guard< stream_type > cleanup1(context->m_FormattingStream);
+ boost::log::aux::cleanup_guard< string_type > cleanup2(context->m_FormattedRecord);
+
+ try
+ {
+ // Perform the formatting
+ context->m_Formatter(rec, context->m_FormattingStream);
+ context->m_FormattingStream.flush();
+
+ // Feed the record
+ BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< BackendMutexT > lock(backend_mutex);)
+ backend.consume(rec, context->m_FormattedRecord);
+ }
+#if !defined(BOOST_LOG_NO_THREADS)
+ catch (thread_interrupted&)
+ {
+ throw;
+ }
+#endif
+ catch (...)
+ {
+ BOOST_LOG_EXPR_IF_MT(boost::log::aux::shared_lock_guard< mutex_type > lock(this->frontend_mutex());)
+ if (this->exception_handler().empty())
+ throw;
+ this->exception_handler()();
+ }
+ }
+
+ //! Attempts to feeds log record to the backend, does not block if \a backend_mutex is locked
+ template< typename BackendMutexT, typename BackendT >
+ bool try_feed_record(record_view const& rec, BackendMutexT& backend_mutex, BackendT& backend)
+ {
+#if !defined(BOOST_LOG_NO_THREADS)
+ unique_lock< BackendMutexT > lock;
+ try
+ {
+ unique_lock< BackendMutexT > tmp_lock(backend_mutex, try_to_lock);
+ if (!tmp_lock.owns_lock())
+ return false;
+ lock.swap(tmp_lock);
+ }
+ catch (thread_interrupted&)
+ {
+ throw;
+ }
+ catch (...)
+ {
+ boost::log::aux::shared_lock_guard< mutex_type > frontend_lock(this->frontend_mutex());
+ if (this->exception_handler().empty())
+ throw;
+ this->exception_handler()();
+ return false;
+ }
+#endif
+ // No need to lock anything in the feed_record method
+ boost::log::aux::fake_mutex m;
+ feed_record(rec, m, backend);
+ return true;
+ }
+};
+
+namespace aux {
+
+ template<
+ typename BackendT,
+ bool RequiresFormattingV = has_requirement<
+ typename BackendT::frontend_requirements,
+ formatted_records
+ >::value
+ >
+ struct make_sink_frontend_base
+ {
+ typedef basic_sink_frontend type;
+ };
+ template< typename BackendT >
+ struct make_sink_frontend_base< BackendT, true >
+ {
+ typedef basic_formatting_sink_frontend< typename BackendT::char_type > type;
+ };
+
+} // namespace aux
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SINKS_BASIC_SINK_FRONTEND_HPP_INCLUDED_
diff --git a/boost/log/sinks/block_on_overflow.hpp b/boost/log/sinks/block_on_overflow.hpp
new file mode 100644
index 0000000000..a23b5ff875
--- /dev/null
+++ b/boost/log/sinks/block_on_overflow.hpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file block_on_overflow.hpp
+ * \author Andrey Semashev
+ * \date 04.01.2012
+ *
+ * The header contains implementation of \c block_on_overflow strategy for handling
+ * queue overflows in bounded queues for the asynchronous sink frontend.
+ */
+
+#ifndef BOOST_LOG_SINKS_BLOCK_ON_OVERFLOW_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_BLOCK_ON_OVERFLOW_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(BOOST_LOG_NO_THREADS)
+#error Boost.Log: This header content is only supported in multithreaded environment
+#endif
+
+#include <boost/intrusive/options.hpp>
+#include <boost/intrusive/list.hpp>
+#include <boost/intrusive/list_hook.hpp>
+#include <boost/thread/condition_variable.hpp>
+#include <boost/log/core/record_view.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+/*!
+ * \brief Blocking strategy for handling log record queue overflows
+ *
+ * This strategy will cause enqueueing threads to block when the
+ * log record queue overflows. The blocked threads will be woken as
+ * soon as there appears free space in the queue, in the same order
+ * they attempted to enqueue records.
+ */
+class block_on_overflow
+{
+#ifndef BOOST_LOG_DOXYGEN_PASS
+private:
+ typedef intrusive::list_base_hook<
+ intrusive::link_mode< intrusive::auto_unlink >
+ > thread_context_hook_t;
+
+ struct thread_context :
+ public thread_context_hook_t
+ {
+ condition_variable cond;
+ bool result;
+
+ thread_context() : result(true) {}
+ };
+
+ typedef intrusive::list<
+ thread_context,
+ intrusive::base_hook< thread_context_hook_t >,
+ intrusive::constant_time_size< false >
+ > thread_contexts;
+
+private:
+ //! Blocked threads
+ thread_contexts m_thread_contexts;
+
+public:
+ /*!
+ * Default constructor.
+ */
+ BOOST_DEFAULTED_FUNCTION(block_on_overflow(), {})
+
+ /*!
+ * This method is called by the queue when overflow is detected.
+ *
+ * \param lock An internal lock that protects the queue
+ *
+ * \retval true Attempt to enqueue the record again.
+ * \retval false Discard the record.
+ */
+ template< typename LockT >
+ bool on_overflow(record_view const&, LockT& lock)
+ {
+ thread_context context;
+ m_thread_contexts.push_back(context);
+ do
+ {
+ context.cond.wait(lock);
+ }
+ while (context.is_linked());
+
+ return context.result;
+ }
+
+ /*!
+ * This method is called by the queue when there appears a free space.
+ * The internal lock protecting the queue is locked when calling this method.
+ */
+ void on_queue_space_available()
+ {
+ if (!m_thread_contexts.empty())
+ {
+ m_thread_contexts.front().cond.notify_one();
+ m_thread_contexts.pop_front();
+ }
+ }
+
+ /*!
+ * This method is called by the queue to interrupt any possible waits in \c on_overflow.
+ * The internal lock protecting the queue is locked when calling this method.
+ */
+ void interrupt()
+ {
+ while (!m_thread_contexts.empty())
+ {
+ thread_context& context = m_thread_contexts.front();
+ context.result = false;
+ context.cond.notify_one();
+ m_thread_contexts.pop_front();
+ }
+ }
+
+ // Copying prohibited
+ BOOST_DELETED_FUNCTION(block_on_overflow(block_on_overflow const&))
+ BOOST_DELETED_FUNCTION(block_on_overflow& operator= (block_on_overflow const&))
+#endif // BOOST_LOG_DOXYGEN_PASS
+};
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SINKS_BLOCK_ON_OVERFLOW_HPP_INCLUDED_
diff --git a/boost/log/sinks/bounded_fifo_queue.hpp b/boost/log/sinks/bounded_fifo_queue.hpp
new file mode 100644
index 0000000000..59b157e259
--- /dev/null
+++ b/boost/log/sinks/bounded_fifo_queue.hpp
@@ -0,0 +1,192 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file bounded_fifo_queue.hpp
+ * \author Andrey Semashev
+ * \date 04.01.2012
+ *
+ * The header contains implementation of bounded FIFO queueing strategy for
+ * the asynchronous sink frontend.
+ */
+
+#ifndef BOOST_LOG_SINKS_BOUNDED_FIFO_QUEUE_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_BOUNDED_FIFO_QUEUE_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(BOOST_LOG_NO_THREADS)
+#error Boost.Log: This header content is only supported in multithreaded environment
+#endif
+
+#include <cstddef>
+#include <queue>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
+#include <boost/log/core/record_view.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+/*!
+ * \brief Bounded FIFO log record queueing strategy
+ *
+ * The \c bounded_fifo_queue class is intended to be used with
+ * the \c asynchronous_sink frontend as a log record queueing strategy.
+ *
+ * This strategy describes log record queueing logic.
+ * The queue has a limited capacity, upon reaching which the enqueue operation will
+ * invoke the overflow handling strategy specified in the \c OverflowStrategyT
+ * template parameter to handle the situation. The library provides overflow handling
+ * strategies for most common cases: \c drop_on_overflow will silently discard the log record,
+ * and \c block_on_overflow will put the enqueueing thread to wait until there is space
+ * in the queue.
+ *
+ * The log record queue imposes no ordering over the queued
+ * elements aside from the order in which they are enqueued.
+ */
+template< std::size_t MaxQueueSizeV, typename OverflowStrategyT >
+class bounded_fifo_queue :
+ private OverflowStrategyT
+{
+private:
+ typedef OverflowStrategyT overflow_strategy;
+ typedef std::queue< record_view > queue_type;
+ typedef boost::mutex mutex_type;
+
+private:
+ //! Synchronization primitive
+ mutex_type m_mutex;
+ //! Condition to block the consuming thread on
+ condition_variable m_cond;
+ //! Log record queue
+ queue_type m_queue;
+ //! Interruption flag
+ bool m_interruption_requested;
+
+protected:
+ //! Default constructor
+ bounded_fifo_queue() : m_interruption_requested(false)
+ {
+ }
+ //! Initializing constructor
+ template< typename ArgsT >
+ explicit bounded_fifo_queue(ArgsT const&) : m_interruption_requested(false)
+ {
+ }
+
+ //! Enqueues log record to the queue
+ void enqueue(record_view const& rec)
+ {
+ unique_lock< mutex_type > lock(m_mutex);
+ std::size_t size = m_queue.size();
+ for (; size >= MaxQueueSizeV; size = m_queue.size())
+ {
+ if (!overflow_strategy::on_overflow(rec, lock))
+ return;
+ }
+
+ m_queue.push(rec);
+ if (size == 0)
+ m_cond.notify_one();
+ }
+
+ //! Attempts to enqueue log record to the queue
+ bool try_enqueue(record_view const& rec)
+ {
+ unique_lock< mutex_type > lock(m_mutex, try_to_lock);
+ if (lock.owns_lock())
+ {
+ const std::size_t size = m_queue.size();
+
+ // Do not invoke the bounding strategy in case of overflow as it may block
+ if (size < MaxQueueSizeV)
+ {
+ m_queue.push(rec);
+ if (size == 0)
+ m_cond.notify_one();
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ //! Attempts to dequeue a log record ready for processing from the queue, does not block if the queue is empty
+ bool try_dequeue_ready(record_view& rec)
+ {
+ return try_dequeue(rec);
+ }
+
+ //! Attempts to dequeue log record from the queue, does not block if the queue is empty
+ bool try_dequeue(record_view& rec)
+ {
+ lock_guard< mutex_type > lock(m_mutex);
+ const std::size_t size = m_queue.size();
+ if (size > 0)
+ {
+ rec.swap(m_queue.front());
+ m_queue.pop();
+ overflow_strategy::on_queue_space_available();
+ return true;
+ }
+
+ return false;
+ }
+
+ //! Dequeues log record from the queue, blocks if the queue is empty
+ bool dequeue_ready(record_view& rec)
+ {
+ unique_lock< mutex_type > lock(m_mutex);
+
+ while (!m_interruption_requested)
+ {
+ const std::size_t size = m_queue.size();
+ if (size > 0)
+ {
+ rec.swap(m_queue.front());
+ m_queue.pop();
+ overflow_strategy::on_queue_space_available();
+ return true;
+ }
+ else
+ {
+ m_cond.wait(lock);
+ }
+ }
+ m_interruption_requested = false;
+
+ return false;
+ }
+
+ //! Wakes a thread possibly blocked in the \c dequeue method
+ void interrupt_dequeue()
+ {
+ lock_guard< mutex_type > lock(m_mutex);
+ m_interruption_requested = true;
+ overflow_strategy::interrupt();
+ m_cond.notify_one();
+ }
+};
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SINKS_BOUNDED_FIFO_QUEUE_HPP_INCLUDED_
diff --git a/boost/log/sinks/bounded_ordering_queue.hpp b/boost/log/sinks/bounded_ordering_queue.hpp
new file mode 100644
index 0000000000..76fe8d6044
--- /dev/null
+++ b/boost/log/sinks/bounded_ordering_queue.hpp
@@ -0,0 +1,262 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file bounded_ordering_queue.hpp
+ * \author Andrey Semashev
+ * \date 06.01.2012
+ *
+ * The header contains implementation of bounded ordering queueing strategy for
+ * the asynchronous sink frontend.
+ */
+
+#ifndef BOOST_LOG_SINKS_BOUNDED_ORDERING_QUEUE_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_BOUNDED_ORDERING_QUEUE_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(BOOST_LOG_NO_THREADS)
+#error Boost.Log: This header content is only supported in multithreaded environment
+#endif
+
+#include <cstddef>
+#include <queue>
+#include <vector>
+#include <boost/cstdint.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
+#include <boost/thread/thread_time.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/log/detail/timestamp.hpp>
+#include <boost/log/detail/enqueued_record.hpp>
+#include <boost/log/keywords/order.hpp>
+#include <boost/log/keywords/ordering_window.hpp>
+#include <boost/log/core/record_view.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+/*!
+ * \brief Bounded ordering log record queueing strategy
+ *
+ * The \c bounded_ordering_queue class is intended to be used with
+ * the \c asynchronous_sink frontend as a log record queueing strategy.
+ *
+ * This strategy provides the following properties to the record queueing mechanism:
+ *
+ * \li The queue has limited capacity specified by the \c MaxQueueSizeV template parameter.
+ * \li Upon reaching the size limit, the queue invokes the overflow handling strategy
+ * specified in the \c OverflowStrategyT template parameter to handle the situation.
+ * The library provides overflow handling strategies for most common cases:
+ * \c drop_on_overflow will silently discard the log record, and \c block_on_overflow
+ * will put the enqueueing thread to wait until there is space in the queue.
+ * \li The queue has a fixed latency window. This means that each log record put
+ * into the queue will normally not be dequeued for a certain period of time.
+ * \li The queue performs stable record ordering within the latency window.
+ * The ordering predicate can be specified in the \c OrderT template parameter.
+ */
+template< typename OrderT, std::size_t MaxQueueSizeV, typename OverflowStrategyT >
+class bounded_ordering_queue :
+ private OverflowStrategyT
+{
+private:
+ typedef OverflowStrategyT overflow_strategy;
+ typedef boost::mutex mutex_type;
+ typedef sinks::aux::enqueued_record enqueued_record;
+
+ typedef std::priority_queue<
+ enqueued_record,
+ std::vector< enqueued_record >,
+ enqueued_record::order< OrderT >
+ > queue_type;
+
+private:
+ //! Ordering window duration, in milliseconds
+ const uint64_t m_ordering_window;
+ //! Synchronization primitive
+ mutex_type m_mutex;
+ //! Condition to block the consuming thread on
+ condition_variable m_cond;
+ //! Log record queue
+ queue_type m_queue;
+ //! Interruption flag
+ bool m_interruption_requested;
+
+public:
+ /*!
+ * Returns ordering window size specified during initialization
+ */
+ posix_time::time_duration get_ordering_window() const
+ {
+ return posix_time::milliseconds(m_ordering_window);
+ }
+
+ /*!
+ * Returns default ordering window size.
+ * The default window size is specific to the operating system thread scheduling mechanism.
+ */
+ static posix_time::time_duration get_default_ordering_window()
+ {
+ // The main idea behind this parameter is that the ordering window should be large enough
+ // to allow the frontend to order records from different threads on an attribute
+ // that contains system time. Thus this value should be:
+ // * No less than the minimum time resolution quant that Boost.DateTime provides on the current OS.
+ // For instance, on Windows it defaults to around 15-16 ms.
+ // * No less than thread switching quant on the current OS. For now 30 ms is large enough window size to
+ // switch threads on any known OS. It can be tuned for other platforms as needed.
+ return posix_time::milliseconds(30);
+ }
+
+protected:
+ //! Initializing constructor
+ template< typename ArgsT >
+ explicit bounded_ordering_queue(ArgsT const& args) :
+ m_ordering_window(args[keywords::ordering_window || &bounded_ordering_queue::get_default_ordering_window].total_milliseconds()),
+ m_queue(args[keywords::order]),
+ m_interruption_requested(false)
+ {
+ }
+
+ //! Enqueues log record to the queue
+ void enqueue(record_view const& rec)
+ {
+ unique_lock< mutex_type > lock(m_mutex);
+ std::size_t size = m_queue.size();
+ for (; size >= MaxQueueSizeV; size = m_queue.size())
+ {
+ if (!overflow_strategy::on_overflow(rec, lock))
+ return;
+ }
+
+ m_queue.push(enqueued_record(rec));
+ if (size == 0)
+ m_cond.notify_one();
+ }
+
+ //! Attempts to enqueue log record to the queue
+ bool try_enqueue(record_view const& rec)
+ {
+ unique_lock< mutex_type > lock(m_mutex, try_to_lock);
+ if (lock.owns_lock())
+ {
+ const std::size_t size = m_queue.size();
+
+ // Do not invoke the bounding strategy in case of overflow as it may block
+ if (size < MaxQueueSizeV)
+ {
+ m_queue.push(enqueued_record(rec));
+ if (size == 0)
+ m_cond.notify_one();
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ //! Attempts to dequeue a log record ready for processing from the queue, does not block if the queue is empty
+ bool try_dequeue_ready(record_view& rec)
+ {
+ lock_guard< mutex_type > lock(m_mutex);
+ const std::size_t size = m_queue.size();
+ if (size > 0)
+ {
+ const boost::log::aux::timestamp now = boost::log::aux::get_timestamp();
+ enqueued_record const& elem = m_queue.top();
+ if (static_cast< uint64_t >((now - elem.m_timestamp).milliseconds()) >= m_ordering_window)
+ {
+ // We got a new element
+ rec = elem.m_record;
+ m_queue.pop();
+ overflow_strategy::on_queue_space_available();
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ //! Attempts to dequeue log record from the queue, does not block if the queue is empty
+ bool try_dequeue(record_view& rec)
+ {
+ lock_guard< mutex_type > lock(m_mutex);
+ const std::size_t size = m_queue.size();
+ if (size > 0)
+ {
+ enqueued_record const& elem = m_queue.top();
+ rec = elem.m_record;
+ m_queue.pop();
+ overflow_strategy::on_queue_space_available();
+ return true;
+ }
+
+ return false;
+ }
+
+ //! Dequeues log record from the queue, blocks if the queue is empty
+ bool dequeue_ready(record_view& rec)
+ {
+ unique_lock< mutex_type > lock(m_mutex);
+
+ while (!m_interruption_requested)
+ {
+ const std::size_t size = m_queue.size();
+ if (size > 0)
+ {
+ const boost::log::aux::timestamp now = boost::log::aux::get_timestamp();
+ enqueued_record const& elem = m_queue.top();
+ const uint64_t difference = (now - elem.m_timestamp).milliseconds();
+ if (difference >= m_ordering_window)
+ {
+ rec = elem.m_record;
+ m_queue.pop();
+ overflow_strategy::on_queue_space_available();
+ return true;
+ }
+ else
+ {
+ // Wait until the element becomes ready to be processed
+ m_cond.timed_wait(lock, posix_time::milliseconds(m_ordering_window - difference));
+ }
+ }
+ else
+ {
+ m_cond.wait(lock);
+ }
+ }
+ m_interruption_requested = false;
+
+ return false;
+ }
+
+ //! Wakes a thread possibly blocked in the \c dequeue method
+ void interrupt_dequeue()
+ {
+ lock_guard< mutex_type > lock(m_mutex);
+ m_interruption_requested = true;
+ overflow_strategy::interrupt();
+ m_cond.notify_one();
+ }
+};
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SINKS_BOUNDED_ORDERING_QUEUE_HPP_INCLUDED_
diff --git a/boost/log/sinks/debug_output_backend.hpp b/boost/log/sinks/debug_output_backend.hpp
new file mode 100644
index 0000000000..034390595a
--- /dev/null
+++ b/boost/log/sinks/debug_output_backend.hpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file debug_output_backend.hpp
+ * \author Andrey Semashev
+ * \date 07.11.2008
+ *
+ * The header contains a logging sink backend that outputs log records to the debugger.
+ */
+
+#ifndef BOOST_LOG_SINKS_DEBUG_OUTPUT_BACKEND_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_DEBUG_OUTPUT_BACKEND_HPP_INCLUDED_
+
+#include <string>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifndef BOOST_LOG_WITHOUT_DEBUG_OUTPUT
+
+#include <boost/log/sinks/basic_sink_backend.hpp>
+#include <boost/log/sinks/frontend_requirements.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include <boost/log/core/record_view.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+/*!
+ * \brief An implementation of a logging sink backend that outputs to the debugger
+ *
+ * The sink uses Windows API in order to write log records as debug messages, if the
+ * application process is run under debugger. The sink backend also provides a specific
+ * filter that allows to check whether the debugger is available and thus elide unnecessary
+ * formatting.
+ */
+template< typename CharT >
+class basic_debug_output_backend :
+ public basic_formatted_sink_backend< CharT, concurrent_feeding >
+{
+ //! Base type
+ typedef basic_formatted_sink_backend< CharT, concurrent_feeding > base_type;
+
+public:
+ //! Character type
+ typedef typename base_type::char_type char_type;
+ //! String type to be used as a message text holder
+ typedef typename base_type::string_type string_type;
+
+public:
+ /*!
+ * Constructor. Initializes the sink backend.
+ */
+ BOOST_LOG_API basic_debug_output_backend();
+ /*!
+ * Destructor
+ */
+ BOOST_LOG_API ~basic_debug_output_backend();
+
+ /*!
+ * The method passes the formatted message to debugger
+ */
+ BOOST_LOG_API void consume(record_view const& rec, string_type const& formatted_message);
+};
+
+#ifdef BOOST_LOG_USE_CHAR
+typedef basic_debug_output_backend< char > debug_output_backend; //!< Convenience typedef for narrow-character logging
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+typedef basic_debug_output_backend< wchar_t > wdebug_output_backend; //!< Convenience typedef for wide-character logging
+#endif
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_WITHOUT_DEBUG_OUTPUT
+
+#endif // BOOST_LOG_SINKS_DEBUG_OUTPUT_BACKEND_HPP_INCLUDED_
diff --git a/boost/log/sinks/drop_on_overflow.hpp b/boost/log/sinks/drop_on_overflow.hpp
new file mode 100644
index 0000000000..cbc2d6370c
--- /dev/null
+++ b/boost/log/sinks/drop_on_overflow.hpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file drop_on_overflow.hpp
+ * \author Andrey Semashev
+ * \date 04.01.2012
+ *
+ * The header contains implementation of \c drop_on_overflow strategy for handling
+ * queue overflows in bounded queues for the asynchronous sink frontend.
+ */
+
+#ifndef BOOST_LOG_SINKS_DROP_ON_OVERFLOW_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_DROP_ON_OVERFLOW_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/core/record_view.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+/*!
+ * \brief Log record dropping strategy
+ *
+ * This strategy will cause log records to be discarded in case of
+ * queue overflow in bounded asynchronous sinks. It should not be used
+ * if losing log records is not acceptable.
+ */
+class drop_on_overflow
+{
+#ifndef BOOST_LOG_DOXYGEN_PASS
+public:
+ /*!
+ * This method is called by the queue when overflow is detected.
+ *
+ * \retval true Attempt to enqueue the record again.
+ * \retval false Discard the record.
+ */
+ template< typename LockT >
+ static bool on_overflow(record_view const&, LockT&)
+ {
+ return false;
+ }
+
+ /*!
+ * This method is called by the queue when there appears a free space.
+ */
+ static void on_queue_space_available()
+ {
+ }
+
+ /*!
+ * This method is called by the queue to interrupt any possible waits in \c on_overflow.
+ */
+ static void interrupt()
+ {
+ }
+#endif // BOOST_LOG_DOXYGEN_PASS
+};
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SINKS_DROP_ON_OVERFLOW_HPP_INCLUDED_
diff --git a/boost/log/sinks/event_log_backend.hpp b/boost/log/sinks/event_log_backend.hpp
new file mode 100644
index 0000000000..5e539e57a9
--- /dev/null
+++ b/boost/log/sinks/event_log_backend.hpp
@@ -0,0 +1,662 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file event_log_backend.hpp
+ * \author Andrey Semashev
+ * \date 07.11.2008
+ *
+ * The header contains a logging sink backend that uses Windows NT event log API
+ * for signaling application events.
+ */
+
+#ifndef BOOST_LOG_SINKS_EVENT_LOG_BACKEND_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_EVENT_LOG_BACKEND_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifndef BOOST_LOG_WITHOUT_EVENT_LOG
+
+#include <map>
+#include <vector>
+#include <string>
+#include <iosfwd>
+#include <boost/filesystem/path.hpp>
+#include <boost/log/detail/light_function.hpp>
+#include <boost/log/detail/parameter_tools.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include <boost/log/keywords/message_file.hpp>
+#include <boost/log/keywords/log_name.hpp>
+#include <boost/log/keywords/log_source.hpp>
+#include <boost/log/keywords/registration.hpp>
+#include <boost/log/keywords/target.hpp>
+#include <boost/log/sinks/basic_sink_backend.hpp>
+#include <boost/log/sinks/frontend_requirements.hpp>
+#include <boost/log/sinks/attribute_mapping.hpp>
+#include <boost/log/sinks/event_log_constants.hpp>
+#include <boost/log/core/record_view.hpp>
+#include <boost/log/expressions/formatter.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+namespace event_log {
+
+ //! Event log source registration modes
+ enum registration_mode
+ {
+ never, //!< Never register event source, even if it's not registered
+ on_demand, //!< Register if the source is not registered yet
+ forced //!< Register always, event if the source is already registered
+ };
+
+ /*!
+ * \brief Straightforward event type mapping
+ *
+ * This type of mapping assumes that attribute with a particular name always
+ * provides values that map directly onto the native event types. The mapping
+ * simply returns the extracted attribute value converted to the native event type.
+ */
+ template< typename AttributeValueT = int >
+ class direct_event_type_mapping :
+ public basic_direct_mapping< event_type, AttributeValueT >
+ {
+ //! Base type
+ typedef basic_direct_mapping< event_type, AttributeValueT > base_type;
+
+ public:
+ /*!
+ * Constructor
+ *
+ * \param name Attribute name
+ */
+ explicit direct_event_type_mapping(attribute_name const& name) :
+ base_type(name, info)
+ {
+ }
+ };
+
+ /*!
+ * \brief Customizable event type mapping
+ *
+ * The class allows to setup a custom mapping between an attribute and native event types.
+ * The mapping should be initialized similarly to the standard \c map container, by using
+ * indexing operator and assignment.
+ */
+ template< typename AttributeValueT = int >
+ class custom_event_type_mapping :
+ public basic_custom_mapping< event_type, AttributeValueT >
+ {
+ //! Base type
+ typedef basic_custom_mapping< event_type, AttributeValueT > base_type;
+
+ public:
+ /*!
+ * Constructor
+ *
+ * \param name Attribute name
+ */
+ explicit custom_event_type_mapping(attribute_name const& name) :
+ base_type(name, info)
+ {
+ }
+ };
+
+ /*!
+ * \brief Straightforward event ID mapping
+ *
+ * This type of mapping assumes that attribute with a particular name always
+ * provides values that map directly onto the event identifiers. The mapping
+ * simply returns the extracted attribute value converted to the event ID.
+ */
+ template< typename AttributeValueT = int >
+ class direct_event_id_mapping :
+ public basic_direct_mapping< event_id, AttributeValueT >
+ {
+ //! Base type
+ typedef basic_direct_mapping< event_id, AttributeValueT > base_type;
+
+ public:
+ /*!
+ * Constructor
+ *
+ * \param name Attribute name
+ */
+ explicit direct_event_id_mapping(attribute_name const& name) :
+ base_type(name, make_event_id(0))
+ {
+ }
+ };
+
+ /*!
+ * \brief Customizable event ID mapping
+ *
+ * The class allows to setup a custom mapping between an attribute and event identifiers.
+ * The mapping should be initialized similarly to the standard \c map container, by using
+ * indexing operator and assignment.
+ */
+ template< typename AttributeValueT = int >
+ class custom_event_id_mapping :
+ public basic_custom_mapping< event_id, AttributeValueT >
+ {
+ //! Base type
+ typedef basic_custom_mapping< event_id, AttributeValueT > base_type;
+
+ public:
+ /*!
+ * Constructor
+ *
+ * \param name Attribute name
+ */
+ explicit custom_event_id_mapping(attribute_name const& name) :
+ base_type(name, make_event_id(0))
+ {
+ }
+ };
+
+ /*!
+ * \brief Straightforward event category mapping
+ *
+ * This type of mapping assumes that attribute with a particular name always
+ * provides values that map directly onto the event categories. The mapping
+ * simply returns the extracted attribute value converted to the event category.
+ */
+ template< typename AttributeValueT = int >
+ class direct_event_category_mapping :
+ public basic_direct_mapping< event_category, AttributeValueT >
+ {
+ //! Base type
+ typedef basic_direct_mapping< event_category, AttributeValueT > base_type;
+
+ public:
+ /*!
+ * Constructor
+ *
+ * \param name Attribute name
+ */
+ explicit direct_event_category_mapping(attribute_name const& name) :
+ base_type(name, make_event_category(0))
+ {
+ }
+ };
+
+ /*!
+ * \brief Customizable event category mapping
+ *
+ * The class allows to setup a custom mapping between an attribute and event categories.
+ * The mapping should be initialized similarly to the standard \c map container, by using
+ * indexing operator and assignment.
+ */
+ template< typename AttributeValueT = int >
+ class custom_event_category_mapping :
+ public basic_custom_mapping< event_category, AttributeValueT >
+ {
+ //! Base type
+ typedef basic_custom_mapping< event_category, AttributeValueT > base_type;
+
+ public:
+ /*!
+ * Constructor
+ *
+ * \param name Attribute name
+ */
+ explicit custom_event_category_mapping(attribute_name const& name) :
+ base_type(name, make_event_category(0))
+ {
+ }
+ };
+
+ /*!
+ * \brief An event composer
+ *
+ * This class is a function object that extracts event identifier from the attribute values set
+ * and formats insertion strings for the particular event. Each insertion string is formatted with
+ * a distinct formatter, which can be created just like regular sinks formatters.
+ *
+ * Before using, the composer must be initialized with the following information:
+ * \li Event identifier extraction logic. One can use \c basic_direct_event_id_mapping or
+ * \c basic_custom_event_id_mapping classes in order to create such extractor and pass it
+ * to the composer constructor.
+ * \li Event identifiers and insertion string formatters. The composer provides the following
+ * syntax to provide this information:
+ *
+ * \code
+ * event_composer comp;
+ * comp[MY_EVENT_ID1] % formatter1 % ... % formatterN;
+ * comp[MY_EVENT_ID2] % formatter1 % ... % formatterN;
+ * ...
+ * \endcode
+ *
+ * The event identifiers in square brackets are provided by the message compiler generated
+ * header (the actual names are specified in the .mc file). The formatters represent
+ * the insertion strings that will be used to replace placeholders in event messages,
+ * thus the number and the order of the formatters must correspond to the message definition.
+ */
+ template< typename CharT >
+ class BOOST_LOG_API basic_event_composer
+ {
+ public:
+ //! Character type
+ typedef CharT char_type;
+ //! String type to be used as a message text holder
+ typedef std::basic_string< char_type > string_type;
+
+ //! Event identifier mapper type
+ typedef boost::log::aux::light_function< event_id (record_view const&) > event_id_mapper_type;
+
+ //! Type of an insertion composer (a formatter)
+ typedef basic_formatter< char_type > formatter_type;
+ //! Type of the composed insertions list
+ typedef std::vector< string_type > insertion_list;
+
+ private:
+ //! \cond
+
+ //! The class that implements formatting of insertion strings
+ class insertion_composer;
+
+ //! Type of the events map
+ typedef std::map< event_id, insertion_composer > event_map;
+
+ //! A smart reference that puts formatters into the composer
+ class event_map_reference;
+ friend class event_map_reference;
+ class event_map_reference
+ {
+ private:
+ //! Event identifier
+ event_id m_ID;
+ //! A reference to the object that created the reference
+ basic_event_composer< char_type >& m_Owner;
+ //! A hint for the owner to optimize insertion
+ insertion_composer* m_Composer;
+
+ public:
+ //! Initializing constructor
+ explicit event_map_reference(event_id id, basic_event_composer< char_type >& owner) :
+ m_ID(id),
+ m_Owner(owner),
+ m_Composer(0)
+ {
+ }
+ //! The operator puts the formatter into the composer
+ template< typename FormatterT >
+ event_map_reference& operator% (FormatterT const& fmt)
+ {
+ m_Composer = m_Owner.add_formatter(m_ID, m_Composer, formatter_type(fmt));
+ return *this;
+ }
+ };
+
+ //! \endcond
+
+ private:
+ //! The mapper that will extract the event identifier
+ event_id_mapper_type m_EventIDMapper;
+ //! The map of event identifiers and their insertion composers
+ event_map m_EventMap;
+
+ public:
+ /*!
+ * Default constructor. Creates an empty map of events.
+ *
+ * \param id_mapper An event identifier mapping function that will be used to extract event ID from attribute values
+ */
+ explicit basic_event_composer(event_id_mapper_type const& id_mapper);
+ /*!
+ * Copy constructor. Performs a deep copy of the object.
+ */
+ basic_event_composer(basic_event_composer const& that);
+ /*!
+ * Destructor
+ */
+ ~basic_event_composer();
+
+ /*!
+ * Assignment. Provides strong exception guarantee.
+ */
+ basic_event_composer& operator= (basic_event_composer that);
+ /*!
+ * Swaps \c *this and \c that objects.
+ */
+ void swap(basic_event_composer& that);
+ /*!
+ * Initiates creation of a new event description. The result of the operator can be used to
+ * add formatters for insertion strings construction. The returned reference type is implementation detail.
+ *
+ * \param id Event identifier.
+ */
+ event_map_reference operator[] (event_id id);
+ /*!
+ * Initiates creation of a new event description. The result of the operator can be used to
+ * add formatters for insertion strings construction. The returned reference type is implementation detail.
+ *
+ * \param id Event identifier.
+ */
+ event_map_reference operator[] (int id);
+ /*!
+ * Event composition operator. Extracts an event identifier from the attribute values by calling event ID mapper.
+ * Then runs all formatters that were registered for the event with the extracted ID. The results of formatting
+ * are returned in the \a insertions parameter.
+ *
+ * \param rec Log record view
+ * \param insertions A sequence of formatted insertion strings
+ * \return An event identifier that was extracted from \c attributes
+ */
+ event_id operator() (record_view const& rec, insertion_list& insertions) const;
+
+ private:
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ //! Adds a formatter to the insertion composers list
+ insertion_composer* add_formatter(event_id id, insertion_composer* composer, formatter_type const& fmt);
+#endif // BOOST_LOG_DOXYGEN_PASS
+ };
+
+#ifdef BOOST_LOG_USE_CHAR
+ typedef basic_event_composer< char > event_composer; //!< Convenience typedef for narrow-character logging
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+ typedef basic_event_composer< wchar_t > wevent_composer; //!< Convenience typedef for wide-character logging
+#endif
+
+} // namespace event_log
+
+/*!
+ * \brief An implementation of a simple logging sink backend that emits events into Windows NT event log
+ *
+ * The sink uses Windows NT 5 (Windows 2000) and later event log API to emit events
+ * to an event log. The sink acts as an event source in terms of the API, it implements all needed resources
+ * and source registration in the Windows registry that is needed for the event delivery.
+ *
+ * The backend performs message text formatting. The composed text is then passed as the first
+ * and only string parameter of the event. The resource embedded into the backend describes the event
+ * so that the parameter is inserted into the event description text, thus making it visible
+ * in the event log.
+ *
+ * The backend allows to customize mapping of application severity levels to the native Windows event types.
+ * This allows to write portable code even if OS-specific sinks, such as this one, are used.
+ *
+ * \note Since the backend registers itself into Windows registry as the resource file that contains
+ * event description, it is important to keep the library binary in a stable place of the filesystem.
+ * Otherwise Windows might not be able to load event resources from the library and display
+ * events correctly.
+ *
+ * \note It is known that Windows is not able to find event resources in the application executable,
+ * which is linked against the static build of the library. Users are advised to use dynamic
+ * builds of the library to solve this problem.
+ */
+template< typename CharT >
+class basic_simple_event_log_backend :
+ public basic_formatted_sink_backend< CharT, concurrent_feeding >
+{
+ //! Base type
+ typedef basic_formatted_sink_backend< CharT, concurrent_feeding > base_type;
+ //! Implementation type
+ struct implementation;
+
+public:
+ //! Character type
+ typedef typename base_type::char_type char_type;
+ //! String type to be used as a message text holder
+ typedef typename base_type::string_type string_type;
+
+ //! Mapper type for the event type
+ typedef boost::log::aux::light_function< event_log::event_type (record_view const&) > event_type_mapper_type;
+
+private:
+ //! Pointer to the backend implementation that hides various types from windows.h
+ implementation* m_pImpl;
+
+public:
+ /*!
+ * Default constructor. Registers event source with name based on the application
+ * executable file name in the Application log. If such a registration is already
+ * present, it is not overridden.
+ */
+ BOOST_LOG_API basic_simple_event_log_backend();
+ /*!
+ * Constructor. Registers event log source with the specified parameters.
+ * The following named parameters are supported:
+ *
+ * \li \c target - Specifies an UNC path to the remote server which log records should be sent to.
+ * The local machine will be used to process log records, if not specified.
+ * \li \c log_name - Specifies the log in which the source should be registered.
+ * The result of \c get_default_log_name is used, if the parameter is not specified.
+ * \li \c log_source - Specifies the source name. The result of \c get_default_source_name
+ * is used, if the parameter is not specified.
+ * \li \c registration - Specifies the event source registration mode in the Windows registry.
+ * Can have values of the \c registration_mode enum. Default value: \c on_demand.
+ *
+ * \param args A set of named parameters.
+ */
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_CALL(basic_simple_event_log_backend, construct)
+#else
+ template< typename... ArgsT >
+ explicit basic_simple_event_log_backend(ArgsT... const& args);
+#endif
+
+ /*!
+ * Destructor. Unregisters event source. The log source description is not removed from the Windows registry.
+ */
+ BOOST_LOG_API ~basic_simple_event_log_backend();
+
+ /*!
+ * The method installs the function object that maps application severity levels to WinAPI event types
+ */
+ BOOST_LOG_API void set_event_type_mapper(event_type_mapper_type const& mapper);
+
+ /*!
+ * \returns Default log name: Application
+ */
+ BOOST_LOG_API static string_type get_default_log_name();
+ /*!
+ * \returns Default log source name that is based on the application executable file name and the sink name
+ */
+ BOOST_LOG_API static string_type get_default_source_name();
+
+ /*!
+ * The method puts the formatted message to the event log
+ */
+ BOOST_LOG_API void consume(record_view const& rec, string_type const& formatted_message);
+
+private:
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ //! Constructs backend implementation
+ template< typename ArgsT >
+ void construct(ArgsT const& args)
+ {
+ construct(
+ args[keywords::target | string_type()],
+ args[keywords::log_name || &basic_simple_event_log_backend::get_default_log_name],
+ args[keywords::log_source || &basic_simple_event_log_backend::get_default_source_name],
+ args[keywords::registration | event_log::on_demand]);
+ }
+ BOOST_LOG_API void construct(
+ string_type const& target,
+ string_type const& log_name,
+ string_type const& source_name,
+ event_log::registration_mode reg_mode);
+#endif // BOOST_LOG_DOXYGEN_PASS
+};
+
+/*!
+ * \brief An implementation of a logging sink backend that emits events into Windows NT event log
+ *
+ * The sink uses Windows NT 5 (Windows 2000) and later event log API to emit events
+ * to an event log. The sink acts as an event source. Unlike \c basic_simple_event_log_backend,
+ * this sink backend allows users to specify the custom event message file and supports
+ * mapping attribute values onto several insertion strings. Although it requires considerably
+ * more scaffolding than the simple backend, this allows to support localizable event descriptions.
+ *
+ * Besides the file name of the module with event resources, the backend provides the following
+ * customizations:
+ * \li Remote server UNC address, log name and source name. These parameters have similar meaning
+ * to \c basic_simple_event_log_backend.
+ * \li Event type and category mappings. These are function object that allow to map attribute
+ * values to the according event parameters. One can use mappings in the \c event_log namespace.
+ * \li Event composer. This function object extracts event identifier and formats string insertions,
+ * that will be used by the API to compose the final event message text.
+ */
+template< typename CharT >
+class basic_event_log_backend :
+ public basic_sink_backend< synchronized_feeding >
+{
+ //! Base type
+ typedef basic_sink_backend< synchronized_feeding > base_type;
+ //! Implementation type
+ struct implementation;
+
+public:
+ //! Character type
+ typedef CharT char_type;
+ //! String type
+ typedef std::basic_string< char_type > string_type;
+ //! Type of the composed insertions list
+ typedef std::vector< string_type > insertion_list;
+
+ //! Mapper type for the event type
+ typedef boost::log::aux::light_function< event_log::event_type (record_view const&) > event_type_mapper_type;
+ //! Mapper type for the event category
+ typedef boost::log::aux::light_function< event_log::event_category (record_view const&) > event_category_mapper_type;
+ //! Event composer type
+ typedef boost::log::aux::light_function< event_log::event_id (record_view const&, insertion_list&) > event_composer_type;
+
+private:
+ //! Pointer to the backend implementation that hides various types from windows.h
+ implementation* m_pImpl;
+
+public:
+ /*!
+ * Constructor. Registers event source with name based on the application
+ * executable file name in the Application log. If such a registration is already
+ * present, it is not overridden.
+ */
+ template< typename T >
+ explicit basic_event_log_backend(std::basic_string< T > const& message_file_name)
+ {
+ construct(keywords::message_file = message_file_name);
+ }
+ /*!
+ * Constructor. Registers event source with name based on the application
+ * executable file name in the Application log. If such a registration is already
+ * present, it is not overridden.
+ */
+ explicit basic_event_log_backend(filesystem::path const& message_file_name)
+ {
+ construct(keywords::message_file = message_file_name);
+ }
+ /*!
+ * Constructor. Registers event log source with the specified parameters.
+ * The following named parameters are supported:
+ *
+ * \li \c message_file - Specifies the file name that contains resources that
+ * describe events and categories.
+ * \li \c target - Specifies an UNC path to the remote server to which log records should be sent to.
+ * The local machine will be used to process log records, if not specified.
+ * \li \c log_name - Specifies the log in which the source should be registered.
+ * The result of \c get_default_log_name is used, if the parameter is not specified.
+ * \li \c log_source - Specifies the source name. The result of \c get_default_source_name
+ * is used, if the parameter is not specified.
+ * \li \c registration - Specifies the event source registration mode in the Windows registry.
+ * Can have values of the \c registration_mode enum. Default value: \c on_demand.
+ *
+ * \param args A set of named parameters.
+ */
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_CALL(basic_event_log_backend, construct)
+#else
+ template< typename... ArgsT >
+ explicit basic_event_log_backend(ArgsT... const& args);
+#endif
+
+ /*!
+ * Destructor. Unregisters event source. The log source description is not removed from the Windows registry.
+ */
+ BOOST_LOG_API ~basic_event_log_backend();
+
+ /*!
+ * The method creates an event in the event log
+ *
+ * \param rec Log record to consume
+ */
+ BOOST_LOG_API void consume(record_view const& rec);
+
+ /*!
+ * The method installs the function object that maps application severity levels to WinAPI event types
+ */
+ BOOST_LOG_API void set_event_type_mapper(event_type_mapper_type const& mapper);
+
+ /*!
+ * The method installs the function object that extracts event category from attribute values
+ */
+ BOOST_LOG_API void set_event_category_mapper(event_category_mapper_type const& mapper);
+
+ /*!
+ * The method installs the function object that extracts event identifier from the attributes and creates
+ * insertion strings that will replace placeholders in the event message.
+ */
+ BOOST_LOG_API void set_event_composer(event_composer_type const& composer);
+
+ /*!
+ * \returns Default log name: Application
+ */
+ BOOST_LOG_API static string_type get_default_log_name();
+ /*!
+ * \returns Default log source name that is based on the application executable file name and the sink name
+ */
+ BOOST_LOG_API static string_type get_default_source_name();
+
+private:
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ //! Constructs backend implementation
+ template< typename ArgsT >
+ void construct(ArgsT const& args)
+ {
+ construct(
+ filesystem::path(args[keywords::message_file]),
+ args[keywords::target | string_type()],
+ args[keywords::log_name || &basic_event_log_backend::get_default_log_name],
+ args[keywords::log_source || &basic_event_log_backend::get_default_source_name],
+ args[keywords::registration | event_log::on_demand]);
+ }
+ BOOST_LOG_API void construct(
+ filesystem::path const& message_file_name,
+ string_type const& target,
+ string_type const& log_name,
+ string_type const& source_name,
+ event_log::registration_mode reg_mode);
+#endif // BOOST_LOG_DOXYGEN_PASS
+};
+
+#ifdef BOOST_LOG_USE_CHAR
+typedef basic_simple_event_log_backend< char > simple_event_log_backend; //!< Convenience typedef for narrow-character logging
+typedef basic_event_log_backend< char > event_log_backend; //!< Convenience typedef for narrow-character logging
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+typedef basic_simple_event_log_backend< wchar_t > wsimple_event_log_backend; //!< Convenience typedef for wide-character logging
+typedef basic_event_log_backend< wchar_t > wevent_log_backend; //!< Convenience typedef for wide-character logging
+#endif
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_WITHOUT_EVENT_LOG
+
+#endif // BOOST_LOG_SINKS_EVENT_LOG_BACKEND_HPP_INCLUDED_
diff --git a/boost/log/sinks/event_log_constants.hpp b/boost/log/sinks/event_log_constants.hpp
new file mode 100644
index 0000000000..e6c361a420
--- /dev/null
+++ b/boost/log/sinks/event_log_constants.hpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file event_log_constants.hpp
+ * \author Andrey Semashev
+ * \date 07.11.2008
+ *
+ * The header contains definition of constants related to Windows NT Event Log API.
+ * The constants can be used in other places without the event log backend.
+ */
+
+#ifndef BOOST_LOG_SINKS_EVENT_LOG_CONSTANTS_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_EVENT_LOG_CONSTANTS_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifndef BOOST_LOG_WITHOUT_EVENT_LOG
+
+#include <boost/log/detail/tagged_integer.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+namespace event_log {
+
+ struct event_id_tag;
+ //! A tagged integral type that represents event identifier for the Windows API
+ typedef boost::log::aux::tagged_integer< unsigned int, event_id_tag > event_id;
+ /*!
+ * The function constructs event identifier from an integer
+ */
+ inline event_id make_event_id(unsigned int id)
+ {
+ event_id iden = { id };
+ return iden;
+ }
+
+ struct event_category_tag;
+ //! A tagged integral type that represents event category for the Windows API
+ typedef boost::log::aux::tagged_integer< unsigned short, event_category_tag > event_category;
+ /*!
+ * The function constructs event category from an integer
+ */
+ inline event_category make_event_category(unsigned short cat)
+ {
+ event_category category = { cat };
+ return category;
+ }
+
+ //! Windows event types
+ enum event_type
+ {
+ success = 0, //!< Equivalent to EVENTLOG_SUCCESS
+ info = 4, //!< Equivalent to EVENTLOG_INFORMATION_TYPE
+ warning = 2, //!< Equivalent to EVENTLOG_WARNING_TYPE
+ error = 1 //!< Equivalent to EVENTLOG_ERROR_TYPE
+ };
+
+ /*!
+ * The function constructs log record level from an integer
+ */
+ BOOST_LOG_API event_type make_event_type(unsigned short lev);
+
+} // namespace event_log
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_WITHOUT_EVENT_LOG
+
+#endif // BOOST_LOG_SINKS_EVENT_LOG_CONSTANTS_HPP_INCLUDED_
diff --git a/boost/log/sinks/frontend_requirements.hpp b/boost/log/sinks/frontend_requirements.hpp
new file mode 100644
index 0000000000..086b023b29
--- /dev/null
+++ b/boost/log/sinks/frontend_requirements.hpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file sinks/frontend_requirements.hpp
+ * \author Andrey Semashev
+ * \date 22.04.2007
+ *
+ * The header contains definition of requirement tags that sink backend may declare
+ * with regard to frontends. These requirements ensure that a backend will not
+ * be used with an incompatible frontend.
+ */
+
+#ifndef BOOST_LOG_SINKS_FRONTEND_REQUIREMENTS_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_FRONTEND_REQUIREMENTS_HPP_INCLUDED_
+
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/mpl/placeholders.hpp>
+#include <boost/mpl/inherit.hpp>
+#include <boost/mpl/inherit_linearly.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifndef BOOST_LOG_COMBINE_REQUIREMENTS_LIMIT
+//! The macro specifies the maximum number of requirements that can be combined with the \c combine_requirements metafunction
+#define BOOST_LOG_COMBINE_REQUIREMENTS_LIMIT 5
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+/*!
+ * The sink backend expects pre-synchronized calls, all needed synchronization is implemented
+ * in the frontend (IOW, only one thread is feeding records to the backend concurrently, but
+ * it is possible for several threads to write sequentially). Note that if a frontend supports
+ * synchronized record feeding, it will also report capable of concurrent record feeding.
+ */
+struct synchronized_feeding {};
+
+#if !defined(BOOST_LOG_NO_THREADS)
+
+/*!
+ * The sink backend ensures all needed synchronization, it is capable to handle multithreaded calls
+ */
+struct concurrent_feeding : synchronized_feeding {};
+
+#else // !defined(BOOST_LOG_NO_THREADS)
+
+// If multithreading is disabled, threading models become redundant
+typedef synchronized_feeding concurrent_feeding;
+
+#endif // !defined(BOOST_LOG_NO_THREADS)
+
+/*!
+ * The sink backend requires the frontend to perform log record formatting before feeding
+ */
+struct formatted_records {};
+
+/*!
+ * The sink backend supports flushing
+ */
+struct flushing {};
+
+#ifdef BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * The metafunction combines multiple requirement tags into one type. The resulting type will
+ * satisfy all specified requirements (i.e. \c has_requirement metafunction will return positive result).
+ */
+template< typename... RequirementsT >
+struct combine_requirements;
+
+#else
+
+template< BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_LOG_COMBINE_REQUIREMENTS_LIMIT, typename ReqT, mpl::na) >
+struct combine_requirements :
+ mpl::inherit_linearly<
+ mpl::vector< BOOST_PP_ENUM_PARAMS(BOOST_LOG_COMBINE_REQUIREMENTS_LIMIT, ReqT) >,
+ mpl::inherit2< mpl::_1, mpl::_2 >
+ >
+{
+};
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * A helper metafunction to check if a requirement is satisfied. The \c TestedT template argument
+ * should be the type combining one or several requirements and \c RequiredT is the requirement
+ * to test against. The metafunction will yield a positive result if \c TestedT supports \c RequiredT.
+ */
+template< typename TestedT, typename RequiredT >
+struct has_requirement :
+ public is_base_of< RequiredT, TestedT >
+{
+};
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SINKS_FRONTEND_REQUIREMENTS_HPP_INCLUDED_
diff --git a/boost/log/sinks/sink.hpp b/boost/log/sinks/sink.hpp
new file mode 100644
index 0000000000..516957d44b
--- /dev/null
+++ b/boost/log/sinks/sink.hpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file sink.hpp
+ * \author Andrey Semashev
+ * \date 22.04.2007
+ *
+ * The header contains an interface declaration for all sinks. This interface is used by the
+ * logging core to feed log records to sinks.
+ */
+
+#ifndef BOOST_LOG_SINKS_SINK_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_SINK_HPP_INCLUDED_
+
+#include <string>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/light_function.hpp>
+#include <boost/log/core/record_view.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+//! A base class for a logging sink frontend
+class BOOST_LOG_NO_VTABLE sink
+{
+public:
+ //! An exception handler type
+ typedef boost::log::aux::light_function< void () > exception_handler_type;
+
+private:
+ //! The flag indicates that the sink passes log records across thread boundaries
+ const bool m_cross_thread;
+
+public:
+ /*!
+ * Default constructor
+ */
+ explicit sink(bool cross_thread) : m_cross_thread(cross_thread)
+ {
+ }
+
+ /*!
+ * Virtual destructor
+ */
+ virtual ~sink() {}
+
+ /*!
+ * The method returns \c true if no filter is set or the attribute values pass the filter
+ *
+ * \param attributes A set of attribute values of a logging record
+ */
+ virtual bool will_consume(attribute_value_set const& attributes) = 0;
+
+ /*!
+ * The method puts logging record to the sink
+ *
+ * \param rec Logging record to consume
+ */
+ virtual void consume(record_view const& rec) = 0;
+
+ /*!
+ * The method attempts to put logging record to the sink. The method may be used by the
+ * core in order to determine the most efficient order of sinks to feed records to in
+ * case of heavy contention. Sink implementations may implement try/backoff logic in
+ * order to improve overall logging throughput.
+ *
+ * \param rec Logging record to consume
+ * \return \c true, if the record was consumed, \c false, if not.
+ */
+ virtual bool try_consume(record_view const& rec)
+ {
+ consume(rec);
+ return true;
+ }
+
+ /*!
+ * The method performs flushing of any internal buffers that may hold log records. The method
+ * may take considerable time to complete and may block both the calling thread and threads
+ * attempting to put new records into the sink while this call is in progress.
+ */
+ virtual void flush() = 0;
+
+ /*!
+ * The method indicates that the sink passes log records between different threads. This information is
+ * needed by the logging core to detach log records from all thread-specific resources before passing it
+ * to the sink.
+ */
+ bool is_cross_thread() const BOOST_NOEXCEPT { return m_cross_thread; }
+
+ BOOST_DELETED_FUNCTION(sink(sink const&))
+ BOOST_DELETED_FUNCTION(sink& operator= (sink const&))
+};
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SINKS_SINK_HPP_INCLUDED_
diff --git a/boost/log/sinks/sync_frontend.hpp b/boost/log/sinks/sync_frontend.hpp
new file mode 100644
index 0000000000..146cc9dc44
--- /dev/null
+++ b/boost/log/sinks/sync_frontend.hpp
@@ -0,0 +1,166 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file sync_frontend.hpp
+ * \author Andrey Semashev
+ * \date 14.07.2009
+ *
+ * The header contains implementation of synchronous sink frontend.
+ */
+
+#ifndef BOOST_LOG_SINKS_SYNC_FRONTEND_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_SYNC_FRONTEND_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(BOOST_LOG_NO_THREADS)
+#error Boost.Log: Synchronous sink frontend is only supported in multithreaded environment
+#endif
+
+#include <boost/static_assert.hpp>
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared_object.hpp>
+#include <boost/thread/recursive_mutex.hpp>
+#include <boost/log/detail/locking_ptr.hpp>
+#include <boost/log/detail/parameter_tools.hpp>
+#include <boost/log/core/record_view.hpp>
+#include <boost/log/sinks/basic_sink_frontend.hpp>
+#include <boost/log/sinks/frontend_requirements.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL(z, n, data)\
+ template< BOOST_PP_ENUM_PARAMS(n, typename T) >\
+ explicit synchronous_sink(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg)) :\
+ base_type(false),\
+ m_pBackend(boost::make_shared< sink_backend_type >(BOOST_PP_ENUM_PARAMS(n, arg))) {}
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * \brief Synchronous logging sink frontend
+ *
+ * The sink frontend serializes threads before passing logging records to the backend
+ */
+template< typename SinkBackendT >
+class synchronous_sink :
+ public aux::make_sink_frontend_base< SinkBackendT >::type
+{
+ typedef typename aux::make_sink_frontend_base< SinkBackendT >::type base_type;
+
+private:
+ //! Synchronization mutex type
+ typedef boost::recursive_mutex backend_mutex_type;
+
+public:
+ //! Sink implementation type
+ typedef SinkBackendT sink_backend_type;
+ //! \cond
+ BOOST_STATIC_ASSERT_MSG((has_requirement< typename sink_backend_type::frontend_requirements, synchronized_feeding >::value), "Synchronous sink frontend is incompatible with the specified backend: thread synchronization requirements are not met");
+ //! \endcond
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+ //! A pointer type that locks the backend until it's destroyed
+ typedef boost::log::aux::locking_ptr< sink_backend_type, backend_mutex_type > locked_backend_ptr;
+
+#else // BOOST_LOG_DOXYGEN_PASS
+
+ //! A pointer type that locks the backend until it's destroyed
+ typedef implementation_defined locked_backend_ptr;
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+private:
+ //! Synchronization mutex
+ backend_mutex_type m_BackendMutex;
+ //! Pointer to the backend
+ const shared_ptr< sink_backend_type > m_pBackend;
+
+public:
+ /*!
+ * Default constructor. Constructs the sink backend instance.
+ * Requires the backend to be default-constructible.
+ */
+ synchronous_sink() :
+ base_type(false),
+ m_pBackend(boost::make_shared< sink_backend_type >())
+ {
+ }
+ /*!
+ * Constructor attaches user-constructed backend instance
+ *
+ * \param backend Pointer to the backend instance
+ *
+ * \pre \a backend is not \c NULL.
+ */
+ explicit synchronous_sink(shared_ptr< sink_backend_type > const& backend) :
+ base_type(false),
+ m_pBackend(backend)
+ {
+ }
+
+ // Constructors that pass arbitrary parameters to the backend constructor
+ BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL, ~)
+
+ /*!
+ * Locking accessor to the attached backend
+ */
+ locked_backend_ptr locked_backend()
+ {
+ return locked_backend_ptr(m_pBackend, m_BackendMutex);
+ }
+
+ /*!
+ * Passes the log record to the backend
+ */
+ void consume(record_view const& rec)
+ {
+ base_type::feed_record(rec, m_BackendMutex, *m_pBackend);
+ }
+
+ /*!
+ * The method attempts to pass logging record to the backend
+ */
+ bool try_consume(record_view const& rec)
+ {
+ return base_type::try_feed_record(rec, m_BackendMutex, *m_pBackend);
+ }
+
+ /*!
+ * The method performs flushing of any internal buffers that may hold log records. The method
+ * may take considerable time to complete and may block both the calling thread and threads
+ * attempting to put new records into the sink while this call is in progress.
+ */
+ void flush()
+ {
+ base_type::flush_backend(m_BackendMutex, *m_pBackend);
+ }
+};
+
+#undef BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SINKS_SYNC_FRONTEND_HPP_INCLUDED_
diff --git a/boost/log/sinks/syslog_backend.hpp b/boost/log/sinks/syslog_backend.hpp
new file mode 100644
index 0000000000..35cfb540ab
--- /dev/null
+++ b/boost/log/sinks/syslog_backend.hpp
@@ -0,0 +1,288 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file syslog_backend.hpp
+ * \author Andrey Semashev
+ * \date 08.01.2008
+ *
+ * The header contains implementation of a Syslog sink backend along with its setup facilities.
+ */
+
+#ifndef BOOST_LOG_SINKS_SYSLOG_BACKEND_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_SYSLOG_BACKEND_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifndef BOOST_LOG_WITHOUT_SYSLOG
+
+#include <string>
+#include <boost/log/detail/asio_fwd.hpp>
+#include <boost/log/detail/light_function.hpp>
+#include <boost/log/detail/parameter_tools.hpp>
+#include <boost/log/sinks/basic_sink_backend.hpp>
+#include <boost/log/sinks/syslog_constants.hpp>
+#include <boost/log/sinks/attribute_mapping.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include <boost/log/keywords/facility.hpp>
+#include <boost/log/keywords/use_impl.hpp>
+#include <boost/log/keywords/ident.hpp>
+#include <boost/log/keywords/ip_version.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+//! Supported IP protocol versions
+enum ip_versions
+{
+ v4,
+ v6
+};
+
+namespace syslog {
+
+ //! The enumeration defined the possible implementation types for the syslog backend
+ enum impl_types
+ {
+#ifdef BOOST_LOG_USE_NATIVE_SYSLOG
+ native = 0 //!< Use native syslog API
+#ifndef BOOST_LOG_NO_ASIO
+ ,
+#endif
+#endif
+#ifndef BOOST_LOG_NO_ASIO
+ udp_socket_based = 1 //!< Use UDP sockets, according to RFC3164
+#endif
+ };
+
+ /*!
+ * \brief Straightforward severity level mapping
+ *
+ * This type of mapping assumes that attribute with a particular name always
+ * provides values that map directly onto the Syslog levels. The mapping
+ * simply returns the extracted attribute value converted to the Syslog severity level.
+ */
+ template< typename AttributeValueT = int >
+ class direct_severity_mapping :
+ public basic_direct_mapping< level, AttributeValueT >
+ {
+ //! Base type
+ typedef basic_direct_mapping< level, AttributeValueT > base_type;
+
+ public:
+ /*!
+ * Constructor
+ *
+ * \param name Attribute name
+ */
+ explicit direct_severity_mapping(attribute_name const& name) :
+ base_type(name, info)
+ {
+ }
+ };
+
+ /*!
+ * \brief Customizable severity level mapping
+ *
+ * The class allows to setup a custom mapping between an attribute and Syslog severity levels.
+ * The mapping should be initialized similarly to the standard \c map container, by using
+ * indexing operator and assignment.
+ */
+ template< typename AttributeValueT = int >
+ class custom_severity_mapping :
+ public basic_custom_mapping< level, AttributeValueT >
+ {
+ //! Base type
+ typedef basic_custom_mapping< level, AttributeValueT > base_type;
+
+ public:
+ /*!
+ * Constructor
+ *
+ * \param name Attribute name
+ */
+ explicit custom_severity_mapping(attribute_name const& name) :
+ base_type(name, info)
+ {
+ }
+ };
+
+} // namespace syslog
+
+/*!
+ * \brief An implementation of a syslog sink backend
+ *
+ * The backend provides support for the syslog protocol, defined in RFC3164.
+ * The backend sends log records to a remote host via UDP. The host name can
+ * be specified by calling the \c set_target_address method. By default log
+ * records will be sent to localhost:514. The local address can be specified
+ * as well, by calling the \c set_local_address method. By default syslog
+ * packets will be sent from any local address available.
+ *
+ * It is safe to create several sink backends with the same local addresses -
+ * the backends within the process will share the same socket. The same applies
+ * to different processes that use the syslog backends to send records from
+ * the same socket. However, it is not guaranteed to work if some third party
+ * facility is using the socket.
+ *
+ * On systems with native syslog implementation it may be preferable to utilize
+ * the POSIX syslog API instead of direct socket management in order to bypass
+ * possible security limitations that may be in action. To do so one has to pass
+ * the <tt>use_impl = native</tt> to the backend constructor. Note, however,
+ * that in that case you will only have one chance to specify syslog facility and
+ * process identification string - on the first native syslog backend construction.
+ * Other native syslog backends will ignore these parameters.
+ * Obviously, the \c set_local_address and \c set_target_address
+ * methods have no effect for native backends. Using <tt>use_impl = native</tt>
+ * on platforms with no native support for POSIX syslog API will have no effect.
+ */
+class syslog_backend :
+ public basic_formatted_sink_backend< char >
+{
+ //! Base type
+ typedef basic_formatted_sink_backend< char > base_type;
+ //! Implementation type
+ struct implementation;
+
+public:
+ //! Character type
+ typedef base_type::char_type char_type;
+ //! String type that is used to pass message test
+ typedef base_type::string_type string_type;
+
+ //! Syslog severity level mapper type
+ typedef boost::log::aux::light_function< syslog::level (record_view const&) > severity_mapper_type;
+
+private:
+ //! Pointer to the implementation
+ implementation* m_pImpl;
+
+public:
+ /*!
+ * Constructor. Creates a UDP socket-based backend with <tt>syslog::user</tt> facility code.
+ * IPv4 protocol will be used.
+ */
+ BOOST_LOG_API syslog_backend();
+ /*!
+ * Constructor. Creates a sink backend with the specified named parameters.
+ * The following named parameters are supported:
+ *
+ * \li \c facility - Specifies the facility code. If not specified, <tt>syslog::user</tt> will be used.
+ * \li \c use_impl - Specifies the backend implementation. Can be one of:
+ * \li \c native - Use the native syslog API, if available. If no native API
+ * is available, it is equivalent to \c udp_socket_based.
+ * \li \c udp_socket_based - Use the UDP socket-based implementation, conforming to
+ * RFC3164 protocol specification. This is the default.
+ * \li \c ip_version - Specifies IP protocol version to use, in case if socket-based implementation
+ * is used. Can be either \c v4 (the default one) or \c v6.
+ * \li \c ident - Process identification string. This parameter is only supported by native syslog implementation.
+ */
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_CALL(syslog_backend, construct)
+#else
+ template< typename... ArgsT >
+ explicit syslog_backend(ArgsT... const& args);
+#endif
+
+ /*!
+ * Destructor
+ */
+ BOOST_LOG_API ~syslog_backend();
+
+ /*!
+ * The method installs the function object that maps application severity levels to syslog levels
+ */
+ BOOST_LOG_API void set_severity_mapper(severity_mapper_type const& mapper);
+
+#if !defined(BOOST_LOG_NO_ASIO)
+
+ /*!
+ * The method sets the local host name which log records will be sent from. The host name
+ * is resolved to obtain the final IP address.
+ *
+ * \note Does not have effect if the backend was constructed to use native syslog API
+ *
+ * \param addr The local address
+ * \param port The local port number
+ */
+ BOOST_LOG_API void set_local_address(std::string const& addr, unsigned short port = 514);
+ /*!
+ * The method sets the local address which log records will be sent from.
+ *
+ * \note Does not have effect if the backend was constructed to use native syslog API
+ *
+ * \param addr The local address
+ * \param port The local port number
+ */
+ BOOST_LOG_API void set_local_address(boost::asio::ip::address const& addr, unsigned short port = 514);
+
+ /*!
+ * The method sets the remote host name where log records will be sent to. The host name
+ * is resolved to obtain the final IP address.
+ *
+ * \note Does not have effect if the backend was constructed to use native syslog API
+ *
+ * \param addr The remote host address
+ * \param port The port number on the remote host
+ */
+ BOOST_LOG_API void set_target_address(std::string const& addr, unsigned short port = 514);
+ /*!
+ * The method sets the address of the remote host where log records will be sent to.
+ *
+ * \note Does not have effect if the backend was constructed to use native syslog API
+ *
+ * \param addr The remote host address
+ * \param port The port number on the remote host
+ */
+ BOOST_LOG_API void set_target_address(boost::asio::ip::address const& addr, unsigned short port = 514);
+
+#endif // !defined(BOOST_LOG_NO_ASIO)
+
+ /*!
+ * The method passes the formatted message to the syslog API or sends to a syslog server
+ */
+ BOOST_LOG_API void consume(record_view const& rec, string_type const& formatted_message);
+
+private:
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ //! The method creates the backend implementation
+ template< typename ArgsT >
+ void construct(ArgsT const& args)
+ {
+ construct(
+ args[keywords::facility | syslog::user],
+#if !defined(BOOST_LOG_NO_ASIO)
+ args[keywords::use_impl | syslog::udp_socket_based],
+#else
+ args[keywords::use_impl | syslog::native],
+#endif
+ args[keywords::ip_version | v4],
+ args[keywords::ident | std::string()]);
+ }
+ BOOST_LOG_API void construct(
+ syslog::facility facility, syslog::impl_types use_impl, ip_versions ip_version, std::string const& ident);
+#endif // BOOST_LOG_DOXYGEN_PASS
+};
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_WITHOUT_SYSLOG
+
+#endif // BOOST_LOG_SINKS_SYSLOG_BACKEND_HPP_INCLUDED_
diff --git a/boost/log/sinks/syslog_constants.hpp b/boost/log/sinks/syslog_constants.hpp
new file mode 100644
index 0000000000..d320ebbbac
--- /dev/null
+++ b/boost/log/sinks/syslog_constants.hpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file syslog_constants.hpp
+ * \author Andrey Semashev
+ * \date 08.01.2008
+ *
+ * The header contains definition of constants related to Syslog API. The constants can be
+ * used in other places without the Syslog backend.
+ */
+
+#ifndef BOOST_LOG_SINKS_SYSLOG_CONSTANTS_HPP_INCLUDED_HPP_
+#define BOOST_LOG_SINKS_SYSLOG_CONSTANTS_HPP_INCLUDED_HPP_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifndef BOOST_LOG_WITHOUT_SYSLOG
+
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+namespace syslog {
+
+ //! Syslog record levels
+ enum level
+ {
+ emergency = 0, //!< Equivalent to LOG_EMERG in syslog API
+ alert = 1, //!< Equivalent to LOG_ALERT in syslog API
+ critical = 2, //!< Equivalent to LOG_CRIT in syslog API
+ error = 3, //!< Equivalent to LOG_ERROR in syslog API
+ warning = 4, //!< Equivalent to LOG_WARNING in syslog API
+ notice = 5, //!< Equivalent to LOG_NOTICE in syslog API
+ info = 6, //!< Equivalent to LOG_INFO in syslog API
+ debug = 7 //!< Equivalent to LOG_DEBUG in syslog API
+ };
+
+ /*!
+ * The function constructs log record level from an integer
+ */
+ BOOST_LOG_API level make_level(int lev);
+
+ //! Syslog facility codes
+ enum facility
+ {
+ kernel = 0 * 8, //!< Kernel messages
+ user = 1 * 8, //!< User-level messages. Equivalent to LOG_USER in syslog API.
+ mail = 2 * 8, //!< Mail system messages. Equivalent to LOG_MAIL in syslog API.
+ daemon = 3 * 8, //!< System daemons. Equivalent to LOG_DAEMON in syslog API.
+ security0 = 4 * 8, //!< Security/authorization messages
+ syslogd = 5 * 8, //!< Messages from the syslogd daemon. Equivalent to LOG_SYSLOG in syslog API.
+ printer = 6 * 8, //!< Line printer subsystem. Equivalent to LOG_LPR in syslog API.
+ news = 7 * 8, //!< Network news subsystem. Equivalent to LOG_NEWS in syslog API.
+ uucp = 8 * 8, //!< Messages from UUCP subsystem. Equivalent to LOG_UUCP in syslog API.
+ clock0 = 9 * 8, //!< Messages from the clock daemon
+ security1 = 10 * 8, //!< Security/authorization messages
+ ftp = 11 * 8, //!< Messages from FTP daemon
+ ntp = 12 * 8, //!< Messages from NTP daemon
+ log_audit = 13 * 8, //!< Security/authorization messages
+ log_alert = 14 * 8, //!< Security/authorization messages
+ clock1 = 15 * 8, //!< Messages from the clock daemon
+ local0 = 16 * 8, //!< For local use. Equivalent to LOG_LOCAL0 in syslog API
+ local1 = 17 * 8, //!< For local use. Equivalent to LOG_LOCAL1 in syslog API
+ local2 = 18 * 8, //!< For local use. Equivalent to LOG_LOCAL2 in syslog API
+ local3 = 19 * 8, //!< For local use. Equivalent to LOG_LOCAL3 in syslog API
+ local4 = 20 * 8, //!< For local use. Equivalent to LOG_LOCAL4 in syslog API
+ local5 = 21 * 8, //!< For local use. Equivalent to LOG_LOCAL5 in syslog API
+ local6 = 22 * 8, //!< For local use. Equivalent to LOG_LOCAL6 in syslog API
+ local7 = 23 * 8 //!< For local use. Equivalent to LOG_LOCAL7 in syslog API
+ };
+
+ /*!
+ * The function constructs log source facility from an integer
+ */
+ BOOST_LOG_API facility make_facility(int fac);
+
+} // namespace syslog
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_WITHOUT_SYSLOG
+
+#endif // BOOST_LOG_SINKS_SYSLOG_CONSTANTS_HPP_INCLUDED_HPP_
diff --git a/boost/log/sinks/text_file_backend.hpp b/boost/log/sinks/text_file_backend.hpp
new file mode 100644
index 0000000000..1d39a633c0
--- /dev/null
+++ b/boost/log/sinks/text_file_backend.hpp
@@ -0,0 +1,539 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file text_file_backend.hpp
+ * \author Andrey Semashev
+ * \date 09.06.2009
+ *
+ * The header contains implementation of a text file sink backend.
+ */
+
+#ifndef BOOST_LOG_SINKS_TEXT_FILE_BACKEND_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_TEXT_FILE_BACKEND_HPP_INCLUDED_
+
+#include <ios>
+#include <string>
+#include <ostream>
+#include <boost/limits.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/date_time/date_defs.hpp>
+#include <boost/date_time/special_defs.hpp>
+#include <boost/date_time/gregorian/greg_day.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/log/keywords/max_size.hpp>
+#include <boost/log/keywords/min_free_space.hpp>
+#include <boost/log/keywords/target.hpp>
+#include <boost/log/keywords/file_name.hpp>
+#include <boost/log/keywords/open_mode.hpp>
+#include <boost/log/keywords/auto_flush.hpp>
+#include <boost/log/keywords/rotation_size.hpp>
+#include <boost/log/keywords/time_based_rotation.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/light_function.hpp>
+#include <boost/log/detail/parameter_tools.hpp>
+#include <boost/log/sinks/basic_sink_backend.hpp>
+#include <boost/log/sinks/frontend_requirements.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+namespace file {
+
+//! The enumeration of the stored files scan methods
+enum scan_method
+{
+ no_scan, //!< Don't scan for stored files
+ scan_matching, //!< Scan for files with names matching the specified mask
+ scan_all //!< Scan for all files in the directory
+};
+
+/*!
+ * \brief Base class for file collectors
+ *
+ * All file collectors, supported by file sink backends, should inherit this class.
+ */
+struct BOOST_LOG_NO_VTABLE collector
+{
+ /*!
+ * Default constructor
+ */
+ BOOST_DEFAULTED_FUNCTION(collector(), {})
+
+ /*!
+ * Virtual destructor
+ */
+ virtual ~collector() {}
+
+ /*!
+ * The function stores the specified file in the storage. May lead to an older file
+ * deletion and a long file moving.
+ *
+ * \param src_path The name of the file to be stored
+ */
+ virtual void store_file(filesystem::path const& src_path) = 0;
+
+ /*!
+ * Scans the target directory for the files that have already been stored. The found
+ * files are added to the collector in order to be tracked and erased, if needed.
+ *
+ * The function may scan the directory in two ways: it will either consider every
+ * file in the directory a log file, or will only consider files with names that
+ * match the specified pattern. The pattern may contain the following placeholders:
+ *
+ * \li %y, %Y, %m, %d - date components, in Boost.DateTime meaning.
+ * \li %H, %M, %S, %f - time components, in Boost.DateTime meaning.
+ * \li %N - numeric file counter. May also contain width specification
+ * in printf-compatible form (e.g. %5N). The resulting number will always be zero-filled.
+ * \li %% - a percent sign
+ *
+ * All other placeholders are not supported.
+ *
+ * \param method The method of scanning. If \c no_scan is specified, the call has no effect.
+ * \param pattern The file name pattern if \a method is \c scan_matching. Otherwise the parameter
+ * is not used.
+ * \param counter If not \c NULL and \a method is \c scan_matching, the method suggests initial value
+ * of a file counter that may be used in the file name pattern. The parameter
+ * is not used otherwise.
+ * \return The number of found files.
+ *
+ * \note In case if \a method is \c scan_matching the effect of this function is highly dependent
+ * on the \a pattern definition. It is recommended to choose patterns with easily
+ * distinguished placeholders (i.e. having delimiters between them). Otherwise
+ * either some files can be mistakenly found or not found, which in turn may lead
+ * to an incorrect file deletion.
+ */
+ virtual uintmax_t scan_for_files(
+ scan_method method, filesystem::path const& pattern = filesystem::path(), unsigned int* counter = 0) = 0;
+
+ BOOST_DELETED_FUNCTION(collector(collector const&))
+ BOOST_DELETED_FUNCTION(collector& operator= (collector const&))
+};
+
+namespace aux {
+
+ //! Creates and returns a file collector with the specified parameters
+ BOOST_LOG_API shared_ptr< collector > make_collector(
+ filesystem::path const& target_dir,
+ uintmax_t max_size,
+ uintmax_t min_free_space
+ );
+ template< typename ArgsT >
+ inline shared_ptr< collector > make_collector(ArgsT const& args)
+ {
+ return aux::make_collector(
+ filesystem::path(args[keywords::target]),
+ args[keywords::max_size | (std::numeric_limits< uintmax_t >::max)()],
+ args[keywords::min_free_space | static_cast< uintmax_t >(0)]);
+ }
+
+} // namespace aux
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+template< typename T1 >
+inline shared_ptr< collector > make_collector(T1 const& a1)
+{
+ return aux::make_collector(a1);
+}
+template< typename T1, typename T2 >
+inline shared_ptr< collector > make_collector(T1 const& a1, T2 const& a2)
+{
+ return aux::make_collector((a1, a2));
+}
+template< typename T1, typename T2, typename T3 >
+inline shared_ptr< collector > make_collector(T1 const& a1, T2 const& a2, T3 const& a3)
+{
+ return aux::make_collector((a1, a2, a3));
+}
+
+#else
+
+/*!
+ * The function creates a file collector for the specified target directory.
+ * Each target directory is managed by a single file collector, so if
+ * this function is called several times for the same directory,
+ * it will return a reference to the same file collector. It is safe
+ * to use the same collector in different sinks, even in a multithreaded
+ * application.
+ *
+ * One can specify certain restrictions for the stored files, such as
+ * maximum total size or minimum free space left in the target directory.
+ * If any of the specified restrictions is not met, the oldest stored file
+ * is deleted. If the same collector is requested more than once with
+ * different restrictions, the collector will act according to the most strict
+ * combination of all specified restrictions.
+ *
+ * The following named parameters are supported:
+ *
+ * \li \c target - Specifies the target directory for the files being stored in. This parameter
+ * is mandatory.
+ * \li \c max_size - Specifies the maximum total size, in bytes, of stored files that the collector
+ * will try not to exceed. If the size exceeds this threshold the oldest file(s) is
+ * deleted to free space. Note that the threshold may be exceeded if the size of
+ * individual files exceed the \c max_size value. The threshold is not maintained,
+ * if not specified.
+ * \li \c min_free_space - Specifies the minimum free space, in bytes, in the target directory that
+ * the collector tries to maintain. If the threshold is exceeded, the oldest
+ * file(s) is deleted to free space. The threshold is not maintained, if not
+ * specified.
+ *
+ * \return The file collector.
+ */
+template< typename... ArgsT >
+shared_ptr< collector > make_collector(ArgsT... const& args);
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * The class represents the time point of log file rotation. One can specify one of three
+ * types of time point based rotation:
+ *
+ * \li rotation takes place every day, at the specified time
+ * \li rotation takes place on the specified day of every week, at the specified time
+ * \li rotation takes place on the specified day of every month, at the specified time
+ *
+ * The time points are considered to be local time.
+ */
+class rotation_at_time_point
+{
+public:
+ typedef bool result_type;
+
+private:
+ enum day_kind
+ {
+ not_specified,
+ weekday,
+ monthday
+ };
+
+ day_kind m_DayKind : 2;
+ unsigned char m_Day : 6;
+ unsigned char m_Hour, m_Minute, m_Second;
+
+ mutable posix_time::ptime m_Previous;
+
+public:
+ /*!
+ * Creates a rotation time point of every day at the specified time
+ *
+ * \param hour The rotation hour, should be within 0 and 23
+ * \param minute The rotation minute, should be within 0 and 59
+ * \param second The rotation second, should be within 0 and 59
+ */
+ BOOST_LOG_API explicit rotation_at_time_point(unsigned char hour, unsigned char minute, unsigned char second);
+
+ /*!
+ * Creates a rotation time point of each specified weekday at the specified time
+ *
+ * \param wday The weekday of the rotation
+ * \param hour The rotation hour, should be within 0 and 23
+ * \param minute The rotation minute, should be within 0 and 59
+ * \param second The rotation second, should be within 0 and 59
+ */
+ BOOST_LOG_API explicit rotation_at_time_point(
+ date_time::weekdays wday,
+ unsigned char hour = 0,
+ unsigned char minute = 0,
+ unsigned char second = 0);
+
+ /*!
+ * Creates a rotation time point of each specified day of month at the specified time
+ *
+ * \param mday The monthday of the rotation, should be within 1 and 31
+ * \param hour The rotation hour, should be within 0 and 23
+ * \param minute The rotation minute, should be within 0 and 59
+ * \param second The rotation second, should be within 0 and 59
+ */
+ BOOST_LOG_API explicit rotation_at_time_point(
+ gregorian::greg_day mday,
+ unsigned char hour = 0,
+ unsigned char minute = 0,
+ unsigned char second = 0);
+
+ /*!
+ * Checks if it's time to rotate the file
+ */
+ BOOST_LOG_API bool operator() () const;
+};
+
+/*!
+ * The class represents the time interval of log file rotation. The log file will be rotated
+ * after the specified time interval has passed.
+ */
+class rotation_at_time_interval
+{
+public:
+ typedef bool result_type;
+
+private:
+ posix_time::time_duration m_Interval;
+ mutable posix_time::ptime m_Previous;
+
+public:
+ /*!
+ * Creates a rotation time interval of the specified duration
+ *
+ * \param interval The interval of the rotation, should be no less than 1 second
+ */
+ explicit rotation_at_time_interval(posix_time::time_duration const& interval) :
+ m_Interval(interval)
+ {
+ BOOST_ASSERT(!interval.is_special());
+ BOOST_ASSERT(interval.total_seconds() > 0);
+ }
+
+ /*!
+ * Checks if it's time to rotate the file
+ */
+ BOOST_LOG_API bool operator() () const;
+};
+
+} // namespace file
+
+
+/*!
+ * \brief An implementation of a text file logging sink backend
+ *
+ * The sink backend puts formatted log records to a text file.
+ * The sink supports file rotation and advanced file control, such as
+ * size and file count restriction.
+ */
+class text_file_backend :
+ public basic_formatted_sink_backend<
+ char,
+ combine_requirements< synchronized_feeding, flushing >::type
+ >
+{
+ //! Base type
+ typedef basic_formatted_sink_backend<
+ char,
+ combine_requirements< synchronized_feeding, flushing >::type
+ > base_type;
+
+public:
+ //! Character type
+ typedef base_type::char_type char_type;
+ //! String type to be used as a message text holder
+ typedef base_type::string_type string_type;
+ //! Stream type
+ typedef std::basic_ostream< char_type > stream_type;
+
+ //! File open handler
+ typedef boost::log::aux::light_function< void (stream_type&) > open_handler_type;
+ //! File close handler
+ typedef boost::log::aux::light_function< void (stream_type&) > close_handler_type;
+
+ //! Predicate that defines the time-based condition for file rotation
+ typedef boost::log::aux::light_function< bool () > time_based_rotation_predicate;
+
+private:
+ //! \cond
+
+ struct implementation;
+ implementation* m_pImpl;
+
+ //! \endcond
+
+public:
+ /*!
+ * Default constructor. The constructed sink backend uses default values of all the parameters.
+ */
+ BOOST_LOG_API text_file_backend();
+
+ /*!
+ * Constructor. Creates a sink backend with the specified named parameters.
+ * The following named parameters are supported:
+ *
+ * \li \c file_name - Specifies the file name pattern where logs are actually written to. The pattern may
+ * contain directory and file name portions, but only the file name may contain
+ * placeholders. The backend supports Boost.DateTime placeholders for injecting
+ * current time and date into the file name. Also, an additional %N placeholder is
+ * supported, it will be replaced with an integral increasing file counter. The placeholder
+ * may also contain width specification in the printf-compatible form (e.g. %5N). The
+ * printed file counter will always be zero-filled. If \c file_name is not specified,
+ * pattern "%5N.log" will be used.
+ * \li \c open_mode - File open mode. The mode should be presented in form of mask compatible to
+ * <tt>std::ios_base::openmode</tt>. If not specified, <tt>trunc | out</tt> will be used.
+ * \li \c rotation_size - Specifies the approximate size, in characters written, of the temporary file
+ * upon which the file is passed to the file collector. Note the size does
+ * not count any possible character conversions that may take place during
+ * writing to the file. If not specified, the file won't be rotated upon reaching
+ * any size.
+ * \li \c time_based_rotation - Specifies the predicate for time-based file rotation.
+ * No time-based file rotations will be performed, if not specified.
+ * \li \c auto_flush - Specifies a flag, whether or not to automatically flush the file after each
+ * written log record. By default, is \c false.
+ *
+ * \note Read the caution note regarding file name pattern in the <tt>sinks::file::collector::scan_for_files</tt>
+ * documentation.
+ */
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_CALL(text_file_backend, construct)
+#else
+ template< typename... ArgsT >
+ explicit text_file_backend(ArgsT... const& args);
+#endif
+
+ /*!
+ * Destructor
+ */
+ BOOST_LOG_API ~text_file_backend();
+
+ /*!
+ * The method sets file name wildcard for the files being written. The wildcard supports
+ * date and time injection into the file name.
+ *
+ * \param pattern The name pattern for the file being written.
+ */
+ template< typename PathT >
+ void set_file_name_pattern(PathT const& pattern)
+ {
+ set_file_name_pattern_internal(filesystem::path(pattern));
+ }
+
+ /*!
+ * The method sets the file open mode
+ *
+ * \param mode File open mode
+ */
+ BOOST_LOG_API void set_open_mode(std::ios_base::openmode mode);
+
+ /*!
+ * The method sets the log file collector function. The function is called
+ * on file rotation and is being passed the written file name.
+ *
+ * \param collector The file collector function object
+ */
+ BOOST_LOG_API void set_file_collector(shared_ptr< file::collector > const& collector);
+
+ /*!
+ * The method sets file opening handler. The handler will be called every time
+ * the backend opens a new temporary file. The handler may write a header to the
+ * opened file in order to maintain file validity.
+ *
+ * \param handler The file open handler function object
+ */
+ BOOST_LOG_API void set_open_handler(open_handler_type const& handler);
+
+ /*!
+ * The method sets file closing handler. The handler will be called every time
+ * the backend closes a temporary file. The handler may write a footer to the
+ * opened file in order to maintain file validity.
+ *
+ * \param handler The file close handler function object
+ */
+ BOOST_LOG_API void set_close_handler(close_handler_type const& handler);
+
+ /*!
+ * The method sets maximum file size. When the size is reached, file rotation is performed.
+ *
+ * \note The size does not count any possible character translations that may happen in
+ * the underlying API. This may result in greater actual sizes of the written files.
+ *
+ * \param size The maximum file size, in characters.
+ */
+ BOOST_LOG_API void set_rotation_size(uintmax_t size);
+
+ /*!
+ * The method sets the predicate that defines the time-based condition for file rotation.
+ *
+ * \note The rotation always occurs on writing a log record, so the rotation is
+ * not strictly bound to the specified condition.
+ *
+ * \param predicate The predicate that defines the time-based condition for file rotation.
+ * If empty, no time-based rotation will take place.
+ */
+ BOOST_LOG_API void set_time_based_rotation(time_based_rotation_predicate const& predicate);
+
+ /*!
+ * Sets the flag to automatically flush buffers of all attached streams after each log record
+ */
+ BOOST_LOG_API void auto_flush(bool f = true);
+
+ /*!
+ * Performs scanning of the target directory for log files that may have been left from
+ * previous runs of the application. The found files are considered by the file collector
+ * as if they were rotated.
+ *
+ * The file scan can be performed in two ways: either all files in the target directory will
+ * be considered as log files, or only those files that satisfy the file name pattern.
+ * See documentation on <tt>sinks::file::collector::scan_for_files</tt> for more information.
+ *
+ * \pre File collector and the proper file name pattern have already been set.
+ *
+ * \param method File scanning method
+ * \param update_counter If \c true and \a method is \c scan_matching, the method attempts
+ * to update the internal file counter according to the found files. The counter
+ * is unaffected otherwise.
+ * \return The number of files found.
+ *
+ * \note The method essentially delegates to the same-named function of the file collector.
+ */
+ BOOST_LOG_API uintmax_t scan_for_files(
+ file::scan_method method = file::scan_matching, bool update_counter = true);
+
+ /*!
+ * The method writes the message to the sink
+ */
+ BOOST_LOG_API void consume(record_view const& rec, string_type const& formatted_message);
+
+ /*!
+ * The method flushes the currently open log file
+ */
+ BOOST_LOG_API void flush();
+
+ /*!
+ * The method rotates the file
+ */
+ BOOST_LOG_API void rotate_file();
+
+private:
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ //! Constructor implementation
+ template< typename ArgsT >
+ void construct(ArgsT const& args)
+ {
+ construct(
+ filesystem::path(args[keywords::file_name | filesystem::path()]),
+ args[keywords::open_mode | (std::ios_base::trunc | std::ios_base::out)],
+ args[keywords::rotation_size | (std::numeric_limits< uintmax_t >::max)()],
+ args[keywords::time_based_rotation | time_based_rotation_predicate()],
+ args[keywords::auto_flush | false]);
+ }
+ //! Constructor implementation
+ BOOST_LOG_API void construct(
+ filesystem::path const& pattern,
+ std::ios_base::openmode mode,
+ uintmax_t rotation_size,
+ time_based_rotation_predicate const& time_based_rotation,
+ bool auto_flush);
+
+ //! The method sets file name mask
+ BOOST_LOG_API void set_file_name_pattern_internal(filesystem::path const& pattern);
+#endif // BOOST_LOG_DOXYGEN_PASS
+};
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SINKS_TEXT_FILE_BACKEND_HPP_INCLUDED_
diff --git a/boost/log/sinks/text_multifile_backend.hpp b/boost/log/sinks/text_multifile_backend.hpp
new file mode 100644
index 0000000000..d2f897892e
--- /dev/null
+++ b/boost/log/sinks/text_multifile_backend.hpp
@@ -0,0 +1,201 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file text_multifile_backend.hpp
+ * \author Andrey Semashev
+ * \date 09.06.2009
+ *
+ * The header contains implementation of a text multi-file sink backend.
+ */
+
+#ifndef BOOST_LOG_SINKS_TEXT_MULTIFILE_BACKEND_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_TEXT_MULTIFILE_BACKEND_HPP_INCLUDED_
+
+#include <ios>
+#include <string>
+#include <locale>
+#include <ostream>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/light_function.hpp>
+#include <boost/log/detail/cleanup_scope_guard.hpp>
+#include <boost/log/sinks/basic_sink_backend.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+namespace file {
+
+ /*!
+ * An adapter class that allows to use regular formatters as file name generators.
+ */
+ template< typename FormatterT >
+ class file_name_composer_adapter
+ {
+ public:
+ //! Functor result type
+ typedef filesystem::path result_type;
+ //! File name character type
+ typedef result_type::string_type::value_type native_char_type;
+ //! The adopted formatter type
+ typedef FormatterT formatter_type;
+ //! Formatting stream type
+ typedef basic_formatting_ostream< native_char_type > stream_type;
+
+ private:
+ //! The adopted formatter
+ formatter_type m_Formatter;
+ //! Formatted file name storage
+ mutable result_type::string_type m_FileName;
+ //! Formatting stream
+ mutable stream_type m_FormattingStream;
+
+ public:
+ /*!
+ * Initializing constructor
+ */
+ explicit file_name_composer_adapter(formatter_type const& formatter, std::locale const& loc = std::locale()) :
+ m_Formatter(formatter),
+ m_FormattingStream(m_FileName)
+ {
+ m_FormattingStream.exceptions(std::ios_base::badbit | std::ios_base::failbit);
+ m_FormattingStream.imbue(loc);
+ }
+ /*!
+ * Copy constructor
+ */
+ file_name_composer_adapter(file_name_composer_adapter const& that) :
+ m_Formatter(that.m_Formatter),
+ m_FormattingStream(m_FileName)
+ {
+ m_FormattingStream.exceptions(std::ios_base::badbit | std::ios_base::failbit);
+ m_FormattingStream.imbue(that.m_FormattingStream.getloc());
+ }
+ /*!
+ * Assignment
+ */
+ file_name_composer_adapter& operator= (file_name_composer_adapter const& that)
+ {
+ m_Formatter = that.m_Formatter;
+ return *this;
+ }
+
+ /*!
+ * The operator generates a file name based on the log record
+ */
+ result_type operator() (record_view const& rec) const
+ {
+ boost::log::aux::cleanup_guard< stream_type > cleanup1(m_FormattingStream);
+ boost::log::aux::cleanup_guard< result_type::string_type > cleanup2(m_FileName);
+
+ m_Formatter(rec, m_FormattingStream);
+ m_FormattingStream.flush();
+
+ return result_type(m_FileName);
+ }
+ };
+
+ /*!
+ * The function adopts a log record formatter into a file name generator
+ */
+ template< typename FormatterT >
+ inline file_name_composer_adapter< FormatterT > as_file_name_composer(
+ FormatterT const& fmt, std::locale const& loc = std::locale())
+ {
+ return file_name_composer_adapter< FormatterT >(fmt, loc);
+ }
+
+} // namespace file
+
+
+/*!
+ * \brief An implementation of a text multiple files logging sink backend
+ *
+ * The sink backend puts formatted log records to one of the text files.
+ * The particular file is chosen upon each record's attribute values, which allows
+ * to distribute records into individual files or to group records related to
+ * some entity or process in a separate file.
+ */
+class text_multifile_backend :
+ public basic_formatted_sink_backend< char >
+{
+ //! Base type
+ typedef basic_formatted_sink_backend< char > base_type;
+
+public:
+ //! Character type
+ typedef base_type::char_type char_type;
+ //! String type to be used as a message text holder
+ typedef base_type::string_type string_type;
+
+ //! File name composer functor type
+ typedef boost::log::aux::light_function< filesystem::path (record_view const&) > file_name_composer_type;
+
+private:
+ //! \cond
+
+ struct implementation;
+ implementation* m_pImpl;
+
+ //! \endcond
+
+public:
+ /*!
+ * Default constructor. The constructed sink backend has no file name composer and
+ * thus will not write any files.
+ */
+ BOOST_LOG_API text_multifile_backend();
+
+ /*!
+ * Destructor
+ */
+ BOOST_LOG_API ~text_multifile_backend();
+
+ /*!
+ * The method sets file name composer functional object. Log record formatters are accepted, too.
+ *
+ * \param composer File name composer functor
+ */
+ template< typename ComposerT >
+ void set_file_name_composer(ComposerT const& composer)
+ {
+ set_file_name_composer_internal(composer);
+ }
+
+ /*!
+ * The method writes the message to the sink
+ */
+ BOOST_LOG_API void consume(record_view const& rec, string_type const& formatted_message);
+
+private:
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ //! The method sets the file name composer
+ BOOST_LOG_API void set_file_name_composer_internal(file_name_composer_type const& composer);
+#endif // BOOST_LOG_DOXYGEN_PASS
+};
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SINKS_TEXT_MULTIFILE_BACKEND_HPP_INCLUDED_
diff --git a/boost/log/sinks/text_ostream_backend.hpp b/boost/log/sinks/text_ostream_backend.hpp
new file mode 100644
index 0000000000..4c93d31357
--- /dev/null
+++ b/boost/log/sinks/text_ostream_backend.hpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file text_ostream_backend.hpp
+ * \author Andrey Semashev
+ * \date 22.04.2007
+ *
+ * The header contains implementation of a text output stream sink backend.
+ */
+
+#ifndef BOOST_LOG_SINKS_TEXT_OSTREAM_BACKEND_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_TEXT_OSTREAM_BACKEND_HPP_INCLUDED_
+
+#include <ostream>
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/sinks/basic_sink_backend.hpp>
+#include <boost/log/sinks/frontend_requirements.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+/*!
+ * \brief An implementation of a text output stream logging sink backend
+ *
+ * The sink backend puts formatted log records to one or more text streams.
+ */
+template< typename CharT >
+class basic_text_ostream_backend :
+ public basic_formatted_sink_backend<
+ CharT,
+ combine_requirements< synchronized_feeding, flushing >::type
+ >
+{
+ //! Base type
+ typedef basic_formatted_sink_backend<
+ CharT,
+ combine_requirements< synchronized_feeding, flushing >::type
+ > base_type;
+
+public:
+ //! Character type
+ typedef typename base_type::char_type char_type;
+ //! String type to be used as a message text holder
+ typedef typename base_type::string_type string_type;
+ //! Output stream type
+ typedef std::basic_ostream< char_type > stream_type;
+
+private:
+ //! \cond
+
+ struct implementation;
+ implementation* m_pImpl;
+
+ //! \endcond
+
+public:
+ /*!
+ * Constructor. No streams attached to the constructed backend, auto flush feature disabled.
+ */
+ BOOST_LOG_API basic_text_ostream_backend();
+ /*!
+ * Destructor
+ */
+ BOOST_LOG_API ~basic_text_ostream_backend();
+
+ /*!
+ * The method adds a new stream to the sink.
+ *
+ * \param strm Pointer to the stream. Must not be NULL.
+ */
+ BOOST_LOG_API void add_stream(shared_ptr< stream_type > const& strm);
+ /*!
+ * The method removes a stream from the sink. If the stream is not attached to the sink,
+ * the method has no effect.
+ *
+ * \param strm Pointer to the stream. Must not be NULL.
+ */
+ BOOST_LOG_API void remove_stream(shared_ptr< stream_type > const& strm);
+
+ /*!
+ * Sets the flag to automatically flush buffers of all attached streams after each log record
+ */
+ BOOST_LOG_API void auto_flush(bool f = true);
+
+ /*!
+ * The method writes the message to the sink
+ */
+ BOOST_LOG_API void consume(record_view const& rec, string_type const& formatted_message);
+
+ /*!
+ * The method flushes the associated streams
+ */
+ BOOST_LOG_API void flush();
+};
+
+#ifdef BOOST_LOG_USE_CHAR
+typedef basic_text_ostream_backend< char > text_ostream_backend; //!< Convenience typedef for narrow-character logging
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+typedef basic_text_ostream_backend< wchar_t > wtext_ostream_backend; //!< Convenience typedef for wide-character logging
+#endif
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SINKS_TEXT_OSTREAM_BACKEND_HPP_INCLUDED_
diff --git a/boost/log/sinks/unbounded_fifo_queue.hpp b/boost/log/sinks/unbounded_fifo_queue.hpp
new file mode 100644
index 0000000000..2782c5476c
--- /dev/null
+++ b/boost/log/sinks/unbounded_fifo_queue.hpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file unbounded_fifo_queue.hpp
+ * \author Andrey Semashev
+ * \date 24.07.2011
+ *
+ * The header contains implementation of unbounded FIFO queueing strategy for
+ * the asynchronous sink frontend.
+ */
+
+#ifndef BOOST_LOG_SINKS_UNBOUNDED_FIFO_QUEUE_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_UNBOUNDED_FIFO_QUEUE_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(BOOST_LOG_NO_THREADS)
+#error Boost.Log: This header content is only supported in multithreaded environment
+#endif
+
+#include <boost/log/detail/event.hpp>
+#include <boost/log/detail/threadsafe_queue.hpp>
+#include <boost/log/core/record_view.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+/*!
+ * \brief Unbounded FIFO log record queueing strategy
+ *
+ * The \c unbounded_fifo_queue class is intended to be used with
+ * the \c asynchronous_sink frontend as a log record queueing strategy.
+ *
+ * This strategy implements the simplest logic of log record buffering between
+ * threads: the queue has no limits and imposes no ordering over the queued
+ * elements aside from the order in which they are enqueued.
+ * Because of this the queue provides decent performance and scalability,
+ * however if sink backends can't consume log records fast enough the queue
+ * may grow uncontrollably. When this is an issue, it is recommended to
+ * use one of the bounded strategies.
+ */
+class unbounded_fifo_queue
+{
+private:
+ typedef boost::log::aux::threadsafe_queue< record_view > queue_type;
+
+private:
+ //! Thread-safe queue
+ queue_type m_queue;
+ //! Event object to block on
+ boost::log::aux::event m_event;
+ //! Interruption flag
+ volatile bool m_interruption_requested; // TODO: make it atomic
+
+protected:
+ //! Default constructor
+ unbounded_fifo_queue() : m_interruption_requested(false)
+ {
+ }
+ //! Initializing constructor
+ template< typename ArgsT >
+ explicit unbounded_fifo_queue(ArgsT const&) : m_interruption_requested(false)
+ {
+ }
+
+ //! Enqueues log record to the queue
+ void enqueue(record_view const& rec)
+ {
+ m_queue.push(rec);
+ m_event.set_signalled();
+ }
+
+ //! Attempts to enqueue log record to the queue
+ bool try_enqueue(record_view const& rec)
+ {
+ // Assume the call never blocks
+ enqueue(rec);
+ return true;
+ }
+
+ //! Attempts to dequeue a log record ready for processing from the queue, does not block if the queue is empty
+ bool try_dequeue_ready(record_view& rec)
+ {
+ return m_queue.try_pop(rec);
+ }
+
+ //! Attempts to dequeue log record from the queue, does not block if the queue is empty
+ bool try_dequeue(record_view& rec)
+ {
+ return m_queue.try_pop(rec);
+ }
+
+ //! Dequeues log record from the queue, blocks if the queue is empty
+ bool dequeue_ready(record_view& rec)
+ {
+ // Try the fast way first
+ if (m_queue.try_pop(rec))
+ return true;
+
+ // Ok, we probably have to wait for new records
+ while (true)
+ {
+ m_event.wait();
+ if (m_interruption_requested)
+ {
+ m_interruption_requested = false;
+ return false;
+ }
+ if (m_queue.try_pop(rec))
+ return true;
+ }
+ }
+
+ //! Wakes a thread possibly blocked in the \c dequeue method
+ void interrupt_dequeue()
+ {
+ m_interruption_requested = true;
+ m_event.set_signalled();
+ }
+};
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SINKS_UNBOUNDED_FIFO_QUEUE_HPP_INCLUDED_
diff --git a/boost/log/sinks/unbounded_ordering_queue.hpp b/boost/log/sinks/unbounded_ordering_queue.hpp
new file mode 100644
index 0000000000..f67e629a3e
--- /dev/null
+++ b/boost/log/sinks/unbounded_ordering_queue.hpp
@@ -0,0 +1,245 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file unbounded_ordering_queue.hpp
+ * \author Andrey Semashev
+ * \date 24.07.2011
+ *
+ * The header contains implementation of unbounded ordering record queueing strategy for
+ * the asynchronous sink frontend.
+ */
+
+#ifndef BOOST_LOG_SINKS_UNBOUNDED_ORDERING_QUEUE_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_UNBOUNDED_ORDERING_QUEUE_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(BOOST_LOG_NO_THREADS)
+#error Boost.Log: This header content is only supported in multithreaded environment
+#endif
+
+#include <queue>
+#include <vector>
+#include <boost/cstdint.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
+#include <boost/thread/thread_time.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/log/detail/timestamp.hpp>
+#include <boost/log/detail/enqueued_record.hpp>
+#include <boost/log/keywords/order.hpp>
+#include <boost/log/keywords/ordering_window.hpp>
+#include <boost/log/core/record_view.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+/*!
+ * \brief Unbounded ordering log record queueing strategy
+ *
+ * The \c unbounded_ordering_queue class is intended to be used with
+ * the \c asynchronous_sink frontend as a log record queueing strategy.
+ *
+ * This strategy provides the following properties to the record queueing mechanism:
+ *
+ * \li The queue has no size limits.
+ * \li The queue has a fixed latency window. This means that each log record put
+ * into the queue will normally not be dequeued for a certain period of time.
+ * \li The queue performs stable record ordering within the latency window.
+ * The ordering predicate can be specified in the \c OrderT template parameter.
+ *
+ * Since this queue has no size limits, it may grow uncontrollably if sink backends
+ * dequeue log records not fast enough. When this is an issue, it is recommended to
+ * use one of the bounded strategies.
+ */
+template< typename OrderT >
+class unbounded_ordering_queue
+{
+private:
+ typedef boost::mutex mutex_type;
+ typedef sinks::aux::enqueued_record enqueued_record;
+
+ typedef std::priority_queue<
+ enqueued_record,
+ std::vector< enqueued_record >,
+ enqueued_record::order< OrderT >
+ > queue_type;
+
+private:
+ //! Ordering window duration, in milliseconds
+ const uint64_t m_ordering_window;
+ //! Synchronization mutex
+ mutex_type m_mutex;
+ //! Condition for blocking
+ condition_variable m_cond;
+ //! Thread-safe queue
+ queue_type m_queue;
+ //! Interruption flag
+ bool m_interruption_requested;
+
+public:
+ /*!
+ * Returns ordering window size specified during initialization
+ */
+ posix_time::time_duration get_ordering_window() const
+ {
+ return posix_time::milliseconds(m_ordering_window);
+ }
+
+ /*!
+ * Returns default ordering window size.
+ * The default window size is specific to the operating system thread scheduling mechanism.
+ */
+ static posix_time::time_duration get_default_ordering_window()
+ {
+ // The main idea behind this parameter is that the ordering window should be large enough
+ // to allow the frontend to order records from different threads on an attribute
+ // that contains system time. Thus this value should be:
+ // * No less than the minimum time resolution quant that Boost.DateTime provides on the current OS.
+ // For instance, on Windows it defaults to around 15-16 ms.
+ // * No less than thread switching quant on the current OS. For now 30 ms is large enough window size to
+ // switch threads on any known OS. It can be tuned for other platforms as needed.
+ return posix_time::milliseconds(30);
+ }
+
+protected:
+ //! Initializing constructor
+ template< typename ArgsT >
+ explicit unbounded_ordering_queue(ArgsT const& args) :
+ m_ordering_window(args[keywords::ordering_window || &unbounded_ordering_queue::get_default_ordering_window].total_milliseconds()),
+ m_queue(args[keywords::order]),
+ m_interruption_requested(false)
+ {
+ }
+
+ //! Enqueues log record to the queue
+ void enqueue(record_view const& rec)
+ {
+ lock_guard< mutex_type > lock(m_mutex);
+ enqueue_unlocked(rec);
+ }
+
+ //! Attempts to enqueue log record to the queue
+ bool try_enqueue(record_view const& rec)
+ {
+ unique_lock< mutex_type > lock(m_mutex, try_to_lock);
+ if (lock.owns_lock())
+ {
+ enqueue_unlocked(rec);
+ return true;
+ }
+ else
+ return false;
+ }
+
+ //! Attempts to dequeue a log record ready for processing from the queue, does not block if no log records are ready to be processed
+ bool try_dequeue_ready(record_view& rec)
+ {
+ lock_guard< mutex_type > lock(m_mutex);
+ if (!m_queue.empty())
+ {
+ const boost::log::aux::timestamp now = boost::log::aux::get_timestamp();
+ enqueued_record const& elem = m_queue.top();
+ if (static_cast< uint64_t >((now - elem.m_timestamp).milliseconds()) >= m_ordering_window)
+ {
+ // We got a new element
+ rec = elem.m_record;
+ m_queue.pop();
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ //! Attempts to dequeue log record from the queue, does not block.
+ bool try_dequeue(record_view& rec)
+ {
+ lock_guard< mutex_type > lock(m_mutex);
+ if (!m_queue.empty())
+ {
+ enqueued_record const& elem = m_queue.top();
+ rec = elem.m_record;
+ m_queue.pop();
+ return true;
+ }
+
+ return false;
+ }
+
+ //! Dequeues log record from the queue, blocks if no log records are ready to be processed
+ bool dequeue_ready(record_view& rec)
+ {
+ unique_lock< mutex_type > lock(m_mutex);
+ while (!m_interruption_requested)
+ {
+ if (!m_queue.empty())
+ {
+ const boost::log::aux::timestamp now = boost::log::aux::get_timestamp();
+ enqueued_record const& elem = m_queue.top();
+ const uint64_t difference = (now - elem.m_timestamp).milliseconds();
+ if (difference >= m_ordering_window)
+ {
+ // We got a new element
+ rec = elem.m_record;
+ m_queue.pop();
+ return true;
+ }
+ else
+ {
+ // Wait until the element becomes ready to be processed
+ m_cond.timed_wait(lock, posix_time::milliseconds(m_ordering_window - difference));
+ }
+ }
+ else
+ {
+ // Wait for an element to come
+ m_cond.wait(lock);
+ }
+ }
+ m_interruption_requested = false;
+
+ return false;
+ }
+
+ //! Wakes a thread possibly blocked in the \c dequeue method
+ void interrupt_dequeue()
+ {
+ lock_guard< mutex_type > lock(m_mutex);
+ m_interruption_requested = true;
+ m_cond.notify_one();
+ }
+
+private:
+ //! Enqueues a log record
+ void enqueue_unlocked(record_view const& rec)
+ {
+ const bool was_empty = m_queue.empty();
+ m_queue.push(enqueued_record(rec));
+ if (was_empty)
+ m_cond.notify_one();
+ }
+};
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SINKS_UNBOUNDED_ORDERING_QUEUE_HPP_INCLUDED_
diff --git a/boost/log/sinks/unlocked_frontend.hpp b/boost/log/sinks/unlocked_frontend.hpp
new file mode 100644
index 0000000000..ab144d57b8
--- /dev/null
+++ b/boost/log/sinks/unlocked_frontend.hpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file unlocked_frontend.hpp
+ * \author Andrey Semashev
+ * \date 14.07.2009
+ *
+ * The header contains declaration of an unlocked sink frontend.
+ */
+
+#ifndef BOOST_LOG_SINKS_UNLOCKED_FRONTEND_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_UNLOCKED_FRONTEND_HPP_INCLUDED_
+
+#include <boost/static_assert.hpp>
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared_object.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/parameter_tools.hpp>
+#include <boost/log/detail/fake_mutex.hpp>
+#include <boost/log/sinks/basic_sink_frontend.hpp>
+#include <boost/log/sinks/frontend_requirements.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL(z, n, types)\
+ template< BOOST_PP_ENUM_PARAMS(n, typename T) >\
+ explicit unlocked_sink(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg)) :\
+ base_type(false),\
+ m_pBackend(boost::make_shared< sink_backend_type >(BOOST_PP_ENUM_PARAMS(n, arg))) {}
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * \brief Non-blocking logging sink frontend
+ *
+ * The sink frontend does not perform thread synchronization and
+ * simply passes logging records to the sink backend.
+ */
+template< typename SinkBackendT >
+class unlocked_sink :
+ public aux::make_sink_frontend_base< SinkBackendT >::type
+{
+ typedef typename aux::make_sink_frontend_base< SinkBackendT >::type base_type;
+
+public:
+ //! Sink implementation type
+ typedef SinkBackendT sink_backend_type;
+ //! \cond
+ BOOST_STATIC_ASSERT_MSG((has_requirement< typename sink_backend_type::frontend_requirements, concurrent_feeding >::value), "Unlocked sink frontend is incompatible with the specified backend: thread synchronization requirements are not met");
+ //! \endcond
+
+ //! Type of pointer to the backend
+ typedef shared_ptr< sink_backend_type > locked_backend_ptr;
+
+private:
+ //! Pointer to the backend
+ const shared_ptr< sink_backend_type > m_pBackend;
+
+public:
+ /*!
+ * Default constructor. Constructs the sink backend instance.
+ * Requires the backend to be default-constructible.
+ */
+ unlocked_sink() :
+ base_type(false),
+ m_pBackend(boost::make_shared< sink_backend_type >())
+ {
+ }
+ /*!
+ * Constructor attaches user-constructed backend instance
+ *
+ * \param backend Pointer to the backend instance
+ *
+ * \pre \a backend is not \c NULL.
+ */
+ explicit unlocked_sink(shared_ptr< sink_backend_type > const& backend) :
+ base_type(false),
+ m_pBackend(backend)
+ {
+ }
+
+ // Constructors that pass arbitrary parameters to the backend constructor
+ BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL, ~)
+
+ /*!
+ * Locking accessor to the attached backend.
+ *
+ * \note Does not do any actual locking, provided only for interface consistency
+ * with other frontends.
+ */
+ locked_backend_ptr locked_backend()
+ {
+ return m_pBackend;
+ }
+
+ /*!
+ * Passes the log record to the backend
+ */
+ void consume(record_view const& rec)
+ {
+ boost::log::aux::fake_mutex m;
+ base_type::feed_record(rec, m, *m_pBackend);
+ }
+
+ /*!
+ * The method performs flushing of any internal buffers that may hold log records. The method
+ * may take considerable time to complete and may block both the calling thread and threads
+ * attempting to put new records into the sink while this call is in progress.
+ */
+ void flush()
+ {
+ boost::log::aux::fake_mutex m;
+ base_type::flush_backend(m, *m_pBackend);
+ }
+};
+
+#undef BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SINKS_UNLOCKED_FRONTEND_HPP_INCLUDED_
diff --git a/boost/log/sources/basic_logger.hpp b/boost/log/sources/basic_logger.hpp
new file mode 100644
index 0000000000..0f0842934b
--- /dev/null
+++ b/boost/log/sources/basic_logger.hpp
@@ -0,0 +1,742 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file basic_logger.hpp
+ * \author Andrey Semashev
+ * \date 08.03.2007
+ *
+ * The header contains implementation of a base class for loggers. Convenience macros
+ * for defining custom loggers are also provided.
+ */
+
+#ifndef BOOST_LOG_SOURCES_BASIC_LOGGER_HPP_INCLUDED_
+#define BOOST_LOG_SOURCES_BASIC_LOGGER_HPP_INCLUDED_
+
+#include <exception>
+#include <utility>
+#include <ostream>
+#include <boost/assert.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/preprocessor/facilities/empty.hpp>
+#include <boost/preprocessor/facilities/identity.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+#include <boost/preprocessor/seq/enum.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/parameter_tools.hpp>
+#include <boost/log/attributes/attribute_set.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/core/core.hpp>
+#include <boost/log/core/record.hpp>
+#include <boost/log/sources/features.hpp>
+#include <boost/log/sources/threading_models.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sources {
+
+/*!
+ * \brief Basic logger class
+ *
+ * The \c basic_logger class template serves as a base class for all loggers
+ * provided by the library. It can also be used as a base for user-defined
+ * loggers. The template parameters are:
+ *
+ * \li \c CharT - logging character type
+ * \li \c FinalT - final type of the logger that eventually derives from
+ * the \c basic_logger. There may be other classes in the hierarchy
+ * between the final class and \c basic_logger.
+ * \li \c ThreadingModelT - threading model policy. Must provide methods
+ * of the Boost.Thread locking concept used in \c basic_logger class
+ * and all its derivatives in the hierarchy up to the \c FinalT class.
+ * The \c basic_logger class itself requires methods of the
+ * SharedLockable concept. The threading model policy must also be
+ * default and copy-constructible and support member function \c swap.
+ * There are currently two policies provided: \c single_thread_model
+ * and \c multi_thread_model.
+ *
+ * The logger implements fundamental facilities of loggers, such as storing
+ * source-specific attribute set and formatting log record messages. The basic
+ * logger interacts with the logging core in order to apply filtering and
+ * pass records to sinks.
+ */
+template< typename CharT, typename FinalT, typename ThreadingModelT >
+class basic_logger :
+ public ThreadingModelT
+{
+ typedef basic_logger this_type;
+ BOOST_COPYABLE_AND_MOVABLE_ALT(this_type)
+
+public:
+ //! Character type
+ typedef CharT char_type;
+ //! Final logger type
+ typedef FinalT final_type;
+ //! Threading model type
+ typedef ThreadingModelT threading_model;
+
+#if !defined(BOOST_LOG_NO_THREADS)
+ //! Lock requirement for the swap_unlocked method
+ typedef boost::log::aux::exclusive_lock_guard< threading_model > swap_lock;
+ //! Lock requirement for the add_attribute_unlocked method
+ typedef boost::log::aux::exclusive_lock_guard< threading_model > add_attribute_lock;
+ //! Lock requirement for the remove_attribute_unlocked method
+ typedef boost::log::aux::exclusive_lock_guard< threading_model > remove_attribute_lock;
+ //! Lock requirement for the remove_all_attributes_unlocked method
+ typedef boost::log::aux::exclusive_lock_guard< threading_model > remove_all_attributes_lock;
+ //! Lock requirement for the get_attributes method
+ typedef boost::log::aux::shared_lock_guard< const threading_model > get_attributes_lock;
+ //! Lock requirement for the open_record_unlocked method
+ typedef boost::log::aux::shared_lock_guard< threading_model > open_record_lock;
+ //! Lock requirement for the set_attributes method
+ typedef boost::log::aux::exclusive_lock_guard< threading_model > set_attributes_lock;
+#else
+ typedef no_lock< threading_model > swap_lock;
+ typedef no_lock< threading_model > add_attribute_lock;
+ typedef no_lock< threading_model > remove_attribute_lock;
+ typedef no_lock< threading_model > remove_all_attributes_lock;
+ typedef no_lock< const threading_model > get_attributes_lock;
+ typedef no_lock< threading_model > open_record_lock;
+ typedef no_lock< threading_model > set_attributes_lock;
+#endif
+
+ //! Lock requirement for the push_record_unlocked method
+ typedef no_lock< threading_model > push_record_lock;
+
+private:
+ //! A pointer to the logging system
+ core_ptr m_pCore;
+
+ //! Logger-specific attribute set
+ attribute_set m_Attributes;
+
+public:
+ /*!
+ * Constructor. Initializes internal data structures of the basic logger class,
+ * acquires reference to the logging core.
+ */
+ basic_logger() :
+ threading_model(),
+ m_pCore(core::get())
+ {
+ }
+ /*!
+ * Copy constructor. Copies all attributes from the source logger.
+ *
+ * \note Not thread-safe. The source logger must be locked in the final class before copying.
+ *
+ * \param that Source logger
+ */
+ basic_logger(basic_logger const& that) :
+ threading_model(static_cast< threading_model const& >(that)),
+ m_pCore(core::get()),
+ m_Attributes(that.m_Attributes)
+ {
+ }
+ /*!
+ * Move constructor. Moves all attributes from the source logger.
+ *
+ * \note Not thread-safe. The source logger must be locked in the final class before copying.
+ *
+ * \param that Source logger
+ */
+ basic_logger(BOOST_RV_REF(basic_logger) that) :
+ threading_model(boost::move(static_cast< threading_model& >(that)))
+ {
+ m_pCore.swap(that.m_pCore);
+ m_Attributes.swap(that.m_Attributes);
+ }
+ /*!
+ * Constructor with named arguments. The constructor ignores all arguments. The result of
+ * construction is equivalent to default construction.
+ */
+ template< typename ArgsT >
+ explicit basic_logger(ArgsT const&) :
+ threading_model(),
+ m_pCore(core::get())
+ {
+ }
+
+protected:
+ /*!
+ * An accessor to the logging system pointer
+ */
+ core_ptr const& core() const { return m_pCore; }
+ /*!
+ * An accessor to the logger attributes
+ */
+ attribute_set& attributes() { return m_Attributes; }
+ /*!
+ * An accessor to the logger attributes
+ */
+ attribute_set const& attributes() const { return m_Attributes; }
+ /*!
+ * An accessor to the threading model base
+ */
+ threading_model& get_threading_model() { return *this; }
+ /*!
+ * An accessor to the threading model base
+ */
+ threading_model const& get_threading_model() const { return *this; }
+ /*!
+ * An accessor to the final logger
+ */
+ final_type* final_this()
+ {
+ BOOST_LOG_ASSUME(this != NULL);
+ return static_cast< final_type* >(this);
+ }
+ /*!
+ * An accessor to the final logger
+ */
+ final_type const* final_this() const
+ {
+ BOOST_LOG_ASSUME(this != NULL);
+ return static_cast< final_type const* >(this);
+ }
+
+ /*!
+ * Unlocked \c swap
+ */
+ void swap_unlocked(basic_logger& that)
+ {
+ get_threading_model().swap(that.get_threading_model());
+ m_Attributes.swap(that.m_Attributes);
+ }
+
+ /*!
+ * Unlocked \c add_attribute
+ */
+ std::pair< attribute_set::iterator, bool > add_attribute_unlocked(attribute_name const& name, attribute const& attr)
+ {
+ return m_Attributes.insert(name, attr);
+ }
+
+ /*!
+ * Unlocked \c remove_attribute
+ */
+ void remove_attribute_unlocked(attribute_set::iterator it)
+ {
+ m_Attributes.erase(it);
+ }
+
+ /*!
+ * Unlocked \c remove_all_attributes
+ */
+ void remove_all_attributes_unlocked()
+ {
+ m_Attributes.clear();
+ }
+
+ /*!
+ * Unlocked \c open_record
+ */
+ record open_record_unlocked()
+ {
+ return m_pCore->open_record(m_Attributes);
+ }
+ /*!
+ * Unlocked \c open_record
+ */
+ template< typename ArgsT >
+ record open_record_unlocked(ArgsT const&)
+ {
+ return m_pCore->open_record(m_Attributes);
+ }
+
+ /*!
+ * Unlocked \c push_record
+ */
+ void push_record_unlocked(BOOST_RV_REF(record) rec)
+ {
+ m_pCore->push_record(boost::move(rec));
+ }
+
+ /*!
+ * Unlocked \c get_attributes
+ */
+ attribute_set get_attributes_unlocked() const
+ {
+ return m_Attributes;
+ }
+
+ /*!
+ * Unlocked \c set_attributes
+ */
+ void set_attributes_unlocked(attribute_set const& attrs)
+ {
+ m_Attributes = attrs;
+ }
+
+ //! Assignment is closed (should be implemented through copy and swap in the final class)
+ BOOST_DELETED_FUNCTION(basic_logger& operator= (basic_logger const&))
+};
+
+/*!
+ * Free-standing swap for all loggers
+ */
+template< typename CharT, typename FinalT, typename ThreadingModelT >
+inline void swap(
+ basic_logger< CharT, FinalT, ThreadingModelT >& left,
+ basic_logger< CharT, FinalT, ThreadingModelT >& right)
+{
+ static_cast< FinalT& >(left).swap(static_cast< FinalT& >(right));
+}
+
+/*!
+ * \brief A composite logger that inherits a number of features
+ *
+ * The composite logger is a helper class that simplifies feature composition into the final logger.
+ * The user's logger class is expected to derive from the composite logger class, instantiated with
+ * the character type, the user's logger class, the threading model and the list of the required features.
+ * The former three parameters are passed to the \c basic_logger class template. The feature list
+ * must be an MPL type sequence, where each element is a unary MPL metafunction class, that upon
+ * applying on its argument results in a logging feature class that derives from the argument.
+ * Every logger feature provided by the library can participate in the feature list.
+ */
+template< typename CharT, typename FinalT, typename ThreadingModelT, typename FeaturesT >
+class basic_composite_logger :
+ public boost::log::sources::aux::inherit_features<
+ basic_logger< CharT, FinalT, ThreadingModelT >,
+ FeaturesT
+ >::type
+{
+private:
+ //! Base type (the hierarchy of features)
+ typedef typename boost::log::sources::aux::inherit_features<
+ basic_logger< CharT, FinalT, ThreadingModelT >,
+ FeaturesT
+ >::type base_type;
+
+protected:
+ //! The composite logger type (for use in the user's logger class)
+ typedef basic_composite_logger logger_base;
+ BOOST_COPYABLE_AND_MOVABLE_ALT(logger_base)
+
+public:
+ //! Threading model being used
+ typedef typename base_type::threading_model threading_model;
+
+#if !defined(BOOST_LOG_NO_THREADS)
+
+public:
+ /*!
+ * Default constructor (default-constructs all features)
+ */
+ basic_composite_logger() {}
+ /*!
+ * Copy constructor
+ */
+ basic_composite_logger(basic_composite_logger const& that) :
+ base_type
+ ((
+ boost::log::aux::shared_lock_guard< const threading_model >(that.get_threading_model()),
+ static_cast< base_type const& >(that)
+ ))
+ {
+ }
+ /*!
+ * Move constructor
+ */
+ basic_composite_logger(BOOST_RV_REF(logger_base) that) :
+ base_type(boost::move(static_cast< base_type& >(that)))
+ {
+ }
+ /*!
+ * Constructor with named parameters
+ */
+ template< typename ArgsT >
+ explicit basic_composite_logger(ArgsT const& args) : base_type(args)
+ {
+ }
+
+ /*!
+ * The method adds an attribute to the source-specific attribute set. The attribute will be implicitly added to
+ * every log record made with the current logger.
+ *
+ * \param name The attribute name.
+ * \param attr The attribute factory.
+ * \return A pair of values. If the second member is \c true, then the attribute is added and the first member points to the
+ * attribute. Otherwise the attribute was not added and the first member points to the attribute that prevents
+ * addition.
+ */
+ std::pair< attribute_set::iterator, bool > add_attribute(attribute_name const& name, attribute const& attr)
+ {
+ typename base_type::add_attribute_lock lock(base_type::get_threading_model());
+ return base_type::add_attribute_unlocked(name, attr);
+ }
+ /*!
+ * The method removes an attribute from the source-specific attribute set.
+ *
+ * \pre The attribute was added with the add_attribute call for this instance of the logger.
+ * \post The attribute is no longer registered as a source-specific attribute for this logger. The iterator is invalidated after removal.
+ *
+ * \param it Iterator to the previously added attribute.
+ */
+ void remove_attribute(attribute_set::iterator it)
+ {
+ typename base_type::remove_attribute_lock lock(base_type::get_threading_model());
+ base_type::remove_attribute_unlocked(it);
+ }
+
+ /*!
+ * The method removes all attributes from the logger. All iterators and references to the removed attributes are invalidated.
+ */
+ void remove_all_attributes()
+ {
+ typename base_type::remove_all_attributes_lock lock(base_type::get_threading_model());
+ base_type::remove_all_attributes_unlocked();
+ }
+
+ /*!
+ * The method retrieves a copy of a set with all attributes from the logger.
+ *
+ * \return The copy of the attribute set. Attributes are shallow-copied.
+ */
+ attribute_set get_attributes() const
+ {
+ typename base_type::get_attributes_lock lock(base_type::get_threading_model());
+ return base_type::get_attributes_unlocked();
+ }
+
+ /*!
+ * The method installs the whole attribute set into the logger. All iterators and references to elements of
+ * the previous set are invalidated. Iterators to the \a attrs set are not valid to be used with the logger (that is,
+ * the logger owns a copy of \a attrs after completion).
+ *
+ * \param attrs The set of attributes to install into the logger. Attributes are shallow-copied.
+ */
+ void set_attributes(attribute_set const& attrs)
+ {
+ typename base_type::set_attributes_lock lock(base_type::get_threading_model());
+ base_type::set_attributes_unlocked(attrs);
+ }
+
+ /*!
+ * The method opens a new log record in the logging core.
+ *
+ * \return A valid record handle if the logging record is opened successfully, an invalid handle otherwise.
+ */
+ record open_record()
+ {
+ // Perform a quick check first
+ if (this->core()->get_logging_enabled())
+ {
+ typename base_type::open_record_lock lock(base_type::get_threading_model());
+ return base_type::open_record_unlocked(boost::log::aux::empty_arg_list());
+ }
+ else
+ return record();
+ }
+ /*!
+ * The method opens a new log record in the logging core.
+ *
+ * \param args A set of additional named arguments. The parameter is ignored.
+ * \return A valid record handle if the logging record is opened successfully, an invalid handle otherwise.
+ */
+ template< typename ArgsT >
+ record open_record(ArgsT const& args)
+ {
+ // Perform a quick check first
+ if (this->core()->get_logging_enabled())
+ {
+ typename base_type::open_record_lock lock(base_type::get_threading_model());
+ return base_type::open_record_unlocked(args);
+ }
+ else
+ return record();
+ }
+ /*!
+ * The method pushes the constructed message to the logging core
+ *
+ * \param rec The log record with the formatted message
+ */
+ void push_record(BOOST_RV_REF(record) rec)
+ {
+ typename base_type::push_record_lock lock(base_type::get_threading_model());
+ base_type::push_record_unlocked(boost::move(rec));
+ }
+ /*!
+ * Thread-safe implementation of swap
+ */
+ void swap(basic_composite_logger& that)
+ {
+ boost::log::aux::multiple_unique_lock2<
+ threading_model,
+ threading_model
+ > lock(base_type::get_threading_model(), that.get_threading_model());
+ base_type::swap_unlocked(that);
+ }
+
+protected:
+ /*!
+ * Assignment for the final class. Threadsafe, provides strong exception guarantee.
+ */
+ FinalT& assign(FinalT const& that)
+ {
+ BOOST_LOG_ASSUME(this != NULL);
+ if (static_cast< FinalT* >(this) != boost::addressof(that))
+ {
+ // We'll have to explicitly create the copy in order to make sure it's unlocked when we attempt to lock *this
+ FinalT tmp(that);
+ boost::log::aux::exclusive_lock_guard< threading_model > lock(base_type::get_threading_model());
+ base_type::swap_unlocked(tmp);
+ }
+ return static_cast< FinalT& >(*this);
+ }
+};
+
+//! An optimized composite logger version with no multithreading support
+template< typename CharT, typename FinalT, typename FeaturesT >
+class basic_composite_logger< CharT, FinalT, single_thread_model, FeaturesT > :
+ public boost::log::sources::aux::inherit_features<
+ basic_logger< CharT, FinalT, single_thread_model >,
+ FeaturesT
+ >::type
+{
+private:
+ typedef typename boost::log::sources::aux::inherit_features<
+ basic_logger< CharT, FinalT, single_thread_model >,
+ FeaturesT
+ >::type base_type;
+
+protected:
+ typedef basic_composite_logger logger_base;
+ BOOST_COPYABLE_AND_MOVABLE_ALT(logger_base)
+
+public:
+ typedef typename base_type::threading_model threading_model;
+
+#endif // !defined(BOOST_LOG_NO_THREADS)
+
+public:
+ basic_composite_logger() {}
+ basic_composite_logger(basic_composite_logger const& that) :
+ base_type(static_cast< base_type const& >(that))
+ {
+ }
+ basic_composite_logger(BOOST_RV_REF(logger_base) that) :
+ base_type(boost::move(static_cast< base_type& >(that)))
+ {
+ }
+ template< typename ArgsT >
+ explicit basic_composite_logger(ArgsT const& args) : base_type(args)
+ {
+ }
+
+ std::pair< attribute_set::iterator, bool > add_attribute(attribute_name const& name, attribute const& attr)
+ {
+ return base_type::add_attribute_unlocked(name, attr);
+ }
+ void remove_attribute(attribute_set::iterator it)
+ {
+ base_type::remove_attribute_unlocked(it);
+ }
+ void remove_all_attributes()
+ {
+ base_type::remove_all_attributes_unlocked();
+ }
+ attribute_set get_attributes() const
+ {
+ return base_type::get_attributes_unlocked();
+ }
+ void set_attributes(attribute_set const& attrs)
+ {
+ base_type::set_attributes_unlocked(attrs);
+ }
+ record open_record()
+ {
+ // Perform a quick check first
+ if (this->core()->get_logging_enabled())
+ return base_type::open_record_unlocked(boost::log::aux::empty_arg_list());
+ else
+ return record();
+ }
+ template< typename ArgsT >
+ record open_record(ArgsT const& args)
+ {
+ // Perform a quick check first
+ if (this->core()->get_logging_enabled())
+ return base_type::open_record_unlocked(args);
+ else
+ return record();
+ }
+ void push_record(BOOST_RV_REF(record) rec)
+ {
+ base_type::push_record_unlocked(boost::move(rec));
+ }
+ void swap(basic_composite_logger& that)
+ {
+ base_type::swap_unlocked(that);
+ }
+
+protected:
+ FinalT& assign(FinalT that)
+ {
+ base_type::swap_unlocked(that);
+ return static_cast< FinalT& >(*this);
+ }
+};
+
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#define BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS_IMPL(class_type, typename_keyword)\
+ public:\
+ BOOST_DEFAULTED_FUNCTION(class_type(), {})\
+ class_type(class_type const& that) : class_type::logger_base(\
+ static_cast< typename_keyword() class_type::logger_base const& >(that)) {}\
+ class_type(BOOST_RV_REF(class_type) that) : class_type::logger_base(\
+ ::boost::move(static_cast< typename_keyword() class_type::logger_base& >(that))) {}\
+ BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_FORWARD(class_type, class_type::logger_base)\
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+#define BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS(class_type)\
+ BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS_IMPL(class_type, BOOST_PP_EMPTY)
+
+#define BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS_TEMPLATE(class_type)\
+ BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS_IMPL(class_type, BOOST_PP_IDENTITY(typename))
+
+#define BOOST_LOG_FORWARD_LOGGER_ASSIGNMENT(class_type)\
+ public:\
+ class_type& operator= (BOOST_COPY_ASSIGN_REF(class_type) that)\
+ {\
+ return class_type::logger_base::assign(static_cast< class_type const& >(that));\
+ }\
+ class_type& operator= (BOOST_RV_REF(class_type) that)\
+ {\
+ BOOST_LOG_EXPR_IF_MT(::boost::log::aux::exclusive_lock_guard< class_type::threading_model > lock(this->get_threading_model());)\
+ this->swap_unlocked(that);\
+ return *this;\
+ }
+
+#define BOOST_LOG_FORWARD_LOGGER_ASSIGNMENT_TEMPLATE(class_type)\
+ public:\
+ class_type& operator= (BOOST_COPY_ASSIGN_REF(class_type) that)\
+ {\
+ return class_type::logger_base::assign(static_cast< class_type const& >(that));\
+ }\
+ class_type& operator= (BOOST_RV_REF(class_type) that)\
+ {\
+ BOOST_LOG_EXPR_IF_MT(::boost::log::aux::exclusive_lock_guard< typename class_type::threading_model > lock(this->get_threading_model());)\
+ this->swap_unlocked(that);\
+ return *this;\
+ }
+
+#define BOOST_LOG_FORWARD_LOGGER_MEMBERS(class_type)\
+ BOOST_COPYABLE_AND_MOVABLE(class_type)\
+ BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS(class_type)\
+ BOOST_LOG_FORWARD_LOGGER_ASSIGNMENT(class_type)
+
+#define BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(class_type)\
+ BOOST_COPYABLE_AND_MOVABLE(class_type)\
+ BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS_TEMPLATE(class_type)\
+ BOOST_LOG_FORWARD_LOGGER_ASSIGNMENT_TEMPLATE(class_type)
+
+} // namespace sources
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+/*!
+ * \brief The macro declares a logger class that inherits a number of base classes
+ *
+ * \param type_name The name of the logger class to declare
+ * \param char_type The character type of the logger. Either char or wchar_t expected.
+ * \param base_seq A Boost.Preprocessor sequence of type identifiers of the base classes templates
+ * \param threading A threading model class
+ */
+#define BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, char_type, base_seq, threading)\
+ class type_name :\
+ public ::boost::log::sources::basic_composite_logger<\
+ char_type,\
+ type_name,\
+ threading,\
+ ::boost::log::sources::features< BOOST_PP_SEQ_ENUM(base_seq) >\
+ >\
+ {\
+ BOOST_LOG_FORWARD_LOGGER_MEMBERS(type_name)\
+ }
+
+
+
+#ifdef BOOST_LOG_USE_CHAR
+
+/*!
+ * \brief The macro declares a narrow-char logger class that inherits a number of base classes
+ *
+ * Equivalent to BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, char, base_seq, single_thread_model)
+ *
+ * \param type_name The name of the logger class to declare
+ * \param base_seq A Boost.Preprocessor sequence of type identifiers of the base classes templates
+ */
+#define BOOST_LOG_DECLARE_LOGGER(type_name, base_seq)\
+ BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, char, base_seq, ::boost::log::sources::single_thread_model)
+
+#if !defined(BOOST_LOG_NO_THREADS)
+
+/*!
+ * \brief The macro declares a narrow-char thread-safe logger class that inherits a number of base classes
+ *
+ * Equivalent to <tt>BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, char, base_seq, multi_thread_model< shared_mutex >)</tt>
+ *
+ * \param type_name The name of the logger class to declare
+ * \param base_seq A Boost.Preprocessor sequence of type identifiers of the base classes templates
+ */
+#define BOOST_LOG_DECLARE_LOGGER_MT(type_name, base_seq)\
+ BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, char, base_seq,\
+ ::boost::log::sources::multi_thread_model< ::boost::shared_mutex >)
+
+#endif // !defined(BOOST_LOG_NO_THREADS)
+#endif // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+
+/*!
+ * \brief The macro declares a wide-char logger class that inherits a number of base classes
+ *
+ * Equivalent to BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, wchar_t, base_seq, single_thread_model)
+ *
+ * \param type_name The name of the logger class to declare
+ * \param base_seq A Boost.Preprocessor sequence of type identifiers of the base classes templates
+ */
+#define BOOST_LOG_DECLARE_WLOGGER(type_name, base_seq)\
+ BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, wchar_t, base_seq, ::boost::log::sources::single_thread_model)
+
+#if !defined(BOOST_LOG_NO_THREADS)
+
+/*!
+ * \brief The macro declares a wide-char thread-safe logger class that inherits a number of base classes
+ *
+ * Equivalent to <tt>BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, wchar_t, base_seq, multi_thread_model< shared_mutex >)</tt>
+ *
+ * \param type_name The name of the logger class to declare
+ * \param base_seq A Boost.Preprocessor sequence of type identifiers of the base classes templates
+ */
+#define BOOST_LOG_DECLARE_WLOGGER_MT(type_name, base_seq)\
+ BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, wchar_t, base_seq,\
+ ::boost::log::sources::multi_thread_model< ::boost::shared_mutex >)
+
+#endif // !defined(BOOST_LOG_NO_THREADS)
+#endif // BOOST_LOG_USE_WCHAR_T
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SOURCES_BASIC_LOGGER_HPP_INCLUDED_
diff --git a/boost/log/sources/channel_feature.hpp b/boost/log/sources/channel_feature.hpp
new file mode 100644
index 0000000000..c93ee6fa2d
--- /dev/null
+++ b/boost/log/sources/channel_feature.hpp
@@ -0,0 +1,242 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file channel_feature.hpp
+ * \author Andrey Semashev
+ * \date 28.02.2008
+ *
+ * The header contains implementation of a channel support feature.
+ */
+
+#ifndef BOOST_LOG_SOURCES_CHANNEL_FEATURE_HPP_INCLUDED_
+#define BOOST_LOG_SOURCES_CHANNEL_FEATURE_HPP_INCLUDED_
+
+#include <string>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/locks.hpp>
+#include <boost/log/detail/default_attribute_names.hpp>
+#include <boost/log/keywords/channel.hpp>
+#include <boost/log/attributes/mutable_constant.hpp>
+#include <boost/log/utility/strictest_lock.hpp>
+#include <boost/log/core/record.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sources {
+
+/*!
+ * \brief Channel feature implementation
+ */
+template< typename BaseT, typename ChannelT >
+class basic_channel_logger :
+ public BaseT
+{
+ //! Base type
+ typedef BaseT base_type;
+ typedef basic_channel_logger this_type;
+ BOOST_COPYABLE_AND_MOVABLE_ALT(this_type)
+
+public:
+ //! Character type
+ typedef typename base_type::char_type char_type;
+ //! Final type
+ typedef typename base_type::final_type final_type;
+ //! Threading model being used
+ typedef typename base_type::threading_model threading_model;
+
+ //! Channel type
+ typedef ChannelT channel_type;
+ //! Channel attribute type
+ typedef attributes::mutable_constant< channel_type > channel_attribute;
+
+ //! Lock requirement for the \c open_record_unlocked method
+ typedef typename strictest_lock<
+ typename base_type::open_record_lock,
+#ifndef BOOST_LOG_NO_THREADS
+ boost::log::aux::exclusive_lock_guard< threading_model >
+#else
+ no_lock< threading_model >
+#endif // !defined(BOOST_LOG_NO_THREADS)
+ >::type open_record_lock;
+
+ //! Lock requirement for the \c swap_unlocked method
+ typedef typename strictest_lock<
+ typename base_type::swap_lock,
+#ifndef BOOST_LOG_NO_THREADS
+ boost::log::aux::exclusive_lock_guard< threading_model >
+#else
+ no_lock< threading_model >
+#endif // !defined(BOOST_LOG_NO_THREADS)
+ >::type swap_lock;
+
+private:
+ //! Default channel name generator
+ struct make_default_channel_name
+ {
+ typedef channel_type result_type;
+ result_type operator() () const { return result_type(); }
+ };
+
+private:
+ //! Channel attribute
+ channel_attribute m_ChannelAttr;
+
+public:
+ /*!
+ * Default constructor. The constructed logger has the default-constructed channel name.
+ */
+ basic_channel_logger() : base_type(), m_ChannelAttr(channel_type())
+ {
+ base_type::add_attribute_unlocked(boost::log::aux::default_attribute_names::channel(), m_ChannelAttr);
+ }
+ /*!
+ * Copy constructor
+ */
+ basic_channel_logger(basic_channel_logger const& that) :
+ base_type(static_cast< base_type const& >(that)),
+ m_ChannelAttr(that.m_ChannelAttr)
+ {
+ base_type::attributes()[boost::log::aux::default_attribute_names::channel()] = m_ChannelAttr;
+ }
+ /*!
+ * Move constructor
+ */
+ basic_channel_logger(BOOST_RV_REF(basic_channel_logger) that) :
+ base_type(boost::move(static_cast< base_type& >(that))),
+ m_ChannelAttr(boost::move(that.m_ChannelAttr))
+ {
+ base_type::attributes()[boost::log::aux::default_attribute_names::channel()] = m_ChannelAttr;
+ }
+ /*!
+ * Constructor with arguments. Allows to register a channel name attribute on construction.
+ *
+ * \param args A set of named arguments. The following arguments are supported:
+ * \li \c channel - a string that represents the channel name
+ */
+ template< typename ArgsT >
+ explicit basic_channel_logger(ArgsT const& args) :
+ base_type(args),
+ m_ChannelAttr(args[keywords::channel || make_default_channel_name()])
+ {
+ base_type::add_attribute_unlocked(boost::log::aux::default_attribute_names::channel(), m_ChannelAttr);
+ }
+
+ /*!
+ * The observer of the channel name
+ *
+ * \return The channel name that was set by the logger
+ */
+ channel_type channel() const
+ {
+ BOOST_LOG_EXPR_IF_MT(boost::log::aux::shared_lock_guard< const threading_model > lock(this->get_threading_model());)
+ return m_ChannelAttr.get();
+ }
+
+ /*!
+ * The setter of the channel name
+ *
+ * \param ch The channel name to be set for the logger
+ */
+ void channel(channel_type const& ch)
+ {
+ BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< threading_model > lock(this->get_threading_model());)
+ m_ChannelAttr.set(ch);
+ }
+
+protected:
+ /*!
+ * Channel attribute accessor
+ */
+ channel_attribute const& get_channel_attribute() const { return m_ChannelAttr; }
+
+ /*!
+ * Unlocked \c open_record
+ */
+ template< typename ArgsT >
+ record open_record_unlocked(ArgsT const& args)
+ {
+ return open_record_with_channel_unlocked(args, args[keywords::channel | parameter::void_()]);
+ }
+
+ /*!
+ * Unlocked swap
+ */
+ void swap_unlocked(basic_channel_logger& that)
+ {
+ base_type::swap_unlocked(static_cast< base_type& >(that));
+ m_ChannelAttr.swap(that.m_ChannelAttr);
+ }
+
+private:
+ //! The \c open_record implementation for the case when the channel is specified in log statement
+ template< typename ArgsT, typename T >
+ record open_record_with_channel_unlocked(ArgsT const& args, T const& ch)
+ {
+ m_ChannelAttr.set(ch);
+ return base_type::open_record_unlocked(args);
+ }
+ //! The \c open_record implementation for the case when the channel is not specified in log statement
+ template< typename ArgsT >
+ record open_record_with_channel_unlocked(ArgsT const& args, parameter::void_)
+ {
+ return base_type::open_record_unlocked(args);
+ }
+};
+
+/*!
+ * \brief Channel support feature
+ *
+ * The logger with this feature automatically registers an attribute with the specified
+ * on construction value, which is a channel name. The channel name can be modified
+ * through the logger life time, either by calling the \c channel method or by specifying
+ * the name in the logging statement.
+ *
+ * The type of the channel name can be customized by providing it as a template parameter
+ * to the feature template. By default, a string will be used.
+ */
+template< typename ChannelT = std::string >
+struct channel
+{
+ template< typename BaseT >
+ struct apply
+ {
+ typedef basic_channel_logger<
+ BaseT,
+ ChannelT
+ > type;
+ };
+};
+
+} // namespace sources
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+//! The macro allows to put a record with a specific channel name into log
+#define BOOST_LOG_STREAM_CHANNEL(logger, chan)\
+ BOOST_LOG_STREAM_WITH_PARAMS((logger), (::boost::log::keywords::channel = (chan)))
+
+#ifndef BOOST_LOG_NO_SHORTHAND_NAMES
+
+//! An equivalent to BOOST_LOG_STREAM_CHANNEL(logger, chan)
+#define BOOST_LOG_CHANNEL(logger, chan) BOOST_LOG_STREAM_CHANNEL(logger, chan)
+
+#endif // BOOST_LOG_NO_SHORTHAND_NAMES
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SOURCES_CHANNEL_FEATURE_HPP_INCLUDED_
diff --git a/boost/log/sources/channel_logger.hpp b/boost/log/sources/channel_logger.hpp
new file mode 100644
index 0000000000..737faa1f17
--- /dev/null
+++ b/boost/log/sources/channel_logger.hpp
@@ -0,0 +1,325 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file channel_logger.hpp
+ * \author Andrey Semashev
+ * \date 28.02.2008
+ *
+ * The header contains implementation of a logger with channel support.
+ */
+
+#ifndef BOOST_LOG_SOURCES_CHANNEL_LOGGER_HPP_INCLUDED_
+#define BOOST_LOG_SOURCES_CHANNEL_LOGGER_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/log/detail/light_rw_mutex.hpp>
+#endif // !defined(BOOST_LOG_NO_THREADS)
+#include <boost/log/sources/features.hpp>
+#include <boost/log/sources/basic_logger.hpp>
+#include <boost/log/sources/threading_models.hpp>
+#include <boost/log/sources/channel_feature.hpp>
+#include <boost/log/keywords/channel.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sources {
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#ifdef BOOST_LOG_USE_CHAR
+
+//! Narrow-char logger with channel support
+template< typename ChannelT = std::string >
+class channel_logger :
+ public basic_composite_logger<
+ char,
+ channel_logger< ChannelT >,
+ single_thread_model,
+ features< channel< ChannelT > >
+ >
+{
+ typedef typename channel_logger::logger_base base_type;
+
+public:
+ BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(channel_logger)
+
+ explicit channel_logger(ChannelT const& channel) : base_type(keywords::channel = channel)
+ {
+ }
+};
+
+#if !defined(BOOST_LOG_NO_THREADS)
+
+//! Narrow-char thread-safe logger with channel support
+template< typename ChannelT = std::string >
+class channel_logger_mt :
+ public basic_composite_logger<
+ char,
+ channel_logger_mt< ChannelT >,
+ multi_thread_model< boost::log::aux::light_rw_mutex >,
+ features< channel< ChannelT > >
+ >
+{
+ typedef typename channel_logger_mt::logger_base base_type;
+
+public:
+ BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(channel_logger_mt)
+
+ explicit channel_logger_mt(ChannelT const& channel) : base_type(keywords::channel = channel)
+ {
+ }
+};
+
+#endif // !defined(BOOST_LOG_NO_THREADS)
+
+#endif // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+
+//! Wide-char logger with channel support
+template< typename ChannelT = std::wstring >
+class wchannel_logger :
+ public basic_composite_logger<
+ wchar_t,
+ wchannel_logger< ChannelT >,
+ single_thread_model,
+ features< channel< ChannelT > >
+ >
+{
+ typedef typename wchannel_logger::logger_base base_type;
+
+public:
+ BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(wchannel_logger)
+
+ explicit wchannel_logger(ChannelT const& channel) : base_type(keywords::channel = channel)
+ {
+ }
+};
+
+#if !defined(BOOST_LOG_NO_THREADS)
+
+//! Wide-char thread-safe logger with channel support
+template< typename ChannelT = std::wstring >
+class wchannel_logger_mt :
+ public basic_composite_logger<
+ wchar_t,
+ wchannel_logger< ChannelT >,
+ multi_thread_model< boost::log::aux::light_rw_mutex >,
+ features< channel< ChannelT > >
+ >
+{
+ typedef typename wchannel_logger_mt::logger_base base_type;
+
+public:
+ BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(wchannel_logger_mt)
+
+ explicit wchannel_logger_mt(ChannelT const& channel) : base_type(keywords::channel = channel)
+ {
+ }
+};
+
+#endif // !defined(BOOST_LOG_NO_THREADS)
+
+#endif // BOOST_LOG_USE_WCHAR_T
+
+#else // BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * \brief Narrow-char logger. Functionally equivalent to \c basic_channel_logger.
+ *
+ * See \c channel class template for a more detailed description
+ */
+template< typename ChannelT = std::string >
+class channel_logger :
+ public basic_composite_logger<
+ char,
+ channel_logger< ChannelT >,
+ single_thread_model,
+ features< channel< ChannelT > >
+ >
+{
+public:
+ /*!
+ * Default constructor
+ */
+ channel_logger();
+ /*!
+ * Copy constructor
+ */
+ channel_logger(channel_logger const& that);
+ /*!
+ * Constructor with named arguments
+ */
+ template< typename... ArgsT >
+ explicit channel_logger(ArgsT... const& args);
+ /*!
+ * The constructor creates the logger with the specified channel name
+ *
+ * \param channel The channel name
+ */
+ explicit channel_logger(ChannelT const& channel);
+ /*!
+ * Assignment operator
+ */
+ channel_logger& operator= (channel_logger const& that)
+ /*!
+ * Swaps two loggers
+ */
+ void swap(channel_logger& that);
+};
+
+/*!
+ * \brief Narrow-char thread-safe logger. Functionally equivalent to \c basic_channel_logger.
+ *
+ * See \c channel class template for a more detailed description
+ */
+template< typename ChannelT = std::string >
+class channel_logger_mt :
+ public basic_composite_logger<
+ char,
+ channel_logger_mt< ChannelT >,
+ multi_thread_model< implementation_defined >,
+ features< channel< ChannelT > >
+ >
+{
+public:
+ /*!
+ * Default constructor
+ */
+ channel_logger_mt();
+ /*!
+ * Copy constructor
+ */
+ channel_logger_mt(channel_logger_mt const& that);
+ /*!
+ * Constructor with named arguments
+ */
+ template< typename... ArgsT >
+ explicit channel_logger_mt(ArgsT... const& args);
+ /*!
+ * The constructor creates the logger with the specified channel name
+ *
+ * \param channel The channel name
+ */
+ explicit channel_logger_mt(ChannelT const& channel);
+ /*!
+ * Assignment operator
+ */
+ channel_logger_mt& operator= (channel_logger_mt const& that)
+ /*!
+ * Swaps two loggers
+ */
+ void swap(channel_logger_mt& that);
+};
+
+/*!
+ * \brief Wide-char logger. Functionally equivalent to \c basic_channel_logger.
+ *
+ * See \c channel class template for a more detailed description
+ */
+template< typename ChannelT = std::wstring >
+class wchannel_logger :
+ public basic_composite_logger<
+ wchar_t,
+ wchannel_logger< ChannelT >,
+ single_thread_model,
+ features< channel< ChannelT > >
+ >
+{
+public:
+ /*!
+ * Default constructor
+ */
+ wchannel_logger();
+ /*!
+ * Copy constructor
+ */
+ wchannel_logger(wchannel_logger const& that);
+ /*!
+ * Constructor with named arguments
+ */
+ template< typename... ArgsT >
+ explicit wchannel_logger(ArgsT... const& args);
+ /*!
+ * The constructor creates the logger with the specified channel name
+ *
+ * \param channel The channel name
+ */
+ explicit wchannel_logger(ChannelT const& channel);
+ /*!
+ * Assignment operator
+ */
+ wchannel_logger& operator= (wchannel_logger const& that)
+ /*!
+ * Swaps two loggers
+ */
+ void swap(wchannel_logger& that);
+};
+
+/*!
+ * \brief Wide-char thread-safe logger. Functionally equivalent to \c basic_channel_logger.
+ *
+ * See \c channel class template for a more detailed description
+ */
+template< typename ChannelT = std::wstring >
+class wchannel_logger_mt :
+ public basic_composite_logger<
+ wchar_t,
+ wchannel_logger< ChannelT >,
+ multi_thread_model< implementation_defined >,
+ features< channel< ChannelT > >
+ >
+{
+public:
+ /*!
+ * Default constructor
+ */
+ wchannel_logger_mt();
+ /*!
+ * Copy constructor
+ */
+ wchannel_logger_mt(wchannel_logger_mt const& that);
+ /*!
+ * Constructor with named arguments
+ */
+ template< typename... ArgsT >
+ explicit wchannel_logger_mt(ArgsT... const& args);
+ /*!
+ * The constructor creates the logger with the specified channel name
+ *
+ * \param channel The channel name
+ */
+ explicit wchannel_logger_mt(ChannelT const& channel);
+ /*!
+ * Assignment operator
+ */
+ wchannel_logger_mt& operator= (wchannel_logger_mt const& that)
+ /*!
+ * Swaps two loggers
+ */
+ void swap(wchannel_logger_mt& that);
+};
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+} // namespace sources
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SOURCES_CHANNEL_LOGGER_HPP_INCLUDED_
diff --git a/boost/log/sources/exception_handler_feature.hpp b/boost/log/sources/exception_handler_feature.hpp
new file mode 100644
index 0000000000..d665d0d84b
--- /dev/null
+++ b/boost/log/sources/exception_handler_feature.hpp
@@ -0,0 +1,253 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file exception_handler_feature.hpp
+ * \author Andrey Semashev
+ * \date 17.07.2009
+ *
+ * The header contains implementation of an exception handler support feature.
+ */
+
+#ifndef BOOST_LOG_SOURCES_EXCEPTION_HANDLER_FEATURE_HPP_INCLUDED_
+#define BOOST_LOG_SOURCES_EXCEPTION_HANDLER_FEATURE_HPP_INCLUDED_
+
+#include <boost/mpl/if.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/light_function.hpp>
+#include <boost/log/detail/locks.hpp>
+#include <boost/log/core/record.hpp>
+#include <boost/log/sources/threading_models.hpp>
+#include <boost/log/utility/strictest_lock.hpp>
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/thread/exceptions.hpp>
+#endif
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sources {
+
+/*!
+ * \brief Exception handler feature implementation
+ */
+template< typename BaseT >
+class basic_exception_handler_logger :
+ public BaseT
+{
+ //! Base type
+ typedef BaseT base_type;
+ typedef basic_exception_handler_logger this_type;
+ BOOST_COPYABLE_AND_MOVABLE_ALT(this_type)
+
+public:
+ //! Threading model being used
+ typedef typename base_type::threading_model threading_model;
+ //! Final logger type
+ typedef typename base_type::final_type final_type;
+ //! Exception handler function type
+ typedef boost::log::aux::light_function< void () > exception_handler_type;
+
+#if defined(BOOST_LOG_DOXYGEN_PASS)
+ //! Lock requirement for the open_record_unlocked method
+ typedef typename strictest_lock<
+ typename base_type::open_record_lock,
+ no_lock< threading_model >
+ >::type open_record_lock;
+ //! Lock requirement for the push_record_unlocked method
+ typedef typename strictest_lock<
+ typename base_type::push_record_lock,
+ no_lock< threading_model >
+ >::type push_record_lock;
+#endif // defined(BOOST_LOG_DOXYGEN_PASS)
+
+ //! Lock requirement for the swap_unlocked method
+ typedef typename strictest_lock<
+ typename base_type::swap_lock,
+#ifndef BOOST_LOG_NO_THREADS
+ boost::log::aux::exclusive_lock_guard< threading_model >
+#else
+ no_lock< threading_model >
+#endif // !defined(BOOST_LOG_NO_THREADS)
+ >::type swap_lock;
+
+private:
+ //! Exception handler
+ exception_handler_type m_ExceptionHandler;
+
+public:
+ /*!
+ * Default constructor. The constructed logger does not have an exception handler.
+ */
+ basic_exception_handler_logger() : base_type()
+ {
+ }
+ /*!
+ * Copy constructor
+ */
+ basic_exception_handler_logger(basic_exception_handler_logger const& that) :
+ base_type(static_cast< base_type const& >(that)),
+ m_ExceptionHandler(that.m_ExceptionHandler)
+ {
+ }
+ /*!
+ * Move constructor
+ */
+ basic_exception_handler_logger(BOOST_RV_REF(basic_exception_handler_logger) that) :
+ base_type(boost::move(static_cast< base_type& >(that))),
+ m_ExceptionHandler(boost::move(that.m_ExceptionHandler))
+ {
+ }
+ /*!
+ * Constructor with arguments. Passes arguments to other features.
+ */
+ template< typename ArgsT >
+ explicit basic_exception_handler_logger(ArgsT const& args) :
+ base_type(args)
+ {
+ }
+
+ /*!
+ * The method sets exception handler function. The function will be called with no arguments
+ * in case if an exception occurs during either \c open_record or \c push_record method
+ * execution. Since exception handler is called from a \c catch statement, the exception
+ * can be rethrown in order to determine its type.
+ *
+ * By default no handler is installed, thus any exception is propagated as usual.
+ *
+ * \sa <tt>utility/exception_handler.hpp</tt>
+ * \param handler Exception handling function
+ *
+ * \note The exception handler can be invoked in several threads concurrently.
+ *
+ * \note Thread interruptions are not affected by exception handlers.
+ */
+ template< typename HandlerT >
+ void set_exception_handler(HandlerT const& handler)
+ {
+#ifndef BOOST_LOG_NO_THREADS
+ boost::log::aux::exclusive_lock_guard< threading_model > lock(this->get_threading_model());
+#endif
+ m_ExceptionHandler = handler;
+ }
+
+protected:
+ /*!
+ * Unlocked \c open_record
+ */
+ template< typename ArgsT >
+ record open_record_unlocked(ArgsT const& args)
+ {
+ try
+ {
+ return base_type::open_record_unlocked(args);
+ }
+#ifndef BOOST_LOG_NO_THREADS
+ catch (thread_interrupted&)
+ {
+ throw;
+ }
+#endif
+ catch (...)
+ {
+ handle_exception();
+ return record();
+ }
+ }
+
+ /*!
+ * Unlocked \c push_record
+ */
+ void push_record_unlocked(BOOST_RV_REF(record) rec)
+ {
+ try
+ {
+ base_type::push_record_unlocked(boost::move(rec));
+ }
+#ifndef BOOST_LOG_NO_THREADS
+ catch (thread_interrupted&)
+ {
+ throw;
+ }
+#endif
+ catch (...)
+ {
+ handle_exception();
+ }
+ }
+
+ /*!
+ * Unlocked swap
+ */
+ void swap_unlocked(basic_exception_handler_logger& that)
+ {
+ base_type::swap_unlocked(static_cast< base_type& >(that));
+ m_ExceptionHandler.swap(that.m_ExceptionHandler);
+ }
+
+private:
+#if !defined(BOOST_LOG_DOXYGEN_PASS)
+ //! The function handles the intercepted exception
+ void handle_exception()
+ {
+#ifndef BOOST_LOG_NO_THREADS
+ // Here's the trick with the lock type. Since the lock
+ // is only needed when an exception is caught, we indicate
+ // no locking requirements in the push_record_lock type.
+ // However, if other features don't require locking either,
+ // we shall acquire a read lock here, when an exception is caught.
+ // If other features do require locking, the thread model is
+ // already locked by now, and we don't do locking at all.
+ typedef typename mpl::if_<
+ is_same< no_lock< threading_model >, typename final_type::push_record_lock >,
+ boost::log::aux::shared_lock_guard< threading_model >,
+ no_lock< threading_model >
+ >::type lock_type;
+ lock_type lock(base_type::get_threading_model());
+#endif // !defined(BOOST_LOG_NO_THREADS)
+
+ if (m_ExceptionHandler.empty())
+ throw;
+ m_ExceptionHandler();
+ }
+#endif // !defined(BOOST_LOG_DOXYGEN_PASS)
+};
+
+/*!
+ * \brief Exception handler support feature
+ *
+ * The logger with this feature will provide an additional method to
+ * install an exception handler functional object. This functional
+ * object will be called if during either opening or pushing a record
+ * an exception is thrown from the logging core.
+ */
+struct exception_handler
+{
+ template< typename BaseT >
+ struct apply
+ {
+ typedef basic_exception_handler_logger< BaseT > type;
+ };
+};
+
+} // namespace sources
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SOURCES_EXCEPTION_HANDLER_FEATURE_HPP_INCLUDED_
diff --git a/boost/log/sources/features.hpp b/boost/log/sources/features.hpp
new file mode 100644
index 0000000000..295cc0bb4f
--- /dev/null
+++ b/boost/log/sources/features.hpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file sources/features.hpp
+ * \author Andrey Semashev
+ * \date 17.07.2009
+ *
+ * The header contains definition of a features list class template.
+ */
+
+#ifndef BOOST_LOG_SOURCES_FEATURES_HPP_INCLUDED_
+#define BOOST_LOG_SOURCES_FEATURES_HPP_INCLUDED_
+
+#include <boost/mpl/lambda.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
+#include <boost/preprocessor/facilities/intercept.hpp>
+
+//! The macro defines the maximum number of features that can be specified for a logger
+#ifndef BOOST_LOG_FEATURES_LIMIT
+#define BOOST_LOG_FEATURES_LIMIT 10
+#endif // BOOST_LOG_FEATURES_LIMIT
+
+#endif
+
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sources {
+
+#if defined(BOOST_LOG_DOXYGEN_PASS) || !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+/*!
+ * \brief A type sequence of logger features
+ *
+ * This class template can be used to specify logger features in a \c basic_composite_logger instantiation.
+ */
+template< typename... FeaturesT >
+struct features
+{
+};
+
+namespace aux {
+
+//! The metafunction produces the inherited features hierarchy with \c RootT as the ultimate base type
+template< typename RootT, typename FeaturesT >
+struct inherit_features;
+
+template< typename RootT, typename FeatureT0, typename... FeaturesT >
+struct inherit_features< RootT, features< FeatureT0, FeaturesT... > >
+{
+ typedef typename mpl::lambda<
+ FeatureT0
+ >::type::BOOST_NESTED_TEMPLATE apply<
+ typename inherit_features<
+ RootT,
+ features< FeaturesT... >
+ >::type
+ >::type type;
+};
+
+template< typename RootT, typename FeatureT0 >
+struct inherit_features< RootT, features< FeatureT0 > >
+{
+ typedef typename mpl::lambda<
+ FeatureT0
+ >::type::BOOST_NESTED_TEMPLATE apply<
+ RootT
+ >::type type;
+};
+
+template< typename RootT >
+struct inherit_features< RootT, features< > >
+{
+ typedef RootT type;
+};
+
+} // namespace aux
+
+#else
+
+//! A type sequence of logger features
+template< BOOST_PP_ENUM_BINARY_PARAMS(BOOST_LOG_FEATURES_LIMIT, typename FeatureT, = void BOOST_PP_INTERCEPT) >
+struct features
+{
+};
+
+namespace aux {
+
+template< typename RootT, typename FeaturesT >
+struct inherit_features;
+
+template< typename RootT, BOOST_PP_ENUM_PARAMS(BOOST_LOG_FEATURES_LIMIT, typename FeatureT) >
+struct inherit_features< RootT, features< BOOST_PP_ENUM_PARAMS(BOOST_LOG_FEATURES_LIMIT, FeatureT) > >
+{
+ typedef typename mpl::lambda<
+ FeatureT0
+ >::type::BOOST_NESTED_TEMPLATE apply<
+ typename inherit_features<
+ RootT,
+ features< BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_LOG_FEATURES_LIMIT, FeatureT) >
+ >::type
+ >::type type;
+};
+
+template< typename RootT, typename FeatureT0 >
+struct inherit_features< RootT, features< FeatureT0, BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_LOG_FEATURES_LIMIT, void BOOST_PP_INTERCEPT) > >
+{
+ typedef typename mpl::lambda<
+ FeatureT0
+ >::type::BOOST_NESTED_TEMPLATE apply<
+ RootT
+ >::type type;
+};
+
+template< typename RootT >
+struct inherit_features< RootT, features< BOOST_PP_ENUM_PARAMS(BOOST_LOG_FEATURES_LIMIT, void BOOST_PP_INTERCEPT) > >
+{
+ typedef RootT type;
+};
+
+} // namespace aux
+
+#endif
+
+} // namespace sources
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SOURCES_FEATURES_HPP_INCLUDED_
diff --git a/boost/log/sources/global_logger_storage.hpp b/boost/log/sources/global_logger_storage.hpp
new file mode 100644
index 0000000000..65811edd2e
--- /dev/null
+++ b/boost/log/sources/global_logger_storage.hpp
@@ -0,0 +1,206 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file global_logger_storage.hpp
+ * \author Andrey Semashev
+ * \date 21.04.2008
+ *
+ * The header contains implementation of facilities to declare global loggers.
+ */
+
+#ifndef BOOST_LOG_SOURCES_GLOBAL_LOGGER_STORAGE_HPP_INCLUDED_
+#define BOOST_LOG_SOURCES_GLOBAL_LOGGER_STORAGE_HPP_INCLUDED_
+
+#include <typeinfo>
+#include <stdexcept>
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared_object.hpp>
+#include <boost/preprocessor/seq/enum.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/singleton.hpp>
+#include <boost/log/detail/visible_type.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sources {
+
+namespace aux {
+
+//! The base class for logger holders
+struct BOOST_LOG_NO_VTABLE BOOST_SYMBOL_VISIBLE logger_holder_base
+{
+ //! The source file name where the logger was registered
+ const char* m_RegistrationFile;
+ //! The line number where the logger was registered
+ unsigned int m_RegistrationLine;
+
+ logger_holder_base(const char* file, unsigned int line) :
+ m_RegistrationFile(file),
+ m_RegistrationLine(line)
+ {
+ }
+ virtual ~logger_holder_base() {}
+ virtual std::type_info const& logger_type() const = 0;
+};
+
+//! The actual logger holder class
+template< typename LoggerT >
+struct BOOST_SYMBOL_VISIBLE logger_holder :
+ public logger_holder_base
+{
+ //! The logger instance
+ LoggerT m_Logger;
+
+ logger_holder(const char* file, unsigned int line, LoggerT const& logger) :
+ logger_holder_base(file, line),
+ m_Logger(logger)
+ {
+ }
+ std::type_info const& logger_type() const { return typeid(LoggerT); }
+};
+
+//! The class implements a global repository of tagged loggers
+struct global_storage
+{
+ typedef shared_ptr< logger_holder_base >(*initializer_t)();
+
+ //! Finds or creates the logger and returns its holder
+ BOOST_LOG_API static shared_ptr< logger_holder_base > get_or_init(std::type_info const& key, initializer_t initializer);
+
+ // Non-constructible, non-copyable, non-assignable
+ BOOST_DELETED_FUNCTION(global_storage())
+ BOOST_DELETED_FUNCTION(global_storage(global_storage const&))
+ BOOST_DELETED_FUNCTION(global_storage& operator= (global_storage const&))
+};
+
+//! Throws the \c odr_violation exception
+BOOST_LOG_API BOOST_LOG_NORETURN void throw_odr_violation(
+ std::type_info const& tag_type,
+ std::type_info const& logger_type,
+ logger_holder_base const& registered);
+
+//! The class implements a logger singleton
+template< typename TagT >
+struct logger_singleton :
+ public boost::log::aux::lazy_singleton<
+ logger_singleton< TagT >,
+ shared_ptr< logger_holder< typename TagT::logger_type > >
+ >
+{
+ //! Base type
+ typedef boost::log::aux::lazy_singleton<
+ logger_singleton< TagT >,
+ shared_ptr< logger_holder< typename TagT::logger_type > >
+ > base_type;
+ //! Logger type
+ typedef typename TagT::logger_type logger_type;
+
+ //! Returns the logger instance
+ static logger_type& get()
+ {
+ return base_type::get()->m_Logger;
+ }
+
+ //! Initializes the logger instance (called only once)
+ static void init_instance()
+ {
+ shared_ptr< logger_holder< logger_type > >& instance = base_type::get_instance();
+ shared_ptr< logger_holder_base > holder = global_storage::get_or_init(
+ typeid(boost::log::aux::visible_type< TagT >),
+ &logger_singleton::construct_logger);
+ instance = boost::dynamic_pointer_cast< logger_holder< logger_type > >(holder);
+ if (!instance)
+ {
+ // In pure C++ this should never happen, since there cannot be two
+ // different tag types that have equal type_infos. In real life it can
+ // happen if the same-named tag is defined differently in two or more
+ // dlls. This check is intended to detect such ODR violations. However, there
+ // is no protection against different definitions of the logger type itself.
+ throw_odr_violation(typeid(TagT), typeid(logger_type), *holder);
+ }
+ }
+
+private:
+ //! Constructs a logger holder
+ static shared_ptr< logger_holder_base > construct_logger()
+ {
+ return boost::make_shared< logger_holder< logger_type > >(
+ TagT::registration_file(),
+ static_cast< unsigned int >(TagT::registration_line),
+ TagT::construct_logger());
+ }
+};
+
+} // namespace aux
+
+//! The macro forward-declares a global logger with a custom initialization
+#define BOOST_LOG_GLOBAL_LOGGER(tag_name, logger)\
+ struct tag_name\
+ {\
+ typedef logger logger_type;\
+ enum registration_line_t { registration_line = __LINE__ };\
+ static const char* registration_file() { return __FILE__; }\
+ static logger_type construct_logger();\
+ static inline logger_type& get()\
+ {\
+ return ::boost::log::sources::aux::logger_singleton< tag_name >::get();\
+ }\
+ };
+
+//! The macro defines a global logger initialization routine
+#define BOOST_LOG_GLOBAL_LOGGER_INIT(tag_name, logger)\
+ tag_name::logger_type tag_name::construct_logger()
+
+//! The macro defines a global logger initializer that will default-construct the logger
+#define BOOST_LOG_GLOBAL_LOGGER_DEFAULT(tag_name, logger)\
+ BOOST_LOG_GLOBAL_LOGGER_INIT(tag_name, logger)\
+ {\
+ return logger_type();\
+ }
+
+//! The macro defines a global logger initializer that will construct the logger with the specified constructor arguments
+#define BOOST_LOG_GLOBAL_LOGGER_CTOR_ARGS(tag_name, logger, args)\
+ BOOST_LOG_GLOBAL_LOGGER_INIT(tag_name, logger)\
+ {\
+ return logger_type(BOOST_PP_SEQ_ENUM(args));\
+ }
+
+//! The macro declares a global logger with a custom initialization
+#define BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(tag_name, logger)\
+ BOOST_LOG_GLOBAL_LOGGER(tag_name, logger)\
+ inline BOOST_LOG_GLOBAL_LOGGER_INIT(tag_name, logger)
+
+//! The macro declares a global logger that will be default-constructed
+#define BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(tag_name, logger)\
+ BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(tag_name, logger)\
+ {\
+ return logger_type();\
+ }
+
+//! The macro declares a global logger that will be constructed with the specified arguments
+#define BOOST_LOG_INLINE_GLOBAL_LOGGER_CTOR_ARGS(tag_name, logger, args)\
+ BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(tag_name, logger)\
+ {\
+ return logger_type(BOOST_PP_SEQ_ENUM(args));\
+ }
+
+} // namespace sources
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SOURCES_GLOBAL_LOGGER_STORAGE_HPP_INCLUDED_
diff --git a/boost/log/sources/logger.hpp b/boost/log/sources/logger.hpp
new file mode 100644
index 0000000000..4f5fbf1ff6
--- /dev/null
+++ b/boost/log/sources/logger.hpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file logger.hpp
+ * \author Andrey Semashev
+ * \date 08.03.2007
+ *
+ * The header contains implementation of a simplistic logger with no features.
+ */
+
+#ifndef BOOST_LOG_SOURCES_LOGGER_HPP_INCLUDED_
+#define BOOST_LOG_SOURCES_LOGGER_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/sources/basic_logger.hpp>
+#include <boost/log/sources/features.hpp>
+#include <boost/log/sources/threading_models.hpp>
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/log/detail/light_rw_mutex.hpp>
+#endif // !defined(BOOST_LOG_NO_THREADS)
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sources {
+
+#ifdef BOOST_LOG_USE_CHAR
+
+/*!
+ * \brief Narrow-char logger. Functionally equivalent to \c basic_logger.
+ *
+ * See \c basic_logger class template for a more detailed description.
+ */
+class logger :
+ public basic_composite_logger< char, logger, single_thread_model, features< > >
+{
+ BOOST_LOG_FORWARD_LOGGER_MEMBERS(logger)
+};
+
+#if !defined(BOOST_LOG_NO_THREADS)
+
+/*!
+ * \brief Narrow-char thread-safe logger. Functionally equivalent to \c basic_logger.
+ *
+ * See \c basic_logger class template for a more detailed description.
+ */
+class logger_mt :
+ public basic_composite_logger< char, logger_mt, multi_thread_model< boost::log::aux::light_rw_mutex >, features< > >
+{
+ BOOST_LOG_FORWARD_LOGGER_MEMBERS(logger_mt)
+};
+
+#endif // !defined(BOOST_LOG_NO_THREADS)
+#endif // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+
+/*!
+ * \brief Wide-char logger. Functionally equivalent to \c basic_logger.
+ *
+ * See \c basic_logger class template for a more detailed description.
+ */
+class wlogger :
+ public basic_composite_logger< wchar_t, wlogger, single_thread_model, features< > >
+{
+ BOOST_LOG_FORWARD_LOGGER_MEMBERS(wlogger)
+};
+
+#if !defined(BOOST_LOG_NO_THREADS)
+
+/*!
+ * \brief Wide-char thread-safe logger. Functionally equivalent to \c basic_logger.
+ *
+ * See \c basic_logger class template for a more detailed description.
+ */
+class wlogger_mt :
+ public basic_composite_logger< wchar_t, wlogger_mt, multi_thread_model< boost::log::aux::light_rw_mutex >, features< > >
+{
+ BOOST_LOG_FORWARD_LOGGER_MEMBERS(wlogger_mt)
+};
+
+#endif // !defined(BOOST_LOG_NO_THREADS)
+#endif // BOOST_LOG_USE_WCHAR_T
+
+} // namespace sources
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SOURCES_LOGGER_HPP_INCLUDED_
diff --git a/boost/log/sources/record_ostream.hpp b/boost/log/sources/record_ostream.hpp
new file mode 100644
index 0000000000..239f3c9f6a
--- /dev/null
+++ b/boost/log/sources/record_ostream.hpp
@@ -0,0 +1,335 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file record_ostream.hpp
+ * \author Andrey Semashev
+ * \date 09.03.2009
+ *
+ * This header contains a wrapper class around a logging record that allows to compose the
+ * record message with a streaming expression.
+ */
+
+#ifndef BOOST_LOG_SOURCES_RECORD_OSTREAM_HPP_INCLUDED_
+#define BOOST_LOG_SOURCES_RECORD_OSTREAM_HPP_INCLUDED_
+
+#include <string>
+#include <ostream>
+#include <boost/assert.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/native_typeof.hpp>
+#include <boost/log/detail/unhandled_exception_count.hpp>
+#include <boost/log/core/record.hpp>
+#include <boost/log/utility/unique_identifier_name.hpp>
+#include <boost/utility/explicit_operator_bool.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * \brief Logging record adapter with a streaming capability
+ *
+ * This class allows to compose the logging record message by streaming operations. It
+ * aggregates the log record and provides the standard output stream interface.
+ */
+template< typename CharT >
+class basic_record_ostream :
+ public basic_formatting_ostream< CharT >
+{
+ //! Self type
+ typedef basic_record_ostream< CharT > this_type;
+ //! Base stream class
+ typedef basic_formatting_ostream< CharT > base_type;
+
+public:
+ //! Character type
+ typedef CharT char_type;
+ //! String type to be used as a message text holder
+ typedef std::basic_string< char_type > string_type;
+ //! Stream type
+ typedef std::basic_ostream< char_type > stream_type;
+
+private:
+ //! Log record
+ record* m_record;
+
+public:
+ /*!
+ * Default constructor. Creates an empty record that is equivalent to the invalid record handle.
+ * The stream capability is not available after construction.
+ *
+ * \post <tt>!*this == true</tt>
+ */
+ basic_record_ostream() BOOST_NOEXCEPT : m_record(NULL) {}
+
+ /*!
+ * Constructor from a record object. Attaches to the provided record.
+ *
+ * \pre <tt>!!rec == true</tt>
+ * \post <tt>&this->get_record() == &rec</tt>
+ * \param rec The record handle being attached to
+ */
+ explicit basic_record_ostream(record& rec)
+ {
+ BOOST_ASSERT_MSG(!!rec, "Boost.Log: basic_record_ostream should only be attached to a valid record");
+ m_record = &rec;
+ init_stream();
+ }
+
+ /*!
+ * Destructor. Destroys the record, releases any sinks and attribute values that were involved in processing this record.
+ */
+ ~basic_record_ostream() BOOST_NOEXCEPT
+ {
+ detach_from_record();
+ }
+
+ /*!
+ * Conversion to an unspecified boolean type
+ *
+ * \return \c true, if stream is valid and ready for formatting, \c false, if the stream is not valid. The latter also applies to
+ * the case when the stream is not attached to a log record.
+ */
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+
+ /*!
+ * Inverted conversion to an unspecified boolean type
+ *
+ * \return \c false, if stream is valid and ready for formatting, \c true, if the stream is not valid. The latter also applies to
+ * the case when the stream is not attached to a log record.
+ */
+ bool operator! () const BOOST_NOEXCEPT
+ {
+ return (!m_record || base_type::fail());
+ }
+
+ /*!
+ * Flushes internal buffers to complete all pending formatting operations and returns the aggregated log record
+ *
+ * \return The aggregated record object
+ */
+ record& get_record()
+ {
+ BOOST_ASSERT(m_record != NULL);
+ this->flush();
+ return *m_record;
+ }
+
+ /*!
+ * Flushes internal buffers to complete all pending formatting operations and returns the aggregated log record
+ *
+ * \return The aggregated record object
+ */
+ record const& get_record() const
+ {
+ BOOST_ASSERT(m_record != NULL);
+ const_cast< this_type* >(this)->flush();
+ return *m_record;
+ }
+
+ /*!
+ * If the stream is attached to a log record, flushes internal buffers to complete all pending formatting operations.
+ * Then reattaches the stream to another log record.
+ *
+ * \param rec New log record to attach to
+ */
+ void attach_record(record& rec)
+ {
+ BOOST_ASSERT_MSG(!!rec, "Boost.Log: basic_record_ostream should only be attached to a valid record");
+ detach_from_record();
+ m_record = &rec;
+ init_stream();
+ }
+
+ //! The function resets the stream into a detached (default initialized) state
+ BOOST_LOG_API void detach_from_record() BOOST_NOEXCEPT;
+
+private:
+ //! The function initializes the stream and the stream buffer
+ BOOST_LOG_API void init_stream();
+
+ // Copy and assignment are closed
+ BOOST_DELETED_FUNCTION(basic_record_ostream(basic_record_ostream const&))
+ BOOST_DELETED_FUNCTION(basic_record_ostream& operator= (basic_record_ostream const&))
+};
+
+
+#ifdef BOOST_LOG_USE_CHAR
+typedef basic_record_ostream< char > record_ostream; //!< Convenience typedef for narrow-character logging
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+typedef basic_record_ostream< wchar_t > wrecord_ostream; //!< Convenience typedef for wide-character logging
+#endif
+
+namespace aux {
+
+//! Internal class that provides formatting streams for record pumps
+template< typename CharT >
+struct stream_provider
+{
+ //! Character type
+ typedef CharT char_type;
+
+ //! Formatting stream compound
+ struct stream_compound
+ {
+ stream_compound* next;
+
+ //! Log record stream adapter
+ basic_record_ostream< char_type > stream;
+
+ //! Initializing constructor
+ explicit stream_compound(record& rec) : next(NULL), stream(rec) {}
+ };
+
+ //! The method returns an allocated stream compound
+ BOOST_LOG_API static stream_compound* allocate_compound(record& rec);
+ //! The method releases a compound
+ BOOST_LOG_API static void release_compound(stream_compound* compound) BOOST_NOEXCEPT;
+
+ // Non-constructible, non-copyable, non-assignable
+ BOOST_DELETED_FUNCTION(stream_provider())
+ BOOST_DELETED_FUNCTION(stream_provider(stream_provider const&))
+ BOOST_DELETED_FUNCTION(stream_provider& operator= (stream_provider const&))
+};
+
+
+/*!
+ * \brief Logging record pump implementation
+ *
+ * The pump is used to format the logging record message text and then
+ * push it to the logging core. It is constructed on each attempt to write
+ * a log record and destroyed afterwards.
+ *
+ * The pump class template is instantiated on the logger type.
+ */
+template< typename LoggerT >
+class record_pump
+{
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(record_pump)
+
+private:
+ //! Logger type
+ typedef LoggerT logger_type;
+ //! Character type
+ typedef typename logger_type::char_type char_type;
+ //! Stream compound provider
+ typedef stream_provider< char_type > stream_provider_type;
+ //! Stream compound type
+ typedef typename stream_provider_type::stream_compound stream_compound;
+
+ //! Stream compound release guard
+ class auto_release;
+ friend class auto_release;
+ class auto_release
+ {
+ stream_compound* m_pCompound;
+
+ public:
+ explicit auto_release(stream_compound* p) BOOST_NOEXCEPT : m_pCompound(p) {}
+ ~auto_release() BOOST_NOEXCEPT { stream_provider_type::release_compound(m_pCompound); }
+ };
+
+protected:
+ //! A reference to the logger
+ logger_type* m_pLogger;
+ //! Stream compound
+ stream_compound* m_pStreamCompound;
+ //! Exception state
+ const unsigned int m_ExceptionCount;
+
+public:
+ //! Constructor
+ explicit record_pump(logger_type& lg, record& rec) :
+ m_pLogger(boost::addressof(lg)),
+ m_pStreamCompound(stream_provider_type::allocate_compound(rec)),
+ m_ExceptionCount(unhandled_exception_count())
+ {
+ }
+ //! Move constructor
+ record_pump(BOOST_RV_REF(record_pump) that) BOOST_NOEXCEPT :
+ m_pLogger(that.m_pLogger),
+ m_pStreamCompound(that.m_pStreamCompound),
+ m_ExceptionCount(that.m_ExceptionCount)
+ {
+ that.m_pLogger = 0;
+ that.m_pStreamCompound = 0;
+ }
+ //! Destructor. Pushes the composed message to log.
+ ~record_pump() BOOST_NOEXCEPT_IF(false)
+ {
+ if (m_pLogger)
+ {
+ auto_release cleanup(m_pStreamCompound); // destructor doesn't throw
+ // Only push the record if no exception has been thrown in the streaming expression (if possible)
+ if (m_ExceptionCount >= unhandled_exception_count())
+ m_pLogger->push_record(boost::move(m_pStreamCompound->stream.get_record()));
+ }
+ }
+
+ //! Returns the stream to be used for message text formatting
+ basic_record_ostream< char_type >& stream() const BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT(m_pStreamCompound != 0);
+ return m_pStreamCompound->stream;
+ }
+};
+
+template< typename LoggerT >
+BOOST_FORCEINLINE record_pump< LoggerT > make_record_pump(LoggerT& lg, record& rec)
+{
+ return record_pump< LoggerT >(lg, rec);
+}
+
+} // namespace aux
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#define BOOST_LOG_STREAM_INTERNAL(logger, rec_var)\
+ for (::boost::log::record rec_var = (logger).open_record(); !!rec_var;)\
+ ::boost::log::aux::make_record_pump((logger), rec_var).stream()
+
+#define BOOST_LOG_STREAM_WITH_PARAMS_INTERNAL(logger, rec_var, params_seq)\
+ for (::boost::log::record rec_var = (logger).open_record((BOOST_PP_SEQ_ENUM(params_seq))); !!rec_var;)\
+ ::boost::log::aux::make_record_pump((logger), rec_var).stream()
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+//! The macro writes a record to the log
+#define BOOST_LOG_STREAM(logger)\
+ BOOST_LOG_STREAM_INTERNAL(logger, BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_record_))
+
+//! The macro writes a record to the log and allows to pass additional named arguments to the logger
+#define BOOST_LOG_STREAM_WITH_PARAMS(logger, params_seq)\
+ BOOST_LOG_STREAM_WITH_PARAMS_INTERNAL(logger, BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_record_), params_seq)
+
+#ifndef BOOST_LOG_NO_SHORTHAND_NAMES
+
+//! An equivalent to BOOST_LOG_STREAM(logger)
+#define BOOST_LOG(logger) BOOST_LOG_STREAM(logger)
+
+//! An equivalent to BOOST_LOG_STREAM_WITH_PARAMS(logger, params_seq)
+#define BOOST_LOG_WITH_PARAMS(logger, params_seq) BOOST_LOG_STREAM_WITH_PARAMS(logger, params_seq)
+
+#endif // BOOST_LOG_NO_SHORTHAND_NAMES
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SOURCES_RECORD_OSTREAM_HPP_INCLUDED_
diff --git a/boost/log/sources/severity_channel_logger.hpp b/boost/log/sources/severity_channel_logger.hpp
new file mode 100644
index 0000000000..aa567e82f6
--- /dev/null
+++ b/boost/log/sources/severity_channel_logger.hpp
@@ -0,0 +1,309 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file severity_channel_logger.hpp
+ * \author Andrey Semashev
+ * \date 28.02.2008
+ *
+ * The header contains implementation of a logger with severity level and channel support.
+ */
+
+#ifndef BOOST_LOG_SOURCES_SEVERITY_CHANNEL_LOGGER_HPP_INCLUDED_
+#define BOOST_LOG_SOURCES_SEVERITY_CHANNEL_LOGGER_HPP_INCLUDED_
+
+#include <string>
+#include <boost/log/detail/config.hpp>
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/log/detail/light_rw_mutex.hpp>
+#endif // !defined(BOOST_LOG_NO_THREADS)
+#include <boost/log/sources/features.hpp>
+#include <boost/log/sources/basic_logger.hpp>
+#include <boost/log/sources/threading_models.hpp>
+#include <boost/log/sources/severity_feature.hpp>
+#include <boost/log/sources/channel_feature.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sources {
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#ifdef BOOST_LOG_USE_CHAR
+
+//! Narrow-char logger with severity level and channel support
+template< typename LevelT = int, typename ChannelT = std::string >
+class severity_channel_logger :
+ public basic_composite_logger<
+ char,
+ severity_channel_logger< LevelT, ChannelT >,
+ single_thread_model,
+ features<
+ severity< LevelT >,
+ channel< ChannelT >
+ >
+ >
+{
+ BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(severity_channel_logger)
+};
+
+#if !defined(BOOST_LOG_NO_THREADS)
+
+//! Narrow-char thread-safe logger with severity level and channel support
+template< typename LevelT = int, typename ChannelT = std::string >
+class severity_channel_logger_mt :
+ public basic_composite_logger<
+ char,
+ severity_channel_logger_mt< LevelT, ChannelT >,
+ multi_thread_model< boost::log::aux::light_rw_mutex >,
+ features<
+ severity< LevelT >,
+ channel< ChannelT >
+ >
+ >
+{
+ BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(severity_channel_logger_mt)
+};
+
+#endif // !defined(BOOST_LOG_NO_THREADS)
+
+#endif // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+
+//! Wide-char logger with severity level and channel support
+template< typename LevelT = int, typename ChannelT = std::wstring >
+class wseverity_channel_logger :
+ public basic_composite_logger<
+ wchar_t,
+ wseverity_channel_logger< LevelT, ChannelT >,
+ single_thread_model,
+ features<
+ severity< LevelT >,
+ channel< ChannelT >
+ >
+ >
+{
+ BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(wseverity_channel_logger)
+};
+
+#if !defined(BOOST_LOG_NO_THREADS)
+
+//! Wide-char thread-safe logger with severity level and channel support
+template< typename LevelT = int, typename ChannelT = std::wstring >
+class wseverity_channel_logger_mt :
+ public basic_composite_logger<
+ wchar_t,
+ wseverity_channel_logger_mt< LevelT, ChannelT >,
+ multi_thread_model< boost::log::aux::light_rw_mutex >,
+ features<
+ severity< LevelT >,
+ channel< ChannelT >
+ >
+ >
+{
+ BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(wseverity_channel_logger_mt)
+};
+
+#endif // !defined(BOOST_LOG_NO_THREADS)
+
+#endif // BOOST_LOG_USE_WCHAR_T
+
+#else // BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * \brief Narrow-char logger. Functionally equivalent to \c basic_severity_logger and \c basic_channel_logger.
+ *
+ * See \c severity and \c channel class templates for a more detailed description
+ */
+template< typename LevelT = int, typename ChannelT = std::string >
+class severity_channel_logger :
+ public basic_composite_logger<
+ char,
+ severity_channel_logger< LevelT, ChannelT >,
+ single_thread_model,
+ features<
+ severity< LevelT >,
+ channel< ChannelT >
+ >
+ >
+{
+public:
+ /*!
+ * Default constructor
+ */
+ severity_channel_logger();
+ /*!
+ * Copy constructor
+ */
+ severity_channel_logger(severity_channel_logger const& that);
+ /*!
+ * Constructor with named arguments
+ */
+ template< typename... ArgsT >
+ explicit severity_channel_logger(ArgsT... const& args);
+ /*!
+ * Assignment operator
+ */
+ severity_channel_logger& operator= (severity_channel_logger const& that)
+ /*!
+ * Swaps two loggers
+ */
+ void swap(severity_channel_logger& that);
+};
+
+/*!
+ * \brief Narrow-char thread-safe logger. Functionally equivalent to \c basic_severity_logger and \c basic_channel_logger.
+ *
+ * See \c severity and \c channel class templates for a more detailed description
+ */
+template< typename LevelT = int, typename ChannelT = std::string >
+class severity_channel_logger_mt :
+ public basic_composite_logger<
+ char,
+ severity_channel_logger_mt< LevelT, ChannelT >,
+ multi_thread_model< implementation_defined >,
+ features<
+ severity< LevelT >,
+ channel< ChannelT >
+ >
+ >
+{
+public:
+ /*!
+ * Default constructor
+ */
+ severity_channel_logger_mt();
+ /*!
+ * Copy constructor
+ */
+ severity_channel_logger_mt(severity_channel_logger_mt const& that);
+ /*!
+ * Constructor with named arguments
+ */
+ template< typename... ArgsT >
+ explicit severity_channel_logger_mt(ArgsT... const& args);
+ /*!
+ * Assignment operator
+ */
+ severity_channel_logger_mt& operator= (severity_channel_logger_mt const& that)
+ /*!
+ * Swaps two loggers
+ */
+ void swap(severity_channel_logger_mt& that);
+};
+
+/*!
+ * \brief Wide-char logger. Functionally equivalent to \c basic_severity_logger and \c basic_channel_logger.
+ *
+ * See \c severity and \c channel class templates for a more detailed description
+ */
+template< typename LevelT = int, typename ChannelT = std::wstring >
+class wseverity_channel_logger :
+ public basic_composite_logger<
+ wchar_t,
+ wseverity_channel_logger< LevelT, ChannelT >,
+ single_thread_model,
+ features<
+ severity< LevelT >,
+ channel< ChannelT >
+ >
+ >
+{
+public:
+ /*!
+ * Default constructor
+ */
+ wseverity_channel_logger();
+ /*!
+ * Copy constructor
+ */
+ wseverity_channel_logger(wseverity_channel_logger const& that);
+ /*!
+ * Constructor with named arguments
+ */
+ template< typename... ArgsT >
+ explicit wseverity_channel_logger(ArgsT... const& args);
+ /*!
+ * Assignment operator
+ */
+ wseverity_channel_logger& operator= (wseverity_channel_logger const& that)
+ /*!
+ * Swaps two loggers
+ */
+ void swap(wseverity_channel_logger& that);
+};
+
+/*!
+ * \brief Wide-char thread-safe logger. Functionally equivalent to \c basic_severity_logger and \c basic_channel_logger.
+ *
+ * See \c severity and \c channel class templates for a more detailed description
+ */
+template< typename LevelT = int, typename ChannelT = std::wstring >
+class wseverity_channel_logger_mt :
+ public basic_composite_logger<
+ wchar_t,
+ wseverity_channel_logger_mt< LevelT, ChannelT >,
+ multi_thread_model< implementation_defined >,
+ features<
+ severity< LevelT >,
+ channel< ChannelT >
+ >
+ >
+{
+public:
+ /*!
+ * Default constructor
+ */
+ wseverity_channel_logger_mt();
+ /*!
+ * Copy constructor
+ */
+ wseverity_channel_logger_mt(wseverity_channel_logger_mt const& that);
+ /*!
+ * Constructor with named arguments
+ */
+ template< typename... ArgsT >
+ explicit wseverity_channel_logger_mt(ArgsT... const& args);
+ /*!
+ * Assignment operator
+ */
+ wseverity_channel_logger_mt& operator= (wseverity_channel_logger_mt const& that)
+ /*!
+ * Swaps two loggers
+ */
+ void swap(wseverity_channel_logger_mt& that);
+};
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+} // namespace sources
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+//! The macro allows to put a record with a specific channel name into log
+#define BOOST_LOG_STREAM_CHANNEL_SEV(logger, chan, lvl)\
+ BOOST_LOG_STREAM_WITH_PARAMS((logger), (::boost::log::keywords::channel = (chan))(::boost::log::keywords::severity = (lvl)))
+
+#ifndef BOOST_LOG_NO_SHORTHAND_NAMES
+
+//! An equivalent to BOOST_LOG_STREAM_CHANNEL_SEV(logger, chan, lvl)
+#define BOOST_LOG_CHANNEL_SEV(logger, chan, lvl) BOOST_LOG_STREAM_CHANNEL_SEV(logger, chan, lvl)
+
+#endif // BOOST_LOG_NO_SHORTHAND_NAMES
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SOURCES_SEVERITY_CHANNEL_LOGGER_HPP_INCLUDED_
diff --git a/boost/log/sources/severity_feature.hpp b/boost/log/sources/severity_feature.hpp
new file mode 100644
index 0000000000..ae34c4c587
--- /dev/null
+++ b/boost/log/sources/severity_feature.hpp
@@ -0,0 +1,310 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file severity_feature.hpp
+ * \author Andrey Semashev
+ * \date 08.03.2007
+ *
+ * The header contains implementation of a severity level support feature.
+ */
+
+#ifndef BOOST_LOG_SOURCES_SEVERITY_FEATURE_HPP_INCLUDED_
+#define BOOST_LOG_SOURCES_SEVERITY_FEATURE_HPP_INCLUDED_
+
+#include <boost/cstdint.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/smart_ptr/intrusive_ptr.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/locks.hpp>
+#include <boost/log/detail/default_attribute_names.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/attributes/attribute_cast.hpp>
+#include <boost/log/attributes/attribute_value_impl.hpp>
+#include <boost/log/utility/strictest_lock.hpp>
+#include <boost/log/utility/type_dispatch/type_dispatcher.hpp>
+#include <boost/log/keywords/severity.hpp>
+#include <boost/log/core/record.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sources {
+
+namespace aux {
+
+ //! The method returns the storage for severity level for the current thread
+ BOOST_LOG_API uintmax_t& get_severity_level();
+
+ //! Severity level attribute implementation
+ template< typename LevelT >
+ class severity_level :
+ public attribute
+ {
+ typedef severity_level this_type;
+ BOOST_COPYABLE_AND_MOVABLE(this_type)
+
+ public:
+ //! Stored level type
+ typedef LevelT value_type;
+ BOOST_STATIC_ASSERT_MSG(sizeof(value_type) <= sizeof(uintmax_t), "Boost.Log: Unsupported severity level type, the severity level must fit into uintmax_t");
+
+ protected:
+ //! Factory implementation
+ class BOOST_SYMBOL_VISIBLE impl :
+ public attribute_value::impl
+ {
+ public:
+ //! The method dispatches the value to the given object
+ bool dispatch(type_dispatcher& dispatcher)
+ {
+ type_dispatcher::callback< value_type > callback = dispatcher.get_callback< value_type >();
+ if (callback)
+ {
+ callback(reinterpret_cast< value_type const& >(get_severity_level()));
+ return true;
+ }
+ else
+ return false;
+ }
+
+ //! The method is called when the attribute value is passed to another thread
+ intrusive_ptr< attribute_value::impl > detach_from_thread()
+ {
+ #if !defined(BOOST_LOG_NO_THREADS)
+ return new attributes::attribute_value_impl< value_type >(
+ reinterpret_cast< value_type const& >(get_severity_level()));
+ #else
+ // With multithreading disabled we may safely return this here. This method will not be called anyway.
+ return this;
+ #endif
+ }
+ };
+
+ public:
+ //! Default constructor
+ severity_level() : attribute(new impl())
+ {
+ }
+ //! Copy constructor
+ severity_level(severity_level const& that) : attribute(static_cast< attribute const& >(that))
+ {
+ }
+ //! Move constructor
+ severity_level(BOOST_RV_REF(severity_level) that) : attribute(boost::move(static_cast< attribute& >(that)))
+ {
+ }
+ //! Constructor for casting support
+ explicit severity_level(attributes::cast_source const& source) :
+ attribute(source.as< impl >())
+ {
+ }
+
+ /*!
+ * Copy assignment
+ */
+ severity_level& operator= (BOOST_COPY_ASSIGN_REF(severity_level) that)
+ {
+ attribute::operator= (that);
+ return *this;
+ }
+
+ /*!
+ * Move assignment
+ */
+ severity_level& operator= (BOOST_RV_REF(severity_level) that)
+ {
+ this->swap(that);
+ return *this;
+ }
+
+ //! The method sets the actual level
+ void set_value(value_type level)
+ {
+ reinterpret_cast< value_type& >(get_severity_level()) = level;
+ }
+ };
+
+} // namespace aux
+
+/*!
+ * \brief Severity level feature implementation
+ */
+template< typename BaseT, typename LevelT = int >
+class basic_severity_logger :
+ public BaseT
+{
+ //! Base type
+ typedef BaseT base_type;
+ typedef basic_severity_logger this_type;
+ BOOST_COPYABLE_AND_MOVABLE_ALT(this_type)
+
+public:
+ //! Character type
+ typedef typename base_type::char_type char_type;
+ //! Final type
+ typedef typename base_type::final_type final_type;
+ //! Threading model being used
+ typedef typename base_type::threading_model threading_model;
+
+ //! Severity level type
+ typedef LevelT severity_level;
+ //! Severity attribute type
+ typedef aux::severity_level< severity_level > severity_attribute;
+
+#if defined(BOOST_LOG_DOXYGEN_PASS)
+ //! Lock requirement for the \c open_record_unlocked method
+ typedef typename strictest_lock<
+ typename base_type::open_record_lock,
+ no_lock< threading_model >
+ >::type open_record_lock;
+#endif // defined(BOOST_LOG_DOXYGEN_PASS)
+
+ //! Lock requirement for the \c swap_unlocked method
+ typedef typename strictest_lock<
+ typename base_type::swap_lock,
+#ifndef BOOST_LOG_NO_THREADS
+ boost::log::aux::exclusive_lock_guard< threading_model >
+#else
+ no_lock< threading_model >
+#endif // !defined(BOOST_LOG_NO_THREADS)
+ >::type swap_lock;
+
+private:
+ //! Default severity
+ severity_level m_DefaultSeverity;
+ //! Severity attribute
+ severity_attribute m_SeverityAttr;
+
+public:
+ /*!
+ * Default constructor. The constructed logger will have a severity attribute registered.
+ * The default level for log records will be 0.
+ */
+ basic_severity_logger() :
+ base_type(),
+ m_DefaultSeverity(static_cast< severity_level >(0))
+ {
+ base_type::add_attribute_unlocked(boost::log::aux::default_attribute_names::severity(), m_SeverityAttr);
+ }
+ /*!
+ * Copy constructor
+ */
+ basic_severity_logger(basic_severity_logger const& that) :
+ base_type(static_cast< base_type const& >(that)),
+ m_DefaultSeverity(that.m_DefaultSeverity),
+ m_SeverityAttr(that.m_SeverityAttr)
+ {
+ base_type::attributes()[boost::log::aux::default_attribute_names::severity()] = m_SeverityAttr;
+ }
+ /*!
+ * Move constructor
+ */
+ basic_severity_logger(BOOST_RV_REF(basic_severity_logger) that) :
+ base_type(boost::move(static_cast< base_type& >(that))),
+ m_DefaultSeverity(boost::move(that.m_DefaultSeverity)),
+ m_SeverityAttr(boost::move(that.m_SeverityAttr))
+ {
+ base_type::attributes()[boost::log::aux::default_attribute_names::severity()] = m_SeverityAttr;
+ }
+ /*!
+ * Constructor with named arguments. Allows to setup the default level for log records.
+ *
+ * \param args A set of named arguments. The following arguments are supported:
+ * \li \c severity - default severity value
+ */
+ template< typename ArgsT >
+ explicit basic_severity_logger(ArgsT const& args) :
+ base_type(args),
+ m_DefaultSeverity(args[keywords::severity | severity_level()])
+ {
+ base_type::add_attribute_unlocked(boost::log::aux::default_attribute_names::severity(), m_SeverityAttr);
+ }
+
+ /*!
+ * Default severity value getter
+ */
+ severity_level default_severity() const { return m_DefaultSeverity; }
+
+protected:
+ /*!
+ * Severity attribute accessor
+ */
+ severity_attribute const& get_severity_attribute() const { return m_SeverityAttr; }
+
+ /*!
+ * Unlocked \c open_record
+ */
+ template< typename ArgsT >
+ record open_record_unlocked(ArgsT const& args)
+ {
+ m_SeverityAttr.set_value(args[keywords::severity | m_DefaultSeverity]);
+ return base_type::open_record_unlocked(args);
+ }
+
+ //! Unlocked \c swap
+ void swap_unlocked(basic_severity_logger& that)
+ {
+ base_type::swap_unlocked(static_cast< base_type& >(that));
+ severity_level t = m_DefaultSeverity;
+ m_DefaultSeverity = that.m_DefaultSeverity;
+ that.m_DefaultSeverity = t;
+ m_SeverityAttr.swap(that.m_SeverityAttr);
+ }
+};
+
+/*!
+ * \brief Severity level support feature
+ *
+ * The logger with this feature registers a special attribute with an integral value type on construction.
+ * This attribute will provide severity level for each log record being made through the logger.
+ * The severity level can be omitted on logging record construction, in which case the default
+ * level will be used. The default level can also be customized by passing it to the logger constructor.
+ *
+ * The type of the severity level attribute can be specified as a template parameter for the feature
+ * template. By default, \c int will be used.
+ */
+template< typename LevelT = int >
+struct severity
+{
+ template< typename BaseT >
+ struct apply
+ {
+ typedef basic_severity_logger<
+ BaseT,
+ LevelT
+ > type;
+ };
+};
+
+} // namespace sources
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+//! The macro allows to put a record with a specific severity level into log
+#define BOOST_LOG_STREAM_SEV(logger, lvl)\
+ BOOST_LOG_STREAM_WITH_PARAMS((logger), (::boost::log::keywords::severity = (lvl)))
+
+#ifndef BOOST_LOG_NO_SHORTHAND_NAMES
+
+//! An equivalent to BOOST_LOG_STREAM_SEV(logger, lvl)
+#define BOOST_LOG_SEV(logger, lvl) BOOST_LOG_STREAM_SEV(logger, lvl)
+
+#endif // BOOST_LOG_NO_SHORTHAND_NAMES
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SOURCES_SEVERITY_FEATURE_HPP_INCLUDED_
diff --git a/boost/log/sources/severity_logger.hpp b/boost/log/sources/severity_logger.hpp
new file mode 100644
index 0000000000..4e9fa580c0
--- /dev/null
+++ b/boost/log/sources/severity_logger.hpp
@@ -0,0 +1,325 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file severity_logger.hpp
+ * \author Andrey Semashev
+ * \date 08.03.2007
+ *
+ * The header contains implementation of a logger with severity level support.
+ */
+
+#ifndef BOOST_LOG_SOURCES_SEVERITY_LOGGER_HPP_INCLUDED_
+#define BOOST_LOG_SOURCES_SEVERITY_LOGGER_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/log/detail/light_rw_mutex.hpp>
+#endif // !defined(BOOST_LOG_NO_THREADS)
+#include <boost/log/sources/features.hpp>
+#include <boost/log/sources/basic_logger.hpp>
+#include <boost/log/sources/threading_models.hpp>
+#include <boost/log/sources/severity_feature.hpp>
+#include <boost/log/keywords/severity.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sources {
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#ifdef BOOST_LOG_USE_CHAR
+
+//! Narrow-char logger with severity level support
+template< typename LevelT = int >
+class severity_logger :
+ public basic_composite_logger<
+ char,
+ severity_logger< LevelT >,
+ single_thread_model,
+ features< severity< LevelT > >
+ >
+{
+ typedef typename severity_logger::logger_base base_type;
+
+public:
+ BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(severity_logger)
+
+ explicit severity_logger(LevelT level) : base_type(keywords::severity = level)
+ {
+ }
+};
+
+#if !defined(BOOST_LOG_NO_THREADS)
+
+//! Narrow-char thread-safe logger with severity level support
+template< typename LevelT = int >
+class severity_logger_mt :
+ public basic_composite_logger<
+ char,
+ severity_logger_mt< LevelT >,
+ multi_thread_model< boost::log::aux::light_rw_mutex >,
+ features< severity< LevelT > >
+ >
+{
+ typedef typename severity_logger_mt::logger_base base_type;
+
+public:
+ BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(severity_logger_mt)
+
+ explicit severity_logger_mt(LevelT level) : base_type(keywords::severity = level)
+ {
+ }
+};
+
+#endif // !defined(BOOST_LOG_NO_THREADS)
+
+#endif
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+
+//! Wide-char logger with severity level support
+template< typename LevelT = int >
+class wseverity_logger :
+ public basic_composite_logger<
+ wchar_t,
+ wseverity_logger< LevelT >,
+ single_thread_model,
+ features< severity< LevelT > >
+ >
+{
+ typedef typename wseverity_logger::logger_base base_type;
+
+public:
+ BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(wseverity_logger)
+
+ explicit wseverity_logger(LevelT level) : base_type(keywords::severity = level)
+ {
+ }
+};
+
+#if !defined(BOOST_LOG_NO_THREADS)
+
+//! Wide-char thread-safe logger with severity level support
+template< typename LevelT = int >
+class wseverity_logger_mt :
+ public basic_composite_logger<
+ wchar_t,
+ wseverity_logger_mt< LevelT >,
+ multi_thread_model< boost::log::aux::light_rw_mutex >,
+ features< severity< LevelT > >
+ >
+{
+ typedef typename wseverity_logger_mt::logger_base base_type;
+
+public:
+ BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(wseverity_logger_mt)
+
+ explicit wseverity_logger_mt(LevelT level) : base_type(keywords::severity = level)
+ {
+ }
+};
+
+#endif // !defined(BOOST_LOG_NO_THREADS)
+
+#endif
+
+#else // BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * \brief Narrow-char logger. Functionally equivalent to \c basic_severity_logger.
+ *
+ * See \c severity class template for a more detailed description
+ */
+template< typename LevelT = int >
+class severity_logger :
+ public basic_composite_logger<
+ char,
+ severity_logger< LevelT >,
+ single_thread_model,
+ features< severity< LevelT > >
+ >
+{
+public:
+ /*!
+ * Default constructor
+ */
+ severity_logger();
+ /*!
+ * Copy constructor
+ */
+ severity_logger(severity_logger const& that);
+ /*!
+ * Constructor with named arguments
+ */
+ template< typename... ArgsT >
+ explicit severity_logger(ArgsT... const& args);
+ /*!
+ * The constructor creates the logger with the specified default severity level
+ *
+ * \param level The default severity level
+ */
+ explicit severity_logger(LevelT level);
+ /*!
+ * Assignment operator
+ */
+ severity_logger& operator= (severity_logger const& that)
+ /*!
+ * Swaps two loggers
+ */
+ void swap(severity_logger& that);
+};
+
+/*!
+ * \brief Narrow-char thread-safe logger. Functionally equivalent to \c basic_severity_logger.
+ *
+ * See \c severity class template for a more detailed description
+ */
+template< typename LevelT = int >
+class severity_logger_mt :
+ public basic_composite_logger<
+ char,
+ severity_logger_mt< LevelT >,
+ multi_thread_model< implementation_defined >,
+ features< severity< LevelT > >
+ >
+{
+public:
+ /*!
+ * Default constructor
+ */
+ severity_logger_mt();
+ /*!
+ * Copy constructor
+ */
+ severity_logger_mt(severity_logger_mt const& that);
+ /*!
+ * Constructor with named arguments
+ */
+ template< typename... ArgsT >
+ explicit severity_logger_mt(ArgsT... const& args);
+ /*!
+ * The constructor creates the logger with the specified default severity level
+ *
+ * \param level The default severity level
+ */
+ explicit severity_logger_mt(LevelT level);
+ /*!
+ * Assignment operator
+ */
+ severity_logger_mt& operator= (severity_logger_mt const& that)
+ /*!
+ * Swaps two loggers
+ */
+ void swap(severity_logger_mt& that);
+};
+
+/*!
+ * \brief Wide-char logger. Functionally equivalent to \c basic_severity_logger.
+ *
+ * See \c severity class template for a more detailed description
+ */
+template< typename LevelT = int >
+class wseverity_logger :
+ public basic_composite_logger<
+ wchar_t,
+ wseverity_logger< LevelT >,
+ single_thread_model,
+ features< severity< LevelT > >
+ >
+{
+public:
+ /*!
+ * Default constructor
+ */
+ wseverity_logger();
+ /*!
+ * Copy constructor
+ */
+ wseverity_logger(wseverity_logger const& that);
+ /*!
+ * Constructor with named arguments
+ */
+ template< typename... ArgsT >
+ explicit wseverity_logger(ArgsT... const& args);
+ /*!
+ * The constructor creates the logger with the specified default severity level
+ *
+ * \param level The default severity level
+ */
+ explicit wseverity_logger(LevelT level);
+ /*!
+ * Assignment operator
+ */
+ wseverity_logger& operator= (wseverity_logger const& that)
+ /*!
+ * Swaps two loggers
+ */
+ void swap(wseverity_logger& that);
+};
+
+/*!
+ * \brief Wide-char thread-safe logger. Functionally equivalent to \c basic_severity_logger.
+ *
+ * See \c severity class template for a more detailed description
+ */
+template< typename LevelT = int >
+class wseverity_logger_mt :
+ public basic_composite_logger<
+ wchar_t,
+ wseverity_logger_mt< LevelT >,
+ multi_thread_model< implementation_defined >,
+ features< severity< LevelT > >
+ >
+{
+public:
+ /*!
+ * Default constructor
+ */
+ wseverity_logger_mt();
+ /*!
+ * Copy constructor
+ */
+ wseverity_logger_mt(wseverity_logger_mt const& that);
+ /*!
+ * Constructor with named arguments
+ */
+ template< typename... ArgsT >
+ explicit wseverity_logger_mt(ArgsT... const& args);
+ /*!
+ * The constructor creates the logger with the specified default severity level
+ *
+ * \param level The default severity level
+ */
+ explicit wseverity_logger_mt(LevelT level);
+ /*!
+ * Assignment operator
+ */
+ wseverity_logger_mt& operator= (wseverity_logger_mt const& that)
+ /*!
+ * Swaps two loggers
+ */
+ void swap(wseverity_logger_mt& that);
+};
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+} // namespace sources
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SOURCES_SEVERITY_LOGGER_HPP_INCLUDED_
diff --git a/boost/log/sources/threading_models.hpp b/boost/log/sources/threading_models.hpp
new file mode 100644
index 0000000000..0cfaf80034
--- /dev/null
+++ b/boost/log/sources/threading_models.hpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file sources/threading_models.hpp
+ * \author Andrey Semashev
+ * \date 04.10.2008
+ *
+ * The header contains definition of threading models that can be used in loggers.
+ * The header also provides a number of tags that can be used to express lock requirements
+ * on a function callee.
+ */
+
+#ifndef BOOST_LOG_SOURCES_THREADING_MODELS_HPP_INCLUDED_
+#define BOOST_LOG_SOURCES_THREADING_MODELS_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/locks.hpp> // is_mutex_type
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/mpl/bool.hpp>
+#endif
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sources {
+
+//! Single thread locking model
+struct single_thread_model
+{
+ // We provide methods for the most advanced locking concept: UpgradeLockable
+ void lock_shared() const {}
+ bool try_lock_shared() const { return true; }
+ template< typename TimeT >
+ bool timed_lock_shared(TimeT const&) const { return true; }
+ void unlock_shared() const {}
+ void lock() const {}
+ bool try_lock() const { return true; }
+ template< typename TimeT >
+ bool timed_lock(TimeT const&) const { return true; }
+ void unlock() const {}
+ void lock_upgrade() const {}
+ bool try_lock_upgrade() const { return true; }
+ template< typename TimeT >
+ bool timed_lock_upgrade(TimeT const&) const { return true; }
+ void unlock_upgrade() const {}
+ void unlock_upgrade_and_lock() const {}
+ void unlock_and_lock_upgrade() const {}
+ void unlock_and_lock_shared() const {}
+ void unlock_upgrade_and_lock_shared() const {}
+
+ void swap(single_thread_model&) {}
+};
+
+#if !defined(BOOST_LOG_NO_THREADS)
+
+//! Multi-thread locking model with maximum locking capabilities
+template< typename MutexT >
+struct multi_thread_model
+{
+ multi_thread_model() {}
+ multi_thread_model(multi_thread_model const&) {}
+ multi_thread_model& operator= (multi_thread_model const&) { return *this; }
+
+ void lock_shared() const { m_Mutex.lock_shared(); }
+ bool try_lock_shared() const { return m_Mutex.try_lock_shared(); }
+ template< typename TimeT >
+ bool timed_lock_shared(TimeT const& t) const { return m_Mutex.timed_lock_shared(t); }
+ void unlock_shared() const { m_Mutex.unlock_shared(); }
+ void lock() const { m_Mutex.lock(); }
+ bool try_lock() const { return m_Mutex.try_lock(); }
+ template< typename TimeT >
+ bool timed_lock(TimeT const& t) const { return m_Mutex.timed_lock(t); }
+ void unlock() const { m_Mutex.unlock(); }
+ void lock_upgrade() const { m_Mutex.lock_upgrade(); }
+ bool try_lock_upgrade() const { return m_Mutex.try_lock_upgrade(); }
+ template< typename TimeT >
+ bool timed_lock_upgrade(TimeT const& t) const { return m_Mutex.timed_lock_upgrade(t); }
+ void unlock_upgrade() const { m_Mutex.unlock_upgrade(); }
+ void unlock_upgrade_and_lock() const { m_Mutex.unlock_upgrade_and_lock(); }
+ void unlock_and_lock_upgrade() const { m_Mutex.unlock_and_lock_upgrade(); }
+ void unlock_and_lock_shared() const { m_Mutex.unlock_and_lock_shared(); }
+ void unlock_upgrade_and_lock_shared() const { m_Mutex.unlock_upgrade_and_lock_shared(); }
+
+ void swap(multi_thread_model&) {}
+
+private:
+ //! Synchronization primitive
+ mutable MutexT m_Mutex;
+};
+
+#endif // !defined(BOOST_LOG_NO_THREADS)
+
+} // namespace sources
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+#if !defined(BOOST_LOG_NO_THREADS) && !defined(BOOST_LOG_DOXYGEN_PASS)
+
+template< >
+struct is_mutex_type< boost::log::sources::single_thread_model > : mpl::true_
+{
+};
+
+template< typename T >
+struct is_mutex_type< boost::log::sources::multi_thread_model< T > > : mpl::true_
+{
+};
+
+#endif // !defined(BOOST_LOG_NO_THREADS)
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SOURCES_THREADING_MODELS_HPP_INCLUDED_
diff --git a/boost/log/support/date_time.hpp b/boost/log/support/date_time.hpp
new file mode 100644
index 0000000000..97924ec401
--- /dev/null
+++ b/boost/log/support/date_time.hpp
@@ -0,0 +1,548 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file support/date_time.hpp
+ * \author Andrey Semashev
+ * \date 07.11.2012
+ *
+ * This header enables Boost.DateTime support for Boost.Log.
+ */
+
+#ifndef BOOST_LOG_SUPPORT_DATE_TIME_HPP_INCLUDED_
+#define BOOST_LOG_SUPPORT_DATE_TIME_HPP_INCLUDED_
+
+#include <ctime>
+#include <string>
+#include <locale>
+#include <ostream>
+#include <iterator>
+#include <boost/cstdint.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/date_time/time.hpp>
+#include <boost/date_time/date.hpp>
+#include <boost/date_time/gregorian/gregorian_types.hpp>
+#include <boost/date_time/local_time/local_time_types.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/date_time_format_parser.hpp>
+#include <boost/log/detail/light_function.hpp>
+#include <boost/log/detail/decomposed_time.hpp>
+#include <boost/log/detail/date_time_fmt_gen_traits_fwd.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+namespace aux {
+
+namespace date_time_support {
+
+template< typename DateT, typename ValueT >
+inline void decompose_date(DateT const& d, boost::log::aux::decomposed_time_wrapper< ValueT >& v)
+{
+ typedef typename DateT::ymd_type ymd_type;
+ ymd_type ymd = d.year_month_day();
+ v.year = ymd.year;
+ v.month = ymd.month;
+ v.day = ymd.day;
+}
+
+template< typename TimeDurationT, typename ValueT >
+inline void decompose_time_of_day(TimeDurationT const& tod, boost::log::aux::decomposed_time_wrapper< ValueT >& v)
+{
+ v.hours = tod.hours();
+ v.minutes = tod.minutes();
+ v.seconds = tod.seconds();
+
+ typedef typename TimeDurationT::traits_type traits_type;
+ enum
+ {
+ adjustment_ratio = (traits_type::ticks_per_second > boost::log::aux::decomposed_time::subseconds_per_second ?
+ traits_type::ticks_per_second / boost::log::aux::decomposed_time::subseconds_per_second :
+ boost::log::aux::decomposed_time::subseconds_per_second / traits_type::ticks_per_second)
+ };
+ uint64_t frac = tod.fractional_seconds();
+ v.subseconds = static_cast< uint32_t >(traits_type::ticks_per_second > boost::log::aux::decomposed_time::subseconds_per_second ? frac / adjustment_ratio : frac * adjustment_ratio);
+}
+
+template< typename TimeDurationT, typename ValueT >
+inline void decompose_time_duration(TimeDurationT const& dur, boost::log::aux::decomposed_time_wrapper< ValueT >& v)
+{
+ if (dur.is_negative())
+ {
+ v.negative = true;
+ (decompose_time_of_day)(-dur, v);
+ }
+ else
+ (decompose_time_of_day)(dur, v);
+}
+
+template< typename DateDurationT, typename ValueT >
+inline void decompose_date_duration(DateDurationT const& dur, boost::log::aux::decomposed_time_wrapper< ValueT >& v)
+{
+ if (dur.is_negative())
+ {
+ v.negative = true;
+ v.day = (-dur).days();
+ }
+ else
+ v.day = dur.days();
+}
+
+template< typename TimeT, typename ValueT >
+inline void decompose_time(TimeT const& t, boost::log::aux::decomposed_time_wrapper< ValueT >& v)
+{
+ (decompose_date)(t.date(), v);
+ (decompose_time_of_day)(t.time_of_day(), v);
+}
+
+} // namespace date_time_support
+
+template< typename TimeT, typename CharT >
+struct date_time_formatter_generator_traits_impl
+{
+ //! Character type
+ typedef CharT char_type;
+ //! String type
+ typedef std::basic_string< char_type > string_type;
+ //! Formatting stream type
+ typedef basic_formatting_ostream< char_type > stream_type;
+ //! Value type
+ typedef TimeT value_type;
+
+ //! Formatter function
+ typedef boost::log::aux::light_function< void (stream_type&, value_type const&) > formatter_function_type;
+
+ //! Formatter implementation
+ class formatter :
+ public boost::log::aux::date_time_formatter< boost::log::aux::decomposed_time_wrapper< value_type >, char_type >
+ {
+ BOOST_COPYABLE_AND_MOVABLE_ALT(formatter)
+
+ private:
+ // Do not change this typedef, copy-pasting the inherited class from above will break compilation with MSVC 2012 because it incorrectly binds value_type.
+ typedef typename formatter::date_time_formatter_ base_type;
+
+ public:
+ typedef typename base_type::result_type result_type;
+ // This typedef is needed to work around MSVC 2012 crappy name lookup. Otherwise base_type::value_type is bound instead.
+ typedef typename date_time_formatter_generator_traits_impl< TimeT, CharT >::value_type value_type;
+
+ public:
+ BOOST_DEFAULTED_FUNCTION(formatter(), {})
+ formatter(formatter const& that) : base_type(static_cast< base_type const& >(that)) {}
+ formatter(BOOST_RV_REF(formatter) that) { this->swap(that); }
+
+ formatter& operator= (formatter that)
+ {
+ this->swap(that);
+ return *this;
+ }
+
+ result_type operator() (stream_type& strm, value_type const& value) const
+ {
+ if (value.is_not_a_date_time())
+ strm << "not-a-date-time";
+ else if (value.is_pos_infinity())
+ strm << "+infinity";
+ else if (value.is_neg_infinity())
+ strm << "-infinity";
+ else
+ {
+ boost::log::aux::decomposed_time_wrapper< value_type > val(value);
+ date_time_support::decompose_time(value, val);
+ base_type::operator() (strm, val);
+ }
+ }
+ };
+
+ //! The function parses format string and constructs formatter function
+ static formatter_function_type parse(string_type const& format)
+ {
+ formatter fmt;
+ boost::log::aux::decomposed_time_formatter_builder< formatter, char_type > builder(fmt);
+ boost::log::aux::parse_date_time_format(format, builder);
+ return formatter_function_type(boost::move(fmt));
+ }
+};
+
+template< typename CharT, typename VoidT >
+struct date_time_formatter_generator_traits< posix_time::ptime, CharT, VoidT > :
+ public date_time_formatter_generator_traits_impl< posix_time::ptime, CharT >
+{
+};
+
+template< typename TimeT, typename TimeZoneT, typename CharT, typename VoidT >
+struct date_time_formatter_generator_traits< local_time::local_date_time_base< TimeT, TimeZoneT >, CharT, VoidT >
+{
+ //! Character type
+ typedef CharT char_type;
+ //! String type
+ typedef std::basic_string< char_type > string_type;
+ //! Formatting stream type
+ typedef basic_formatting_ostream< char_type > stream_type;
+ //! Value type
+ typedef local_time::local_date_time_base< TimeT, TimeZoneT > value_type;
+
+ //! Formatter function
+ typedef boost::log::aux::light_function< void (stream_type&, value_type const&) > formatter_function_type;
+
+ //! Formatter implementation
+ class formatter :
+ public boost::log::aux::date_time_formatter< boost::log::aux::decomposed_time_wrapper< value_type >, char_type >
+ {
+ BOOST_COPYABLE_AND_MOVABLE_ALT(formatter)
+
+ private:
+ // Do not change this typedef, copy-pasting the inherited class from above will break compilation with MSVC 2012 because it incorrectly binds value_type.
+ typedef typename formatter::date_time_formatter_ base_type;
+
+ public:
+ typedef typename base_type::result_type result_type;
+ typedef typename base_type::context context;
+ // This typedef is needed to work around MSVC 2012 crappy name lookup. Otherwise base_type::value_type is bound instead.
+ typedef typename date_time_formatter_generator_traits< local_time::local_date_time_base< TimeT, TimeZoneT >, CharT, VoidT >::value_type value_type;
+
+ public:
+ BOOST_DEFAULTED_FUNCTION(formatter(), {})
+ formatter(formatter const& that) : base_type(static_cast< base_type const& >(that)) {}
+ formatter(BOOST_RV_REF(formatter) that) { this->swap(that); }
+
+ formatter& operator= (formatter that)
+ {
+ this->swap(that);
+ return *this;
+ }
+
+ result_type operator() (stream_type& strm, value_type const& value) const
+ {
+ if (value.is_not_a_date_time())
+ strm << "not-a-date-time";
+ else if (value.is_pos_infinity())
+ strm << "+infinity";
+ else if (value.is_neg_infinity())
+ strm << "-infinity";
+ else
+ {
+ boost::log::aux::decomposed_time_wrapper< value_type > val(value);
+ date_time_support::decompose_time(value.local_time(), val);
+ base_type::operator() (strm, val);
+ }
+ }
+
+ public:
+ static void format_iso_time_zone(context& ctx)
+ {
+ ctx.strm << ctx.value.m_time.zone_abbrev(true);
+ ctx.strm.flush();
+ }
+
+ static void format_extended_iso_time_zone(context& ctx)
+ {
+ ctx.strm << ctx.value.m_time.zone_name(true);
+ ctx.strm.flush();
+ }
+ };
+
+ class formatter_builder :
+ public boost::log::aux::decomposed_time_formatter_builder< formatter, char_type >
+ {
+ private:
+ typedef boost::log::aux::decomposed_time_formatter_builder< formatter, char_type > base_type;
+
+ public:
+ explicit formatter_builder(formatter& fmt) : base_type(fmt)
+ {
+ }
+
+ void on_iso_time_zone()
+ {
+ this->m_formatter.add_formatter(&formatter::format_iso_time_zone);
+ }
+
+ void on_extended_iso_time_zone()
+ {
+ this->m_formatter.add_formatter(&formatter::format_extended_iso_time_zone);
+ }
+ };
+
+ //! The function parses format string and constructs formatter function
+ static formatter_function_type parse(string_type const& format)
+ {
+ formatter fmt;
+ formatter_builder builder(fmt);
+ boost::log::aux::parse_date_time_format(format, builder);
+ return formatter_function_type(boost::move(fmt));
+ }
+};
+
+template< typename DateT, typename CharT >
+struct date_formatter_generator_traits_impl
+{
+ //! Character type
+ typedef CharT char_type;
+ //! String type
+ typedef std::basic_string< char_type > string_type;
+ //! Formatting stream type
+ typedef basic_formatting_ostream< char_type > stream_type;
+ //! Value type
+ typedef DateT value_type;
+
+ //! Formatter function
+ typedef boost::log::aux::light_function< void (stream_type&, value_type const&) > formatter_function_type;
+
+ //! Formatter implementation
+ class formatter :
+ public boost::log::aux::date_time_formatter< boost::log::aux::decomposed_time_wrapper< value_type >, char_type >
+ {
+ BOOST_COPYABLE_AND_MOVABLE_ALT(formatter)
+
+ private:
+ // Do not change this typedef, copy-pasting the inherited class from above will break compilation with MSVC 2012 because it incorrectly binds value_type.
+ typedef typename formatter::date_time_formatter_ base_type;
+
+ public:
+ typedef typename base_type::result_type result_type;
+ // This typedef is needed to work around MSVC 2012 crappy name lookup. Otherwise base_type::value_type is bound instead.
+ typedef typename date_formatter_generator_traits_impl< DateT, CharT >::value_type value_type;
+
+ public:
+ BOOST_DEFAULTED_FUNCTION(formatter(), {})
+ formatter(formatter const& that) : base_type(static_cast< base_type const& >(that)) {}
+ formatter(BOOST_RV_REF(formatter) that) { this->swap(that); }
+
+ formatter& operator= (formatter that)
+ {
+ this->swap(that);
+ return *this;
+ }
+
+ result_type operator() (stream_type& strm, value_type const& value) const
+ {
+ if (value.is_not_a_date())
+ strm << "not-a-date-time";
+ else if (value.is_pos_infinity())
+ strm << "+infinity";
+ else if (value.is_neg_infinity())
+ strm << "-infinity";
+ else
+ {
+ boost::log::aux::decomposed_time_wrapper< value_type > val(value);
+ date_time_support::decompose_date(value, val);
+ base_type::operator() (strm, val);
+ }
+ }
+ };
+
+ //! The function parses format string and constructs formatter function
+ static formatter_function_type parse(string_type const& format)
+ {
+ formatter fmt;
+ boost::log::aux::decomposed_time_formatter_builder< formatter, char_type > builder(fmt);
+ boost::log::aux::parse_date_format(format, builder);
+ return formatter_function_type(boost::move(fmt));
+ }
+};
+
+template< typename CharT, typename VoidT >
+struct date_time_formatter_generator_traits< gregorian::date, CharT, VoidT > :
+ public date_formatter_generator_traits_impl< gregorian::date, CharT >
+{
+};
+
+template< typename TimeDurationT, typename CharT >
+struct time_duration_formatter_generator_traits_impl
+{
+ //! Character type
+ typedef CharT char_type;
+ //! String type
+ typedef std::basic_string< char_type > string_type;
+ //! Formatting stream type
+ typedef basic_formatting_ostream< char_type > stream_type;
+ //! Value type
+ typedef TimeDurationT value_type;
+
+ //! Formatter function
+ typedef boost::log::aux::light_function< void (stream_type&, value_type const&) > formatter_function_type;
+
+ //! Formatter implementation
+ class formatter :
+ public boost::log::aux::date_time_formatter< boost::log::aux::decomposed_time_wrapper< value_type >, char_type >
+ {
+ BOOST_COPYABLE_AND_MOVABLE_ALT(formatter)
+
+ private:
+ // Do not change this typedef, copy-pasting the inherited class from above will break compilation with MSVC 2012 because it incorrectly binds value_type.
+ typedef typename formatter::date_time_formatter_ base_type;
+
+ public:
+ typedef typename base_type::result_type result_type;
+ // This typedef is needed to work around MSVC 2012 crappy name lookup. Otherwise base_type::value_type is bound instead.
+ typedef typename time_duration_formatter_generator_traits_impl< TimeDurationT, CharT >::value_type value_type;
+
+ public:
+ BOOST_DEFAULTED_FUNCTION(formatter(), {})
+ formatter(formatter const& that) : base_type(static_cast< base_type const& >(that)) {}
+ formatter(BOOST_RV_REF(formatter) that) { this->swap(that); }
+
+ formatter& operator= (formatter that)
+ {
+ this->swap(that);
+ return *this;
+ }
+
+ result_type operator() (stream_type& strm, value_type const& value) const
+ {
+ if (value.is_not_a_date_time())
+ strm << "not-a-date-time";
+ else if (value.is_pos_infinity())
+ strm << "+infinity";
+ else if (value.is_neg_infinity())
+ strm << "-infinity";
+ else
+ {
+ boost::log::aux::decomposed_time_wrapper< value_type > val(value);
+ date_time_support::decompose_time_duration(value, val);
+ base_type::operator() (strm, val);
+ }
+ }
+ };
+
+ //! The function parses format string and constructs formatter function
+ static formatter_function_type parse(string_type const& format)
+ {
+ formatter fmt;
+ boost::log::aux::decomposed_time_formatter_builder< formatter, char_type > builder(fmt);
+ boost::log::aux::parse_time_format(format, builder);
+ return formatter_function_type(boost::move(fmt));
+ }
+};
+
+template< typename CharT, typename VoidT >
+struct date_time_formatter_generator_traits< posix_time::time_duration, CharT, VoidT > :
+ public time_duration_formatter_generator_traits_impl< posix_time::time_duration, CharT >
+{
+};
+
+template< typename CharT, typename VoidT >
+struct date_time_formatter_generator_traits< posix_time::hours, CharT, VoidT > :
+ public time_duration_formatter_generator_traits_impl< posix_time::hours, CharT >
+{
+};
+
+template< typename CharT, typename VoidT >
+struct date_time_formatter_generator_traits< posix_time::minutes, CharT, VoidT > :
+ public time_duration_formatter_generator_traits_impl< posix_time::minutes, CharT >
+{
+};
+
+template< typename CharT, typename VoidT >
+struct date_time_formatter_generator_traits< posix_time::seconds, CharT, VoidT > :
+ public time_duration_formatter_generator_traits_impl< posix_time::seconds, CharT >
+{
+};
+
+template< typename BaseDurationT, uint64_t FracOfSecondV, typename CharT, typename VoidT >
+struct date_time_formatter_generator_traits< date_time::subsecond_duration< BaseDurationT, FracOfSecondV >, CharT, VoidT > :
+ public time_duration_formatter_generator_traits_impl< date_time::subsecond_duration< BaseDurationT, FracOfSecondV >, CharT >
+{
+};
+
+template< typename DateDurationT, typename CharT >
+struct date_duration_formatter_generator_traits_impl
+{
+ //! Character type
+ typedef CharT char_type;
+ //! String type
+ typedef std::basic_string< char_type > string_type;
+ //! Formatting stream type
+ typedef basic_formatting_ostream< char_type > stream_type;
+ //! Value type
+ typedef DateDurationT value_type;
+
+ //! Formatter function
+ typedef boost::log::aux::light_function< void (stream_type&, value_type const&) > formatter_function_type;
+
+ //! Formatter implementation
+ class formatter :
+ public boost::log::aux::date_time_formatter< boost::log::aux::decomposed_time_wrapper< value_type >, char_type >
+ {
+ BOOST_COPYABLE_AND_MOVABLE_ALT(formatter)
+
+ private:
+ // Do not change this typedef, copy-pasting the inherited class from above will break compilation with MSVC 2012 because it incorrectly binds value_type.
+ typedef typename formatter::date_time_formatter_ base_type;
+
+ public:
+ typedef typename base_type::result_type result_type;
+ // This typedef is needed to work around MSVC 2012 crappy name lookup. Otherwise base_type::value_type is bound instead.
+ typedef typename date_duration_formatter_generator_traits_impl< DateDurationT, CharT >::value_type value_type;
+
+ public:
+ BOOST_DEFAULTED_FUNCTION(formatter(), {})
+ formatter(formatter const& that) : base_type(static_cast< base_type const& >(that)) {}
+ formatter(BOOST_RV_REF(formatter) that) { this->swap(that); }
+
+ formatter& operator= (formatter that)
+ {
+ this->swap(that);
+ return *this;
+ }
+
+ result_type operator() (stream_type& strm, value_type const& value) const
+ {
+ if (value.is_not_a_date())
+ strm << "not-a-date-time";
+ else if (value.is_pos_infinity())
+ strm << "+infinity";
+ else if (value.is_neg_infinity())
+ strm << "-infinity";
+ else
+ {
+ boost::log::aux::decomposed_time_wrapper< value_type > val(value);
+ date_time_support::decompose_date_duration(value, val);
+ base_type::operator() (strm, val);
+ }
+ }
+ };
+
+ //! The function parses format string and constructs formatter function
+ static formatter_function_type parse(string_type const& format)
+ {
+ formatter fmt;
+ boost::log::aux::decomposed_time_formatter_builder< formatter, char_type > builder(fmt);
+ boost::log::aux::parse_date_format(format, builder);
+ return formatter_function_type(boost::move(fmt));
+ }
+};
+
+template< typename CharT, typename VoidT >
+struct date_time_formatter_generator_traits< gregorian::date_duration, CharT, VoidT > :
+ public date_formatter_generator_traits_impl< gregorian::date_duration, CharT >
+{
+};
+
+} // namespace aux
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SUPPORT_DATE_TIME_HPP_INCLUDED_
diff --git a/boost/log/support/exception.hpp b/boost/log/support/exception.hpp
new file mode 100644
index 0000000000..3b0ff9767b
--- /dev/null
+++ b/boost/log/support/exception.hpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file support/exception.hpp
+ * \author Andrey Semashev
+ * \date 18.07.2009
+ *
+ * This header enables Boost.Exception support for Boost.Log.
+ */
+
+#ifndef BOOST_LOG_SUPPORT_EXCEPTION_HPP_INCLUDED_
+#define BOOST_LOG_SUPPORT_EXCEPTION_HPP_INCLUDED_
+
+#include <boost/exception/info.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/named_scope.hpp>
+#include <boost/log/utility/type_info_wrapper.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * Attribute name exception information
+ */
+typedef error_info< struct attribute_name_info_tag, attribute_name > attribute_name_info;
+
+/*!
+ * Type info exception information
+ */
+typedef error_info< struct type_info_info_tag, type_info_wrapper > type_info_info;
+
+/*!
+ * Parse position exception information
+ */
+typedef error_info< struct position_info_tag, unsigned int > position_info;
+
+/*!
+ * Current scope exception information
+ */
+typedef error_info< struct current_scope_info_tag, attributes::named_scope_list > current_scope_info;
+
+/*!
+ * The function returns an error information object that contains current stack of scopes.
+ * This information can then be attached to an exception and extracted at the catch site.
+ * The extracted scope list won't be affected by any scope changes that may happen during
+ * the exception propagation.
+ *
+ * \note See the \c named_scope attribute documentation on how to maintain scope list.
+ */
+inline current_scope_info current_scope()
+{
+ return current_scope_info(attributes::named_scope::get_scopes());
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SUPPORT_EXCEPTION_HPP_INCLUDED_
diff --git a/boost/log/support/regex.hpp b/boost/log/support/regex.hpp
new file mode 100644
index 0000000000..cecb106ad6
--- /dev/null
+++ b/boost/log/support/regex.hpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file support/regex.hpp
+ * \author Andrey Semashev
+ * \date 18.07.2009
+ *
+ * This header enables Boost.Regex support for Boost.Log.
+ */
+
+#ifndef BOOST_LOG_SUPPORT_REGEX_HPP_INCLUDED_
+#define BOOST_LOG_SUPPORT_REGEX_HPP_INCLUDED_
+
+#include <string>
+#include <boost/regex.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/utility/functional/matches.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! This tag type is used if an expression is recognized as a Boost.Regex expression
+struct boost_regex_expression_tag;
+
+//! The metafunction detects the matching expression kind and returns a tag that is used to specialize \c match_traits
+template< typename CharT, typename TraitsT >
+struct matching_expression_kind< boost::basic_regex< CharT, TraitsT > >
+{
+ typedef boost_regex_expression_tag type;
+};
+
+//! The matching function implementation
+template< typename ExpressionT >
+struct match_traits< ExpressionT, boost_regex_expression_tag >
+{
+ typedef ExpressionT compiled_type;
+ static compiled_type compile(ExpressionT const& expr) { return expr; }
+
+ template< typename StringT, typename CharT, typename TraitsT >
+ static bool matches(StringT const& str, boost::basic_regex< CharT, TraitsT > const& expr, boost::regex_constants::match_flag_type flags = boost::regex_constants::match_default)
+ {
+ return boost::regex_match(str.begin(), str.end(), expr, flags);
+ }
+
+ template< typename CharT, typename StringTraitsT, typename AllocatorT, typename ReTraitsT >
+ static bool matches(
+ std::basic_string< CharT, StringTraitsT, AllocatorT > const& str,
+ boost::basic_regex< CharT, ReTraitsT > const& expr,
+ boost::regex_constants::match_flag_type flags = boost::regex_constants::match_default)
+ {
+ const CharT* p = str.c_str();
+ return boost::regex_match(p, p + str.size(), expr, flags);
+ }
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SUPPORT_REGEX_HPP_INCLUDED_
diff --git a/boost/log/support/spirit_classic.hpp b/boost/log/support/spirit_classic.hpp
new file mode 100644
index 0000000000..fb8a6f047d
--- /dev/null
+++ b/boost/log/support/spirit_classic.hpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file support/spirit_classic.hpp
+ * \author Andrey Semashev
+ * \date 19.07.2009
+ *
+ * This header enables Boost.Spirit (classic) support for Boost.Log.
+ */
+
+#ifndef BOOST_LOG_SUPPORT_SPIRIT_CLASSIC_HPP_INCLUDED_
+#define BOOST_LOG_SUPPORT_SPIRIT_CLASSIC_HPP_INCLUDED_
+
+#include <boost/mpl/bool.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/utility/functional/matches.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if !defined(BOOST_LOG_NO_THREADS) && !defined(BOOST_SPIRIT_THREADSAFE) && !defined(BOOST_LOG_DOXYGEN_PASS)
+/*
+ * As Boost.Log filters may be called in multiple threads concurrently,
+ * this may lead to using Boost.Spirit parsers in a multithreaded context.
+ * In order to protect parsers properly, BOOST_SPIRIT_THREADSAFE macro should
+ * be defined.
+ *
+ * If we got here, it means that the user did not define that macro and we
+ * have to define it ourselves. However, it may also lead to ODR violations
+ * or even total ignorance of this macro, if the user has included Boost.Spirit
+ * headers before including this header, or uses Boost.Spirit without the macro
+ * in other translation units. The only reliable way to settle this problem is to
+ * define the macro for the whole project (i.e. all translation units).
+ */
+#if defined(__GNUC__)
+#pragma message "Boost.Log: Boost.Spirit requires BOOST_SPIRIT_THREADSAFE macro to be defined if parsers are used in a multithreaded context. It is strongly recommended to define this macro project-wide."
+#elif defined(_MSC_VER)
+#pragma message("Boost.Log: Boost.Spirit requires BOOST_SPIRIT_THREADSAFE macro to be defined if parsers are used in a multithreaded context. It is strongly recommended to define this macro project-wide.")
+#endif
+#define BOOST_SPIRIT_THREADSAFE 1
+#endif // !defined(BOOST_LOG_NO_THREADS) && !defined(BOOST_SPIRIT_THREADSAFE)
+
+#include <boost/spirit/include/classic_parser.hpp>
+
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! This tag type is used if an expression is recognized as a Boost.Spirit.Classic expression
+struct boost_spirit_classic_expression_tag;
+
+//! The trait verifies if the type can be converted to a Boost.Spirit (classic) parser
+template< typename T >
+struct is_spirit_classic_parser
+{
+private:
+ typedef char yes_type;
+ struct no_type { char dummy[2]; };
+
+ template< typename U >
+ static yes_type check_spirit_classic_parser(spirit::classic::parser< U > const&);
+ static no_type check_spirit_classic_parser(...);
+ static T& get_T();
+
+public:
+ enum { value = sizeof(check_spirit_classic_parser(get_T())) == sizeof(yes_type) };
+ typedef mpl::bool_< value > type;
+};
+
+//! The metafunction detects the matching expression kind and returns a tag that is used to specialize \c match_traits
+template< typename ExpressionT >
+struct matching_expression_kind< ExpressionT, typename boost::enable_if_c< is_spirit_classic_parser< ExpressionT >::value >::type >
+{
+ typedef boost_spirit_classic_expression_tag type;
+};
+
+//! The matching function implementation
+template< typename ExpressionT >
+struct match_traits< ExpressionT, boost_spirit_classic_expression_tag >
+{
+ typedef ExpressionT compiled_type;
+ static compiled_type compile(ExpressionT const& expr) { return expr; }
+
+ template< typename StringT >
+ static bool matches(StringT const& str, ExpressionT const& expr)
+ {
+ typedef typename StringT::const_iterator const_iterator;
+ spirit::classic::parse_info< const_iterator > info =
+ spirit::classic::parse(str.begin(), str.end(), expr);
+ return info.full;
+ }
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SUPPORT_SPIRIT_CLASSIC_HPP_INCLUDED_
diff --git a/boost/log/support/spirit_qi.hpp b/boost/log/support/spirit_qi.hpp
new file mode 100644
index 0000000000..48c0059a44
--- /dev/null
+++ b/boost/log/support/spirit_qi.hpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file support/spirit_qi.hpp
+ * \author Andrey Semashev
+ * \date 19.07.2009
+ *
+ * This header enables Boost.Spirit.Qi support for Boost.Log.
+ */
+
+#ifndef BOOST_LOG_SUPPORT_SPIRIT_QI_HPP_INCLUDED_
+#define BOOST_LOG_SUPPORT_SPIRIT_QI_HPP_INCLUDED_
+
+#include <boost/utility/enable_if.hpp>
+#include <boost/spirit/include/qi_parse.hpp>
+#include <boost/spirit/include/qi_domain.hpp>
+#include <boost/spirit/include/support_unused.hpp>
+#include <boost/spirit/home/support/meta_compiler.hpp> // spirit::compile()
+#include <boost/spirit/home/qi/nonterminal/nonterminal_fwd.hpp> // rule forward declaration
+#include <boost/log/detail/config.hpp>
+#include <boost/log/utility/functional/matches.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! This tag type is used if an expression is recognized as a Boost.Spirit.Qi expression
+struct boost_spirit_qi_expression_tag;
+
+//! The metafunction detects the matching expression kind and returns a tag that is used to specialize \c match_traits
+template< typename ExpressionT >
+struct matching_expression_kind< ExpressionT, typename boost::enable_if< spirit::traits::matches< spirit::qi::domain, ExpressionT > >::type >
+{
+ typedef boost_spirit_qi_expression_tag type;
+};
+
+//! The matching function implementation
+template< typename ExpressionT >
+struct match_traits< ExpressionT, boost_spirit_qi_expression_tag >
+{
+ typedef typename spirit::result_of::compile< spirit::qi::domain, ExpressionT, spirit::unused_type >::type compiled_type;
+
+ static compiled_type compile(ExpressionT const& expr)
+ {
+ return spirit::compile< spirit::qi::domain >(expr);
+ }
+
+ template< typename StringT >
+ static bool matches(StringT const& str, ExpressionT const& expr)
+ {
+ typedef typename StringT::const_iterator const_iterator;
+ const_iterator it = str.begin(), end = str.end();
+ return (spirit::qi::parse(it, end, expr) && it == end);
+ }
+};
+
+//! The matching function implementation
+template< typename IteratorT, typename T1, typename T2, typename T3, typename T4 >
+struct match_traits< spirit::qi::rule< IteratorT, T1, T2, T3, T4 >, boost_spirit_qi_expression_tag >
+{
+ typedef spirit::qi::rule< IteratorT, T1, T2, T3, T4 > compiled_type;
+ static compiled_type compile(compiled_type const& expr) { return expr; }
+
+ template< typename StringT >
+ static bool matches(StringT const& str, compiled_type const& expr)
+ {
+ typedef typename StringT::const_iterator const_iterator;
+ const_iterator it = str.begin(), end = str.end();
+ return (spirit::qi::parse(it, end, expr) && it == end);
+ }
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SUPPORT_SPIRIT_QI_HPP_INCLUDED_
diff --git a/boost/log/support/std_regex.hpp b/boost/log/support/std_regex.hpp
new file mode 100644
index 0000000000..92395352ac
--- /dev/null
+++ b/boost/log/support/std_regex.hpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file support/std_regex.hpp
+ * \author Andrey Semashev
+ * \date 19.03.2014
+ *
+ * This header enables \c std::regex support for Boost.Log.
+ */
+
+#ifndef BOOST_LOG_SUPPORT_STD_REGEX_HPP_INCLUDED_
+#define BOOST_LOG_SUPPORT_STD_REGEX_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(BOOST_NO_CXX11_HDR_REGEX)
+
+#if defined(__GNUC__)
+#pragma message "Boost.Log: This header requires support for std::regex in the standard library."
+#elif defined(_MSC_VER)
+#pragma message("Boost.Log: This header requires support for std::regex in the standard library.")
+#endif
+
+#else // defined(BOOST_NO_CXX11_HDR_REGEX)
+
+#include <regex>
+#include <string>
+#include <boost/log/utility/functional/matches.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! This tag type is used if an expression is recognized as \c std::regex
+struct std_regex_expression_tag;
+
+//! The metafunction detects the matching expression kind and returns a tag that is used to specialize \c match_traits
+template< typename CharT, typename ReTraitsT >
+struct matching_expression_kind< std::basic_regex< CharT, ReTraitsT > >
+{
+ typedef std_regex_expression_tag type;
+};
+
+//! The matching function implementation
+template< typename ExpressionT >
+struct match_traits< ExpressionT, std_regex_expression_tag >
+{
+ typedef ExpressionT compiled_type;
+ static compiled_type compile(ExpressionT const& expr) { return expr; }
+
+ template< typename StringT, typename CharT, typename ReTraitsT >
+ static bool matches(StringT const& str, std::basic_regex< CharT, ReTraitsT > const& expr, std::regex_constants::match_flag_type flags = std::regex_constants::match_default)
+ {
+ return std::regex_match(str.begin(), str.end(), expr, flags);
+ }
+
+ template< typename CharT, typename StringTraitsT, typename AllocatorT, typename ReTraitsT >
+ static bool matches(std::basic_string< CharT, StringTraitsT, AllocatorT > const& str, std::basic_regex< CharT, ReTraitsT > const& expr, std::regex_constants::match_flag_type flags = std::regex_constants::match_default)
+ {
+ const CharT* p = str.c_str();
+ return std::regex_match(p, p + str.size(), expr, flags);
+ }
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // defined(BOOST_NO_CXX11_HDR_REGEX)
+
+#endif // BOOST_LOG_SUPPORT_STD_REGEX_HPP_INCLUDED_
diff --git a/boost/log/support/xpressive.hpp b/boost/log/support/xpressive.hpp
new file mode 100644
index 0000000000..5959716e57
--- /dev/null
+++ b/boost/log/support/xpressive.hpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file support/xpressive.hpp
+ * \author Andrey Semashev
+ * \date 18.07.2009
+ *
+ * This header enables Boost.Xpressive support for Boost.Log.
+ */
+
+#ifndef BOOST_LOG_SUPPORT_XPRESSIVE_HPP_INCLUDED_
+#define BOOST_LOG_SUPPORT_XPRESSIVE_HPP_INCLUDED_
+
+#include <string>
+#include <boost/xpressive/basic_regex.hpp>
+#include <boost/xpressive/regex_constants.hpp>
+#include <boost/xpressive/regex_algorithms.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/utility/functional/matches.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! This tag type is used if an expression is recognized as a Boost.Xpressive expression
+struct boost_xpressive_expression_tag;
+
+//! The metafunction detects the matching expression kind and returns a tag that is used to specialize \c match_traits
+template< typename T >
+struct matching_expression_kind< xpressive::basic_regex< T > >
+{
+ typedef boost_xpressive_expression_tag type;
+};
+
+//! The matching function implementation
+template< typename ExpressionT >
+struct match_traits< ExpressionT, boost_xpressive_expression_tag >
+{
+ typedef ExpressionT compiled_type;
+ static compiled_type compile(ExpressionT const& expr) { return expr; }
+
+ template< typename StringT, typename T >
+ static bool matches(StringT const& str, xpressive::basic_regex< T > const& expr, xpressive::regex_constants::match_flag_type flags = xpressive::regex_constants::match_default)
+ {
+ return xpressive::regex_match(str, expr, flags);
+ }
+
+ template< typename CharT, typename TraitsT, typename AllocatorT >
+ static bool matches(std::basic_string< CharT, TraitsT, AllocatorT > const& str, xpressive::basic_regex< const CharT* > const& expr, xpressive::regex_constants::match_flag_type flags = xpressive::regex_constants::match_default)
+ {
+ const CharT* p = str.c_str();
+ return xpressive::regex_match(p, p + str.size(), expr, flags);
+ }
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SUPPORT_XPRESSIVE_HPP_INCLUDED_
diff --git a/boost/log/trivial.hpp b/boost/log/trivial.hpp
new file mode 100644
index 0000000000..90de113b68
--- /dev/null
+++ b/boost/log/trivial.hpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file log/trivial.hpp
+ * \author Andrey Semashev
+ * \date 07.11.2009
+ *
+ * This header defines tools for trivial logging support
+ */
+
+#ifndef BOOST_LOG_TRIVIAL_HPP_INCLUDED_
+#define BOOST_LOG_TRIVIAL_HPP_INCLUDED_
+
+#include <iosfwd>
+#include <ostream>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/keywords/severity.hpp>
+#include <boost/log/sources/severity_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if !defined(BOOST_LOG_USE_CHAR)
+#error Boost.Log: Trivial logging is available for narrow-character builds only. Use advanced initialization routines to setup wide-character logging.
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace trivial {
+
+//! Trivial severity levels
+enum severity_level
+{
+ trace,
+ debug,
+ info,
+ warning,
+ error,
+ fatal
+};
+
+//! Returns stringized enumeration value or \c NULL, if the value is not valid
+BOOST_LOG_API const char* to_string(severity_level lvl);
+
+//! Outputs stringized representation of the severity level to the stream
+template< typename CharT, typename TraitsT >
+inline std::basic_ostream< CharT, TraitsT >& operator<< (
+ std::basic_ostream< CharT, TraitsT >& strm, severity_level lvl)
+{
+ const char* str = boost::log::trivial::to_string(lvl);
+ if (str)
+ strm << str;
+ else
+ strm << static_cast< int >(lvl);
+ return strm;
+}
+
+//! Reads stringized representation of the severity level from the stream
+template< typename CharT, typename TraitsT >
+BOOST_LOG_API std::basic_istream< CharT, TraitsT >& operator>> (
+ std::basic_istream< CharT, TraitsT >& strm, severity_level& lvl);
+
+//! Trivial logger type
+#if !defined(BOOST_LOG_NO_THREADS)
+typedef sources::severity_logger_mt< severity_level > logger_type;
+#else
+typedef sources::severity_logger< severity_level > logger_type;
+#endif
+
+/*!
+ * \brief Trivial logger tag
+ *
+ * This tag can be used to acquire the logger that is used with lrivial logging macros.
+ * This may be useful when the logger is used with other macros which require a logger.
+ */
+struct logger
+{
+ //! Logger type
+ typedef trivial::logger_type logger_type;
+
+ /*!
+ * Returns a reference to the trivial logger instance
+ */
+ static BOOST_LOG_API logger_type& get();
+
+ // Implementation details - never use these
+#if !defined(BOOST_LOG_DOXYGEN_PASS)
+ enum registration_line_t { registration_line = __LINE__ };
+ static const char* registration_file() { return __FILE__; }
+ static BOOST_LOG_API logger_type construct_logger();
+#endif
+};
+
+/*!
+ * The macro is used to initiate logging. The \c lvl argument of the macro specifies one of the following
+ * severity levels: \c trace, \c debug, \c info, \c warning, \c error or \c fatal (see \c severity_level enum).
+ * Following the macro, there may be a streaming expression that composes the record message string. For example:
+ *
+ * \code
+ * BOOST_LOG_TRIVIAL(info) << "Hello, world!";
+ * \endcode
+ */
+#define BOOST_LOG_TRIVIAL(lvl)\
+ BOOST_LOG_STREAM_WITH_PARAMS(::boost::log::trivial::logger::get(),\
+ (::boost::log::keywords::severity = ::boost::log::trivial::lvl))
+
+} // namespace trivial
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+#if defined(BOOST_LOG_EXPRESSIONS_KEYWORD_HPP_INCLUDED_)
+#include <boost/log/detail/trivial_keyword.hpp>
+#endif
+
+#endif // BOOST_LOG_TRIVIAL_HPP_INCLUDED_
diff --git a/boost/log/utility/empty_deleter.hpp b/boost/log/utility/empty_deleter.hpp
new file mode 100644
index 0000000000..67e5abc97b
--- /dev/null
+++ b/boost/log/utility/empty_deleter.hpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file empty_deleter.hpp
+ * \author Andrey Semashev
+ * \date 22.04.2007
+ *
+ * This header is deprecated, use boost/utility/empty_deleter.hpp instead. The header is left for
+ * backward compatibility and will be removed in future versions.
+ */
+
+#ifndef BOOST_LOG_UTILITY_EMPTY_DELETER_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_EMPTY_DELETER_HPP_INCLUDED_
+
+#include <boost/core/null_deleter.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(__GNUC__)
+#pragma message "Boost.Log: This header is deprecated, use boost/core/null_deleter.hpp instead."
+#elif defined(_MSC_VER)
+#pragma message("Boost.Log: This header is deprecated, use boost/core/null_deleter.hpp instead.")
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+typedef boost::null_deleter empty_deleter;
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_UTILITY_EMPTY_DELETER_HPP_INCLUDED_
diff --git a/boost/log/utility/exception_handler.hpp b/boost/log/utility/exception_handler.hpp
new file mode 100644
index 0000000000..c5392be687
--- /dev/null
+++ b/boost/log/utility/exception_handler.hpp
@@ -0,0 +1,354 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file exception_handler.hpp
+ * \author Andrey Semashev
+ * \date 12.07.2009
+ *
+ * This header contains tools for exception handlers support in different parts of the library.
+ */
+
+#ifndef BOOST_LOG_UTILITY_EXCEPTION_HANDLER_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_EXCEPTION_HANDLER_HPP_INCLUDED_
+
+#include <new> // std::nothrow_t
+#include <boost/mpl/bind.hpp>
+#include <boost/mpl/quote.hpp>
+#include <boost/mpl/fold.hpp>
+#include <boost/mpl/placeholders.hpp>
+#include <boost/mpl/has_xxx.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/utility/functional/nop.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifndef BOOST_LOG_MAX_EXCEPTION_TYPES
+//! Maximum number of exception types that can be specified for exception handlers
+#define BOOST_LOG_MAX_EXCEPTION_TYPES 10
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_exception_types, exception_types, false)
+
+//! Root class for the exception handler class hierarchy
+template< typename HandlerT >
+class eh_root
+{
+public:
+ //! The exception handler type
+ typedef HandlerT handler_type;
+ //! The handler result type
+ typedef void result_type;
+
+protected:
+ //! Exception handler
+ handler_type m_Handler;
+
+public:
+ //! Initializing constructor
+ explicit eh_root(handler_type const& handler) : m_Handler(handler)
+ {
+ }
+
+ //! Exception launcher
+ void operator()() const
+ {
+ throw;
+ }
+};
+
+//! A cons-list element of the exception handler class hierarchy
+template< typename ExceptionT, typename BaseT >
+class eh_cons :
+ public BaseT
+{
+ //! Base type
+ typedef BaseT base_type;
+
+public:
+ //! The exception handler type
+ typedef typename base_type::handler_type handler_type;
+
+public:
+ //! Initializing constructor
+ explicit eh_cons(handler_type const& handler) : base_type(handler)
+ {
+ }
+
+ //! Exception launcher
+ void operator()() const
+ {
+ try
+ {
+ base_type::operator()();
+ }
+ catch (ExceptionT& e)
+ {
+ this->m_Handler(e);
+ }
+ }
+};
+
+template< template< typename, typename > class EHT, typename HandlerT >
+struct make_self_contained_exception_handler
+{
+ typedef EHT< typename HandlerT::exception_types, HandlerT > type;
+};
+
+} // namespace aux
+
+/*!
+ * An exception handler functional object. The handler aggregates a user-defined
+ * functional object that will be called when one of the specified exception types
+ * is caught.
+ */
+template< typename SequenceT, typename HandlerT >
+class exception_handler :
+ public mpl::fold<
+ SequenceT,
+ aux::eh_root< HandlerT >,
+ mpl::bind< mpl::quote2< aux::eh_cons >, mpl::_2, mpl::_1 >
+ >::type
+{
+ //! Base type
+ typedef typename mpl::fold<
+ SequenceT,
+ aux::eh_root< HandlerT >,
+ mpl::bind< mpl::quote2< aux::eh_cons >, mpl::_2, mpl::_1 >
+ >::type base_type;
+
+public:
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ typedef typename base_type::handler_type handler_type;
+#else
+ //! The exception handler type
+ typedef HandlerT handler_type;
+ //! The handler result type
+ typedef void result_type;
+#endif
+
+public:
+ /*!
+ * Initializing constructor. Creates an exception handler with the specified
+ * function object that will receive the exception.
+ */
+ explicit exception_handler(handler_type const& handler) : base_type(handler)
+ {
+ }
+
+ /*!
+ * Exception launcher. Rethrows the current exception in order to detect its type
+ * and pass it to the aggregated function object.
+ *
+ * \note Must be called from within a \c catch statement.
+ */
+ void operator()() const
+ {
+ base_type::operator()();
+ }
+};
+
+/*!
+ * A no-throw exception handler functional object. Acts similar to \c exception_handler,
+ * but in case if the exception cannot be handled the exception is not propagated
+ * from the handler. Instead the user-defined functional object is called with
+ * no parameters.
+ */
+template< typename SequenceT, typename HandlerT >
+class nothrow_exception_handler :
+ public exception_handler< SequenceT, HandlerT >
+{
+ //! Base type
+ typedef exception_handler< SequenceT, HandlerT > base_type;
+
+public:
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ typedef typename base_type::handler_type handler_type;
+#else
+ //! The exception handler type
+ typedef HandlerT handler_type;
+ //! The handler result type
+ typedef void result_type;
+#endif
+
+public:
+ /*!
+ * Initializing constructor. Creates an exception handler with the specified
+ * function object that will receive the exception.
+ */
+ explicit nothrow_exception_handler(handler_type const& handler) : base_type(handler)
+ {
+ }
+
+ /*!
+ * Exception launcher. Rethrows the current exception in order to detect its type
+ * and pass it to the aggregated function object. If the type of the exception
+ * could not be detected, the user-defined handler is called with no arguments.
+ *
+ * \note Must be called from within a \c catch statement.
+ */
+ void operator()() const
+ {
+ try
+ {
+ base_type::operator()();
+ }
+ catch (...)
+ {
+ this->m_Handler();
+ }
+ }
+};
+
+/*!
+ * The function creates an empty exception handler that effectively suppresses any exception
+ */
+inline nop make_exception_suppressor()
+{
+ return nop();
+}
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+template< typename HandlerT >
+inline typename lazy_enable_if<
+ aux::has_exception_types< HandlerT >,
+ aux::make_self_contained_exception_handler< exception_handler, HandlerT >
+>::type make_exception_handler(HandlerT const& handler)
+{
+ typedef typename aux::make_self_contained_exception_handler< exception_handler, HandlerT >::type eh_t;
+ return eh_t(handler);
+}
+
+template< typename HandlerT >
+inline typename lazy_enable_if<
+ aux::has_exception_types< HandlerT >,
+ aux::make_self_contained_exception_handler< nothrow_exception_handler, HandlerT >
+>::type make_exception_handler(HandlerT const& handler, std::nothrow_t const&)
+{
+ typedef typename aux::make_self_contained_exception_handler< nothrow_exception_handler, HandlerT >::type eh_t;
+ return eh_t(handler);
+}
+
+#define BOOST_LOG_MAKE_EXCEPTION_HANDLER_INTERNAL(z, n, data)\
+ template< BOOST_PP_ENUM_PARAMS(n, typename T), typename HandlerT >\
+ inline exception_handler<\
+ BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(n, T) >,\
+ HandlerT\
+ > make_exception_handler(HandlerT const& handler)\
+ {\
+ typedef exception_handler<\
+ BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(n, T) >,\
+ HandlerT\
+ > eh_t;\
+ return eh_t(handler);\
+ }\
+ template< BOOST_PP_ENUM_PARAMS(n, typename T), typename HandlerT >\
+ inline nothrow_exception_handler<\
+ BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(n, T) >,\
+ HandlerT\
+ > make_exception_handler(HandlerT const& handler, std::nothrow_t const&)\
+ {\
+ typedef nothrow_exception_handler<\
+ BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(n, T) >,\
+ HandlerT\
+ > eh_t;\
+ return eh_t(handler);\
+ }
+
+BOOST_PP_REPEAT_FROM_TO(1, BOOST_LOG_MAX_EXCEPTION_TYPES, BOOST_LOG_MAKE_EXCEPTION_HANDLER_INTERNAL, ~)
+
+#undef BOOST_LOG_MAKE_EXCEPTION_HANDLER_INTERNAL
+
+#else // BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * The function creates an exception handler functional object. The handler will call to the
+ * user-specified functional object with an exception as its argument.
+ *
+ * \param handler User-defined functional object that will receive exceptions.
+ * \return A nullary functional object that should be called from within a \c catch statement.
+ *
+ * \note This form requires the user-defined functional object to have an \c exception_types
+ * nested type. This type should be an MPL sequence of all expected exception types.
+ */
+template< typename HandlerT >
+exception_handler< typename HandlerT::exception_types, HandlerT >
+make_exception_handler(HandlerT const& handler);
+
+/*!
+ * The function creates an exception handler functional object. The handler will call to the
+ * user-specified functional object with an exception as its argument. If the exception type
+ * cannot be identified, the handler will call the user-defined functor with no arguments,
+ * instead of propagating exception to the caller.
+ *
+ * \overload
+ *
+ * \param handler User-defined functional object that will receive exceptions.
+ * \return A nullary functional object that should be called from within a \c catch statement.
+ *
+ * \note This form requires the user-defined functional object to have an \c exception_types
+ * nested type. This type should be an MPL sequence of all expected exception types.
+ */
+template< typename HandlerT >
+nothrow_exception_handler< typename HandlerT::exception_types, HandlerT >
+make_exception_handler(HandlerT const& handler, std::nothrow_t const&);
+
+/*!
+ * The function creates an exception handler functional object. The handler will call to the
+ * user-specified functional object with an exception as its argument. All expected exception
+ * types should be specified as first template parameters explicitly, in the order they would
+ * be specified in a corresponding <tt>try/catch</tt> statement.
+ *
+ * \overload
+ *
+ * \param handler User-defined functional object that will receive exceptions.
+ * \return A nullary functional object that should be called from within a \c catch statement.
+ */
+template< typename... ExceptionsT, typename HandlerT >
+exception_handler< MPL_sequence_of_ExceptionsT, HandlerT >
+make_exception_handler(HandlerT const& handler);
+
+/*!
+ * The function creates an exception handler functional object. The handler will call to the
+ * user-specified functional object with an exception as its argument. If the exception type
+ * cannot be identified, the handler will call the user-defined functor with no arguments,
+ * instead of propagating exception to the caller. All expected exception types should be
+ * specified as first template parameters explicitly, in the order they would be specified in
+ * a corresponding <tt>try/catch</tt> statement.
+ *
+ * \overload
+ *
+ * \param handler User-defined functional object that will receive exceptions.
+ * \return A nullary functional object that should be called from within a \c catch statement.
+ */
+template< typename... ExceptionsT, typename HandlerT >
+nothrow_exception_handler< MPL_sequence_of_ExceptionsT, HandlerT >
+make_exception_handler(HandlerT const& handler, std::nothrow_t const&);
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_EXCEPTION_HANDLER_HPP_INCLUDED_
diff --git a/boost/log/utility/explicit_operator_bool.hpp b/boost/log/utility/explicit_operator_bool.hpp
new file mode 100644
index 0000000000..0d708288dc
--- /dev/null
+++ b/boost/log/utility/explicit_operator_bool.hpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file explicit_operator_bool.hpp
+ * \author Andrey Semashev
+ * \date 08.03.2009
+ *
+ * This header is deprecated, use boost/utility/explicit_operator_bool.hpp instead. The header is left for
+ * backward compatibility and will be removed in future versions.
+ */
+
+#ifndef BOOST_LOG_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_
+
+#include <boost/utility/explicit_operator_bool.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(__GNUC__)
+#pragma message "Boost.Log: This header is deprecated, use boost/utility/explicit_operator_bool.hpp instead."
+#elif defined(_MSC_VER)
+#pragma message("Boost.Log: This header is deprecated, use boost/utility/explicit_operator_bool.hpp instead.")
+#endif
+
+/*!
+ * \brief The macro defines an explicit operator of conversion to \c bool
+ *
+ * The macro should be used inside the definition of a class that has to
+ * support the conversion. The class should also implement <tt>operator!</tt>,
+ * in terms of which the conversion operator will be implemented.
+ */
+#define BOOST_LOG_EXPLICIT_OPERATOR_BOOL()\
+ BOOST_EXPLICIT_OPERATOR_BOOL()
+
+#endif // BOOST_LOG_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_
diff --git a/boost/log/utility/formatting_ostream.hpp b/boost/log/utility/formatting_ostream.hpp
new file mode 100644
index 0000000000..a32df35c83
--- /dev/null
+++ b/boost/log/utility/formatting_ostream.hpp
@@ -0,0 +1,748 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file formatting_ostream.hpp
+ * \author Andrey Semashev
+ * \date 11.07.2012
+ *
+ * The header contains implementation of a string stream used for log record formatting.
+ */
+
+#ifndef BOOST_LOG_UTILITY_FORMATTING_OSTREAM_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_FORMATTING_OSTREAM_HPP_INCLUDED_
+
+#include <ostream>
+#include <string>
+#include <memory>
+#include <locale>
+#include <boost/utility/string_ref_fwd.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/attachable_sstream_buf.hpp>
+#include <boost/log/detail/code_conversion.hpp>
+#include <boost/log/utility/string_literal_fwd.hpp>
+#include <boost/log/utility/formatting_ostream_fwd.hpp>
+#include <boost/utility/explicit_operator_bool.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+template< typename T, typename R >
+struct enable_if_char_type {};
+template< typename R >
+struct enable_if_char_type< char, R > { typedef R type; };
+template< typename R >
+struct enable_if_char_type< wchar_t, R > { typedef R type; };
+#if !defined(BOOST_NO_CXX11_CHAR16_T)
+template< typename R >
+struct enable_if_char_type< char16_t, R > { typedef R type; };
+#endif
+#if !defined(BOOST_NO_CXX11_CHAR32_T)
+template< typename R >
+struct enable_if_char_type< char32_t, R > { typedef R type; };
+#endif
+
+} // namespace aux
+
+/*!
+ * \brief Stream wrapper for log records formatting.
+ *
+ * This stream wrapper is used by the library for log record formatting. It implements the standard string stream interface
+ * with a few differences:
+ *
+ * \li It does not derive from standard types <tt>std::basic_ostream</tt>, <tt>std::basic_ios</tt> and <tt>std::ios_base</tt>,
+ * although it tries to implement their interfaces closely. There are a few small differences, mostly regarding <tt>rdbuf</tt>
+ * and <tt>str</tt> signatures, as well as the supported insertion operator overloads. The actual wrapped stream can be accessed
+ * through the <tt>stream</tt> methods.
+ * \li By default, \c bool values are formatted using alphabetical representation rather than numeric.
+ * \li The stream supports writing strings of character types different from the stream character type. The stream will perform
+ * character code conversion as needed using the imbued locale.
+ * \li The stream operates on an external string object rather than on the embedded one. The string can be attached or detached
+ * from the stream dynamically.
+ *
+ * Although <tt>basic_formatting_ostream</tt> does not derive from <tt>std::basic_ostream</tt>, users are not required to add
+ * special overloads of \c operator<< for it since the stream will by default reuse the operators for <tt>std::basic_ostream</tt>.
+ * However, one can define special overloads of \c operator<< for <tt>basic_formatting_ostream</tt> if a certain type needs
+ * special formatting when output to log.
+ */
+template< typename CharT, typename TraitsT, typename AllocatorT >
+class basic_formatting_ostream
+{
+public:
+ //! Character type
+ typedef CharT char_type;
+ //! Character traits
+ typedef TraitsT traits_type;
+ //! Memory allocator
+ typedef AllocatorT allocator_type;
+ //! Stream buffer type
+ typedef boost::log::aux::basic_ostringstreambuf< char_type, traits_type, allocator_type > streambuf_type;
+ //! Target string type
+ typedef typename streambuf_type::string_type string_type;
+
+ //! Stream type
+ typedef std::basic_ostream< char_type, traits_type > ostream_type;
+ //! Stream position type
+ typedef typename ostream_type::pos_type pos_type;
+ //! Stream offset type
+ typedef typename ostream_type::off_type off_type;
+ //! Integer type for characters
+ typedef typename ostream_type::int_type int_type;
+
+ typedef typename ostream_type::failure failure;
+ typedef typename ostream_type::fmtflags fmtflags;
+ typedef typename ostream_type::iostate iostate;
+ typedef typename ostream_type::openmode openmode;
+ typedef typename ostream_type::seekdir seekdir;
+ typedef typename ostream_type::Init Init;
+
+ typedef typename ostream_type::event event;
+ typedef typename ostream_type::event_callback event_callback;
+
+ class sentry :
+ public ostream_type::sentry
+ {
+ typedef typename ostream_type::sentry base_type;
+
+ public:
+ explicit sentry(basic_formatting_ostream& strm) : base_type(strm.stream())
+ {
+ }
+
+ BOOST_DELETED_FUNCTION(sentry(sentry const&))
+ BOOST_DELETED_FUNCTION(sentry& operator= (sentry const&))
+ };
+
+private:
+ // Function types
+ typedef std::ios_base& (*ios_base_manip)(std::ios_base&);
+ typedef std::basic_ios< char_type, traits_type >& (*basic_ios_manip)(std::basic_ios< char_type, traits_type >&);
+ typedef ostream_type& (*stream_manip)(ostream_type&);
+
+public:
+ static BOOST_CONSTEXPR_OR_CONST fmtflags boolalpha = ostream_type::boolalpha;
+ static BOOST_CONSTEXPR_OR_CONST fmtflags dec = ostream_type::dec;
+ static BOOST_CONSTEXPR_OR_CONST fmtflags fixed = ostream_type::fixed;
+ static BOOST_CONSTEXPR_OR_CONST fmtflags hex = ostream_type::hex;
+ static BOOST_CONSTEXPR_OR_CONST fmtflags internal = ostream_type::internal;
+ static BOOST_CONSTEXPR_OR_CONST fmtflags left = ostream_type::left;
+ static BOOST_CONSTEXPR_OR_CONST fmtflags oct = ostream_type::oct;
+ static BOOST_CONSTEXPR_OR_CONST fmtflags right = ostream_type::right;
+ static BOOST_CONSTEXPR_OR_CONST fmtflags scientific = ostream_type::scientific;
+ static BOOST_CONSTEXPR_OR_CONST fmtflags showbase = ostream_type::showbase;
+ static BOOST_CONSTEXPR_OR_CONST fmtflags showpoint = ostream_type::showpoint;
+ static BOOST_CONSTEXPR_OR_CONST fmtflags skipws = ostream_type::skipws;
+ static BOOST_CONSTEXPR_OR_CONST fmtflags unitbuf = ostream_type::unitbuf;
+ static BOOST_CONSTEXPR_OR_CONST fmtflags uppercase = ostream_type::uppercase;
+ static BOOST_CONSTEXPR_OR_CONST fmtflags adjustfield = ostream_type::adjustfield;
+ static BOOST_CONSTEXPR_OR_CONST fmtflags basefield = ostream_type::basefield;
+ static BOOST_CONSTEXPR_OR_CONST fmtflags floatfield = ostream_type::floatfield;
+
+ static BOOST_CONSTEXPR_OR_CONST iostate badbit = ostream_type::badbit;
+ static BOOST_CONSTEXPR_OR_CONST iostate eofbit = ostream_type::eofbit;
+ static BOOST_CONSTEXPR_OR_CONST iostate failbit = ostream_type::failbit;
+ static BOOST_CONSTEXPR_OR_CONST iostate goodbit = ostream_type::goodbit;
+
+ static BOOST_CONSTEXPR_OR_CONST openmode app = ostream_type::app;
+ static BOOST_CONSTEXPR_OR_CONST openmode ate = ostream_type::ate;
+ static BOOST_CONSTEXPR_OR_CONST openmode binary = ostream_type::binary;
+ static BOOST_CONSTEXPR_OR_CONST openmode in = ostream_type::in;
+ static BOOST_CONSTEXPR_OR_CONST openmode out = ostream_type::out;
+ static BOOST_CONSTEXPR_OR_CONST openmode trunc = ostream_type::trunc;
+
+ static BOOST_CONSTEXPR_OR_CONST seekdir beg = ostream_type::beg;
+ static BOOST_CONSTEXPR_OR_CONST seekdir cur = ostream_type::cur;
+ static BOOST_CONSTEXPR_OR_CONST seekdir end = ostream_type::end;
+
+ static BOOST_CONSTEXPR_OR_CONST event erase_event = ostream_type::erase_event;
+ static BOOST_CONSTEXPR_OR_CONST event imbue_event = ostream_type::imbue_event;
+ static BOOST_CONSTEXPR_OR_CONST event copyfmt_event = ostream_type::copyfmt_event;
+
+private:
+ mutable streambuf_type m_streambuf;
+ ostream_type m_stream;
+
+public:
+ /*!
+ * Default constructor. Creates an empty record that is equivalent to the invalid record handle.
+ * The stream capability is not available after construction.
+ *
+ * \post <tt>!*this == true</tt>
+ */
+ basic_formatting_ostream() : m_stream(&m_streambuf)
+ {
+ init_stream();
+ }
+
+ /*!
+ * Initializing constructor. Attaches the string to the constructed stream.
+ * The string will be used to store the formatted characters.
+ *
+ * \post <tt>!*this == false</tt>
+ * \param str The string buffer to attach.
+ */
+ explicit basic_formatting_ostream(string_type& str) :
+ m_streambuf(str),
+ m_stream(&m_streambuf)
+ {
+ init_stream();
+ }
+
+ /*!
+ * Destructor. Destroys the record, releases any sinks and attribute values that were involved in processing this record.
+ */
+ ~basic_formatting_ostream()
+ {
+ if (m_streambuf.storage())
+ flush();
+ }
+
+ /*!
+ * Attaches the stream to the string. The string will be used to store the formatted characters.
+ *
+ * \param str The string buffer to attach.
+ */
+ void attach(string_type& str)
+ {
+ m_streambuf.attach(str);
+ m_stream.clear(ostream_type::goodbit);
+ }
+ /*!
+ * Detaches the stream from the string. Any buffered data is flushed to the string.
+ */
+ void detach()
+ {
+ m_streambuf.detach();
+ m_stream.clear(ostream_type::badbit);
+ }
+
+ /*!
+ * \returns Reference to the attached string. The string must be attached before calling this method.
+ */
+ string_type const& str() const
+ {
+ string_type* storage = m_streambuf.storage();
+ BOOST_ASSERT(storage != NULL);
+
+ m_streambuf.pubsync();
+
+ return *storage;
+ }
+
+ /*!
+ * \returns Reference to the wrapped stream
+ */
+ ostream_type& stream() { return m_stream; }
+
+ /*!
+ * \returns Reference to the wrapped stream
+ */
+ ostream_type const& stream() const { return m_stream; }
+
+ // std::ios_base method forwarders
+ fmtflags flags() const { return m_stream.flags(); }
+ fmtflags flags(fmtflags f) { return m_stream.flags(f); }
+ fmtflags setf(fmtflags f) { return m_stream.setf(f); }
+ fmtflags setf(fmtflags f, fmtflags mask) { return m_stream.setf(f, mask); }
+ void unsetf(fmtflags f) { m_stream.unsetf(f); }
+
+ std::streamsize precision() const { return m_stream.precision(); }
+ std::streamsize precision(std::streamsize p) { return m_stream.precision(p); }
+
+ std::streamsize width() const { return m_stream.width(); }
+ std::streamsize width(std::streamsize w) { return m_stream.width(w); }
+
+ std::locale getloc() const { return m_stream.getloc(); }
+ std::locale imbue(std::locale const& loc) { return m_stream.imbue(loc); }
+
+ static int xalloc() { return ostream_type::xalloc(); }
+ long& iword(int index) { return m_stream.iword(index); }
+ void*& pword(int index) { return m_stream.pword(index); }
+
+ void register_callback(event_callback fn, int index) { m_stream.register_callback(fn, index); }
+
+ static bool sync_with_stdio(bool sync = true) { return ostream_type::sync_with_stdio(sync); }
+
+ // std::basic_ios method forwarders
+ BOOST_EXPLICIT_OPERATOR_BOOL()
+ bool operator! () const { return !m_stream; }
+
+ iostate rdstate() const { return m_stream.rdstate(); }
+ void clear(iostate state = goodbit) { m_stream.clear(state); }
+ void setstate(iostate state) { m_stream.setstate(state); }
+ bool good() const { return m_stream.good(); }
+ bool eof() const { return m_stream.eof(); }
+ bool fail() const { return m_stream.fail(); }
+ bool bad() const { return m_stream.bad(); }
+
+ iostate exceptions() const { return m_stream.exceptions(); }
+ void exceptions(iostate s) { m_stream.exceptions(s); }
+
+ ostream_type* tie() const { return m_stream.tie(); }
+ ostream_type* tie(ostream_type* strm) { return m_stream.tie(strm); }
+
+ streambuf_type* rdbuf() const { return &m_streambuf; }
+
+ basic_formatting_ostream& copyfmt(std::basic_ios< char_type, traits_type >& rhs)
+ {
+ m_stream.copyfmt(rhs);
+ return *this;
+ }
+ basic_formatting_ostream& copyfmt(basic_formatting_ostream& rhs)
+ {
+ m_stream.copyfmt(rhs.stream());
+ return *this;
+ }
+
+ char_type fill() const { return m_stream.fill(); }
+ char_type fill(char_type ch) { return m_stream.fill(ch); }
+
+ char narrow(char_type ch, char def) const { return m_stream.narrow(ch, def); }
+ char_type widen(char ch) const { return m_stream.widen(ch); }
+
+ // std::basic_ostream method forwarders
+ basic_formatting_ostream& flush()
+ {
+ m_stream.flush();
+ return *this;
+ }
+
+ pos_type tellp() { return m_stream.tellp(); }
+ basic_formatting_ostream& seekp(pos_type pos)
+ {
+ m_stream.seekp(pos);
+ return *this;
+ }
+ basic_formatting_ostream& seekp(off_type off, std::ios_base::seekdir dir)
+ {
+ m_stream.seekp(off, dir);
+ return *this;
+ }
+
+ basic_formatting_ostream& put(char_type c)
+ {
+ m_stream.put(c);
+ return *this;
+ }
+
+ template< typename OtherCharT >
+ typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type
+ put(OtherCharT c)
+ {
+ write(&c, 1);
+ return *this;
+ }
+
+ basic_formatting_ostream& write(const char_type* p, std::streamsize size)
+ {
+ m_stream.write(p, size);
+ return *this;
+ }
+
+ template< typename OtherCharT >
+ typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type
+ write(const OtherCharT* p, std::streamsize size)
+ {
+ sentry guard(*this);
+ if (guard)
+ {
+ m_stream.flush();
+
+ string_type* storage = m_streambuf.storage();
+ aux::code_convert(p, static_cast< std::size_t >(size), *storage, m_stream.getloc());
+ }
+
+ return *this;
+ }
+
+ basic_formatting_ostream& operator<< (ios_base_manip manip)
+ {
+ m_stream << manip;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (basic_ios_manip manip)
+ {
+ m_stream << manip;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (stream_manip manip)
+ {
+ m_stream << manip;
+ return *this;
+ }
+
+ basic_formatting_ostream& operator<< (char c)
+ {
+ return this->formatted_write(&c, 1);
+ }
+ basic_formatting_ostream& operator<< (const char* p)
+ {
+ return this->formatted_write(p, static_cast< std::streamsize >(std::char_traits< char >::length(p)));
+ }
+
+#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
+ basic_formatting_ostream& operator<< (wchar_t c)
+ {
+ return this->formatted_write(&c, 1);
+ }
+ basic_formatting_ostream& operator<< (const wchar_t* p)
+ {
+ return this->formatted_write(p, static_cast< std::streamsize >(std::char_traits< wchar_t >::length(p)));
+ }
+#endif
+#if !defined(BOOST_NO_CXX11_CHAR16_T)
+ basic_formatting_ostream& operator<< (char16_t c)
+ {
+ return this->formatted_write(&c, 1);
+ }
+ basic_formatting_ostream& operator<< (const char16_t* p)
+ {
+ return this->formatted_write(p, static_cast< std::streamsize >(std::char_traits< char16_t >::length(p)));
+ }
+#endif
+#if !defined(BOOST_NO_CXX11_CHAR32_T)
+ basic_formatting_ostream& operator<< (char32_t c)
+ {
+ return this->formatted_write(&c, 1);
+ }
+ basic_formatting_ostream& operator<< (const char32_t* p)
+ {
+ return this->formatted_write(p, static_cast< std::streamsize >(std::char_traits< char32_t >::length(p)));
+ }
+#endif
+
+ basic_formatting_ostream& operator<< (bool value)
+ {
+ m_stream << value;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (signed char value)
+ {
+ m_stream << value;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (unsigned char value)
+ {
+ m_stream << value;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (short value)
+ {
+ m_stream << value;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (unsigned short value)
+ {
+ m_stream << value;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (int value)
+ {
+ m_stream << value;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (unsigned int value)
+ {
+ m_stream << value;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (long value)
+ {
+ m_stream << value;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (unsigned long value)
+ {
+ m_stream << value;
+ return *this;
+ }
+#if !defined(BOOST_NO_LONG_LONG)
+ basic_formatting_ostream& operator<< (long long value)
+ {
+ m_stream << value;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (unsigned long long value)
+ {
+ m_stream << value;
+ return *this;
+ }
+#endif
+
+ basic_formatting_ostream& operator<< (float value)
+ {
+ m_stream << value;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (double value)
+ {
+ m_stream << value;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (long double value)
+ {
+ m_stream << value;
+ return *this;
+ }
+
+ basic_formatting_ostream& operator<< (const void* value)
+ {
+ m_stream << value;
+ return *this;
+ }
+
+ basic_formatting_ostream& operator<< (std::basic_streambuf< char_type, traits_type >* buf)
+ {
+ m_stream << buf;
+ return *this;
+ }
+
+ template< typename OtherCharT, typename OtherTraitsT, typename OtherAllocatorT >
+ friend typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type
+ operator<< (basic_formatting_ostream& strm, std::basic_string< OtherCharT, OtherTraitsT, OtherAllocatorT > const& str)
+ {
+ return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size()));
+ }
+
+ template< typename OtherCharT, typename OtherTraitsT >
+ friend typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type
+ operator<< (basic_formatting_ostream& strm, basic_string_literal< OtherCharT, OtherTraitsT > const& str)
+ {
+ return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size()));
+ }
+
+ template< typename OtherCharT, typename OtherTraitsT >
+ friend typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type
+ operator<< (basic_formatting_ostream& strm, basic_string_ref< OtherCharT, OtherTraitsT > const& str)
+ {
+ return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
+ }
+
+private:
+ void init_stream()
+ {
+ m_stream.clear(m_streambuf.storage() ? ostream_type::goodbit : ostream_type::badbit);
+ m_stream.flags
+ (
+ ostream_type::dec |
+ ostream_type::skipws |
+ ostream_type::boolalpha // this differs from the default stream flags but makes logs look better
+ );
+ m_stream.width(0);
+ m_stream.precision(6);
+ m_stream.fill(static_cast< char_type >(' '));
+ }
+
+ basic_formatting_ostream& formatted_write(const char_type* p, std::streamsize size)
+ {
+ sentry guard(*this);
+ if (guard)
+ {
+ m_stream.flush();
+
+ if (m_stream.width() <= size)
+ m_streambuf.storage()->append(p, static_cast< std::size_t >(size));
+ else
+ this->aligned_write(p, size);
+
+ m_stream.width(0);
+ }
+
+ return *this;
+ }
+
+ template< typename OtherCharT >
+ basic_formatting_ostream& formatted_write(const OtherCharT* p, std::streamsize size)
+ {
+ sentry guard(*this);
+ if (guard)
+ {
+ m_stream.flush();
+
+ if (m_stream.width() <= size)
+ aux::code_convert(p, static_cast< std::size_t >(size), *m_streambuf.storage(), m_stream.getloc());
+ else
+ this->aligned_write(p, size);
+
+ m_stream.width(0);
+ }
+
+ return *this;
+ }
+
+ void aligned_write(const char_type* p, std::streamsize size);
+
+ template< typename OtherCharT >
+ void aligned_write(const OtherCharT* p, std::streamsize size);
+
+ //! Copy constructor (closed)
+ BOOST_DELETED_FUNCTION(basic_formatting_ostream(basic_formatting_ostream const& that))
+ //! Assignment (closed)
+ BOOST_DELETED_FUNCTION(basic_formatting_ostream& operator= (basic_formatting_ostream const& that))
+};
+
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::boolalpha;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::dec;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fixed;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::hex;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::internal;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::left;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::oct;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::right;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::scientific;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::showbase;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::showpoint;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::skipws;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::unitbuf;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::uppercase;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::adjustfield;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::basefield;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::floatfield;
+
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::iostate basic_formatting_ostream< CharT, TraitsT, AllocatorT >::badbit;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::iostate basic_formatting_ostream< CharT, TraitsT, AllocatorT >::eofbit;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::iostate basic_formatting_ostream< CharT, TraitsT, AllocatorT >::failbit;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::iostate basic_formatting_ostream< CharT, TraitsT, AllocatorT >::goodbit;
+
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::app;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::ate;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::binary;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::in;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::out;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::trunc;
+
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::seekdir basic_formatting_ostream< CharT, TraitsT, AllocatorT >::beg;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::seekdir basic_formatting_ostream< CharT, TraitsT, AllocatorT >::cur;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::seekdir basic_formatting_ostream< CharT, TraitsT, AllocatorT >::end;
+
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::event basic_formatting_ostream< CharT, TraitsT, AllocatorT >::erase_event;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::event basic_formatting_ostream< CharT, TraitsT, AllocatorT >::imbue_event;
+template< typename CharT, typename TraitsT, typename AllocatorT >
+BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::event basic_formatting_ostream< CharT, TraitsT, AllocatorT >::copyfmt_event;
+
+template< typename CharT, typename TraitsT, typename AllocatorT >
+void basic_formatting_ostream< CharT, TraitsT, AllocatorT >::aligned_write(const char_type* p, std::streamsize size)
+{
+ string_type* const storage = m_streambuf.storage();
+ typename string_type::size_type const alignment_size =
+ static_cast< typename string_type::size_type >(m_stream.width() - size);
+ const bool align_left = (m_stream.flags() & ostream_type::adjustfield) == ostream_type::left;
+ if (align_left)
+ {
+ storage->append(p, static_cast< std::size_t >(size));
+ storage->append(alignment_size, m_stream.fill());
+ }
+ else
+ {
+ storage->append(alignment_size, m_stream.fill());
+ storage->append(p, static_cast< std::size_t >(size));
+ }
+}
+
+template< typename CharT, typename TraitsT, typename AllocatorT >
+template< typename OtherCharT >
+void basic_formatting_ostream< CharT, TraitsT, AllocatorT >::aligned_write(const OtherCharT* p, std::streamsize size)
+{
+ string_type* const storage = m_streambuf.storage();
+ typename string_type::size_type const alignment_size =
+ static_cast< typename string_type::size_type >(m_stream.width() - size);
+ const bool align_left = (m_stream.flags() & ostream_type::adjustfield) == ostream_type::left;
+ if (align_left)
+ {
+ aux::code_convert(p, static_cast< std::size_t >(size), *storage, m_stream.getloc());
+ storage->append(alignment_size, m_stream.fill());
+ }
+ else
+ {
+ storage->append(alignment_size, m_stream.fill());
+ aux::code_convert(p, static_cast< std::size_t >(size), *storage, m_stream.getloc());
+ }
+}
+
+template< typename CharT, typename TraitsT, typename AllocatorT, typename T >
+inline basic_formatting_ostream< CharT, TraitsT, AllocatorT >&
+operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >& strm, T const& value)
+{
+ strm.stream() << value;
+ return strm;
+}
+
+template< typename CharT, typename TraitsT, typename AllocatorT, typename T >
+inline basic_formatting_ostream< CharT, TraitsT, AllocatorT >&
+operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >& strm, T& value)
+{
+ strm.stream() << value;
+ return strm;
+}
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+template< typename CharT, typename TraitsT, typename AllocatorT, typename T >
+inline basic_formatting_ostream< CharT, TraitsT, AllocatorT >&
+operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >&& strm, T const& value)
+{
+ static_cast< basic_formatting_ostream< CharT, TraitsT, AllocatorT >& >(strm) << value;
+ return strm;
+}
+
+template< typename CharT, typename TraitsT, typename AllocatorT, typename T >
+inline basic_formatting_ostream< CharT, TraitsT, AllocatorT >&
+operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >&& strm, T& value)
+{
+ static_cast< basic_formatting_ostream< CharT, TraitsT, AllocatorT >& >(strm) << value;
+ return strm;
+}
+
+#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_FORMATTING_OSTREAM_HPP_INCLUDED_
diff --git a/boost/log/utility/formatting_ostream_fwd.hpp b/boost/log/utility/formatting_ostream_fwd.hpp
new file mode 100644
index 0000000000..ba9b6e18d5
--- /dev/null
+++ b/boost/log/utility/formatting_ostream_fwd.hpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file formatting_ostream_fwd.hpp
+ * \author Andrey Semashev
+ * \date 11.07.2012
+ *
+ * The header contains forward declaration of a string stream used for log record formatting.
+ */
+
+#ifndef BOOST_LOG_UTILITY_FORMATTING_OSTREAM_FWD_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_FORMATTING_OSTREAM_FWD_HPP_INCLUDED_
+
+#include <string>
+#include <memory>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * \brief Stream for log records formatting
+ */
+template<
+ typename CharT,
+ typename TraitsT = std::char_traits< CharT >,
+ typename AllocatorT = std::allocator< CharT >
+>
+class basic_formatting_ostream;
+
+#ifdef BOOST_LOG_USE_CHAR
+typedef basic_formatting_ostream< char > formatting_ostream;
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+typedef basic_formatting_ostream< wchar_t > wformatting_ostream;
+#endif
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_UTILITY_FORMATTING_OSTREAM_FWD_HPP_INCLUDED_
diff --git a/boost/log/utility/functional.hpp b/boost/log/utility/functional.hpp
new file mode 100644
index 0000000000..bc48619a01
--- /dev/null
+++ b/boost/log/utility/functional.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file functional.hpp
+ * \author Andrey Semashev
+ * \date 30.03.2008
+ *
+ * This header includes all functional helpers.
+ */
+
+#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_FUNCTIONAL_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#include <boost/log/utility/functional/logical.hpp>
+#include <boost/log/utility/functional/in_range.hpp>
+#include <boost/log/utility/functional/begins_with.hpp>
+#include <boost/log/utility/functional/ends_with.hpp>
+#include <boost/log/utility/functional/contains.hpp>
+#include <boost/log/utility/functional/matches.hpp>
+
+#include <boost/log/utility/functional/nop.hpp>
+#include <boost/log/utility/functional/bind_assign.hpp>
+#include <boost/log/utility/functional/bind_output.hpp>
+#include <boost/log/utility/functional/bind_to_log.hpp>
+#include <boost/log/utility/functional/bind.hpp>
+#include <boost/log/utility/functional/fun_ref.hpp>
+#include <boost/log/utility/functional/as_action.hpp>
+#include <boost/log/utility/functional/save_result.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#endif // BOOST_LOG_UTILITY_FUNCTIONAL_HPP_INCLUDED_
diff --git a/boost/log/utility/functional/as_action.hpp b/boost/log/utility/functional/as_action.hpp
new file mode 100644
index 0000000000..a12cee250a
--- /dev/null
+++ b/boost/log/utility/functional/as_action.hpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file as_action.hpp
+ * \author Andrey Semashev
+ * \date 30.03.2008
+ *
+ * This header contains function object adapter for compatibility with Boost.Spirit actions interface requirements.
+ */
+
+#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_AS_ACTION_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_FUNCTIONAL_AS_ACTION_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+//! Function object adapter for Boost.Spirit actions
+template< typename FunT >
+struct as_action_adapter
+{
+ typedef typename FunT::result_type result_type;
+
+ BOOST_DEFAULTED_FUNCTION(as_action_adapter(), {})
+ explicit as_action_adapter(FunT const& fun) : m_fun(fun) {}
+
+ template< typename AttributeT, typename ContextT >
+ result_type operator() (AttributeT const& attr, ContextT const& ctx, bool& pass) const
+ {
+ return m_fun(attr);
+ }
+
+private:
+ FunT m_fun;
+};
+
+template< typename FunT >
+BOOST_FORCEINLINE as_action_adapter< FunT > as_action(FunT const& fun)
+{
+ return as_action_adapter< FunT >(fun);
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_FUNCTIONAL_AS_ACTION_HPP_INCLUDED_
diff --git a/boost/log/utility/functional/begins_with.hpp b/boost/log/utility/functional/begins_with.hpp
new file mode 100644
index 0000000000..b8e91baa7e
--- /dev/null
+++ b/boost/log/utility/functional/begins_with.hpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file begins_with.hpp
+ * \author Andrey Semashev
+ * \date 30.03.2008
+ *
+ * This header contains a predicate for checking if the provided string begins with a substring.
+ */
+
+#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_BEGINS_WITH_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_FUNCTIONAL_BEGINS_WITH_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+//! The \c begins_with functor
+struct begins_with_fun
+{
+ typedef bool result_type;
+
+ template< typename T, typename U >
+ bool operator() (T const& left, U const& right) const
+ {
+ typedef typename T::const_iterator left_iterator;
+ typedef typename U::const_iterator right_iterator;
+
+ left_iterator left_it = left.begin(), left_end = left.end();
+ right_iterator right_it = right.begin(), right_end = right.end();
+ for (; left_it != left_end && right_it != right_end; ++left_it, ++right_it)
+ {
+ if (*left_it != *right_it)
+ break;
+ }
+ return right_it == right_end;
+ }
+};
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_FUNCTIONAL_BEGINS_WITH_HPP_INCLUDED_
diff --git a/boost/log/utility/functional/bind.hpp b/boost/log/utility/functional/bind.hpp
new file mode 100644
index 0000000000..cdc79cba57
--- /dev/null
+++ b/boost/log/utility/functional/bind.hpp
@@ -0,0 +1,237 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file bind.hpp
+ * \author Andrey Semashev
+ * \date 30.03.2008
+ *
+ * This header contains function object adapters.
+ * This is a lightweight alternative to what Boost.Phoenix and Boost.Bind provides.
+ */
+
+#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_BIND_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_FUNCTIONAL_BIND_HPP_INCLUDED_
+
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+template< typename T >
+struct make_arg_type
+{
+ typedef T const& type;
+};
+
+template< typename T >
+struct make_arg_type< T& >
+{
+ typedef T& type;
+};
+
+} // namespace aux
+
+//! First argument binder
+template< typename FunT, typename FirstArgT >
+struct binder1st :
+ private FunT
+{
+ typedef typename FunT::result_type result_type;
+
+ binder1st(FunT const& fun, typename aux::make_arg_type< FirstArgT >::type arg) : FunT(fun), m_arg(arg) {}
+
+ result_type operator() () const
+ {
+ return FunT::operator()(m_arg);
+ }
+
+ template< typename T0 >
+ result_type operator() (T0 const& arg0) const
+ {
+ return FunT::operator()(m_arg, arg0);
+ }
+
+ template< typename T0, typename T1 >
+ result_type operator() (T0 const& arg0, T1 const& arg1) const
+ {
+ return FunT::operator()(m_arg, arg0, arg1);
+ }
+
+private:
+ FirstArgT m_arg;
+};
+
+//! First argument binder
+template< typename FunT, typename FirstArgT >
+struct binder1st< FunT&, FirstArgT >
+{
+ typedef typename remove_cv< FunT >::type::result_type result_type;
+
+ binder1st(FunT& fun, typename aux::make_arg_type< FirstArgT >::type arg) : m_fun(fun), m_arg(arg) {}
+
+ result_type operator() () const
+ {
+ return m_fun(m_arg);
+ }
+
+ template< typename T0 >
+ result_type operator() (T0 const& arg0) const
+ {
+ return m_fun(m_arg, arg0);
+ }
+
+ template< typename T0, typename T1 >
+ result_type operator() (T0 const& arg0, T1 const& arg1) const
+ {
+ return m_fun(m_arg, arg0, arg1);
+ }
+
+private:
+ FunT& m_fun;
+ FirstArgT m_arg;
+};
+
+template< typename FunT, typename FirstArgT >
+BOOST_FORCEINLINE binder1st< FunT, FirstArgT > bind1st(FunT fun, FirstArgT const& arg)
+{
+ return binder1st< FunT, FirstArgT >(fun, arg);
+}
+
+template< typename FunT, typename FirstArgT >
+BOOST_FORCEINLINE binder1st< FunT, FirstArgT > bind1st(FunT fun, FirstArgT& arg)
+{
+ return binder1st< FunT, FirstArgT >(fun, arg);
+}
+
+//! Second argument binder
+template< typename FunT, typename SecondArgT >
+struct binder2nd :
+ private FunT
+{
+ typedef typename FunT::result_type result_type;
+
+ binder2nd(FunT const& fun, typename aux::make_arg_type< SecondArgT >::type arg) : FunT(fun), m_arg(arg) {}
+
+ template< typename T >
+ result_type operator() (T const& arg) const
+ {
+ return FunT::operator()(arg, m_arg);
+ }
+
+ template< typename T0, typename T1 >
+ result_type operator() (T0 const& arg0, T1 const& arg1) const
+ {
+ return FunT::operator()(arg0, m_arg, arg1);
+ }
+
+private:
+ SecondArgT m_arg;
+};
+
+//! Second argument binder
+template< typename FunT, typename SecondArgT >
+struct binder2nd< FunT&, SecondArgT >
+{
+ typedef typename remove_cv< FunT >::type::result_type result_type;
+
+ binder2nd(FunT& fun, typename aux::make_arg_type< SecondArgT >::type arg) : m_fun(fun), m_arg(arg) {}
+
+ template< typename T >
+ result_type operator() (T const& arg) const
+ {
+ return m_fun(arg, m_arg);
+ }
+
+ template< typename T0, typename T1 >
+ result_type operator() (T0 const& arg0, T1 const& arg1) const
+ {
+ return m_fun(arg0, m_arg, arg1);
+ }
+
+private:
+ FunT& m_fun;
+ SecondArgT m_arg;
+};
+
+template< typename FunT, typename SecondArgT >
+BOOST_FORCEINLINE binder2nd< FunT, SecondArgT > bind2nd(FunT fun, SecondArgT const& arg)
+{
+ return binder2nd< FunT, SecondArgT >(fun, arg);
+}
+
+template< typename FunT, typename SecondArgT >
+BOOST_FORCEINLINE binder2nd< FunT, SecondArgT > bind2nd(FunT fun, SecondArgT& arg)
+{
+ return binder2nd< FunT, SecondArgT >(fun, arg);
+}
+
+//! Third argument binder
+template< typename FunT, typename ThirdArgT >
+struct binder3rd :
+ private FunT
+{
+ typedef typename FunT::result_type result_type;
+
+ binder3rd(FunT const& fun, typename aux::make_arg_type< ThirdArgT >::type arg) : FunT(fun), m_arg(arg) {}
+
+ template< typename T0, typename T1 >
+ result_type operator() (T0 const& arg0, T1 const& arg1) const
+ {
+ return FunT::operator()(arg0, arg1, m_arg);
+ }
+
+private:
+ ThirdArgT m_arg;
+};
+
+//! Third argument binder
+template< typename FunT, typename ThirdArgT >
+struct binder3rd< FunT&, ThirdArgT >
+{
+ typedef typename remove_cv< FunT >::type::result_type result_type;
+
+ binder3rd(FunT& fun, typename aux::make_arg_type< ThirdArgT >::type arg) : m_fun(fun), m_arg(arg) {}
+
+ template< typename T0, typename T1 >
+ result_type operator() (T0 const& arg0, T1 const& arg1) const
+ {
+ return m_fun(arg0, arg1, m_arg);
+ }
+
+private:
+ FunT& m_fun;
+ ThirdArgT m_arg;
+};
+
+template< typename FunT, typename ThirdArgT >
+BOOST_FORCEINLINE binder3rd< FunT, ThirdArgT > bind3rd(FunT fun, ThirdArgT const& arg)
+{
+ return binder3rd< FunT, ThirdArgT >(fun, arg);
+}
+
+template< typename FunT, typename ThirdArgT >
+BOOST_FORCEINLINE binder3rd< FunT, ThirdArgT > bind3rd(FunT fun, ThirdArgT& arg)
+{
+ return binder3rd< FunT, ThirdArgT >(fun, arg);
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_FUNCTIONAL_BIND_HPP_INCLUDED_
diff --git a/boost/log/utility/functional/bind_assign.hpp b/boost/log/utility/functional/bind_assign.hpp
new file mode 100644
index 0000000000..acfad9426e
--- /dev/null
+++ b/boost/log/utility/functional/bind_assign.hpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file bind_assign.hpp
+ * \author Andrey Semashev
+ * \date 30.03.2008
+ *
+ * This header contains a function object that assigns the received value to the bound object.
+ * This is a lightweight alternative to what Boost.Phoenix and Boost.Lambda provides.
+ */
+
+#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_BIND_ASSIGN_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_FUNCTIONAL_BIND_ASSIGN_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/utility/functional/bind.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+//! The function object that assigns its second operand to the first one
+struct assign_fun
+{
+ typedef void result_type;
+
+ template< typename LeftT, typename RightT >
+ void operator() (LeftT& assignee, RightT const& val) const
+ {
+ assignee = val;
+ }
+};
+
+template< typename AssigneeT >
+BOOST_FORCEINLINE binder1st< assign_fun, AssigneeT& > bind_assign(AssigneeT& assignee)
+{
+ return binder1st< assign_fun, AssigneeT& >(assign_fun(), assignee);
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_FUNCTIONAL_BIND_ASSIGN_HPP_INCLUDED_
diff --git a/boost/log/utility/functional/bind_output.hpp b/boost/log/utility/functional/bind_output.hpp
new file mode 100644
index 0000000000..19cd88b947
--- /dev/null
+++ b/boost/log/utility/functional/bind_output.hpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file bind_output.hpp
+ * \author Andrey Semashev
+ * \date 30.03.2008
+ *
+ * This header contains a function object that puts the received value to the bound stream.
+ * This is a lightweight alternative to what Boost.Phoenix and Boost.Lambda provides.
+ */
+
+#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_BIND_OUTPUT_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_FUNCTIONAL_BIND_OUTPUT_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/utility/functional/bind.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+//! The function object that outputs its second operand to the first one
+struct output_fun
+{
+ typedef void result_type;
+
+ template< typename StreamT, typename T >
+ void operator() (StreamT& strm, T const& val) const
+ {
+ strm << val;
+ }
+};
+
+template< typename StreamT >
+BOOST_FORCEINLINE binder1st< output_fun, StreamT& > bind_output(StreamT& strm)
+{
+ return binder1st< output_fun, StreamT& >(output_fun(), strm);
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_FUNCTIONAL_BIND_OUTPUT_HPP_INCLUDED_
diff --git a/boost/log/utility/functional/bind_to_log.hpp b/boost/log/utility/functional/bind_to_log.hpp
new file mode 100644
index 0000000000..9131d6658f
--- /dev/null
+++ b/boost/log/utility/functional/bind_to_log.hpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file bind_to_log.hpp
+ * \author Andrey Semashev
+ * \date 06.11.2012
+ *
+ * This header contains a function object that puts the received value to the bound stream using the \c to_log manipulator.
+ * This is a lightweight alternative to what Boost.Phoenix and Boost.Lambda provides.
+ */
+
+#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_BIND_TO_LOG_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_FUNCTIONAL_BIND_TO_LOG_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/utility/functional/bind.hpp>
+#include <boost/log/utility/manipulators/to_log.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+//! The function object that outputs its second operand to the first one
+template< typename TagT = void >
+struct to_log_fun
+{
+ typedef void result_type;
+
+ template< typename StreamT, typename T >
+ void operator() (StreamT& strm, T const& val) const
+ {
+ strm << boost::log::to_log< TagT >(val);
+ }
+};
+
+//! The function object that outputs its second operand to the first one
+template< >
+struct to_log_fun< void >
+{
+ typedef void result_type;
+
+ template< typename StreamT, typename T >
+ void operator() (StreamT& strm, T const& val) const
+ {
+ strm << boost::log::to_log(val);
+ }
+};
+
+template< typename StreamT >
+BOOST_FORCEINLINE binder1st< to_log_fun< >, StreamT& > bind_to_log(StreamT& strm)
+{
+ return binder1st< to_log_fun< >, StreamT& >(to_log_fun< >(), strm);
+}
+
+template< typename TagT, typename StreamT >
+BOOST_FORCEINLINE binder1st< to_log_fun< TagT >, StreamT& > bind_to_log(StreamT& strm)
+{
+ return binder1st< to_log_fun< TagT >, StreamT& >(to_log_fun< TagT >(), strm);
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_FUNCTIONAL_BIND_TO_LOG_HPP_INCLUDED_
diff --git a/boost/log/utility/functional/contains.hpp b/boost/log/utility/functional/contains.hpp
new file mode 100644
index 0000000000..84b6cd3d53
--- /dev/null
+++ b/boost/log/utility/functional/contains.hpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file contains.hpp
+ * \author Andrey Semashev
+ * \date 30.03.2008
+ *
+ * This header contains a predicate for checking if the provided string contains a substring.
+ */
+
+#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_CONTAINS_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_FUNCTIONAL_CONTAINS_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+//! The \c contains functor
+struct contains_fun
+{
+ typedef bool result_type;
+
+ template< typename T, typename U >
+ bool operator() (T const& left, U const& right) const
+ {
+ typedef typename T::const_iterator left_iterator;
+ typedef typename U::const_iterator right_iterator;
+
+ typename U::size_type const right_size = right.size();
+ if (left.size() >= right_size)
+ {
+ const left_iterator search_end = left.end() - right_size + 1;
+ const right_iterator right_end = right.end();
+ for (left_iterator it = left.begin(); it != search_end; ++it)
+ {
+ left_iterator left_it = it;
+ right_iterator right_it = right.begin();
+ for (; right_it != right_end; ++left_it, ++right_it)
+ {
+ if (*left_it != *right_it)
+ break;
+ }
+ if (right_it == right_end)
+ return true;
+ }
+ }
+
+ return false;
+ }
+};
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_FUNCTIONAL_CONTAINS_HPP_INCLUDED_
diff --git a/boost/log/utility/functional/ends_with.hpp b/boost/log/utility/functional/ends_with.hpp
new file mode 100644
index 0000000000..ddf6578a2e
--- /dev/null
+++ b/boost/log/utility/functional/ends_with.hpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file ends_with.hpp
+ * \author Andrey Semashev
+ * \date 30.03.2008
+ *
+ * This header contains a predicate for checking if the provided string ends with a substring.
+ */
+
+#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_ENDS_WITH_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_FUNCTIONAL_ENDS_WITH_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+//! The \c ends_with functor
+struct ends_with_fun
+{
+ typedef bool result_type;
+
+ template< typename T, typename U >
+ bool operator() (T const& left, U const& right) const
+ {
+ typedef typename T::const_reverse_iterator left_iterator;
+ typedef typename U::const_reverse_iterator right_iterator;
+
+ left_iterator left_it = left.rbegin(), left_end = left.rend();
+ right_iterator right_it = right.rbegin(), right_end = right.rend();
+ for (; left_it != left_end && right_it != right_end; ++left_it, ++right_it)
+ {
+ if (*left_it != *right_it)
+ break;
+ }
+ return right_it == right_end;
+ }
+};
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_FUNCTIONAL_ENDS_WITH_HPP_INCLUDED_
diff --git a/boost/log/utility/functional/fun_ref.hpp b/boost/log/utility/functional/fun_ref.hpp
new file mode 100644
index 0000000000..08e3c6ac95
--- /dev/null
+++ b/boost/log/utility/functional/fun_ref.hpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file fun_ref.hpp
+ * \author Andrey Semashev
+ * \date 30.03.2008
+ *
+ * This header contains function object reference adapter. The adapter stores a reference to external
+ * function object and forwards all calls to the referred function.
+ */
+
+#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_FUN_REF_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_FUNCTIONAL_FUN_REF_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+//! Reference wrapper for function objects
+template< typename FunT >
+struct function_reference_wrapper
+{
+ typedef typename FunT::result_type result_type;
+
+ explicit function_reference_wrapper(FunT& fun) : m_Fun(fun) {}
+
+ result_type operator() () const
+ {
+ return m_Fun();
+ }
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template< typename... ArgsT >
+ result_type operator() (ArgsT const&... args) const
+ {
+ return m_Fun(args...);
+ }
+#else
+ template< typename T >
+ result_type operator() (T const& arg) const
+ {
+ return m_Fun(arg);
+ }
+
+ template< typename T1, typename T2 >
+ result_type operator() (T1 const& arg1, T2 const& arg2) const
+ {
+ return m_Fun(arg1, arg2);
+ }
+#endif
+
+private:
+ FunT& m_Fun;
+};
+
+template< typename FunT >
+BOOST_FORCEINLINE function_reference_wrapper< FunT > fun_ref(FunT& fun)
+{
+ return function_reference_wrapper< FunT >(fun);
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_FUNCTIONAL_FUN_REF_HPP_INCLUDED_
diff --git a/boost/log/utility/functional/in_range.hpp b/boost/log/utility/functional/in_range.hpp
new file mode 100644
index 0000000000..3fe808a74a
--- /dev/null
+++ b/boost/log/utility/functional/in_range.hpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file in_range.hpp
+ * \author Andrey Semashev
+ * \date 30.03.2008
+ *
+ * This header contains a predicate for checking if the provided value is within a half-open range.
+ */
+
+#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_IN_RANGE_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_FUNCTIONAL_IN_RANGE_HPP_INCLUDED_
+
+#include <utility>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/utility/functional/logical.hpp> // make_common_integral_type
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+//! The in_range functor
+struct in_range_fun
+{
+ typedef bool result_type;
+
+ template< typename T, typename U >
+ bool operator() (T const& value, std::pair< U, U > const& rng) const
+ {
+ return op(value, rng, typename mpl::and_< is_integral< T >, is_integral< U > >::type());
+ }
+
+private:
+ template< typename T, typename U >
+ static bool op(T const& value, std::pair< U, U > const& rng, mpl::false_ const&)
+ {
+ return (value >= rng.first && value < rng.second);
+ }
+ template< typename T, typename U >
+ static bool op(T const& value, std::pair< U, U > const& rng, mpl::true_ const&)
+ {
+ typedef typename aux::make_common_integral_type< T, U >::type common_integral_type;
+ return (static_cast< common_integral_type >(value) >= static_cast< common_integral_type >(rng.first))
+ && (static_cast< common_integral_type >(value) < static_cast< common_integral_type >(rng.second));
+ }
+};
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_FUNCTIONAL_IN_RANGE_HPP_INCLUDED_
diff --git a/boost/log/utility/functional/logical.hpp b/boost/log/utility/functional/logical.hpp
new file mode 100644
index 0000000000..92bd79705b
--- /dev/null
+++ b/boost/log/utility/functional/logical.hpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file logical.hpp
+ * \author Andrey Semashev
+ * \date 30.03.2008
+ *
+ * This header contains logical predicates for value comparison, analogous to \c std::less, \c std::greater
+ * and others. The main difference from the standard equivalents is that the predicates defined in this
+ * header are not templates and therefore do not require a fixed argument type. Furthermore, both arguments
+ * may have different types, in which case the comparison is performed without type conversion.
+ *
+ * \note In case if arguments are integral, the conversion is performed according to the standard C++ rules
+ * in order to avoid warnings from the compiler.
+ */
+
+#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_LOGICAL_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_FUNCTIONAL_LOGICAL_HPP_INCLUDED_
+
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_unsigned.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! The trait creates a common integral type suitable for comparison. This is mostly to silence compiler warnings like 'signed/unsigned mismatch'.
+template< typename T, typename U, unsigned int TSizeV = sizeof(T), unsigned int USizeV = sizeof(U), bool TSmallerThanU = (sizeof(T) < sizeof(U)) >
+struct make_common_integral_type
+{
+ typedef T type;
+};
+
+//! Specialization for case when \c T is smaller than \c U
+template< typename T, typename U, unsigned int TSizeV, unsigned int USizeV >
+struct make_common_integral_type< T, U, TSizeV, USizeV, true >
+{
+ typedef U type;
+};
+
+//! Specialization for the case when both types have the same size
+template< typename T, typename U, unsigned int SizeV >
+struct make_common_integral_type< T, U, SizeV, SizeV, false > :
+ public mpl::if_<
+ is_unsigned< T >,
+ T,
+ U
+ >
+{
+};
+
+} // namespace aux
+
+//! Equality predicate
+struct equal_to
+{
+ typedef bool result_type;
+
+ template< typename T, typename U >
+ bool operator() (T const& left, U const& right) const
+ {
+ return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type());
+ }
+
+private:
+ template< typename T, typename U >
+ static bool op(T const& left, U const& right, mpl::false_ const&)
+ {
+ return (left == right);
+ }
+ template< typename T, typename U >
+ static bool op(T const& left, U const& right, mpl::true_ const&)
+ {
+ typedef typename aux::make_common_integral_type< T, U >::type common_integral_type;
+ return static_cast< common_integral_type >(left) == static_cast< common_integral_type >(right);
+ }
+};
+
+//! Inequality predicate
+struct not_equal_to
+{
+ typedef bool result_type;
+
+ template< typename T, typename U >
+ bool operator() (T const& left, U const& right) const
+ {
+ return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type());
+ }
+
+private:
+ template< typename T, typename U >
+ static bool op(T const& left, U const& right, mpl::false_ const&)
+ {
+ return (left != right);
+ }
+ template< typename T, typename U >
+ static bool op(T const& left, U const& right, mpl::true_ const&)
+ {
+ typedef typename aux::make_common_integral_type< T, U >::type common_integral_type;
+ return static_cast< common_integral_type >(left) != static_cast< common_integral_type >(right);
+ }
+};
+
+//! Less predicate
+struct less
+{
+ typedef bool result_type;
+
+ template< typename T, typename U >
+ bool operator() (T const& left, U const& right) const
+ {
+ return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type());
+ }
+
+private:
+ template< typename T, typename U >
+ static bool op(T const& left, U const& right, mpl::false_ const&)
+ {
+ return (left < right);
+ }
+ template< typename T, typename U >
+ static bool op(T const& left, U const& right, mpl::true_ const&)
+ {
+ typedef typename aux::make_common_integral_type< T, U >::type common_integral_type;
+ return static_cast< common_integral_type >(left) < static_cast< common_integral_type >(right);
+ }
+};
+
+//! Greater predicate
+struct greater
+{
+ typedef bool result_type;
+
+ template< typename T, typename U >
+ bool operator() (T const& left, U const& right) const
+ {
+ return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type());
+ }
+
+private:
+ template< typename T, typename U >
+ static bool op(T const& left, U const& right, mpl::false_ const&)
+ {
+ return (left > right);
+ }
+ template< typename T, typename U >
+ static bool op(T const& left, U const& right, mpl::true_ const&)
+ {
+ typedef typename aux::make_common_integral_type< T, U >::type common_integral_type;
+ return static_cast< common_integral_type >(left) > static_cast< common_integral_type >(right);
+ }
+};
+
+//! Less or equal predicate
+struct less_equal
+{
+ typedef bool result_type;
+
+ template< typename T, typename U >
+ bool operator() (T const& left, U const& right) const
+ {
+ return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type());
+ }
+
+private:
+ template< typename T, typename U >
+ static bool op(T const& left, U const& right, mpl::false_ const&)
+ {
+ return (left <= right);
+ }
+ template< typename T, typename U >
+ static bool op(T const& left, U const& right, mpl::true_ const&)
+ {
+ typedef typename aux::make_common_integral_type< T, U >::type common_integral_type;
+ return static_cast< common_integral_type >(left) <= static_cast< common_integral_type >(right);
+ }
+};
+
+//! Greater or equal predicate
+struct greater_equal
+{
+ typedef bool result_type;
+
+ template< typename T, typename U >
+ bool operator() (T const& left, U const& right) const
+ {
+ return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type());
+ }
+
+private:
+ template< typename T, typename U >
+ static bool op(T const& left, U const& right, mpl::false_ const&)
+ {
+ return (left >= right);
+ }
+ template< typename T, typename U >
+ static bool op(T const& left, U const& right, mpl::true_ const&)
+ {
+ typedef typename aux::make_common_integral_type< T, U >::type common_integral_type;
+ return static_cast< common_integral_type >(left) >= static_cast< common_integral_type >(right);
+ }
+};
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_FUNCTIONAL_LOGICAL_HPP_INCLUDED_
diff --git a/boost/log/utility/functional/matches.hpp b/boost/log/utility/functional/matches.hpp
new file mode 100644
index 0000000000..b530f1e964
--- /dev/null
+++ b/boost/log/utility/functional/matches.hpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file matches.hpp
+ * \author Andrey Semashev
+ * \date 30.03.2008
+ *
+ * This header contains a predicate for checking if the provided string matches a regular expression.
+ */
+
+#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_MATCHES_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_FUNCTIONAL_MATCHES_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! The metafunction detects the matching expression kind and returns a tag that is used to specialize \c match_traits
+template< typename ExpressionT, typename = void >
+struct matching_expression_kind;
+
+//! The matching function implementation
+template< typename ExpressionT, typename TagT = typename matching_expression_kind< ExpressionT >::type >
+struct match_traits;
+
+} // namespace aux
+
+//! The regex matching functor
+struct matches_fun
+{
+ typedef bool result_type;
+
+ template< typename StringT, typename ExpressionT >
+ bool operator() (StringT const& str, ExpressionT const& expr) const
+ {
+ typedef aux::match_traits< ExpressionT > impl;
+ return impl::matches(str, expr);
+ }
+ template< typename StringT, typename ExpressionT, typename ArgT >
+ bool operator() (StringT const& str, ExpressionT const& expr, ArgT const& arg) const
+ {
+ typedef aux::match_traits< ExpressionT > impl;
+ return impl::matches(str, expr, arg);
+ }
+};
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_FUNCTIONAL_MATCHES_HPP_INCLUDED_
diff --git a/boost/log/utility/functional/nop.hpp b/boost/log/utility/functional/nop.hpp
new file mode 100644
index 0000000000..0a6e310337
--- /dev/null
+++ b/boost/log/utility/functional/nop.hpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file nop.hpp
+ * \author Andrey Semashev
+ * \date 30.03.2008
+ *
+ * This header contains a function object that does nothing.
+ */
+
+#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_NOP_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_FUNCTIONAL_NOP_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+//! The function object that does nothing
+struct nop
+{
+ typedef void result_type;
+
+ void operator() () const BOOST_NOEXCEPT {}
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template< typename... ArgsT >
+ void operator() (ArgsT const&...) const BOOST_NOEXCEPT {}
+#else
+ template< typename T >
+ void operator() (T const&) const BOOST_NOEXCEPT {}
+ template< typename T1, typename T2 >
+ void operator() (T1 const&, T2 const&) const BOOST_NOEXCEPT {}
+ template< typename T1, typename T2, typename T3 >
+ void operator() (T1 const&, T2 const&, T3 const&) const BOOST_NOEXCEPT {}
+#endif
+};
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_FUNCTIONAL_NOP_HPP_INCLUDED_
diff --git a/boost/log/utility/functional/save_result.hpp b/boost/log/utility/functional/save_result.hpp
new file mode 100644
index 0000000000..d0b22fdff2
--- /dev/null
+++ b/boost/log/utility/functional/save_result.hpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file save_result.hpp
+ * \author Andrey Semashev
+ * \date 19.01.2013
+ *
+ * This header contains function object adapter that saves the result of the adopted function to an external variable.
+ */
+
+#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_SAVE_RESULT_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_FUNCTIONAL_SAVE_RESULT_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+//! Function object wrapper for saving the adopted function object result
+template< typename FunT, typename AssigneeT >
+struct save_result_wrapper
+{
+ typedef void result_type;
+
+ save_result_wrapper(FunT fun, AssigneeT& assignee) : m_fun(fun), m_assignee(assignee) {}
+
+ template< typename ArgT >
+ result_type operator() (ArgT const& arg) const
+ {
+ m_assignee = m_fun(arg);
+ }
+
+private:
+ FunT m_fun;
+ AssigneeT& m_assignee;
+};
+
+template< typename FunT, typename AssigneeT >
+BOOST_FORCEINLINE save_result_wrapper< FunT, AssigneeT > save_result(FunT const& fun, AssigneeT& assignee)
+{
+ return save_result_wrapper< FunT, AssigneeT >(fun, assignee);
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_FUNCTIONAL_SAVE_RESULT_HPP_INCLUDED_
diff --git a/boost/log/utility/intrusive_ref_counter.hpp b/boost/log/utility/intrusive_ref_counter.hpp
new file mode 100644
index 0000000000..025c21ac81
--- /dev/null
+++ b/boost/log/utility/intrusive_ref_counter.hpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file intrusive_ref_counter.hpp
+ * \author Andrey Semashev
+ * \date 12.03.2009
+ *
+ * This header is deprecated, use boost/smart_ptr/intrusive_ref_counter.hpp instead. The header is left for
+ * backward compatibility and will be removed in future versions.
+ */
+
+#ifndef BOOST_LOG_UTILITY_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_
+
+#include <boost/smart_ptr/intrusive_ptr.hpp>
+#include <boost/smart_ptr/intrusive_ref_counter.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(__GNUC__)
+#pragma message "Boost.Log: This header is deprecated, use boost/smart_ptr/intrusive_ref_counter.hpp instead."
+#elif defined(_MSC_VER)
+#pragma message("Boost.Log: This header is deprecated, use boost/smart_ptr/intrusive_ref_counter.hpp instead.")
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+struct legacy_intrusive_ref_counter_root
+{
+ virtual ~legacy_intrusive_ref_counter_root() {}
+};
+
+} // namespace aux
+
+typedef boost::intrusive_ref_counter< aux::legacy_intrusive_ref_counter_root > intrusive_ref_counter;
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_
diff --git a/boost/log/utility/manipulators.hpp b/boost/log/utility/manipulators.hpp
new file mode 100644
index 0000000000..cee1affd2a
--- /dev/null
+++ b/boost/log/utility/manipulators.hpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file manipulators.hpp
+ * \author Andrey Semashev
+ * \date 06.11.2012
+ *
+ * This header includes all manipulators.
+ */
+
+#ifndef BOOST_LOG_UTILITY_MANIPULATORS_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_MANIPULATORS_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#include <boost/log/utility/manipulators/add_value.hpp>
+#include <boost/log/utility/manipulators/to_log.hpp>
+#include <boost/log/utility/manipulators/dump.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#endif // BOOST_LOG_UTILITY_MANIPULATORS_HPP_INCLUDED_
diff --git a/boost/log/utility/manipulators/add_value.hpp b/boost/log/utility/manipulators/add_value.hpp
new file mode 100644
index 0000000000..8d4a7c610f
--- /dev/null
+++ b/boost/log/utility/manipulators/add_value.hpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file add_value.hpp
+ * \author Andrey Semashev
+ * \date 26.11.2012
+ *
+ * This header contains the \c add_value manipulator.
+ */
+
+#ifndef BOOST_LOG_UTILITY_MANIPULATORS_ADD_VALUE_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_MANIPULATORS_ADD_VALUE_HPP_INCLUDED_
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_scalar.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/embedded_string_type.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/attribute_value_impl.hpp>
+#include <boost/log/expressions/keyword_fwd.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(push)
+// 'boost::log::v2s_mt_nt6::add_value_manip<RefT>::m_value' : reference member is initialized to a temporary that doesn't persist after the constructor exits
+// This is intentional since the manipulator can be used with a temporary, which will be used before the streaming expression ends and it is destroyed.
+#pragma warning(disable: 4413)
+// returning address of local variable or temporary
+// This warning refers to add_value_manip<RefT>::get_value() when RefT is an rvalue reference. We store the reference in the manipulator and we intend to return it as is.
+#pragma warning(disable: 4172)
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+//! Attribute value manipulator
+template< typename RefT >
+class add_value_manip
+{
+public:
+ //! Stored reference type
+ typedef RefT reference_type;
+ //! Attribute value type
+ typedef typename remove_cv< typename remove_reference< reference_type >::type >::type value_type;
+
+private:
+ // The stored reference type is an lvalue reference since apparently different compilers (GCC and MSVC) have different quirks when rvalue references are stored as members.
+ // Additionally, MSVC (at least 11.0) has a bug which causes a dangling reference to be stored in the manipulator, if a scalar rvalue is passed to the add_value generator.
+ // To work around this problem we save the value inside the manipulator in this case.
+ typedef typename remove_reference< reference_type >::type& lvalue_reference_type;
+
+ typedef typename mpl::if_<
+ is_scalar< value_type >,
+ value_type,
+ lvalue_reference_type
+ >::type stored_type;
+
+ typedef typename mpl::if_<
+ is_scalar< value_type >,
+ value_type,
+ reference_type
+ >::type get_value_result_type;
+
+private:
+ //! Attribute value
+ stored_type m_value;
+ //! Attribute name
+ attribute_name m_name;
+
+public:
+ //! Initializing constructor
+ add_value_manip(attribute_name const& name, reference_type value) : m_value(static_cast< lvalue_reference_type >(value)), m_name(name)
+ {
+ }
+
+ //! Returns attribute name
+ attribute_name get_name() const { return m_name; }
+ //! Returns attribute value
+ get_value_result_type get_value() const { return static_cast< get_value_result_type >(m_value); }
+};
+
+//! The operator attaches an attribute value to the log record
+template< typename CharT, typename RefT >
+inline basic_record_ostream< CharT >& operator<< (basic_record_ostream< CharT >& strm, add_value_manip< RefT > const& manip)
+{
+ typedef typename aux::make_embedded_string_type< typename add_value_manip< RefT >::value_type >::type value_type;
+ attribute_value value(new attributes::attribute_value_impl< value_type >(manip.get_value()));
+ strm.get_record().attribute_values().insert(manip.get_name(), value);
+ return strm;
+}
+
+//! The function creates a manipulator that attaches an attribute value to a log record
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+template< typename T >
+inline add_value_manip< T&& > add_value(attribute_name const& name, T&& value)
+{
+ return add_value_manip< T&& >(name, static_cast< T&& >(value));
+}
+
+//! \overload
+template< typename DescriptorT, template< typename > class ActorT >
+inline add_value_manip< typename DescriptorT::value_type&& >
+add_value(expressions::attribute_keyword< DescriptorT, ActorT > const&, typename DescriptorT::value_type&& value)
+{
+ typedef typename DescriptorT::value_type value_type;
+ return add_value_manip< value_type&& >(DescriptorT::get_name(), static_cast< value_type&& >(value));
+}
+
+//! \overload
+template< typename DescriptorT, template< typename > class ActorT >
+inline add_value_manip< typename DescriptorT::value_type& >
+add_value(expressions::attribute_keyword< DescriptorT, ActorT > const&, typename DescriptorT::value_type& value)
+{
+ return add_value_manip< typename DescriptorT::value_type& >(DescriptorT::get_name(), value);
+}
+
+//! \overload
+template< typename DescriptorT, template< typename > class ActorT >
+inline add_value_manip< typename DescriptorT::value_type const& >
+add_value(expressions::attribute_keyword< DescriptorT, ActorT > const&, typename DescriptorT::value_type const& value)
+{
+ return add_value_manip< typename DescriptorT::value_type const& >(DescriptorT::get_name(), value);
+}
+
+#else // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+template< typename T >
+inline add_value_manip< T const& > add_value(attribute_name const& name, T const& value)
+{
+ return add_value_manip< T const& >(name, value);
+}
+
+template< typename DescriptorT, template< typename > class ActorT >
+inline add_value_manip< typename DescriptorT::value_type const& >
+add_value(expressions::attribute_keyword< DescriptorT, ActorT > const&, typename DescriptorT::value_type const& value)
+{
+ return add_value_manip< typename DescriptorT::value_type const& >(DescriptorT::get_name(), value);
+}
+
+#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_MANIPULATORS_ADD_VALUE_HPP_INCLUDED_
diff --git a/boost/log/utility/manipulators/dump.hpp b/boost/log/utility/manipulators/dump.hpp
new file mode 100644
index 0000000000..99b2fad749
--- /dev/null
+++ b/boost/log/utility/manipulators/dump.hpp
@@ -0,0 +1,231 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file dump.hpp
+ * \author Andrey Semashev
+ * \date 03.05.2013
+ *
+ * This header contains the \c dump output manipulator.
+ */
+
+#ifndef BOOST_LOG_UTILITY_MANIPULATORS_DUMP_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_MANIPULATORS_DUMP_HPP_INCLUDED_
+
+#include <cstddef>
+#include <iosfwd>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+typedef void dump_data_char_t(const void* data, std::size_t size, std::basic_ostream< char >& strm);
+extern BOOST_LOG_API dump_data_char_t* dump_data_char;
+BOOST_FORCEINLINE void dump_data(const void* data, std::size_t size, std::basic_ostream< char >& strm)
+{
+ (dump_data_char)(data, size, strm);
+}
+
+typedef void dump_data_wchar_t(const void* data, std::size_t size, std::basic_ostream< wchar_t >& strm);
+extern BOOST_LOG_API dump_data_wchar_t* dump_data_wchar;
+BOOST_FORCEINLINE void dump_data(const void* data, std::size_t size, std::basic_ostream< wchar_t >& strm)
+{
+ (dump_data_wchar)(data, size, strm);
+}
+
+#if !defined(BOOST_NO_CXX11_CHAR16_T)
+typedef void dump_data_char16_t(const void* data, std::size_t size, std::basic_ostream< char16_t >& strm);
+extern BOOST_LOG_API dump_data_char16_t* dump_data_char16;
+BOOST_FORCEINLINE void dump_data(const void* data, std::size_t size, std::basic_ostream< char16_t >& strm)
+{
+ (dump_data_char16)(data, size, strm);
+}
+#endif
+
+#if !defined(BOOST_NO_CXX11_CHAR32_T)
+typedef void dump_data_char32_t(const void* data, std::size_t size, std::basic_ostream< char32_t >& strm);
+extern BOOST_LOG_API dump_data_char32_t* dump_data_char32;
+BOOST_FORCEINLINE void dump_data(const void* data, std::size_t size, std::basic_ostream< char32_t >& strm)
+{
+ (dump_data_char32)(data, size, strm);
+}
+#endif
+
+template< std::size_t SizeV, typename R >
+struct enable_dump_size_based
+{
+};
+
+template< typename R >
+struct enable_dump_size_based< 1u, R >
+{
+ typedef R type;
+};
+
+template< typename T, typename R >
+struct enable_dump :
+ public enable_dump_size_based< sizeof(T), R >
+{
+};
+
+template< typename R >
+struct enable_dump< void, R >
+{
+ typedef R type;
+};
+
+template< typename R >
+struct enable_dump< const void, R >
+{
+ typedef R type;
+};
+
+template< typename R >
+struct enable_dump< volatile void, R >
+{
+ typedef R type;
+};
+
+template< typename R >
+struct enable_dump< const volatile void, R >
+{
+ typedef R type;
+};
+
+} // namespace aux
+
+/*!
+ * \brief Manipulator for printing binary representation of the data
+ */
+class dump_manip
+{
+private:
+ //! Beginning of the data
+ const void* m_data;
+ //! Size of the data, in bytes
+ std::size_t m_size;
+
+public:
+ dump_manip(const void* data, std::size_t size) BOOST_NOEXCEPT : m_data(data), m_size(size) {}
+ dump_manip(dump_manip const& that) BOOST_NOEXCEPT : m_data(that.m_data), m_size(that.m_size) {}
+
+ const void* get_data() const BOOST_NOEXCEPT { return m_data; }
+ std::size_t get_size() const BOOST_NOEXCEPT { return m_size; }
+};
+
+//! The operator outputs binary data to a stream
+template< typename CharT, typename TraitsT >
+inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, dump_manip const& manip)
+{
+ if (strm.good())
+ aux::dump_data(manip.get_data(), manip.get_size(), strm);
+
+ return strm;
+}
+
+/*!
+ * \brief Manipulator for printing binary representation of the data with a size limit
+ */
+class bounded_dump_manip :
+ public dump_manip
+{
+private:
+ //! Maximum size to output, in bytes
+ std::size_t m_max_size;
+
+public:
+ bounded_dump_manip(const void* data, std::size_t size, std::size_t max_size) BOOST_NOEXCEPT : dump_manip(data, size), m_max_size(max_size) {}
+ bounded_dump_manip(bounded_dump_manip const& that) BOOST_NOEXCEPT : dump_manip(static_cast< dump_manip const& >(that)), m_max_size(that.m_max_size) {}
+
+ std::size_t get_max_size() const BOOST_NOEXCEPT { return m_max_size; }
+};
+
+//! The operator outputs binary data to a stream
+template< typename CharT, typename TraitsT >
+inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, bounded_dump_manip const& manip)
+{
+ if (strm.good())
+ {
+ const std::size_t size = manip.get_size(), max_size = manip.get_max_size();
+ if (max_size >= size)
+ {
+ aux::dump_data(manip.get_data(), size, strm);
+ }
+ else
+ {
+ aux::dump_data(manip.get_data(), max_size, strm);
+ strm << " and " << (size - max_size) << " bytes more";
+ }
+ }
+
+ return strm;
+}
+
+/*!
+ * \brief Creates a stream manipulator that will output contents of a memory region in hexadecimal form
+ * \param data The pointer to the beginning of the region
+ * \param size The size of the region, in bytes
+ * \return The manipulator that is to be put to a stream
+ */
+template< typename T >
+inline typename aux::enable_dump< T, dump_manip >::type dump(T* data, std::size_t size) BOOST_NOEXCEPT
+{
+ return dump_manip((const void*)data, size);
+}
+
+/*!
+ * \brief Creates a stream manipulator that will dump elements of an array in hexadecimal form
+ * \param data The pointer to the beginning of the array
+ * \param count The size of the region, in number of \c T elements
+ * \return The manipulator that is to be put to a stream
+ */
+template< typename T >
+inline dump_manip dump_elements(T* data, std::size_t count) BOOST_NOEXCEPT
+{
+ return dump_manip((const void*)data, count * sizeof(T));
+}
+
+/*!
+ * \brief Creates a stream manipulator that will output contents of a memory region in hexadecimal form
+ * \param data The pointer to the beginning of the region
+ * \param size The size of the region, in bytes
+ * \params max_size The maximum number of bytes of the region to output
+ * \return The manipulator that is to be put to a stream
+ */
+template< typename T >
+inline typename aux::enable_dump< T, bounded_dump_manip >::type dump(T* data, std::size_t size, std::size_t max_size) BOOST_NOEXCEPT
+{
+ return bounded_dump_manip((const void*)data, size, max_size);
+}
+
+/*!
+ * \brief Creates a stream manipulator that will dump elements of an array in hexadecimal form
+ * \param data The pointer to the beginning of the array
+ * \param count The size of the region, in number of \c T elements
+ * \params max_count The maximum number of elements to output
+ * \return The manipulator that is to be put to a stream
+ */
+template< typename T >
+inline bounded_dump_manip dump_elements(T* data, std::size_t count, std::size_t max_count) BOOST_NOEXCEPT
+{
+ return bounded_dump_manip((const void*)data, count * sizeof(T), max_count * sizeof(T));
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_MANIPULATORS_DUMP_HPP_INCLUDED_
diff --git a/boost/log/utility/manipulators/to_log.hpp b/boost/log/utility/manipulators/to_log.hpp
new file mode 100644
index 0000000000..51e96f5bc1
--- /dev/null
+++ b/boost/log/utility/manipulators/to_log.hpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file to_log.hpp
+ * \author Andrey Semashev
+ * \date 06.11.2012
+ *
+ * This header contains the \c to_log output manipulator.
+ */
+
+#ifndef BOOST_LOG_UTILITY_MANIPULATORS_TO_LOG_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_MANIPULATORS_TO_LOG_HPP_INCLUDED_
+
+#include <iosfwd>
+#include <boost/mpl/bool.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/utility/formatting_ostream_fwd.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * \brief Generic manipulator for customizing output to log
+ */
+template< typename T, typename TagT = void >
+class to_log_manip
+{
+public:
+ //! Output value type
+ typedef T value_type;
+ //! Value tag type
+ typedef TagT tag_type;
+
+private:
+ //! Reference to the value
+ value_type const& m_value;
+
+public:
+ explicit to_log_manip(value_type const& value) : m_value(value) {}
+ to_log_manip(to_log_manip const& that) : m_value(that.m_value) {}
+
+ value_type const& get() const { return m_value; }
+};
+
+template< typename CharT, typename TraitsT, typename T, typename TagT >
+inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, to_log_manip< T, TagT > manip)
+{
+ strm << manip.get();
+ return strm;
+}
+
+template< typename CharT, typename TraitsT, typename AllocatorT, typename T, typename TagT >
+inline basic_formatting_ostream< CharT, TraitsT, AllocatorT >& operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >& strm, to_log_manip< T, TagT > manip)
+{
+ strm << manip.get();
+ return strm;
+}
+
+template< typename T >
+inline to_log_manip< T > to_log(T const& value)
+{
+ return to_log_manip< T >(value);
+}
+
+template< typename TagT, typename T >
+inline to_log_manip< T, TagT > to_log(T const& value)
+{
+ return to_log_manip< T, TagT >(value);
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_MANIPULATORS_TO_LOG_HPP_INCLUDED_
diff --git a/boost/log/utility/once_block.hpp b/boost/log/utility/once_block.hpp
new file mode 100644
index 0000000000..e52f3d1738
--- /dev/null
+++ b/boost/log/utility/once_block.hpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file once_block.hpp
+ * \author Andrey Semashev
+ * \date 23.06.2010
+ *
+ * \brief The header defines classes and macros for once-blocks.
+ */
+
+#ifndef BOOST_LOG_UTILITY_ONCE_BLOCK_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_ONCE_BLOCK_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/utility/unique_identifier_name.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifndef BOOST_LOG_NO_THREADS
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * \brief A flag to detect if a code block has already been executed.
+ *
+ * This structure should be used in conjunction with the \c BOOST_LOG_ONCE_BLOCK_FLAG
+ * macro. Usage example:
+ *
+ * <code>
+ * once_block_flag flag = BOOST_LOG_ONCE_BLOCK_INIT;
+ *
+ * void foo()
+ * {
+ * BOOST_LOG_ONCE_BLOCK_FLAG(flag)
+ * {
+ * puts("Hello, world once!");
+ * }
+ * }
+ * </code>
+ */
+struct once_block_flag
+{
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ // Do not use, implementation detail
+ enum
+ {
+ uninitialized = 0, // this must be zero, so that zero-initialized once_block_flag is equivalent to the one initialized with uninitialized
+ being_initialized,
+ initialized
+ };
+ unsigned char status;
+#endif // BOOST_LOG_DOXYGEN_PASS
+};
+
+/*!
+ * \def BOOST_LOG_ONCE_BLOCK_INIT
+ *
+ * The static initializer for \c once_block_flag.
+ */
+#define BOOST_LOG_ONCE_BLOCK_INIT { boost::log::once_block_flag::uninitialized }
+
+namespace aux {
+
+class once_block_sentry
+{
+private:
+ once_block_flag& m_flag;
+
+public:
+ explicit once_block_sentry(once_block_flag& f) BOOST_NOEXCEPT : m_flag(f)
+ {
+ }
+
+ ~once_block_sentry() BOOST_NOEXCEPT
+ {
+ if (m_flag.status != once_block_flag::initialized)
+ rollback();
+ }
+
+ bool executed() const BOOST_NOEXCEPT
+ {
+ return (m_flag.status == once_block_flag::initialized || enter_once_block());
+ }
+
+ BOOST_LOG_API void commit() BOOST_NOEXCEPT;
+
+private:
+ BOOST_LOG_API bool enter_once_block() const BOOST_NOEXCEPT;
+ BOOST_LOG_API void rollback() BOOST_NOEXCEPT;
+
+ // Non-copyable, non-assignable
+ BOOST_DELETED_FUNCTION(once_block_sentry(once_block_sentry const&))
+ BOOST_DELETED_FUNCTION(once_block_sentry& operator= (once_block_sentry const&))
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#else // BOOST_LOG_NO_THREADS
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+struct once_block_flag
+{
+ bool status;
+};
+
+#define BOOST_LOG_ONCE_BLOCK_INIT { false }
+
+namespace aux {
+
+class once_block_sentry
+{
+private:
+ once_block_flag& m_flag;
+
+public:
+ explicit once_block_sentry(once_block_flag& f) BOOST_NOEXCEPT : m_flag(f)
+ {
+ }
+
+ bool executed() const BOOST_NOEXCEPT
+ {
+ return m_flag.status;
+ }
+
+ void commit() BOOST_NOEXCEPT
+ {
+ m_flag.status = true;
+ }
+
+ // Non-copyable, non-assignable
+ BOOST_DELETED_FUNCTION(once_block_sentry(once_block_sentry const&))
+ BOOST_DELETED_FUNCTION(once_block_sentry& operator= (once_block_sentry const&))
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_NO_THREADS
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#define BOOST_LOG_ONCE_BLOCK_FLAG_INTERNAL(flag_var, sentry_var)\
+ for (boost::log::aux::once_block_sentry sentry_var((flag_var));\
+ BOOST_UNLIKELY(!sentry_var.executed()); sentry_var.commit())
+
+// NOTE: flag_var deliberately doesn't have an initializer so that it is zero-initialized at the static initialization stage
+#define BOOST_LOG_ONCE_BLOCK_INTERNAL(flag_var, sentry_var)\
+ static boost::log::once_block_flag flag_var;\
+ BOOST_LOG_ONCE_BLOCK_FLAG_INTERNAL(flag_var, sentry_var)
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * \def BOOST_LOG_ONCE_BLOCK_FLAG(flag_var)
+ *
+ * Begins a code block to be executed only once, with protection against thread concurrency.
+ * User has to provide the flag variable that controls whether the block has already
+ * been executed.
+ */
+#define BOOST_LOG_ONCE_BLOCK_FLAG(flag_var)\
+ BOOST_LOG_ONCE_BLOCK_FLAG_INTERNAL(\
+ flag_var,\
+ BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_once_block_sentry_))
+
+/*!
+ * \def BOOST_LOG_ONCE_BLOCK()
+ *
+ * Begins a code block to be executed only once, with protection against thread concurrency.
+ */
+#define BOOST_LOG_ONCE_BLOCK()\
+ BOOST_LOG_ONCE_BLOCK_INTERNAL(\
+ BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_once_block_flag_),\
+ BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_once_block_sentry_))
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_ONCE_BLOCK_HPP_INCLUDED_
diff --git a/boost/log/utility/record_ordering.hpp b/boost/log/utility/record_ordering.hpp
new file mode 100644
index 0000000000..bed3b80280
--- /dev/null
+++ b/boost/log/utility/record_ordering.hpp
@@ -0,0 +1,229 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file record_ordering.hpp
+ * \author Andrey Semashev
+ * \date 23.08.2009
+ *
+ * This header contains ordering predicates for logging records.
+ */
+
+#ifndef BOOST_LOG_UTILITY_RECORD_ORDERING_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_RECORD_ORDERING_HPP_INCLUDED_
+
+#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/function_traits.hpp>
+#include <boost/log/core/record_view.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/attribute_value.hpp>
+#include <boost/log/attributes/value_visitation.hpp>
+#include <boost/log/utility/functional/logical.hpp>
+#include <boost/log/utility/functional/nop.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * \brief Ordering predicate, based on opaque pointers to the record view implementation data
+ *
+ * Since record views only refer to a shared implementation data, this predicate is able to order the views
+ * by comparing the pointers to the data. Therefore two views are considered to be equivalent if they
+ * refer to the same implementation data. Otherwise it is not specified whether one record is ordered before
+ * the other until the predicate is applied. Note that the ordering may change every time the application runs.
+ *
+ * This kind of ordering may be useful if log records are to be stored in an associative
+ * container with as least performance overhead as possible, when the particular order is not important.
+ *
+ * The \c FunT template argument is the predicate that is used to actually compare pointers. It should be
+ * able to compare <tt>const void*</tt> pointers. The compared pointers may refer to distinct memory regions,
+ * the pointers must not be interpreted in any way.
+ */
+template< typename FunT = less >
+class abstract_ordering :
+ private FunT
+{
+public:
+ //! Result type
+ typedef bool result_type;
+
+public:
+ /*!
+ * Default constructor. Requires \c FunT to be default constructible.
+ */
+ abstract_ordering() : FunT()
+ {
+ }
+ /*!
+ * Initializing constructor. Constructs \c FunT instance as a copy of the \a fun argument.
+ */
+ explicit abstract_ordering(FunT const& fun) : FunT(fun)
+ {
+ }
+
+ /*!
+ * Ordering operator
+ */
+ result_type operator() (record_view const& left, record_view const& right) const
+ {
+ // We rely on the fact that the attribute_values() method returns a reference to the object in the record implementation,
+ // so we can compare pointers.
+ return FunT::operator() (static_cast< const void* >(&left.attribute_values()), static_cast< const void* >(&right.attribute_values()));
+ }
+};
+
+/*!
+ * \brief Ordering predicate, based on attribute values associated with records
+ *
+ * This predicate allows to order log records based on values of a specifically named attribute
+ * associated with them. Two given log records being compared should both have the specified
+ * attribute value of the specified type to be able to be ordered properly. As a special case,
+ * if neither of the records have the value, these records are considered equivalent. Otherwise,
+ * the ordering results are unspecified.
+ */
+template< typename ValueT, typename FunT = less >
+class attribute_value_ordering :
+ private FunT
+{
+public:
+ //! Result type
+ typedef bool result_type;
+ //! Compared attribute value type
+ typedef ValueT value_type;
+
+private:
+ template< typename LeftT >
+ struct l2_visitor
+ {
+ typedef void result_type;
+
+ l2_visitor(FunT const& fun, LeftT const& left, bool& result) :
+ m_fun(fun), m_left(left), m_result(result)
+ {
+ }
+
+ template< typename RightT >
+ result_type operator() (RightT const& right) const
+ {
+ m_result = m_fun(m_left, right);
+ }
+
+ private:
+ FunT const& m_fun;
+ LeftT const& m_left;
+ bool& m_result;
+ };
+
+ struct l1_visitor;
+ friend struct l1_visitor;
+ struct l1_visitor
+ {
+ typedef void result_type;
+
+ l1_visitor(attribute_value_ordering const& owner, record_view const& right, bool& result) :
+ m_owner(owner), m_right(right), m_result(result)
+ {
+ }
+
+ template< typename LeftT >
+ result_type operator() (LeftT const& left) const
+ {
+ boost::log::visit< value_type >(m_owner.m_name, m_right, l2_visitor< LeftT >(static_cast< FunT const& >(m_owner), left, m_result));
+ }
+
+ private:
+ attribute_value_ordering const& m_owner;
+ record_view const& m_right;
+ bool& m_result;
+ };
+
+private:
+ //! Attribute value name
+ const attribute_name m_name;
+
+public:
+ /*!
+ * Initializing constructor.
+ *
+ * \param name The attribute value name to be compared
+ * \param fun The ordering functor
+ */
+ explicit attribute_value_ordering(attribute_name const& name, FunT const& fun = FunT()) :
+ FunT(fun),
+ m_name(name)
+ {
+ }
+
+ /*!
+ * Ordering operator
+ */
+ result_type operator() (record_view const& left, record_view const& right) const
+ {
+ bool result = false;
+ if (!boost::log::visit< value_type >(m_name, left, l1_visitor(*this, right, result)))
+ {
+ return !boost::log::visit< value_type >(m_name, right, nop());
+ }
+ return result;
+ }
+};
+
+/*!
+ * The function constructs a log record ordering predicate
+ */
+template< typename ValueT, typename FunT >
+inline attribute_value_ordering< ValueT, FunT > make_attr_ordering(attribute_name const& name, FunT const& fun)
+{
+ typedef attribute_value_ordering< ValueT, FunT > ordering_t;
+ return ordering_t(name, fun);
+}
+
+#if !defined(BOOST_LOG_NO_FUNCTION_TRAITS)
+
+namespace aux {
+
+ //! An ordering predicate constructor that uses SFINAE to disable invalid instantiations
+ template<
+ typename FunT,
+ typename ArityCheckT = typename enable_if_c< aux::arity_of< FunT >::value == 2 >::type,
+ typename Arg1T = typename aux::first_argument_type_of< FunT >::type,
+ typename Arg2T = typename aux::second_argument_type_of< FunT >::type,
+ typename ArgsCheckT = typename enable_if< is_same< Arg1T, Arg2T > >::type
+ >
+ struct make_attr_ordering_type
+ {
+ typedef attribute_value_ordering< Arg1T, FunT > type;
+ };
+
+} // namespace aux
+
+/*!
+ * The function constructs a log record ordering predicate
+ */
+template< typename FunT >
+inline typename aux::make_attr_ordering_type< FunT >::type make_attr_ordering(attribute_name const& name, FunT const& fun)
+{
+ typedef typename aux::make_attr_ordering_type< FunT >::type ordering_t;
+ return ordering_t(name, fun);
+}
+
+#endif // BOOST_LOG_NO_FUNCTION_TRAITS
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_RECORD_ORDERING_HPP_INCLUDED_
diff --git a/boost/log/utility/setup.hpp b/boost/log/utility/setup.hpp
new file mode 100644
index 0000000000..135d7dc33c
--- /dev/null
+++ b/boost/log/utility/setup.hpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file setup.hpp
+ * \author Andrey Semashev
+ * \date 16.02.2013
+ *
+ * This header includes all library setup helpers.
+ */
+
+#ifndef BOOST_LOG_UTILITY_SETUP_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_SETUP_HPP_INCLUDED_
+
+#include <boost/log/detail/setup_config.hpp>
+
+#include <boost/log/utility/setup/common_attributes.hpp>
+
+#include <boost/log/utility/setup/console.hpp>
+#include <boost/log/utility/setup/file.hpp>
+
+#include <boost/log/utility/setup/from_settings.hpp>
+#include <boost/log/utility/setup/from_stream.hpp>
+
+#include <boost/log/utility/setup/settings.hpp>
+#include <boost/log/utility/setup/settings_parser.hpp>
+#include <boost/log/utility/setup/filter_parser.hpp>
+#include <boost/log/utility/setup/formatter_parser.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#endif // BOOST_LOG_UTILITY_SETUP_HPP_INCLUDED_
diff --git a/boost/log/utility/setup/common_attributes.hpp b/boost/log/utility/setup/common_attributes.hpp
new file mode 100644
index 0000000000..f2545e963c
--- /dev/null
+++ b/boost/log/utility/setup/common_attributes.hpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file common_attributes.hpp
+ * \author Andrey Semashev
+ * \date 16.05.2008
+ *
+ * The header contains implementation of convenience functions for registering commonly used attributes.
+ */
+
+#ifndef BOOST_LOG_UTILITY_SETUP_COMMON_ATTRIBUTES_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_SETUP_COMMON_ATTRIBUTES_HPP_INCLUDED_
+
+#include <iostream>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/core/core.hpp>
+#include <boost/log/attributes/clock.hpp>
+#include <boost/log/attributes/counter.hpp>
+#include <boost/log/attributes/current_process_id.hpp>
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/log/attributes/current_thread_id.hpp>
+#endif
+#include <boost/log/detail/default_attribute_names.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * \brief Simple attribute initialization routine
+ *
+ * The function adds commonly used attributes to the logging system. Specifically, the following
+ * attributes are registered globally:
+ *
+ * \li LineID - logging records counter with value type <tt>unsigned int</tt>
+ * \li TimeStamp - local time generator with value type <tt>boost::posix_time::ptime</tt>
+ * \li ProcessID - current process identifier with value type
+ * <tt>attributes::current_process_id::value_type</tt>
+ * \li ThreadID - in multithreaded builds, current thread identifier with
+ * value type <tt>attributes::current_thread_id::value_type</tt>
+ */
+inline void add_common_attributes()
+{
+ shared_ptr< core > pCore = core::get();
+ pCore->add_global_attribute(
+ aux::default_attribute_names::line_id(),
+ attributes::counter< unsigned int >(1));
+ pCore->add_global_attribute(
+ aux::default_attribute_names::timestamp(),
+ attributes::local_clock());
+ pCore->add_global_attribute(
+ aux::default_attribute_names::process_id(),
+ attributes::current_process_id());
+#if !defined(BOOST_LOG_NO_THREADS)
+ pCore->add_global_attribute(
+ aux::default_attribute_names::thread_id(),
+ attributes::current_thread_id());
+#endif
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_SETUP_COMMON_ATTRIBUTES_HPP_INCLUDED_
diff --git a/boost/log/utility/setup/console.hpp b/boost/log/utility/setup/console.hpp
new file mode 100644
index 0000000000..fadde4e9b6
--- /dev/null
+++ b/boost/log/utility/setup/console.hpp
@@ -0,0 +1,243 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file console.hpp
+ * \author Andrey Semashev
+ * \date 16.05.2008
+ *
+ * The header contains implementation of convenience functions for enabling logging to console.
+ */
+
+#ifndef BOOST_LOG_UTILITY_SETUP_CONSOLE_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_SETUP_CONSOLE_HPP_INCLUDED_
+
+#include <iostream>
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared_object.hpp>
+#include <boost/core/null_deleter.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/sink_init_helpers.hpp>
+#ifndef BOOST_LOG_NO_THREADS
+#include <boost/log/sinks/sync_frontend.hpp>
+#else
+#include <boost/log/sinks/unlocked_frontend.hpp>
+#endif
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/keywords/format.hpp>
+#include <boost/log/keywords/filter.hpp>
+#include <boost/log/keywords/auto_flush.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+#ifndef BOOST_LOG_NO_THREADS
+#define BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL sinks::synchronous_sink
+#else
+#define BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL sinks::unlocked_sink
+#endif
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+// The function creates and initializes the sink
+template< typename CharT, typename ArgsT >
+shared_ptr<
+ BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL<
+ sinks::basic_text_ostream_backend< CharT >
+ >
+> add_console_log(std::basic_ostream< CharT >& strm, ArgsT const& args)
+{
+ shared_ptr< std::basic_ostream< CharT > > pStream(&strm, boost::null_deleter());
+
+ typedef sinks::basic_text_ostream_backend< CharT > backend_t;
+ shared_ptr< backend_t > pBackend = boost::make_shared< backend_t >();
+
+ pBackend->add_stream(pStream);
+ pBackend->auto_flush(args[keywords::auto_flush | false]);
+
+ typedef BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL< backend_t > sink_t;
+ shared_ptr< sink_t > pSink = boost::make_shared< sink_t >(pBackend);
+
+ aux::setup_filter(*pSink, args,
+ typename is_void< typename parameter::binding< ArgsT, keywords::tag::filter, void >::type >::type());
+
+ aux::setup_formatter(*pSink, args,
+ typename is_void< typename parameter::binding< ArgsT, keywords::tag::format, void >::type >::type());
+
+ core::get()->add_sink(pSink);
+
+ return pSink;
+}
+
+template< typename CharT >
+struct default_console_stream;
+
+#ifdef BOOST_LOG_USE_CHAR
+template< >
+struct default_console_stream< char >
+{
+ static std::ostream& get() { return std::clog; }
+};
+#endif // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+template< >
+struct default_console_stream< wchar_t >
+{
+ static std::wostream& get() { return std::wclog; }
+};
+#endif // BOOST_LOG_USE_WCHAR_T
+
+} // namespace aux
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+template< typename CharT >
+inline shared_ptr<
+ BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL<
+ sinks::basic_text_ostream_backend< CharT >
+ >
+> add_console_log()
+{
+ return aux::add_console_log(
+ aux::default_console_stream< CharT >::get(), keywords::auto_flush = false);
+}
+
+
+template< typename CharT >
+inline shared_ptr<
+ BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL<
+ sinks::basic_text_ostream_backend< CharT >
+ >
+> add_console_log(std::basic_ostream< CharT >& strm)
+{
+ return aux::add_console_log(strm, keywords::auto_flush = false);
+}
+
+template< typename CharT, typename ArgT1 >
+inline shared_ptr<
+ BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL<
+ sinks::basic_text_ostream_backend< CharT >
+ >
+> add_console_log(std::basic_ostream< CharT >& strm, ArgT1 const& arg1)
+{
+ return aux::add_console_log(strm, arg1);
+}
+
+template< typename CharT, typename ArgT1, typename ArgT2 >
+inline shared_ptr<
+ BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL<
+ sinks::basic_text_ostream_backend< CharT >
+ >
+> add_console_log(std::basic_ostream< CharT >& strm, ArgT1 const& arg1, ArgT2 const& arg2)
+{
+ return aux::add_console_log(strm, (arg1, arg2));
+}
+
+template< typename CharT, typename ArgT1, typename ArgT2, typename ArgT3 >
+inline shared_ptr<
+ BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL<
+ sinks::basic_text_ostream_backend< CharT >
+ >
+> add_console_log(std::basic_ostream< CharT >& strm, ArgT1 const& arg1, ArgT2 const& arg2, ArgT3 const& arg3)
+{
+ return aux::add_console_log(strm, (arg1, arg2, arg3));
+}
+
+#else // BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * The function constructs sink for the specified console stream and adds it to the core
+ *
+ * \param strm One of the standard console streams: <tt>std::cout</tt>, <tt>std::cerr</tt> or <tt>std::clog</tt>
+ * (or the corresponding wide-character analogues).
+ * \param args Optional additional named arguments for the sink initialization. The following arguments are supported:
+ * \li \c filter Specifies a filter to install into the sink. May be a string that represents a filter,
+ * or a filter lambda expression.
+ * \li \c format Specifies a formatter to install into the sink. May be a string that represents a formatter,
+ * or a formatter lambda expression (either streaming or Boost.Format-like notation).
+ * \li \c auto_flush A boolean flag that shows whether the sink should automatically flush the stream
+ * after each written record.
+ * \return Pointer to the constructed sink.
+ */
+template< typename CharT, typename... ArgsT >
+shared_ptr<
+ BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL<
+ sinks::basic_text_ostream_backend< CharT >
+ >
+> add_console_log(std::basic_ostream< CharT >& strm, ArgsT... const& args);
+
+/*!
+ * Equivalent to: <tt>add_console_log(std::clog);</tt> or <tt>add_console_log(std::wclog);</tt>,
+ * depending on the \c CharT type.
+ *
+ * \overload
+ */
+template< typename CharT, typename... ArgsT >
+shared_ptr<
+ BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL<
+ sinks::basic_text_ostream_backend< CharT >
+ >
+> add_console_log(ArgsT... const& args);
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+#ifdef BOOST_LOG_USE_CHAR
+
+/*!
+ * The function constructs sink for the <tt>std::clog</tt> stream and adds it to the core
+ *
+ * \overload
+ *
+ * \return Pointer to the constructed sink.
+ */
+inline shared_ptr<
+ BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL<
+ sinks::text_ostream_backend
+ >
+> add_console_log()
+{
+ return add_console_log(std::clog);
+}
+
+#endif // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+
+/*!
+ * The function constructs sink for the <tt>std::wclog</tt> stream and adds it to the core
+ *
+ * \return Pointer to the constructed sink.
+ */
+inline shared_ptr<
+ BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL<
+ sinks::wtext_ostream_backend
+ >
+> wadd_console_log()
+{
+ return add_console_log(std::wclog);
+}
+
+#endif // BOOST_LOG_USE_WCHAR_T
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#undef BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_SETUP_CONSOLE_HPP_INCLUDED_
diff --git a/boost/log/utility/setup/file.hpp b/boost/log/utility/setup/file.hpp
new file mode 100644
index 0000000000..12e9f0bc30
--- /dev/null
+++ b/boost/log/utility/setup/file.hpp
@@ -0,0 +1,166 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file file.hpp
+ * \author Andrey Semashev
+ * \date 16.05.2008
+ *
+ * The header contains implementation of convenience functions for enabling logging to a file.
+ */
+
+#ifndef BOOST_LOG_UTILITY_SETUP_FILE_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_SETUP_FILE_HPP_INCLUDED_
+
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared_object.hpp>
+#include <boost/parameter/parameters.hpp> // for is_named_argument
+#include <boost/preprocessor/comparison/greater.hpp>
+#include <boost/preprocessor/punctuation/comma_if.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/sink_init_helpers.hpp>
+#include <boost/log/detail/parameter_tools.hpp>
+#include <boost/log/core/core.hpp>
+#ifndef BOOST_LOG_NO_THREADS
+#include <boost/log/sinks/sync_frontend.hpp>
+#else
+#include <boost/log/sinks/unlocked_frontend.hpp>
+#endif
+#include <boost/log/sinks/text_file_backend.hpp>
+#include <boost/log/keywords/scan_method.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+#ifndef BOOST_LOG_NO_THREADS
+#define BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL sinks::synchronous_sink
+#else
+#define BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL sinks::unlocked_sink
+#endif
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! The function creates a file collector according to the specified arguments
+template< typename ArgsT >
+inline shared_ptr< sinks::file::collector > setup_file_collector(ArgsT const&, mpl::true_ const&)
+{
+ return shared_ptr< sinks::file::collector >();
+}
+template< typename ArgsT >
+inline shared_ptr< sinks::file::collector > setup_file_collector(ArgsT const& args, mpl::false_ const&)
+{
+ return sinks::file::make_collector(args);
+}
+
+//! The function constructs the sink and adds it to the core
+template< typename ArgsT >
+shared_ptr< BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL< sinks::text_file_backend > > add_file_log(ArgsT const& args)
+{
+ typedef sinks::text_file_backend backend_t;
+ shared_ptr< backend_t > pBackend = boost::make_shared< backend_t >(args);
+
+ shared_ptr< sinks::file::collector > pCollector = aux::setup_file_collector(args,
+ typename is_void< typename parameter::binding< ArgsT, keywords::tag::target, void >::type >::type());
+ if (pCollector)
+ {
+ pBackend->set_file_collector(pCollector);
+ pBackend->scan_for_files(args[keywords::scan_method | sinks::file::scan_matching]);
+ }
+
+ shared_ptr< BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL< backend_t > > pSink =
+ boost::make_shared< BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL< backend_t > >(pBackend);
+
+ aux::setup_filter(*pSink, args,
+ typename is_void< typename parameter::binding< ArgsT, keywords::tag::filter, void >::type >::type());
+
+ aux::setup_formatter(*pSink, args,
+ typename is_void< typename parameter::binding< ArgsT, keywords::tag::format, void >::type >::type());
+
+ core::get()->add_sink(pSink);
+
+ return pSink;
+}
+
+//! The function wraps the argument into a file_name named argument, if needed
+template< typename T >
+inline T const& wrap_file_name(T const& arg, mpl::true_)
+{
+ return arg;
+}
+template< typename T >
+inline typename parameter::aux::tag< keywords::tag::file_name, T const >::type
+wrap_file_name(T const& arg, mpl::false_)
+{
+ return keywords::file_name = arg;
+}
+
+} // namespace aux
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#define BOOST_LOG_INIT_LOG_TO_FILE_INTERNAL(z, n, data)\
+ template< BOOST_PP_ENUM_PARAMS(n, typename T) >\
+ inline shared_ptr< BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL< sinks::text_file_backend > > add_file_log(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg))\
+ {\
+ return aux::add_file_log((\
+ aux::wrap_file_name(arg0, typename parameter::aux::is_named_argument< T0 >::type())\
+ BOOST_PP_COMMA_IF(BOOST_PP_GREATER(n, 1))\
+ BOOST_PP_ENUM_SHIFTED_PARAMS(n, arg)\
+ ));\
+ }
+
+BOOST_PP_REPEAT_FROM_TO(1, BOOST_LOG_MAX_PARAMETER_ARGS, BOOST_LOG_INIT_LOG_TO_FILE_INTERNAL, ~)
+
+#undef BOOST_LOG_INIT_LOG_TO_FILE_INTERNAL
+
+#else // BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * The function initializes the logging library to write logs to a file stream.
+ *
+ * \param args A number of named arguments. The following parameters are supported:
+ * \li \c file_name The file name or its pattern. This parameter is mandatory.
+ * \li \c open_mode The mask that describes the open mode for the file. See <tt>std::ios_base::openmode</tt>.
+ * \li \c rotation_size The size of the file at which rotation should occur. See <tt>basic_text_file_backend</tt>.
+ * \li \c time_based_rotation The predicate for time-based file rotations. See <tt>basic_text_file_backend</tt>.
+ * \li \c auto_flush A boolean flag that shows whether the sink should automatically flush the file
+ * after each written record.
+ * \li \c target The target directory to store rotated files in. See <tt>sinks::file::make_collector</tt>.
+ * \li \c max_size The maximum total size of rotated files in the target directory. See <tt>sinks::file::make_collector</tt>.
+ * \li \c min_free_space Minimum free space in the target directory. See <tt>sinks::file::make_collector</tt>.
+ * \li \c scan_method The method of scanning the target directory for log files. See <tt>sinks::file::scan_method</tt>.
+ * \li \c filter Specifies a filter to install into the sink. May be a string that represents a filter,
+ * or a filter lambda expression.
+ * \li \c format Specifies a formatter to install into the sink. May be a string that represents a formatter,
+ * or a formatter lambda expression (either streaming or Boost.Format-like notation).
+ * \return Pointer to the constructed sink.
+ */
+template< typename... ArgsT >
+shared_ptr< BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL< sinks::text_file_backend > > add_file_log(ArgsT... const& args);
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#undef BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_SETUP_FILE_HPP_INCLUDED_
diff --git a/boost/log/utility/setup/filter_parser.hpp b/boost/log/utility/setup/filter_parser.hpp
new file mode 100644
index 0000000000..cdc0634fd1
--- /dev/null
+++ b/boost/log/utility/setup/filter_parser.hpp
@@ -0,0 +1,346 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file filter_parser.hpp
+ * \author Andrey Semashev
+ * \date 31.03.2008
+ *
+ * The header contains definition of a filter parser function.
+ */
+
+#ifndef BOOST_LOG_UTILITY_SETUP_FILTER_PARSER_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_SETUP_FILTER_PARSER_HPP_INCLUDED_
+
+#include <string>
+#include <boost/lexical_cast.hpp>
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared_object.hpp>
+#include <boost/phoenix/operator/comparison.hpp>
+#include <boost/type_traits/is_base_and_derived.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/log/detail/setup_config.hpp>
+#include <boost/log/detail/code_conversion.hpp>
+#include <boost/log/exceptions.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include <boost/log/expressions/filter.hpp>
+#include <boost/log/expressions/keyword_fwd.hpp>
+#include <boost/log/expressions/attr.hpp>
+#include <boost/log/expressions/predicates/has_attr.hpp>
+#include <boost/log/core/core.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * The interface class for all filter factories.
+ */
+template< typename CharT >
+struct filter_factory
+{
+ //! Character type
+ typedef CharT char_type;
+ //! String type
+ typedef std::basic_string< char_type > string_type;
+
+ /*!
+ * Default constructor
+ */
+ BOOST_DEFAULTED_FUNCTION(filter_factory(), {})
+
+ /*!
+ * Virtual destructor
+ */
+ virtual ~filter_factory() {}
+
+ /*!
+ * The callback for filter for the attribute existence test
+ */
+ virtual filter on_exists_test(attribute_name const& name)
+ {
+ return filter(expressions::has_attr(name));
+ }
+
+ /*!
+ * The callback for equality relation filter
+ */
+ virtual filter on_equality_relation(attribute_name const& name, string_type const& arg)
+ {
+ BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The equality attribute value relation is not supported", (name));
+ BOOST_LOG_UNREACHABLE_RETURN(filter());
+ }
+ /*!
+ * The callback for inequality relation filter
+ */
+ virtual filter on_inequality_relation(attribute_name const& name, string_type const& arg)
+ {
+ BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The inequality attribute value relation is not supported", (name));
+ BOOST_LOG_UNREACHABLE_RETURN(filter());
+ }
+ /*!
+ * The callback for less relation filter
+ */
+ virtual filter on_less_relation(attribute_name const& name, string_type const& arg)
+ {
+ BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The less attribute value relation is not supported", (name));
+ BOOST_LOG_UNREACHABLE_RETURN(filter());
+ }
+ /*!
+ * The callback for greater relation filter
+ */
+ virtual filter on_greater_relation(attribute_name const& name, string_type const& arg)
+ {
+ BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The greater attribute value relation is not supported", (name));
+ BOOST_LOG_UNREACHABLE_RETURN(filter());
+ }
+ /*!
+ * The callback for less or equal relation filter
+ */
+ virtual filter on_less_or_equal_relation(attribute_name const& name, string_type const& arg)
+ {
+ BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The less-or-equal attribute value relation is not supported", (name));
+ BOOST_LOG_UNREACHABLE_RETURN(filter());
+ }
+ /*!
+ * The callback for greater or equal relation filter
+ */
+ virtual filter on_greater_or_equal_relation(attribute_name const& name, string_type const& arg)
+ {
+ BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The greater-or-equal attribute value relation is not supported", (name));
+ BOOST_LOG_UNREACHABLE_RETURN(filter());
+ }
+
+ /*!
+ * The callback for custom relation filter
+ */
+ virtual filter on_custom_relation(attribute_name const& name, string_type const& rel, string_type const& arg)
+ {
+ BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The custom attribute value relation \"" + boost::log::aux::to_narrow(arg) + "\" is not supported", (name));
+ BOOST_LOG_UNREACHABLE_RETURN(filter());
+ }
+
+ BOOST_DELETED_FUNCTION(filter_factory(filter_factory const&))
+ BOOST_DELETED_FUNCTION(filter_factory& operator= (filter_factory const&))
+};
+
+/*!
+ * The base class for filter factories. The class defines default implementations for most
+ * filter expressions. In order to be able to construct filters, the attribute value type must
+ * support reading from a stream. Also, the default filters will rely on relational operators for
+ * the type, so these operators must also be defined.
+ */
+template< typename CharT, typename AttributeValueT >
+class basic_filter_factory :
+ public filter_factory< CharT >
+{
+ //! Base type
+ typedef filter_factory< CharT > base_type;
+
+public:
+ //! The type(s) of the attribute value expected
+ typedef AttributeValueT value_type;
+ // Type imports
+ typedef typename base_type::string_type string_type;
+
+ /*!
+ * The callback for filter for the attribute existence test
+ */
+ virtual filter on_exists_test(attribute_name const& name)
+ {
+ return filter(expressions::has_attr< value_type >(name));
+ }
+
+ /*!
+ * The callback for equality relation filter
+ */
+ virtual filter on_equality_relation(attribute_name const& name, string_type const& arg)
+ {
+ return filter(expressions::attr< value_type >(name) == parse_argument(arg));
+ }
+ /*!
+ * The callback for inequality relation filter
+ */
+ virtual filter on_inequality_relation(attribute_name const& name, string_type const& arg)
+ {
+ return filter(expressions::attr< value_type >(name) != parse_argument(arg));
+ }
+ /*!
+ * The callback for less relation filter
+ */
+ virtual filter on_less_relation(attribute_name const& name, string_type const& arg)
+ {
+ return filter(expressions::attr< value_type >(name) < parse_argument(arg));
+ }
+ /*!
+ * The callback for greater relation filter
+ */
+ virtual filter on_greater_relation(attribute_name const& name, string_type const& arg)
+ {
+ return filter(expressions::attr< value_type >(name) > parse_argument(arg));
+ }
+ /*!
+ * The callback for less or equal relation filter
+ */
+ virtual filter on_less_or_equal_relation(attribute_name const& name, string_type const& arg)
+ {
+ return filter(expressions::attr< value_type >(name) <= parse_argument(arg));
+ }
+ /*!
+ * The callback for greater or equal relation filter
+ */
+ virtual filter on_greater_or_equal_relation(attribute_name const& name, string_type const& arg)
+ {
+ return filter(expressions::attr< value_type >(name) >= parse_argument(arg));
+ }
+
+ /*!
+ * The callback for custom relation filter
+ */
+ virtual filter on_custom_relation(attribute_name const& name, string_type const& rel, string_type const& arg)
+ {
+ BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The custom attribute value relation \"" + boost::log::aux::to_narrow(arg) + "\" is not supported", (name));
+ BOOST_LOG_UNREACHABLE_RETURN(filter());
+ }
+
+ /*!
+ * The function parses the argument value for a binary relation
+ */
+ virtual value_type parse_argument(string_type const& arg)
+ {
+ return boost::lexical_cast< value_type >(arg);
+ }
+};
+
+/*!
+ * The function registers a filter factory object for the specified attribute name. The factory will be
+ * used to construct a filter during parsing the filter string.
+ *
+ * \pre <tt>name != NULL && factory != NULL</tt>, <tt>name</tt> points to a zero-terminated string
+ * \param name Attribute name to associate the factory with
+ * \param factory The filter factory
+ */
+template< typename CharT >
+BOOST_LOG_SETUP_API void register_filter_factory(
+ attribute_name const& name, shared_ptr< filter_factory< CharT > > const& factory);
+
+/*!
+ * The function registers a filter factory object for the specified attribute name. The factory will be
+ * used to construct a filter during parsing the filter string.
+ *
+ * \pre <tt>name != NULL && factory != NULL</tt>, <tt>name</tt> points to a zero-terminated string
+ * \param name Attribute name to associate the factory with
+ * \param factory The filter factory
+ */
+template< typename FactoryT >
+inline typename enable_if<
+ is_base_and_derived< filter_factory< typename FactoryT::char_type >, FactoryT >
+>::type register_filter_factory(attribute_name const& name, shared_ptr< FactoryT > const& factory)
+{
+ typedef filter_factory< typename FactoryT::char_type > factory_base;
+ register_filter_factory(name, boost::static_pointer_cast< factory_base >(factory));
+}
+
+/*!
+ * The function registers a simple filter factory object for the specified attribute name. The factory will
+ * support attribute values of type \c AttributeValueT, which must support all relation operations, such as
+ * equality comparison and less/greater ordering, and also extraction from stream.
+ *
+ * \pre <tt>name != NULL</tt>, <tt>name</tt> points to a zero-terminated string
+ * \param name Attribute name to associate the factory with
+ */
+template< typename AttributeValueT, typename CharT >
+inline void register_simple_filter_factory(attribute_name const& name)
+{
+ shared_ptr< filter_factory< CharT > > factory =
+ boost::make_shared< basic_filter_factory< CharT, AttributeValueT > >();
+ register_filter_factory(name, factory);
+}
+
+/*!
+ * The function registers a simple filter factory object for the specified attribute name. The factory will
+ * support attribute values of type \c AttributeValueT, which must support all relation operations, such as
+ * equality comparison and less/greater ordering, and also extraction from stream.
+ *
+ * \pre <tt>name != NULL</tt>, <tt>name</tt> points to a zero-terminated string
+ * \param name Attribute name to associate the factory with
+ */
+template< typename AttributeValueT >
+inline void register_simple_filter_factory(attribute_name const& name)
+{
+ register_simple_filter_factory< AttributeValueT, char >(name);
+}
+
+/*!
+ * The function registers a simple filter factory object for the specified attribute keyword. The factory will
+ * support attribute values described by the keyword. The values must support all relation operations, such as
+ * equality comparison and less/greater ordering, and also extraction from stream.
+ *
+ * \pre <tt>name != NULL</tt>, <tt>name</tt> points to a zero-terminated string
+ * \param keyword Attribute keyword to associate the factory with
+ */
+template< typename CharT, typename DescriptorT, template< typename > class ActorT >
+inline void register_simple_filter_factory(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword)
+{
+ register_simple_filter_factory< typename DescriptorT::value_type, CharT >(keyword.get_name());
+}
+
+/*!
+ * The function parses a filter from the sequence of characters
+ *
+ * \pre <tt>begin <= end</tt>, both pointers must not be \c NULL
+ * \param begin Pointer to the first character of the sequence
+ * \param end Pointer to the after-the-last character of the sequence
+ * \return A function object that can be used as a filter.
+ *
+ * \b Throws: An <tt>std::exception</tt>-based exception, if a filter cannot be recognized in the character sequence.
+ */
+template< typename CharT >
+BOOST_LOG_SETUP_API filter parse_filter(const CharT* begin, const CharT* end);
+
+/*!
+ * The function parses a filter from the string
+ *
+ * \param str A string that contains filter description
+ * \return A function object that can be used as a filter.
+ *
+ * \b Throws: An <tt>std::exception</tt>-based exception, if a filter cannot be recognized in the character sequence.
+ */
+template< typename CharT, typename TraitsT, typename AllocatorT >
+inline filter parse_filter(std::basic_string< CharT, TraitsT, AllocatorT > const& str)
+{
+ const CharT* p = str.c_str();
+ return parse_filter(p, p + str.size());
+}
+
+/*!
+ * The function parses a filter from the string
+ *
+ * \pre <tt>str != NULL</tt>, <tt>str</tt> points to a zero-terminated string.
+ * \param str A string that contains filter description.
+ * \return A function object that can be used as a filter.
+ *
+ * \b Throws: An <tt>std::exception</tt>-based exception, if a filter cannot be recognized in the character sequence.
+ */
+template< typename CharT >
+inline filter parse_filter(const CharT* str)
+{
+ return parse_filter(str, str + std::char_traits< CharT >::length(str));
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_SETUP_FILTER_PARSER_HPP_INCLUDED_
diff --git a/boost/log/utility/setup/formatter_parser.hpp b/boost/log/utility/setup/formatter_parser.hpp
new file mode 100644
index 0000000000..df78d2ae7e
--- /dev/null
+++ b/boost/log/utility/setup/formatter_parser.hpp
@@ -0,0 +1,216 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file formatter_parser.hpp
+ * \author Andrey Semashev
+ * \date 07.04.2008
+ *
+ * The header contains definition of a formatter parser function, along with facilities to
+ * add support for custom formatters.
+ */
+
+#ifndef BOOST_LOG_UTILITY_SETUP_FORMATTER_PARSER_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_SETUP_FORMATTER_PARSER_HPP_INCLUDED_
+
+#include <iosfwd>
+#include <map>
+#include <string>
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared_object.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/is_base_and_derived.hpp>
+#include <boost/log/detail/setup_config.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/core/record.hpp>
+#include <boost/log/expressions/formatter.hpp>
+#include <boost/log/expressions/attr.hpp>
+#include <boost/log/expressions/formatters/stream.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * Formatter factory base interface.
+ */
+template< typename CharT >
+struct formatter_factory
+{
+ //! Character type
+ typedef CharT char_type;
+ //! String type
+ typedef std::basic_string< char_type > string_type;
+ //! The formatter function object
+ typedef basic_formatter< char_type > formatter_type;
+ /*!
+ * Type of the map of formatter factory arguments [argument name -> argument value].
+ * This type of maps will be passed to formatter factories on attempt to create a formatter.
+ */
+ typedef std::map< string_type, string_type > args_map;
+
+ /*!
+ * Default constructor
+ */
+ BOOST_DEFAULTED_FUNCTION(formatter_factory(), {})
+
+ /*!
+ * Virtual destructor
+ */
+ virtual ~formatter_factory() {}
+
+ /*!
+ * The function creates a formatter for the specified attribute.
+ *
+ * \param name Attribute name
+ * \param args Formatter arguments
+ */
+ virtual formatter_type create_formatter(attribute_name const& name, args_map const& args) = 0;
+
+ BOOST_DELETED_FUNCTION(formatter_factory(formatter_factory const&))
+ BOOST_DELETED_FUNCTION(formatter_factory& operator= (formatter_factory const&))
+};
+
+/*!
+ * Base class for formatter factories. This class provides default implementation of formatter expressions for
+ * types supporting stream output. The factory does not take into account any additional parameters that may be specified.
+ */
+template< typename CharT, typename AttributeValueT >
+class basic_formatter_factory :
+ public formatter_factory< CharT >
+{
+private:
+ typedef formatter_factory< CharT > base_type;
+
+public:
+ //! Attribute value type
+ typedef AttributeValueT value_type;
+ // Type imports from the base class
+ typedef typename base_type::formatter_type formatter_type;
+ typedef typename base_type::args_map args_map;
+
+ /*!
+ * The function creates a formatter for the specified attribute.
+ *
+ * \param name Attribute name
+ * \param args Formatter arguments
+ */
+ formatter_type create_formatter(attribute_name const& name, args_map const& args)
+ {
+ return formatter_type(expressions::stream << expressions::attr< value_type >(name));
+ }
+};
+
+/*!
+ * \brief The function registers a user-defined formatter factory
+ *
+ * The function registers a user-defined formatter factory. The registered factory function will be
+ * called when the formatter parser detects the specified attribute name in the formatter string.
+ *
+ * \pre <tt>!!attr_name && !!factory</tt>.
+ *
+ * \param attr_name Attribute name
+ * \param factory Pointer to the formatter factory
+ */
+template< typename CharT >
+BOOST_LOG_SETUP_API void register_formatter_factory(
+ attribute_name const& attr_name, shared_ptr< formatter_factory< CharT > > const& factory);
+
+/*!
+ * \brief The function registers a user-defined formatter factory
+ *
+ * The function registers a user-defined formatter factory. The registered factory function will be
+ * called when the formatter parser detects the specified attribute name in the formatter string.
+ *
+ * \pre <tt>!!attr_name && !!factory</tt>.
+ *
+ * \param attr_name Attribute name
+ * \param factory Pointer to the formatter factory
+ */
+template< typename FactoryT >
+inline typename enable_if<
+ is_base_and_derived< formatter_factory< typename FactoryT::char_type >, FactoryT >
+>::type register_formatter_factory(attribute_name const& attr_name, shared_ptr< FactoryT > const& factory)
+{
+ typedef formatter_factory< typename FactoryT::char_type > factory_base;
+ register_formatter_factory(attr_name, boost::static_pointer_cast< factory_base >(factory));
+}
+
+/*!
+ * \brief The function registers a simple formatter factory
+ *
+ * The function registers a simple formatter factory. The registered factory will generate formatters
+ * that will be equivalent to the <tt>log::expressions::attr</tt> formatter (i.e. that will use the
+ * native \c operator<< to format the attribute value). The factory does not use any arguments from the format string,
+ * if specified.
+ *
+ * \pre <tt>!!attr_name</tt>.
+ *
+ * \param attr_name Attribute name
+ */
+template< typename AttributeValueT, typename CharT >
+inline void register_simple_formatter_factory(attribute_name const& attr_name)
+{
+ shared_ptr< formatter_factory< CharT > > factory =
+ boost::make_shared< basic_formatter_factory< CharT, AttributeValueT > >();
+ register_formatter_factory(attr_name, factory);
+}
+
+/*!
+ * The function parses a formatter from the sequence of characters
+ *
+ * \pre <tt>begin <= end</tt>, both pointers must not be NULL
+ * \param begin Pointer to the first character of the sequence
+ * \param end Pointer to the after-the-last character of the sequence
+ * \return The parsed formatter.
+ *
+ * \b Throws: An <tt>std::exception</tt>-based exception, if a formatter cannot be recognized in the character sequence.
+ */
+template< typename CharT >
+BOOST_LOG_SETUP_API basic_formatter< CharT > parse_formatter(const CharT* begin, const CharT* end);
+
+/*!
+ * The function parses a formatter from the string
+ *
+ * \param str A string that contains format description
+ * \return The parsed formatter.
+ *
+ * \b Throws: An <tt>std::exception</tt>-based exception, if a formatter cannot be recognized in the character sequence.
+ */
+template< typename CharT, typename TraitsT, typename AllocatorT >
+inline basic_formatter< CharT > parse_formatter(std::basic_string< CharT, TraitsT, AllocatorT > const& str)
+{
+ const CharT* p = str.c_str();
+ return parse_formatter(p, p + str.size());
+}
+
+/*!
+ * The function parses a formatter from the string
+ *
+ * \pre <tt>str != NULL</tt>, <tt>str</tt> points to a zero-terminated string
+ * \param str A string that contains format description.
+ * \return The parsed formatter.
+ *
+ * \b Throws: An <tt>std::exception</tt>-based exception, if a formatter cannot be recognized in the character sequence.
+ */
+template< typename CharT >
+inline basic_formatter< CharT > parse_formatter(const CharT* str)
+{
+ return parse_formatter(str, str + std::char_traits< CharT >::length(str));
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_SETUP_FORMATTER_PARSER_HPP_INCLUDED_
diff --git a/boost/log/utility/setup/from_settings.hpp b/boost/log/utility/setup/from_settings.hpp
new file mode 100644
index 0000000000..50c36f524c
--- /dev/null
+++ b/boost/log/utility/setup/from_settings.hpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file from_settings.hpp
+ * \author Andrey Semashev
+ * \date 11.10.2009
+ *
+ * The header contains definition of facilities that allows to initialize the library from
+ * settings.
+ */
+
+#ifndef BOOST_LOG_UTILITY_SETUP_FROM_SETTINGS_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_SETUP_FROM_SETTINGS_HPP_INCLUDED_
+
+#include <string>
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/is_base_and_derived.hpp>
+#include <boost/log/detail/setup_config.hpp>
+#include <boost/log/sinks/sink.hpp>
+#include <boost/log/utility/setup/settings.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * The function initializes the logging library from a settings container
+ *
+ * \param setts Library settings container
+ *
+ * \b Throws: An <tt>std::exception</tt>-based exception if the provided settings are not valid.
+ */
+template< typename CharT >
+BOOST_LOG_SETUP_API void init_from_settings(basic_settings_section< CharT > const& setts);
+
+
+/*!
+ * Sink factory base interface
+ */
+template< typename CharT >
+struct sink_factory
+{
+ //! Character type
+ typedef CharT char_type;
+ //! String type
+ typedef std::basic_string< char_type > string_type;
+ //! Settings section type
+ typedef basic_settings_section< char_type > settings_section;
+
+ /*!
+ * Default constructor
+ */
+ BOOST_DEFAULTED_FUNCTION(sink_factory(), {})
+
+ /*!
+ * Virtual destructor
+ */
+ virtual ~sink_factory() {}
+
+ /*!
+ * The function creates a formatter for the specified attribute.
+ *
+ * \param settings Sink parameters
+ */
+ virtual shared_ptr< sinks::sink > create_sink(settings_section const& settings) = 0;
+
+ BOOST_DELETED_FUNCTION(sink_factory(sink_factory const&))
+ BOOST_DELETED_FUNCTION(sink_factory& operator= (sink_factory const&))
+};
+
+/*!
+ * \brief The function registers a factory for a custom sink
+ *
+ * The function registers a factory for a sink. The factory will be called to create sink
+ * instance when the parser discovers the specified sink type in the settings file. The
+ * factory must accept a map of parameters [parameter name -> parameter value] that it
+ * may use to initialize the sink. The factory must return a non-NULL pointer to the
+ * constructed sink instance.
+ *
+ * \param sink_name The custom sink name. Must point to a zero-terminated sequence of characters,
+ * must not be NULL.
+ * \param factory Pointer to the custom sink factory. Must not be NULL.
+ */
+template< typename CharT >
+BOOST_LOG_SETUP_API void register_sink_factory(const char* sink_name, shared_ptr< sink_factory< CharT > > const& factory);
+
+/*!
+ * \brief The function registers a factory for a custom sink
+ *
+ * The function registers a factory for a sink. The factory will be called to create sink
+ * instance when the parser discovers the specified sink type in the settings file. The
+ * factory must accept a map of parameters [parameter name -> parameter value] that it
+ * may use to initialize the sink. The factory must return a non-NULL pointer to the
+ * constructed sink instance.
+ *
+ * \param sink_name The custom sink name
+ * \param factory Pointer to the custom sink factory. Must not be NULL.
+ */
+template< typename CharT >
+inline void register_sink_factory(std::string const& sink_name, shared_ptr< sink_factory< CharT > > const& factory)
+{
+ register_sink_factory(sink_name.c_str(), factory);
+}
+
+/*!
+ * \brief The function registers a factory for a custom sink
+ *
+ * The function registers a factory for a sink. The factory will be called to create sink
+ * instance when the parser discovers the specified sink type in the settings file. The
+ * factory must accept a map of parameters [parameter name -> parameter value] that it
+ * may use to initialize the sink. The factory must return a non-NULL pointer to the
+ * constructed sink instance.
+ *
+ * \param sink_name The custom sink name. Must point to a zero-terminated sequence of characters,
+ * must not be NULL.
+ * \param factory Pointer to the custom sink factory. Must not be NULL.
+ */
+template< typename FactoryT >
+inline typename enable_if<
+ is_base_and_derived< sink_factory< typename FactoryT::char_type >, FactoryT >
+>::type register_sink_factory(const char* sink_name, shared_ptr< FactoryT > const& factory)
+{
+ typedef sink_factory< typename FactoryT::char_type > factory_base;
+ register_sink_factory(sink_name, boost::static_pointer_cast< factory_base >(factory));
+}
+
+/*!
+ * \brief The function registers a factory for a custom sink
+ *
+ * The function registers a factory for a sink. The factory will be called to create sink
+ * instance when the parser discovers the specified sink type in the settings file. The
+ * factory must accept a map of parameters [parameter name -> parameter value] that it
+ * may use to initialize the sink. The factory must return a non-NULL pointer to the
+ * constructed sink instance.
+ *
+ * \param sink_name The custom sink name
+ * \param factory Pointer to the custom sink factory. Must not be NULL.
+ */
+template< typename FactoryT >
+inline typename enable_if<
+ is_base_and_derived< sink_factory< typename FactoryT::char_type >, FactoryT >
+>::type register_sink_factory(std::string const& sink_name, shared_ptr< FactoryT > const& factory)
+{
+ typedef sink_factory< typename FactoryT::char_type > factory_base;
+ register_sink_factory(sink_name.c_str(), boost::static_pointer_cast< factory_base >(factory));
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_SETUP_FROM_SETTINGS_HPP_INCLUDED_
diff --git a/boost/log/utility/setup/from_stream.hpp b/boost/log/utility/setup/from_stream.hpp
new file mode 100644
index 0000000000..0b87459e7c
--- /dev/null
+++ b/boost/log/utility/setup/from_stream.hpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file from_stream.hpp
+ * \author Andrey Semashev
+ * \date 22.03.2008
+ *
+ * The header contains definition of facilities that allows to initialize the library from a
+ * settings file.
+ */
+
+#ifndef BOOST_LOG_UTILITY_SETUP_FROM_STREAM_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_SETUP_FROM_STREAM_HPP_INCLUDED_
+
+#include <iosfwd>
+#include <boost/log/detail/setup_config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * The function initializes the logging library from a stream containing logging settings
+ *
+ * \param strm Stream, that provides library settings
+ *
+ * \b Throws: An <tt>std::exception</tt>-based exception if the read data cannot be interpreted as the library settings
+ */
+template< typename CharT >
+BOOST_LOG_SETUP_API void init_from_stream(std::basic_istream< CharT >& strm);
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_SETUP_FROM_STREAM_HPP_INCLUDED_
diff --git a/boost/log/utility/setup/settings.hpp b/boost/log/utility/setup/settings.hpp
new file mode 100644
index 0000000000..bf8a608dea
--- /dev/null
+++ b/boost/log/utility/setup/settings.hpp
@@ -0,0 +1,643 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file settings.hpp
+ * \author Andrey Semashev
+ * \date 11.10.2009
+ *
+ * The header contains definition of the library settings container.
+ */
+
+#ifndef BOOST_LOG_UTILITY_SETUP_SETTINGS_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_SETUP_SETTINGS_HPP_INCLUDED_
+
+#include <cstddef>
+#include <string>
+#include <iterator>
+#include <boost/assert.hpp>
+#include <boost/move/core.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/optional/optional.hpp>
+#include <boost/property_tree/ptree.hpp>
+#include <boost/log/detail/setup_config.hpp>
+#include <boost/log/detail/native_typeof.hpp>
+#include <boost/utility/explicit_operator_bool.hpp>
+#if !defined(BOOST_LOG_TYPEOF)
+#include <boost/utility/enable_if.hpp>
+#endif
+#if defined(BOOST_LOG_TYPEOF) && defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
+#include <boost/utility/declval.hpp>
+#endif
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+// This workaround is needed for MSVC 10 to work around ICE caused by stack overflow
+template< typename SectionT, bool IsConstV >
+struct basic_settings_section_iterator_base;
+
+template< typename SectionT >
+struct basic_settings_section_iterator_base< SectionT, true >
+{
+ typedef typename SectionT::BOOST_NESTED_TEMPLATE iter< true > iterator_type;
+ typedef typename SectionT::property_tree_type::const_iterator base_iterator_type;
+ typedef iterator_adaptor<
+ iterator_type,
+ base_iterator_type,
+ SectionT,
+ use_default,
+ const SectionT
+ > type;
+};
+
+template< typename SectionT >
+struct basic_settings_section_iterator_base< SectionT, false >
+{
+ typedef typename SectionT::BOOST_NESTED_TEMPLATE iter< false > iterator_type;
+ typedef typename SectionT::property_tree_type::iterator base_iterator_type;
+ typedef iterator_adaptor<
+ iterator_type,
+ base_iterator_type,
+ SectionT,
+ use_default,
+ SectionT
+ > type;
+};
+
+} // namespace aux
+
+/*!
+ * \brief The class represents a reference to the settings container section
+ *
+ * The section refers to a sub-tree of the library settings container. It does not
+ * own the referred sub-tree but allows for convenient access to parameters within the subsection.
+ */
+template< typename CharT >
+class basic_settings_section
+{
+ template< typename SectionT, bool IsConstV >
+ friend struct aux::basic_settings_section_iterator_base;
+
+public:
+ //! Character type
+ typedef CharT char_type;
+ //! String type
+ typedef std::basic_string< char_type > string_type;
+ //! Property tree type
+ typedef property_tree::basic_ptree< std::string, string_type > property_tree_type;
+ //! Property tree path type
+ typedef typename property_tree_type::path_type path_type;
+
+private:
+#if !defined(BOOST_LOG_DOXYGEN_PASS)
+
+ //! A reference proxy object
+#ifndef BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS
+ template< bool IsConstV >
+ class ref;
+ template< bool IsConstV >
+ friend class ref;
+#endif
+ template< bool IsConstV >
+ class ref
+ {
+ private:
+ typedef typename mpl::if_c<
+ IsConstV,
+ basic_settings_section< char_type > const,
+ basic_settings_section< char_type >
+ >::type section_type;
+
+ private:
+ section_type& m_section;
+ path_type m_path;
+
+ public:
+ ref(section_type& section, std::string const& section_name) :
+ m_section(section),
+ m_path(section_name)
+ {
+ }
+ ref(section_type& section, const char* section_name) :
+ m_section(section),
+ m_path(section_name)
+ {
+ }
+
+ ref& operator[] (std::string const& param_name)
+ {
+ m_path /= param_name;
+ return *this;
+ }
+
+ ref& operator= (string_type const& value)
+ {
+ BOOST_ASSERT(m_section.m_ptree != NULL);
+ m_section.m_ptree->put(m_path, value);
+ return *this;
+ }
+
+ template< bool V >
+ ref& operator= (ref< V > const& value)
+ {
+ BOOST_ASSERT(m_section.m_ptree != NULL);
+ optional< string_type > val = value.get();
+ if (!!val)
+ {
+ m_section.m_ptree->put(m_path, val);
+ }
+ else if (optional< property_tree_type& > node = m_section.m_ptree->get_child_optional(m_path))
+ {
+ node.put_value(string_type());
+ }
+
+ return *this;
+ }
+
+ template< typename T >
+ ref& operator= (T const& value)
+ {
+ BOOST_ASSERT(m_section.m_ptree != NULL);
+ m_section.m_ptree->put(m_path, value);
+ return *this;
+ }
+
+ BOOST_EXPLICIT_OPERATOR_BOOL()
+
+ bool operator! () const
+ {
+ return !m_section.m_ptree || !m_section.m_ptree->get_child_optional(m_path);
+ }
+
+ std::string get_name() const
+ {
+ return m_path.dump();
+ }
+
+ operator optional< string_type > () const
+ {
+ return get();
+ }
+
+ optional< string_type > get() const
+ {
+ if (m_section.m_ptree)
+ return m_section.m_ptree->template get_optional< string_type >(m_path);
+ else
+ return optional< string_type >();
+ }
+
+ template< typename T >
+ optional< T > get() const
+ {
+ if (m_section.m_ptree)
+ return m_section.m_ptree->template get_optional< T >(m_path);
+ else
+ return optional< T >();
+ }
+
+ operator section_type () const
+ {
+ return get_section();
+ }
+
+ section_type get_section() const
+ {
+ if (m_section.m_ptree)
+ return section_type(m_section.m_ptree->get_child_optional(m_path).get_ptr());
+ else
+ return section_type();
+ }
+
+#if defined(BOOST_LOG_TYPEOF) && !(defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__) && !defined(__PATHSCALE__) && !defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ == 4 && __GNUC_MINOR__ <= 5))
+#if !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
+ template< typename T >
+ auto or_default(T const& def_value) const -> BOOST_LOG_TYPEOF(property_tree_type().get(typename property_tree_type::path_type(), def_value))
+ {
+ if (m_section.m_ptree)
+ return m_section.m_ptree->get(m_path, def_value);
+ else
+ return def_value;
+ }
+#else
+ // GCC up to 4.5 (inclusively) segfaults on the following code, if C++11 mode is not enabled
+ template< typename T >
+ BOOST_LOG_TYPEOF(property_tree_type().get(typename property_tree_type::path_type(), boost::declval< T >())) or_default(T const& def_value) const
+ {
+ if (m_section.m_ptree)
+ return m_section.m_ptree->get(m_path, def_value);
+ else
+ return def_value;
+ }
+#endif
+#else
+ template< typename T >
+ T or_default(T const& def_value) const
+ {
+ if (m_section.m_ptree)
+ return m_section.m_ptree->get(m_path, def_value);
+ else
+ return def_value;
+ }
+
+ template< typename T >
+ typename enable_if< boost::property_tree::detail::is_character< T >, std::basic_string< T > >::type
+ or_default(const T* def_value) const
+ {
+ if (m_section.m_ptree)
+ return m_section.m_ptree->get(m_path, def_value);
+ else
+ return def_value;
+ }
+#endif
+ string_type or_default(string_type const& def_value) const
+ {
+ return get().get_value_or(def_value);
+ }
+ string_type or_default(typename string_type::value_type const* def_value) const
+ {
+ if (optional< string_type > val = get())
+ return val.get();
+ else
+ return def_value;
+ }
+ };
+
+ //! An iterator over subsections and parameters
+#ifndef BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS
+ template< bool IsConstV >
+ class iter;
+ template< bool IsConstV >
+ friend class iter;
+#endif
+ template< bool IsConstV >
+ class iter :
+ public aux::basic_settings_section_iterator_base< basic_settings_section< char_type >, IsConstV >::type
+ {
+ friend class boost::iterator_core_access;
+
+ typedef typename iter::iterator_adaptor_ iterator_adaptor_;
+ // NOTE: This typedef must not come from iterator_adaptor_::base_type in order to work around MSVC 10 ICE
+ typedef typename aux::basic_settings_section_iterator_base< basic_settings_section< char_type >, IsConstV >::base_iterator_type base_iterator_type;
+
+ public:
+ typedef typename iterator_adaptor_::reference reference;
+
+ public:
+ BOOST_DEFAULTED_FUNCTION(iter(), {})
+ template< bool OtherIsConstV >
+ iter(iter< OtherIsConstV > const& that) : iterator_adaptor_(that.base()) {}
+ explicit iter(base_iterator_type const& it) : iterator_adaptor_(it) {}
+
+ //! Returns the section name
+ std::string const& get_name() const
+ {
+ return this->base()->first;
+ }
+
+ private:
+ reference dereference() const
+ {
+ return reference(const_cast< property_tree_type* >(&this->base()->second));
+ }
+ };
+
+public:
+ typedef ref< true > const_reference;
+ typedef ref< false > reference;
+ typedef iter< true > const_iterator;
+ typedef iter< false > iterator;
+ typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
+ typedef std::reverse_iterator< iterator > reverse_iterator;
+
+#else
+
+public:
+ /*!
+ * Constant reference to the parameter value
+ */
+ typedef implementation_defined const_reference;
+ /*!
+ * Mutable reference to the parameter value
+ */
+ typedef implementation_defined reference;
+
+ /*!
+ * Constant iterator over nested parameters and subsections
+ */
+ typedef implementation_defined const_iterator;
+ /*!
+ * Mutable iterator over nested parameters and subsections
+ */
+ typedef implementation_defined iterator;
+
+#endif // !defined(BOOST_LOG_DOXYGEN_PASS)
+
+protected:
+ //! Parameters
+ property_tree_type* m_ptree;
+
+public:
+ /*!
+ * Default constructor. Creates an empty settings container.
+ */
+ basic_settings_section() : m_ptree(NULL)
+ {
+ }
+
+ /*!
+ * Copy constructor.
+ */
+ basic_settings_section(basic_settings_section const& that) : m_ptree(that.m_ptree)
+ {
+ }
+
+ /*!
+ * Checks if the section refers to the container.
+ */
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+
+ /*!
+ * Checks if the section refers to the container.
+ */
+ bool operator! () const BOOST_NOEXCEPT { return !m_ptree; }
+
+ /*!
+ * Returns an iterator over the nested subsections and parameters.
+ */
+ iterator begin()
+ {
+ if (m_ptree)
+ return iterator(m_ptree->begin());
+ else
+ return iterator();
+ }
+
+ /*!
+ * Returns an iterator over the nested subsections and parameters.
+ */
+ iterator end()
+ {
+ if (m_ptree)
+ return iterator(m_ptree->end());
+ else
+ return iterator();
+ }
+
+ /*!
+ * Returns an iterator over the nested subsections and parameters.
+ */
+ const_iterator begin() const
+ {
+ if (m_ptree)
+ return const_iterator(m_ptree->begin());
+ else
+ return const_iterator();
+ }
+
+ /*!
+ * Returns an iterator over the nested subsections and parameters.
+ */
+ const_iterator end() const
+ {
+ if (m_ptree)
+ return const_iterator(m_ptree->end());
+ else
+ return const_iterator();
+ }
+
+ /*!
+ * Returns a reverse iterator over the nested subsections and parameters.
+ */
+ reverse_iterator rbegin() { return reverse_iterator(begin()); }
+
+ /*!
+ * Returns a reverse iterator over the nested subsections and parameters.
+ */
+ reverse_iterator rend() { return reverse_iterator(end()); }
+
+ /*!
+ * Returns a reverse iterator over the nested subsections and parameters.
+ */
+ const_reverse_iterator rbegin() const { return const_reverse_iterator(begin()); }
+
+ /*!
+ * Returns a reverse iterator over the nested subsections and parameters.
+ */
+ const_reverse_iterator rend() const { return const_reverse_iterator(end()); }
+
+ /*!
+ * Checks if the container is empty (i.e. contains no sections and parameters).
+ */
+ bool empty() const { return m_ptree == NULL || m_ptree->empty(); }
+
+ /*!
+ * Accessor to a single parameter. This operator should be used in conjunction
+ * with the subsequent subscript operator that designates the parameter name.
+ *
+ * \param section_name The name of the section in which the parameter resides
+ * \return An unspecified reference type that can be used for parameter name specifying
+ */
+ reference operator[] (std::string const& section_name) { return reference(*this, section_name); }
+ /*!
+ * Accessor to a single parameter. This operator should be used in conjunction
+ * with the subsequent subscript operator that designates the parameter name.
+ *
+ * \param section_name The name of the section in which the parameter resides
+ * \return An unspecified reference type that can be used for parameter name specifying
+ */
+ const_reference operator[] (std::string const& section_name) const { return const_reference(*this, section_name); }
+
+ /*!
+ * Accessor to a single parameter. This operator should be used in conjunction
+ * with the subsequent subscript operator that designates the parameter name.
+ *
+ * \param section_name The name of the section in which the parameter resides
+ * \return An unspecified reference type that can be used for parameter name specifying
+ */
+ reference operator[] (const char* section_name) { return reference(*this, section_name); }
+ /*!
+ * Accessor to a single parameter. This operator should be used in conjunction
+ * with the subsequent subscript operator that designates the parameter name.
+ *
+ * \param section_name The name of the section in which the parameter resides
+ * \return An unspecified reference type that can be used for parameter name specifying
+ */
+ const_reference operator[] (const char* section_name) const { return const_reference(*this, section_name); }
+
+ /*!
+ * Accessor for the embedded property tree
+ */
+ property_tree_type const& property_tree() const { return *m_ptree; }
+ /*!
+ * Accessor for the embedded property tree
+ */
+ property_tree_type& property_tree() { return *m_ptree; }
+
+ /*!
+ * Checks if the specified section is present in the container.
+ *
+ * \param section_name The name of the section
+ */
+ bool has_section(string_type const& section_name) const
+ {
+ return m_ptree != NULL && !!m_ptree->get_child_optional(section_name);
+ }
+ /*!
+ * Checks if the specified parameter is present in the container.
+ *
+ * \param section_name The name of the section in which the parameter resides
+ * \param param_name The name of the parameter
+ */
+ bool has_parameter(string_type const& section_name, string_type const& param_name) const
+ {
+ if (m_ptree)
+ {
+ optional< property_tree_type& > section = m_ptree->get_child_optional(section_name);
+ if (!!section)
+ return (section->find(param_name) != section->not_found());
+ }
+
+ return false;
+ }
+
+ /*!
+ * Swaps two references to settings sections.
+ */
+ void swap(basic_settings_section& that)
+ {
+ property_tree_type* const p = m_ptree;
+ m_ptree = that.m_ptree;
+ that.m_ptree = p;
+ }
+
+protected:
+ explicit basic_settings_section(property_tree_type* tree) : m_ptree(tree)
+ {
+ }
+};
+
+template< typename CharT >
+inline void swap(basic_settings_section< CharT >& left, basic_settings_section< CharT >& right)
+{
+ left.swap(right);
+}
+
+
+/*!
+ * \brief The class represents settings container
+ *
+ * All settings are presented as a number of named parameters divided into named sections.
+ * The parameters values are stored as strings. Individual parameters may be queried via subscript operators, like this:
+ *
+ * <code><pre>
+ * optional< string > param = settings["Section1"]["Param1"]; // reads parameter "Param1" in section "Section1"
+ * // returns an empty value if no such parameter exists
+ * settings["Section2"]["Param2"] = 10; // sets the parameter "Param2" in section "Section2"
+ * // to value "10"
+ * </pre></code>
+ *
+ * There are also other methods to work with parameters.
+ */
+template< typename CharT >
+class basic_settings :
+ public basic_settings_section< CharT >
+{
+ typedef basic_settings this_type;
+ BOOST_COPYABLE_AND_MOVABLE(this_type)
+
+public:
+ //! Section type
+ typedef basic_settings_section< CharT > section;
+ //! Property tree type
+ typedef typename section::property_tree_type property_tree_type;
+
+public:
+ /*!
+ * Default constructor. Creates an empty settings container.
+ */
+ basic_settings() : section(new property_tree_type())
+ {
+ }
+
+ /*!
+ * Copy constructor.
+ */
+ basic_settings(basic_settings const& that) :
+ section(that.m_ptree ? new property_tree_type(*that.m_ptree) : static_cast< property_tree_type* >(NULL))
+ {
+ }
+
+ /*!
+ * Move constructor.
+ */
+ basic_settings(BOOST_RV_REF(this_type) that)
+ {
+ this->swap(that);
+ }
+ /*!
+ * Initializing constructor. Creates a settings container with the copy of the specified property tree.
+ */
+ explicit basic_settings(property_tree_type const& tree) : section(new property_tree_type(tree))
+ {
+ }
+
+ /*!
+ * Destructor
+ */
+ ~basic_settings()
+ {
+ delete this->m_ptree;
+ }
+
+ /*!
+ * Copy assignment operator.
+ */
+ basic_settings& operator= (BOOST_COPY_ASSIGN_REF(basic_settings) that)
+ {
+ if (this != &that)
+ {
+ basic_settings tmp = that;
+ this->swap(tmp);
+ }
+ return *this;
+ }
+ /*!
+ * Move assignment operator.
+ */
+ basic_settings& operator= (BOOST_RV_REF(basic_settings) that)
+ {
+ this->swap(that);
+ return *this;
+ }
+};
+
+#ifdef BOOST_LOG_USE_CHAR
+typedef basic_settings< char > settings; //!< Convenience typedef for narrow-character logging
+typedef basic_settings_section< char > settings_section; //!< Convenience typedef for narrow-character logging
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+typedef basic_settings< wchar_t > wsettings; //!< Convenience typedef for wide-character logging
+typedef basic_settings_section< wchar_t > wsettings_section; //!< Convenience typedef for wide-character logging
+#endif
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_SETUP_SETTINGS_HPP_INCLUDED_
diff --git a/boost/log/utility/setup/settings_parser.hpp b/boost/log/utility/setup/settings_parser.hpp
new file mode 100644
index 0000000000..cf1ea8ea1a
--- /dev/null
+++ b/boost/log/utility/setup/settings_parser.hpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file settings_parser.hpp
+ * \author Andrey Semashev
+ * \date 20.07.2012
+ *
+ * The header contains definition of a settings parser function.
+ */
+
+#ifndef BOOST_LOG_UTILITY_SETUP_SETTINGS_PARSER_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_SETUP_SETTINGS_PARSER_HPP_INCLUDED_
+
+#include <iosfwd>
+#include <boost/log/detail/setup_config.hpp>
+#include <boost/log/utility/setup/settings.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * The function parses library settings from an input stream
+ *
+ * \param strm Stream, that provides library settings
+ *
+ * \b Throws: An <tt>std::exception</tt>-based exception if the read data cannot be interpreted as the library settings
+ */
+template< typename CharT >
+BOOST_LOG_SETUP_API basic_settings< CharT > parse_settings(std::basic_istream< CharT >& strm);
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_SETUP_SETTINGS_PARSER_HPP_INCLUDED_
diff --git a/boost/log/utility/strictest_lock.hpp b/boost/log/utility/strictest_lock.hpp
new file mode 100644
index 0000000000..44733167a6
--- /dev/null
+++ b/boost/log/utility/strictest_lock.hpp
@@ -0,0 +1,214 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file utility/strictest_lock.hpp
+ * \author Andrey Semashev
+ * \date 30.05.2010
+ *
+ * The header contains definition of the \c strictest_lock metafunction that
+ * allows to select a lock with the strictest access requirements.
+ */
+
+#ifndef BOOST_LOG_UTILITY_STRICTEST_LOCK_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_STRICTEST_LOCK_HPP_INCLUDED_
+
+#include <boost/mpl/integral_c.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/locks.hpp>
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/arithmetic/sub.hpp>
+#include <boost/preprocessor/arithmetic/inc.hpp>
+#include <boost/preprocessor/arithmetic/dec.hpp>
+#include <boost/preprocessor/repetition/enum_trailing.hpp>
+#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
+#include <boost/log/detail/pp_identity.hpp>
+#endif
+#if defined(BOOST_LOG_BROKEN_CONSTANT_EXPRESSIONS)
+#include <boost/mpl/less.hpp>
+#endif
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#if !defined(BOOST_LOG_STRICTEST_LOCK_LIMIT)
+/*!
+ * The macro defines the maximum number of template arguments that the \c strictest_lock
+ * metafunction accepts. Should not be less than 2.
+ */
+#define BOOST_LOG_STRICTEST_LOCK_LIMIT 10
+#endif // BOOST_LOG_STRICTEST_LOCK_LIMIT
+#if BOOST_LOG_STRICTEST_LOCK_LIMIT < 2
+#error The BOOST_LOG_STRICTEST_LOCK_LIMIT macro should not be less than 2
+#endif
+#endif // defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+//! Access modes for different types of locks
+enum lock_access_mode
+{
+ unlocked_access, //!< A thread that owns this kind of lock doesn't restrict other threads in any way
+ shared_access, //!< A thread that owns this kind of lock requires that no other thread modify the locked data
+ exclusive_access //!< A thread that owns this kind of lock requires that no other thread has access to the locked data
+};
+
+//! The trait allows to select an access mode by the lock type
+template< typename LockT >
+struct thread_access_mode_of;
+
+template< typename MutexT >
+struct thread_access_mode_of< no_lock< MutexT > > : mpl::integral_c< lock_access_mode, unlocked_access >
+{
+};
+
+#if !defined(BOOST_LOG_NO_THREADS)
+
+template< typename MutexT >
+struct thread_access_mode_of< lock_guard< MutexT > > : mpl::integral_c< lock_access_mode, exclusive_access >
+{
+};
+
+template< typename MutexT >
+struct thread_access_mode_of< unique_lock< MutexT > > : mpl::integral_c< lock_access_mode, exclusive_access >
+{
+};
+
+template< typename MutexT >
+struct thread_access_mode_of< shared_lock< MutexT > > : mpl::integral_c< lock_access_mode, shared_access >
+{
+};
+
+template< typename MutexT >
+struct thread_access_mode_of< upgrade_lock< MutexT > > : mpl::integral_c< lock_access_mode, shared_access >
+{
+};
+
+template< typename MutexT >
+struct thread_access_mode_of< boost::log::aux::exclusive_lock_guard< MutexT > > : mpl::integral_c< lock_access_mode, exclusive_access >
+{
+};
+
+template< typename MutexT >
+struct thread_access_mode_of< boost::log::aux::shared_lock_guard< MutexT > > : mpl::integral_c< lock_access_mode, shared_access >
+{
+};
+
+#endif // !defined(BOOST_LOG_NO_THREADS)
+
+namespace aux {
+
+//! The metafunction selects the most strict lock type of the two
+template<
+ typename LeftLockT,
+ typename RightLockT,
+#if !defined(BOOST_LOG_BROKEN_CONSTANT_EXPRESSIONS)
+ bool CondV = (thread_access_mode_of< LeftLockT >::value < thread_access_mode_of< RightLockT >::value)
+#else
+ bool CondV = mpl::less< thread_access_mode_of< LeftLockT >, thread_access_mode_of< RightLockT > >::value
+#endif
+>
+struct strictest_lock_impl
+{
+ typedef RightLockT type;
+};
+template< typename LeftLockT, typename RightLockT >
+struct strictest_lock_impl< LeftLockT, RightLockT, false >
+{
+ typedef LeftLockT type;
+};
+
+} // namespace aux
+
+#if defined(BOOST_LOG_DOXYGEN_PASS)
+
+/*!
+ * \brief The metafunction selects the most strict lock type of the specified.
+ *
+ * The template supports all lock types provided by the Boost.Thread
+ * library (except for \c upgrade_to_unique_lock), plus additional
+ * pseudo-lock \c no_lock that indicates no locking at all.
+ * Exclusive locks are considered the strictest, shared locks are weaker,
+ * and \c no_lock is the weakest.
+ */
+template< typename... LocksT >
+struct strictest_lock
+{
+ typedef implementation_defined type;
+};
+
+#else // defined(BOOST_LOG_DOXYGEN_PASS)
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+template< typename LockT, typename... LocksT >
+struct strictest_lock;
+
+template< typename LockT >
+struct strictest_lock< LockT >
+{
+ typedef LockT type;
+};
+
+template< typename LeftLockT, typename RightLockT >
+struct strictest_lock< LeftLockT, RightLockT >
+{
+ typedef typename aux::strictest_lock_impl< LeftLockT, RightLockT >::type type;
+};
+
+template< typename LeftLockT, typename RightLockT, typename... LocksT >
+struct strictest_lock< LeftLockT, RightLockT, LocksT... >
+{
+ typedef typename strictest_lock<
+ typename aux::strictest_lock_impl< LeftLockT, RightLockT >::type,
+ LocksT...
+ >::type type;
+};
+
+#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+# define BOOST_LOG_TYPE_INTERNAL(z, i, data) BOOST_PP_CAT(T, BOOST_PP_INC(i))
+
+template<
+ typename T,
+ BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PP_DEC(BOOST_LOG_STRICTEST_LOCK_LIMIT), typename T, void)
+>
+struct strictest_lock
+{
+ typedef typename strictest_lock<
+ typename boost::log::aux::strictest_lock_impl< T, T0 >::type
+ BOOST_PP_ENUM_TRAILING(BOOST_PP_SUB(BOOST_LOG_STRICTEST_LOCK_LIMIT, 2), BOOST_LOG_TYPE_INTERNAL, ~)
+ >::type type;
+};
+
+template< typename T >
+struct strictest_lock<
+ T
+ BOOST_PP_ENUM_TRAILING(BOOST_PP_DEC(BOOST_LOG_STRICTEST_LOCK_LIMIT), BOOST_LOG_PP_IDENTITY, void)
+>
+{
+ typedef T type;
+};
+
+# undef BOOST_LOG_TYPE_INTERNAL
+
+#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+#endif // defined(BOOST_LOG_DOXYGEN_PASS)
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_STRICTEST_LOCK_HPP_INCLUDED_
diff --git a/boost/log/utility/string_literal.hpp b/boost/log/utility/string_literal.hpp
new file mode 100644
index 0000000000..cb437fbc33
--- /dev/null
+++ b/boost/log/utility/string_literal.hpp
@@ -0,0 +1,617 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file string_literal.hpp
+ * \author Andrey Semashev
+ * \date 24.06.2007
+ *
+ * The header contains implementation of a constant string literal wrapper.
+ */
+
+#ifndef BOOST_LOG_UTILITY_STRING_LITERAL_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_STRING_LITERAL_HPP_INCLUDED_
+
+#include <cstddef>
+#include <stdexcept>
+#include <iosfwd>
+#include <ios> // std::streamsize
+#include <string>
+#include <iterator>
+#include <boost/operators.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/utility/string_literal_fwd.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * \brief String literal wrapper
+ *
+ * The \c basic_string_literal is a thin wrapper around a constant string literal.
+ * It provides interface similar to STL strings, but because of read-only nature
+ * of string literals, lacks ability to modify string contents. However,
+ * \c basic_string_literal objects can be assigned to and cleared.
+ *
+ * The main advantage of this class comparing to other string classes is that
+ * it doesn't dynamically allocate memory and therefore is fast, thin and exception safe.
+ */
+template< typename CharT, typename TraitsT >
+class basic_string_literal
+ //! \cond
+ : public totally_ordered1< basic_string_literal< CharT, TraitsT >,
+ totally_ordered2< basic_string_literal< CharT, TraitsT >, const CharT*,
+ totally_ordered2<
+ basic_string_literal< CharT, TraitsT >,
+ std::basic_string< CharT, TraitsT >
+ >
+ >
+ >
+ //! \endcond
+{
+ //! Self type
+ typedef basic_string_literal< CharT, TraitsT > this_type;
+
+public:
+ typedef CharT value_type;
+ typedef TraitsT traits_type;
+
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef const value_type* const_pointer;
+ typedef value_type const& const_reference;
+ typedef const value_type* const_iterator;
+ typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
+
+ //! Corresponding STL string type
+ typedef std::basic_string< value_type, traits_type > string_type;
+
+private:
+ //! Pointer to the beginning of the literal
+ const_pointer m_pStart;
+ //! Length
+ size_type m_Len;
+
+ //! Empty string literal to support clear
+ static const value_type g_EmptyString[1];
+
+public:
+ /*!
+ * Constructor
+ *
+ * \post <tt>empty() == true</tt>
+ */
+ basic_string_literal() BOOST_NOEXCEPT { clear(); }
+
+ /*!
+ * Constructor from a string literal
+ *
+ * \post <tt>*this == p</tt>
+ * \param p A zero-terminated constant sequence of characters
+ */
+ template< typename T, size_type LenV >
+ basic_string_literal(T(&p)[LenV]
+ //! \cond
+ , typename enable_if< is_same< T, const value_type >, int >::type = 0
+ //! \endcond
+ ) BOOST_NOEXCEPT
+ : m_pStart(p), m_Len(LenV - 1)
+ {
+ }
+
+ /*!
+ * Copy constructor
+ *
+ * \post <tt>*this == that</tt>
+ * \param that Source literal to copy string from
+ */
+ basic_string_literal(basic_string_literal const& that) BOOST_NOEXCEPT : m_pStart(that.m_pStart), m_Len(that.m_Len) {}
+
+ /*!
+ * Assignment operator
+ *
+ * \post <tt>*this == that</tt>
+ * \param that Source literal to copy string from
+ */
+ this_type& operator= (this_type const& that) BOOST_NOEXCEPT
+ {
+ return assign(that);
+ }
+ /*!
+ * Assignment from a string literal
+ *
+ * \post <tt>*this == p</tt>
+ * \param p A zero-terminated constant sequence of characters
+ */
+ template< typename T, size_type LenV >
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ typename enable_if<
+ is_same< T, const value_type >,
+ this_type&
+ >::type
+#else
+ this_type&
+#endif // BOOST_LOG_DOXYGEN_PASS
+ operator= (T(&p)[LenV]) BOOST_NOEXCEPT
+ {
+ return assign(p);
+ }
+
+ /*!
+ * Lexicographical comparison (equality)
+ *
+ * \param that Comparand
+ * \return \c true if the comparand string equals to this string, \c false otherwise
+ */
+ bool operator== (this_type const& that) const BOOST_NOEXCEPT
+ {
+ return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) == 0);
+ }
+ /*!
+ * Lexicographical comparison (equality)
+ *
+ * \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
+ * \return \c true if the comparand string equals to this string, \c false otherwise
+ */
+ bool operator== (const_pointer str) const BOOST_NOEXCEPT
+ {
+ return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) == 0);
+ }
+ /*!
+ * Lexicographical comparison (equality)
+ *
+ * \param that Comparand
+ * \return \c true if the comparand string equals to this string, \c false otherwise
+ */
+ bool operator== (string_type const& that) const
+ {
+ return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) == 0);
+ }
+
+ /*!
+ * Lexicographical comparison (less ordering)
+ *
+ * \param that Comparand
+ * \return \c true if this string is less than the comparand, \c false otherwise
+ */
+ bool operator< (this_type const& that) const BOOST_NOEXCEPT
+ {
+ return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) < 0);
+ }
+ /*!
+ * Lexicographical comparison (less ordering)
+ *
+ * \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
+ * \return \c true if this string is less than the comparand, \c false otherwise
+ */
+ bool operator< (const_pointer str) const BOOST_NOEXCEPT
+ {
+ return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) < 0);
+ }
+ /*!
+ * Lexicographical comparison (less ordering)
+ *
+ * \param that Comparand
+ * \return \c true if this string is less than the comparand, \c false otherwise
+ */
+ bool operator< (string_type const& that) const
+ {
+ return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) < 0);
+ }
+
+ /*!
+ * Lexicographical comparison (greater ordering)
+ *
+ * \param that Comparand
+ * \return \c true if this string is greater than the comparand, \c false otherwise
+ */
+ bool operator> (this_type const& that) const BOOST_NOEXCEPT
+ {
+ return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) > 0);
+ }
+ /*!
+ * Lexicographical comparison (greater ordering)
+ *
+ * \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
+ * \return \c true if this string is greater than the comparand, \c false otherwise
+ */
+ bool operator> (const_pointer str) const BOOST_NOEXCEPT
+ {
+ return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) > 0);
+ }
+ /*!
+ * Lexicographical comparison (greater ordering)
+ *
+ * \param that Comparand
+ * \return \c true if this string is greater than the comparand, \c false otherwise
+ */
+ bool operator> (string_type const& that) const
+ {
+ return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) > 0);
+ }
+
+ /*!
+ * Subscript operator
+ *
+ * \pre <tt>i < size()</tt>
+ * \param i Requested character index
+ * \return Constant reference to the requested character
+ */
+ const_reference operator[] (size_type i) const BOOST_NOEXCEPT
+ {
+ return m_pStart[i];
+ }
+ /*!
+ * Checked subscript
+ *
+ * \param i Requested character index
+ * \return Constant reference to the requested character
+ *
+ * \b Throws: An <tt>std::exception</tt>-based exception if index \a i is out of string boundaries
+ */
+ const_reference at(size_type i) const
+ {
+ if (i >= m_Len)
+ BOOST_THROW_EXCEPTION(std::out_of_range("basic_string_literal::at: the index value is out of range"));
+ return m_pStart[i];
+ }
+
+ /*!
+ * \return Pointer to the beginning of the literal
+ */
+ const_pointer c_str() const BOOST_NOEXCEPT { return m_pStart; }
+ /*!
+ * \return Pointer to the beginning of the literal
+ */
+ const_pointer data() const BOOST_NOEXCEPT { return m_pStart; }
+ /*!
+ * \return Length of the literal
+ */
+ size_type size() const BOOST_NOEXCEPT { return m_Len; }
+ /*!
+ * \return Length of the literal
+ */
+ size_type length() const BOOST_NOEXCEPT { return m_Len; }
+
+ /*!
+ * \return \c true if the literal is an empty string, \c false otherwise
+ */
+ bool empty() const BOOST_NOEXCEPT
+ {
+ return (m_Len == 0);
+ }
+
+ /*!
+ * \return Iterator that points to the first character of the literal
+ */
+ const_iterator begin() const BOOST_NOEXCEPT { return m_pStart; }
+ /*!
+ * \return Iterator that points after the last character of the literal
+ */
+ const_iterator end() const BOOST_NOEXCEPT { return m_pStart + m_Len; }
+ /*!
+ * \return Reverse iterator that points to the last character of the literal
+ */
+ const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); }
+ /*!
+ * \return Reverse iterator that points before the first character of the literal
+ */
+ const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); }
+
+ /*!
+ * \return STL string constructed from the literal
+ */
+ string_type str() const
+ {
+ return string_type(m_pStart, m_Len);
+ }
+
+ /*!
+ * The method clears the literal
+ *
+ * \post <tt>empty() == true</tt>
+ */
+ void clear() BOOST_NOEXCEPT
+ {
+ m_pStart = g_EmptyString;
+ m_Len = 0;
+ }
+ /*!
+ * The method swaps two literals
+ */
+ void swap(this_type& that) BOOST_NOEXCEPT
+ {
+ const_pointer p = m_pStart;
+ m_pStart = that.m_pStart;
+ that.m_pStart = p;
+
+ size_type l = m_Len;
+ m_Len = that.m_Len;
+ that.m_Len = l;
+ }
+
+ /*!
+ * Assignment from another literal
+ *
+ * \post <tt>*this == that</tt>
+ * \param that Source literal to copy string from
+ */
+ this_type& assign(this_type const& that) BOOST_NOEXCEPT
+ {
+ m_pStart = that.m_pStart;
+ m_Len = that.m_Len;
+ return *this;
+ }
+ /*!
+ * Assignment from another literal
+ *
+ * \post <tt>*this == p</tt>
+ * \param p A zero-terminated constant sequence of characters
+ */
+ template< typename T, size_type LenV >
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ typename enable_if<
+ is_same< T, const value_type >,
+ this_type&
+ >::type
+#else
+ this_type&
+#endif // BOOST_LOG_DOXYGEN_PASS
+ assign(T(&p)[LenV]) BOOST_NOEXCEPT
+ {
+ m_pStart = p;
+ m_Len = LenV - 1;
+ return *this;
+ }
+
+ /*!
+ * The method copies the literal or its portion to an external buffer
+ *
+ * \pre <tt>pos <= size()</tt>
+ * \param str Pointer to the external buffer beginning. Must not be NULL.
+ * The buffer must have enough capacity to accommodate the requested number of characters.
+ * \param n Maximum number of characters to copy
+ * \param pos Starting position to start copying from
+ * \return Number of characters copied
+ *
+ * \b Throws: An <tt>std::exception</tt>-based exception if \a pos is out of range.
+ */
+ size_type copy(value_type* str, size_type n, size_type pos = 0) const
+ {
+ if (pos > m_Len)
+ BOOST_THROW_EXCEPTION(std::out_of_range("basic_string_literal::copy: the position is out of range"));
+
+ size_type len = m_Len - pos;
+ if (len > n)
+ len = n;
+ traits_type::copy(str, m_pStart + pos, len);
+ return len;
+ }
+
+ /*!
+ * Lexicographically compares the argument string to a part of this string
+ *
+ * \pre <tt>pos <= size()</tt>
+ * \param pos Starting position within this string to perform comparison to
+ * \param n Length of the substring of this string to perform comparison to
+ * \param str Comparand. Must point to a sequence of characters, must not be NULL.
+ * \param len Number of characters in the sequence \a str.
+ * \return Zero if the comparand equals this string, a negative value if this string is less than the comparand,
+ * a positive value if this string is greater than the comparand.
+ *
+ * \b Throws: An <tt>std::exception</tt>-based exception if \a pos is out of range.
+ */
+ int compare(size_type pos, size_type n, const_pointer str, size_type len) const
+ {
+ if (pos > m_Len)
+ BOOST_THROW_EXCEPTION(std::out_of_range("basic_string_literal::compare: the position is out of range"));
+
+ size_type compare_size = m_Len - pos;
+ if (compare_size > len)
+ compare_size = len;
+ if (compare_size > n)
+ compare_size = n;
+ return compare_internal(m_pStart + pos, compare_size, str, compare_size);
+ }
+ /*!
+ * Lexicographically compares the argument string to a part of this string
+ *
+ * \pre <tt>pos <= size()</tt>
+ * \param pos Starting position within this string to perform comparison to
+ * \param n Length of the substring of this string to perform comparison to
+ * \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
+ * \return Zero if the comparand equals this string, a negative value if this string is less than the comparand,
+ * a positive value if this string is greater than the comparand.
+ *
+ * \b Throws: An <tt>std::exception</tt>-based exception if \a pos is out of range.
+ */
+ int compare(size_type pos, size_type n, const_pointer str) const BOOST_NOEXCEPT
+ {
+ return compare(pos, n, str, traits_type::length(str));
+ }
+ /*!
+ * Lexicographically compares the argument string literal to a part of this string
+ *
+ * \pre <tt>pos <= size()</tt>
+ * \param pos Starting position within this string to perform comparison to
+ * \param n Length of the substring of this string to perform comparison to
+ * \param that Comparand
+ * \return Zero if the comparand equals this string, a negative value if this string is less than the comparand,
+ * a positive value if this string is greater than the comparand.
+ *
+ * \b Throws: An <tt>std::exception</tt>-based exception if \a pos is out of range.
+ */
+ int compare(size_type pos, size_type n, this_type const& that) const BOOST_NOEXCEPT
+ {
+ return compare(pos, n, that.c_str(), that.size());
+ }
+ /*!
+ * Lexicographically compares the argument string to this string
+ *
+ * \param str Comparand. Must point to a sequence of characters, must not be NULL.
+ * \param len Number of characters in the sequence \a str.
+ * \return Zero if the comparand equals this string, a negative value if this string is less than the comparand,
+ * a positive value if this string is greater than the comparand.
+ */
+ int compare(const_pointer str, size_type len) const BOOST_NOEXCEPT
+ {
+ return compare(0, m_Len, str, len);
+ }
+ /*!
+ * Lexicographically compares the argument string to this string
+ *
+ * \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
+ * \return Zero if the comparand equals this string, a negative value if this string is less than the comparand,
+ * a positive value if this string is greater than the comparand.
+ */
+ int compare(const_pointer str) const BOOST_NOEXCEPT
+ {
+ return compare(0, m_Len, str, traits_type::length(str));
+ }
+ /*!
+ * Lexicographically compares the argument string to this string
+ *
+ * \param that Comparand
+ * \return Zero if the comparand equals this string, a negative value if this string is less than the comparand,
+ * a positive value if this string is greater than the comparand.
+ */
+ int compare(this_type const& that) const BOOST_NOEXCEPT
+ {
+ return compare(0, m_Len, that.c_str(), that.size());
+ }
+
+private:
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ //! Internal comparison implementation
+ static int compare_internal(const_pointer pLeft, size_type LeftLen, const_pointer pRight, size_type RightLen) BOOST_NOEXCEPT
+ {
+ if (pLeft != pRight)
+ {
+ const int result = traits_type::compare(pLeft, pRight, (LeftLen < RightLen ? LeftLen : RightLen));
+ if (result != 0)
+ return result;
+ }
+ return LeftLen < RightLen ? -1 : (LeftLen > RightLen ? 1 : 0);
+ }
+#endif // BOOST_LOG_DOXYGEN_PASS
+};
+
+template< typename CharT, typename TraitsT >
+typename basic_string_literal< CharT, TraitsT >::value_type const
+basic_string_literal< CharT, TraitsT >::g_EmptyString[1] = { 0 };
+
+namespace aux {
+
+template< typename CharT, typename TraitsT >
+inline void insert_fill_chars(std::basic_ostream< CharT, TraitsT >& strm, std::size_t n)
+{
+ enum { chunk_size = 8 };
+ CharT fill_chars[chunk_size];
+ const CharT filler = strm.fill();
+ for (unsigned int i = 0; i < chunk_size; ++i)
+ fill_chars[i] = filler;
+ for (; n >= chunk_size && strm.good(); n -= chunk_size)
+ strm.write(fill_chars, static_cast< std::size_t >(chunk_size));
+ if (n > 0 && strm.good())
+ strm.write(fill_chars, n);
+}
+
+template< typename CharT, typename TraitsT >
+void insert_aligned(std::basic_ostream< CharT, TraitsT >& strm, const CharT* p, std::size_t size)
+{
+ const std::size_t alignment_size = static_cast< std::size_t >(strm.width()) - size;
+ const bool align_left = (strm.flags() & std::basic_ostream< CharT, TraitsT >::adjustfield) == std::basic_ostream< CharT, TraitsT >::left;
+ if (align_left)
+ {
+ strm.write(p, size);
+ if (strm.good())
+ aux::insert_fill_chars(strm, alignment_size);
+ }
+ else
+ {
+ aux::insert_fill_chars(strm, alignment_size);
+ if (strm.good())
+ strm.write(p, size);
+ }
+}
+
+} // namespace aux
+
+//! Output operator
+template< typename CharT, typename StrmTraitsT, typename LitTraitsT >
+inline std::basic_ostream< CharT, StrmTraitsT >& operator<< (
+ std::basic_ostream< CharT, StrmTraitsT >& strm, basic_string_literal< CharT, LitTraitsT > const& lit)
+{
+ if (strm.good())
+ {
+ const std::size_t size = lit.size();
+ const std::size_t w = static_cast< std::size_t >(strm.width());
+ if (w <= size)
+ strm.write(lit.c_str(), static_cast< std::streamsize >(size));
+ else
+ aux::insert_aligned(strm, lit.c_str(), lit.size());
+ strm.width(0);
+ }
+ return strm;
+}
+
+//! External swap
+template< typename CharT, typename TraitsT >
+inline void swap(basic_string_literal< CharT, TraitsT >& left, basic_string_literal< CharT, TraitsT >& right) BOOST_NOEXCEPT
+{
+ left.swap(right);
+}
+
+//! Creates a string literal wrapper from a constant string literal
+#ifdef BOOST_LOG_USE_CHAR
+template< typename T, std::size_t LenV >
+inline
+#ifndef BOOST_LOG_DOXYGEN_PASS
+typename enable_if<
+ is_same< T, const char >,
+ string_literal
+>::type
+#else
+basic_string_literal< T >
+#endif // BOOST_LOG_DOXYGEN_PASS
+str_literal(T(&p)[LenV])
+{
+ return string_literal(p);
+}
+#endif
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+template< typename T, std::size_t LenV >
+inline typename enable_if<
+ is_same< T, const wchar_t >,
+ wstring_literal
+>::type
+str_literal(T(&p)[LenV])
+{
+ return wstring_literal(p);
+}
+#endif
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_STRING_LITERAL_HPP_INCLUDED_
diff --git a/boost/log/utility/string_literal_fwd.hpp b/boost/log/utility/string_literal_fwd.hpp
new file mode 100644
index 0000000000..69f48986f3
--- /dev/null
+++ b/boost/log/utility/string_literal_fwd.hpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file string_literal_fwd.hpp
+ * \author Andrey Semashev
+ * \date 24.06.2007
+ *
+ * The header contains forward declaration of a constant string literal wrapper.
+ */
+
+#ifndef BOOST_LOG_UTILITY_STRING_LITERAL_FWD_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_STRING_LITERAL_FWD_HPP_INCLUDED_
+
+#include <string>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * \brief String literal wrapper
+ *
+ * The \c basic_string_literal is a thin wrapper around a constant string literal.
+ * It provides interface similar to STL strings, but because of read-only nature
+ * of string literals, lacks ability to modify string contents. However,
+ * \c basic_string_literal objects can be assigned to and cleared.
+ *
+ * The main advantage of this class comparing to other string classes is that
+ * it doesn't dynamically allocate memory and therefore is fast, thin and exception safe.
+ */
+template< typename CharT, typename TraitsT = std::char_traits< CharT > >
+class basic_string_literal;
+
+// Convenience typedefs
+#ifdef BOOST_LOG_USE_CHAR
+typedef basic_string_literal< char > string_literal; //!< String literal type for narrow characters
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+typedef basic_string_literal< wchar_t > wstring_literal; //!< String literal type for wide characters
+#endif
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_UTILITY_STRING_LITERAL_FWD_HPP_INCLUDED_
diff --git a/boost/log/utility/type_dispatch/date_time_types.hpp b/boost/log/utility/type_dispatch/date_time_types.hpp
new file mode 100644
index 0000000000..5d91ab40c0
--- /dev/null
+++ b/boost/log/utility/type_dispatch/date_time_types.hpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file date_time_types.hpp
+ * \author Andrey Semashev
+ * \date 13.03.2008
+ *
+ * The header contains definition of date and time-related types supported by the library by default.
+ */
+
+#ifndef BOOST_LOG_DATE_TIME_TYPES_HPP_INCLUDED_
+#define BOOST_LOG_DATE_TIME_TYPES_HPP_INCLUDED_
+
+#include <ctime>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/mpl/push_back.hpp>
+#include <boost/date_time/gregorian/gregorian_types.hpp>
+#include <boost/date_time/local_time/local_time_types.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * An MPL-sequence of natively supported date and time types of attributes
+ */
+typedef mpl::vector<
+ std::time_t,
+ std::tm
+> native_date_time_types;
+
+/*!
+ * An MPL-sequence of Boost date and time types of attributes
+ */
+typedef mpl::vector<
+ posix_time::ptime,
+ local_time::local_date_time
+> boost_date_time_types;
+
+/*!
+ * An MPL-sequence with the complete list of the supported date and time types
+ */
+typedef mpl::copy<
+ boost_date_time_types,
+ mpl::back_inserter< native_date_time_types >
+>::type date_time_types;
+
+/*!
+ * An MPL-sequence of natively supported date types of attributes
+ */
+typedef native_date_time_types native_date_types;
+
+/*!
+ * An MPL-sequence of Boost date types of attributes
+ */
+typedef mpl::push_back<
+ boost_date_time_types,
+ gregorian::date
+>::type boost_date_types;
+
+/*!
+ * An MPL-sequence with the complete list of the supported date types
+ */
+typedef mpl::copy<
+ boost_date_types,
+ mpl::back_inserter< native_date_types >
+>::type date_types;
+
+/*!
+ * An MPL-sequence of natively supported time types
+ */
+typedef native_date_time_types native_time_types;
+
+//! An MPL-sequence of Boost time types
+typedef boost_date_time_types boost_time_types;
+
+/*!
+ * An MPL-sequence with the complete list of the supported time types
+ */
+typedef date_time_types time_types;
+
+/*!
+ * An MPL-sequence of natively supported time duration types of attributes
+ */
+typedef mpl::vector<
+ double // result of difftime
+> native_time_duration_types;
+
+/*!
+ * An MPL-sequence of Boost time duration types of attributes
+ */
+typedef mpl::vector<
+ posix_time::time_duration,
+ gregorian::date_duration
+> boost_time_duration_types;
+
+/*!
+ * An MPL-sequence with the complete list of the supported time duration types
+ */
+typedef mpl::copy<
+ boost_time_duration_types,
+ mpl::back_inserter< native_time_duration_types >
+>::type time_duration_types;
+
+/*!
+ * An MPL-sequence of Boost time duration types of attributes
+ */
+typedef mpl::vector<
+ posix_time::time_period,
+ local_time::local_time_period,
+ gregorian::date_period
+> boost_time_period_types;
+
+/*!
+ * An MPL-sequence with the complete list of the supported time period types
+ */
+typedef boost_time_period_types time_period_types;
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DATE_TIME_TYPES_HPP_INCLUDED_
diff --git a/boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp b/boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp
new file mode 100644
index 0000000000..8fa3c82d33
--- /dev/null
+++ b/boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file dynamic_type_dispatcher.hpp
+ * \author Andrey Semashev
+ * \date 15.04.2007
+ *
+ * The header contains implementation of the run-time type dispatcher.
+ */
+
+#ifndef BOOST_LOG_DYNAMIC_TYPE_DISPATCHER_HPP_INCLUDED_
+#define BOOST_LOG_DYNAMIC_TYPE_DISPATCHER_HPP_INCLUDED_
+
+#include <new>
+#include <memory>
+#include <map>
+#include <boost/ref.hpp>
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared_object.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/visible_type.hpp>
+#include <boost/log/utility/type_info_wrapper.hpp>
+#include <boost/log/utility/type_dispatch/type_dispatcher.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * \brief A dynamic type dispatcher
+ *
+ * The type dispatcher can be used to pass objects of arbitrary types from one
+ * component to another. With regard to the library, the type dispatcher
+ * can be used to extract attribute values.
+ *
+ * The dynamic type dispatcher can be initialized in run time and, therefore,
+ * can support different types, depending on runtime conditions. Each
+ * supported type is associated with a functional object that will be called
+ * when an object of the type is dispatched.
+ */
+class dynamic_type_dispatcher :
+ public type_dispatcher
+{
+private:
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ template< typename T, typename VisitorT >
+ class callback_impl :
+ public callback_base
+ {
+ private:
+ VisitorT m_Visitor;
+
+ public:
+ explicit callback_impl(VisitorT const& visitor) : m_Visitor(visitor)
+ {
+ this->m_pVisitor = (void*)boost::addressof(m_Visitor);
+ typedef void (*trampoline_t)(void*, T const&);
+ BOOST_STATIC_ASSERT_MSG(sizeof(trampoline_t) == sizeof(void*), "Boost.Log: Unsupported platform, the size of a function pointer differs from the size of a pointer");
+ union
+ {
+ void* as_pvoid;
+ trampoline_t as_trampoline;
+ }
+ caster;
+ caster.as_trampoline = &callback_base::trampoline< VisitorT, T >;
+ this->m_pTrampoline = caster.as_pvoid;
+ }
+ };
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+ //! The dispatching map
+ typedef std::map< type_info_wrapper, shared_ptr< callback_base > > dispatching_map;
+ dispatching_map m_DispatchingMap;
+
+public:
+ /*!
+ * Default constructor
+ */
+ dynamic_type_dispatcher() : type_dispatcher(&dynamic_type_dispatcher::get_callback)
+ {
+ }
+
+ /*!
+ * Copy constructor
+ */
+ dynamic_type_dispatcher(dynamic_type_dispatcher const& that) :
+ type_dispatcher(static_cast< type_dispatcher const& >(that)),
+ m_DispatchingMap(that.m_DispatchingMap)
+ {
+ }
+
+ /*!
+ * Copy assignment
+ */
+ dynamic_type_dispatcher& operator= (dynamic_type_dispatcher const& that)
+ {
+ m_DispatchingMap = that.m_DispatchingMap;
+ return *this;
+ }
+
+ /*!
+ * The method registers a new type
+ *
+ * \param visitor Function object that will be associated with the type \c T
+ */
+ template< typename T, typename VisitorT >
+ void register_type(VisitorT const& visitor)
+ {
+ boost::shared_ptr< callback_base > p(
+ boost::make_shared< callback_impl< T, VisitorT > >(boost::cref(visitor)));
+
+ type_info_wrapper wrapper(typeid(aux::visible_type< T >));
+ m_DispatchingMap[wrapper].swap(p);
+ }
+
+ /*!
+ * The method returns the number of registered types
+ */
+ dispatching_map::size_type registered_types_count() const
+ {
+ return m_DispatchingMap.size();
+ }
+
+private:
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ static callback_base get_callback(type_dispatcher* p, std::type_info const& type)
+ {
+ dynamic_type_dispatcher* const self = static_cast< dynamic_type_dispatcher* >(p);
+ type_info_wrapper wrapper(type);
+ dispatching_map::iterator it = self->m_DispatchingMap.find(wrapper);
+ if (it != self->m_DispatchingMap.end())
+ return *it->second;
+ else
+ return callback_base();
+ }
+#endif // BOOST_LOG_DOXYGEN_PASS
+};
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DYNAMIC_TYPE_DISPATCHER_HPP_INCLUDED_
diff --git a/boost/log/utility/type_dispatch/standard_types.hpp b/boost/log/utility/type_dispatch/standard_types.hpp
new file mode 100644
index 0000000000..0bf6a1db24
--- /dev/null
+++ b/boost/log/utility/type_dispatch/standard_types.hpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file standard_types.hpp
+ * \author Andrey Semashev
+ * \date 19.05.2007
+ *
+ * The header contains definition of standard types supported by the library by default.
+ */
+
+#ifndef BOOST_LOG_STANDARD_TYPES_HPP_INCLUDED_
+#define BOOST_LOG_STANDARD_TYPES_HPP_INCLUDED_
+
+#include <string>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/utility/string_literal_fwd.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * An MPL-sequence of integral types of attributes, supported by default
+ */
+typedef mpl::vector<
+ bool,
+ char,
+#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
+ wchar_t,
+#endif
+ signed char,
+ unsigned char,
+ short,
+ unsigned short,
+ int,
+ unsigned int,
+ long,
+ unsigned long
+#if defined(BOOST_HAS_LONG_LONG)
+ , long long
+ , unsigned long long
+#endif // defined(BOOST_HAS_LONG_LONG)
+> integral_types;
+
+/*!
+ * An MPL-sequence of FP types of attributes, supported by default
+ */
+typedef mpl::vector<
+ float,
+ double,
+ long double
+> floating_point_types;
+
+/*!
+ * An MPL-sequence of all numeric types of attributes, supported by default
+ */
+typedef mpl::copy<
+ floating_point_types,
+ mpl::back_inserter< integral_types >
+>::type numeric_types;
+
+/*!
+ * An MPL-sequence of string types of attributes, supported by default
+ */
+typedef mpl::vector<
+#ifdef BOOST_LOG_USE_CHAR
+ std::string,
+ string_literal
+#ifdef BOOST_LOG_USE_WCHAR_T
+ ,
+#endif
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+ std::wstring,
+ wstring_literal
+#endif
+> string_types;
+
+/*!
+ * An MPL-sequence of all attribute value types that are supported by the library by default.
+ */
+typedef mpl::copy<
+ string_types,
+ mpl::back_inserter< numeric_types >
+>::type default_attribute_types;
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_STANDARD_TYPES_HPP_INCLUDED_
diff --git a/boost/log/utility/type_dispatch/static_type_dispatcher.hpp b/boost/log/utility/type_dispatch/static_type_dispatcher.hpp
new file mode 100644
index 0000000000..73cf21b243
--- /dev/null
+++ b/boost/log/utility/type_dispatch/static_type_dispatcher.hpp
@@ -0,0 +1,319 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file static_type_dispatcher.hpp
+ * \author Andrey Semashev
+ * \date 15.04.2007
+ *
+ * The header contains implementation of a compile-time type dispatcher.
+ */
+
+#ifndef BOOST_LOG_STATIC_TYPE_DISPATCHER_HPP_INCLUDED_
+#define BOOST_LOG_STATIC_TYPE_DISPATCHER_HPP_INCLUDED_
+
+#include <cstddef>
+#include <utility>
+#include <iterator>
+#include <algorithm>
+#include <boost/array.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/begin.hpp>
+#include <boost/mpl/end.hpp>
+#include <boost/mpl/deref.hpp>
+#include <boost/mpl/next.hpp>
+#include <boost/mpl/is_sequence.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/visible_type.hpp>
+#include <boost/log/utility/once_block.hpp>
+#include <boost/log/utility/type_info_wrapper.hpp>
+#include <boost/log/utility/type_dispatch/type_dispatcher.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! Ordering predicate for type dispatching map
+struct dispatching_map_order
+{
+ typedef bool result_type;
+ typedef std::pair< type_info_wrapper, void* > first_argument_type, second_argument_type;
+ result_type operator() (first_argument_type const& left, second_argument_type const& right) const
+ {
+ return (left.first < right.first);
+ }
+};
+
+//! Dispatching map filler
+template< typename VisitorT >
+struct dispatching_map_initializer
+{
+ template< typename IteratorT >
+ static BOOST_FORCEINLINE void init(IteratorT*, IteratorT*, std::pair< type_info_wrapper, void* >*)
+ {
+ }
+
+ template< typename BeginIteratorT, typename EndIteratorT >
+ static BOOST_FORCEINLINE void init(BeginIteratorT*, EndIteratorT* end, std::pair< type_info_wrapper, void* >* p)
+ {
+ typedef typename mpl::deref< BeginIteratorT >::type type;
+ do_init(static_cast< visible_type< type >* >(0), p);
+
+ typedef typename mpl::next< BeginIteratorT >::type next_iterator_type;
+ init(static_cast< next_iterator_type* >(0), end, p + 1);
+ }
+
+private:
+ template< typename T >
+ static BOOST_FORCEINLINE void do_init(visible_type< T >*, std::pair< type_info_wrapper, void* >* p)
+ {
+ p->first = typeid(visible_type< T >);
+
+ typedef void (*trampoline_t)(void*, T const&);
+ BOOST_STATIC_ASSERT_MSG(sizeof(trampoline_t) == sizeof(void*), "Boost.Log: Unsupported platform, the size of a function pointer differs from the size of a pointer");
+ union
+ {
+ void* as_pvoid;
+ trampoline_t as_trampoline;
+ }
+ caster;
+ caster.as_trampoline = &type_dispatcher::callback_base::trampoline< VisitorT, T >;
+ p->second = caster.as_pvoid;
+ }
+};
+
+//! A base class for a dispatcher that supports a sequence of types
+class type_sequence_dispatcher_base :
+ public type_dispatcher
+{
+private:
+ //! Dispatching map element type
+ typedef std::pair< type_info_wrapper, void* > dispatching_map_element_type;
+
+private:
+ //! Dispatching map
+ const dispatching_map_element_type* m_dispatching_map_begin;
+ //! Dispatching map size
+ std::size_t m_dispatching_map_size;
+ //! Pointer to the receiver function
+ void* m_visitor;
+
+protected:
+ //! Initializing constructor
+ type_sequence_dispatcher_base(const dispatching_map_element_type* disp_map, std::size_t disp_map_size, void* visitor) BOOST_NOEXCEPT :
+ type_dispatcher(&type_sequence_dispatcher_base::get_callback),
+ m_dispatching_map_begin(disp_map),
+ m_dispatching_map_size(disp_map_size),
+ m_visitor(visitor)
+ {
+ }
+
+private:
+ //! The get_callback method implementation
+ static callback_base get_callback(type_dispatcher* p, std::type_info const& type)
+ {
+ type_sequence_dispatcher_base* const self = static_cast< type_sequence_dispatcher_base* >(p);
+ type_info_wrapper wrapper(type);
+ const dispatching_map_element_type* begin = self->m_dispatching_map_begin;
+ const dispatching_map_element_type* end = begin + self->m_dispatching_map_size;
+ const dispatching_map_element_type* it = std::lower_bound
+ (
+ begin,
+ end,
+ dispatching_map_element_type(wrapper, (void*)0),
+ dispatching_map_order()
+ );
+
+ if (it != end && it->first == wrapper)
+ return callback_base(self->m_visitor, it->second);
+ else
+ return callback_base();
+ }
+
+ // Copying and assignment closed
+ BOOST_DELETED_FUNCTION(type_sequence_dispatcher_base(type_sequence_dispatcher_base const&))
+ BOOST_DELETED_FUNCTION(type_sequence_dispatcher_base& operator= (type_sequence_dispatcher_base const&))
+};
+
+//! A dispatcher that supports a sequence of types
+template< typename TypeSequenceT >
+class type_sequence_dispatcher :
+ public type_sequence_dispatcher_base
+{
+public:
+ //! Type sequence of the supported types
+ typedef TypeSequenceT supported_types;
+
+private:
+ //! The dispatching map
+ typedef array<
+ std::pair< type_info_wrapper, void* >,
+ mpl::size< supported_types >::value
+ > dispatching_map;
+
+public:
+ /*!
+ * Constructor. Initializes the dispatcher internals.
+ */
+ template< typename VisitorT >
+ explicit type_sequence_dispatcher(VisitorT& visitor) :
+ type_sequence_dispatcher_base(get_dispatching_map< VisitorT >().data(), dispatching_map::static_size, (void*)boost::addressof(visitor))
+ {
+ }
+
+private:
+ //! The method returns the dispatching map instance
+ template< typename VisitorT >
+ static dispatching_map const& get_dispatching_map()
+ {
+ static const dispatching_map* pinstance = NULL;
+
+ BOOST_LOG_ONCE_BLOCK()
+ {
+ static dispatching_map instance;
+ typename dispatching_map::value_type* p = &*instance.begin();
+
+ typedef typename mpl::begin< supported_types >::type begin_iterator_type;
+ typedef typename mpl::end< supported_types >::type end_iterator_type;
+ typedef dispatching_map_initializer< VisitorT > initializer;
+ initializer::init(static_cast< begin_iterator_type* >(0), static_cast< end_iterator_type* >(0), p);
+
+ std::sort(instance.begin(), instance.end(), dispatching_map_order());
+
+ pinstance = &instance;
+ }
+
+ return *pinstance;
+ }
+
+ // Copying and assignment closed
+ BOOST_DELETED_FUNCTION(type_sequence_dispatcher(type_sequence_dispatcher const&))
+ BOOST_DELETED_FUNCTION(type_sequence_dispatcher& operator= (type_sequence_dispatcher const&))
+};
+
+//! A base class for a single-type dispatcher
+class single_type_dispatcher_base :
+ public type_dispatcher
+{
+private:
+ //! The type to match against
+ std::type_info const& m_type;
+ //! A callback for the supported type
+ callback_base m_callback;
+
+protected:
+ //! Initializing constructor
+ single_type_dispatcher_base(std::type_info const& type, callback_base const& callback) BOOST_NOEXCEPT :
+ type_dispatcher(&single_type_dispatcher_base::get_callback),
+ m_type(type),
+ m_callback(callback)
+ {
+ }
+
+private:
+ //! The get_callback method implementation
+ static callback_base get_callback(type_dispatcher* p, std::type_info const& type)
+ {
+ single_type_dispatcher_base* const self = static_cast< single_type_dispatcher_base* >(p);
+ if (type == self->m_type)
+ return self->m_callback;
+ else
+ return callback_base();
+ }
+
+ // Copying and assignment closed
+ BOOST_DELETED_FUNCTION(single_type_dispatcher_base(single_type_dispatcher_base const&))
+ BOOST_DELETED_FUNCTION(single_type_dispatcher_base& operator= (single_type_dispatcher_base const&))
+};
+
+//! A simple dispatcher that only supports one type
+template< typename T >
+class single_type_dispatcher :
+ public single_type_dispatcher_base
+{
+public:
+ //! Constructor
+ template< typename VisitorT >
+ explicit single_type_dispatcher(VisitorT& visitor) BOOST_NOEXCEPT :
+ single_type_dispatcher_base(typeid(visible_type< T >), callback_base((void*)boost::addressof(visitor), &callback_base::trampoline< VisitorT, T >))
+ {
+ }
+
+ // Copying and assignment closed
+ BOOST_DELETED_FUNCTION(single_type_dispatcher(single_type_dispatcher const&))
+ BOOST_DELETED_FUNCTION(single_type_dispatcher& operator= (single_type_dispatcher const&))
+};
+
+} // namespace aux
+
+/*!
+ * \brief A static type dispatcher class
+ *
+ * The type dispatcher can be used to pass objects of arbitrary types from one
+ * component to another. With regard to the library, the type dispatcher
+ * can be used to extract attribute values.
+ *
+ * Static type dispatchers allow to specify one or several supported types at compile
+ * time.
+ */
+template< typename T >
+class static_type_dispatcher
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ :
+ public mpl::if_<
+ mpl::is_sequence< T >,
+ boost::log::aux::type_sequence_dispatcher< T >,
+ boost::log::aux::single_type_dispatcher< T >
+ >::type
+#endif
+{
+private:
+ //! Base type
+ typedef typename mpl::if_<
+ mpl::is_sequence< T >,
+ boost::log::aux::type_sequence_dispatcher< T >,
+ boost::log::aux::single_type_dispatcher< T >
+ >::type base_type;
+
+public:
+ /*!
+ * Constructor. Initializes the dispatcher internals.
+ *
+ * The \a receiver object is not copied inside the dispatcher, but references to
+ * it may be kept by the dispatcher after construction. The receiver object must remain
+ * valid until the dispatcher is destroyed.
+ *
+ * \param receiver Unary function object that will be called on a dispatched value. The receiver
+ * must be callable with an argument of any of the supported types of the dispatcher.
+ */
+ template< typename ReceiverT >
+ explicit static_type_dispatcher(ReceiverT& receiver) :
+ base_type(receiver)
+ {
+ }
+
+ // Copying and assignment prohibited
+ BOOST_DELETED_FUNCTION(static_type_dispatcher(static_type_dispatcher const&))
+ BOOST_DELETED_FUNCTION(static_type_dispatcher& operator= (static_type_dispatcher const&))
+};
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_STATIC_TYPE_DISPATCHER_HPP_INCLUDED_
diff --git a/boost/log/utility/type_dispatch/type_dispatcher.hpp b/boost/log/utility/type_dispatch/type_dispatcher.hpp
new file mode 100644
index 0000000000..36e1ce8b05
--- /dev/null
+++ b/boost/log/utility/type_dispatch/type_dispatcher.hpp
@@ -0,0 +1,189 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file type_dispatcher.hpp
+ * \author Andrey Semashev
+ * \date 15.04.2007
+ *
+ * The header contains definition of generic type dispatcher interfaces.
+ */
+
+#ifndef BOOST_LOG_TYPE_DISPATCHER_HPP_INCLUDED_
+#define BOOST_LOG_TYPE_DISPATCHER_HPP_INCLUDED_
+
+#include <typeinfo>
+#include <boost/static_assert.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/visible_type.hpp>
+#include <boost/utility/explicit_operator_bool.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * \brief A type dispatcher interface
+ *
+ * All type dispatchers support this interface. It is used to acquire the
+ * visitor interface for the requested type.
+ */
+class type_dispatcher
+{
+public:
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+ //! The base class for type dispatcher callbacks
+ class callback_base
+ {
+ protected:
+ void* m_pVisitor;
+ void* m_pTrampoline;
+
+ public:
+ explicit callback_base(void* visitor = 0, void* tramp = 0) BOOST_NOEXCEPT :
+ m_pVisitor(visitor),
+ m_pTrampoline(tramp)
+ {
+ }
+ template< typename ValueT >
+ explicit callback_base(void* visitor, void (*tramp)(void*, ValueT const&)) BOOST_NOEXCEPT :
+ m_pVisitor(visitor)
+ {
+ typedef void (*trampoline_t)(void*, ValueT const&);
+ BOOST_STATIC_ASSERT_MSG(sizeof(trampoline_t) == sizeof(void*), "Boost.Log: Unsupported platform, the size of a function pointer differs from the size of a pointer");
+ union
+ {
+ void* as_pvoid;
+ trampoline_t as_trampoline;
+ }
+ caster;
+ caster.as_trampoline = tramp;
+ m_pTrampoline = caster.as_pvoid;
+ }
+
+ template< typename VisitorT, typename T >
+ static void trampoline(void* visitor, T const& value)
+ {
+ (*static_cast< VisitorT* >(visitor))(value);
+ }
+ };
+
+ //! An interface to the callback for the concrete type visitor
+ template< typename T >
+ class callback :
+ private callback_base
+ {
+ private:
+ //! Type of the trampoline method
+ typedef void (*trampoline_t)(void*, T const&);
+
+ public:
+ //! The type, which the visitor is able to consume
+ typedef T supported_type;
+
+ public:
+ callback() BOOST_NOEXCEPT : callback_base()
+ {
+ }
+ explicit callback(callback_base const& base) BOOST_NOEXCEPT : callback_base(base)
+ {
+ }
+
+ void operator() (T const& value) const
+ {
+ BOOST_STATIC_ASSERT_MSG(sizeof(trampoline_t) == sizeof(void*), "Boost.Log: Unsupported platform, the size of a function pointer differs from the size of a pointer");
+ union
+ {
+ void* as_pvoid;
+ trampoline_t as_trampoline;
+ }
+ caster;
+ caster.as_pvoid = this->m_pTrampoline;
+ (caster.as_trampoline)(this->m_pVisitor, value);
+ }
+
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+
+ bool operator! () const BOOST_NOEXCEPT { return (this->m_pVisitor == 0); }
+ };
+
+#else // BOOST_LOG_DOXYGEN_PASS
+
+ /*!
+ * This interface is used by type dispatchers to consume the dispatched value.
+ */
+ template< typename T >
+ class callback
+ {
+ public:
+ /*!
+ * The operator invokes the visitor-specific logic with the given value
+ *
+ * \param value The dispatched value
+ */
+ void operator() (T const& value) const;
+
+ /*!
+ * The operator checks if the visitor is attached to a receiver
+ */
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+
+ /*!
+ * The operator checks if the visitor is not attached to a receiver
+ */
+ bool operator! () const BOOST_NOEXCEPT;
+ };
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+protected:
+ //! Pointer to the callback acquisition method
+ typedef callback_base (*get_callback_impl_type)(type_dispatcher*, std::type_info const&);
+
+private:
+ //! Pointer to the callback acquisition method
+ get_callback_impl_type m_get_callback_impl;
+
+protected:
+ /*!
+ * Initializing constructor
+ */
+ explicit type_dispatcher(get_callback_impl_type get_callback_impl) BOOST_NOEXCEPT : m_get_callback_impl(get_callback_impl)
+ {
+ }
+
+ // Destructor and copying can only be called from the derived classes
+ BOOST_DEFAULTED_FUNCTION(~type_dispatcher(), {})
+ BOOST_DEFAULTED_FUNCTION(type_dispatcher(type_dispatcher const& that), : m_get_callback_impl(that.m_get_callback_impl) {})
+ BOOST_DEFAULTED_FUNCTION(type_dispatcher& operator= (type_dispatcher const& that), { m_get_callback_impl = that.m_get_callback_impl; return *this; })
+
+public:
+ /*!
+ * The method requests a callback for the value of type \c T
+ *
+ * \return The type-specific callback or an empty value, if the type is not supported
+ */
+ template< typename T >
+ callback< T > get_callback()
+ {
+ return callback< T >((this->m_get_callback_impl)(this, typeid(boost::log::aux::visible_type< T >)));
+ }
+};
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_TYPE_DISPATCHER_HPP_INCLUDED_
diff --git a/boost/log/utility/type_info_wrapper.hpp b/boost/log/utility/type_info_wrapper.hpp
new file mode 100644
index 0000000000..8ce4ea2414
--- /dev/null
+++ b/boost/log/utility/type_info_wrapper.hpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file type_info_wrapper.hpp
+ * \author Andrey Semashev
+ * \date 15.04.2007
+ *
+ * The header contains implementation of a type information wrapper.
+ */
+
+#ifndef BOOST_LOG_UTILITY_TYPE_INFO_WRAPPER_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_TYPE_INFO_WRAPPER_HPP_INCLUDED_
+
+#include <typeinfo>
+#include <string>
+#include <boost/core/demangle.hpp>
+#include <boost/core/explicit_operator_bool.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * \brief A simple <tt>std::type_info</tt> wrapper that implements value semantic for type information objects
+ *
+ * The type info wrapper is very useful for storing type information objects in containers,
+ * as a key or value. It also provides a number of useful features, such as default construction
+ * and assignment support, an empty state and extended support for human-friendly type names.
+ */
+class type_info_wrapper
+{
+private:
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ //! An inaccessible type to indicate an uninitialized state of the wrapper
+ struct BOOST_SYMBOL_VISIBLE uninitialized {};
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+private:
+ //! A pointer to the actual type info
+ std::type_info const* info;
+
+public:
+ /*!
+ * Default constructor
+ *
+ * \post <tt>!*this == true</tt>
+ */
+ type_info_wrapper() BOOST_NOEXCEPT : info(&typeid(uninitialized)) {}
+ /*!
+ * Copy constructor
+ *
+ * \post <tt>*this == that</tt>
+ * \param that Source type info wrapper to copy from
+ */
+ type_info_wrapper(type_info_wrapper const& that) BOOST_NOEXCEPT : info(that.info) {}
+ /*!
+ * Conversion constructor
+ *
+ * \post <tt>*this == that && !!*this</tt>
+ * \param that Type info object to be wrapped
+ */
+ type_info_wrapper(std::type_info const& that) BOOST_NOEXCEPT : info(&that) {}
+
+ /*!
+ * \return \c true if the type info wrapper was initialized with a particular type,
+ * \c false if the wrapper was default-constructed and not yet initialized
+ */
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+
+ /*!
+ * Stored type info getter
+ *
+ * \pre <tt>!!*this</tt>
+ * \return Constant reference to the wrapped type info object
+ */
+ std::type_info const& get() const BOOST_NOEXCEPT { return *info; }
+
+ /*!
+ * Swaps two instances of the wrapper
+ */
+ void swap(type_info_wrapper& that) BOOST_NOEXCEPT
+ {
+ std::type_info const* temp = info;
+ info = that.info;
+ that.info = temp;
+ }
+
+ /*!
+ * The method returns the contained type name string in a possibly more readable format than <tt>get().name()</tt>
+ *
+ * \pre <tt>!!*this</tt>
+ * \return Type name string
+ */
+ std::string pretty_name() const
+ {
+ if (!this->operator!())
+ return boost::core::demangle(info->name());
+ else
+ return "[uninitialized]";
+ }
+
+ /*!
+ * \return \c false if the type info wrapper was initialized with a particular type,
+ * \c true if the wrapper was default-constructed and not yet initialized
+ */
+ bool operator! () const BOOST_NOEXCEPT { return (info == &typeid(uninitialized) || *info == typeid(uninitialized)); }
+
+ /*!
+ * Equality comparison
+ *
+ * \param that Comparand
+ * \return If either this object or comparand is in empty state and the other is not, the result is \c false.
+ * If both arguments are empty, the result is \c true. If both arguments are not empty, the result
+ * is \c true if this object wraps the same type as the comparand and \c false otherwise.
+ */
+ bool operator== (type_info_wrapper const& that) const BOOST_NOEXCEPT
+ {
+ return (info == that.info || *info == *that.info);
+ }
+ /*!
+ * Ordering operator
+ *
+ * \pre <tt>!!*this && !!that</tt>
+ * \param that Comparand
+ * \return \c true if this object wraps type info object that is ordered before
+ * the type info object in the comparand, \c false otherwise
+ * \note The results of this operator are only consistent within a single run of application.
+ * The result may change for the same types after rebuilding or even restarting the application.
+ */
+ bool operator< (type_info_wrapper const& that) const BOOST_NOEXCEPT
+ {
+ return static_cast< bool >(info->before(*that.info));
+ }
+};
+
+//! Inequality operator
+inline bool operator!= (type_info_wrapper const& left, type_info_wrapper const& right) BOOST_NOEXCEPT
+{
+ return !left.operator==(right);
+}
+
+//! Ordering operator
+inline bool operator<= (type_info_wrapper const& left, type_info_wrapper const& right) BOOST_NOEXCEPT
+{
+ return (left.operator==(right) || left.operator<(right));
+}
+
+//! Ordering operator
+inline bool operator> (type_info_wrapper const& left, type_info_wrapper const& right) BOOST_NOEXCEPT
+{
+ return !(left.operator==(right) || left.operator<(right));
+}
+
+//! Ordering operator
+inline bool operator>= (type_info_wrapper const& left, type_info_wrapper const& right) BOOST_NOEXCEPT
+{
+ return !left.operator<(right);
+}
+
+//! Free swap for type info wrapper
+inline void swap(type_info_wrapper& left, type_info_wrapper& right) BOOST_NOEXCEPT
+{
+ left.swap(right);
+}
+
+//! The function for exception serialization to string
+inline std::string to_string(type_info_wrapper const& ti)
+{
+ return ti.pretty_name();
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_TYPE_INFO_WRAPPER_HPP_INCLUDED_
diff --git a/boost/log/utility/unique_identifier_name.hpp b/boost/log/utility/unique_identifier_name.hpp
new file mode 100644
index 0000000000..ad25296e55
--- /dev/null
+++ b/boost/log/utility/unique_identifier_name.hpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file unique_identifier_name.hpp
+ * \author Andrey Semashev
+ * \date 30.04.2008
+ *
+ * The header contains \c BOOST_LOG_UNIQUE_IDENTIFIER_NAME macro definition.
+ */
+
+#ifndef BOOST_LOG_UTILITY_UNIQUE_IDENTIFIER_NAME_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_UNIQUE_IDENTIFIER_NAME_HPP_INCLUDED_
+
+#include <boost/preprocessor/cat.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#define BOOST_LOG_UNIQUE_IDENTIFIER_NAME_INTERNAL_(prefix, postfix)\
+ BOOST_PP_CAT(prefix, postfix)
+#define BOOST_LOG_UNIQUE_IDENTIFIER_NAME_INTERNAL(prefix, postfix)\
+ BOOST_LOG_UNIQUE_IDENTIFIER_NAME_INTERNAL_(prefix, postfix)
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * \def BOOST_LOG_UNIQUE_IDENTIFIER_NAME(prefix)
+ *
+ * Constructs a unique (in the current file scope) token that can be used as a variable name.
+ * The name will contain a prefix passed in the \a prefix argument. This allows to use the
+ * macro multiple times on a single line.
+ */
+
+// In VC 7.0 and later when compiling with /ZI option __LINE__ macro is corrupted
+#ifdef BOOST_MSVC
+# define BOOST_LOG_UNIQUE_IDENTIFIER_NAME(prefix)\
+ BOOST_LOG_UNIQUE_IDENTIFIER_NAME_INTERNAL(prefix, __COUNTER__)
+#else
+# define BOOST_LOG_UNIQUE_IDENTIFIER_NAME(prefix)\
+ BOOST_LOG_UNIQUE_IDENTIFIER_NAME_INTERNAL(prefix, __LINE__)
+#endif // BOOST_MSVC
+
+#endif // BOOST_LOG_UTILITY_UNIQUE_IDENTIFIER_NAME_HPP_INCLUDED_
diff --git a/boost/log/utility/unused_variable.hpp b/boost/log/utility/unused_variable.hpp
new file mode 100644
index 0000000000..816e102533
--- /dev/null
+++ b/boost/log/utility/unused_variable.hpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file unused_variable.hpp
+ * \author Andrey Semashev
+ * \date 10.05.2008
+ *
+ * The header contains definition of a macro to suppress compiler warnings about unused variables.
+ */
+
+#ifndef BOOST_LOG_UTILITY_UNUSED_VARIABLE_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_UNUSED_VARIABLE_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(__GNUC__)
+
+//! The macro suppresses compiler warnings for \c var being unused
+#define BOOST_LOG_UNUSED_VARIABLE(type, var, initializer) __attribute__((unused)) type var initializer
+
+#else
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+template< typename T >
+BOOST_FORCEINLINE void no_unused_warnings(T const&) BOOST_NOEXCEPT {}
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+//! The macro suppresses compiler warnings for \c var being unused
+#define BOOST_LOG_UNUSED_VARIABLE(type, var, initializer) type var initializer; ::boost::log::aux::no_unused_warnings(var)
+
+#endif
+
+#endif // BOOST_LOG_UTILITY_UNUSED_VARIABLE_HPP_INCLUDED_
diff --git a/boost/log/utility/value_ref.hpp b/boost/log/utility/value_ref.hpp
new file mode 100644
index 0000000000..08fda4c553
--- /dev/null
+++ b/boost/log/utility/value_ref.hpp
@@ -0,0 +1,630 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file value_ref.hpp
+ * \author Andrey Semashev
+ * \date 27.07.2012
+ *
+ * The header contains implementation of a value reference wrapper.
+ */
+
+#ifndef BOOST_LOG_UTILITY_VALUE_REF_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_VALUE_REF_HPP_INCLUDED_
+
+#include <cstddef>
+#include <iosfwd>
+#include <boost/assert.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/is_sequence.hpp>
+#include <boost/mpl/front.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/contains.hpp>
+#include <boost/mpl/index_of.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/optional/optional_fwd.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/is_void.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/parameter_tools.hpp>
+#include <boost/log/detail/value_ref_visitation.hpp>
+#include <boost/utility/explicit_operator_bool.hpp>
+#include <boost/log/utility/formatting_ostream_fwd.hpp>
+#include <boost/log/utility/functional/logical.hpp>
+#include <boost/log/utility/functional/bind.hpp>
+#include <boost/log/utility/functional/bind_output.hpp>
+#include <boost/log/utility/functional/bind_to_log.hpp>
+#include <boost/log/utility/manipulators/to_log.hpp>
+#include <boost/log/utility/value_ref_fwd.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! The function object applies the function object to the bound visitable object and argument
+template< typename VisitableT, typename FunT >
+struct vistation_invoker
+{
+ typedef typename FunT::result_type result_type;
+
+ vistation_invoker(VisitableT& visitable, result_type const& def_val) : m_visitable(visitable), m_def_val(def_val)
+ {
+ }
+
+ template< typename ArgT >
+ result_type operator() (ArgT const& arg) const
+ {
+ return m_visitable.apply_visitor_or_default(binder1st< FunT, ArgT const& >(FunT(), arg), m_def_val);
+ }
+
+private:
+ VisitableT& m_visitable;
+ result_type m_def_val;
+};
+
+//! Attribute value reference implementation for a single type case
+template< typename T, typename TagT >
+class singular_ref
+{
+public:
+ //! Referenced value type
+ typedef T value_type;
+ //! Tag type
+ typedef TagT tag_type;
+
+protected:
+ //! The metafunction tests if the type is compatible with the reference wrapper
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ template< typename U >
+ using is_compatible = is_same< U, value_type >;
+#else
+ template< typename U >
+ struct is_compatible :
+ public is_same< U, value_type >
+ {
+ };
+#endif
+
+protected:
+ //! Pointer to the value
+ const value_type* m_ptr;
+
+protected:
+ //! Default constructor
+ singular_ref() BOOST_NOEXCEPT : m_ptr(NULL)
+ {
+ }
+
+ //! Initializing constructor
+ explicit singular_ref(const value_type* p) BOOST_NOEXCEPT : m_ptr(p)
+ {
+ }
+
+public:
+ //! Returns a pointer to the referred value
+ const value_type* operator-> () const BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT(m_ptr != NULL);
+ return m_ptr;
+ }
+
+ //! Returns a pointer to the referred value
+ const value_type* get_ptr() const BOOST_NOEXCEPT
+ {
+ return m_ptr;
+ }
+
+ //! Returns a pointer to the referred value
+ template< typename U >
+ typename enable_if< is_compatible< U >, const U* >::type get_ptr() const BOOST_NOEXCEPT
+ {
+ return m_ptr;
+ }
+
+ //! Returns a reference to the value
+ value_type const& operator* () const BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT(m_ptr != NULL);
+ return *m_ptr;
+ }
+
+ //! Returns a reference to the value
+ value_type const& get() const BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT(m_ptr != NULL);
+ return *m_ptr;
+ }
+
+ //! Returns a reference to the value
+ template< typename U >
+ typename enable_if< is_compatible< U >, U const& >::type get() const BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT(m_ptr != NULL);
+ return *m_ptr;
+ }
+
+
+ //! Resets the reference
+ void reset() BOOST_NOEXCEPT
+ {
+ m_ptr = NULL;
+ }
+
+ //! Returns the stored type index
+ static BOOST_CONSTEXPR unsigned int which()
+ {
+ return 0u;
+ }
+
+ //! Swaps two reference wrappers
+ void swap(singular_ref& that) BOOST_NOEXCEPT
+ {
+ const void* p = m_ptr;
+ m_ptr = that.m_ptr;
+ that.m_ptr = p;
+ }
+
+ //! Applies a visitor function object to the referred value
+ template< typename VisitorT >
+ typename VisitorT::result_type apply_visitor(VisitorT visitor) const
+ {
+ BOOST_ASSERT(m_ptr != NULL);
+ return visitor(*m_ptr);
+ }
+
+ //! Applies a visitor function object to the referred value
+ template< typename VisitorT >
+ typename enable_if< is_void< typename VisitorT::result_type >, bool >::type apply_visitor_optional(VisitorT visitor) const
+ {
+ if (m_ptr)
+ {
+ visitor(*m_ptr);
+ return true;
+ }
+ else
+ return false;
+ }
+
+ //! Applies a visitor function object to the referred value
+ template< typename VisitorT >
+ typename disable_if< is_void< typename VisitorT::result_type >, optional< typename VisitorT::result_type > >::type apply_visitor_optional(VisitorT visitor) const
+ {
+ typedef optional< typename VisitorT::result_type > result_type;
+ if (m_ptr)
+ return result_type(visitor(*m_ptr));
+ else
+ return result_type();
+ }
+
+ //! Applies a visitor function object to the referred value or returns a default value
+ template< typename VisitorT, typename DefaultT >
+ typename VisitorT::result_type apply_visitor_or_default(VisitorT visitor, DefaultT& def_val) const
+ {
+ if (m_ptr)
+ return visitor(*m_ptr);
+ else
+ return def_val;
+ }
+
+ //! Applies a visitor function object to the referred value or returns a default value
+ template< typename VisitorT, typename DefaultT >
+ typename VisitorT::result_type apply_visitor_or_default(VisitorT visitor, DefaultT const& def_val) const
+ {
+ if (m_ptr)
+ return visitor(*m_ptr);
+ else
+ return def_val;
+ }
+};
+
+//! Attribute value reference implementation for multiple types case
+template< typename T, typename TagT >
+class variant_ref
+{
+public:
+ //! Referenced value type
+ typedef T value_type;
+ //! Tag type
+ typedef TagT tag_type;
+
+protected:
+ //! The metafunction tests if the type is compatible with the reference wrapper
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ template< typename U >
+ using is_compatible = mpl::contains< value_type, U >;
+#else
+ template< typename U >
+ struct is_compatible :
+ public mpl::contains< value_type, U >
+ {
+ };
+#endif
+
+protected:
+ //! Pointer to the value
+ const void* m_ptr;
+ //! Type index
+ unsigned int m_type_idx;
+
+protected:
+ //! Default constructor
+ variant_ref() BOOST_NOEXCEPT : m_ptr(NULL), m_type_idx(0)
+ {
+ }
+
+ //! Initializing constructor
+ template< typename U >
+ explicit variant_ref(const U* p) BOOST_NOEXCEPT : m_ptr(p), m_type_idx(mpl::index_of< value_type, U >::type::value)
+ {
+ }
+
+public:
+ //! Resets the reference
+ void reset() BOOST_NOEXCEPT
+ {
+ m_ptr = NULL;
+ m_type_idx = 0;
+ }
+
+ //! Returns a pointer to the referred value
+ template< typename U >
+ typename enable_if< is_compatible< U >, const U* >::type get_ptr() const BOOST_NOEXCEPT
+ {
+ if (m_type_idx == static_cast< unsigned int >(mpl::index_of< value_type, U >::type::value))
+ return static_cast< const U* >(m_ptr);
+ else
+ return NULL;
+ }
+
+ //! Returns a reference to the value
+ template< typename U >
+ typename enable_if< is_compatible< U >, U const& >::type get() const BOOST_NOEXCEPT
+ {
+ const U* const p = get_ptr< U >();
+ BOOST_ASSERT(p != NULL);
+ return *p;
+ }
+
+ //! Returns the stored type index
+ unsigned int which() const BOOST_NOEXCEPT
+ {
+ return m_type_idx;
+ }
+
+ //! Swaps two reference wrappers
+ void swap(variant_ref& that) BOOST_NOEXCEPT
+ {
+ const void* p = m_ptr;
+ m_ptr = that.m_ptr;
+ that.m_ptr = p;
+ unsigned int type_idx = m_type_idx;
+ m_type_idx = that.m_type_idx;
+ that.m_type_idx = type_idx;
+ }
+
+ //! Applies a visitor function object to the referred value
+ template< typename VisitorT >
+ typename VisitorT::result_type apply_visitor(VisitorT visitor) const
+ {
+ BOOST_ASSERT(m_ptr != NULL);
+ return do_apply_visitor(visitor);
+ }
+
+ //! Applies a visitor function object to the referred value
+ template< typename VisitorT >
+ typename enable_if< is_void< typename VisitorT::result_type >, bool >::type apply_visitor_optional(VisitorT visitor) const
+ {
+ if (m_ptr)
+ {
+ do_apply_visitor(visitor);
+ return true;
+ }
+ else
+ return false;
+ }
+
+ //! Applies a visitor function object to the referred value
+ template< typename VisitorT >
+ typename disable_if< is_void< typename VisitorT::result_type >, optional< typename VisitorT::result_type > >::type apply_visitor_optional(VisitorT visitor) const
+ {
+ typedef optional< typename VisitorT::result_type > result_type;
+ if (m_ptr)
+ return result_type(do_apply_visitor(visitor));
+ else
+ return result_type();
+ }
+
+ //! Applies a visitor function object to the referred value or returns a default value
+ template< typename VisitorT, typename DefaultT >
+ typename VisitorT::result_type apply_visitor_or_default(VisitorT visitor, DefaultT& def_val) const
+ {
+ if (m_ptr)
+ return do_apply_visitor(visitor);
+ else
+ return def_val;
+ }
+
+ //! Applies a visitor function object to the referred value or returns a default value
+ template< typename VisitorT, typename DefaultT >
+ typename VisitorT::result_type apply_visitor_or_default(VisitorT visitor, DefaultT const& def_val) const
+ {
+ if (m_ptr)
+ return do_apply_visitor(visitor);
+ else
+ return def_val;
+ }
+
+private:
+ template< typename VisitorT >
+ typename VisitorT::result_type do_apply_visitor(VisitorT& visitor) const
+ {
+ BOOST_ASSERT(m_type_idx < static_cast< unsigned int >(mpl::size< value_type >::value));
+ return apply_visitor_dispatch< value_type, VisitorT >::call(m_ptr, m_type_idx, visitor);
+ }
+};
+
+template< typename T, typename TagT >
+struct value_ref_base
+{
+ typedef typename mpl::eval_if<
+ mpl::and_< mpl::is_sequence< T >, mpl::equal_to< mpl::size< T >, mpl::int_< 1 > > >,
+ mpl::front< T >,
+ mpl::identity< T >
+ >::type value_type;
+
+ typedef typename mpl::if_<
+ mpl::is_sequence< value_type >,
+ variant_ref< value_type, TagT >,
+ singular_ref< value_type, TagT >
+ >::type type;
+};
+
+} // namespace aux
+
+/*!
+ * \brief Reference wrapper for a stored attribute value.
+ *
+ * The \c value_ref class template provides access to the stored attribute value. It is not a traditional reference wrapper
+ * since it may be empty (i.e. refer to no value at all) and it can also refer to values of different types. Therefore its
+ * interface and behavior combines features of Boost.Ref, Boost.Optional and Boost.Variant, depending on the use case.
+ *
+ * The template parameter \c T can be a single type or an MPL sequence of possible types being referred. The reference wrapper
+ * will act as either an optional reference or an optional variant of references to the specified types. In any case, the
+ * referred values will not be modifiable (i.e. \c value_ref always models a const reference).
+ *
+ * Template parameter \c TagT is optional. It can be used for customizing the operations on this reference wrapper, such as
+ * putting the referred value to log.
+ */
+template< typename T, typename TagT >
+class value_ref :
+ public aux::value_ref_base< T, TagT >::type
+{
+#ifndef BOOST_LOG_DOXYGEN_PASS
+public:
+ typedef void _has_basic_formatting_ostream_insert_operator;
+#endif
+
+private:
+ //! Base implementation type
+ typedef typename aux::value_ref_base< T, TagT >::type base_type;
+
+public:
+ /*!
+ * Default constructor. Creates a reference wrapper that does not refer to a value.
+ */
+ BOOST_DEFAULTED_FUNCTION(value_ref(), BOOST_NOEXCEPT {})
+
+ /*!
+ * Copy constructor.
+ */
+ BOOST_DEFAULTED_FUNCTION(value_ref(value_ref const& that), BOOST_NOEXCEPT : base_type(static_cast< base_type const& >(that)) {})
+
+ /*!
+ * Initializing constructor. Creates a reference wrapper that refers to the specified value.
+ */
+ template< typename U >
+ explicit value_ref(U const& val, typename enable_if< typename base_type::BOOST_NESTED_TEMPLATE is_compatible< U >, int >::type = 0) BOOST_NOEXCEPT :
+ base_type(boost::addressof(val))
+ {
+ }
+
+ /*!
+ * The operator verifies if the wrapper refers to a value.
+ */
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+
+ /*!
+ * The operator verifies if the wrapper does not refer to a value.
+ */
+ bool operator! () const BOOST_NOEXCEPT
+ {
+ return !this->m_ptr;
+ }
+
+ /*!
+ * \return \c true if the wrapper does not refer to a value.
+ */
+ bool empty() const BOOST_NOEXCEPT
+ {
+ return !this->m_ptr;
+ }
+
+ /*!
+ * Swaps two reference wrappers
+ */
+ void swap(value_ref& that) BOOST_NOEXCEPT
+ {
+ base_type::swap(that);
+ }
+};
+
+//! Free swap function
+template< typename T, typename TagT >
+inline void swap(value_ref< T, TagT >& left, value_ref< T, TagT >& right)
+{
+ left.swap(right);
+}
+
+//! Stream output operator
+template< typename CharT, typename TraitsT, typename T, typename TagT >
+inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, value_ref< T, TagT > const& val)
+{
+ if (!!val)
+ val.apply_visitor(boost::log::bind_output(strm));
+ return strm;
+}
+
+//! Log formatting operator
+template< typename CharT, typename TraitsT, typename AllocatorT, typename T, typename TagT >
+inline basic_formatting_ostream< CharT, TraitsT, AllocatorT >& operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >& strm, value_ref< T, TagT > const& val)
+{
+ if (!!val)
+ val.apply_visitor(boost::log::bind_to_log< TagT >(strm));
+ return strm;
+}
+
+// Equality comparison
+template< typename T, typename TagT, typename U >
+inline bool operator== (value_ref< T, TagT > const& left, U const& right)
+{
+ return left.apply_visitor_or_default(binder2nd< equal_to, U const& >(equal_to(), right), false);
+}
+
+template< typename U, typename T, typename TagT >
+inline bool operator== (U const& left, value_ref< T, TagT > const& right)
+{
+ return right.apply_visitor_or_default(binder1st< equal_to, U const& >(equal_to(), left), false);
+}
+
+template< typename T1, typename TagT1, typename T2, typename TagT2 >
+inline bool operator== (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
+{
+ if (!left && !right)
+ return true;
+ return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, equal_to >(right, false), false);
+}
+
+// Inequality comparison
+template< typename T, typename TagT, typename U >
+inline bool operator!= (value_ref< T, TagT > const& left, U const& right)
+{
+ return left.apply_visitor_or_default(binder2nd< not_equal_to, U const& >(not_equal_to(), right), false);
+}
+
+template< typename U, typename T, typename TagT >
+inline bool operator!= (U const& left, value_ref< T, TagT > const& right)
+{
+ return right.apply_visitor_or_default(binder1st< not_equal_to, U const& >(not_equal_to(), left), false);
+}
+
+template< typename T1, typename TagT1, typename T2, typename TagT2 >
+inline bool operator!= (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
+{
+ if (!left && !right)
+ return false;
+ return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, not_equal_to >(right, false), false);
+}
+
+// Less than ordering
+template< typename T, typename TagT, typename U >
+inline bool operator< (value_ref< T, TagT > const& left, U const& right)
+{
+ return left.apply_visitor_or_default(binder2nd< less, U const& >(less(), right), false);
+}
+
+template< typename U, typename T, typename TagT >
+inline bool operator< (U const& left, value_ref< T, TagT > const& right)
+{
+ return right.apply_visitor_or_default(binder1st< less, U const& >(less(), left), false);
+}
+
+template< typename T1, typename TagT1, typename T2, typename TagT2 >
+inline bool operator< (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
+{
+ return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, less >(right, false), false);
+}
+
+// Greater than ordering
+template< typename T, typename TagT, typename U >
+inline bool operator> (value_ref< T, TagT > const& left, U const& right)
+{
+ return left.apply_visitor_or_default(binder2nd< greater, U const& >(greater(), right), false);
+}
+
+template< typename U, typename T, typename TagT >
+inline bool operator> (U const& left, value_ref< T, TagT > const& right)
+{
+ return right.apply_visitor_or_default(binder1st< greater, U const& >(greater(), left), false);
+}
+
+template< typename T1, typename TagT1, typename T2, typename TagT2 >
+inline bool operator> (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
+{
+ return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, greater >(right, false), false);
+}
+
+// Less or equal ordering
+template< typename T, typename TagT, typename U >
+inline bool operator<= (value_ref< T, TagT > const& left, U const& right)
+{
+ return left.apply_visitor_or_default(binder2nd< less_equal, U const& >(less_equal(), right), false);
+}
+
+template< typename U, typename T, typename TagT >
+inline bool operator<= (U const& left, value_ref< T, TagT > const& right)
+{
+ return right.apply_visitor_or_default(binder1st< less_equal, U const& >(less_equal(), left), false);
+}
+
+template< typename T1, typename TagT1, typename T2, typename TagT2 >
+inline bool operator<= (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
+{
+ if (!left && !right)
+ return true;
+ return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, less_equal >(right, false), false);
+}
+
+// Greater or equal ordering
+template< typename T, typename TagT, typename U >
+inline bool operator>= (value_ref< T, TagT > const& left, U const& right)
+{
+ return left.apply_visitor_or_default(binder2nd< greater_equal, U const& >(greater_equal(), right), false);
+}
+
+template< typename U, typename T, typename TagT >
+inline bool operator>= (U const& left, value_ref< T, TagT > const& right)
+{
+ return right.apply_visitor_or_default(binder1st< greater_equal, U const& >(greater_equal(), left), false);
+}
+
+template< typename T1, typename TagT1, typename T2, typename TagT2 >
+inline bool operator>= (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
+{
+ if (!left && !right)
+ return true;
+ return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, greater_equal >(right, false), false);
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_VALUE_REF_HPP_INCLUDED_
diff --git a/boost/log/utility/value_ref_fwd.hpp b/boost/log/utility/value_ref_fwd.hpp
new file mode 100644
index 0000000000..aa4fa20225
--- /dev/null
+++ b/boost/log/utility/value_ref_fwd.hpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file value_ref_fwd.hpp
+ * \author Andrey Semashev
+ * \date 27.07.2012
+ *
+ * The header contains forward declaration of a value reference wrapper.
+ */
+
+#ifndef BOOST_LOG_UTILITY_VALUE_REF_FWD_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_VALUE_REF_FWD_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * \brief Reference wrapper for a stored attribute value.
+ */
+template< typename T, typename TagT = void >
+class value_ref;
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_UTILITY_VALUE_REF_FWD_HPP_INCLUDED_