Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r83860 - in trunk: boost/log boost/log/attributes boost/log/core boost/log/detail boost/log/expressions boost/log/expressions/formatters boost/log/expressions/predicates boost/log/keywords boost/log/sinks boost/log/sources boost/log/support boost/log/utility boost/log/utility/functional boost/log/utility/manipulators boost/log/utility/setup boost/log/utility/type_dispatch libs libs/log libs/log/build libs/log/doc libs/log/example libs/log/example/advanced_usage libs/log/example/async_log libs/log/example/basic_usage libs/log/example/bounded_async_log libs/log/example/doc libs/log/example/event_log libs/log/example/keywords libs/log/example/multiple_files libs/log/example/multiple_threads libs/log/example/native_syslog libs/log/example/rotating_file libs/log/example/settings_file libs/log/example/settings_file_formatter_factory libs/log/example/syslog libs/log/example/trivial libs/log/example/wide_char libs/log/src libs/log/test libs/log/test/common libs/log/test/compile libs/log/test/compile_fail libs/log/test/performance libs/log/test/run
From: andrey.semashev_at_[hidden]
Date: 2013-04-13 08:31:13


Author: andysem
Date: 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
New Revision: 83860
URL: http://svn.boost.org/trac/boost/changeset/83860

Log:
Boost.Log merged to trunk.
Added:
   trunk/boost/log/
   trunk/boost/log/attributes/
   trunk/boost/log/attributes.hpp (contents, props changed)
   trunk/boost/log/attributes/attribute.hpp (contents, props changed)
   trunk/boost/log/attributes/attribute_cast.hpp (contents, props changed)
   trunk/boost/log/attributes/attribute_name.hpp (contents, props changed)
   trunk/boost/log/attributes/attribute_set.hpp (contents, props changed)
   trunk/boost/log/attributes/attribute_value.hpp (contents, props changed)
   trunk/boost/log/attributes/attribute_value_impl.hpp (contents, props changed)
   trunk/boost/log/attributes/attribute_value_set.hpp (contents, props changed)
   trunk/boost/log/attributes/clock.hpp (contents, props changed)
   trunk/boost/log/attributes/constant.hpp (contents, props changed)
   trunk/boost/log/attributes/counter.hpp (contents, props changed)
   trunk/boost/log/attributes/current_process_id.hpp (contents, props changed)
   trunk/boost/log/attributes/current_process_name.hpp (contents, props changed)
   trunk/boost/log/attributes/current_thread_id.hpp (contents, props changed)
   trunk/boost/log/attributes/fallback_policy.hpp (contents, props changed)
   trunk/boost/log/attributes/fallback_policy_fwd.hpp (contents, props changed)
   trunk/boost/log/attributes/function.hpp (contents, props changed)
   trunk/boost/log/attributes/mutable_constant.hpp (contents, props changed)
   trunk/boost/log/attributes/named_scope.hpp (contents, props changed)
   trunk/boost/log/attributes/scoped_attribute.hpp (contents, props changed)
   trunk/boost/log/attributes/time_traits.hpp (contents, props changed)
   trunk/boost/log/attributes/timer.hpp (contents, props changed)
   trunk/boost/log/attributes/value_extraction.hpp (contents, props changed)
   trunk/boost/log/attributes/value_extraction_fwd.hpp (contents, props changed)
   trunk/boost/log/attributes/value_visitation.hpp (contents, props changed)
   trunk/boost/log/attributes/value_visitation_fwd.hpp (contents, props changed)
   trunk/boost/log/common.hpp (contents, props changed)
   trunk/boost/log/core/
   trunk/boost/log/core.hpp (contents, props changed)
   trunk/boost/log/core/core.hpp (contents, props changed)
   trunk/boost/log/core/record.hpp (contents, props changed)
   trunk/boost/log/core/record_view.hpp (contents, props changed)
   trunk/boost/log/detail/
   trunk/boost/log/detail/alignas.hpp (contents, props changed)
   trunk/boost/log/detail/asio_fwd.hpp (contents, props changed)
   trunk/boost/log/detail/attachable_sstream_buf.hpp (contents, props changed)
   trunk/boost/log/detail/attr_output_impl.hpp (contents, props changed)
   trunk/boost/log/detail/attr_output_terminal.hpp (contents, props changed)
   trunk/boost/log/detail/attribute_get_value_impl.hpp (contents, props changed)
   trunk/boost/log/detail/attribute_predicate.hpp (contents, props changed)
   trunk/boost/log/detail/cleanup_scope_guard.hpp (contents, props changed)
   trunk/boost/log/detail/code_conversion.hpp (contents, props changed)
   trunk/boost/log/detail/config.hpp (contents, props changed)
   trunk/boost/log/detail/custom_terminal_spec.hpp (contents, props changed)
   trunk/boost/log/detail/date_time_fmt_gen_traits_fwd.hpp (contents, props changed)
   trunk/boost/log/detail/date_time_format_parser.hpp (contents, props changed)
   trunk/boost/log/detail/decomposed_time.hpp (contents, props changed)
   trunk/boost/log/detail/deduce_char_type.hpp (contents, props changed)
   trunk/boost/log/detail/default_attribute_names.hpp (contents, props changed)
   trunk/boost/log/detail/embedded_string_type.hpp (contents, props changed)
   trunk/boost/log/detail/event.hpp (contents, props changed)
   trunk/boost/log/detail/fake_mutex.hpp (contents, props changed)
   trunk/boost/log/detail/footer.hpp (contents, props changed)
   trunk/boost/log/detail/format.hpp (contents, props changed)
   trunk/boost/log/detail/function_traits.hpp (contents, props changed)
   trunk/boost/log/detail/generate_overloads.hpp (contents, props changed)
   trunk/boost/log/detail/header.hpp (contents, props changed)
   trunk/boost/log/detail/id.hpp (contents, props changed)
   trunk/boost/log/detail/light_function.hpp (contents, props changed)
   trunk/boost/log/detail/light_function_pp.hpp (contents, props changed)
   trunk/boost/log/detail/light_rw_mutex.hpp (contents, props changed)
   trunk/boost/log/detail/locking_ptr.hpp (contents, props changed)
   trunk/boost/log/detail/locks.hpp (contents, props changed)
   trunk/boost/log/detail/named_scope_fmt_pp.hpp (contents, props changed)
   trunk/boost/log/detail/native_typeof.hpp (contents, props changed)
   trunk/boost/log/detail/parameter_tools.hpp (contents, props changed)
   trunk/boost/log/detail/pp_identity.hpp (contents, props changed)
   trunk/boost/log/detail/process_id.hpp (contents, props changed)
   trunk/boost/log/detail/setup_config.hpp (contents, props changed)
   trunk/boost/log/detail/singleton.hpp (contents, props changed)
   trunk/boost/log/detail/sink_init_helpers.hpp (contents, props changed)
   trunk/boost/log/detail/snprintf.hpp (contents, props changed)
   trunk/boost/log/detail/spin_mutex.hpp (contents, props changed)
   trunk/boost/log/detail/tagged_integer.hpp (contents, props changed)
   trunk/boost/log/detail/thread_id.hpp (contents, props changed)
   trunk/boost/log/detail/thread_specific.hpp (contents, props changed)
   trunk/boost/log/detail/threadsafe_queue.hpp (contents, props changed)
   trunk/boost/log/detail/timestamp.hpp (contents, props changed)
   trunk/boost/log/detail/trivial_keyword.hpp (contents, props changed)
   trunk/boost/log/detail/unary_function_terminal.hpp (contents, props changed)
   trunk/boost/log/detail/unhandled_exception_count.hpp (contents, props changed)
   trunk/boost/log/detail/value_ref_visitation.hpp (contents, props changed)
   trunk/boost/log/detail/visible_type.hpp (contents, props changed)
   trunk/boost/log/exceptions.hpp (contents, props changed)
   trunk/boost/log/expressions/
   trunk/boost/log/expressions.hpp (contents, props changed)
   trunk/boost/log/expressions/attr.hpp (contents, props changed)
   trunk/boost/log/expressions/attr_fwd.hpp (contents, props changed)
   trunk/boost/log/expressions/filter.hpp (contents, props changed)
   trunk/boost/log/expressions/formatter.hpp (contents, props changed)
   trunk/boost/log/expressions/formatters/
   trunk/boost/log/expressions/formatters.hpp (contents, props changed)
   trunk/boost/log/expressions/formatters/c_decorator.hpp (contents, props changed)
   trunk/boost/log/expressions/formatters/char_decorator.hpp (contents, props changed)
   trunk/boost/log/expressions/formatters/csv_decorator.hpp (contents, props changed)
   trunk/boost/log/expressions/formatters/date_time.hpp (contents, props changed)
   trunk/boost/log/expressions/formatters/format.hpp (contents, props changed)
   trunk/boost/log/expressions/formatters/if.hpp (contents, props changed)
   trunk/boost/log/expressions/formatters/named_scope.hpp (contents, props changed)
   trunk/boost/log/expressions/formatters/stream.hpp (contents, props changed)
   trunk/boost/log/expressions/formatters/wrap_formatter.hpp (contents, props changed)
   trunk/boost/log/expressions/formatters/xml_decorator.hpp (contents, props changed)
   trunk/boost/log/expressions/is_keyword_descriptor.hpp (contents, props changed)
   trunk/boost/log/expressions/keyword.hpp (contents, props changed)
   trunk/boost/log/expressions/keyword_fwd.hpp (contents, props changed)
   trunk/boost/log/expressions/message.hpp (contents, props changed)
   trunk/boost/log/expressions/predicates/
   trunk/boost/log/expressions/predicates.hpp (contents, props changed)
   trunk/boost/log/expressions/predicates/begins_with.hpp (contents, props changed)
   trunk/boost/log/expressions/predicates/channel_severity_filter.hpp (contents, props changed)
   trunk/boost/log/expressions/predicates/contains.hpp (contents, props changed)
   trunk/boost/log/expressions/predicates/ends_with.hpp (contents, props changed)
   trunk/boost/log/expressions/predicates/has_attr.hpp (contents, props changed)
   trunk/boost/log/expressions/predicates/is_debugger_present.hpp (contents, props changed)
   trunk/boost/log/expressions/predicates/is_in_range.hpp (contents, props changed)
   trunk/boost/log/expressions/predicates/matches.hpp (contents, props changed)
   trunk/boost/log/expressions/record.hpp (contents, props changed)
   trunk/boost/log/keywords/
   trunk/boost/log/keywords/auto_flush.hpp (contents, props changed)
   trunk/boost/log/keywords/channel.hpp (contents, props changed)
   trunk/boost/log/keywords/delimiter.hpp (contents, props changed)
   trunk/boost/log/keywords/depth.hpp (contents, props changed)
   trunk/boost/log/keywords/facility.hpp (contents, props changed)
   trunk/boost/log/keywords/file_name.hpp (contents, props changed)
   trunk/boost/log/keywords/filter.hpp (contents, props changed)
   trunk/boost/log/keywords/format.hpp (contents, props changed)
   trunk/boost/log/keywords/ident.hpp (contents, props changed)
   trunk/boost/log/keywords/ip_version.hpp (contents, props changed)
   trunk/boost/log/keywords/iteration.hpp (contents, props changed)
   trunk/boost/log/keywords/log_name.hpp (contents, props changed)
   trunk/boost/log/keywords/log_source.hpp (contents, props changed)
   trunk/boost/log/keywords/max_size.hpp (contents, props changed)
   trunk/boost/log/keywords/message_file.hpp (contents, props changed)
   trunk/boost/log/keywords/min_free_space.hpp (contents, props changed)
   trunk/boost/log/keywords/open_mode.hpp (contents, props changed)
   trunk/boost/log/keywords/order.hpp (contents, props changed)
   trunk/boost/log/keywords/ordering_window.hpp (contents, props changed)
   trunk/boost/log/keywords/registration.hpp (contents, props changed)
   trunk/boost/log/keywords/rotation_size.hpp (contents, props changed)
   trunk/boost/log/keywords/scan_method.hpp (contents, props changed)
   trunk/boost/log/keywords/severity.hpp (contents, props changed)
   trunk/boost/log/keywords/start_thread.hpp (contents, props changed)
   trunk/boost/log/keywords/target.hpp (contents, props changed)
   trunk/boost/log/keywords/time_based_rotation.hpp (contents, props changed)
   trunk/boost/log/keywords/use_impl.hpp (contents, props changed)
   trunk/boost/log/sinks/
   trunk/boost/log/sinks.hpp (contents, props changed)
   trunk/boost/log/sinks/async_frontend.hpp (contents, props changed)
   trunk/boost/log/sinks/attribute_mapping.hpp (contents, props changed)
   trunk/boost/log/sinks/basic_sink_backend.hpp (contents, props changed)
   trunk/boost/log/sinks/basic_sink_frontend.hpp (contents, props changed)
   trunk/boost/log/sinks/block_on_overflow.hpp (contents, props changed)
   trunk/boost/log/sinks/bounded_fifo_queue.hpp (contents, props changed)
   trunk/boost/log/sinks/bounded_ordering_queue.hpp (contents, props changed)
   trunk/boost/log/sinks/debug_output_backend.hpp (contents, props changed)
   trunk/boost/log/sinks/drop_on_overflow.hpp (contents, props changed)
   trunk/boost/log/sinks/event_log_backend.hpp (contents, props changed)
   trunk/boost/log/sinks/event_log_constants.hpp (contents, props changed)
   trunk/boost/log/sinks/frontend_requirements.hpp (contents, props changed)
   trunk/boost/log/sinks/sink.hpp (contents, props changed)
   trunk/boost/log/sinks/sync_frontend.hpp (contents, props changed)
   trunk/boost/log/sinks/syslog_backend.hpp (contents, props changed)
   trunk/boost/log/sinks/syslog_constants.hpp (contents, props changed)
   trunk/boost/log/sinks/text_file_backend.hpp (contents, props changed)
   trunk/boost/log/sinks/text_multifile_backend.hpp (contents, props changed)
   trunk/boost/log/sinks/text_ostream_backend.hpp (contents, props changed)
   trunk/boost/log/sinks/unbounded_fifo_queue.hpp (contents, props changed)
   trunk/boost/log/sinks/unbounded_ordering_queue.hpp (contents, props changed)
   trunk/boost/log/sinks/unlocked_frontend.hpp (contents, props changed)
   trunk/boost/log/sources/
   trunk/boost/log/sources/basic_logger.hpp (contents, props changed)
   trunk/boost/log/sources/channel_feature.hpp (contents, props changed)
   trunk/boost/log/sources/channel_logger.hpp (contents, props changed)
   trunk/boost/log/sources/exception_handler_feature.hpp (contents, props changed)
   trunk/boost/log/sources/features.hpp (contents, props changed)
   trunk/boost/log/sources/global_logger_storage.hpp (contents, props changed)
   trunk/boost/log/sources/logger.hpp (contents, props changed)
   trunk/boost/log/sources/record_ostream.hpp (contents, props changed)
   trunk/boost/log/sources/severity_channel_logger.hpp (contents, props changed)
   trunk/boost/log/sources/severity_feature.hpp (contents, props changed)
   trunk/boost/log/sources/severity_logger.hpp (contents, props changed)
   trunk/boost/log/sources/threading_models.hpp (contents, props changed)
   trunk/boost/log/support/
   trunk/boost/log/support/date_time.hpp (contents, props changed)
   trunk/boost/log/support/exception.hpp (contents, props changed)
   trunk/boost/log/support/regex.hpp (contents, props changed)
   trunk/boost/log/support/spirit_classic.hpp (contents, props changed)
   trunk/boost/log/support/spirit_qi.hpp (contents, props changed)
   trunk/boost/log/support/xpressive.hpp (contents, props changed)
   trunk/boost/log/trivial.hpp (contents, props changed)
   trunk/boost/log/utility/
   trunk/boost/log/utility/empty_deleter.hpp (contents, props changed)
   trunk/boost/log/utility/exception_handler.hpp (contents, props changed)
   trunk/boost/log/utility/explicit_operator_bool.hpp (contents, props changed)
   trunk/boost/log/utility/formatting_ostream.hpp (contents, props changed)
   trunk/boost/log/utility/formatting_ostream_fwd.hpp (contents, props changed)
   trunk/boost/log/utility/functional/
   trunk/boost/log/utility/functional.hpp (contents, props changed)
   trunk/boost/log/utility/functional/as_action.hpp (contents, props changed)
   trunk/boost/log/utility/functional/begins_with.hpp (contents, props changed)
   trunk/boost/log/utility/functional/bind.hpp (contents, props changed)
   trunk/boost/log/utility/functional/bind_assign.hpp (contents, props changed)
   trunk/boost/log/utility/functional/bind_output.hpp (contents, props changed)
   trunk/boost/log/utility/functional/bind_to_log.hpp (contents, props changed)
   trunk/boost/log/utility/functional/contains.hpp (contents, props changed)
   trunk/boost/log/utility/functional/ends_with.hpp (contents, props changed)
   trunk/boost/log/utility/functional/fun_ref.hpp (contents, props changed)
   trunk/boost/log/utility/functional/in_range.hpp (contents, props changed)
   trunk/boost/log/utility/functional/logical.hpp (contents, props changed)
   trunk/boost/log/utility/functional/matches.hpp (contents, props changed)
   trunk/boost/log/utility/functional/nop.hpp (contents, props changed)
   trunk/boost/log/utility/functional/save_result.hpp (contents, props changed)
   trunk/boost/log/utility/intrusive_ref_counter.hpp (contents, props changed)
   trunk/boost/log/utility/manipulators/
   trunk/boost/log/utility/manipulators.hpp (contents, props changed)
   trunk/boost/log/utility/manipulators/add_value.hpp (contents, props changed)
   trunk/boost/log/utility/manipulators/to_log.hpp (contents, props changed)
   trunk/boost/log/utility/once_block.hpp (contents, props changed)
   trunk/boost/log/utility/record_ordering.hpp (contents, props changed)
   trunk/boost/log/utility/setup/
   trunk/boost/log/utility/setup.hpp (contents, props changed)
   trunk/boost/log/utility/setup/common_attributes.hpp (contents, props changed)
   trunk/boost/log/utility/setup/console.hpp (contents, props changed)
   trunk/boost/log/utility/setup/file.hpp (contents, props changed)
   trunk/boost/log/utility/setup/filter_parser.hpp (contents, props changed)
   trunk/boost/log/utility/setup/formatter_parser.hpp (contents, props changed)
   trunk/boost/log/utility/setup/from_settings.hpp (contents, props changed)
   trunk/boost/log/utility/setup/from_stream.hpp (contents, props changed)
   trunk/boost/log/utility/setup/settings.hpp (contents, props changed)
   trunk/boost/log/utility/setup/settings_parser.hpp (contents, props changed)
   trunk/boost/log/utility/strictest_lock.hpp (contents, props changed)
   trunk/boost/log/utility/string_literal.hpp (contents, props changed)
   trunk/boost/log/utility/string_literal_fwd.hpp (contents, props changed)
   trunk/boost/log/utility/type_dispatch/
   trunk/boost/log/utility/type_dispatch/date_time_types.hpp (contents, props changed)
   trunk/boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp (contents, props changed)
   trunk/boost/log/utility/type_dispatch/standard_types.hpp (contents, props changed)
   trunk/boost/log/utility/type_dispatch/static_type_dispatcher.hpp (contents, props changed)
   trunk/boost/log/utility/type_dispatch/type_dispatcher.hpp (contents, props changed)
   trunk/boost/log/utility/type_info_wrapper.hpp (contents, props changed)
   trunk/boost/log/utility/unique_identifier_name.hpp (contents, props changed)
   trunk/boost/log/utility/unused_variable.hpp (contents, props changed)
   trunk/boost/log/utility/value_ref.hpp (contents, props changed)
   trunk/boost/log/utility/value_ref_fwd.hpp (contents, props changed)
   trunk/libs/log/
   trunk/libs/log/build/
   trunk/libs/log/build/Jamfile.v2 (contents, props changed)
   trunk/libs/log/doc/
   trunk/libs/log/doc/Design.dia (contents, props changed)
   trunk/libs/log/doc/Design.png (contents, props changed)
   trunk/libs/log/doc/Jamfile.v2 (contents, props changed)
   trunk/libs/log/doc/attributes.qbk (contents, props changed)
   trunk/libs/log/doc/changelog.qbk (contents, props changed)
   trunk/libs/log/doc/core.qbk (contents, props changed)
   trunk/libs/log/doc/design.qbk (contents, props changed)
   trunk/libs/log/doc/expressions.qbk (contents, props changed)
   trunk/libs/log/doc/extension.qbk (contents, props changed)
   trunk/libs/log/doc/filters_reference.qbk (contents, props changed)
   trunk/libs/log/doc/formatters_reference.qbk (contents, props changed)
   trunk/libs/log/doc/gen_references.xsl (contents, props changed)
   trunk/libs/log/doc/log.qbk (contents, props changed)
   trunk/libs/log/doc/rationale.qbk (contents, props changed)
   trunk/libs/log/doc/sink_backends.qbk (contents, props changed)
   trunk/libs/log/doc/sink_frontends.qbk (contents, props changed)
   trunk/libs/log/doc/sources.qbk (contents, props changed)
   trunk/libs/log/doc/todo.qbk (contents, props changed)
   trunk/libs/log/doc/tutorial.qbk (contents, props changed)
   trunk/libs/log/doc/utilities.qbk (contents, props changed)
   trunk/libs/log/example/
   trunk/libs/log/example/Jamfile.v2 (contents, props changed)
   trunk/libs/log/example/advanced_usage/
   trunk/libs/log/example/advanced_usage/Jamfile.v2 (contents, props changed)
   trunk/libs/log/example/advanced_usage/main.cpp (contents, props changed)
   trunk/libs/log/example/async_log/
   trunk/libs/log/example/async_log/Jamfile.v2 (contents, props changed)
   trunk/libs/log/example/async_log/main.cpp (contents, props changed)
   trunk/libs/log/example/basic_usage/
   trunk/libs/log/example/basic_usage/Jamfile.v2 (contents, props changed)
   trunk/libs/log/example/basic_usage/main.cpp (contents, props changed)
   trunk/libs/log/example/bounded_async_log/
   trunk/libs/log/example/bounded_async_log/Jamfile.v2 (contents, props changed)
   trunk/libs/log/example/bounded_async_log/main.cpp (contents, props changed)
   trunk/libs/log/example/doc/
   trunk/libs/log/example/doc/Jamfile.v2 (contents, props changed)
   trunk/libs/log/example/doc/attr_value_extraction.cpp (contents, props changed)
   trunk/libs/log/example/doc/attr_value_visitation.cpp (contents, props changed)
   trunk/libs/log/example/doc/core_core_manual.cpp (contents, props changed)
   trunk/libs/log/example/doc/core_record.cpp (contents, props changed)
   trunk/libs/log/example/doc/exception_handling.cpp (contents, props changed)
   trunk/libs/log/example/doc/expressions_attr_fmt_tag.cpp (contents, props changed)
   trunk/libs/log/example/doc/expressions_channel_severity_filter.cpp (contents, props changed)
   trunk/libs/log/example/doc/expressions_has_attr_stat_accum.cpp (contents, props changed)
   trunk/libs/log/example/doc/expressions_keyword_fmt_tag.cpp (contents, props changed)
   trunk/libs/log/example/doc/extension_app_launcher.cpp (contents, props changed)
   trunk/libs/log/example/doc/extension_filter_parser.cpp (contents, props changed)
   trunk/libs/log/example/doc/extension_filter_parser_custom_rel.cpp (contents, props changed)
   trunk/libs/log/example/doc/extension_formatter_parser.cpp (contents, props changed)
   trunk/libs/log/example/doc/extension_record_tagger.cpp (contents, props changed)
   trunk/libs/log/example/doc/extension_stat_collector.cpp (contents, props changed)
   trunk/libs/log/example/doc/extension_stat_collector_settings.cpp (contents, props changed)
   trunk/libs/log/example/doc/extension_system_uptime_attr.cpp (contents, props changed)
   trunk/libs/log/example/doc/sinks_async.cpp (contents, props changed)
   trunk/libs/log/example/doc/sinks_async_bounded.cpp (contents, props changed)
   trunk/libs/log/example/doc/sinks_async_ordering.cpp (contents, props changed)
   trunk/libs/log/example/doc/sinks_debugger.cpp (contents, props changed)
   trunk/libs/log/example/doc/sinks_file.cpp (contents, props changed)
   trunk/libs/log/example/doc/sinks_multifile.cpp (contents, props changed)
   trunk/libs/log/example/doc/sinks_ostream.cpp (contents, props changed)
   trunk/libs/log/example/doc/sinks_simple_event_log.cpp (contents, props changed)
   trunk/libs/log/example/doc/sinks_sync.cpp (contents, props changed)
   trunk/libs/log/example/doc/sinks_syslog.cpp (contents, props changed)
   trunk/libs/log/example/doc/sinks_unlocked.cpp (contents, props changed)
   trunk/libs/log/example/doc/sinks_xml_file.cpp (contents, props changed)
   trunk/libs/log/example/doc/sources_net_connection.cpp (contents, props changed)
   trunk/libs/log/example/doc/sources_net_connection_chan.cpp (contents, props changed)
   trunk/libs/log/example/doc/sources_net_connection_dynamic_chan.cpp (contents, props changed)
   trunk/libs/log/example/doc/sources_severity.cpp (contents, props changed)
   trunk/libs/log/example/doc/sources_severity_channel.cpp (contents, props changed)
   trunk/libs/log/example/doc/tutorial_attributes.cpp (contents, props changed)
   trunk/libs/log/example/doc/tutorial_file.cpp (contents, props changed)
   trunk/libs/log/example/doc/tutorial_file_manual.cpp (contents, props changed)
   trunk/libs/log/example/doc/tutorial_filtering.cpp (contents, props changed)
   trunk/libs/log/example/doc/tutorial_fmt_custom.cpp (contents, props changed)
   trunk/libs/log/example/doc/tutorial_fmt_format.cpp (contents, props changed)
   trunk/libs/log/example/doc/tutorial_fmt_stream.cpp (contents, props changed)
   trunk/libs/log/example/doc/tutorial_fmt_stream_manual.cpp (contents, props changed)
   trunk/libs/log/example/doc/tutorial_fmt_string.cpp (contents, props changed)
   trunk/libs/log/example/doc/tutorial_logging.cpp (contents, props changed)
   trunk/libs/log/example/doc/tutorial_trivial.cpp (contents, props changed)
   trunk/libs/log/example/doc/tutorial_trivial_flt.cpp (contents, props changed)
   trunk/libs/log/example/doc/util_dynamic_type_disp.cpp (contents, props changed)
   trunk/libs/log/example/doc/util_manip_to_log.cpp (contents, props changed)
   trunk/libs/log/example/doc/util_static_type_disp.cpp (contents, props changed)
   trunk/libs/log/example/event_log/
   trunk/libs/log/example/event_log/Jamfile.v2 (contents, props changed)
   trunk/libs/log/example/event_log/event_log_messages.mc (contents, props changed)
   trunk/libs/log/example/event_log/main.cpp (contents, props changed)
   trunk/libs/log/example/keywords/
   trunk/libs/log/example/keywords/Jamfile.v2 (contents, props changed)
   trunk/libs/log/example/keywords/main.cpp (contents, props changed)
   trunk/libs/log/example/multiple_files/
   trunk/libs/log/example/multiple_files/Jamfile.v2 (contents, props changed)
   trunk/libs/log/example/multiple_files/main.cpp (contents, props changed)
   trunk/libs/log/example/multiple_threads/
   trunk/libs/log/example/multiple_threads/Jamfile.v2 (contents, props changed)
   trunk/libs/log/example/multiple_threads/main.cpp (contents, props changed)
   trunk/libs/log/example/native_syslog/
   trunk/libs/log/example/native_syslog/Jamfile.v2 (contents, props changed)
   trunk/libs/log/example/native_syslog/main.cpp (contents, props changed)
   trunk/libs/log/example/rotating_file/
   trunk/libs/log/example/rotating_file/Jamfile.v2 (contents, props changed)
   trunk/libs/log/example/rotating_file/main.cpp (contents, props changed)
   trunk/libs/log/example/settings_file/
   trunk/libs/log/example/settings_file/Jamfile.v2 (contents, props changed)
   trunk/libs/log/example/settings_file/main.cpp (contents, props changed)
   trunk/libs/log/example/settings_file/settings.txt (contents, props changed)
   trunk/libs/log/example/settings_file_formatter_factory/
   trunk/libs/log/example/settings_file_formatter_factory/Jamfile.v2 (contents, props changed)
   trunk/libs/log/example/settings_file_formatter_factory/main.cpp (contents, props changed)
   trunk/libs/log/example/settings_file_formatter_factory/settings.txt (contents, props changed)
   trunk/libs/log/example/syslog/
   trunk/libs/log/example/syslog/Jamfile.v2 (contents, props changed)
   trunk/libs/log/example/syslog/main.cpp (contents, props changed)
   trunk/libs/log/example/trivial/
   trunk/libs/log/example/trivial/Jamfile.v2 (contents, props changed)
   trunk/libs/log/example/trivial/main.cpp (contents, props changed)
   trunk/libs/log/example/wide_char/
   trunk/libs/log/example/wide_char/Jamfile.v2 (contents, props changed)
   trunk/libs/log/example/wide_char/main.cpp (contents, props changed)
   trunk/libs/log/index.html (contents, props changed)
   trunk/libs/log/src/
   trunk/libs/log/src/alignment_gap_between.hpp (contents, props changed)
   trunk/libs/log/src/atomic_queue.hpp (contents, props changed)
   trunk/libs/log/src/attribute_name.cpp (contents, props changed)
   trunk/libs/log/src/attribute_set.cpp (contents, props changed)
   trunk/libs/log/src/attribute_set_impl.hpp (contents, props changed)
   trunk/libs/log/src/attribute_value_set.cpp (contents, props changed)
   trunk/libs/log/src/code_conversion.cpp (contents, props changed)
   trunk/libs/log/src/core.cpp (contents, props changed)
   trunk/libs/log/src/date_time_format_parser.cpp (contents, props changed)
   trunk/libs/log/src/debug_output_backend.cpp (contents, props changed)
   trunk/libs/log/src/default_attribute_names.cpp (contents, props changed)
   trunk/libs/log/src/default_filter_factory.cpp (contents, props changed)
   trunk/libs/log/src/default_filter_factory.hpp (contents, props changed)
   trunk/libs/log/src/default_sink.cpp (contents, props changed)
   trunk/libs/log/src/default_sink.hpp (contents, props changed)
   trunk/libs/log/src/event.cpp (contents, props changed)
   trunk/libs/log/src/event_log_backend.cpp (contents, props changed)
   trunk/libs/log/src/event_log_registry.hpp (contents, props changed)
   trunk/libs/log/src/exceptions.cpp (contents, props changed)
   trunk/libs/log/src/filter_parser.cpp (contents, props changed)
   trunk/libs/log/src/format_parser.cpp (contents, props changed)
   trunk/libs/log/src/formatter_parser.cpp (contents, props changed)
   trunk/libs/log/src/global_logger_storage.cpp (contents, props changed)
   trunk/libs/log/src/init_from_settings.cpp (contents, props changed)
   trunk/libs/log/src/init_from_stream.cpp (contents, props changed)
   trunk/libs/log/src/light_rw_mutex.cpp (contents, props changed)
   trunk/libs/log/src/named_scope.cpp (contents, props changed)
   trunk/libs/log/src/named_scope_format_parser.cpp (contents, props changed)
   trunk/libs/log/src/once_block.cpp (contents, props changed)
   trunk/libs/log/src/parser_utils.cpp (contents, props changed)
   trunk/libs/log/src/parser_utils.hpp (contents, props changed)
   trunk/libs/log/src/process_id.cpp (contents, props changed)
   trunk/libs/log/src/process_name.cpp (contents, props changed)
   trunk/libs/log/src/record_ostream.cpp (contents, props changed)
   trunk/libs/log/src/settings_parser.cpp (contents, props changed)
   trunk/libs/log/src/severity_level.cpp (contents, props changed)
   trunk/libs/log/src/simple_event_log.mc (contents, props changed)
   trunk/libs/log/src/spirit_encoding.cpp (contents, props changed)
   trunk/libs/log/src/spirit_encoding.hpp (contents, props changed)
   trunk/libs/log/src/stateless_allocator.hpp (contents, props changed)
   trunk/libs/log/src/syslog_backend.cpp (contents, props changed)
   trunk/libs/log/src/text_file_backend.cpp (contents, props changed)
   trunk/libs/log/src/text_ostream_backend.cpp (contents, props changed)
   trunk/libs/log/src/thread_id.cpp (contents, props changed)
   trunk/libs/log/src/thread_specific.cpp (contents, props changed)
   trunk/libs/log/src/threadsafe_queue.cpp (contents, props changed)
   trunk/libs/log/src/timer.cpp (contents, props changed)
   trunk/libs/log/src/timestamp.cpp (contents, props changed)
   trunk/libs/log/src/trivial.cpp (contents, props changed)
   trunk/libs/log/src/unhandled_exception_count.cpp (contents, props changed)
   trunk/libs/log/src/windows_version.hpp (contents, props changed)
   trunk/libs/log/test/
   trunk/libs/log/test/Jamfile.v2 (contents, props changed)
   trunk/libs/log/test/common/
   trunk/libs/log/test/common/attr_comparison.hpp (contents, props changed)
   trunk/libs/log/test/common/char_definitions.hpp (contents, props changed)
   trunk/libs/log/test/common/make_record.hpp (contents, props changed)
   trunk/libs/log/test/common/test_sink.hpp (contents, props changed)
   trunk/libs/log/test/compile/
   trunk/libs/log/test/compile/current_function_support.cpp (contents, props changed)
   trunk/libs/log/test/compile/src_logger_assignable.cpp (contents, props changed)
   trunk/libs/log/test/compile/util_explicit_operator_bool.cpp (contents, props changed)
   trunk/libs/log/test/compile/util_unique_identifier.cpp (contents, props changed)
   trunk/libs/log/test/compile_fail/
   trunk/libs/log/test/compile_fail/attr_functor_void_return.cpp (contents, props changed)
   trunk/libs/log/test/compile_fail/util_explicit_operator_bool_conv_int.cpp (contents, props changed)
   trunk/libs/log/test/compile_fail/util_explicit_operator_bool_conv_pvoid.cpp (contents, props changed)
   trunk/libs/log/test/compile_fail/util_explicit_operator_bool_delete.cpp (contents, props changed)
   trunk/libs/log/test/compile_fail/util_explicit_operator_bool_shift.cpp (contents, props changed)
   trunk/libs/log/test/performance/
   trunk/libs/log/test/performance/Jamfile.v2 (contents, props changed)
   trunk/libs/log/test/performance/record_emission.cpp (contents, props changed)
   trunk/libs/log/test/run/
   trunk/libs/log/test/run/attr_attribute_set.cpp (contents, props changed)
   trunk/libs/log/test/run/attr_attribute_value_impl.cpp (contents, props changed)
   trunk/libs/log/test/run/attr_attribute_value_set.cpp (contents, props changed)
   trunk/libs/log/test/run/attr_function.cpp (contents, props changed)
   trunk/libs/log/test/run/attr_named_scope.cpp (contents, props changed)
   trunk/libs/log/test/run/attr_value_visitation.cpp (contents, props changed)
   trunk/libs/log/test/run/core.cpp (contents, props changed)
   trunk/libs/log/test/run/filt_attr.cpp (contents, props changed)
   trunk/libs/log/test/run/filt_has_attr.cpp (contents, props changed)
   trunk/libs/log/test/run/form_attr.cpp (contents, props changed)
   trunk/libs/log/test/run/form_date_time.cpp (contents, props changed)
   trunk/libs/log/test/run/form_format.cpp (contents, props changed)
   trunk/libs/log/test/run/form_if.cpp (contents, props changed)
   trunk/libs/log/test/run/form_message.cpp (contents, props changed)
   trunk/libs/log/test/run/form_named_scope.cpp (contents, props changed)
   trunk/libs/log/test/run/util_dynamic_type_dispatcher.cpp (contents, props changed)
   trunk/libs/log/test/run/util_exception_handler.cpp (contents, props changed)
   trunk/libs/log/test/run/util_once_block.cpp (contents, props changed)
   trunk/libs/log/test/run/util_static_type_dispatcher.cpp (contents, props changed)
   trunk/libs/log/test/run/util_string_literal.cpp (contents, props changed)
   trunk/libs/log/test/run/util_type_info_wrapper.cpp (contents, props changed)
Text files modified:
   trunk/libs/libraries.htm | 1 +
   trunk/libs/maintainers.txt | 3 ++-
   2 files changed, 3 insertions(+), 1 deletions(-)

Added: trunk/boost/log/attributes.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,38 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#endif // BOOST_LOG_ATTRIBUTES_HPP_INCLUDED_

Added: trunk/boost/log/attributes/attribute.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/attribute.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,186 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/intrusive_ptr.hpp>
+#include <boost/move/core.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/utility/intrusive_ref_counter.hpp>
+#include <boost/log/utility/explicit_operator_bool.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_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 considirable 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_LOG_VISIBLE impl :
+ public intrusive_ref_counter
+ {
+ /*!
+ * \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_LOG_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_LOG_EXPLICIT_OPERATOR_BOOL()
+
+ /*!
+ * 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_

Added: trunk/boost/log/attributes/attribute_cast.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/attribute_cast.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,74 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/attributes/attribute_name.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/attribute_name.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,185 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/log/utility/explicit_operator_bool.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_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 thanslation 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_LOG_EXPLICIT_OPERATOR_BOOL()
+ /*!
+ * 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_

Added: trunk/boost/log/attributes/attribute_set.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/attribute_set.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,507 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_DELETED_FUNCTION(node_base(node_base const&))
+ BOOST_LOG_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
+ {
+ register 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_

Added: trunk/boost/log/attributes/attribute_value.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/attribute_value.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,381 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/intrusive_ptr.hpp>
+#include <boost/move/core.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/utility/explicit_operator_bool.hpp>
+#include <boost/log/utility/intrusive_ref_counter.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_LOG_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 acquision. 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_LOG_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_LOG_EXPLICIT_OPERATOR_BOOL()
+ /*!
+ * 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 a 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 a 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 a 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 a 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_FUNCTION_TEMPLATE_DEFAULT_ARGS) || 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 a 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 a 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 a 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 a 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_FUNCTION_TEMPLATE_DEFAULT_ARGS) || 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 a 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_

Added: trunk/boost/log/attributes/attribute_value_impl.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/attribute_value_impl.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,136 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+#include <boost/type_traits/remove_reference.hpp>
+#endif
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_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_RVALUE_REFERENCES) && !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_

Added: trunk/boost/log/attributes/attribute_value_set.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/attribute_value_set.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,479 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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;
+
+ //! A base class for the container nodes
+ struct node_base
+ {
+ node_base* m_pPrev;
+ node_base* m_pNext;
+
+ node_base();
+
+ BOOST_LOG_DELETED_FUNCTION(node_base(node_base const&))
+ BOOST_LOG_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
+ {
+ register 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_

Added: trunk/boost/log/attributes/clock.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/clock.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,95 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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 th 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_LOG_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_

Added: trunk/boost/log/attributes/constant.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/constant.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,122 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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 simpliest 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_LOG_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_

Added: trunk/boost/log/attributes/counter.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/counter.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,218 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_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()
+ {
+ register unsigned long next_counter = static_cast< unsigned long >(++m_Counter);
+ register 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_

Added: trunk/boost/log/attributes/current_process_id.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/current_process_id.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,67 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/attributes/current_process_name.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/current_process_name.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,71 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/attributes/current_thread_id.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/current_thread_id.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,109 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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/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_LOG_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_

Added: trunk/boost/log/attributes/fallback_policy.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/fallback_policy.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,186 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/attributes/fallback_policy_fwd.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/fallback_policy_fwd.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,48 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/attributes/function.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/function.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,170 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_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 imitialization
+ */
+ 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_

Added: trunk/boost/log/attributes/mutable_constant.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/mutable_constant.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,327 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/static_assert.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_LOG_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 attibute 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. 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.
+ */
+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
+ 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
+>
+class mutable_constant :
+ public attribute
+{
+public:
+ //! The attribute value type
+ typedef T value_type;
+
+protected:
+ //! Factory implementation
+ class BOOST_LOG_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_LOG_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_

Added: trunk/boost/log/attributes/named_scope.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/named_scope.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,445 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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
+{
+ /*!
+ * 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;
+
+ /*!
+ * 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) BOOST_NOEXCEPT :
+ scope_name(sn),
+ file_name(fn),
+ line(ln)
+ {
+ }
+};
+
+/*!
+ * \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) BOOST_NOEXCEPT :
+ m_Entry(sn, fn, ln)
+ {
+ 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_LOG_DELETED_FUNCTION(sentry(sentry const&))
+ BOOST_LOG_DELETED_FUNCTION(sentry& operator= (sentry const&))
+
+ private:
+ scope_entry m_Entry;
+ };
+
+private:
+ //! Attribute implementation class
+ struct BOOST_LOG_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
+
+//! \cond
+
+#define BOOST_LOG_NAMED_SCOPE_INTERNAL(var, name, file, line)\
+ BOOST_LOG_UNUSED_VARIABLE(::boost::log::attributes::named_scope::sentry, var, (name, file, line));
+
+//! \endcond
+
+/*!
+ * 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__)
+
+/*!
+ * Macro for function scope markup. The scope name is constructed with help of compiler and contains current function name.
+ * 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(BOOST_CURRENT_FUNCTION)
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTRIBUTES_NAMED_SCOPE_HPP_INCLUDED_

Added: trunk/boost/log/attributes/scoped_attribute.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/scoped_attribute.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,253 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_

Added: trunk/boost/log/attributes/time_traits.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/time_traits.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,81 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/attributes/timer.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/timer.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,83 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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 acquision.
+ * 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 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_LOG_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_

Added: trunk/boost/log/attributes/value_extraction.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/value_extraction.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,816 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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 a 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 a 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_LOG_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_LOG_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_LOG_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 excercised if the default value is a temporary object. Because the function returns
+ * a reference, if the temporary object is destroued, 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 excercised if the default value is a temporary object. Because the function returns
+ * a reference, if the temporary object is destroued, 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 excercised if the default value is a temporary object. Because the function returns
+ * a reference, if the temporary object is destroued, 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 excercised if the default value is a temporary object. Because the function returns
+ * a reference, if the temporary object is destroued, 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 excercised if the default value is a temporary object. Because the function returns
+ * a reference, if the temporary object is destroued, 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 excercised if the default value is a temporary object. Because the function returns
+ * a reference, if the temporary object is destroued, 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 excercised if the default value is a temporary object. Because the function returns
+ * a reference, if the temporary object is destroued, 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_

Added: trunk/boost/log/attributes/value_extraction_fwd.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/value_extraction_fwd.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,62 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/attributes/value_visitation.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/value_visitation.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,372 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/log/utility/explicit_operator_bool.hpp>
+#include <boost/log/utility/type_dispatch/static_type_dispatcher.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_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 vew, 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_LOG_EXPLICIT_OPERATOR_BOOL()
+ /*!
+ * 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
+ * an 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_LOG_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_

Added: trunk/boost/log/attributes/value_visitation_fwd.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/attributes/value_visitation_fwd.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,45 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/common.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/common.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,41 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#endif // BOOST_LOG_COMMON_HPP_INCLUDED_

Added: trunk/boost/log/core.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/core.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,28 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#endif // BOOST_LOG_CORE_HPP_INCLUDED_

Added: trunk/boost/log/core/core.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/core/core.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,329 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/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_LOG_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 interchangable.
+ *
+ * \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_LOG_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_LOG_FORCEINLINE void push_record(BOOST_RV_REF(record) rec)
+ {
+ push_record_move(static_cast< record& >(rec));
+ }
+
+ BOOST_LOG_DELETED_FUNCTION(core(core const&))
+ BOOST_LOG_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_

Added: trunk/boost/log/core/record.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/core/record.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,196 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/log/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_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+class core;
+
+/*!
+ * \brief Logging record class
+ *
+ * The logging record incapsulates 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_LOG_EXPLICIT_OPERATOR_BOOL()
+
+ /*!
+ * 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 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_

Added: trunk/boost/log/core/record_view.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/core/record_view.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,249 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/intrusive_ptr.hpp>
+#include <boost/move/core.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/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_LOG_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 incapsulates 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_LOG_DELETED_FUNCTION(public_data(public_data const&))
+ BOOST_LOG_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_LOG_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_LOG_EXPLICIT_OPERATOR_BOOL()
+
+ /*!
+ * 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 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_

Added: trunk/boost/log/detail/alignas.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/alignas.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,45 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 alignas.hpp
+ * \author Andrey Semashev
+ * \date 06.07.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_ALIGNAS_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_ALIGNAS_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+// The macro allows to specify type or variable alignment
+#if defined(_MSC_VER)
+#define BOOST_LOG_ALIGNAS(x) __declspec(align(x))
+#elif defined(BOOST_CLANG)
+#if __has_feature(cxx_alignas) || __has_extension(cxx_alignas)
+#define BOOST_LOG_ALIGNAS(x) alignas(x)
+#endif
+#elif defined(__GNUC__)
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
+#define BOOST_LOG_ALIGNAS(x) alignas(x)
+#else
+#define BOOST_LOG_ALIGNAS(x) __attribute__((__aligned__(x)))
+#endif
+#endif
+
+#if !defined(BOOST_LOG_ALIGNAS)
+#define BOOST_LOG_NO_ALIGNAS 1
+#define BOOST_LOG_ALIGNAS(x)
+#endif
+
+#endif // BOOST_LOG_DETAIL_ALIGNAS_HPP_INCLUDED_

Added: trunk/boost/log/detail/asio_fwd.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/asio_fwd.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,43 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_

Added: trunk/boost/log/detail/attachable_sstream_buf.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/attachable_sstream_buf.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,172 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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()
+ {
+ register char_type* pBase = this->pbase();
+ register 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);
+ register char_type* pBase = this->pbase();
+ register 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;
+ register 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_LOG_DELETED_FUNCTION(basic_ostringstreambuf(basic_ostringstreambuf const& that))
+ //! Assignment (closed)
+ BOOST_LOG_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_

Added: trunk/boost/log/detail/attr_output_impl.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/attr_output_impl.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,111 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_

Added: trunk/boost/log/detail/attr_output_terminal.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/attr_output_terminal.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,173 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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 ContextT >
+ struct result< this_type(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;
+ };
+
+ template< typename ContextT >
+ struct result< const this_type(ContextT) >
+ {
+ typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type;
+ typedef typename phoenix::evaluator::impl<
+ typename LeftT::proto_base_expr const&,
+ 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_LOG_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_

Added: trunk/boost/log/detail/attribute_get_value_impl.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/attribute_get_value_impl.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,43 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_

Added: trunk/boost/log/detail/attribute_predicate.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/attribute_predicate.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,116 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/detail/cleanup_scope_guard.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/cleanup_scope_guard.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,55 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_LOG_DELETED_FUNCTION(cleanup_guard(cleanup_guard const&))
+ BOOST_LOG_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_

Added: trunk/boost/log/detail/code_conversion.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/code_conversion.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,119 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_CHAR16_T) && !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_CHAR32_T) && !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_

Added: trunk/boost/log/detail/config.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/config.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,402 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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>
+#include <boost/version.hpp>
+
+#if BOOST_VERSION < 104800
+# error Boost.Log: Boost version 1.48 or later is required
+#endif
+
+#if defined(BOOST_NO_RTTI)
+# error Boost.Log: RTTI is required by the library
+#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
+
+#if (defined(_MSC_VER) && (_MSC_VER >= 1020)) || defined(__GNUC__) || defined(BOOST_CLANG) || defined(BOOST_INTEL) || defined(__COMO__) || defined(__DMC__)
+# define BOOST_LOG_HAS_PRAGMA_ONCE
+#endif
+
+#ifdef BOOST_LOG_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 instantiations
+# define BOOST_LOG_BROKEN_FRIEND_TEMPLATE_INSTANTIATIONS
+# 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)
+ // Intel compiler has problems with friend declarations for member classes
+# 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(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)) && !defined(BOOST_NO_COMPILER_CONFIG)
+ // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
+# define BOOST_LOG_NO_UNSPECIFIED_BOOL
+#endif // (defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)) && !defined(BOOST_NO_COMPILER_CONFIG)
+
+#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1))
+ // GCC 4.0.0 (and probably older) can't cope with some optimizations regarding string literals
+# define BOOST_LOG_BROKEN_STRING_LITERALS
+#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
+
+#define BOOST_LOG_NO_TRAILING_RESULT_TYPE
+#define BOOST_LOG_NO_INLINE_NAMESPACES
+
+#if defined(BOOST_CLANG)
+# if __has_feature(cxx_trailing_return)
+# undef BOOST_LOG_NO_TRAILING_RESULT_TYPE
+# endif
+# if __has_feature(cxx_inline_namespaces)
+# undef BOOST_LOG_NO_INLINE_NAMESPACES
+# endif
+#elif defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
+# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
+# undef BOOST_LOG_NO_TRAILING_RESULT_TYPE
+# undef BOOST_LOG_NO_INLINE_NAMESPACES
+# endif
+#endif
+
+#if defined(BOOST_NO_VARIADIC_TEMPLATES) || 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
+
+// Extended declaration macros. Used to implement compiler-specific optimizations.
+#if defined(BOOST_FORCEINLINE)
+# define BOOST_LOG_FORCEINLINE BOOST_FORCEINLINE
+#elif defined(_MSC_VER)
+# define BOOST_LOG_FORCEINLINE __forceinline
+#elif defined(__GNUC__) && (__GNUC__ > 3)
+# define BOOST_LOG_FORCEINLINE inline __attribute__((always_inline))
+#else
+# define BOOST_LOG_FORCEINLINE inline
+#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()
+#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 (supposedly) 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(__CLANG__) || defined(__GNUC__)) && !defined(__QNX__)
+// The cxxabi.h is available
+#define BOOST_LOG_HAS_CXXABI_H
+#endif
+
+#if defined(BOOST_SYMBOL_VISIBLE)
+# define BOOST_LOG_VISIBLE BOOST_SYMBOL_VISIBLE
+#elif defined(__GNUC__) && (__GNUC__ >= 4)
+# define BOOST_LOG_VISIBLE __attribute__((visibility("default")))
+#else
+# define BOOST_LOG_VISIBLE
+#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_LOG_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)
+
+#if defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ <= 5)
+ // GCC 4.5 forbids declaration of defaulted functions in private or protected sections
+# define BOOST_LOG_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS
+#endif
+
+#if defined(BOOST_LOG_DOXYGEN_PASS) || !(defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || defined(BOOST_LOG_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS))
+# define BOOST_LOG_DEFAULTED_FUNCTION(fun, body) fun = default;
+#else
+# define BOOST_LOG_DEFAULTED_FUNCTION(fun, body) fun body
+#endif
+
+#if defined(BOOST_LOG_DOXYGEN_PASS) || !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
+# define BOOST_LOG_DELETED_FUNCTION(fun) fun = delete;
+#else
+# define BOOST_LOG_DELETED_FUNCTION(fun) private: fun;
+#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_LOG_NO_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))
+__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)
+
+} // namespace boost
+
+#endif // BOOST_LOG_DETAIL_CONFIG_HPP_INCLUDED_

Added: trunk/boost/log/detail/custom_terminal_spec.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/custom_terminal_spec.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,70 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/detail/date_time_fmt_gen_traits_fwd.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/date_time_fmt_gen_traits_fwd.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,44 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_

Added: trunk/boost/log/detail/date_time_format_parser.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/date_time_format_parser.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,486 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/detail/decomposed_time.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/decomposed_time.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,440 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_LOG_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_LOG_DELETED_FUNCTION(context(context const&))
+ BOOST_LOG_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_LOG_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_literals);
+ 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), ctx.strm, ' ', &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_

Added: trunk/boost/log/detail/deduce_char_type.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/deduce_char_type.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,108 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_RVALUE_REFERENCES) && !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_

Added: trunk/boost/log/detail/default_attribute_names.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/default_attribute_names.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,53 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_

Added: trunk/boost/log/detail/embedded_string_type.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/embedded_string_type.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,125 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_CHAR16_T) && !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_CHAR32_T) && !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_

Added: trunk/boost/log/detail/event.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/event.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,145 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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();
+
+private:
+ // Copying prohibited
+ sem_based_event(sem_based_event const&);
+ 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();
+
+private:
+ // Copying prohibited
+ winapi_based_event(winapi_based_event const&);
+ 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();
+
+private:
+ // Copying prohibited
+ generic_event(generic_event const&);
+ 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_

Added: trunk/boost/log/detail/fake_mutex.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/fake_mutex.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,56 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_LOG_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_LOG_DELETED_FUNCTION(fake_mutex(fake_mutex const&))
+ BOOST_LOG_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_

Added: trunk/boost/log/detail/footer.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/footer.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,16 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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)
+#endif
+
+#endif // !defined(BOOST_LOG_ENABLE_WARNINGS)
+
+#include <boost/config/abi_suffix.hpp>

Added: trunk/boost/log/detail/format.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/format.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,336 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_LOG_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_LOG_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_LOG_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_SNPRINTF_HPP_INCLUDED_

Added: trunk/boost/log/detail/function_traits.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/function_traits.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,236 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_

Added: trunk/boost/log/detail/generate_overloads.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/generate_overloads.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,30 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_RVALUE_REFERENCES) && !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_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)

Added: trunk/boost/log/detail/header.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/header.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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)
+#endif
+
+#endif // !defined(BOOST_LOG_ENABLE_WARNINGS)

Added: trunk/boost/log/detail/id.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/id.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,84 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_

Added: trunk/boost/log/detail/light_function.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/light_function.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,489 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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/log/utility/explicit_operator_bool.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#if defined(BOOST_NO_VARIADIC_TEMPLATES) || 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_RVALUE_REFERENCES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/mpl/or.hpp>
+#else
+#include <boost/type_traits/remove_reference.hpp>
+#endif
+#if defined(BOOST_NO_NULLPTR) || defined(BOOST_NO_CXX11_NULLPTR)
+#include <boost/assert.hpp>
+#endif
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_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 {
+
+template< typename SignatureT >
+class light_function;
+
+#if !defined(BOOST_NO_VARIADIC_TEMPLATES) && !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)(impl_base*, ArgsT...);
+ const invoke_type invoke;
+
+ typedef impl_base* (*clone_type)(const impl_base*);
+ const clone_type clone;
+
+ typedef void (*destroy_type)(impl_base*);
+ const destroy_type destroy;
+
+ impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr)
+ {
+ }
+ };
+
+#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_RVALUE_REFERENCES) && !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(fun)
+ {
+ }
+#endif // !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+ static void destroy_impl(impl_base* self)
+ {
+ delete static_cast< impl* >(self);
+ }
+ static impl_base* clone_impl(const impl_base* self)
+ {
+ return new impl(static_cast< const impl* >(self)->m_Function);
+ }
+ static result_type invoke_impl(impl_base* self, ArgsT... args)
+ {
+ return static_cast< impl* >(self)->m_Function(args...);
+ }
+ };
+
+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_RVALUE_REFERENCES) && !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< mpl::or_< move_detail::is_rv< FunT >, is_same< FunT, this_type > >, int >::type = 0) :
+ m_pImpl(new impl< FunT >(fun))
+ {
+ }
+ template< typename FunT >
+ light_function(rv< FunT > const& fun, typename disable_if< is_same< typename remove_cv< FunT >::type, this_type >, int >::type = 0) :
+ m_pImpl(new impl< typename remove_cv< FunT >::type >(fun))
+ {
+ }
+#endif
+
+ //! Constructor from NULL
+#if !defined(BOOST_NO_NULLPTR) && !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_NULLPTR) || 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(that);
+ this->swap(tmp);
+ return *this;
+ }
+ //! Assignment of NULL
+#if !defined(BOOST_NO_NULLPTR) && !defined(BOOST_NO_CXX11_NULLPTR)
+ light_function& operator= (std::nullptr_t)
+#else
+ light_function& operator= (int p)
+#endif
+ {
+#if defined(BOOST_NO_NULLPTR) || defined(BOOST_NO_CXX11_NULLPTR)
+ BOOST_ASSERT(p == 0);
+#endif
+ clear();
+ return *this;
+ }
+#if !defined(BOOST_NO_RVALUE_REFERENCES) && !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< mpl::or_< move_detail::is_rv< FunT >, is_same< FunT, this_type > >, 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_LOG_EXPLICIT_OPERATOR_BOOL()
+ 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
+ {
+ register 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)(impl_base*, ArgsT...);
+ const invoke_type invoke;
+
+ typedef impl_base* (*clone_type)(const impl_base*);
+ const clone_type clone;
+
+ typedef void (*destroy_type)(impl_base*);
+ const destroy_type destroy;
+
+ impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr)
+ {
+ }
+ };
+
+#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_RVALUE_REFERENCES) && !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(fun)
+ {
+ }
+#endif // !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+ static void destroy_impl(impl_base* self)
+ {
+ delete static_cast< impl* >(self);
+ }
+ static impl_base* clone_impl(const impl_base* self)
+ {
+ return new impl(static_cast< const impl* >(self)->m_Function);
+ }
+ static result_type invoke_impl(impl_base* self, ArgsT... args)
+ {
+ static_cast< impl* >(self)->m_Function(args...);
+ }
+ };
+
+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_RVALUE_REFERENCES) && !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< mpl::or_< move_detail::is_rv< FunT >, is_same< FunT, this_type > >, int >::type = 0) :
+ m_pImpl(new impl< FunT >(fun))
+ {
+ }
+ template< typename FunT >
+ light_function(rv< FunT > const& fun, typename disable_if< is_same< typename remove_cv< FunT >::type, this_type >, int >::type = 0) :
+ m_pImpl(new impl< typename remove_cv< FunT >::type >(fun))
+ {
+ }
+#endif
+
+ //! Constructor from NULL
+#if !defined(BOOST_NO_NULLPTR) && !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_NULLPTR) || 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 = that;
+ this->swap(tmp);
+ return *this;
+ }
+ //! Assignment of NULL
+#if !defined(BOOST_NO_NULLPTR) && !defined(BOOST_NO_CXX11_NULLPTR)
+ light_function& operator= (std::nullptr_t)
+#else
+ light_function& operator= (int p)
+#endif
+ {
+#if defined(BOOST_NO_NULLPTR) || defined(BOOST_NO_CXX11_NULLPTR)
+ BOOST_ASSERT(p == 0);
+#endif
+ clear();
+ return *this;
+ }
+#if !defined(BOOST_NO_RVALUE_REFERENCES) && !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< mpl::or_< move_detail::is_rv< FunT >, is_same< FunT, this_type > >, 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_LOG_EXPLICIT_OPERATOR_BOOL()
+ 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
+ {
+ register impl_base* p = m_pImpl;
+ m_pImpl = that.m_pImpl;
+ that.m_pImpl = p;
+ }
+};
+
+#else // !defined(BOOST_NO_VARIADIC_TEMPLATES) && !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_VARIADIC_TEMPLATES) && !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_

Added: trunk/boost/log/detail/light_function_pp.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/light_function_pp.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,412 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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)(impl_base* BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), ArgT));
+ const invoke_type invoke;
+
+ typedef impl_base* (*clone_type)(const impl_base*);
+ const clone_type clone;
+
+ typedef void (*destroy_type)(impl_base*);
+ const destroy_type destroy;
+
+ impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr)
+ {
+ }
+ };
+
+#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_RVALUE_REFERENCES) && !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(fun)
+ {
+ }
+#endif // !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+ static void destroy_impl(impl_base* self)
+ {
+ delete static_cast< impl* >(self);
+ }
+ static impl_base* clone_impl(const impl_base* self)
+ {
+ return new impl(static_cast< const impl* >(self)->m_Function);
+ }
+ static result_type invoke_impl(impl_base* self BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg))
+ {
+ return static_cast< impl* >(self)->m_Function(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg));
+ }
+ };
+
+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_RVALUE_REFERENCES) && !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< mpl::or_< move_detail::is_rv< FunT >, is_same< FunT, this_type > >, int >::type = 0) :
+ m_pImpl(new impl< FunT >(fun))
+ {
+ }
+ template< typename FunT >
+ light_function(rv< FunT > const& fun, typename disable_if< is_same< typename remove_cv< FunT >::type, this_type >, int >::type = 0) :
+ m_pImpl(new impl< typename remove_cv< FunT >::type >(fun))
+ {
+ }
+#endif
+
+ //! Constructor from NULL
+#if !defined(BOOST_NO_NULLPTR) && !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_NULLPTR) || 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 = that;
+ this->swap(tmp);
+ return *this;
+ }
+ //! Assignment of NULL
+#if !defined(BOOST_NO_NULLPTR) && !defined(BOOST_NO_CXX11_NULLPTR)
+ light_function& operator= (std::nullptr_t)
+#else
+ light_function& operator= (int p)
+#endif
+ {
+#if defined(BOOST_NO_NULLPTR) || defined(BOOST_NO_CXX11_NULLPTR)
+ BOOST_ASSERT(p == 0);
+#endif
+ clear();
+ return *this;
+ }
+#if !defined(BOOST_NO_RVALUE_REFERENCES) && !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< mpl::or_< move_detail::is_rv< FunT >, is_same< FunT, this_type > >, 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_LOG_EXPLICIT_OPERATOR_BOOL()
+ 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
+ {
+ register 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)(impl_base* BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), ArgT));
+ const invoke_type invoke;
+
+ typedef impl_base* (*clone_type)(const impl_base*);
+ const clone_type clone;
+
+ typedef void (*destroy_type)(impl_base*);
+ const destroy_type destroy;
+
+ impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr)
+ {
+ }
+ };
+
+#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_RVALUE_REFERENCES) && !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(fun)
+ {
+ }
+#endif // !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+ static void destroy_impl(impl_base* self)
+ {
+ delete static_cast< impl* >(self);
+ }
+ static impl_base* clone_impl(const impl_base* self)
+ {
+ return new impl(static_cast< const impl* >(self)->m_Function);
+ }
+ static result_type invoke_impl(impl_base* self BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg))
+ {
+ static_cast< impl* >(self)->m_Function(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg));
+ }
+ };
+
+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_RVALUE_REFERENCES) && !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< mpl::or_< move_detail::is_rv< FunT >, is_same< FunT, this_type > >, int >::type = 0) :
+ m_pImpl(new impl< FunT >(fun))
+ {
+ }
+ template< typename FunT >
+ light_function(rv< FunT > const& fun, typename disable_if< is_same< typename remove_cv< FunT >::type, this_type >, int >::type = 0) :
+ m_pImpl(new impl< typename remove_cv< FunT >::type >(fun))
+ {
+ }
+#endif
+
+ //! Constructor from NULL
+#if !defined(BOOST_NO_NULLPTR) && !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_NULLPTR) || 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 = that;
+ this->swap(tmp);
+ return *this;
+ }
+ //! Assignment of NULL
+#if !defined(BOOST_NO_NULLPTR) && !defined(BOOST_NO_CXX11_NULLPTR)
+ light_function& operator= (std::nullptr_t)
+#else
+ light_function& operator= (int p)
+#endif
+ {
+#if defined(BOOST_NO_NULLPTR) || defined(BOOST_NO_CXX11_NULLPTR)
+ BOOST_ASSERT(p == 0);
+#endif
+ clear();
+ return *this;
+ }
+#if !defined(BOOST_NO_RVALUE_REFERENCES) && !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< mpl::or_< move_detail::is_rv< FunT >, is_same< FunT, this_type > >, 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_LOG_EXPLICIT_OPERATOR_BOOL()
+ 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
+ {
+ register impl_base* p = m_pImpl;
+ m_pImpl = that.m_pImpl;
+ that.m_pImpl = p;
+ }
+};

Added: trunk/boost/log/detail/light_rw_mutex.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/light_rw_mutex.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,208 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_LOG_DELETED_FUNCTION(light_rw_mutex(light_rw_mutex const&))
+ BOOST_LOG_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_LOG_DELETED_FUNCTION(light_rw_mutex(light_rw_mutex const&))
+ BOOST_LOG_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_LOG_DELETED_FUNCTION(light_rw_mutex(light_rw_mutex const&))
+ BOOST_LOG_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_

Added: trunk/boost/log/detail/locking_ptr.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/locking_ptr.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,157 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_
+
+#include <boost/shared_ptr.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/utility/explicit_operator_bool.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+ //! Shared lock object to support locking_ptr
+ struct BOOST_LOG_NO_VTABLE locking_ptr_counter_base
+ {
+ unsigned int m_RefCounter;
+
+ locking_ptr_counter_base() : m_RefCounter(0)
+ {
+ }
+
+ virtual ~locking_ptr_counter_base() {}
+ virtual void lock() = 0;
+ virtual bool try_lock() = 0;
+ virtual void unlock() = 0;
+
+ private:
+ locking_ptr_counter_base(locking_ptr_counter_base const&);
+ locking_ptr_counter_base& operator= (locking_ptr_counter_base const&);
+ };
+
+ struct try_lock_tag {};
+ const try_lock_tag try_lock = {};
+
+ //! A pointer type that locks the backend until it's destroyed
+ template< typename T >
+ class locking_ptr
+ {
+ public:
+ //! Pointed type
+ typedef T element_type;
+
+ private:
+ //! The pointer to the backend
+ shared_ptr< element_type > m_pElement;
+ //! Reference to the shared lock control object
+ locking_ptr_counter_base* m_pLock;
+
+ public:
+ //! Constructor
+ locking_ptr(shared_ptr< element_type > const& p, locking_ptr_counter_base& l)
+ : m_pElement(p), m_pLock(&l)
+ {
+ if (m_pLock->m_RefCounter == 0)
+ m_pLock->lock();
+ ++m_pLock->m_RefCounter;
+ }
+ //! Constructor
+ locking_ptr(shared_ptr< element_type > const& p, locking_ptr_counter_base& l, try_lock_tag const&)
+ : m_pElement(p), m_pLock(&l)
+ {
+ if (m_pLock->m_RefCounter > 0 || m_pLock->try_lock())
+ {
+ ++m_pLock->m_RefCounter;
+ }
+ else
+ {
+ 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->m_RefCounter;
+ }
+ //! Destructor
+ ~locking_ptr()
+ {
+ if (m_pLock && --m_pLock->m_RefCounter == 0)
+ m_pLock->unlock();
+ }
+
+ //! Assignment
+ locking_ptr& operator= (locking_ptr that)
+ {
+ this->swap(that);
+ return *this;
+ }
+
+ //! Indirection
+ element_type* operator-> () const { return m_pElement.get(); }
+ //! Dereferencing
+ element_type& operator* () const { return *m_pElement; }
+
+ //! Accessor to the raw pointer
+ element_type* get() const { return m_pElement.get(); }
+
+ //! Checks for null pointer
+ BOOST_LOG_EXPLICIT_OPERATOR_BOOL()
+ //! Checks for null pointer
+ bool operator! () const { return !m_pElement; }
+
+ //! Swaps two pointers
+ void swap(locking_ptr& that)
+ {
+ m_pElement.swap(that.m_pElement);
+ register locking_ptr_counter_base* p = m_pLock;
+ m_pLock = that.m_pLock;
+ that.m_pLock = p;
+ }
+ };
+
+ //! Free raw pointer getter to assist generic programming
+ template< typename T >
+ inline T* get_pointer(locking_ptr< T > const& p)
+ {
+ return p.get();
+ }
+ //! Free swap operation
+ template< typename T >
+ inline void swap(locking_ptr< T >& left, locking_ptr< T >& right)
+ {
+ 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_

Added: trunk/boost/log/detail/locks.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/locks.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,180 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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(T*, void (T::*)() = &T::lock, void (T::*)() = &T::unlock);
+ static false_type check(void*);
+
+ enum value_t { value = sizeof(check((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(T*, void (T::*)() = &T::lock_shared, void (T::*)() = &T::unlock_shared);
+ static false_type check(void*);
+
+ enum value_t { value = sizeof(check((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_

Added: trunk/boost/log/detail/named_scope_fmt_pp.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/named_scope_fmt_pp.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,82 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_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_LOG_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)));
+}

Added: trunk/boost/log/detail/native_typeof.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/native_typeof.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,63 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if !defined(BOOST_NO_DECLTYPE) && !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_AUTO_DECLARATIONS) && !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 // defined(BOOST_LOG_TYPEOF)
+
+#endif // BOOST_LOG_DETAIL_NATIVE_TYPEOF_HPP_INCLUDED_

Added: trunk/boost/log/detail/parameter_tools.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/parameter_tools.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,114 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_

Added: trunk/boost/log/detail/pp_identity.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/pp_identity.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,27 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#define BOOST_LOG_PP_IDENTITY(z, n, data) data
+
+#endif // BOOST_LOG_DETAIL_PP_IDENTITY_HPP_INCLUDED_

Added: trunk/boost/log/detail/process_id.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/process_id.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,60 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_

Added: trunk/boost/log/detail/setup_config.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/setup_config.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,61 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_

Added: trunk/boost/log/detail/singleton.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/singleton.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,89 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_LOG_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_LOG_DELETED_FUNCTION(lazy_singleton(lazy_singleton const&))
+ BOOST_LOG_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_

Added: trunk/boost/log/detail/sink_init_helpers.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/sink_init_helpers.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,118 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_

Added: trunk/boost/log/detail/snprintf.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/snprintf.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,116 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_SNPRINTF_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_SNPRINTF_HPP_INCLUDED_
+
+#include <cstdio>
+#include <cstdarg>
+#include <boost/log/detail/config.hpp>
+#ifdef BOOST_LOG_USE_WCHAR_T
+#include <cwchar>
+#endif // BOOST_LOG_USE_WCHAR_T
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_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)
+
+# if _MSC_VER >= 1400
+
+// MSVC 2005 and later provide the safe-CRT implementation of the conforming snprintf
+inline int vsnprintf(char* buf, std::size_t size, const char* format, std::va_list args)
+{
+ return ::vsprintf_s(buf, size, format, args);
+}
+
+# ifdef BOOST_LOG_USE_WCHAR_T
+inline int vswprintf(wchar_t* buf, std::size_t size, const wchar_t* format, std::va_list args)
+{
+ return ::vswprintf_s(buf, size, format, args);
+}
+# endif // BOOST_LOG_USE_WCHAR_T
+
+# else // _MSC_VER >= 1400
+
+// MSVC prior to 2005 had a non-conforming extension _vsnprintf, that sometimes did not put a terminating '\0'
+inline int vsnprintf(char* buf, std::size_t size, const char* format, std::va_list args)
+{
+ register int n = _vsnprintf(buf, size - 1, format, args);
+ 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)
+{
+ register int n = _vsnwprintf(buf, size - 1, format, args);
+ buf[size - 1] = L'\0';
+ return n;
+}
+# endif // BOOST_LOG_USE_WCHAR_T
+
+# endif // _MSC_VER >= 1400
+
+inline int snprintf(char* buf, std::size_t size, const char* format, ...)
+{
+ std::va_list args;
+ va_start(args, format);
+ register 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);
+ register 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_

Added: trunk/boost/log/detail/spin_mutex.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/spin_mutex.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,268 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifndef BOOST_LOG_NO_THREADS
+
+#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 __asm { nop }
+# elif _MSC_VER >= 1310
+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)
+ register unsigned int pause_count = initial_pause;
+#endif
+ while (!try_lock())
+ {
+#if defined(BOOST_LOG_PAUSE_OP)
+ if (pause_count < max_pause)
+ {
+ for (register 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_LOG_DELETED_FUNCTION(spin_mutex(spin_mutex const&))
+ BOOST_LOG_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()
+ {
+ BOOST_VERIFY(pthread_spin_init(&m_State, PTHREAD_PROCESS_PRIVATE) == 0);
+ }
+ ~spin_mutex()
+ {
+ pthread_spin_destroy(&m_State);
+ }
+ bool try_lock()
+ {
+ return (pthread_spin_trylock(&m_State) == 0);
+ }
+ void lock()
+ {
+ BOOST_VERIFY(pthread_spin_lock(&m_State) == 0);
+ }
+ void unlock()
+ {
+ pthread_spin_unlock(&m_State);
+ }
+
+ // Non-copyable
+ BOOST_LOG_DELETED_FUNCTION(spin_mutex(spin_mutex const&))
+ BOOST_LOG_DELETED_FUNCTION(spin_mutex& operator= (spin_mutex const&))
+};
+
+#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()
+ {
+ BOOST_VERIFY(pthread_mutex_init(&m_State, NULL) == 0);
+ }
+ ~spin_mutex()
+ {
+ pthread_mutex_destroy(&m_State);
+ }
+ bool try_lock()
+ {
+ return (pthread_mutex_trylock(&m_State) == 0);
+ }
+ void lock()
+ {
+ BOOST_VERIFY(pthread_mutex_lock(&m_State) == 0);
+ }
+ void unlock()
+ {
+ pthread_mutex_unlock(&m_State);
+ }
+
+ // Non-copyable
+ BOOST_LOG_DELETED_FUNCTION(spin_mutex(spin_mutex const&))
+ BOOST_LOG_DELETED_FUNCTION(spin_mutex& operator= (spin_mutex const&))
+};
+
+#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_

Added: trunk/boost/log/detail/tagged_integer.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/tagged_integer.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,147 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_

Added: trunk/boost/log/detail/thread_id.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/thread_id.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,65 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_process
+
+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_

Added: trunk/boost/log/detail/thread_specific.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/thread_specific.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,116 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_LOG_DELETED_FUNCTION(thread_specific_base(thread_specific_base const&))
+ BOOST_LOG_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_LOG_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_

Added: trunk/boost/log/detail/threadsafe_queue.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/threadsafe_queue.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,279 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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 Swappable (i.e. there should be an efficient \c swap implementation for this type).
+ *
+ * The last requirement is not mandatory but is crucial for decent performance. In future
+ * it may be replaced with Moveable requirement.
+ */
+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))
+ {
+ register 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;
+ }
+
+private:
+ // Copying and assignment is prohibited
+ threadsafe_queue(threadsafe_queue const&);
+ 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_

Added: trunk/boost/log/detail/timestamp.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/timestamp.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,99 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_

Added: trunk/boost/log/detail/trivial_keyword.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/trivial_keyword.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,43 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_

Added: trunk/boost/log/detail/unary_function_terminal.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/unary_function_terminal.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,151 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/custom_terminal_spec.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+namespace aux {
+
+/*!
+ * \brief An adapter for an unary function to be used as a terminal in a Boost.Phoenix expression
+ *
+ * This class is an adapter between Boost.Phoenix expression invokation protocol and
+ * an unary function. It forwards the call to the base function, passing only the first argument
+ * from the original call. This allows to 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 ContextT >
+ struct result< this_type(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::result_of< function_type(typename fusion::result_of::at_c< args_type, 0 >::type) >::type type;
+ };
+
+ template< typename ContextT >
+ struct result< const this_type(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::result_of< const 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_LOG_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_

Added: trunk/boost/log/detail/unhandled_exception_count.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/unhandled_exception_count.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_

Added: trunk/boost/log/detail/value_ref_visitation.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/value_ref_visitation.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,107 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_LOG_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

Added: trunk/boost/log/detail/visible_type.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/detail/visible_type.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,48 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/libs/log/doc/log.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_LOG_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_LOG_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_

Added: trunk/boost/log/exceptions.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/exceptions.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,387 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_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_

Added: trunk/boost/log/expressions.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,38 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#endif // BOOST_LOG_EXPRESSIONS_HPP_INCLUDED_

Added: trunk/boost/log/expressions/attr.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/attr.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,285 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/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_LOG_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 ContextT >
+ struct result< this_type(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::result_of< value_extractor_type(attribute_name const&, typename fusion::result_of::at_c< args_type, 0 >::type) >::type type;
+ };
+
+ template< typename ContextT >
+ struct result< const this_type(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::result_of< const 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_LOG_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_LOG_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_LOG_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_

Added: trunk/boost/log/expressions/attr_fwd.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/attr_fwd.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,69 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/expressions/filter.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/filter.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,165 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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
+ */
+ 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_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template< typename FunT >
+ filter(FunT const& fun)
+#else
+ template< typename FunT >
+ filter(FunT const& fun, typename disable_if< move_detail::is_rv< FunT >, int >::type = 0)
+#endif
+ : m_Filter(fun)
+ {
+ }
+
+ /*!
+ * Move assignment.
+ */
+ 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_RVALUE_REFERENCES) && !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_

Added: trunk/boost/log/expressions/formatter.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/formatter.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,196 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/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_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * 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&, stream_type&) > formatter_type;
+
+ //! Default formatter, always returns \c true
+ struct default_formatter
+ {
+ typedef void result_type;
+
+ default_formatter() : m_MessageName(expressions::tag::message::get_name())
+ {
+ }
+
+ result_type operator() (record_view const& rec, stream_type& strm) const
+ {
+ boost::log::visit< expressions::tag::message::value_type >(m_MessageName, rec, boost::log::bind_output(strm));
+ }
+
+ private:
+ const attribute_name m_MessageName;
+ };
+
+private:
+ //! Formatter function
+ formatter_type m_Formatter;
+
+public:
+ /*!
+ * Default constructor. Creates a formatter that only outputs log message.
+ */
+ basic_formatter() : m_Formatter(default_formatter())
+ {
+ }
+ /*!
+ * Copy constructor
+ */
+ basic_formatter(basic_formatter const& that) : m_Formatter(that.m_Formatter)
+ {
+ }
+ /*!
+ * Move constructor
+ */
+ 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_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template< typename FunT >
+ basic_formatter(FunT const& fun)
+#else
+ template< typename FunT >
+ basic_formatter(FunT const& fun, typename disable_if< move_detail::is_rv< FunT >, int >::type = 0)
+#endif
+ : m_Formatter(fun)
+ {
+ }
+
+ /*!
+ * Move assignment.
+ */
+ 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_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template< typename FunT >
+ basic_formatter& operator= (FunT const& fun)
+#else
+ template< typename FunT >
+ typename disable_if< is_same< typename remove_cv< FunT >::type, this_type >, this_type& >::type
+ operator= (FunT const& fun)
+#endif
+ {
+ this_type(fun).swap(*this);
+ return *this;
+ }
+
+ /*!
+ * 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, strm);
+ }
+
+ /*!
+ * Resets the formatter to the default. The default formatter only outputs message text.
+ */
+ void reset()
+ {
+ m_Formatter = default_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_

Added: trunk/boost/log/expressions/formatters.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/formatters.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,38 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_HPP_INCLUDED_

Added: trunk/boost/log/expressions/formatters/c_decorator.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/formatters/c_decorator.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,270 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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)
+ {
+ return static_cast< std::size_t >(
+ boost::log::aux::snprintf(buf, N, "\\x%0.2X", static_cast< unsigned int >(static_cast< uint8_t >(c))));
+ }
+};
+#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;
+ register 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);
+ }
+
+ return static_cast< std::size_t >(boost::log::aux::swprintf(buf, N, format, val));
+ }
+};
+#endif // BOOST_LOG_USE_WCHAR_T
+
+template< typename CharT >
+struct c_decorator_gen
+{
+ typedef CharT char_type;
+
+ template< typename SubactorT >
+ BOOST_LOG_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_LOG_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_LOG_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_LOG_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_

Added: trunk/boost/log/expressions/formatters/char_decorator.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/formatters/char_decorator.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,650 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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 ContextT >
+ struct result< this_type(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;
+ };
+
+ template< typename ContextT >
+ struct result< const this_type(ContextT) >
+ {
+ typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type;
+ typedef typename phoenix::evaluator::impl<
+ typename LeftT::proto_base_expr const&,
+ 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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_

Added: trunk/boost/log/expressions/formatters/csv_decorator.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/formatters/csv_decorator.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,140 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_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_LOG_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_

Added: trunk/boost/log/expressions/formatters/date_time.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/formatters/date_time.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,325 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_DATE_TIME_HPP_INCLUDED_

Added: trunk/boost/log/expressions/formatters/format.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/formatters/format.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,128 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_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_LOG_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_LOG_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_

Added: trunk/boost/log/expressions/formatters/if.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/formatters/if.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,337 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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 ContextT >
+ struct result< this_type(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;
+ };
+
+ template< typename ContextT >
+ struct result< const this_type(ContextT) >
+ {
+ typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type;
+ typedef typename phoenix::evaluator::impl<
+ typename LeftT::proto_base_expr const&,
+ 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_LOG_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 ContextT >
+ struct result< this_type(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;
+ };
+
+ template< typename ContextT >
+ struct result< const this_type(ContextT) >
+ {
+ typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type;
+ typedef typename phoenix::evaluator::impl<
+ typename LeftT::proto_base_expr const&,
+ 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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_

Added: trunk/boost/log/expressions/formatters/named_scope.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/formatters/named_scope.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,602 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/detail/header.hpp>
+
+#ifdef BOOST_LOG_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 {
+
+//! Parses the named scope format string and constructs the formatter function
+template< typename CharT >
+BOOST_LOG_API boost::log::aux::light_function< void (basic_formatting_ostream< CharT >&, attributes::named_scope::value_type::value_type const&) >
+parse_named_scope_format(const CharT* begin, const CharT* end);
+
+//! 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;
+ //! 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, value_type::size_type depth, scope_iteration_direction direction) :
+ m_element_formatter(element_formatter),
+ m_delimiter(delimiter),
+ 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_depth(that.m_depth),
+ m_direction(that.m_direction)
+ {
+ }
+
+ //! Formatting operator
+ result_type operator() (stream_type& strm, value_type const& scopes) const
+ {
+ if (m_direction == expressions::forward)
+ format_forward(strm, scopes);
+ else
+ format_reverse(strm, scopes);
+ }
+
+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_delimiter;
+
+ 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_delimiter << "...";
+ }
+ }
+};
+
+} // 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, value_type::size_type depth, scope_iteration_direction direction) :
+ m_name(name), m_formatter(aux::parse_named_scope_format(element_format), delimiter, 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_LOG_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_LOG_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 correct default delimiter depending on the character type
+template< typename CharT >
+struct default_scope_delimiter;
+
+#ifdef BOOST_LOG_USE_CHAR
+template< >
+struct default_scope_delimiter< char >
+{
+ static const char* forward() { return "->"; }
+ static const char* reverse() { return "<-"; }
+};
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+template< >
+struct default_scope_delimiter< wchar_t >
+{
+ static const wchar_t* forward() { return L"->"; }
+ static const wchar_t* reverse() { return L"<-"; }
+};
+#endif
+
+template< typename CharT, template< typename > class ActorT, typename FallbackPolicyT, typename ArgsT >
+BOOST_LOG_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;
+ scope_iteration_direction dir = args[keywords::iteration | expressions::forward];
+ const CharT* default_delimiter = (dir == expressions::forward ? default_scope_delimiter< CharT >::forward() : default_scope_delimiter< CharT >::reverse());
+ typename actor_type::base_type act =
+ {{
+ terminal_type
+ (
+ name,
+ fallback,
+ args[keywords::format],
+ args[keywords::delimiter | default_delimiter],
+ 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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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, 4)
+# 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 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_

Added: trunk/boost/log/expressions/formatters/stream.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/formatters/stream.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,53 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/expressions/formatters/wrap_formatter.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/formatters/wrap_formatter.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,349 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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 ContextT >
+ struct result< this_type(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;
+ };
+
+ template< typename ContextT >
+ struct result< const this_type(ContextT) >
+ {
+ typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type;
+ typedef typename phoenix::evaluator::impl<
+ typename LeftT::proto_base_expr const&,
+ 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_LOG_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_LOG_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_LOG_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_LOG_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_

Added: trunk/boost/log/expressions/formatters/xml_decorator.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/formatters/xml_decorator.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,138 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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;", "&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"'"
+ };
+ 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"&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_LOG_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_LOG_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_

Added: trunk/boost/log/expressions/is_keyword_descriptor.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/is_keyword_descriptor.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,67 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/expressions/keyword.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/keyword.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,258 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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 addidionally
+ * 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_

Added: trunk/boost/log/expressions/keyword_fwd.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/keyword_fwd.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,53 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/expressions/message.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/message.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,130 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/expressions/predicates.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/predicates.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,34 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#endif // BOOST_LOG_EXPRESSIONS_PREDICATES_HPP_INCLUDED_

Added: trunk/boost/log/expressions/predicates/begins_with.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/predicates/begins_with.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,129 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_TEMPLATE_ALIASES) && !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_TEMPLATE_ALIASES) && !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_TEMPLATE_ALIASES) && !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_LOG_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_LOG_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_LOG_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_

Added: trunk/boost/log/expressions/predicates/channel_severity_filter.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/predicates/channel_severity_filter.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,572 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_

Added: trunk/boost/log/expressions/predicates/contains.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/predicates/contains.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,129 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_TEMPLATE_ALIASES) && !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_TEMPLATE_ALIASES) && !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_TEMPLATE_ALIASES) && !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_LOG_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_LOG_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_LOG_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_

Added: trunk/boost/log/expressions/predicates/ends_with.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/predicates/ends_with.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,129 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_TEMPLATE_ALIASES) && !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_TEMPLATE_ALIASES) && !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_TEMPLATE_ALIASES) && !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_LOG_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_LOG_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_LOG_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_

Added: trunk/boost/log/expressions/predicates/has_attr.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/predicates/has_attr.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,172 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_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_LOG_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_LOG_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_

Added: trunk/boost/log/expressions/predicates/is_debugger_present.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/predicates/is_debugger_present.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,107 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/expressions/predicates/is_in_range.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/predicates/is_in_range.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,133 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_TEMPLATE_ALIASES) && !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_TEMPLATE_ALIASES) && !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_TEMPLATE_ALIASES) && !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_LOG_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_LOG_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_LOG_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_

Added: trunk/boost/log/expressions/predicates/matches.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/predicates/matches.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,128 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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.
+ */
+#if !defined(BOOST_NO_TEMPLATE_ALIASES) && !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template< typename T, typename RegexT, typename FallbackPolicyT = fallback_to_none >
+using attribute_matches = aux::attribute_predicate< T, RegexT, matches_fun, FallbackPolicyT >;
+
+#else // !defined(BOOST_NO_TEMPLATE_ALIASES) && !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template< typename T, typename RegexT, typename FallbackPolicyT = fallback_to_none >
+class attribute_matches :
+ public aux::attribute_predicate< T, RegexT, matches_fun, FallbackPolicyT >
+{
+ typedef aux::attribute_predicate< T, RegexT, 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, 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, rex, arg)
+ {
+ }
+};
+
+#endif // !defined(BOOST_NO_TEMPLATE_ALIASES) && !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, matches the specified regular expression.
+ */
+template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename RegexT >
+BOOST_LOG_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_LOG_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_LOG_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_

Added: trunk/boost/log/expressions/record.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/expressions/record.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,50 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/auto_flush.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/auto_flush.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/channel.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/channel.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/delimiter.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/delimiter.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/depth.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/depth.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/facility.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/facility.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/file_name.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/file_name.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/filter.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/filter.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/format.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/format.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/ident.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/ident.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/ip_version.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/ip_version.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/iteration.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/iteration.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/log_name.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/log_name.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/log_source.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/log_source.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/max_size.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/max_size.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/message_file.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/message_file.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/min_free_space.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/min_free_space.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/open_mode.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/open_mode.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/order.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/order.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/ordering_window.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/ordering_window.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/registration.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/registration.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/rotation_size.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/rotation_size.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/scan_method.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/scan_method.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/severity.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/severity.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/start_thread.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/start_thread.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/target.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/target.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/time_based_rotation.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/time_based_rotation.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/keywords/use_impl.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/keywords/use_impl.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/sinks.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,47 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#endif // BOOST_LOG_SINKS_HPP_INCLUDED_

Added: trunk/boost/log/sinks/async_frontend.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks/async_frontend.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,470 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_LOG_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/thread/locks.hpp>
+#include <boost/thread/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,
+ private boost::log::aux::locking_ptr_counter_base,
+ 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::mutex backend_mutex_type;
+ //! Frontend syncronization 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 > 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,
+ static_cast< boost::log::aux::locking_ptr_counter_base& >(*this));
+ }
+
+ /*!
+ * 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);
+ }
+
+ // locking_ptr_counter_base methods
+ void lock() { m_BackendMutex.lock(); }
+ bool try_lock() { return m_BackendMutex.try_lock(); }
+ void unlock() { m_BackendMutex.unlock(); }
+
+ //! The record feeding loop
+ void do_feed_records()
+ {
+ while (!m_StopRequested)
+ {
+ record_view rec;
+ register 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_

Added: trunk/boost/log/sinks/attribute_mapping.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks/attribute_mapping.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,290 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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 successfull, 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_

Added: trunk/boost/log/sinks/basic_sink_backend.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks/basic_sink_backend.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,97 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_DEFAULTED_FUNCTION(basic_sink_backend(), {})
+
+ BOOST_LOG_DELETED_FUNCTION(basic_sink_backend(basic_sink_backend const&))
+ BOOST_LOG_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_

Added: trunk/boost/log/sinks/basic_sink_frontend.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks/basic_sink_frontend.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,523 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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>
+#include <boost/concept_check.hpp>
+#endif // !defined(BOOST_LOG_NO_THREADS)
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_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()();
+ }
+#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()();
+ }
+#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_

Added: trunk/boost/log/sinks/block_on_overflow.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks/block_on_overflow.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,148 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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;
+
+private:
+ // Copying prohibited
+ block_on_overflow(block_on_overflow const&);
+ block_on_overflow& operator= (block_on_overflow const&);
+
+public:
+ /*!
+ * Default constructor.
+ */
+ 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();
+ }
+ }
+#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_

Added: trunk/boost/log/sinks/bounded_fifo_queue.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks/bounded_fifo_queue.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,194 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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();
+ if (size == MaxQueueSizeV)
+ 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();
+ if (size == MaxQueueSizeV)
+ 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_

Added: trunk/boost/log/sinks/bounded_ordering_queue.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks/bounded_ordering_queue.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,318 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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/move/core.hpp>
+#include <boost/move/utility.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/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;
+
+ //! Log record with enqueueing timestamp
+ class enqueued_record
+ {
+ BOOST_COPYABLE_AND_MOVABLE(enqueued_record)
+
+ public:
+ //! Ordering predicate
+ 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;
+ }
+ };
+
+ typedef std::priority_queue<
+ enqueued_record,
+ std::vector< enqueued_record >,
+ typename enqueued_record::order
+ > 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();
+ if (size == MaxQueueSizeV)
+ 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();
+ if (size == MaxQueueSizeV)
+ 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();
+ if (size == MaxQueueSizeV)
+ 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_

Added: trunk/boost/log/sinks/debug_output_backend.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks/debug_output_backend.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,93 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/sinks/drop_on_overflow.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks/drop_on_overflow.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,80 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/sinks/event_log_backend.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks/event_log_backend.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,662 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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 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_

Added: trunk/boost/log/sinks/event_log_constants.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks/event_log_constants.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,88 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/sinks/frontend_requirements.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks/frontend_requirements.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,119 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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
+ * is 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_

Added: trunk/boost/log/sinks/sink.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks/sink.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,115 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_DELETED_FUNCTION(sink(sink const&))
+ BOOST_LOG_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_

Added: trunk/boost/log/sinks/sync_frontend.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks/sync_frontend.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,177 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/thread/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,
+ private boost::log::aux::locking_ptr_counter_base
+{
+ typedef typename aux::make_sink_frontend_base< SinkBackendT >::type base_type;
+
+private:
+ //! Synchronization mutex type
+ typedef boost::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 > 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,
+ static_cast< boost::log::aux::locking_ptr_counter_base& >(*this));
+ }
+
+ /*!
+ * 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);
+ }
+
+private:
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ // locking_ptr_counter_base methods
+ void lock() { m_BackendMutex.lock(); }
+ bool try_lock() { return m_BackendMutex.try_lock(); }
+ void unlock() { m_BackendMutex.unlock(); }
+#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_SYNC_FRONTEND_HPP_INCLUDED_

Added: trunk/boost/log/sinks/syslog_backend.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks/syslog_backend.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,289 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifndef BOOST_LOG_WITHOUT_SYSLOG
+
+#include <string>
+#include <boost/shared_ptr.hpp>
+#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_

Added: trunk/boost/log/sinks/syslog_constants.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks/syslog_constants.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,101 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/sinks/text_file_backend.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks/text_file_backend.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,539 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/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_LOG_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_LOG_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_LOG_DELETED_FUNCTION(collector(collector const&))
+ BOOST_LOG_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 caution regarding file name pattern in the <tt>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>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_

Added: trunk/boost/log/sinks/text_multifile_backend.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks/text_multifile_backend.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,201 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/sinks/text_ostream_backend.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks/text_ostream_backend.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,124 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/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_LOG_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_

Added: trunk/boost/log/sinks/unbounded_fifo_queue.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks/unbounded_fifo_queue.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,142 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/sinks/unbounded_ordering_queue.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks/unbounded_ordering_queue.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,298 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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/move/core.hpp>
+#include <boost/move/utility.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/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;
+
+ //! Log record with enqueueing timestamp
+ class enqueued_record
+ {
+ BOOST_COPYABLE_AND_MOVABLE(enqueued_record)
+
+ public:
+ //! Ordering predicate
+ 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;
+ }
+ };
+
+ typedef std::priority_queue<
+ enqueued_record,
+ std::vector< enqueued_record >,
+ typename enqueued_record::order
+ > 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_

Added: trunk/boost/log/sinks/unlocked_frontend.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sinks/unlocked_frontend.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,142 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/static_assert.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_LOG_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 intarface 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_

Added: trunk/boost/log/sources/basic_logger.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sources/basic_logger.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,743 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/shared_ptr.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_LOG_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< 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< 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_LOG_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 a MPL type sequence, where each element is an 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_LOG_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_

Added: trunk/boost/log/sources/channel_feature.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sources/channel_feature.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,242 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/sources/channel_logger.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sources/channel_logger.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,325 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/sources/exception_handler_feature.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sources/exception_handler_feature.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,252 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/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_LOG_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_

Added: trunk/boost/log/sources/features.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sources/features.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,150 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
+#include <boost/preprocessor/repetition/enum_shifted_binary_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_VARIADIC_TEMPLATES) || 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_

Added: trunk/boost/log/sources/global_logger_storage.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sources/global_logger_storage.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,206 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/shared_ptr.hpp>
+#include <boost/make_shared.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_LOG_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_LOG_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_LOG_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_LOG_DELETED_FUNCTION(global_storage())
+ BOOST_LOG_DELETED_FUNCTION(global_storage(global_storage const&))
+ BOOST_LOG_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_

Added: trunk/boost/log/sources/logger.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sources/logger.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,103 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/sources/record_ostream.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sources/record_ostream.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,335 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/log/utility/explicit_operator_bool.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_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_LOG_EXPLICIT_OPERATOR_BOOL()
+
+ /*!
+ * 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_LOG_DELETED_FUNCTION(basic_record_ostream(basic_record_ostream const&))
+ BOOST_LOG_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_LOG_DELETED_FUNCTION(stream_provider())
+ BOOST_LOG_DELETED_FUNCTION(stream_provider(stream_provider const&))
+ BOOST_LOG_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_LOG_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_

Added: trunk/boost/log/sources/severity_channel_logger.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sources/severity_channel_logger.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,309 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/sources/severity_feature.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sources/severity_feature.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,310 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/intrusive_ptr.hpp>
+#include <boost/static_assert.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_LOG_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_LOG_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_

Added: trunk/boost/log/sources/severity_logger.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sources/severity_logger.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,325 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/sources/threading_models.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/sources/threading_models.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,125 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/support/date_time.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/support/date_time.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,548 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_LOG_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_

Added: trunk/boost/log/support/exception.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/support/exception.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,72 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/support/regex.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/support/regex.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,74 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <boost/regex.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/utility/functional/matches.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! The trait verifies if the type can be converted to a Boost.Regex expression
+template< typename T >
+struct is_regex< T, true >
+{
+private:
+ typedef char yes_type;
+ struct no_type { char dummy[2]; };
+
+ template< typename CharT, typename TraitsT >
+ static yes_type check(basic_regex< CharT, TraitsT > const&);
+ static no_type check(...);
+ static T& get_T();
+
+public:
+ enum { value = sizeof(check(get_T())) == sizeof(yes_type) };
+ typedef mpl::bool_< value > type;
+};
+
+//! The regex matching functor implementation
+template< >
+struct matches_fun_impl< boost_regex_expression_tag >
+{
+ template< typename StringT, typename CharT, typename TraitsT >
+ static bool matches(
+ StringT const& str,
+ basic_regex< CharT, TraitsT > const& expr,
+ match_flag_type flags = match_default)
+ {
+ return boost::regex_match(str.begin(), str.end(), 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_

Added: trunk/boost/log/support/spirit_classic.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/support/spirit_classic.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,96 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/log/detail/config.hpp>
+#include <boost/log/utility/functional/matches.hpp>
+
+#ifdef BOOST_LOG_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).
+ */
+#warning 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.
+#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 {
+
+//! The trait verifies if the type can be converted to a Boost.Spirit (classic) parser
+template< typename T >
+struct is_spirit_classic_parser< T, true >
+{
+private:
+ typedef char yes_type;
+ struct no_type { char dummy[2]; };
+
+ template< typename U >
+ static yes_type check(spirit::classic::parser< U > const&);
+ static no_type check(...);
+ static T& get_T();
+
+public:
+ enum { value = sizeof(check(get_T())) == sizeof(yes_type) };
+ typedef mpl::bool_< value > type;
+};
+
+//! The matching functor implementation
+template< >
+struct matches_fun_impl< boost_spirit_classic_expression_tag >
+{
+ template< typename StringT, typename ParserT >
+ static bool matches(
+ StringT const& str,
+ ParserT 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_

Added: trunk/boost/log/support/spirit_qi.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/support/spirit_qi.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,65 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/log/detail/config.hpp>
+#include <boost/log/utility/functional/matches.hpp>
+#include <boost/spirit/include/qi_parse.hpp>
+#include <boost/spirit/include/qi_domain.hpp>
+#include <boost/spirit/include/support_component.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! The trait verifies if the type can be converted to a Boost.Spirit.Qi parser
+template< typename T >
+struct is_spirit_qi_parser< T, true > :
+ public spirit::traits::is_component< spirit::qi::domain, T >
+{
+};
+
+//! The matching functor implementation
+template< >
+struct matches_fun_impl< boost_spirit_qi_expression_tag >
+{
+ template< typename StringT, typename ParserT >
+ static bool matches(
+ StringT const& str,
+ ParserT 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_

Added: trunk/boost/log/support/xpressive.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/support/xpressive.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,94 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <boost/mpl/bool.hpp>
+#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_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! The trait verifies if the type can be converted to a Boost.Xpressive regex
+template< typename T >
+struct is_xpressive_regex< T, true >
+{
+private:
+ typedef char yes_type;
+ struct no_type { char dummy[2]; };
+
+ template< typename U >
+ static yes_type check(xpressive::basic_regex< U > const&);
+ static no_type check(...);
+ static T& get_T();
+
+public:
+ enum { value = sizeof(check(get_T())) == sizeof(yes_type) };
+ typedef mpl::bool_< value > type;
+};
+
+//! The regex matching functor implementation
+template< >
+struct matches_fun_impl< boost_xpressive_expression_tag >
+{
+ 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 StringT >
+ static bool matches(
+ StringT const& str,
+ xpressive::basic_regex< typename StringT::value_type* > const& expr,
+ xpressive::regex_constants::match_flag_type flags = xpressive::regex_constants::match_default)
+ {
+ return xpressive::regex_match(str.c_str(), expr, flags);
+ }
+
+ template< typename StringT >
+ static bool matches(
+ StringT const& str,
+ xpressive::basic_regex< typename StringT::value_type const* > const& expr,
+ xpressive::regex_constants::match_flag_type flags = xpressive::regex_constants::match_default)
+ {
+ return xpressive::regex_match(str.c_str(), 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_

Added: trunk/boost/log/trivial.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/trivial.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,112 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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 stringified enumeration value or \c NULL, if the value is not valid
+BOOST_LOG_API const char* to_string(severity_level lvl);
+
+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;
+}
+
+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
+
+//! Trivial logger tag
+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
+#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_

Added: trunk/boost/log/utility/empty_deleter.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/empty_deleter.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,47 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 contains an \c empty_deleter implementation. This is an empty
+ * function object that receives a pointer and does nothing with it.
+ * Such empty deletion strategy may be convenient, for example, when
+ * constructing <tt>shared_ptr</tt>s that point to some object that should not be
+ * deleted (i.e. a variable on the stack or some global singleton, like <tt>std::cout</tt>).
+ */
+
+#ifndef BOOST_LOG_UTILITY_EMPTY_DELETER_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_EMPTY_DELETER_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+//! A function object that does nothing and can be used as an empty deleter for \c shared_ptr
+struct empty_deleter
+{
+ //! Function object result type
+ typedef void result_type;
+ /*!
+ * Does nothing
+ */
+ void operator() (const volatile void*) const {}
+};
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_UTILITY_EMPTY_DELETER_HPP_INCLUDED_

Added: trunk/boost/log/utility/exception_handler.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/exception_handler.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,354 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <exception>
+#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_LOG_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_

Added: trunk/boost/log/utility/explicit_operator_bool.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/explicit_operator_bool.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,87 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 defines a compatibility macro that implements an unspecified
+ * \c bool operator idiom, which is superceded with explicit conversion operators in
+ * C++0x.
+ */
+
+#ifndef BOOST_LOG_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(BOOST_LOG_DOXYGEN_PASS) || (!defined(BOOST_NO_EXPLICIT_CONVERSION_OPERATORS) && !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS))
+
+/*!
+ * \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_LOG_FORCEINLINE explicit operator bool () const\
+ {\
+ return !this->operator! ();\
+ }
+
+#elif !defined(BOOST_LOG_NO_UNSPECIFIED_BOOL)
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+ struct unspecified_bool
+ {
+ // NOTE TO THE USER: If you see this in error messages then you tried
+ // to apply an unsupported operator on the object that supports
+ // explicit conversion to bool.
+ struct OPERATORS_NOT_ALLOWED;
+ static void true_value(OPERATORS_NOT_ALLOWED*) {}
+ };
+ typedef void (*unspecified_bool_type)(unspecified_bool::OPERATORS_NOT_ALLOWED*);
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#define BOOST_LOG_EXPLICIT_OPERATOR_BOOL()\
+ BOOST_LOG_FORCEINLINE operator boost::log::aux::unspecified_bool_type () const\
+ {\
+ if (!this->operator!())\
+ return &boost::log::aux::unspecified_bool::true_value;\
+ else\
+ return 0;\
+ }
+
+#else
+
+#define BOOST_LOG_EXPLICIT_OPERATOR_BOOL()\
+ BOOST_LOG_FORCEINLINE operator bool () const\
+ {\
+ return !this->operator! ();\
+ }
+
+#endif
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_

Added: trunk/boost/log/utility/formatting_ostream.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/formatting_ostream.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,441 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/ref.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/utility/base_from_member.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/detail/parameter_tools.hpp>
+#include <boost/log/utility/string_literal_fwd.hpp>
+#include <boost/log/utility/formatting_ostream_fwd.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+template< typename T, typename R, typename VoidT = void >
+struct enable_basic_formatting_ostream_generic_insert_operator { typedef R type; };
+template< typename T, typename R >
+struct enable_basic_formatting_ostream_generic_insert_operator< T, R, typename T::_has_basic_formatting_ostream_insert_operator > {};
+template< typename T, typename R >
+struct enable_basic_formatting_ostream_generic_insert_operator< T*, R > {};
+template< typename CharT, typename TraitsT, typename AllocatorT, typename R >
+struct enable_basic_formatting_ostream_generic_insert_operator< std::basic_string< CharT, TraitsT, AllocatorT >, R > {};
+template< typename CharT, typename TraitsT, typename R >
+struct enable_basic_formatting_ostream_generic_insert_operator< basic_string_literal< CharT, TraitsT >, R > {};
+
+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 for log records formatting.
+ *
+ * This stream type is used by the library for log record formatting. It implements the standard string stream interface
+ * with a few extensions:
+ *
+ * \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.
+ */
+template< typename CharT, typename TraitsT, typename AllocatorT >
+class basic_formatting_ostream :
+ private base_from_member< boost::log::aux::basic_ostringstreambuf< CharT, TraitsT, AllocatorT > >,
+ public std::basic_ostream< CharT, TraitsT >
+{
+ typedef base_from_member< boost::log::aux::basic_ostringstreambuf< CharT, TraitsT, AllocatorT > > streambuf_base_type;
+
+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;
+
+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:
+ /*!
+ * 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() : ostream_type(&this->streambuf_base_type::member)
+ {
+ 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) :
+ streambuf_base_type(boost::ref(str)),
+ ostream_type(&this->streambuf_base_type::member)
+ {
+ init_stream();
+ }
+
+ /*!
+ * Destructor. Destroys the record, releases any sinks and attribute values that were involved in processing this record.
+ */
+ ~basic_formatting_ostream()
+ {
+ if (this->streambuf_base_type::member.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)
+ {
+ streambuf_base_type::member.attach(str);
+ ostream_type::clear(ostream_type::goodbit);
+ }
+ /*!
+ * Detaches the stream from the string. Any buffered data is flushed to the string.
+ */
+ void detach()
+ {
+ streambuf_base_type::member.detach();
+ ostream_type::clear(ostream_type::badbit);
+ }
+
+ /*!
+ * \returns Reference to the attached string. The string must be attached before calling this method.
+ */
+ string_type const& str()
+ {
+ flush();
+
+ string_type* storage = this->streambuf_base_type::member.storage();
+ BOOST_ASSERT(storage != NULL);
+
+ return *storage;
+ }
+
+ // Stream method overrides
+ basic_formatting_ostream& flush()
+ {
+ ostream_type::flush();
+ return *this;
+ }
+
+ basic_formatting_ostream& seekp(pos_type pos)
+ {
+ ostream_type::seekp(pos);
+ return *this;
+ }
+
+ basic_formatting_ostream& seekp(off_type off, std::ios_base::seekdir dir)
+ {
+ ostream_type::seekp(off, dir);
+ return *this;
+ }
+
+ streambuf_type* rdbuf()
+ {
+ return &this->streambuf_base_type::member;
+ }
+
+ basic_formatting_ostream& put(char_type c)
+ {
+ ostream_type::put(c);
+ return *this;
+ }
+
+ template< typename OtherCharT >
+ typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type
+ put(OtherCharT c)
+ {
+ write(boost::addressof(c), 1);
+ return *this;
+ }
+
+ basic_formatting_ostream& write(const char_type* p, std::streamsize size)
+ {
+ ostream_type::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)
+ {
+ flush();
+
+ string_type* storage = this->streambuf_base_type::member.storage();
+ BOOST_ASSERT(storage != NULL);
+ aux::code_convert(p, static_cast< std::size_t >(size), *storage, this->getloc());
+
+ return *this;
+ }
+
+ basic_formatting_ostream& operator<< (ios_base_manip manip)
+ {
+ *static_cast< ostream_type* >(this) << manip;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (basic_ios_manip manip)
+ {
+ *static_cast< ostream_type* >(this) << manip;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (stream_manip manip)
+ {
+ *static_cast< ostream_type* >(this) << manip;
+ return *this;
+ }
+
+ basic_formatting_ostream& operator<< (char c)
+ {
+ this->put(c);
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (const char* p)
+ {
+ this->write(p, static_cast< std::streamsize >(std::char_traits< char >::length(p)));
+ return *this;
+ }
+
+#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
+ basic_formatting_ostream& operator<< (wchar_t c)
+ {
+ this->put(c);
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (const wchar_t* p)
+ {
+ this->write(p, static_cast< std::streamsize >(std::char_traits< wchar_t >::length(p)));
+ return *this;
+ }
+#endif
+#if !defined(BOOST_NO_CXX11_CHAR16_T)
+ basic_formatting_ostream& operator<< (char16_t c)
+ {
+ this->put(c);
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (const char16_t* p)
+ {
+ this->write(p, static_cast< std::streamsize >(std::char_traits< char16_t >::length(p)));
+ return *this;
+ }
+#endif
+#if !defined(BOOST_NO_CXX11_CHAR32_T)
+ basic_formatting_ostream& operator<< (char32_t c)
+ {
+ this->put(c);
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (const char32_t* p)
+ {
+ this->write(p, static_cast< std::streamsize >(std::char_traits< char32_t >::length(p)));
+ return *this;
+ }
+#endif
+
+ basic_formatting_ostream& operator<< (bool value)
+ {
+ *static_cast< ostream_type* >(this) << value;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (signed char value)
+ {
+ *static_cast< ostream_type* >(this) << value;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (unsigned char value)
+ {
+ *static_cast< ostream_type* >(this) << value;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (short value)
+ {
+ *static_cast< ostream_type* >(this) << value;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (unsigned short value)
+ {
+ *static_cast< ostream_type* >(this) << value;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (int value)
+ {
+ *static_cast< ostream_type* >(this) << value;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (unsigned int value)
+ {
+ *static_cast< ostream_type* >(this) << value;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (long value)
+ {
+ *static_cast< ostream_type* >(this) << value;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (unsigned long value)
+ {
+ *static_cast< ostream_type* >(this) << value;
+ return *this;
+ }
+#if !defined(BOOST_NO_LONG_LONG)
+ basic_formatting_ostream& operator<< (long long value)
+ {
+ *static_cast< ostream_type* >(this) << value;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (unsigned long long value)
+ {
+ *static_cast< ostream_type* >(this) << value;
+ return *this;
+ }
+#endif
+
+ basic_formatting_ostream& operator<< (float value)
+ {
+ *static_cast< ostream_type* >(this) << value;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (double value)
+ {
+ *static_cast< ostream_type* >(this) << value;
+ return *this;
+ }
+ basic_formatting_ostream& operator<< (long double value)
+ {
+ *static_cast< ostream_type* >(this) << value;
+ return *this;
+ }
+
+ basic_formatting_ostream& operator<< (const void* value)
+ {
+ *static_cast< ostream_type* >(this) << value;
+ return *this;
+ }
+
+ basic_formatting_ostream& operator<< (std::basic_streambuf< char_type, traits_type >* buf)
+ {
+ *static_cast< ostream_type* >(this) << buf;
+ return *this;
+ }
+
+ template< typename OtherCharT, typename OtherTraitsT, typename OtherAllocatorT >
+ typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type
+ operator<< (std::basic_string< OtherCharT, OtherTraitsT, OtherAllocatorT > const& str)
+ {
+ this->write(str.c_str(), static_cast< std::streamsize >(str.size()));
+ return *this;
+ }
+
+ template< typename OtherCharT, typename OtherTraitsT >
+ typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type
+ operator<< (basic_string_literal< OtherCharT, OtherTraitsT > const& str)
+ {
+ this->write(str.c_str(), static_cast< std::streamsize >(str.size()));
+ return *this;
+ }
+
+ template< typename T >
+ typename aux::enable_basic_formatting_ostream_generic_insert_operator< T, basic_formatting_ostream& >::type
+ operator<< (T const& value)
+ {
+ *static_cast< ostream_type* >(this) << value;
+ return *this;
+ }
+
+private:
+ void init_stream()
+ {
+ ostream_type::clear(this->streambuf_base_type::member.storage() ? ostream_type::goodbit : ostream_type::badbit);
+ ostream_type::flags
+ (
+ ostream_type::dec |
+ ostream_type::skipws |
+ ostream_type::boolalpha // this differs from the default stream flags but makes logs look better
+ );
+ ostream_type::width(0);
+ ostream_type::precision(6);
+ ostream_type::fill(static_cast< char_type >(' '));
+ }
+
+ //! Copy constructor (closed)
+ BOOST_LOG_DELETED_FUNCTION(basic_formatting_ostream(basic_formatting_ostream const& that))
+ //! Assignment (closed)
+ BOOST_LOG_DELETED_FUNCTION(basic_formatting_ostream& operator= (basic_formatting_ostream const& that))
+};
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_FORMATTING_OSTREAM_HPP_INCLUDED_

Added: trunk/boost/log/utility/formatting_ostream_fwd.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/formatting_ostream_fwd.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,51 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/utility/functional.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/functional.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#endif // BOOST_LOG_UTILITY_FUNCTIONAL_HPP_INCLUDED_

Added: trunk/boost/log/utility/functional/as_action.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/functional/as_action.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,60 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_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_LOG_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_

Added: trunk/boost/log/utility/functional/begins_with.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/functional/begins_with.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,57 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/utility/functional/bind.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/functional/bind.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,237 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_FORCEINLINE binder1st< FunT, FirstArgT > bind1st(FunT fun, FirstArgT const& arg)
+{
+ return binder1st< FunT, FirstArgT >(fun, arg);
+}
+
+template< typename FunT, typename FirstArgT >
+BOOST_LOG_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_LOG_FORCEINLINE binder2nd< FunT, SecondArgT > bind2nd(FunT fun, SecondArgT const& arg)
+{
+ return binder2nd< FunT, SecondArgT >(fun, arg);
+}
+
+template< typename FunT, typename SecondArgT >
+BOOST_LOG_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_LOG_FORCEINLINE binder3rd< FunT, ThirdArgT > bind3rd(FunT fun, ThirdArgT const& arg)
+{
+ return binder3rd< FunT, ThirdArgT >(fun, arg);
+}
+
+template< typename FunT, typename ThirdArgT >
+BOOST_LOG_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_

Added: trunk/boost/log/utility/functional/bind_assign.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/functional/bind_assign.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,55 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_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_

Added: trunk/boost/log/utility/functional/bind_output.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/functional/bind_output.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,55 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_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_

Added: trunk/boost/log/utility/functional/bind_to_log.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/functional/bind_to_log.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,76 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_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_LOG_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_

Added: trunk/boost/log/utility/functional/contains.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/functional/contains.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,69 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/utility/functional/ends_with.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/functional/ends_with.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,57 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/utility/functional/fun_ref.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/functional/fun_ref.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,79 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_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_

Added: trunk/boost/log/utility/functional/in_range.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/functional/in_range.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,63 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/utility/functional/logical.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/functional/logical.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,225 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 intergal, 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_LOG_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_

Added: trunk/boost/log/utility/functional/matches.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/functional/matches.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,129 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/mpl/bool.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! This tag type is used if an expression is not supported for matching against strings
+struct unsupported_match_expression_tag;
+//! This tag type is used if an expression is recognized as a Boost.Regex expression
+struct boost_regex_expression_tag;
+//! This tag type is used if an expression is recognized as a Boost.Xpressive expression
+struct boost_xpressive_expression_tag;
+//! This tag type is used if an expression is recognized as a Boost.Spirit (classic) expression
+struct boost_spirit_classic_expression_tag;
+//! This tag type is used if an expression is recognized as a Boost.Spirit.Qi expression
+struct boost_spirit_qi_expression_tag;
+
+//! Preliminary declaration of a trait that detects if an expression is a Boost.Regex expression
+template< typename, bool = true >
+struct is_regex :
+ public mpl::false_
+{
+};
+//! Preliminary declaration of a trait that detects if an expression is a Boost.Xpressive expression
+template< typename, bool = true >
+struct is_xpressive_regex :
+ public mpl::false_
+{
+};
+//! Preliminary declaration of a trait that detects if an expression is a Boost.Spirit (classic) expression
+template< typename, bool = true >
+struct is_spirit_classic_parser :
+ public mpl::false_
+{
+};
+//! Preliminary declaration of a trait that detects if an expression is a Boost.Spirit.Qi expression
+template< typename, bool = true >
+struct is_spirit_qi_parser :
+ public mpl::false_
+{
+};
+
+//! The regex matching functor implementation
+template< typename TagT >
+struct matches_fun_impl;
+
+} // namespace aux
+
+//! The regex matching functor
+struct matches_fun
+{
+ typedef bool result_type;
+
+private:
+ //! A traits to obtain the tag of the expression
+ template< typename ExpressionT >
+ struct match_traits
+ {
+ typedef typename mpl::eval_if<
+ aux::is_regex< ExpressionT >,
+ mpl::identity< aux::boost_regex_expression_tag >,
+ mpl::eval_if<
+ aux::is_xpressive_regex< ExpressionT >,
+ mpl::identity< aux::boost_xpressive_expression_tag >,
+ mpl::eval_if<
+ aux::is_spirit_classic_parser< ExpressionT >,
+ mpl::identity< aux::boost_spirit_classic_expression_tag >,
+ mpl::if_<
+ aux::is_spirit_qi_parser< ExpressionT >,
+ aux::boost_spirit_qi_expression_tag,
+ aux::unsupported_match_expression_tag
+ >
+ >
+ >
+ >::type tag_type;
+ };
+
+public:
+ template< typename StringT, typename ExpressionT >
+ bool operator() (StringT const& str, ExpressionT const& expr) const
+ {
+ typedef typename match_traits< ExpressionT >::tag_type tag_type;
+ typedef aux::matches_fun_impl< tag_type > 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 typename match_traits< ExpressionT >::tag_type tag_type;
+ typedef aux::matches_fun_impl< tag_type > 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_

Added: trunk/boost/log/utility/functional/nop.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/functional/nop.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,55 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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 {}
+
+#if !defined(BOOST_NO_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template< typename... ArgsT >
+ void operator() (ArgsT const&...) const {}
+#else
+ template< typename T >
+ void operator() (T const&) const {}
+ template< typename T1, typename T2 >
+ void operator() (T1 const&, T2 const&) const {}
+ template< typename T1, typename T2, typename T3 >
+ void operator() (T1 const&, T2 const&, T3 const&) const {}
+#endif
+};
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_FUNCTIONAL_NOP_HPP_INCLUDED_

Added: trunk/boost/log/utility/functional/save_result.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/functional/save_result.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,60 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_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_

Added: trunk/boost/log/utility/intrusive_ref_counter.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/intrusive_ref_counter.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,122 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 contains a reference counter class for \c intrusive_ptr.
+ */
+
+#ifndef BOOST_LOG_UTILITY_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_
+
+#include <boost/intrusive_ptr.hpp>
+#include <boost/log/detail/config.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_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+class intrusive_ref_counter;
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+void intrusive_ptr_add_ref(const intrusive_ref_counter* p);
+void intrusive_ptr_release(const intrusive_ref_counter* p);
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * \brief A reference counter base class
+ *
+ * This base class can be used with user-defined classes to add support
+ * for \c intrusive_ptr. The class contains a thread-safe reference counter
+ * and a virtual destructor, which makes the derived class polymorphic.
+ * Upon releasing the last \c intrusive_ptr referencing the object
+ * derived from the \c intrusive_ref_counter class, operator \c delete
+ * is automatically called on the pointer to the object.
+ */
+class intrusive_ref_counter
+{
+private:
+ //! Reference counter
+#ifndef BOOST_LOG_NO_THREADS
+ mutable boost::detail::atomic_count m_RefCounter;
+#else
+ mutable unsigned long m_RefCounter;
+#endif // BOOST_LOG_NO_THREADS
+
+public:
+ /*!
+ * Default constructor
+ *
+ * \post <tt>use_count() == 0</tt>
+ */
+ intrusive_ref_counter() : m_RefCounter(0)
+ {
+ }
+ /*!
+ * Copy constructor
+ *
+ * \post <tt>use_count() == 0</tt>
+ */
+ intrusive_ref_counter(intrusive_ref_counter const&) : m_RefCounter(0)
+ {
+ }
+
+ /*!
+ * Virtual destructor
+ */
+ virtual ~intrusive_ref_counter() {}
+
+ /*!
+ * Assignment
+ *
+ * \post The reference counter is not modified after assignment
+ */
+ intrusive_ref_counter& operator= (intrusive_ref_counter const&) { return *this; }
+
+ /*!
+ * \return The reference counter
+ */
+ unsigned long use_count() const
+ {
+ return static_cast< unsigned long >(static_cast< long >(m_RefCounter));
+ }
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ friend void intrusive_ptr_add_ref(const intrusive_ref_counter* p);
+ friend void intrusive_ptr_release(const intrusive_ref_counter* p);
+#endif // BOOST_LOG_DOXYGEN_PASS
+};
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+inline void intrusive_ptr_add_ref(const intrusive_ref_counter* p)
+{
+ ++p->m_RefCounter;
+}
+inline void intrusive_ptr_release(const intrusive_ref_counter* p)
+{
+ if (--p->m_RefCounter == 0)
+ delete p;
+}
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_

Added: trunk/boost/log/utility/manipulators.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/manipulators.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,28 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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>
+
+#ifdef BOOST_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#endif // BOOST_LOG_UTILITY_MANIPULATORS_HPP_INCLUDED_

Added: trunk/boost/log/utility/manipulators/add_value.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/manipulators/add_value.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,141 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/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_LOG_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 always an lvalue reference since apparently different compilers (GCC and MSVC) have different quirks when rvalue references are stored as members
+ typedef typename remove_reference< reference_type >::type& stored_reference_type;
+
+private:
+ //! Attribute value
+ stored_reference_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< stored_reference_type >(value)), m_name(name)
+ {
+ }
+
+ //! Returns attribute name
+ attribute_name get_name() const { return m_name; }
+ //! Returns attribute value
+ reference_type get_value() const { return static_cast< reference_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);
+}
+
+#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_

Added: trunk/boost/log/utility/manipulators/to_log.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/manipulators/to_log.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,92 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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
+{
+#ifndef BOOST_LOG_DOXYGEN_PASS
+public:
+ typedef void _has_basic_formatting_ostream_insert_operator;
+#endif
+
+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_

Added: trunk/boost/log/utility/once_block.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/once_block.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,195 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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>
+ * void foo()
+ * {
+ * static once_block_flag flag = BOOST_LOG_ONCE_BLOCK_INIT;
+ * 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,
+ being_initialized,
+ initialized
+ }
+ 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) : m_Flag(f)
+ {
+ }
+
+ ~once_block_sentry()
+ {
+ if (m_Flag.status != once_block_flag::initialized)
+ rollback();
+ }
+
+ bool executed() const
+ {
+ return (m_Flag.status == once_block_flag::initialized || enter_once_block());
+ }
+
+ BOOST_LOG_API void commit();
+
+private:
+ // Non-copyable, non-assignable
+ once_block_sentry(once_block_sentry const&);
+ once_block_sentry& operator= (once_block_sentry const&);
+
+ BOOST_LOG_API bool enter_once_block() const;
+ BOOST_LOG_API void rollback();
+};
+
+} // 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) : m_Flag(f)
+ {
+ }
+
+ bool executed() const
+ {
+ return m_Flag.status;
+ }
+
+ void commit()
+ {
+ m_Flag.status = true;
+ }
+
+private:
+ // Non-copyable, non-assignable
+ once_block_sentry(once_block_sentry const&);
+ 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));\
+ !sentry_var.executed(); sentry_var.commit())
+
+#define BOOST_LOG_ONCE_BLOCK_INTERNAL(flag_var, sentry_var)\
+ static boost::log::once_block_flag flag_var = BOOST_LOG_ONCE_BLOCK_INIT;\
+ 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_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_

Added: trunk/boost/log/utility/record_ordering.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/record_ordering.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,229 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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 comare 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 specificly 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_

Added: trunk/boost/log/utility/setup.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/setup.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,37 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#endif // BOOST_LOG_UTILITY_SETUP_HPP_INCLUDED_

Added: trunk/boost/log/utility/setup/common_attributes.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/setup/common_attributes.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,76 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/utility/setup/console.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/setup/console.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,243 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/shared_ptr.hpp>
+#include <boost/make_shared.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/utility/empty_deleter.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_LOG_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, empty_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 automaticallu 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_

Added: trunk/boost/log/utility/setup/file.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/setup/file.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,166 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/shared_ptr.hpp>
+#include <boost/make_shared.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_LOG_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>file::make_collector</tt>.
+ * \li \c max_size The maximum total size of rotated files in the target directory. See <tt>file::make_collector</tt>.
+ * \li \c min_free_space Minimum free space in the target directory. See <tt>file::make_collector</tt>.
+ * \li \c scan_method The method of scanning the target directory for log files. See <tt>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_

Added: trunk/boost/log/utility/setup/filter_parser.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/setup/filter_parser.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,346 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/lexical_cast.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_LOG_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_LOG_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();
+ }
+ /*!
+ * 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();
+ }
+ /*!
+ * 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();
+ }
+ /*!
+ * 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();
+ }
+ /*!
+ * 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();
+ }
+ /*!
+ * 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();
+ }
+
+ /*!
+ * 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();
+ }
+
+ BOOST_LOG_DELETED_FUNCTION(filter_factory(filter_factory const&))
+ BOOST_LOG_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 optrators 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();
+ }
+
+ /*!
+ * 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_

Added: trunk/boost/log/utility/setup/formatter_parser.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/setup/formatter_parser.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,216 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/shared_ptr.hpp>
+#include <boost/make_shared.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_LOG_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_LOG_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_LOG_DELETED_FUNCTION(formatter_factory(formatter_factory const&))
+ BOOST_LOG_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_

Added: trunk/boost/log/utility/setup/from_settings.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/setup/from_settings.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,164 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/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_LOG_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_LOG_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_LOG_DELETED_FUNCTION(sink_factory(sink_factory const&))
+ BOOST_LOG_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_

Added: trunk/boost/log/utility/setup/from_stream.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/setup/from_stream.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,47 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/utility/setup/settings.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/setup/settings.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,643 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/log/utility/explicit_operator_bool.hpp>
+#if !defined(BOOST_LOG_TYPEOF)
+#include <boost/utility/enable_if.hpp>
+#endif
+#if defined(BOOST_LOG_TYPEOF) && defined(BOOST_LOG_NO_TRAILING_RESULT_TYPE)
+#include <boost/utility/declval.hpp>
+#endif
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_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_LOG_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_LOG_NO_TRAILING_RESULT_TYPE)
+ 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_LOG_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_LOG_EXPLICIT_OPERATOR_BOOL()
+
+ /*!
+ * Checks if the section refers to the container.
+ */
+ bool operator! () const { 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 const& > 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_

Added: trunk/boost/log/utility/setup/settings_parser.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/setup/settings_parser.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,47 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/utility/strictest_lock.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/strictest_lock.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,214 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/utility/string_literal.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/string_literal.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,573 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <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_LOG_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() { 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
+ )
+ : 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) : 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)
+ {
+ 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])
+ {
+ 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
+ {
+ 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
+ {
+ 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
+ {
+ 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
+ {
+ 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
+ {
+ 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
+ {
+ 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
+ {
+ 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 { return m_pStart; }
+ /*!
+ * \return Pointer to the beginning of the literal
+ */
+ const_pointer data() const { return m_pStart; }
+ /*!
+ * \return Length of the literal
+ */
+ size_type size() const { return m_Len; }
+ /*!
+ * \return Length of the literal
+ */
+ size_type length() const { return m_Len; }
+
+ /*!
+ * \return \c true if the literal is an empty string, \c false otherwise
+ */
+ bool empty() const
+ {
+ return (m_Len == 0);
+ }
+
+ /*!
+ * \return Iterator that points to the first character of the literal
+ */
+ const_iterator begin() const { return m_pStart; }
+ /*!
+ * \return Iterator that points after the last character of the literal
+ */
+ const_iterator end() const { return m_pStart + m_Len; }
+ /*!
+ * \return Reverse iterator that points to the last character of the literal
+ */
+ const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
+ /*!
+ * \return Reverse iterator that points before the first character of the literal
+ */
+ const_reverse_iterator rend() const { 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()
+ {
+ m_pStart = g_EmptyString;
+ m_Len = 0;
+ }
+ /*!
+ * The method swaps two literals
+ */
+ void swap(this_type& that)
+ {
+ register const_pointer p = m_pStart;
+ m_pStart = that.m_pStart;
+ that.m_pStart = p;
+
+ register 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)
+ {
+ 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])
+ {
+ 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"));
+
+ register 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"));
+
+ register 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
+ {
+ 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
+ {
+ 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
+ {
+ 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
+ {
+ 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
+ {
+ 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)
+ {
+ if (pLeft != pRight)
+ {
+ register const int result = traits_type::compare(
+ pLeft, pRight, (LeftLen < RightLen ? LeftLen : RightLen));
+ if (result != 0)
+ return result;
+ }
+ return static_cast< int >(LeftLen - RightLen);
+ }
+#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 };
+
+//! 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)
+{
+ strm.write(lit.c_str(), static_cast< std::streamsize >(lit.size()));
+ return strm;
+}
+
+//! External swap
+template< typename CharT, typename TraitsT >
+inline void swap(
+ basic_string_literal< CharT, TraitsT >& left,
+ basic_string_literal< CharT, TraitsT >& right)
+{
+ 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_

Added: trunk/boost/log/utility/string_literal_fwd.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/string_literal_fwd.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,55 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/utility/type_dispatch/date_time_types.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/type_dispatch/date_time_types.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,138 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,154 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/shared_ptr.hpp>
+#include <boost/make_shared.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_LOG_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_

Added: trunk/boost/log/utility/type_dispatch/standard_types.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/type_dispatch/standard_types.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,105 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Added: trunk/boost/log/utility/type_dispatch/static_type_dispatcher.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/type_dispatch/static_type_dispatcher.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,272 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_FORCEINLINE void init(IteratorT*, IteratorT*, std::pair< type_info_wrapper, void* >*)
+ {
+ }
+
+ template< typename BeginIteratorT, typename EndIteratorT >
+ static BOOST_LOG_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_LOG_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 dispatcher that supports a sequence of types
+template< typename TypeSequenceT >
+class type_sequence_dispatcher :
+ public type_dispatcher
+{
+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;
+
+private:
+ //! Pointer to the receiver function
+ void* m_pVisitor;
+ //! Pointer to the dispatching map
+ dispatching_map const& m_DispatchingMap;
+
+public:
+ /*!
+ * Constructor. Initializes the dispatcher internals.
+ */
+ template< typename VisitorT >
+ explicit type_sequence_dispatcher(VisitorT& visitor) :
+ type_dispatcher(&type_sequence_dispatcher< supported_types >::get_callback),
+ m_pVisitor((void*)boost::addressof(visitor)),
+ m_DispatchingMap(get_dispatching_map< VisitorT >())
+ {
+ }
+
+private:
+ //! The get_callback method implementation
+ static callback_base get_callback(type_dispatcher* p, std::type_info const& type)
+ {
+ type_sequence_dispatcher* const self = static_cast< type_sequence_dispatcher* >(p);
+ type_info_wrapper wrapper(type);
+ typename dispatching_map::value_type const* begin = &*self->m_DispatchingMap.begin();
+ typename dispatching_map::value_type const* end = begin + dispatching_map::static_size;
+ typename dispatching_map::value_type const* it =
+ std::lower_bound(
+ begin,
+ end,
+ std::make_pair(wrapper, (void*)0),
+ dispatching_map_order()
+ );
+
+ if (it != end && it->first == wrapper)
+ return callback_base(self->m_pVisitor, it->second);
+ else
+ return callback_base();
+ }
+
+ //! 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_LOG_DELETED_FUNCTION(type_sequence_dispatcher(type_sequence_dispatcher const&))
+ BOOST_LOG_DELETED_FUNCTION(type_sequence_dispatcher& operator= (type_sequence_dispatcher const&))
+};
+
+//! A simple dispatcher that only supports one type
+template< typename T >
+class single_type_dispatcher :
+ public type_dispatcher
+{
+private:
+ //! A callback for the supported type
+ callback_base m_Callback;
+
+public:
+ //! Constructor
+ template< typename VisitorT >
+ explicit single_type_dispatcher(VisitorT& visitor) :
+ type_dispatcher(&single_type_dispatcher< T >::get_callback),
+ m_Callback(
+ (void*)boost::addressof(visitor),
+ &callback_base::trampoline< VisitorT, T >
+ )
+ {
+ }
+ //! The get_callback method implementation
+ static callback_base get_callback(type_dispatcher* p, std::type_info const& type)
+ {
+ if (type == typeid(visible_type< T >))
+ {
+ single_type_dispatcher* const self = static_cast< single_type_dispatcher* >(p);
+ return self->m_Callback;
+ }
+ else
+ return callback_base();
+ }
+
+ // Copying and assignment closed
+ BOOST_LOG_DELETED_FUNCTION(single_type_dispatcher(single_type_dispatcher const&))
+ BOOST_LOG_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.
+ */
+ template< typename ReceiverT >
+ explicit static_type_dispatcher(ReceiverT& receiver) :
+ base_type(receiver)
+ {
+ }
+
+ // Copying and assignment prohibited
+ BOOST_LOG_DELETED_FUNCTION(static_type_dispatcher(static_type_dispatcher const&))
+ BOOST_LOG_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_

Added: trunk/boost/log/utility/type_dispatch/type_dispatcher.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/type_dispatch/type_dispatcher.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,188 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/log/utility/explicit_operator_bool.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_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) :
+ m_pVisitor(visitor),
+ m_pTrampoline(tramp)
+ {
+ }
+ template< typename ValueT >
+ explicit callback_base(void* visitor, void (*tramp)(void*, ValueT const&)) :
+ 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() : callback_base()
+ {
+ }
+ explicit callback(callback_base const& base) : 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_LOG_EXPLICIT_OPERATOR_BOOL()
+
+ bool operator! () const { 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_LOG_EXPLICIT_OPERATOR_BOOL()
+
+ /*!
+ * The operator checks if the visitor is not attached to a receiver
+ */
+ bool operator! () const;
+ };
+
+#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) : m_get_callback_impl(get_callback_impl)
+ {
+ }
+ // Destructor and copying can only be called from the derived classes
+ BOOST_LOG_DEFAULTED_FUNCTION(~type_dispatcher(), {})
+ BOOST_LOG_DEFAULTED_FUNCTION(type_dispatcher(type_dispatcher const& that), : m_get_callback_impl(that.m_get_callback_impl) {})
+ BOOST_LOG_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_

Added: trunk/boost/log/utility/type_info_wrapper.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/type_info_wrapper.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,222 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/log/detail/config.hpp>
+#include <boost/log/utility/explicit_operator_bool.hpp>
+
+#ifdef BOOST_LOG_HAS_CXXABI_H
+#include <cxxabi.h>
+#include <stdlib.h>
+#endif // BOOST_LOG_HAS_CXXABI_H
+
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_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_LOG_VISIBLE uninitialized {};
+
+#ifdef BOOST_LOG_HAS_CXXABI_H
+ //! A simple scope guard for automatic memory free
+ struct auto_free
+ {
+ explicit auto_free(void* p) : p_(p) {}
+ ~auto_free() { free(p_); }
+ private:
+ void* p_;
+ };
+#endif // BOOST_LOG_HAS_CXXABI_H
+
+#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() : 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) : 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) : 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_LOG_EXPLICIT_OPERATOR_BOOL()
+
+ /*!
+ * Stored type info getter
+ *
+ * \pre <tt>!!*this</tt>
+ * \return Constant reference to the wrapped type info object
+ */
+ std::type_info const& get() const { return *info; }
+
+ /*!
+ * Swaps two instances of the wrapper
+ */
+ void swap(type_info_wrapper& that)
+ {
+ register 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!())
+ {
+#ifdef BOOST_LOG_HAS_CXXABI_H
+ // GCC returns decorated type name, will need to demangle it using ABI
+ int status = 0;
+ size_t size = 0;
+ const char* name = info->name();
+ char* undecorated = abi::__cxa_demangle(name, NULL, &size, &status);
+ auto_free cleanup(undecorated);
+
+ if (undecorated)
+ return undecorated;
+ else
+ return name;
+#else
+ return info->name();
+#endif
+ }
+ 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 { 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
+ {
+ 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
+ {
+ return static_cast< bool >(info->before(*that.info));
+ }
+};
+
+//! Inequality operator
+inline bool operator!= (type_info_wrapper const& left, type_info_wrapper const& right)
+{
+ return !left.operator==(right);
+}
+
+//! Ordering operator
+inline bool operator<= (type_info_wrapper const& left, type_info_wrapper const& right)
+{
+ return (left.operator==(right) || left.operator<(right));
+}
+
+//! Ordering operator
+inline bool operator> (type_info_wrapper const& left, type_info_wrapper const& right)
+{
+ return !(left.operator==(right) || left.operator<(right));
+}
+
+//! Ordering operator
+inline bool operator>= (type_info_wrapper const& left, type_info_wrapper const& right)
+{
+ return !left.operator<(right);
+}
+
+//! Free swap for type info wrapper
+inline void swap(type_info_wrapper& left, type_info_wrapper& right)
+{
+ left.swap(right);
+}
+
+//! A The function for support of 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_

Added: trunk/boost/log/utility/unique_identifier_name.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/unique_identifier_name.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,52 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 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/detail/workaround.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_LOG_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 in another macro.
+ */
+
+// In VC 7.0 and later when compiling with /ZI option __LINE__ macro is corrupted
+#if BOOST_WORKAROUND(BOOST_MSVC, >=1300)
+# 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_WORKAROUND(BOOST_MSVC, >= 1300)
+
+#endif // BOOST_LOG_UTILITY_UNIQUE_IDENTIFIER_NAME_HPP_INCLUDED_

Added: trunk/boost/log/utility/unused_variable.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/unused_variable.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,51 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_LOG_FORCEINLINE void no_unused_warnings(T const&) {}
+
+} // 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_

Added: trunk/boost/log/utility/value_ref.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/value_ref.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,630 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/log/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_LOG_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_TEMPLATE_ALIASES) && !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_TEMPLATE_ALIASES) && !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_MSG(m_type_idx < mpl::size< value_type >::value, "Boost.Log: Value reference is corrupted, type index is out of bounds");
+ 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 seqence 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_LOG_DEFAULTED_FUNCTION(value_ref(), BOOST_NOEXCEPT {})
+
+ /*!
+ * Copy constructor.
+ */
+ BOOST_LOG_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_LOG_EXPLICIT_OPERATOR_BOOL()
+
+ /*!
+ * 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_

Added: trunk/boost/log/utility/value_ref_fwd.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/log/utility/value_ref_fwd.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,38 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_LOG_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_

Modified: trunk/libs/libraries.htm
==============================================================================
--- trunk/libs/libraries.htm (original)
+++ trunk/libs/libraries.htm 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -199,6 +199,7 @@
     <li>locale - Provide localization and Unicode
     handling tools for C++, from Artyom Beilis</li>
     <li>lockfree - Lockfree data structures, from Tim Blechmann</li>
+ <li>log - Logging library, from Andrey Semashev</li>
     <li>math - Several contributions in the
     domain of mathematics, from various authors.</li>
     <li>math/complex number algorithms -

Added: trunk/libs/log/build/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/log/build/Jamfile.v2 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,156 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+
+import modules ;
+import os ;
+import feature ;
+
+lib psapi ;
+lib ws2_32 ;
+
+local rule default_logapi ( )
+{
+ local api = unix ;
+ if [ os.name ] = "NT" { api = winnt ; }
+ return $(api) ;
+}
+
+feature.feature logapi : unix winnt : propagated ;
+feature.set-default logapi : [ default_logapi ] ;
+
+project boost/log
+ : source-location ../src
+ : requirements
+ <link>shared:<define>BOOST_LOG_DLL
+ <logapi>unix:<define>BOOST_LOG_USE_NATIVE_SYSLOG=1
+ <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>msvc:<cxxflags>/bigobj
+ <toolset>intel-win:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>gcc:<cxxflags>-ftemplate-depth-1024
+ <toolset>gcc:<cxxflags>-fno-strict-aliasing # avoids strict aliasing violations in other Boost components
+ <toolset>gcc-mingw:<linkflags>-Wl,--enable-auto-import
+ <toolset>gcc-cygwin:<linkflags>-Wl,--enable-auto-import
+ <library>/boost/date_time//boost_date_time
+ <library>/boost/filesystem//boost_filesystem
+ <library>/boost/system//boost_system
+ <threading>single:<define>BOOST_LOG_NO_THREADS
+ <threading>multi:<library>/boost/thread//boost_thread
+ ;
+
+local no_event_log = [ MATCH (define=BOOST_LOG_WITHOUT_EVENT_LOG) : [ modules.peek : ARGV ] ] ;
+local BOOST_LOG_MC_SRC ;
+
+if ! $(no_event_log)
+{
+ DEPENDS event_log_backend.cpp : simple_event_log.mc ;
+ BOOST_LOG_MC_SRC = simple_event_log.mc ;
+}
+
+local BOOST_LOG_COMMON_SRC =
+ attribute_name.cpp
+ attribute_set.cpp
+ attribute_value_set.cpp
+ code_conversion.cpp
+ core.cpp
+ record_ostream.cpp
+ severity_level.cpp
+ global_logger_storage.cpp
+ named_scope.cpp
+ process_name.cpp
+ process_id.cpp
+ thread_id.cpp
+ timer.cpp
+ exceptions.cpp
+ default_attribute_names.cpp
+ default_sink.cpp
+ text_ostream_backend.cpp
+ text_file_backend.cpp
+ syslog_backend.cpp
+ thread_specific.cpp
+ once_block.cpp
+ timestamp.cpp
+ threadsafe_queue.cpp
+ event.cpp
+ trivial.cpp
+ spirit_encoding.cpp
+ format_parser.cpp
+ date_time_format_parser.cpp
+ named_scope_format_parser.cpp
+ unhandled_exception_count.cpp
+ ;
+
+lib boost_log
+ : ## sources ##
+ $(BOOST_LOG_COMMON_SRC)
+ ## winnt sources ##
+ $(BOOST_LOG_MC_SRC)
+ event_log_backend.cpp
+ debug_output_backend.cpp
+ light_rw_mutex.cpp
+ psapi
+ ws2_32
+ : ## requirements ##
+ <define>BOOST_LOG_BUILDING_THE_LIB=1
+ <define>BOOST_SPIRIT_USE_PHOENIX_V3=1
+ <define>BOOST_THREAD_DONT_USE_CHRONO=1 # Don't introduce false dependency on Boost.Chrono
+ <logapi>winnt
+ ;
+
+lib boost_log
+ : ## sources ##
+ $(BOOST_LOG_COMMON_SRC)
+ ## unix sources ##
+ : ## requirements ##
+ <define>BOOST_LOG_BUILDING_THE_LIB=1
+ <define>BOOST_SPIRIT_USE_PHOENIX_V3=1
+ <define>BOOST_THREAD_DONT_USE_CHRONO=1 # Don't introduce false dependency on Boost.Chrono
+ <logapi>unix
+ ;
+
+
+local BOOST_LOG_SETUP_COMMON_SRC =
+ parser_utils.cpp
+ init_from_stream.cpp
+ init_from_settings.cpp
+ settings_parser.cpp
+ filter_parser.cpp
+ formatter_parser.cpp
+ default_filter_factory.cpp
+ ;
+
+lib boost_log_setup
+ : ## sources ##
+ $(BOOST_LOG_SETUP_COMMON_SRC)
+ ## winnt sources ##
+ ws2_32
+ : ## requirements ##
+ <link>shared:<define>BOOST_LOG_SETUP_DLL
+ <define>BOOST_LOG_SETUP_BUILDING_THE_LIB=1
+ <define>BOOST_SPIRIT_USE_PHOENIX_V3=1
+ <define>BOOST_THREAD_DONT_USE_CHRONO=1 # Don't introduce false dependency on Boost.Chrono
+ <library>boost_log
+ <logapi>winnt
+ ;
+
+lib boost_log_setup
+ : ## sources ##
+ $(BOOST_LOG_SETUP_COMMON_SRC)
+ ## unix sources ##
+ : ## requirements ##
+ <link>shared:<define>BOOST_LOG_SETUP_DLL
+ <define>BOOST_LOG_SETUP_BUILDING_THE_LIB=1
+ <define>BOOST_SPIRIT_USE_PHOENIX_V3=1
+ <define>BOOST_THREAD_DONT_USE_CHRONO=1 # Don't introduce false dependency on Boost.Chrono
+ <library>boost_log
+ <logapi>unix
+ ;

Added: trunk/libs/log/doc/Design.dia
==============================================================================
Binary file. No diff available.

Added: trunk/libs/log/doc/Design.png
==============================================================================
Binary file. No diff available.

Added: trunk/libs/log/doc/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/log/doc/Jamfile.v2 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,251 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+
+using quickbook ;
+using boostbook ;
+using doxygen ;
+using xsltproc ;
+
+import set ;
+import doxygen ;
+import xsltproc ;
+import notfile ;
+import path ;
+
+project boost/libs/log/doc ;
+
+path-constant images_location : html ;
+
+local doxygen_params =
+ <doxygen:param>RECURSIVE=YES
+ <doxygen:param>ALPHABETICAL_INDEX=YES
+ <doxygen:param>REPEAT_BRIEF=YES
+ <doxygen:param>ALWAYS_DETAILED_SEC=YES
+ <doxygen:param>BRIEF_MEMBER_DESC=NO
+ <doxygen:param>ABBREVIATE_BRIEF=YES
+ <doxygen:param>INHERIT_DOCS=YES
+ <doxygen:param>HIDE_UNDOC_MEMBERS=YES
+ <doxygen:param>HIDE_UNDOC_CLASSES=YES
+ <doxygen:param>HIDE_SCOPE_NAMES=YES
+ <doxygen:param>EXTRACT_ALL=NO
+ <doxygen:param>EXTRACT_PRIVATE=NO
+ <doxygen:param>BUILTIN_STL_SUPPORT=YES
+ <doxygen:param>ENABLE_PREPROCESSING=YES
+ <doxygen:param>MACRO_EXPANSION=YES
+ <doxygen:param>TAB_SIZE=4
+ <doxygen:param>SOURCE_BROWSER=YES
+ <doxygen:param>VERBATIM_HEADERS=NO
+# <doxygen:param>SEARCH_INCLUDES=YES
+# <doxygen:param>"INCLUDE_PATH=../../.."
+# <doxygen:param>EXCLUDE_SYMBOLS="aux aux::*"
+ <doxygen:param>"PREDEFINED=BOOST_LOG_DOXYGEN_PASS \\
+ BOOST_LOG_NO_VTABLE= \\
+ BOOST_LOG_VISIBLE= \\
+ BOOST_LOG_FORCEINLINE=inline \\
+ BOOST_STATIC_ASSERT(x)= \\
+ BOOST_STATIC_ASSERT_MSG(x,y)= \\
+ BOOST_RV_REF(x)=\"x&&\" \\
+ BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\
+ BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(x)= \\
+ BOOST_LOG_UNIQUE_IDENTIFIER_NAME(x)=anonymous \\
+ BOOST_LOG_USE_NATIVE_SYSLOG=1 \\
+ BOOST_PARAMETER_KEYWORD(x,y)=\"keyword y;\" \\
+ BOOST_LOG_AUX_VOID_DEFAULT=\"= void\" \\
+ BOOST_LOG_NAMESPACE=log \\
+ BOOST_LOG_OPEN_NAMESPACE=\"namespace log {\" \\
+ BOOST_LOG_CLOSE_NAMESPACE=\"}\" \\
+ BOOST_LOG_USE_CHAR \\
+ BOOST_LOG_USE_WCHAR_T \\
+ BOOST_LOG_API= \\
+ BOOST_LOG_SETUP_API="
+ <xsl:param>boost.doxygen.detailns=aux
+# <xsl:param>boost.doxygen.detail=implementation_
+ ;
+
+
+local top_level_includes =
+ [ glob
+ ../../../boost/log/*.hpp
+ ] ;
+
+local core_includes =
+ [ glob
+ ../../../boost/log/core/*.hpp
+ ] ;
+
+local attributes_includes =
+ [ glob
+ ../../../boost/log/attributes/*.hpp
+ ] ;
+
+local expressions_includes =
+ [ glob
+ ../../../boost/log/expressions/*.hpp
+ ../../../boost/log/expressions/predicates/*.hpp
+ ../../../boost/log/expressions/formatters/*.hpp
+ ] ;
+
+local sources_includes =
+ [ glob
+ ../../../boost/log/sources/*.hpp
+ ] ;
+
+local sinks_includes =
+ [ set.difference
+ # Document all these files...
+ [ glob
+ ../../../boost/log/sinks/*.hpp
+ ]
+ :
+ # ...except these
+ [ glob
+ ../../../boost/log/sinks/nt6_event_log*.hpp
+ ]
+ ] ;
+
+local utility_includes =
+ [ glob
+ ../../../boost/log/utility/*.hpp
+ ../../../boost/log/utility/setup/*.hpp
+ ../../../boost/log/utility/type_dispatch/*.hpp
+ ../../../boost/log/utility/functional/*.hpp
+ ../../../boost/log/utility/manipulators/*.hpp
+ ] ;
+
+local support_includes =
+ [ glob
+ ../../../boost/log/support/*.hpp
+ ] ;
+
+
+# This rule generates *.qbk files with macros with references to files, classes, etc. from the doxygen resulting *.xml files.
+rule gen-references ( target : source : properties * )
+{
+ DEPENDS target : source ;
+ local source-path = [ path.make [ on $(source) return $(LOCATE) ] ] ;
+ STYLESHEET on $(target) = [ path.native [ path.join $(source-path) gen_references.xsl ] ] ;
+ local target-name = $(source:B) ;
+ TARGET on $(target) = [ path.native [ path.join $(source-path) $(target-name:S=.qbk) ] ] ;
+}
+actions gen-references
+{
+# echo "*** Executing " $(NAME:E=xsltproc) -o "$(TARGET)" "$(STYLESHEET)" "$(>)"
+ $(NAME:E=xsltproc) -o "$(TARGET)" "$(STYLESHEET)" "$(>)"
+}
+
+
+doxygen top_level_reference
+ :
+ $(top_level_includes)
+ :
+ $(doxygen_params)
+ <xsl:param>"boost.doxygen.reftitle=Top level headers"
+ ;
+
+notfile top_level_refs : @gen-references : top_level_reference.xml ;
+
+doxygen core_reference
+ :
+ $(core_includes)
+ :
+ $(doxygen_params)
+ <xsl:param>"boost.doxygen.reftitle=Core components"
+ ;
+
+notfile core_refs : @gen-references : core_reference.xml ;
+
+doxygen attributes_reference
+ :
+ $(attributes_includes)
+ :
+ $(doxygen_params)
+ <xsl:param>"boost.doxygen.reftitle=Attributes"
+ ;
+
+notfile attributes_refs : @gen-references : attributes_reference.xml ;
+
+doxygen expressions_reference
+ :
+ $(expressions_includes)
+ :
+ $(doxygen_params)
+ <xsl:param>"boost.doxygen.reftitle=Expressions"
+ ;
+
+notfile expressions_refs : @gen-references : expressions_reference.xml ;
+
+doxygen sources_reference
+ :
+ $(sources_includes)
+ :
+ $(doxygen_params)
+ <xsl:param>"boost.doxygen.reftitle=Logging sources"
+ ;
+
+notfile sources_refs : @gen-references : sources_reference.xml ;
+
+doxygen sinks_reference
+ :
+ $(sinks_includes)
+ :
+ $(doxygen_params)
+ <xsl:param>"boost.doxygen.reftitle=Sinks"
+ ;
+
+notfile sinks_refs : @gen-references : sinks_reference.xml ;
+
+doxygen utility_reference
+ :
+ $(utility_includes)
+ :
+ $(doxygen_params)
+ <xsl:param>"boost.doxygen.reftitle=Utilities"
+ ;
+
+notfile utility_refs : @gen-references : utility_reference.xml ;
+
+doxygen support_reference
+ :
+ $(support_includes)
+ :
+ $(doxygen_params)
+ <xsl:param>"boost.doxygen.reftitle=Other libraries support layer"
+ ;
+
+notfile support_refs : @gen-references : support_reference.xml ;
+
+
+xml log_doc
+ :
+ log.qbk
+ :
+ <dependency>top_level_refs
+ <dependency>core_refs
+ <dependency>attributes_refs
+ <dependency>expressions_refs
+ <dependency>sources_refs
+ <dependency>sinks_refs
+ <dependency>utility_refs
+ <dependency>support_refs
+ ;
+
+boostbook log
+ :
+ log_doc
+ :
+ <xsl:param>boost.root=../../../..
+ <xsl:param>boost.libraries=../../../libs/libraries.htm
+ <xsl:param>nav.layout=none
+ <xsl:param>boost.image=Boost
+ <xsl:param>navig.graphics=1
+ <xsl:param>chunk.section.depth=2
+ <xsl:param>boost.compact.function=0
+ <format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/libs/log/doc/html
+ <format>pdf:<xsl:param>img.src.path=$(images_location)/
+ ;
+
+# install html : ../../../doc/src/boostbook.css ;

Added: trunk/libs/log/doc/attributes.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/log/doc/attributes.qbk 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,589 @@
+[/
+ Copyright Andrey Semashev 2007 - 2013.
+ 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)
+
+ This document is a part of Boost.Log library documentation.
+/]
+
+[section:attributes Attributes]
+
+ #include <``[boost_log_attributes_attribute_hpp]``>
+ #include <``[boost_log_attributes_attribute_cast_hpp]``>
+ #include <``[boost_log_attributes_attribute_value_hpp]``>
+
+All attributes in the library are implemented using the [@http://c2.com/cgi/wiki?PimplIdiom pimpl idiom], or more specifically - shared pimpl idiom. Every attribute provides an interface class which derives from the [class_log_attribute] class and an implementation class that derives from [class_log_attribute_impl]. The interface class only holds a reference counted pointer to the actual implementation of the attribute; this pointer is a member of the [class_log_attribute] class, so derived interface classes don't have any data members. When the interface class is default constructed, it creates the corresponding implementation object and initializes the [class_log_attribute] base class with a pointer to the implementation. Therefore the pimpl nature of attributes is transparent for users in a typical workflow.
+
+The shared pimpl design comes significant in a few cases though. One such case is copying the attribute. The copy operation is shallow, so multiple interface objects may refer to a single implementation object. There is no way to deep copy an attribute. Another case is default construction of [class_log_attribute] which creates an empty object that does not refer to an implementation. Attributes in such empty state should not be passed to the library but can be useful in some cases, e.g. when a delayed variable initialization is needed.
+
+It is possible to upcast the attribute interface from [class_log_attribute] to the actual interface class. To do this one has to apply [funcref boost::log::attribute_cast `attribute_cast`]:
+
+ logging::attribute attr = ...;
+ attrs::constant< int > const_attr = logging::attribute_cast< attrs::constant< int > >(attr);
+
+In this example, the cast will succeed (i.e. the `const_attr` will be non-empty) if the attribute `attr` was originally created as `attrs::constant< int >`. Since all data is stored in the implementation object, no data is lost in the casting process.
+
+The main purpose of attributes is to generate attribute values. Values are semantically distinct from the attributes. Such separation allows implementing attributes that can return different values at different time points (like clock-related attributes, for example) and, on the other hand, allows using different values of the same attribute independently. The [class_log_attribute] interface has a method named `get_value` that returns the actual attribute value. Attribute values are also implemented using the shared pimpl approach, the interface class is [class_log_attribute_value] and implementation classes derive from [class_log_attribute_value_impl].
+
+The attribute value object is mostly intended to store the actual attribute value and implement type dispatching in order to be able to extract the stored value. One should not confuse the attribute value object type and the stored value type. The former is in most cases not needed by users and provides type erasure, but the latter is needed to be able to extract the value. For brevity we call the stored attribute value type simply the attribute value type in this documentation.
+
+[section:constant Constants]
+
+ #include <``[boost_log_attributes_constant_hpp]``>
+
+The most simple and frequently used attribute type is a constant value of some type. This kind of attribute is implemented with the [class_attributes_constant] class template. The template is parametrized with the attribute value type. The constant value should be passed to the attribute constructor. Here is an example:
+
+ void foo()
+ {
+ src::logger lg;
+
+ // Register a constant attribute that always yields value -5
+ lg.add_attribute("MyInteger", attrs::constant< int >(-5));
+
+ // Register another constant attribute. Make it a string this time.
+ lg.add_attribute("MyString", attrs::constant< std::string >("Hello world!"));
+
+ // There is also a convenience generator function. "MyInteger2" is constant< int > here.
+ lg.add_attribute("MyInteger2", attrs::make_constant(10));
+ }
+
+That's it, there's nothing much you can do with a constant attribute. Constants are very useful when one wants to highlight some log records or just pass some data to a sink backend (e.g. pass statistical parameters to the collector).
+
+[endsect]
+
+[section:mutable_constant Mutable constants]
+
+ #include <``[boost_log_attributes_mutable_constant_hpp]``>
+
+This kind of attribute is an extension for the [link log.detailed.attributes.constant constant attribute]. In addition to being able to store some value, the [class_attributes_mutable_constant] class template has two distinctions:
+
+* it allows modification of the stored value without re-registering the attribute
+* it allows synchronization of the stores and reads of the stored value
+
+In order to change the stored value of the attribute, one must call the `set` method:
+
+ void foo()
+ {
+ src::logger lg;
+
+ // Register a mutable constant attribute that always yields value -5
+ attrs::mutable_constant< int > attr(-5);
+ lg.add_attribute("MyInteger", attr);
+ BOOST_LOG(lg) << "This record has MyInteger == -5";
+
+ // Change the attribute value
+ attr.set(100);
+ BOOST_LOG(lg) << "This record has MyInteger == 100";
+ }
+
+In multithreaded applications the `set` method calls must be serialized with the `get_value` calls (which, generally speaking, happen on every log record being made). By default [class_attributes_mutable_constant] does not serialize calls in any way, assuming that the user will do so externally. However, the [class_attributes_mutable_constant] template provides three additional template arguments: synchronization primitive type, scoped exclusive lock type and scoped shareable lock type. If a synchronization primitive type is specified, the scoped exclusive lock type is a mandatory parameter. If the scoped shareable lock type is not specified, the attribute will fall back to the exclusive lock instead of shared locks. For example:
+
+ // This mutable constant will always lock exclusively
+ // either for reading or storing the value
+ typedef attrs::mutable_constant<
+ int, // attribute value type
+ boost::mutex, // synchronization primitive
+ boost::lock_guard< boost::mutex > // exclusive lock type
+ > exclusive_mc;
+ exclusive_mc my_int1(10);
+
+ // This mutable constant will use shared clocking for reading the value
+ // and exclusive locking for storing
+ typedef attrs::mutable_constant<
+ int, // attribute value type
+ boost::shared_mutex, // synchronization primitive
+ boost::unique_lock< boost::shared_mutex >, // exclusive lock type
+ boost::shared_lock< boost::shared_mutex > // shared lock type
+ > shared_mc;
+ shared_mc my_int2(20);
+
+ BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(my_logger, src::logger_mt)
+ {
+ src::logger_mt lg;
+ lg.add_attribute("MyInteger1", my_int1);
+ lg.add_attribute("MyInteger2", my_int2);
+
+ return lg;
+ }
+
+ void foo()
+ {
+ src::logger_mt& lg = get_my_logger();
+
+ // This is safe, even if executed in multiple threads
+ my_int1.set(200);
+ BOOST_LOG(lg) << "This record has MyInteger1 == 200";
+
+ my_int2.set(300);
+ BOOST_LOG(lg) << "This record has MyInteger2 == 300";
+ }
+
+Mutable constants are often used as auxiliary attributes inside loggers to store attributes that may change on some events. As opposed to regular constants, which would require re-registering in case of value modification, mutable constants allow modifying the value in-place.
+
+[endsect]
+
+[section:counter Counters]
+
+ #include <``[boost_log_attributes_counter_hpp]``>
+
+Counters are one of the simplest attributes that generate a new value each time requested. Counters are often used to identify log records or to count some events, e.g. accepted network connections. The class template [class_attributes_counter] provides such functionality. This template is parametrized with the counter value type, which should support arithmetic operations, such as `operator +` and `operator -`. The counter attribute allows specification of the initial value and step (which can be negative) on construction.
+
+ BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(my_logger, src::logger_mt)
+ {
+ src::logger_mt lg;
+
+ // This counter will count lines, starting from 0
+ lg.add_attribute("LineCounter", attrs::counter< unsigned int >());
+
+ // This counter will count backwards, starting from 100 with step -5
+ lg.add_attribute("CountDown", attrs::counter< int >(100, -5));
+
+ return lg;
+ }
+
+ void foo()
+ {
+ src::logger_mt& lg = get_my_logger();
+ BOOST_LOG(lg) << "This record has LineCounter == 0, CountDown == 100";
+ BOOST_LOG(lg) << "This record has LineCounter == 1, CountDown == 95";
+ BOOST_LOG(lg) << "This record has LineCounter == 2, CountDown == 90";
+ }
+
+[note Don't expect that the log records with the [class_attributes_counter] attribute will always have ascending or descending counter values in the resulting log. In multithreaded applications counter values acquired by different threads may come to a sink in any order. See [link log.rationale.why_weak_record_ordering Rationale] for a more detailed explanation on why it can happen. For this reason it is more accurate to say that the [class_attributes_counter] attribute generates an identifier in an ascending or descending order rather than that it counts log records in either order.]
+
+[endsect]
+
+[section:clock Wall clock]
+
+ #include <``[boost_log_attributes_clock_hpp]``>
+
+One of the "must-have" features of any logging library is support for attaching a time stamp to every log record. The library provides two attributes for this purpose: `utc_clock` and `local_clock`. The former returns the current UTC time and the latter returns the current local time. In either case the returned time stamp is acquired with the maximum precision for the target platform. The attribute value is `boost::posix_time::ptime` (see __boost_date_time__). The usage is quite straightforward:
+
+ BOOST_LOG_DECLARE_GLOBAL_LOGGER(my_logger, src::logger_mt)
+
+ void foo()
+ {
+ logging::core::get()->add_global_attribute(
+ "TimeStamp",
+ attrs::local_clock());
+
+ // Now every log record ever made will have a time stamp attached
+ src::logger_mt& lg = get_my_logger();
+ BOOST_LOG(lg) << "This record has a time stamp";
+ }
+
+[endsect]
+
+[section:timer Stop watch (timer)]
+
+ #include <``[boost_log_attributes_timer_hpp]``>
+
+The [class_attributes_timer] attribute is very useful when there is a need to estimate the duration of some prolonged process. The attribute returns the time elapsed since the attribute construction. The attribute value type is `boost::posix_time::ptime::time_duration_type` (see __boost_date_time__).
+
+ // The class represents a single peer-to-peer connection
+ class network_connection
+ {
+ src::logger m_logger;
+
+ public:
+ network_connection()
+ {
+ m_logger.add_attribute("Duration", attrs::timer());
+ BOOST_LOG(m_logger) << "Connection established";
+ }
+ ~network_connection()
+ {
+ // This log record will show the whole life time duration of the connection
+ BOOST_LOG(m_logger) << "Connection closed";
+ }
+ };
+
+The attribute provides high resolution of the time estimation and can even be used as a simple in-place performance profiling tool.
+
+[tip The [class_attributes_timer] attribute can even be used to profile the code in different modules without recompiling them. The trick is to wrap an expensive call to a foreign module with the thread-specific [class_attributes_timer] [link log.detailed.attributes.related_components.scoped_attributes scoped attribute], which will markup all log records made from within the module with time readings.]
+
+[endsect]
+
+[section:named_scope Named scopes]
+
+ #include <``[boost_log_attributes_named_scope_hpp]``>
+
+ // Supporting headers
+ #include <``[boost_log_support_exception_hpp]``>
+
+The logging library supports maintaining scope stack tracking during the application's execution. This stack may either be written to log or be used for other needs (for example, to save the exact call sequence that led to an exception when throwing one). Each stack element contains the following information (see the [class_attributes_named_scope_entry] structure template definition):
+
+* Scope name. It can be defined by the user or generated by the compiler, but in any case it [_must be a constant string literal] (see [link log.rationale.why_str_lit Rationale]).
+* Source file name, where the scope begins. It is usually a result of the standard `__FILE__` macro expansion. Like the scope name, the file name [_must be a constant string literal].
+* Line number in the source file. Usually it is a result of the standard `__LINE__` macro expansion.
+
+The scope stack is implemented as a thread-specific global storage internally. There is the [class_attributes_named_scope] attribute that allows hooking this stack into the logging pipeline. This attribute generates value of the nested type `named_scope::scope_stack` which is the instance of the scope stack. The attribute can be registered in the following way:
+
+ logging::core::get()->add_global_attribute("Scope", attrs::named_scope());
+
+Note that it is perfectly valid to register the attribute globally because the scope stack is thread-local anyway. This will also implicitly add scope tracking to all threads of the application, which is often exactly what is needed.
+
+Now we can mark execution scopes with the macros `BOOST_LOG_FUNCTION` and `BOOST_LOG_NAMED_SCOPE` (the latter accepts the scope name as its argument). These macros automatically add source position information to each scope entry. An example follows:
+
+ void foo(int n)
+ {
+ // Mark the scope of the function foo
+ BOOST_LOG_FUNCTION();
+
+ switch (n)
+ {
+ case 0:
+ {
+ // Mark the current scope
+ BOOST_LOG_NAMED_SCOPE("case 0");
+ BOOST_LOG(lg) << "Some log record";
+ bar(); // call some function
+ }
+ break;
+
+ case 1:
+ {
+ // Mark the current scope
+ BOOST_LOG_NAMED_SCOPE("case 1");
+ BOOST_LOG(lg) << "Some log record";
+ bar(); // call some function
+ }
+ break;
+
+ default:
+ {
+ // Mark the current scope
+ BOOST_LOG_NAMED_SCOPE("default");
+ BOOST_LOG(lg) << "Some log record";
+ bar(); // call some function
+ }
+ break;
+ }
+ }
+
+After executing `foo` we will be able to see in the log that the `bar` function was called from `foo` and, more precisely, from the case statement that corresponds to the value of `n`. This may be very useful when tracking down subtle bugs that show up only when `bar` is called from a specific location (e.g. if `bar` is being passed invalid arguments in that particular location).
+
+Another good use case is attaching the scope stack information to an exception. With the help of __boost_exception__, this is possible:
+
+ void bar(int x)
+ {
+ BOOST_LOG_FUNCTION();
+
+ if (x < 0)
+ {
+ // Attach a copy of the current scope stack to the exception
+ throw boost::enable_error_info(std::range_error("x must not be negative"))
+ << logging::current_scope();
+ }
+ }
+
+ void foo()
+ {
+ BOOST_LOG_FUNCTION();
+
+ try
+ {
+ bar(-1);
+ }
+ catch (std::range_error& e)
+ {
+ // Acquire the scope stack from the exception object
+ BOOST_LOG(lg) << "bar call failed: " << e.what() << ", scopes stack:\n"
+ << *boost::get_error_info< logging::current_scope_info >(e);
+ }
+ }
+
+[note In order this code to compile, the __boost_exception__ support header has to be included.]
+
+[note We do not inject the [class_attributes_named_scope] attribute into the exception. Since scope stacks are maintained globally, throwing an exception will cause stack unwinding and, as a result, will truncate the global stack. Instead we create a copy of the scope stack bu calling [funcref boost::log::current_scope `current_scope`] at the throw site. This copy will be kept intact even if the global stack instance changes during the stack unwinding.]
+
+[endsect]
+
+[section:process_id Current process identifier]
+
+ #include <``[boost_log_attributes_current_process_id_hpp]``>
+
+It is often useful to know the process identifier that produces the log, especially if the log can eventually combine the output of different processes. The [class_attributes_current_process_id] attribute is a constant that formats into the current process identifier. The value type of the attribute can be determined by the `current_process_id::value_type` typedef.
+
+ void foo()
+ {
+ logging::core::get()->add_global_attribute(
+ "ProcessID",
+ attrs::current_process_id());
+ }
+
+[endsect]
+
+[section:process_name Current process name]
+
+ #include <``[boost_log_attributes_current_process_name_hpp]``>
+
+The [class_attributes_current_process_name] produces `std::string` values with the executable name of the current process.
+
+[note This attribute is not universally portable, although Windows, Linux and OS X are supported. The attribute may work on other POSIX systems as well, but it was not tested. If the process name cannot be obtained the attribute will generate a string with the process id.]
+
+ void foo()
+ {
+ logging::core::get()->add_global_attribute(
+ "Process",
+ attrs::current_process_name());
+ }
+
+[endsect]
+
+[section:thread_id Current thread identifier]
+
+ #include <``[boost_log_attributes_current_thread_id_hpp]``>
+
+Multithreaded builds of the library also support the [class_attributes_current_thread_id] attribute with value type `current_thread_id::value_type`. The attribute will generate values specific to the calling thread. The usage is similar to the process id.
+
+ void foo()
+ {
+ logging::core::get()->add_global_attribute(
+ "ThreadID",
+ attrs::current_thread_id());
+ }
+
+[tip You may have noticed that the attribute is registered globally. This will not result in all threads having the same ThreadID in log records as the attribute will always return a thread-specific value. The additional benefit is that you don't have to do a thing in the thread initialization routines to have the thread-specific attribute value in log records.]
+
+[endsect]
+
+[section:function Function objects as attributes]
+
+ #include <``[boost_log_attributes_function_hpp]``>
+
+This attribute is a simple wrapper around a user-defined function object. Each attempt to acquire the attribute value results in the function object call. The result of the call is returned as the attribute value (this implies that the function must not return `void`). The function object attribute can be constructed with the `make_function` helper function, like this:
+
+ void foo()
+ {
+ logging::core::get()->add_global_attribute("MyRandomAttr", attrs::make_function(&std::rand));
+ }
+
+Auto-generated function objects, like the ones defined in __boost_bind__ or STL, are also supported.
+
+[note Some deficient compilers may not support `result_of` construct properly. This metafunction is used in the `make_function` function to automatically detect the return type of the function object. If `result_of` breaks or detects incorrect type, one can try to explicitly specify the return type of the function object as a template argument to the `make_function` function.]
+
+[endsect]
+
+[section:related_components Other attribute-related components]
+
+[section:attribute_name Attribute names]
+
+ #include <``[boost_log_attributes_attribute_name_hpp]``>
+
+Attribute names are represented with [class_log_attribute_name] objects which are used as keys in associative containers of attributes used by the library. The [class_log_attribute_name] object can be created from a string, so most of the time its use is transparent.
+
+The name is not stored as a string within the [class_log_attribute_name] object. Instead, a process-wide unique identifier is generated and associated with the particular name. This association is preserved until the process termination, so every time the [class_log_attribute_name] object is created for the same name it obtains the same identifier. The association is not stable across the different runs of the application though.
+
+[warning Since the association between string names and identifiers involves some state allocation, it is not advised to use externally provided or known to be changing strings for attribute names. Even if the name is not used in any log records, the association is preserved anyway. Continuously constructing [class_log_attribute_name] objects with unique string names may manifest itself as a memory leak.]
+
+Working with identifiers is much more efficient than with strings. For example, copying does not involve dynamic memory allocation and comparison operators are very lightweight. On the other hand, it is easy to get a human-readable attribute name for presentation, if needed.
+
+The [class_log_attribute_name] class supports an empty (uninitialized) state when default constructed. In this state the name object is not equal to any other initialized name object. Unitnitialized attribute names should not be passed to the library but can be useful in some contexts (e.g. when a delayed initialization is desired).
+
+[endsect]
+
+[section:attribute_set Attribute set]
+
+ #include <``[boost_log_attributes_attribute_set_hpp]``>
+
+Attribute set is an unordered associative container that maps [link log.detailed.attributes.related_components.attribute_name attribute names] to [link log.detailed.attributes attributes]. It is used in [link log.detailed.sources loggers] and the [link log.detailed.core.core logging core] to store source-specific, thread-specific and global attributes. The interface is very similar to STL associative containers and is described in the [class_log_attribute_set] class reference.
+
+[endsect]
+
+[section:attribute_value_set Attribute value set]
+
+ #include <``[boost_log_attributes_attribute_value_set_hpp]``>
+
+Attribute value set is an unordered assocoative container that maps [link log.detailed.attributes.related_components.attribute_name attribute names] to [link log.detailed.attributes attribute values]. This container is used in log [link log.detailed.core.record records] to represent attribute values. Unlike conventional containers, [class_log_attribute_value_set] does not support removing or modifying elements after being inserted. This warrants that the attribute values that participated filtering will not disappear from the log record in the middle of the processing.
+
+Additionally, the set can be constructed from three [link log.detailed.attributes.related_components.attribute_set attribute sets], which are interpreted as the sets of source-specific, thread-specific and global attributes. The constructor adopts attribute values from the three attribute sets into a single set of attribute values. After construction, [class_log_attribute_value_set] is considered to be in an unfrozen state. This means that the container may keep references to the elements of the attribute sets used as the source for the value set construction. While in this state, neither the attribute sets nor the value set must not be modified in any way as this may make the value set corrupted. The value set can be used for reading in this state, its lookup operations will perform as usual. The value set can be frozen by calling the `freeze` method; the set will no longer be attached to the original attribute sets and will be available for further insertions after this call. The library will ensure that
the value set is always frosen when a log record is returned from the logging core; the set is [_not] frozen during filtering though.
+
+[tip In the unfrozen state the value set may not have all attribute values acquired from the attributes. It will only acquire the values as requested by filters. After freezing the container has all attribute values. This transition allows to optimize the library so that attribute values are only acquired when needed.]
+
+For futher details on the container interface please consult the [class_log_attribute_value_set] reference.
+
+[endsect]
+
+[section:value_processing Attribute value extraction and visitation]
+
+Since attribute values do not expose the stored value in the interface, an API is needed to acquire the stored value. The library provides two APIs for this purpose: value visitation and extraction.
+
+[section:visitation Value visitation]
+
+ #include <``[boost_log_attributes_value_visitation_fwd_hpp]``>
+ #include <``[boost_log_attributes_value_visitation_hpp]``>
+
+Attribute value visitation implements the visitor design pattern, hence the naming. The user has to provide an unary function object (a visitor) which will be invoked on the stored attribute value. The caller also has to provide the expected type or set of possible types of the stored value. Obviously, the visitor must be capable of receiving an argument of the expected type. Visitation will only succeed if the stored type matches the expectation.
+
+In order to apply the visitor, one should call the [funcref boost::log::visit `visit`] function on the attribute value. Let's see an example:
+
+[example_attr_value_visitation]
+
+[@boost:/libs/log/example/doc/attr_value_visitation.cpp See the complete code].
+
+In this example we print the stored attribute value in our `print_visitor`. We expect the attribute value to have either `int` or `std::string` stored type; only in this case the visitor will be invoked and the visitation result will be positive. In case of failure the [class_log_visitation_result] class provides additional information on the failure reason. The class has the method named `code` which returns visitation error code. The following error codes are possible:
+
+* `ok` - visitation succeeded, the visitor has been invoked; visitation result is positive when this code is used
+* `value_not_found` - visitation failed because the requested value was not found; this code is used when visitation is applied to a log record or a set of attrinute values rather than a single value
+* `value_has_invalid_type` - visitation failed because the value has type differing from any of the expected types
+
+By default the visitor function result is ignored but it is possible to obtain it. To do this one should use a special [funcref boost::log::save_result `save_result`] wrapper for the visitor; the wrapper will save the visitor resulting value into an external variable captured by reference. The visitor result is initialized when the returned [class_log_visitation_result] is positive. See the following example where we compute the hash value on the stored value.
+
+[example_attr_value_visitation_with_retval]
+
+[@boost:/libs/log/example/doc/attr_value_visitation.cpp See the complete code].
+
+[tip When there is no default state for the visitor result it is convenient to use __boost_optional__ to wrap the returned value. The `optional` will be initialized with the visitor result if visitation succeeded. In case if visitor is polymorphic (i.e. it has different result types depending on its argument type) __boost_variant__ can be used to receive the resulting value. It is also worthwhile to use an empty type, such as `boost::blank`, to indicate the uninitialized state of the `variant`.]
+
+As it has been mentioned, visitation can also be applied to log records and attribute value sets. The syntax is the same, except that the attribute name also has to be specified. The [funcref boost::log::visit `visit`] algorithm will try to find the attribute value by name and then apply the visitor to the found element.
+
+[example_attr_value_visitation_with_retval_rec]
+
+Also, for convenience [class_log_attribute_value] has the method named `visit` with the same meaning as the free function applied to the attribute value.
+
+[endsect]
+
+[section:extraction Value extraction]
+
+ #include <``[boost_log_attributes_value_extraction_fwd_hpp]``>
+ #include <``[boost_log_attributes_value_extraction_hpp]``>
+
+Attribute value extraction API allows to acquire a reference to the stored value. It does not require a visitor function object, but the user still has to provide the expected type or a set of types the stored value may have.
+
+[example_attr_value_extraction]
+
+[@boost:/libs/log/example/doc/attr_value_extraction.cpp See the complete code].
+
+In this example we expect the attribute value to have the stored type `int`. The [funcref boost::log::extract `extract`] function attempts to extract a reference to the stored value and returns the filled [link log.detailed.utilities.value_ref `value_ref`] object if succeeded.
+
+Value extraction can also be used with a set of expected stored types. The follwoing code snippet demonstrates this:
+
+[example_attr_value_extraction_multiple_types]
+
+Notice that we used `which` method of the returned reference to dispatch between possible types. The method returns the index of the type in the `types` sequence. Also note that the `get` method now accepts an explicit template parameter to select the reference type to acquire; naturally, this type must correspond to the actual referred type, which is warranted by the switch/case statement in our case.
+
+Value visitation is also supported by the [link log.detailed.utilities.value_ref `value_ref`] object. Here is how we compute a hash value from the extracted value:
+
+[example_attr_value_extraction_visitor]
+
+Lastly, like with value visitation, value extraction can also be applied to log records and attribute value sets.
+
+[example_attr_value_extraction_visitor_rec]
+
+In addition the library provides two special variants of the [funcref boost::log::extract `extract`] function: [funcref boost::log::extract_or_throw `extract_or_throw`] and [funcref boost::log::extract_or_default `extract_or_default`]. As the naming implies, the functions provide different behavior in case if the attribute value cannot be extracted. The former one throws an exception if the value cannot be extracted and the latter one returns the default value.
+
+[warning Care must be taken with the [funcref boost::log::extract_or_default `extract_or_default`] function. The function accepts the default value is accepted by constant reference, and this reference can eventually be returned from [funcref boost::log::extract_or_default `extract_or_default`]. If a temporary object as used for the default value, user must ensure that the result of [funcref boost::log::extract_or_default `extract_or_default`] is saved by value and not by reference. Otherwise the saved reference may become dangling when the temporary is destroyed.]
+
+Similarly to `visit`, the [class_log_attribute_value] class has methods named `extract`, `extract_or_throw` and `extract_or_default` with the same meaning as the corresponding free functions applied to the attribute value.
+
+[endsect]
+
+[endsect]
+
+[section:scoped_attributes Scoped attributes]
+
+ #include <``[boost_log_attributes_scoped_attribute_hpp]``>
+
+Scoped attributes are a powerful mechanism of tagging log records that can be used for different purposes. As the naming implies, scoped attributes are registered in the beginning of a scope and unregistered on the end of the scope. The mechanism includes the following macros:
+
+ ``[macroref BOOST_LOG_SCOPED_LOGGER_ATTR]``(logger, attr_name, attr);
+ ``[macroref BOOST_LOG_SCOPED_THREAD_ATTR]``(attr_name, attr);
+
+The first macro registers a source-specific attribute in the `logger` logger object. The attribute name and the attribute itself are given in the `attr_name` and `attr` arguments. The second macro does exactly the same but the attribute is registered for the current thread in the logging core (which does not require a logger).
+
+[note If an attribute with the same name is already registered in the logger/logging core, the macros won't override the existing attribute and will eventually have no effect. See [link log.rationale.why_weak_scoped_attributes Rationale] for a more detailed explanation of the reasons for such behavior.]
+
+Usage example follows:
+
+ BOOST_LOG_DECLARE_GLOBAL_LOGGER(my_logger, src::logger_mt)
+
+ void foo()
+ {
+ // This log record will also be marked with the "Tag" attribute,
+ // whenever it is called from the A::bar function.
+ // It will not be marked when called from other places.
+ BOOST_LOG(get_my_logger()) << "A log message from foo";
+ }
+
+ struct A
+ {
+ src::logger m_Logger;
+
+ void bar()
+ {
+ // Set a thread-wide markup tag.
+ // Note the additional parentheses to form a Boost.PP sequence.
+ BOOST_LOG_SCOPED_THREAD_ATTR("Tag",
+ attrs::constant< std::string >("Called from A::bar"));
+
+ // This log record will be marked
+ BOOST_LOG(m_Logger) << "A log message from A::bar";
+
+ foo();
+ }
+ };
+
+ int main(int, char*[])
+ {
+ src::logger lg;
+
+ // Let's measure our application run time
+ BOOST_LOG_SCOPED_LOGGER_ATTR(lg, "RunTime", attrs::timer());
+
+ // Mark application start.
+ // The "RunTime" attribute should be nearly 0 at this point.
+ BOOST_LOG(lg) << "Application started";
+
+ // Note that no other log records are affected by the "RunTime" attribute.
+ foo();
+
+ A a;
+ a.bar();
+
+ // Mark application ending.
+ // The "RunTime" attribute will show the execution time elapsed.
+ BOOST_LOG(lg) << "Application ended";
+
+ return 0;
+ }
+
+It is quite often convenient to mark a group of log records with a constant value in order to be able to filter the records later. The library provides two convenience macros just for this purpose:
+
+ ``[macroref BOOST_LOG_SCOPED_LOGGER_TAG]``(logger, tag_name, tag_value);
+ ``[macroref BOOST_LOG_SCOPED_THREAD_TAG]``(tag_name, tag_value);
+
+The macros are effectively wrappers around [macroref BOOST_LOG_SCOPED_LOGGER_ATTR] and [macroref BOOST_LOG_SCOPED_THREAD_ATTR], respectively. For example, the "Tag" scoped attribute from the example above can be registered like this:
+
+ BOOST_LOG_SCOPED_THREAD_TAG("Tag", "Called from A::bar");
+
+[warning When using scoped attributes, make sure that the scoped attribute is not altered in the attribute set in which it was registered. For example, one should not clear or reinstall the attribute set of the logger if there are logger-specific scoped attributes registered in it. Otherwise the program will likely crash. This issue is especially critical in multithreaded application, when one thread may not know whether there are scoped attributes in the logger or there are not. Future releases may solve this limitation but currently the scoped attribute must remain intact until unregistered on leaving the scope.]
+
+Although the described macros are intended to be the primary interface for the functionality, there is also a C++ interface available. It may be useful if the user decides to develop his own macros that cannot be based on the existing ones.
+
+Any scoped attribute is attached to a generic sentry object of type `scoped_attribute`. As long as the sentry exists, the attribute is registered. There are several functions that create sentries for source or thread-specific attributes:
+
+ // Source-specific scoped attribute registration
+ template< typename LoggerT >
+ [unspecified] add_scoped_logger_attribute(
+ LoggerT& l,
+ attribute_name const& name,
+ attribute const& attr);
+
+ // Thread-specific scoped attribute registration
+ template< typename CharT >
+ [unspecified] add_scoped_thread_attribute(
+ attribute_name const& name,
+ attribute const& attr);
+
+An object of the `scoped_attribute` type is able to attach results of each of these functions on its construction. For example, `BOOST_LOG_SCOPED_LOGGER_ATTR(lg, "RunTime", attrs::timer())` can roughly be expanded to this:
+
+ attrs::scoped_attribute sentry =
+ attrs::add_scoped_logger_attribute(lg, "RunTime", attrs::timer());
+
+[endsect]
+
+[endsect]
+
+[endsect]

Added: trunk/libs/log/doc/changelog.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/log/doc/changelog.qbk 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,144 @@
+[/
+ Copyright Andrey Semashev 2007 - 2013.
+ 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)
+
+ This document is a part of Boost.Log library documentation.
+/]
+
+[section:changelog Changelog]
+
+[heading 2.0]
+
+[*General changes:]
+
+* The library is now compatible with Boost 1.53 or newer. __boost_filesystem__ v2 no longer supported.
+* The library now does not introduce separate logging cores for different character types. A lot of other library components also became character type agnostic. The application can now use loggers of different character types with the common logging core. The library performs character code conversion as needed. __boost_locale__ can be used to construct locale objects for proper encoding conversion.
+* The `BOOST_LOG_NO_COMPILER_TLS` configuration macro has been replaced with `BOOST_LOG_USE_COMPILER_TLS` with the opposite meaning. The support for compiler intrinsics for TLS is now disabled by default.
+* Added configuration macros `BOOST_LOG_WITHOUT_DEBUG_OUTPUT`, `BOOST_LOG_WITHOUT_EVENT_LOG` and `BOOST_LOG_WITHOUT_SYSLOG`. `BOOST_LOG_NO_SETTINGS_PARSERS_SUPPORT` macro renamed to `BOOST_LOG_WITHOUT_SETTINGS_PARSERS`. The new macros allow to selectively disable support for the corresponding sink backends.
+* The library now uses __boost_xpressive__ instead of __boost_regex__ internally which makes it unnecessary to build the latter in order to use the library. __boost_regex__ is still supported on the user's side.
+* Made some internal code to detect Windows NT6 API availability at run time, if not explicitly enabled by the `BOOST_LOG_USE_WINNT6_API` macro. The code compiled without the macro defined will still be able run on NT5, but when run on NT6 it will be more efficient. With the macro defined the resulting code will not run on NT5, but will be a little more efficient on NT6 than without the macro.
+* Added a concept of a default sink. The default sink is used when there are no sinks configured in the logging core. The sink is synchronous and thread-safe, it requires no configuration and is overridden by any sinks configured in the core by user. The default sink will write log messages to the console, prepending with a timestamp, thread id and severity level.
+* Trivial logging no longer implicitly initializes the library. Instead, the default sink is used to display log messages, unless the library is configured otherwise. It is now possible to use both trivial and advanced logging.
+* Attribute values can now be added to log records after filtering. Such values do not participate in filtering but can be used by formatters and sinks. Log record message is now one of such attribute values, it is no longer directly accessible from the log record interface.
+* Formatters and sinks no longer operate on log records but rather on [class_log_record_view]s. Records are now moved from when pushed to the core for further processing. This is done in order to eliminate the possibility of unsafe record modification after pushing to the core. As a consequence, log records can no longer be copied, only moving is allowed. Record views can be copied and moved; copying is a shallow operation.
+* The implementation now provides several stream manipulators. Notably, the [link log.detailed.utilities.manipulators.to_log `to_log`] manipulator allows to customize formatting for particular types and attributes without changing the regular streaming operator. Also, the [link log.detailed.utilities.manipulators.add_value `add_value`] manipulator can be used in logging expressions to attach attribute values to the record.
+* Made a lot of improvements to speedup code compilation.
+
+[*Attributes:]
+
+* Changed the interface and the way of handling attribute values. The value is now a pimpl wrapper around the value holder. The [class_log_attribute_value] class in various components of the library is no longer pointed to with `shared_ptr`s but instead is handled by value. This allowed to simplify attribute value handling in simple cases.
+* Similarly to attribute values, the interface of attributes has been reworked in the pimpl fashion. All attributes now derive from the [class_log_attribute] base class, which holds the reference to the implementation. All attributes now have to be created by value rather than wrapped into `shared_ptr` by user, which makes the code more concise.
+* Added support for casting attributes from the base class [class_log_attribute] to the actual attribute type. This can be useful when the concrete attribute factory provides additional interfaces.
+* The attribute value no longer has the `get` method. Use the `extract` function as a replacement.
+* The key type of attribute sets and attribute values set has been changed. The new key type is called [class_log_attribute_name]. It is constructible from strings, so in most cases users won't need to change the code. See [link log.detailed.attributes.related_components.attribute_name here] for more information.
+* Attribute values view have been renamed to attribute value set. The container now supports adding more attribute values after being constructed.
+* Attribute sets and attribute value sets no longer maintain order of elements. Although it wasn't stated explicitly, the containers used to be ordered associative containers. Now the order of elements is unspecified. The implementation has been reworked to speed up insertion/removal of attributes, as well as attribute lookup and values set construction. The drawback is that memory footprint may get increased in some cases.
+* Attribute sets now use small memory pools to speed up element insertion/removal.
+* The header `scoped_attribute.hpp` moved from `utility` to the `attributes` directory. The header `attribute_value_extractor.hpp` in `utility` has been replaced with headers [boost_log_attributes_value_extraction_hpp] and [boost_log_attributes_value_visitation_hpp] in the `attributes` directory. The two new headers define the revised API of attribute value extraction and visitation, respectively. See [link log.detailed.attributes.related_components.value_processing here] for more details.
+* [link log.detailed.attributes.related_components.scoped_attributes Scoped attibute] macros simplified. The attribute constructor arguments are specified next to the attribute type and tag type is no longer required.
+* The [link log.detailed.attributes.thread_id `current_thread_id`] attribute no longer uses `boost::thread::id` type for thread identification. An internal type is used instead, the type is accessible as `current_thread_id::value_type`. The new thread ids are taken from the underlying OS API and thus more closely correlate to what may be displayed by debuggers and system diagnostic tools.
+* Added [link log.detailed.attributes.process_name `current_process_name`] attribute. The attribute generates a string with the executable name of the current process.
+* The `functor` attribute has been renamed to [class_attributes_function]. The generator function has been renamed from `make_functor_attr` to `make_function`. The header has been renamed from `functor.hpp` to `function.hpp`.
+
+[*Logging sources:]
+
+* Fixed compilation problems with exception handling logger feature.
+* Global logger storage made more friendly to the setups in which hidden visibility is set by default.
+* Added the macros for separated global logger declaration and definition. Old macros have been renamed to better reflect their effect (`BOOST_LOG_DECLARE_GLOBAL_LOGGER_INIT` to `BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT`, `BOOST_LOG_DECLARE_GLOBAL_LOGGER` to `BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT`, `BOOST_LOG_DECLARE_GLOBAL_LOGGER_CTOR_ARGS` to `BOOST_LOG_INLINE_GLOBAL_LOGGER_CTOR_ARGS`). Also, the macros no longer define the `get_logger` free function for logger acquisition. Use `logger::get` instead. See [link log.detailed.sources.global_storage here] for more information.
+* The channel logger now supports changing the channel name after construction. The channel name can be set either by calling the modifier method or by specifying the name in the logging statement. Added `BOOST_LOG_STREAM_CHANNEL` and `BOOST_LOG_STREAM_CHANNEL_SEV` (as well as their shorthands `BOOST_LOG_CHANNEL` and `BOOST_LOG_CHANNEL_SEV`) macros that allow to specify channel name for the log record.
+
+[*Logging sinks:]
+
+* Types for integral constants for syslog and event log were renamed to drop the `_t` suffix.
+* Formatting functionality moved to sink frontends. Sink backends that support record formatting derive from the `basic_formatting_sink_backend` class template, which indicates to the frontend that record formatting is required. This breaks user-side API of the library: the formatter and locale has to be set to the frontend rather than backend.
+* Formatting support no longer makes frontend thread synchronization mandatory. Formatting is done prior to locking for processing the record in the backend and can be performed concurrently in multiple threads.
+* Added support for flushing sinks. A sink backend that supports flushing has to define public method with the following signature: `void flush()`.
+* Asynchronous sink frontend reworkerd, ordering asynchronous sink removed. The [class_sinks_asynchronous_sink] class template now allows to specify record queueing strategy. Several strategies provided, including [class_sinks_unbounded_fifo_queue] (the default) and [class_sinks_unbounded_ordering_queue] which cover the functionality of asynchronous sink frontends in 1.x releases. See the [link log.detailed.sink_frontends.async asynchronous sink frontend] docs for more details.
+* Lock-free FIFO record queueing in asynchronous sinks reworked to reduce log record processing stalls.
+* Added `Append` configuration file parameter for text file sinks. If this parameter is set to `true`, the sink will append log records to the existing log file instead of overwriting it.
+* Added bounded variants of asynchronous sink frontends. Implemented two strategies to handle queue overflows: either log records are dropped or logging threads are blocked until there is space in the queue.
+
+[*Filters and formatters:]
+
+* As a result of character type unification, filters no longer depend on the character type.
+* Two new types were introduced to dynamically store filters and formatters: [class_log_filter] and [class_log_basic_formatter]. Both new types implement type erasure and provide function calling operators to invoke the stored filter or formatter.
+* Filters and formatters were rewritten. The new implementation is based on __boost_phoenix__ and resides in the `expressions` namespace. Attribute placeholders are now interoperable with other template expressions based on __boost_phoenix__. All template expression headers now reside in the `expressions` subdirectory.
+* The library now supports defining keywords for attributes (see `BOOST_LOG_ATTRIBUTE_KEYWORD` macro). Keywords can be used in template expressions instead of attribute placeholders and also as a key in container lookups.
+* Filters and formatters do not throw exceptions by default when an attribute value cannot be used to complete the function (e.g. when the value is missing or has inappropriate type). The offending filter subexpression will return `false` in such cases, the formatter will result in empty string instead of the value. The behavior can be changed by calling `or_default` or `or_throw` member functions on the attribute value placeholder in the filtering/formatting expression.
+* Date and time formatter implementation is not based on __boost_date_time__ IO facets anymore. The new implementation improves formatting performance. The formatter has been renamed to [link log.detailed.expressions.formatters.date_time `format_date_time`].
+* Named scope formatter now supports scope format specification. The scope format can include the scope name, as well as file name and line number. The formatter has been renamed to [link log.detailed.expressions.formatters.named_scope `format_named_scope`].
+* [link log.detailed.expressions.formatters.decorators Character decorators] were renamed to `c_decor`, `c_ascii_decor`, `xml_decor` and `csv_decor`. The generic character decorator is named `char_decor` now.
+* Added a new [link log.detailed.expressions.predicates.channel_severity_filter channel severity filter]. The filter allows to setup severity thresholds for different channels. The filter checks log record severity level against the threshold corresponding to the channel the record belongs to.
+
+[*Documentation changes:]
+
+* Most code examples from the docs have been extracted into compilable standalone examples, which can be used for testing and experimenting with the library.
+* Added a lot of cross-references to the documentation, which should simplify navigation.
+
+[*Miscellaneous:]
+
+* Fixed a bug: the logging core could enter an infinite loop inside `push_record` if a sink throws and the exception is suppressed by the exception handler set in the core.
+* Changed the type dispatching implementation to reduce the usage of virtual functions. This greatly reduced the library size.
+* Type dispatchers made more friendly to the setups in which hidden visibility is set by default.
+* The interface of type dispatchers changed. The dispatcher now returns `type_visitor` instance by value, and the visitor is no longer a base for the actual receiver of the dispatched value. Instead, the visitor now refers to the receiver, if one is capable to consume the value. The `visit` method has been renamed to `operator ()`. The static type dispatcher now requires a reference to the receiver on construction, it doesn't imply that the receiver derives from the dispatcher anymore.
+* The `slim_string` utility has been removed. There is no replacement.
+* The library now uses many features from the latest C++ standard (aka C++11). For instance, many library components now support move semantics. __boost_move__ is used for move emulation on C++03-compatible compilers.
+
+[heading 1.1, 02 December 2011]
+
+This release mostly fixes bugs in the code and documentation.
+
+* Added support for __boost_filesystem__ v3.
+* A number of bugs fixed.
+* Corrections in the documentation.
+
+[heading 1.0, 09 May 2010]
+
+This release mostly fixes bugs in the code and documentation. The next major release (2.0) will contain breaking changes and feature additions. The 1.0 branch will not receive any feature updates.
+
+* Added some optimization for thread local storage. In Windows setups, if you dynamically load Boost.Log binaries during the application run time, this optimization may lead to crashes. In that case, you may disable it by defining `BOOST_LOG_NO_COMPILER_TLS` during the library build process. The macro also affects other platforms, which may be useful if your compiler does not support TLS.
+* Added a few public accessors and convenience constructors to severity and channel loggers.
+* Added ability to rotate log files at the specified time points. The `rotation_interval` keyword is no longer available. The same functionality is achieved with the new `time_based_rotation` keyword and the `rotation_at_time_interval` predicate. See [link log.detailed.sink_backends.text_file here] for more details.
+* Improved support for MinGW and Cygwin.
+* A number of bugs fixed. Added workarounds to compile on GCC 4.2.
+* Lots of corrections in the documentation.
+
+[heading Release Candidate 4, 08 Jan 2010]
+
+* Substantial documentation improvement. The tutorial section has been reorganized.
+* Library headers have been reorganized. Some other Boost libraries that were previously included by headers have been made optional. Such dependencies have been extracted into separate headers in the `support` directory. Top level library headers now mostly include nested headers.
+* Keywords have moved into a dedicated `keywords` namespace. There are no longer nested `keywords` namespaces in `sinks`, `attributes`, etc. All keywords have been extracted into separate headers in the `keywords` directory.
+* Removed rotating file stream. As a replacement, a [link log.detailed.sink_backends.text_file new file sink] has been added, which allows to achieve the same results ans adds a few more features.
+* Added a new [link log.detailed.sink_backends.text_multifile multifile] sink backend.
+* Added a new ordering asynchronous sink frontend.
+* The [link log.detailed.sink_backends.syslog syslog] sink backend is now supported on Windows, too. The sink no longer requires native support for POSIX API for syslog, but is able to send syslog packets to a remote server over UDP.
+* Loggers implementation has been improved. Feature composition mechanism has been cleaned up.
+* Added support for scoped logging. There is now a distinct [link log.detailed.core.record log record entity], which is returned by the core as a result of filtering. It is possible to fill in the record message in any way the user wants, not necessarilly with a streaming expression. The record object is now processed by sinks and formatters.
+* Added support for exception control. User can register exception handlers at one of the three layers: for a particular sink, at the core layer, and for a particular logger (given that it has the appropriate feature). Sinks and core will not suppress exceptions by default. Filter and formatters will throw if the requested attribute value is not found.
+* Added a few new formatters, called character decorators. These can be useful to post-process the formatted output before passing it on to the sink.
+* Added attributes for thread and process identifiers. These identifiers are automatically added after the call to `add_common_attributes`.
+* Helper initialization functions, such as `init_log_to_file` now accept more customization options as named arguments.
+* A new [link log.detailed.utilities.setup.settings initialization interface] has been exposed. One can fill a settings container and use it to initialize the library.
+* The library setup support code has beed extracted into a separate binary. Further on, this binary will be made optional to build.
+* Added a new mode of logging, called trivial logging. In this mode the library requires no initialization at all, however it does not offer many ways of customization.
+* A number of bugs fixed.
+* A few optimizations added to improve multithreaded applications performance.
+* Removed some bug workarounds for older Boost releases. The library now requires Boost 1.39 or newer.
+
+[heading Release Candidate 3, 08 Feb 2009]
+
+* Substantial documentation improvement.
+* Added several Windows-specific sinks: Event Log (simplified and advanced), Windows debugger and experimental Event Trace for Windows Vista and later.
+* Loggers now consist of a number of independent features that can be composed the way the user needs. User-defined features can be developed and injected into the mix.
+* Attribute value extractors improved. With the new extract function attribute values can be extracted from the attribute values view by employing lambda functors.
+* Some files and classes were moved or renamed to improve code clarity and shorten names.
+* A number of bugs fixed.
+* Added tests.
+
+[heading Release Candidate 2]
+
+Noone really remembers these dark ages...
+
+[endsect]

Added: trunk/libs/log/doc/core.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/log/doc/core.qbk 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,177 @@
+[/
+ Copyright Andrey Semashev 2007 - 2013.
+ 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)
+
+ This document is a part of Boost.Log library documentation.
+/]
+
+[section:core Core facilities]
+
+[section:record Logging records]
+
+ #include <``[boost_log_core_record_hpp]``>
+
+All the information that the logging library processes is packed into a single object of type [class_log_record]. All attached data, including the message text, is represented as named attribute values that can be fetched and processed by filters, formatters and sinks. Particular attribute values can be accessed in different ways, here are a few quick examples:
+
+* Through [link log.detailed.attributes.related_components.value_processing value visitation and extraction].
+
+[example_core_record_visitation_extraction]
+
+* By searching the [link log.detailed.attributes.related_components.attribute_value_set set of attribute values] accessible with the `attribute_values` method of the record.
+
+[example_core_record_attr_value_lookup]
+
+* By applying the subscript operator with the attribute keyword. This is actually a convenience wrapper around the value extraction API.
+
+[example_core_record_subscript]
+
+Log records cannot be copied, only moved. A record can be default-constructed in which case it is in an empty state; such records are mostly unusable and should not be passed to the library for processing. Non-empty log records can only be created by the [link log.detailed.core.core logging core] as a result of successful filtering. The non-empty record contains attribute values acquired from attributes. More attribute values can be added to the non-empty record after filtering. The added values will not affect filtering results but can still be used by formatters and sinks.
+
+In multithreaded environments, after being constructed a non-empty log record is considered to be tied to the current thread as it may refer to some thread-specific resources. For example, the record may contain an attribute value which refers to the named scope list which is stored on the stack. For this reason log records must not be passed between different threads.
+
+[heading Record views]
+
+ #include <``[boost_log_core_record_view_hpp]``>
+
+While records are used for filling the information, the library uses another type to actually process it. Record views provide a similar interface to records with a few notable distinctions:
+
+* Record views are immutable. This prevents formatters and sinks from modifying the record while it is being processed.
+* Record views are copyable. Since its contents are constant, the copy operation is shallow and therefore cheap.
+
+The library will automatically create a record view from the record by calling the `lock` method. The call will also make sure the resulting view is not attached to the current thread if a sink is asynchronous. The `lock` call is a one time operation; the record is left in the empty state afterwards. All APIs for interacting with attribute values described for log records are also applicable to record views and can be used in custom formatters and sinks.
+
+[endsect]
+
+[section:core Logging core]
+
+ #include <``[boost_log_core_core_hpp]``>
+
+The logging core is a central hub that provides the following facilities:
+
+* Maintains global and thread-specific attribute sets.
+* Performs global filtering of log records.
+* Dispatches log records between sinks by applying sink-specific filters.
+* Provides a global hook for exception handlers.
+* Provides an entry point for log sources to put log records to.
+* Provides the `flush` method that can be used to enforce the synchronized state for all log sinks.
+
+The logging core is an application-wide singleton, thus every logging source has access to it. The core instance is accessible with the static method `get`.
+
+ void foo()
+ {
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ // ...
+ }
+
+[section:attribute_sets Attribute sets]
+
+In order to add or remove global or thread-specific attributes to the core there are corresponding methods: `add_global_attribute`, `remove_global_attribute`, `add_thread_attribute` and `remove_thread_attribute`. Attribute sets provide interface similar to `std::map`, so the `add_*` methods accept an attribute name string (key) and a pointer to the attribute (mapped value) and return a pair of iterator and boolean value, like `std::map< ... >::insert` does. The `remove_*` methods accept an iterator to a previously added attribute.
+
+ void foo()
+ {
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ // Add a global attribute
+ std::pair< logging::attribute_set::iterator, bool > res =
+ core->add_global_attribute("LineID", attrs::counter< unsigned int >());
+
+ // ...
+
+ // Remove the added attribute
+ core->remove_global_attribute(res.first);
+ }
+
+[tip It must be said that all methods of logging core are thread-safe in multithreaded environments. However, that may not be true for other components, such as iterators or attribute sets.]
+
+It is possible to acquire a copy of the whole attribute set (global or thread-specific) or install it into the core. Methods `get_global_attributes`, `set_global_attributes`, `get_thread_attributes` and `set_thread_attributes` serve this purpose.
+
+[warning After installing a whole attribute set into the core, all iterators that were previously returned by the corresponding `add_*` methods are invalidated. In particular, it affects [link log.detailed.attributes.related_components.scoped_attributes scoped attributes], so the user must be careful when to switch attribute sets.]
+
+[endsect]
+
+[section:filtering Global filtering]
+
+Global filtering is handled by the filter function object, which can be provided with the `set_filter` method. More on creating filters appears in [link log.detailed.expressions.predicates this section]. Here it will suffice to say that the filter accepts a set of attribute values and returns a boolean value that tells whether a log record with these attribute values passed filtering or not. The global filter is applied to every log record made throughout the application, so it can be used to wipe out excessive log records quickly.
+
+The global filter can be removed by the `reset_filter` method. When there is no filter set in the core it is assumed that no records are filtered away. This is the default after initial construction of the logging core.
+
+ enum severity_level
+ {
+ normal,
+ warning,
+ error,
+ critical
+ };
+
+ void foo()
+ {
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ // Set a global filter so that only error messages are logged
+ core->set_filter(expr::attr< severity_level >("Severity") >= error);
+
+ // ...
+ }
+
+The core also provides another way to disable logging. By calling the `set_logging_enabled` with a boolean argument one may completely disable or reenable logging, including applying filtering. Disabling logging with this method may be more benefical in terms of application performance than setting a global filter that always fails.
+
+[endsect]
+
+[section:sinks Sink management]
+
+After global filtering is applied, log sinks step into action. In order to add and remove sinks the core provides `add_sink` and `remove_sink` methods. Both these methods accept a pointer to the sink. The `add_sink` will add the sink to the core if it's not added already. The `remove_sink` method will seek for the provided sink in an internal list of previously added sinks and remove the sink if it finds it. The order in which the core processes sinks internally is unspecified.
+
+ void foo()
+ {
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ // Set a sink that will write log records to the console
+ boost::shared_ptr< sinks::text_ostream_backend > backend =
+ boost::make_shared< sinks::text_ostream_backend >();
+ backend->add_stream(
+ boost::shared_ptr< std::ostream >(&std::clog, logging::empty_deleter()));
+
+ typedef sinks::unlocked_sink< sinks::text_ostream_backend > sink_t;
+ boost::shared_ptr< sink_t > sink = boost::make_shared< sink_t >(backend);
+ core->add_sink(sink);
+
+ // ...
+
+ // Remove the sink
+ core->remove_sink(sink);
+ }
+
+You can read more on the design of sinks in the following sections: [link log.detailed.sink_frontends Sink Frontends] and [link log.detailed.sink_backends Sink Backends].
+
+[endsect]
+
+[section:exception_handling Exception handling]
+
+The core provides a way to set up centralized exception handling. If an exception takes place during filtering or processing in one of the added sinks, the core will invoke an exception handler if one was installed with the `set_exception_handler` method. An exception handler is a nullary function object that is invoked from within a `catch` clause. The library provides [link log.detailed.utilities.exception_handlers tools] to simplify exception handlers construction.
+
+[tip The exception handler in the logging core is global and thus is intended to perform some common actions on errors. Logging sinks and sources also provide exception handling facilities (see [link log.detailed.sink_frontends.basic_services.exception_handling here] and [link log.detailed.sources.exception_handling here]), which can be used to do a finer grained error processing.]
+
+[example_utility_exception_handler]
+
+[endsect]
+
+[section:record_feeding Feeding log records]
+
+One of the most important functions of the logging core is providing an entry point for all logging sources to feed log records into. This is done with the `open_record` and `push_record` methods.
+
+The first method is used to initiate the record logging process. It accepts the source-specific set of attributes. The method constructs a common set of attribute values of the three sets of attributes (global, thread-specific and source-specific) and applies filtering. If the filtering succeeded, i.e. at least one sink accepts a record with these attribute values, the method returns a non-empty [link log.detailed.core.record record object], which can be used to fill in the log record message. If the filtering failed, an empty record object is returned.
+
+When the log source is ready to complete the logging procedure, it has to call the `push_record` method with the record returned by the `open_record` method. Note that one should not call `push_record` with an empty record. The record should be passed as rvalue reference. During the call the record view will be constructed from the record. The view will then be passed on to the sinks that accepted it during filtering. This may involve record formatting and further processing, like storing it into a file or sending it over the network. After that the record object can be destroyed.
+
+[example_core_core_manual_logging]
+
+All this logic is usually hidden in the loggers and macros provided by the library. However, this may be useful for those developing new log sources.
+
+[endsect]
+
+[endsect]
+
+[endsect]

Added: trunk/libs/log/doc/design.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/log/doc/design.qbk 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,54 @@
+[/
+ Copyright Andrey Semashev 2007 - 2013.
+ 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)
+
+ This document is a part of Boost.Log library documentation.
+/]
+
+[section:design Design overview]
+
+Boost.Log was designed to be very modular and extensible. It supports both narrow-character and wide-character logging. Both narrow and wide-character loggers provide similar capabilities, so through most of the documentation only the narrow-character interface will be described.
+
+The library consists of three main layers: the layer of log data collection, the layer of processing the collected data and the central hub that interconnects the former two layers. The design is presented on the figure below.
+
+[$images/log/Design.png]
+
+The arrows show the direction of logging information flow - from parts of your application, at the left, to the final storage, (if any) at the right. The storage is optional because the result of log processing may include some actions without actually storing the information anywhere. For example, if your application is in a critical state, it can emit a special log record that will be processed so that the user sees an error message as a tool-tip notification over the application icon in the system tray and hears an alarming sound. This is a very important library feature: it is orthogonal to collecting, processing logging data and, in fact, what data logging records consist of. This allows for use of the library not only for classic logging, but to indicate some important events to the application user and accumulate statistical data.
+
+[heading Logging sources]
+
+Getting back to the figure, in the left side your application emits log records with help of loggers - special objects that provide streams to format messages that will eventually be put to log. The library provides a number of different logger types and you can craft many more yourself, extending the existing ones. Loggers are designed as a mixture of distinct features that can be combined with each other in any combination. You can simply develop your own feature and add it to the soup. You will be able to use the constructed logger just like the others - embed it into your application classes or create and use a global instance of the logger. Either approach provides its benefits. Embedding a logger into some class provides a way to differentiate logs from different instances of the class. On the other hand, in functional-style programming it is usually more convenient to have a single global logger somewhere and have a simple access to it.
+
+Generally speaking, the library does not require the use of loggers to write logs. The more generic term "log source" designates the entity that initiates logging by constructing a log record. Other log sources might include captured console output of a child application or data received from network. However, loggers are the most common kind of log sources.
+
+[heading Attributes and attribute values]
+
+In order to initiate logging a log source must pass all data, associated with the log record, to the logging core. This data or, more precisely, the logic of the data acquisition is represented with a set of named attributes. Each attribute is, basically, a function, whose result is called "attribute value" and is actually processed on further stages. An example of an attribute is a function that returns the current time. Its result - the particular time point - is the attribute value.
+
+There are three kinds of attribute sets:
+
+* global
+* thread-specific
+* source-specific
+
+You can see in the figure that the former two sets are maintained by the logging core and thus need not be passed by the log source in order to initiate logging. Attributes that participate in the global attribute set are attached to any log record ever made. Obviously, thread-specific attributes are attached only to the records made from the thread in which they were registered in the set. The source-specific attribute set is maintained by the source that initiates logging, these attributes are attached only to the records being made through that particular source.
+
+When a source initiates logging, attribute values are acquired from attributes of all three attribute sets. These attribute values then form a single set of named attribute values, which is processed further. You can add more attribute values to the set; these values will only be attached to the particular log record and will not be associated with the logging source or logging core. As you may notice, it is possible for a same-named attribute to appear in several attribute sets. Such conflicts are solved on priority basis: global attributes have the least priority, source-specific attributes have the highest; the lower priority attributes are discarded from consideration in case of conflicts.
+
+[heading Logging core and filtering]
+
+When the set of attribute values is composed, the logging core decides if this log record is going to be processed in sinks. This is called filtering. There are two layers of filtering available: the global filtering is applied first within the logging core itself and allows quickly wiping away unneeded log records; the sink-specific filtering is applied second, for each sink separately. The sink-specific filtering allows directing log records to particular sinks. Note that at this point it is not significant which logging source emitted the record, the filtering relies solely on the set of attribute values attached to the record.
+
+It must be mentioned that for a given log record filtering is performed only once. Obviously, only those attribute values attached to the record before filtering starts can participate in filtering. Some attribute values, like log record message, are typically attached to the record after the filtering is done; such values cannot be used in filters, they can only be used by formatters and sinks themselves.
+
+[heading Sinks and formatting]
+
+If a log record passes filtering for at least one sink the record is considered to be consumable. If the sink supports formatted output, this is the point when log message formatting takes place. The formatted message along with the composed set of attribute values is passed to the sink that accepted the record. Note that formatting is performed on the per-sink basis so that each sink can output log records in its own specific format.
+
+As you may have noticed on the figure above, sinks consist of two parts: the frontend and the backend. This division is made in order to extract the common functionality of sinks, such as filtering, formatting and thread synchronization, into separate entities (frontends). Sink frontends are provided by the library, most likely users won't have to re-implement them. Backends, on the other hand, are one of the most likely places for extending the library. It is sink backends that do the actual processing of log records. There can be a sink that stores log records into a file; there can be a sink that sends log records over the network to the remote log processing node; there can be the aforementioned sink that puts record messages into tool-tip notifications - you name it. The most commonly used sink backends are already provided by the library.
+
+Along with the primary facilities described above, the library provides a wide variety of auxiliary tools, such as attributes, support for formatters and filters, represented as lambda expressions, and even basic helpers for the library initialization. You will find their description in the [link log.detailed Detailed features description] section. However, for new users it is recommended to start discovering the library from the [link log.tutorial Tutorial] section.
+
+[endsect]

Added: trunk/libs/log/doc/expressions.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/log/doc/expressions.qbk 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,568 @@
+[/
+ Copyright Andrey Semashev 2007 - 2013.
+ 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)
+
+ This document is a part of Boost.Log library documentation.
+/]
+
+[section:expressions Lambda expressions]
+
+As it was pointed out in [link log.tutorial tutorial], filters and formatters can be specified as Lambda expressions with placeholders for attribute values. This section will describe the placeholders that can be used to build more complex Lambda expressions.
+
+There is also a way to specify the filter in the form of a string template. This can be useful for initialization from the application settings. This part of the library is described [link log.detailed.utilities.setup.filter_formatter here].
+
+[section:attr Generic attribute placeholder]
+
+ #include <``[boost_log_expressions_attr_fwd_hpp]``>
+ #include <``[boost_log_expressions_attr_hpp]``>
+
+The [funcref boost::log::expressions::attr attr] placeholder represents an attribute value in template expressions. Given the record view or a set of attribute values, the placeholder will attempt to extract the specified attribute value from the argument upon invokation. This can be roughly described with the following pseudo-code:
+
+ logging::value_ref< T, TagT > val = expr::attr< T, TagT >(name)(rec);
+
+where `val` is the [link log.detailed.utilities.value_ref reference] to the extracted value, `name` and `T` are the attribute value [link log.detailed.attributes.related_components.attribute_name name] and type, `TagT` is an optional tag (we'll return to it in a moment) and `rec` is the log [link log.detailed.core.record record view] or [link log.detailed.attributes.related_components.attribute_value_set attribute value set]. `T` can be a __boost_mpl__ type sequence with possible expected types of the value; the extraction will succeed if the type of the value matches one of the types in the sequence.
+
+The `attr` placeholder can be used in __boost_phoenix__ expressions, including the `bind` expression.
+
+[example_tutorial_filtering_bind]
+
+The placeholder can be used both in filters and formatters:
+
+ sink->set_filter
+ (
+ expr::attr< int >("Severity") >= 5 &&
+ expr::attr< std::string >("Channel") == "net"
+ );
+
+ sink->set_formatter
+ (
+ expr::stream
+ << expr::attr< int >("Severity")
+ << " [" << expr::attr< std::string >("Channel") << "] "
+ << expr::smessage
+ );
+
+The call to `set_filter` registers a composite filter that consists of two elementary subfilters: the first one checks the severity level, and the second checks the channel name. The call to `set_formatter` installs a formatter that composes a string containing the severity level and the channel name along with the message text.
+
+[heading Customizing fallback policy]
+
+By default, when the requested attribute value is not found in the record, `attr` will return an empty reference. In case of filters, this will result in `false` in any ordering expressions, and in case of formatters the output from the placeholder will be empty. This behavior can be changed:
+
+* To throw an exception ([class_log_missing_value] or [class_log_invalid_type], depending on the reason of the failure). Add the `or_throw` modifier:
+
+ sink->set_filter
+ (
+ expr::attr< int >("Severity").or_throw() >= 5 &&
+ expr::attr< std::string >("Channel").or_throw() == "net"
+ );
+
+* To use a default value instead. Add the `or_default` modifier with the desired default value:
+
+ sink->set_filter
+ (
+ expr::attr< int >("Severity").or_default(0) >= 5 &&
+ expr::attr< std::string >("Channel").or_default(std::string("general")) == "net"
+ );
+
+[tip You can also use the [link log.detailed.expressions.predicates.has_attr `has_attr`] predicate to implement filters and formatters conditional on the attribute value presence.]
+
+The default behavior is also accessible through the `or_none` modifier. The modified placeholders can be used in filters and formatters just the same way as the unmodified ones.
+
+In `bind` expressions, the bound function object will still receive the [link log.detailed.utilities.value_ref `value_ref`]-wrapped values in place of the modified `attr` placeholder. Even though both `or_throw` and `or_default` modifiers guarantee that the bound function will receive a filled reference, [link log.detailed.utilities.value_ref `value_ref`] is still needed if the value type is specified as a type sequence. Also, the reference wrapper may contain a tag type which may be useful for formatting customization.
+
+[heading Attribute tags and custom formatting operators]
+
+The `TagT` type in the [link log.detailed.expressions.attr abstract description] of `attr` above is optional and by default is `void`. This is an attribute tag which can be used to customize the output formatters produce for different attributes. This tag is forwarded to the [link log.detailed.utilities.manipulators.to_log `to_log`] manipulator when the extracted attribute value is put to a stream (this behavior is warranted by [link log.detailed.utilities.value_ref `value_ref`] implementation). Here's a quick example:
+
+[example_expressions_attr_formatter_stream_tag]
+
+[@boost:/libs/log/example/doc/expressions_attr_fmt_tag.cpp See the complete code].
+
+Here we specify a different formatting operator for the severity level wrapped in the [link log.detailed.utilities.manipulators.to_log `to_log_manip`] manipulator marked with the tag `severity_tag`. This operator will be called when log records are formatted while the regular `operator<<` will be used in other contexts.
+
+[endsect]
+
+[section:attr_keywords Defining attribute keywords]
+
+ #include <``[boost_log_expressions_keyword_fwd_hpp]``>
+ #include <``[boost_log_expressions_keyword_hpp]``>
+
+Attribute keywords can be used as replacements for the [link log.detailed.expressions.attr `attr`] placeholders in filters and formatters while providing a more concise and less error prone syntax. An attribute keyword can be declared with the [macroref BOOST_LOG_ATTRIBUTE_KEYWORD] macro:
+
+ BOOST_LOG_ATTRIBUTE_KEYWORD(keyword, "Keyword", type)
+
+Here the macro declares a keyword `keyword` for an attribute named "Keyword" with the value type of `type`. Additionally, the macro defines an attribute tag type `keyword` within the `tag` namespace. We can rewrite the previous example in the following way:
+
+[example_expressions_keyword_formatter_stream_tag]
+
+Attribute keywords behave the same way as the [link log.detailed.expressions.attr `attr`] placeholders and can be used both in filters and formatters. The `or_throw` and `or_default` modifiers are also supported.
+
+Keywords can also be used in attribute value lookup expressions in log records and attribute value sets:
+
+[example_expressions_keyword_lookup]
+
+[endsect]
+
+[section:record Record placeholder]
+
+ #include <``[boost_log_expressions_record_hpp]``>
+
+The `record` placeholder can be used in `bind` expressions to pass the whole log [link log.detailed.core.record record view] to the bound function object.
+
+ void my_formatter(logging::formatting_ostream& strm, logging::record_view const& rec)
+ {
+ // ...
+ }
+
+ namespace phoenix = boost::phoenix;
+ sink->set_formatter(phoenix::bind(&my_formatter, expr::stream, expr::record));
+
+[note In case of filters, the placeholder will correspond to the [link log.detailed.attributes.related_components.attribute_value_set set of attribute values] rather than the log record itself. This is because the record is not constructed yet at the point of filtering, and filters only operate on the set of attribute values.]
+
+[endsect]
+
+[section:message Message text placeholders]
+
+ #include <``[boost_log_expressions_message_hpp]``>
+
+Log records typically contain a special attribute "Message" with the value of one of the string types (more specifically, an `std::basic_string` specialization). This attribute contains the text of the log message that is constructed at the point of the record creation. This attribute is only constructed after filtering, so filters cannot use it. There are several keywords to access this attribute value:
+
+* `smessage` - the attribute value is expected to be an `std::string`
+* `wmessage` - the attribute value is expected to be an `std::wstring`
+* `message` - the attribute value is expected to be an `std::string` or `std::wstring`
+
+The `message` keyword has to dispatch between different string types, so it is slightly less efficient than the other two keywords. If the application is able to guarantee the fixed character type of log messages, it is advised to use the corresponding keyword for better performance.
+
+ // Sets up a formatter that will ignore all attributes and only print log record text
+ sink->set_formatter(expr::stream << expr::message);
+
+[endsect]
+
+[section:predicates Predicate expressions]
+
+This section describes several expressions that can be used as predicates in the filtering expressions.
+
+[section:has_attr Attribute presence filter]
+
+ #include <``[boost_log_expressions_predicates_has_attr_hpp]``>
+
+The filter [funcref boost::log::expressions::has_attr `has_attr`] checks if an attribute value with the specified name and, optionally, type is attached to a log record. If no type specified to the filter, the filter returns `true` if any value with the specified name is found. If an MPL-compatible type sequence in specified as a value type, the filter returns `true` if a value with the specified name and one of the specified types is found.
+
+This filter is usually used in conjunction with [link log.detailed.expressions.formatters.conditional conditional formatters], but it also can be used as a quick filter based on the log record structure. For example, one can use this filter to extract statistic records and route them to a specific sink.
+
+[example_expressions_has_attr_stat_accumulator]
+
+[@boost:/libs/log/example/doc/expressions_has_attr_stat_accum.cpp See the complete code].
+
+In this example, log records emitted with the `PUT_STAT` macto will be directed to the `my_stat_accumulator` sink backend, which will accumulate the changes passed in the "Change" attribute values. All other records (even those made through the same logger) will be passed to the filte sink. This is achieved with the mutually exclusive filters set for the two sinks.
+
+Please note that in the example above we extended the library in two ways: we defined a new sink backend `my_stat_accumulator` and a new macro `PUT_STAT`. Also note that `has_attr` can accept attribute keywords to identify the attribute to check.
+
+[endsect]
+
+[section:is_in_range Range checking filter]
+
+ #include <``[boost_log_expressions_predicates_is_in_range_hpp]``>
+
+The [funcref boost::log::expressions::is_in_range `is_in_range`] predicate checks that the attribute value fits in the half-open range (i.e. it returns `true` if the attribute value `x` satisfies the following condition: `left <= x < right`). For example:
+
+ sink->set_filter
+ (
+ // drops all records that have level below 3 or greater than 4
+ expr::is_in_range(expr::attr< int >("Severity"), 3, 5)
+ );
+
+The attribute can also be identified by an attribute keyword or name and type:
+
+ sink->set_filter
+ (
+ expr::is_in_range(severity, 3, 5)
+ );
+
+ sink->set_filter
+ (
+ expr::is_in_range< int >("Severity", 3, 5)
+ );
+
+[endsect]
+
+[section:simple_string_matching Simple string matching filters]
+
+ #include <``[boost_log_expressions_predicates_begins_with_hpp]``>
+ #include <``[boost_log_expressions_predicates_ends_with_hpp]``>
+ #include <``[boost_log_expressions_predicates_contains_hpp]``>
+
+Predicates [funcref boost::log::expressions::begins_with `begins_with`], [funcref boost::log::expressions::ends_with `ends_with`] and [funcref boost::log::expressions::contains `contains`] provide an easy way of matching string attribute values. As follows from their names, the functions construct filters that return `true` if an attribute value begins with, ends with or contains the specified substring, respectively. The string comparison is case sensitive.
+
+ sink->set_filter
+ (
+ // selects only records that are related to Russian web domains
+ expr::ends_with(expr::attr< std::string >("Domain"), ".ru")
+ );
+
+The attribute can also be identified by an attribute keyword or name and type.
+
+[endsect]
+
+[section:advanced_string_matching Advanced string matching filter]
+
+ #include <``[boost_log_expressions_predicates_matches_hpp]``>
+
+ // Supporting headers
+ #include <``[boost_log_support_regex_hpp]``>
+ #include <``[boost_log_support_xpressive_hpp]``>
+ #include <``[boost_log_support_spirit_qi_hpp]``>
+ #include <``[boost_log_support_spirit_classic_hpp]``>
+
+The [funcref boost::log::expressions::matches `matches`] function creates a filter that apples a regular expression or a parser to a string attribute value. The regular expression can be provided by __boost_regex__ or __boost_xpressive__. Parsers from __boost_spirit__ and __boost_spirit2__ are also supported. The filter returns `true` if the regular expression matches or the parser successfully parses the attribute value.
+
+[note In order to use this predicate, a corresponding supporting header should also be included.]
+
+ sink->set_filter
+ (
+ expr::matches(expr::attr< std::string >("Domain"), boost::regex("www\\..*\\.ru"))
+ );
+
+The attribute can also be identified by an attribute keyword or name and type.
+
+[endsect]
+
+[section:channel_severity_filter Severity threshold per channel filter]
+
+ #include <``[boost_log_expressions_predicates_channel_severity_filter_hpp]``>
+
+This filter is aimed for a specific but commonly encountered use case. The [funcref boost::log::expressions::channel_severity_filter `channel_severity_filter`] function creates a predicate that will check log record severity levels against a threshold. The predicate allows setting different thresholds for different channels. The mapping between channel names and severity thresholds can be filled in `std::map` style by using the subscript operator or by calling `add` method on the filter itself (the [class_expressions_channel_severity_filter_actor] instance). Let's see an example:
+
+[example_expressions_channel_severity_filter]
+
+[@boost:/libs/log/example/doc/expressions_channel_severity_filter.cpp See the complete code].
+
+The filter for the console sink is composed from the [class_expressions_channel_severity_filter_actor] filter and a general severity level check. This general check will be used when log records do not have a channel attribute or the channel name is not one of those specified in [class_expressions_channel_severity_filter_actor] initialization. It should be noted that it is possible to set the default result of the threshold filter that will be used in this case; the default result can be set by the `set_default` method. The [class_expressions_channel_severity_filter_actor] filter is set up to limit record severity levels for channels "general", "network" and "gui" - all records in these channels with levels below the specified thresholds will not pass the filter and will be ignored.
+
+The threshold filter is implemented as an equivalent to `std::map` over the channels, which means that the channel value type must support partial ordering. Obviously, the severity level type must also support ordering to be able to be compared against thresholds. By default the predicate will use `std::less` equivalent for channel name ordering and `std::greater_equal` equivalent to compare severity levels. It is possible to customize the ordering predicates. Consult the reference of the [class_expressions_channel_severity_filter_actor] class and [funcref boost::log::expressions::channel_severity_filter `channel_severity_filter`] generator to see the relevant template parameters.
+
+[endsect]
+
+[section:is_debugger_present Debugger presence filter]
+
+ #include <``[boost_log_expressions_predicates_is_debugger_present_hpp]``>
+
+This filter is implemented for Windows only. The `is_debugger_present` filter returns `true` if the application is run under a debugger and `false` otherwise. It does not use any attribute values from the log record. This predicate is typically used with the [link log.detailed.sink_backends.debugger debugger output] sink.
+
+[example_sinks_debugger]
+
+[@boost:/libs/log/example/doc/sinks_debugger.cpp See the complete code].
+
+[endsect]
+
+[endsect]
+
+[section:formatters Formatting expressions]
+
+As was noted in the [link log.tutorial.formatters tutorial], the library provides several ways of expressing formatters, most notable being with a stream-style syntax and __boost_format__-style expression. Which of the two formats is chosen is determined by the appropriate anchor expression. To use stream-style syntax one should begin the formatter definition with the `stream` keyword, like that:
+
+ #include <``[boost_log_expressions_formatters_stream_hpp]``>
+
+ sink->set_formatter(expr::stream << expr1 << expr2 << ... << exprN);
+
+Here expressions `expr1` through `exprN` may be either manipulators, described in this section, or other expressions resulting in an object that supports putting into an STL-stream.
+
+To use __boost_format__-style syntax one should use `format` construct:
+
+ #include <``[boost_log_expressions_formatters_format_hpp]``>
+
+ sink->set_formatter(expr::format("format string") % expr1 % expr2 % ... % exprN);
+
+The format string passed to the `format` keyword should contain positional placeholders for the appropriate expressions. In the case of wide-character logging the format string should be wide. Expressions `expr1` through `exprN` have the same meaning as in stream-like variant. It should be noted though that using stream-like syntax usually results in a faster formatter than the one constructed with the `format` keyword.
+
+Another useful way of expressing formatters is by using string templates. This part of the library is described in [link log.detailed.utilities.setup.filter_formatter this] section and is mostly intended to support initialization from the application settings.
+
+[section:date_time Date and time formatter]
+
+ #include <``[boost_log_expressions_formatters_date_time_hpp]``>
+
+ // Supporting headers
+ #include <``[boost_log_support_date_time_hpp]``>
+
+The library provides the [funcref boost::log::expressions::format_date_time `format_date_time`] formatter dedicated to date and time-related attribute value types. The function accepts the attribute value name and the format string compatible with __boost_date_time__.
+
+ sink->set_formatter
+ (
+ expr::stream << expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S")
+ );
+
+The attribute value can alternatively be identified with the [link log.detailed.expressions.attr `attr`] placeholder or the [link log.detailed.expressions.attr_keywords attribute keyword].
+
+The following placeholders are supported in the format string:
+
+[table Date format placeholders
+ [[Placeholder][Meaning][Example]]
+ [[%a] [Abbreviated weekday name]["Mon" => Monday]]
+ [[%A] [Long weekday name]["Monday"]]
+ [[%b] [Abbreviated month name]["Feb" => February]]
+ [[%B] [Long month name]["February"]]
+ [[%d] [Numeric day of month with leading zero]["01"]]
+ [[%e] [Numeric day of month with leading space][" 1"]]
+ [[%m] [Numeric month, 01-12]["01"]]
+ [[%w] [Numeric day of week, 1-7]["1"]]
+ [[%y] [Short year]["12" => 2012]]
+ [[%Y] [Long year]["2012"]]
+]
+
+[table Time format placeholders
+ [[Placeholder][Meaning][Example]]
+ [[%f] [Fractional seconds with leading zeros]["000231"]]
+ [[%H, %O] [Hours in 24 hour clock or hours in time duration types with leading zero if less than 10]["07"]]
+ [[%I] [Hours in 12 hour clock with leading zero if less than 10]["07"]]
+ [[%k] [Hours in 24 hour clock or hours in time duration types with leading space if less than 10][" 7"]]
+ [[%l] [Hours in 12 hour clock with leading space if less than 10][" 7"]]
+ [[%M] [Minutes]["32"]]
+ [[%p] [AM/PM mark, uppercase]["AM"]]
+ [[%P] [AM/PM mark, lowercase]["am"]]
+ [[%q] [ISO time zone]["-0700" => Mountain Standard Time]]
+ [[%Q] [Extended ISO time zone]["-05:00" => Eastern Standard Time]]
+ [[%S] [Seconds]["26"]]
+]
+
+[table Miscellaneous placeholders
+ [[Placeholder][Meaning][Example]]
+ [[%-] [Negative sign in case of time duration, if the duration is less than zero]["-"]]
+ [[%+] [Sign of time duration, even if positive]["+"]]
+ [[%%] [An escaped percent sign]["%"]]
+ [[%T] [Extended ISO time, equivalent to "%H:%M:%S"]["07:32:26"]]
+]
+
+Note that in order to use this formatter you will also have to include a supporting header. When [boost_log_support_date_time_hpp] is included, the formatter supports the following types of __boost_date_time__:
+
+* Date and time types: `boost::posix_time::ptime` and `boost::local_time::local_date_time`.
+* Gregorian date type: `boost::gregorian::date`.
+* Time duration types: `boost::posix_time::time_duration` as well as all the specialized time units such as `boost::posix_time::seconds`, including subsecond units.
+* Date duration types: `boost::gregorian::date_duration`.
+
+[tip __boost_date_time__ already provides formatting functionality implemented as a number of locale facets. This functionality can be used instead of this formatter, although the formatter is expected to provide better performance.]
+
+[endsect]
+
+[section:named_scope Named scope formatter]
+
+ #include <``[boost_log_expressions_formatters_named_scope_hpp]``>
+
+The formatter [funcref boost::log::expressions::format_named_scope `format_named_scope`] is intended to add support for flexible formatting of the [link log.detailed.attributes.named_scope named scope] attribute values. The basic usage is quite straightforward and its result is similar to what [link log.detailed.expressions.attr `attr`] provides:
+
+ // Puts the scope stack from outer ones towards inner ones: outer scope -> inner scope
+ sink->set_formatter(expr::stream << expr::format_named_scope("Scopes", "%n"));
+
+The first argument names the attribute and the second is the format string. The string can contain the following placeholders:
+
+[table Named scope format placeholders
+ [[Placeholder][Meaning][Example]]
+ [[%n] [Scope name]["void foo()"]]
+ [[%f] [Source file name of the scope]["foo.cpp"]]
+ [[%l] [Line number in the source file]["45"]]
+]
+
+While the format string describes the presentation of each named scope in the list, the following named arguments allow to customize the list traversal and formatting:
+
+* `format`. The named scope format string, as described above. This parameter is used to specify the format when other named parameters are used.
+* `iteration`. The argument describes the direction of iteration through scopes. Can have values `forward` (default) or `reverse`.
+* `delimiter`. The argument can be used to specify the delimiters between scopes. The default delimiter depends on the `iteration` argument. If `iteration == forward` the default `delimiter` will be "->", otherwise it will be "<-".
+* `depth`. The argument can be used to limit the number of scopes to put to log. The formatter will print `depth` innermost scopes and, if there are more scopes left, append an ellipsis to the written sequence. By default the formatter will write all scope names.
+
+Here are a few usage examples:
+
+ // Puts the scope stack in reverse order:
+ // inner scope (file:line) <- outer scope (file:line)
+ sink->set_formatter
+ (
+ expr::stream
+ << expr::format_named_scope(
+ "Scopes",
+ keywords::format = "%n (%f:%l)",
+ keywords::iteration = expr::reverse)
+ );
+
+ // Puts the scope stack in reverse order with a custom delimiter:
+ // inner scope | outer scope
+ sink->set_formatter
+ (
+ expr::stream
+ << expr::named_scope(
+ "Scopes",
+ keywords::format = "%n",
+ keywords::iteration = expr::reverse,
+ keywords::delimiter = " | ")
+ );
+
+ // Puts the scope stack in forward order, no more than 2 inner scopes:
+ // ... -> outer scope -> inner scope
+ sink->set_formatter
+ (
+ expr::stream
+ << expr::named_scope(
+ "Scopes",
+ keywords::format = "%n",
+ keywords::iteration = expr::forward,
+ keywords::depth = 2)
+ );
+
+ // Puts the scope stack in reverse order, no more than 2 inner scopes:
+ // inner scope <- outer scope <- ...
+ sink->set_formatter
+ (
+ expr::stream
+ << expr::named_scope(
+ "Scopes",
+ keywords::format = "%n",
+ keywords::iteration = expr::reverse,
+ keywords::depth = 2)
+ );
+
+[endsect]
+
+[section:conditional Conditional formatters]
+
+ #include <``[boost_log_expressions_formatters_if_hpp]``>
+
+There are cases when one would want to check some condition about the log record and format it depending on that condition. One example of such a need is formatting an attribute value depending on its runtime type. The general syntax of the conditional formatter is as follows:
+
+ expr::if_ (filter)
+ [
+ true_formatter
+ ]
+ .else_
+ [
+ false_formatter
+ ]
+
+Those familiar with __boost_phoenix__ lambda expressions will find this syntax quite familiar. The `filter` argument is a filter that is applied to the record being formatted. If it returns `true`, the `true_formatter` is executed, otherwise `false_formatter` is executed. The `else_` section with `false_formatter` is optional. If it is omitted and `filter` yields `false`, no formatter is executed. Here is an example:
+
+ sink->set_formatter
+ (
+ expr::stream
+ // First, put the current time
+ << expr::format_date_time("TimeStamp", "%Y-%m-%d %H:%M:%S.%f") << " "
+ << expr::if_ (expr::has_attr< int >("ID"))
+ [
+ // if "ID" is present then put it to the record
+ expr::stream << expr::attr< int >("ID")
+ ]
+ .else_
+ [
+ // otherwise put a missing marker
+ expr::stream << "--"
+ ]
+ // and after that goes the log record text
+ << " " << expr::message
+ );
+
+[endsect]
+
+[section:decorators Character decorators]
+
+There are times when one would like to additionally post-process the composed string before passing it to the sink backend. For example, in order to store log into an XML file the formatted log record should be checked for special characters that have a special meaning in XML documents. This is where decorators step in.
+
+[note Unlike most other formatters, decorators are dependent on the character type of the formatted output and this type cannot be deduced from the decorated formatter. By default, the character type is assumed to be `char`. If the formatter is used to compose a wide-character string, prepend the decorator name with the `w` letter (e.g. use `wxml_decor` instead of `xml_decor`). Also, for each decorator there is a generator function that accepts the character type as a template parameter; the function is named similarly to the decorator prepended with the `make_` prefix (e.g. `make_xml_decor`).]
+
+[heading XML character decorator]
+
+ #include <``[boost_log_expressions_formatters_xml_decorator_hpp]``>
+
+This decorator replaces XML special characters (&, <, > and \') with the corresponding tokens (`&amp;`, `&lt;`, `&gt;` and `&apos;`, correspondingly). The usage is as follows:
+
+ xml_sink->set_formatter
+ (
+ // Apply the decoration to the whole formatted record
+ expr::xml_decor
+ [
+ expr::stream << expr::message
+ ]
+ );
+
+Since character decorators are yet another kind of formatters, it's fine to use them in other contexts where formatters are appropriate. For example, this is also a valid example:
+
+ xml_sink->set_formatter
+ (
+ expr::format("<message>%1%: %2%</message>")
+ % expr::attr< unsigned int >("LineID")
+ % expr::xml_decor[ expr::stream << expr::message ]; // Only decorate the message text
+ );
+
+There is an example of the library set up for logging into an XML file, see [@boost:/libs/log/example/doc/sinks_xml_file.cpp here].
+
+[heading CSV character decorator]
+
+ #include <``[boost_log_expressions_formatters_csv_decorator_hpp]``>
+
+This decorator allows to ensure that the resulting string conforms to the [@http://en.wikipedia.org/wiki/Comma-separated_values CSV] format requirements. In particular, it duplicates the quote characters in the formatted string.
+
+ csv_sink->set_formatter
+ (
+ expr::stream
+ << expr::attr< unsigned int >("LineID") << ","
+ << expr::csv_decor[ expr::stream << expr::attr< std::string >("Tag") ] << ","
+ << expr::csv_decor[ expr::stream << expr::message ]
+ );
+
+[heading C-style character decorators]
+
+ #include <``[boost_log_expressions_formatters_c_decorator_hpp]``>
+
+The header defines two character decorators: `c_decor` and `c_ascii_decor`. The first one replaces the following characters with their escaped counerparts: \\ (backslash, 0x5c), \\a (bell character, 0x07), \\b (backspace, 0x08), \\f (formfeed, 0x0c), \\n (newline, 0x0a), \\r (carriage return, 0x0d), \\t (horizontal tabulation, 0x09), \\v (vertical tabulation, 0x0b), \' (apostroph, 0x27), \" (quote, 0x22), ? (question mark, 0x3f). The `c_ascii_decor` decorator does the same but also replaces all other non-printable and non-ASCII characters with escaped hexadecimal character codes in C notation (e.g. "\\x8c"). The usage is similar to other character decorators:
+
+ sink->set_formatter
+ (
+ expr::stream
+ << expr::attr< unsigned int >("LineID") << ": ["
+ << expr::c_decor[ expr::stream << expr::attr< std::string >("Tag") ] << "] "
+ << expr::c_ascii_decor[ expr::stream << expr::message ]
+ );
+
+[heading General character decorator]
+
+ #include <``[boost_log_expressions_formatters_char_decorator_hpp]``>
+
+This decorator allows the user to define his own character replacement mapping in one of the two forms. The first form is a range of `std::pair`s of strings (which can be C-style strings or ranges of characters, including `std::string`s). The strings in the `first` elements of pairs will be replaced with the `second` elements of the corresponding pair.
+
+ std::array< std::pair< const char*, const char* >, 3 > shell_escapes =
+ {
+ { "\"", "\\\"" },
+ { "'", "\\'" },
+ { "$", "\\$" }
+ };
+
+ sink->set_formatter
+ (
+ expr::char_decor(shell_escapes)
+ [
+ expr::stream << expr::message
+ ]
+ );
+
+The second form is two same-sized sequences of strings; the first containing the search patterns and the second - the corresponding replacements.
+
+ std::array< const char*, 3 > shell_patterns =
+ {
+ "\"", "'", "$"
+ };
+ std::array< const char*, 3 > shell_replacements =
+ {
+ "\\\"", "\\'", "\\$"
+ };
+
+ sink->set_formatter
+ (
+ expr::char_decor(shell_patterns, shell_replacements)
+ [
+ expr::stream << expr::message
+ ]
+ );
+
+In both cases the patterns are not interpreted and are sought in the formatted characters in the original form.
+
+[endsect]
+
+[endsect]
+
+[endsect]

Added: trunk/libs/log/doc/extension.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/log/doc/extension.qbk 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,364 @@
+[/
+ Copyright Andrey Semashev 2007 - 2013.
+ 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)
+
+ This document is a part of Boost.Log library documentation.
+/]
+
+[section:extension Extending the library]
+
+[section:sinks Writing your own sinks]
+
+ #include <``[boost_log_sinks_basic_sink_backend_hpp]``>
+
+As was described in the [link log.design Design overview] section, sinks consist of two parts: frontend and backend. Frontends are provided by the library and usually do not need to be reimplemented. Thanks to frontends, implementing backends is much easier than it could be: all filtering, formatting and thread synchronization is done there.
+
+In order to develop a sink backend, you derive your class from either [class_sinks_basic_sink_backend] or [class_sinks_basic_formatted_sink_backend], depending on whether your backend requires formatted log records or not. Both base classes define a set of types that are required to interface with sink frontends. One of these types is `frontend_requirements`.
+
+[heading Frontend requirements]
+
+ #include <``[boost_log_sinks_frontend_requirements_hpp]``>
+
+In order to work with sink backends, frontends use the `frontend_requirements` type defined by all backends. The type combines one or several requirement tags:
+
+* [class_sinks_synchronized_feeding]. If the backend has this requirement, it expects log records to be passed from frontend in synchronized manner (i.e. only one thread should be feeding a record at a time). Note that different threads may be feeding different records, the requirement merely states that there will be no concurrent feeds.
+* [class_sinks_concurrent_feeding]. This requirement extends [class_sinks_synchronized_feeding] by allowing different threads to feed records concurrently. The backend implements all necessary thread synchronization in this case.
+* [class_sinks_formatted_records]. The backend expects formatted log records. The frontend implements formatting to a string with character type defined by the `char_type` typedef within the backend. The formatted string will be passed along with the log record to the backend. The [class_sinks_basic_formatted_sink_backend] base class automatically adds this requirement to the `frontend_requirements` type.
+* [class_sinks_flushing]. The backend supports flushing its internal buffers. If the backend indicates this requirement it has to implement the `flush` method taking no arguments; this method will be called by the frontend when flushed.
+
+[tip By chosing either of the thread synchronization requirements you effectively allow or prohibit certain [link log.detailed.sink_frontends sink frontends] from being used with your backend.]
+
+Multiple requirements can be combined into `frontend_requirements` type with the [class_sinks_combine_requirements] metafunction:
+
+ typedef sinks::combine_requirements<
+ sinks::synchronized_feeding,
+ sinks::formatted_records,
+ sinks::flushing
+ >::type frontend_requirements;
+
+It must be noted that [class_sinks_synchronized_feeding] and [class_sinks_concurrent_feeding] should not be combined together as it would make the synchronization requirement ambiguous. The [class_sinks_synchronized_feeding] is a more strict requirement than [class_sinks_concurrent_feeding], so whenever the backend requires concurrent feeding it is also capable of synchronized feeding.
+
+The [class_sinks_has_requirement] metafunction can be used to test for a specific requirement in the `frontend_requirements` typedef.
+
+[heading Minimalistic sink backend]
+
+As an example of the [class_sinks_basic_sink_backend] class usage, let's implement a simple statistical information collector backend. Assume we have a network server and we want to monitor how many incoming connections are active and how much data was sent or received. The collected information should be written to a CSV-file every minute. The backend definition could look something like this:
+
+[example_extension_stat_collector_definition]
+
+As you can see, the public interface of the backend is quite simple. Only the `consume` and `flush` methods are called by frontends. The `consume` function is called every time a logging record passes filtering in the frontend. The record, as was stated before, contains a set of attribute values and the message string. Since we have no need for the record message, we will ignore it for now. But from the other attributes we can extract the statistical data to accumulate and write to the file. We can use [link log.detailed.expressions.attr_keywords attribute keywords] and [link log.detailed.attributes.related_components.value_processing.visitation value visitation] to accomplish this.
+
+[example_extension_stat_collector_consume]
+
+Note that we used __boost_phoenix__ to automatically generate visitor function objects for attribute values.
+
+The last bit of implementation is the `flush` method. It is used to flush all buffered data to the external storage, which is a file in our case. The method can be implemented in the following way:
+
+[example_extension_stat_collector_flush]
+
+You can find the complete code of this example [@boost:/libs/log/example/doc/extension_stat_collector.cpp here].
+
+[heading Formatting sink backend]
+
+As an example of a formatting sink backend, let's implement a sink that will display text notifications for every log record passed to it.
+
+[tip Real world applications would probably use some GUI toolkit API to display notifications but GUI programming is out of scope of this documentation. In order to display notifications we shall use an external program which does just that. In this example we shall employ `notify-send` program which is available on Linux (Ubuntu/Debian users can install it with the `libnotify-bin` package; other distros should also have it available in their package repositories). The program takes the notification parameters in the command line, displays the notification in the current desktop environment and then exits. Other platforms may also have similar tools.]
+
+The definition of the backend is very similar to what we have seen in the previous section:
+
+[example_extension_app_launcher_definition]
+
+The first thing to notice is that the `app_launcher` backend derives from [class_sinks_basic_formatted_sink_backend] rather than [class_sinks_basic_sink_backend]. This base class accepts the character type in addition to the requirements. The specified character type defines the target string type the formatter will compose in the frontend and it typically corresponds to the underlying API the backend uses to process records. It must be mentioned that the character type the backend requires is not related to the character types of string attribute values, including the message text. The formatter will take care of character code conversion when needed.
+
+The second notable difference from the previous examples is that `consume` method takes an additional string parameter besides the log record. This is the result of formatting. The `string_type` type is defined by the [class_sinks_basic_formatted_sink_backend] base class and it corresponds to the requested character type.
+
+We don't need to flush any buffers in this example, so we didn't specify the [class_sinks_flushing] requirement and omitted the `flush` method in the backens. Although we don't need any synchronization in our backend, we specified [class_sinks_synchronized_feeding] requirement so that we don't spawn multiple instances of `notify-send` program and cause a "fork bomb".
+
+Now, the `consume` implementation is trivial:
+
+[example_extension_app_launcher_consume]
+
+So the formatted string is expected to actually be a command line to start the application. The exact application name and arguments are to be determined by the formatter. This approach adds flexibility because the backend can be used for different purposes and updating the command line is as easy as updating the formatter.
+
+The sink can be configured with the following code:
+
+[example_extension_app_launcher_formatting]
+
+The most interesting part is the sink setup. The [class_sinks_synchronous_sink] frontend (as well as any other frontend) will detect that the `app_launcher` backend requires formatting and enable the corresponding functionality. The `set_formatter` method becomes available and can be used to set the formatting expression that composes the command line to start the `notify-send` program. We used [link log.detailed.expressions.attr_keywords attribute keywords] to identify particular attribute values in the formatter. Notice that string attribute values have to be preprocessed so that special characters interpreted by the shell are escaped in the command line. We achieve that with the [funcref boost::log::expressions::char_decor `char_decor`] decorator with our custom replacement map. After the sink is configured we also add the [link log.detailed.attributes.process_name current process name] attribute to the core so that we don't have to add it to every record.
+
+After all this is done, we can finally display some notifications:
+
+[example_extension_app_launcher_logging]
+
+The complete code of this example is available [@boost:/libs/log/example/doc/extension_app_launcher.cpp here].
+
+[endsect]
+
+[section:sources Writing your own sources]
+
+ #include <``[boost_log_sources_threading_models_hpp]``>
+ #include <``[boost_log_sources_basic_logger_hpp]``>
+
+You can extend the library by developing your own sources and, for that matter, ways of collecting log data. Basically, you have two choices of how to start: you can either develop a new logger feature or design a whole new type of source. The first approach is good if all you need is to tweak the functionality of the existing loggers. The second approach is reasonable if the whole mechanism of collecting logs by the provided loggers is unsuitable for your needs.
+
+[heading Creating a new logger feature]
+
+Every logger provided by the library consists of a number of features that can be combined with each other. Each feature is responsible for a single and independent aspect of the logger functionality. For example, loggers that provide the ability to assign severity levels to logging records include the [class_sources_severity] feature. You can implement your own feature and use it along with the ones provided by the library.
+
+A logger feature should follow these basic requirements:
+
+* A logging feature should be a class template. It should have at least one template parameter type (let's name it `BaseT`).
+* The feature must publicly derive from the `BaseT` template parameter.
+* The feature must be default-constructible and copy-constructible.
+* The feature must be constructible with a single argument of a templated type. The feature may not use this argument itself, but it should pass this argument to the `BaseT` constructor.
+
+These requirements allow composition of a logger from a number of features derived from each other. The root class of the features hierarchy will be the [class_sources_basic_logger] class template instance. This class implements most of the basic functionality of loggers, like storing logger-specific attributes and providing the interface for log message formatting. The hierarchy composition is done by the [class_sources_basic_composite_logger] class template, which is instantiated on a sequence of features (don't worry, this will be shown in an example in a few moments). The constructor with a templated argument allows initializing features with named parameters, using the __boost_parameter__ library.
+
+A logging feature may also contain internal data. In that case, to maintain thread safety for the logger, the feature should follow these additional guidelines:
+
+# Usually there is no need to introduce a mutex or another synchronization mechanism in each feature. Moreover, it is advised not to do so, because the same feature can be used in both thread-safe and not thread-safe loggers. Instead, features should use the threading model of the logger as a synchronization primitive, similar to how they would use a mutex. The threading model is accessible through the `get_threading_model` method, defined in the [class_sources_basic_logger] class template.
+# If the feature has to override `*_unlocked` methods of the protected interface of the [class_sources_basic_logger] class template (or the same part of the base feature interface), the following should be considered with regard to such methods:
+
+ * The public methods that eventually call these methods are implemented by the [class_sources_basic_composite_logger] class template. These implementations do the necessary locking and then pass control to the corresponding `_unlocked` method of the base features.
+ * The thread safety requirements for these methods are expressed with lock types. These types are available as typedefs in each feature and the [class_sources_basic_logger] class template. If the feature exposes a protected function `foo_unlocked`, it will also expose type `foo_lock`, which will express the locking requirements of `foo_unlocked`. The corresponding method `foo` in the [class_sources_basic_composite_logger] class template will use this typedef in order to lock the threading model before calling `foo_unlocked`.
+ * Feature constructors don't need locking, and thus there's no need for lock types for them.
+
+# The feature may implement a copy constructor. The argument of the constructor is already locked with a shared lock when the constructor is called. Naturally, the feature is expected to forward the copy constructor call to the `BaseT` class.
+# The feature need not implement an assignment operator. The assignment will be automatically provided by the [class_sources_basic_composite_logger] class instance. However, the feature may provide a `swap_unlocked` method that will swap contents of this feature and the method argument, and call similar method in the `BaseT` class. The automatically generated assignment operator will use this method, along with copy constructor.
+
+In order to illustrate all these lengthy recommendations, let's implement a simple logger feature. Suppose we want our logger to be able to tag individual log records. In other words, the logger has to temporarily add an attribute to its set of attributes, emit the logging record, and then automatically remove the attribute. Somewhat similar functionality can be achieved with scoped attributes, although the syntax may complicate wrapping it into a neat macro:
+
+ // We want something equivalent to this
+ {
+ BOOST_LOG_SCOPED_LOGGER_TAG(logger, "Tag", "[GUI]");
+ BOOST_LOG(logger) << "The user has confirmed his choice";
+ }
+
+Let's declare our logger feature:
+
+[example_extension_record_tagger_declaration]
+
+You can see that we use the [class_log_strictest_lock] template in order to define lock types that would fulfill the base class thread safety requirements for methods that are to be called from the corresponding methods of `record_tagger_feature`. The `open_record_lock` definition shows that the `open_record_unlocked` implementation for the `record_tagger_feature` feature requires exclusive lock (which `lock_guard` is) for the logger, but it also takes into account locking requirements of the `open_record_unlocked`, `add_attribute_unlocked` and `remove_attribute_unlocked` methods of the base class, because it will have to call them. The generated `open_record` method of the final logger class will make use of this typedef in order to automatically acquire the corresponding lock type before forwarding to the `open_record_unlocked` methods.
+
+Actually, in this particular example, there was no need to use the [class_log_strictest_lock] trait, because all our methods require exclusive locking, which is already the strictest one. However, this template may come in handy, should you use shared locking.
+
+The implementation of the public interface becomes quite trivial:
+
+[example_extension_record_tagger_structors]
+
+Now, since all locking is extracted into the public interface, we have the most of our feature logic to be implemented in the protected part of the interface. In order to set up tag value in the logger, we will have to introduce a new __boost_parameter__ keyword. Following recommendations from that library documentation, it's better to introduce the keyword in a special namespace:
+
+[example_extension_record_tagger_keyword]
+
+Opening a new record can now look something like this:
+
+[example_extension_record_tagger_open_record]
+
+Here we add a new attribute with the tag value, if one is specified in call to `open_record`. When a log record is opened, all attribute values are acquired and locked after the record, so we remove the tag from the attribute set with the __boost_scope_exit__ block.
+
+Ok, we got our feature, and it's time to inject it into a logger. Assume we want to combine it with the standard severity level logging. No problems:
+
+[example_extension_record_tagger_my_logger]
+
+As you can see, creating a logger is a quite simple procedure. The `BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE` macro you see here is for mere convenience purpose: it unfolds into a default constructor, copy constructor, assignment operator and a number of constructors to support named arguments. For non-template loggers there is a similar `BOOST_LOG_FORWARD_LOGGER_MEMBERS` macro.
+
+Assuming we have defined severity levels like this:
+
+[example_extension_record_tagger_severity]
+
+we can now use our logger as follows:
+
+[example_extension_record_tagger_manual_logging]
+
+All this verbosity is usually not required. One can define a special macro to make the code more concise:
+
+[example_extension_record_tagger_macro_logging]
+
+[@boost:/libs/log/example/doc/extension_record_tagger.cpp See the complete code].
+
+[heading Guidelines for designers of standalone logging sources]
+
+In general, you can implement new logging sources the way you like, the library does not mandate any design requirements on log sources. However, there are some notes regarding the way log sources should interact with logging core.
+
+# Whenever a logging source is ready to emit a log record, it should call the `open_record` in the core. The source-specific attributes should be passed into that call. During that call the core allocates resources for the record being made and performs filtering.
+# If the call to `open_record` returned a valid log record, then the record has passed the filtering and is considered to be opened. The record may later be either confirmed by the source by subsequently calling `push_record` or withdrawn by destroying it.
+# If the call to `open_record` returned an invalid (empty) log record, it means that the record has not been opened (most likely due to filtering rejection). In that case the logging core does not hold any resources associated with the record, and thus the source must not call `push_record` for that particular logging attempt.
+# The source may subsequently open more than one record. Opened log records exist independently from each other.
+
+[endsect]
+
+[section:attributes Writing your own attributes]
+
+ #include <``[boost_log_attributes_attribute_hpp]``>
+ #include <``[boost_log_attributes_attribute_value_hpp]``>
+ #include <``[boost_log_attributes_attribute_value_impl_hpp]``>
+
+Developing your own attributes is quite simple. Generally, you need to do the following:
+
+# Define what will be the attribute value. Most likely, it will be a piece of constant data that you want to participate in filtering and formatting. Envelop this data into a class that derives from the [class_log_attribute_value_impl] interface; this is the attribute value implementation class. This object will have to implement the `dispatch` method that will extract the stored data (or, in other words, the stored value) to a type dispatcher. In most cases the class [class_attributes_attribute_value_impl] provided by the library can be used for this.
+# Use the [class_log_attribute_value] class as the interface class that holds a reference to the attribute value implementation.
+# Define how attribute values are going to be produced. In a corner case the values do not need to be produced (like in the case of the [class_attributes_constant] attribute provided by the library), but often there is some logic that needs to be invoked to acquire the attribute value. This logic has to be concentrated in a class derived from the [class_log_attribute_impl] interface, more precisely - in the `get_value` method. This class is the attribute implementation class. You can think of it as an attribute value factory.
+# Define the attribute interface class that derives from [class_log_attribute]. By convention, the interface class should create the corresponding implementation on construction and pass the pointer to it to the [class_log_attribute] class constructor. The interface class may have interface methods but it typically should not contain any data members as the data will be lost when the attribute is added to the library. All relevant data should be placed in the implementation class instead.
+
+While designing an attribute, one has to strive to make it as independent from the values it produces, as possible. The attribute can be called from different threads concurrently to produce a value. Once produced, the attribute value can be used several times by the library (maybe even concurrently), it can outlive the attribute object that created it, and several attribute values produced by the same attribute can exist simultaneously.
+
+From the library perspective, each attribute value is considered independent from other attribute values or the attribute itself. That said, it is still possible to implement attributes that are also attribute values, which allows to optimize performance in some cases. This is possible if the following requirements are fulfilled:
+
+* The attribute value never changes, so it's possible to store it in the attribute itself. The [class_attributes_constant] attribute is an example.
+* The attribute stores its value in a global (external with regard to the attribute) storage, that can be accessed from any attribute value. The attribute values must guarantee, though, that their stored values do not change over time and are safely accessible concurrently from different threads.
+
+As a special case for the second point, it is possible to store attribute values (or their parts) in a thread-specific storage. However, in that case the user has to implement the `detach_from_thread` method of the attribute value implementation properly. The result of this method - another attribute value - must be independent from the thread it is being called in, but its stored value should be equivalent to the original attribute value. This method will be called by the library when the attribute value passes to a thread that is different from the thread where it was created. As of this moment, this will only happen in the case of [link log.detailed.sink_frontends.async asynchronous logging sinks].
+
+But in the vast majority of cases attribute values must be self-contained objects with no dependencies on other entities. In fact, this case is so common that the library provides a ready to use attribute value implementation class template [class_attributes_attribute_value_impl] and [funcref boost::log::attributes::make_attribute_value make_attribute_value] generator function. The class template has to be instantiated on the stored value type, and the stored value has to be provided to the class constructor. For example, let's implement an attribute that returns system uptime in seconds. This is the attribute implementation class.
+
+[example_extension_system_uptime_attr_impl]
+
+Since there is no need for special attribute value classes we can use the [funcref boost::log::attributes::make_attribute_value make_attribute_value] function to create the value envelop.
+
+[tip For cases like this, when the attribute value can be obtained in a single function call, it is typically more convenient to use the [link log.detailed.attributes.function `function`] attribute.]
+
+The interface class of the attribute can be defined as follows:
+
+[example_extension_system_uptime_attr]
+
+As it was mentioned before, the default constructor creates the implementation instance so that the default constructed attribute can be used by the library.
+
+The second constructor adds support for [link log.detailed.attributes attribute casting]. The constructor argument contains a reference to an attribute implementation object, and by calling `as` on it the constructor attempts to upcast it to the implementation object of our custom attribute. The `as` method will return `NULL` if the upcast fails, which will result in an empty attribute constructed in case of failure.
+
+Having defined these two classes, the attribute can be used with the library as usual:
+
+[example_extension_system_uptime_use]
+
+[@boost:/libs/log/example/doc/extension_system_uptime_attr.cpp See the complete code].
+
+[endsect]
+
+[section:settings Extending library settings support]
+
+If you write your own logging sinks or use your own types in attributes, you may want to add support for these components to the settings parser provided by the library. Without doing this, the library will not be aware of your types and thus will not be able to use them when parsing settings.
+
+[heading Adding support for user-defined types to the formatter parser]
+
+ #include <``[boost_log_utility_setup_formatter_parser_hpp]``>
+
+In order to add support for user-defined types to the formatter parser, one has to register a formatter factory. The factory is basically an object that derives from [class_log_formatter_factory] interface. The factory mainly implements the single `create_formatter` method which, when called, will construct a formatter for the particular attribute value.
+
+When the user-defined type supports putting to a stream with `operator<<` and this operator behavior is suitable for logging, one can use a simple generic formatter factory provided by the library out of the box. For example, let's assume we have the following user-defined type that we want to use as an attribute value:
+
+[example_extension_formatter_parser_point_definition]
+
+Then, in order to register this type with the simple formatter factory, a single call to [funcref boost::log::register_simple_formatter_factory `register_simple_formatter_factory`] will suffice:
+
+[example_extension_simple_formatter_factory]
+
+[note The `operator<<` for the attribute value stored type must be visible from the point of this call.]
+
+The function takes the stored attribute value type (`point`, in our case) and the target character type used by formatters as template parameters. From the point of this call, whenever the formatter parser encounters a reference to the "Coordinates" attribute in the format string, it will invoke the formatter factory, which will construct the formatter that calls our `operator<<` for class `point`.
+
+[tip It is typically a good idea to register all formatter factories at an early stage of the application initialization, before any other library initialization, such as reading config files.]
+
+From the [link log.detailed.utilities.setup.filter_formatter formatter parser description] it is known that the parser supports passing additional parameters from the format string to the formatter factory. We can use these parameters to customize the output generated by the formatter.
+
+For example, let's implement customizable formatting of our `point` objects, so that the following format string works as expected:
+
+[pre %TimeStamp% %Coordinates(format\="{%0.3f; %0.3f}")% %Message%]
+
+The simple formatter factory ignores all additional parameters from the format string, so we have to implement our own factory instead. Custom factories are registered with the [funcref boost::log::register_formatter_factory `register_formatter_factory`] function, which is similar to [funcref boost::log::register_simple_formatter_factory `register_simple_formatter_factory`] but accepts a pointer to the factory instead of the explicit template parameters.
+
+[example_extension_custom_formatter_factory]
+
+Let's walk through this code sample. Our `point_formatter_factory` class derives from the [class_log_basic_formatter_factory] base class provided by the library. This class derives from the base [class_log_formatter_factory] interface and defines a few useful types, such as `formatter_type` and `args_map` that we use. The only thing left to do in our factory is to define the `create_formatter` method. The method analyzes the parameters from the format string which are passed as the `args` argument, which is basically `std::map` of string keys (parameter names) to string values (the parameter values). We seek for the `format` parameter and expect it to contain a __boost_format__-compatible format string for our `point` objects. If the parameter is found we create a formatter that invokes `point_formatter` for the attribute values. Otherwise we create a default formatter that simply uses the `operator<<`, like the simple formatter factory does. Note that we use the `name` argument of `create_formatter` to ide
ntify the attribute so that the same factory can be used for different attributes.
+
+The `point_formatter` is our custom formatter based on __boost_format__. With help of __boost_phoenix__ and [link log.detailed.expressions.attr expression placeholders] we can construct a formatter that will extract the attribute value and pass it along with the target stream to the `point_formatter` function object. Note that the formatter accepts the attribute value wrapped into the [link log.detailed.utilities.value_ref `value_ref`] wrapper which can be empty if the value is not present.
+
+Lastly, the call to [funcref boost::log::register_formatter_factory `register_formatter_factory`] creates the factory and adds it to the library.
+
+You can find the complete code of this example [@boost:/libs/log/example/doc/extension_formatter_parser.cpp here].
+
+[heading Adding support for user-defined types to the filter parser]
+
+ #include <``[boost_log_utility_setup_filter_parser_hpp]``>
+
+You can extend filter parser in the similar way you can extend the formatter parser - by registering filter factories for your attribute values into the library. However, since it takes a considerably more complex syntax to describe filters, a filter factory typically implements several generator functions.
+
+Like with formatter parser extension, you can avoid spelling out the filter factory and register a simple factlry provided by the library:
+
+[example_extension_simple_filter_factory]
+
+In order this to work the user's type should fullfill these requirements:
+
+# Support reading from an input stream with `operator>>`.
+# Support the complete set of comparison and ordering operators.
+
+Naturally, all these operators must be visible from the point of the [funcref boost::log::register_simple_filter_factory `register_simple_filter_factory`] call. Note that unlike the simple formatter factory, the filter factory requires the user's type to support reading from a stream. This is so because the filter factory would have to parse the argument of the filter relation from a string.
+
+But we won't get away with a simple filter factory, because our `point` class doesn't have a sensible ordering semantics and thus we cannot define the complete set of operators. We'll have to implement our own filter factory instead. Filter factories derive from the [class_log_filter_factory] interface. This base class declares a number of virtual functions that will be called in order to create filters, according to the filter expression. If some functions are not overriden by the factory, the corresponding operations are considered to be not supported by the attribute value. But before we define the filter factory we have to improve our `point` class slightly:
+
+[example_extension_filter_parser_point_definition]
+
+We have added comparison and input operators for the `point` class. The output operator is still used by formatters and not required by the filter factory. Now we can define and register the filter factory:
+
+[example_extension_custom_filter_factory]
+
+Having called the [funcref boost::log::register_filter_factory `register_filter_factory`] function, whenever the [link log.detailed.utilities.setup.filter_formatter filter parser] encounters the "Coordinates" attribute mentioned in the filter, it will use the `point_filter_factory` object to construct the appropriate filter. For example, in the case of the following filter
+
+[pre %Coordinates% \= "(10, 10)"]
+
+the `on_equality_relation` method will be called with `name` argument being "Coordinates" and `arg` being "(10, 10)".
+
+[note The quotes around the parenthesis are necessary because the filter parser should interpret the point coordinates as a single string. Also, round brackets are already used to group subexpressions of the filter expression. Whenever there is need to pass several parameters to the relation (like in this case - a number of components of the `point` class) the parameters should be encoded into a quoted string. The string may include C-style escape sequences that will be unfolded upon parsing.]
+
+The constructed filter will use the corresponding comparison operators for the `point` class. Ordering operations, like ">" or "<=", will not be supported for attributes named "Coordinates", and this is exactly the way we want it, because the `point` class does not support them either. The complete example is available [@boost:/libs/log/example/doc/extension_filter_parser.cpp here].
+
+The library allows not only adding support for new types, but also associating new relations with them. For instance, we can create a new relation "is_in_rect" that will yield positive if the coordinates fit into a rectangle denoted with two points. The filter might look like this:
+
+[pre %Coordinates% is\_in\_rect "{(10, 10) - (20, 20)}"]
+
+First, let's define our rectangle class:
+
+[example_extension_filter_parser_rectangle_definition]
+
+As it was said, the rectangle is described by two points - the top left and the bottom right corners of the rectangle area. Now let's extend our filter factory with the `on_custom_relation` method:
+
+[example_extension_custom_filter_factory_with_custom_rel]
+
+The `on_custom_relation` method is called with the relation name (the "is\_in\_rect" string in our case) and the right-hand argument for the relation (the rectangle description). All we have to do is to construct the filter, which is implemented by our `is_in_rect` function. We use `bind` from __boost_phoenix__ to compose the filter from the function and the [link log.detailed.expressions.attr attribute placeholder]. You can find the complete code of this example [@boost:/libs/log/example/doc/extension_filter_parser_custom_rel.cpp here].
+
+[heading Adding support for user-defined sinks]
+
+ #include <``[boost_log_utility_setup_from_settings_hpp]``>
+ #include <``[boost_log_utility_setup_from_stream_hpp]``>
+
+The library provides mechanism of extending support for sinks similar to the formatter and filter parsers. In order to be able to mention user-defined sinks in a settings file, the user has to register a sink factory, which essentially contains the `create_sink` method that receives a [link log.detailed.utilities.setup.settings settings subsection] and returns a pointer to the initialized sink. The factory is registered for a specific destination (see the [link log.detailed.utilities.setup.settings settings file description]), so whenever a sink with the specified destination is mentioned in the settings file, the factory gets called.
+
+For example, let's register the `stat_collector` sink we described [link log.extension.sinks before] in the library. First, let's remember the sink definition:
+
+[example_extension_stat_collector_settings_definition]
+
+Compared to the earlier definition we added the `write_interval` constructor parameter so we can set the statistical information flush interval in the settings file. The implementation of the sink stays pretty much the same as before. Now we have to define the factory:
+
+[example_extension_stat_collector_factory]
+
+As you can see, we read parameters from settings and simply create our sink with them as a result of `create_sink` method. Generally, users are free to name parameters of their sinks the way they like, as long as [link log.detailed.utilities.setup.settings_file settings file format] is adhered. However, it is a good idea to follow the pattern established by the library and reuse parameter names with the same meaning. That is, it should be obvious that the parameter "Filter" means the same for both the library-provided "TextFile" sink and out custom "StatCollector" sink.
+
+After defining the factory we only have to register it with the [funcref boost::log::register_sink_factory `register_sink_factory`] call. The first argument is the new value of the "Destination" parameter in the settings. Whenever the library finds sink description with destination "StatCollector", our factory will be invoked to create the sink. It is also possible to override library-provided destination types with user-defined factories, however it is not possble to restore the default factories afterwards.
+
+[note As the "Destination" parameter is used to determine the sink factory, this parameter is reserved and cannot be used by sink factories for their own purposes.]
+
+Now that the factory is registered, we can use it when initializing from files or settings. For example, this is what the settings file could look like:
+
+[pre
+\[Sinks.MyStat\]
+
+Destination\=StatCollector
+FileName\=stat.csv
+WriteInterval\=30
+]
+
+The complete code of the example in this section can be found [@boost:/libs/log/example/doc/extension_stat_collector_settings.cpp here].
+
+[endsect]
+
+[endsect]

Added: trunk/libs/log/doc/filters_reference.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/log/doc/filters_reference.qbk 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+[/
+ Copyright Andrey Semashev 2007 - 2013.
+ 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)
+
+ This document is a part of Boost.Log library documentation.
+
+ This document was automatically generated, DO NOT EDIT!
+/]
+
+[template boost_log_filters_attr_hpp[][headerref boost/log/filters/attr.hpp]]
+
+[template class_filters_flt_attr[][classref boost::log::filters::flt_attr flt_attr]]
+
+[template boost_log_filters_basic_filters_hpp[][headerref boost/log/filters/basic_filters.hpp]]
+
+[template class_filters_filter_base[][classref boost::filters::filter_base filter_base]]
+
+[template class_filters_is_filter[][classref boost::filters::is_filter is_filter]]
+
+[template class_filters_basic_filter[][classref boost::filters::basic_filter basic_filter]]
+
+[template class_filters_flt_wrap[][classref boost::filters::flt_wrap flt_wrap]]
+
+[template class_filters_flt_negation[][classref boost::filters::flt_negation flt_negation]]
+
+[template class_filters_flt_and[][classref boost::filters::flt_and flt_and]]
+
+[template class_filters_flt_or[][classref boost::filters::flt_or flt_or]]
+
+[template boost_log_filters_exception_policies_hpp[][headerref boost/log/filters/exception_policies.hpp]]
+
+[template class_filters_no_throw_policy[][classref boost::filters::no_throw_policy no_throw_policy]]
+
+[template class_filters_throw_policy[][classref boost::filters::throw_policy throw_policy]]
+
+[template boost_log_filters_has_attr_hpp[][headerref boost/log/filters/has_attr.hpp]]
+
+[template class_filters_flt_has_attr[][classref boost::filters::flt_has_attr flt_has_attr]]

Added: trunk/libs/log/doc/formatters_reference.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/log/doc/formatters_reference.qbk 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,82 @@
+[/
+ Copyright Andrey Semashev 2007 - 2013.
+ 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)
+
+ This document is a part of Boost.Log library documentation.
+
+ This document was automatically generated, DO NOT EDIT!
+/]
+
+[template boost_log_formatters_attr_hpp[][headerref boost/log/formatters/attr.hpp]]
+
+[template class_formatters_fmt_attr[][classref boost::formatters::fmt_attr fmt_attr]]
+
+[template class_formatters_fmt_attr_formatted[][classref boost::formatters::fmt_attr_formatted fmt_attr_formatted]]
+
+[template boost_log_formatters_basic_formatters_hpp[][headerref boost/log/formatters/basic_formatters.hpp]]
+
+[template class_formatters_formatter_base[][classref boost::formatters::formatter_base formatter_base]]
+
+[template class_formatters_is_formatter[][classref boost::formatters::is_formatter is_formatter]]
+
+[template class_formatters_basic_formatter[][classref boost::formatters::basic_formatter basic_formatter]]
+
+[template boost_log_formatters_c_decorator_hpp[][headerref boost/log/formatters/c_decorator.hpp]]
+
+[template class_formatters_fmt_c_ascii_decorator[][classref boost::formatters::fmt_c_ascii_decorator fmt_c_ascii_decorator]]
+
+[template boost_log_formatters_chain_hpp[][headerref boost/log/formatters/chain.hpp]]
+
+[template class_formatters_fmt_chain[][classref boost::formatters::fmt_chain fmt_chain]]
+
+[template boost_log_formatters_char_decorator_hpp[][headerref boost/log/formatters/char_decorator.hpp]]
+
+[template class_formatters_fmt_char_decorator[][classref boost::log::formatters::fmt_char_decorator fmt_char_decorator]]
+
+[template boost_log_formatters_csv_decorator_hpp[][headerref boost/log/formatters/csv_decorator.hpp]]
+
+[template boost_log_formatters_date_time_hpp[][headerref boost/log/formatters/date_time.hpp]]
+
+[template class_formatters_fmt_date_time_facade[][classref boost::formatters::fmt_date_time_facade fmt_date_time_facade]]
+
+[template boost_log_formatters_exception_policies_hpp[][headerref boost/log/formatters/exception_policies.hpp]]
+
+[template class_formatters_no_throw_policy[][classref boost::formatters::no_throw_policy no_throw_policy]]
+
+[template class_formatters_throw_policy[][classref boost::formatters::throw_policy throw_policy]]
+
+[template boost_log_formatters_format_hpp[][headerref boost/log/formatters/format.hpp]]
+
+[template class_formatters_fmt_format[][classref boost::formatters::fmt_format fmt_format]]
+
+[template boost_log_formatters_if_hpp[][headerref boost/log/formatters/if.hpp]]
+
+[template class_formatters_fmt_if_else[][classref boost::formatters::fmt_if_else fmt_if_else]]
+
+[template class_formatters_fmt_if[][classref boost::formatters::fmt_if fmt_if]]
+
+[template boost_log_formatters_message_hpp[][headerref boost/log/formatters/message.hpp]]
+
+[template class_formatters_fmt_message[][classref boost::formatters::fmt_message fmt_message]]
+
+[template boost_log_formatters_named_scope_hpp[][headerref boost/log/formatters/named_scope.hpp]]
+
+[template class_formatters_fmt_named_scope[][classref boost::formatters::fmt_named_scope fmt_named_scope]]
+
+[template boost_log_formatters_stream_hpp[][headerref boost/log/formatters/stream.hpp]]
+
+[template class_formatters_stream_placeholder[][classref boost::formatters::stream_placeholder stream_placeholder]]
+
+[template boost_log_formatters_wrappers_hpp[][headerref boost/log/formatters/wrappers.hpp]]
+
+[template class_formatters_fmt_wrapper[][classref boost::formatters::fmt_wrapper fmt_wrapper]]
+
+[template class_formatters_wrap_if_c[][classref boost::formatters::wrap_if_c wrap_if_c]]
+
+[template class_formatters_wrap_if[][classref boost::formatters::wrap_if wrap_if]]
+
+[template class_formatters_wrap_if_not_formatter[][classref boost::formatters::wrap_if_not_formatter wrap_if_not_formatter]]
+
+[template boost_log_formatters_xml_decorator_hpp[][headerref boost/log/formatters/xml_decorator.hpp]]

Added: trunk/libs/log/doc/gen_references.xsl
==============================================================================
--- (empty file)
+++ trunk/libs/log/doc/gen_references.xsl 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ Copyright Andrey Semashev 2007 - 2013.
+ 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)
+
+ This stylesheet extracts information about headers, classes, etc.
+ from the Doxygen-generated reference documentation and writes
+ it as QuickBook templates that refer to the according Reference sections.
+-->
+<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="text"/>
+<xsl:template match="/library-reference">
+<xsl:text disable-output-escaping="yes">[/
+ Copyright Andrey Semashev 2007 - 2013.
+ 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)
+
+ This document is a part of Boost.Log library documentation.
+
+ This document was automatically generated, DO NOT EDIT!
+/]
+</xsl:text>
+<xsl:apply-templates>
+<xsl:with-param name="namespace"/>
+<xsl:with-param name="enclosing_namespace"/>
+</xsl:apply-templates>
+</xsl:template>
+
+<!-- Skip any text nodes -->
+<xsl:template match="text()"/>
+
+<!-- Headers -->
+<xsl:template match="header">
+<xsl:param name="namespace"/>
+<xsl:param name="enclosing_namespace"/>
+[template <xsl:value-of select="translate(@name, '/.', '__')"/>[][headerref <xsl:value-of select="@name"/>]]
+<xsl:apply-templates>
+<xsl:with-param name="namespace" select="$namespace"/>
+<xsl:with-param name="enclosing_namespace" select="$enclosing_namespace"/>
+</xsl:apply-templates>
+</xsl:template>
+
+<!-- Namespaces - only needed to construct fully qualified class names -->
+<xsl:template match="namespace">
+<xsl:param name="namespace"/>
+<xsl:param name="enclosing_namespace"/>
+<xsl:variable name="namespace_prefix">
+<xsl:value-of select="$namespace"/><xsl:if test="string-length($namespace) &gt; 0"><xsl:text>::</xsl:text></xsl:if>
+</xsl:variable>
+<xsl:apply-templates>
+<xsl:with-param name="namespace" select="concat($namespace_prefix, @name)"/>
+<xsl:with-param name="enclosing_namespace" select="@name"/>
+</xsl:apply-templates>
+</xsl:template>
+
+<!-- Classses -->
+<xsl:template match="class|struct">
+<xsl:param name="namespace"/>
+<xsl:param name="enclosing_namespace"/>
+[template <xsl:value-of select="concat('class_', $enclosing_namespace, '_', @name)"/>[][classref <xsl:value-of select="concat($namespace, '::', @name)"/><xsl:text> </xsl:text><xsl:value-of select="@name"/>]]
+<xsl:apply-templates>
+<xsl:with-param name="namespace" select="concat($namespace, '::', @name)"/>
+<xsl:with-param name="enclosing_namespace" select="concat($enclosing_namespace, '_', @name)"/>
+</xsl:apply-templates>
+</xsl:template>
+
+<!-- Free functions - currently disabled because multiple overloads generate duplicate QuickBook templates -->
+<!--
+<xsl:template match="function">
+<xsl:param name="namespace"/>
+<xsl:param name="enclosing_namespace"/>
+[template <xsl:value-of select="concat('func_', $enclosing_namespace, '_', @name)"/>[][funcref <xsl:value-of select="concat($namespace, '::', @name)"/><xsl:text> </xsl:text><xsl:value-of select="@name"/>]]
+</xsl:template>
+-->
+
+</xsl:transform>

Added: trunk/libs/log/doc/log.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/log/doc/log.qbk 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,303 @@
+[library Boost.Log
+ [quickbook 1.5]
+ [version 2.0]
+ [authors [Semashev, Andrey]]
+ [copyright 2007 - 2013 Andrey Semashev]
+ [license
+ 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]).
+ ]
+ [id log]
+ [source-mode c++]
+ [last-revision $Date: 2013-03-10 18:29:41 +0400 (Sun, 10 Mar 2013) $]
+]
+
+[c++]
+
+[/ Links to external resources /]
+[def __boost_smart_ptr__ [@http://www.boost.org/doc/libs/release/libs/smart_ptr/smart_ptr.htm Boost.SmartPtr]]
+[def __boost_function__ [@http://www.boost.org/doc/libs/release/doc/html/function.html Boost.Function]]
+[def __boost_filesystem__ [@http://www.boost.org/doc/libs/release/libs/filesystem/doc/index.htm Boost.Filesystem]]
+[def __boost_system__ [@http://www.boost.org/doc/libs/release/libs/system/doc/index.html Boost.System]]
+[def __boost_date_time__ [@http://www.boost.org/doc/libs/release/doc/html/date_time.html Boost.DateTime]]
+[def __boost_date_time_format__ [@http://www.boost.org/doc/libs/release/doc/html/date_time/date_time_io.html#date_time.format_flags Boost.DateTime]]
+[def __boost_thread__ [@http://www.boost.org/doc/libs/release/doc/html/thread.html Boost.Thread]]
+[def __boost_regex__ [@http://www.boost.org/doc/libs/release/libs/regex/index.html Boost.Regex]]
+[def __boost_xpressive__ [@http://www.boost.org/doc/libs/release/doc/html/xpressive.html Boost.Xpressive]]
+[def __boost_parameter__ [@http://www.boost.org/doc/libs/release/libs/parameter/doc/html/index.html Boost.Parameter]]
+[def __boost_format__ [@http://www.boost.org/doc/libs/release/libs/format/index.html Boost.Format]]
+[def __boost_preprocessor__ [@http://www.boost.org/doc/libs/release/libs/preprocessor/doc/index.html Boost.Preprocessor]]
+[def __boost_bind__ [@http://www.boost.org/doc/libs/release/libs/bind/bind.html Boost.Bind]]
+[def __boost_lambda__ [@http://www.boost.org/doc/libs/release/doc/html/lambda.html Boost.Lambda]]
+[def __boost_phoenix__ [@http://www.boost.org/doc/libs/release/libs/phoenix/doc/html/index.html Boost.Phoenix]]
+[def __boost_spirit__ [@http://www.boost.org/doc/libs/release/libs/spirit/classic/index.html Boost.Spirit]]
+[def __boost_spirit2__ [@http://www.boost.org/doc/libs/release/libs/spirit/doc/html/index.html Boost.Spirit2]]
+[def __boost_optional__ [@http://www.boost.org/doc/libs/release/libs/optional/index.html Boost.Optional]]
+[def __boost_variant__ [@http://www.boost.org/doc/libs/release/doc/html/variant.html Boost.Variant]]
+[def __boost_intrusive__ [@http://www.boost.org/doc/libs/release/doc/html/intrusive.html Boost.Intrusive]]
+[def __boost_iostreams__ [@http://www.boost.org/doc/libs/release/libs/iostreams/doc/index.html Boost.IOStreams]]
+[def __boost_mpl__ [@http://www.boost.org/doc/libs/release/libs/mpl/doc/index.html Boost.MPL]]
+[def __boost_exception__ [@http://www.boost.org/doc/libs/release/libs/exception/doc/boost-exception.html Boost.Exception]]
+[def __boost_scope_exit__ [@http://www.boost.org/doc/libs/release/libs/scope_exit/doc/html/index.html Boost.ScopeExit]]
+[def __boost_any__ [@http://www.boost.org/doc/libs/release/doc/html/any.html Boost.Any]]
+[def __boost_property_tree__ [@http://www.boost.org/doc/libs/release/doc/html/property_tree.html Boost.PropertyTree]]
+[def __boost_asio__ [@http://www.boost.org/doc/libs/release/doc/html/boost_asio.html Boost.ASIO]]
+[def __boost_move__ [@http://www.boost.org/doc/libs/release/doc/html/move.html Boost.Move]]
+[def __boost_locale__ [@http://www.boost.org/doc/libs/release/libs/locale/doc/html/index.html Boost.Locale]]
+[def __boost_quickbook__ [@http://www.boost.org/doc/libs/release/doc/html/quickbook.html Boost.Quickbook]]
+
+[/ Auto-generated macros that refer to Reference sections /]
+[include top_level_reference.qbk]
+[include core_reference.qbk]
+[include attributes_reference.qbk]
+[include expressions_reference.qbk]
+[include sources_reference.qbk]
+[include sinks_reference.qbk]
+[include utility_reference.qbk]
+[include support_reference.qbk]
+
+[/ Code samples /]
+[import ../example/doc/tutorial_trivial.cpp]
+[import ../example/doc/tutorial_trivial_flt.cpp]
+[import ../example/doc/tutorial_file.cpp]
+[import ../example/doc/tutorial_file_manual.cpp]
+[import ../example/doc/tutorial_fmt_stream.cpp]
+[import ../example/doc/tutorial_fmt_stream_manual.cpp]
+[import ../example/doc/tutorial_fmt_format.cpp]
+[import ../example/doc/tutorial_fmt_string.cpp]
+[import ../example/doc/tutorial_fmt_custom.cpp]
+[import ../example/doc/tutorial_logging.cpp]
+[import ../example/doc/tutorial_attributes.cpp]
+[import ../example/doc/tutorial_filtering.cpp]
+[import ../example/doc/core_record.cpp]
+[import ../example/doc/core_core_manual.cpp]
+[import ../example/doc/attr_value_visitation.cpp]
+[import ../example/doc/attr_value_extraction.cpp]
+[import ../example/doc/expressions_attr_fmt_tag.cpp]
+[import ../example/doc/expressions_keyword_fmt_tag.cpp]
+[import ../example/doc/expressions_has_attr_stat_accum.cpp]
+[import ../example/doc/expressions_channel_severity_filter.cpp]
+[import ../example/doc/sources_net_connection.cpp]
+[import ../example/doc/sources_net_connection_chan.cpp]
+[import ../example/doc/sources_net_connection_dynamic_chan.cpp]
+[import ../example/doc/sources_severity.cpp]
+[import ../example/doc/sources_severity_channel.cpp]
+[import ../example/doc/exception_handling.cpp]
+[import ../example/doc/sinks_unlocked.cpp]
+[import ../example/doc/sinks_sync.cpp]
+[import ../example/doc/sinks_async.cpp]
+[import ../example/doc/sinks_async_bounded.cpp]
+[import ../example/doc/sinks_async_ordering.cpp]
+[import ../example/doc/sinks_ostream.cpp]
+[import ../example/doc/sinks_file.cpp]
+[import ../example/doc/sinks_xml_file.cpp]
+[import ../example/doc/sinks_multifile.cpp]
+[import ../example/doc/sinks_syslog.cpp]
+[import ../example/doc/sinks_debugger.cpp]
+[import ../example/doc/sinks_simple_event_log.cpp]
+[import ../example/doc/util_static_type_disp.cpp]
+[import ../example/doc/util_dynamic_type_disp.cpp]
+[import ../example/doc/util_manip_to_log.cpp]
+[import ../example/doc/extension_stat_collector.cpp]
+[import ../example/doc/extension_app_launcher.cpp]
+[import ../example/doc/extension_record_tagger.cpp]
+[import ../example/doc/extension_system_uptime_attr.cpp]
+[import ../example/doc/extension_formatter_parser.cpp]
+[import ../example/doc/extension_filter_parser.cpp]
+[import ../example/doc/extension_filter_parser_custom_rel.cpp]
+[import ../example/doc/extension_stat_collector_settings.cpp]
+[import ../example/wide_char/main.cpp]
+[import ../example/event_log/main.cpp]
+
+[section:moti Motivation]
+
+Today applications grow rapidly, becoming complicated and difficult to test and debug. Most of the time applications run on a remote site, leaving the developer little chance to monitor their execution and figure out the reasons for their failure, once it should happen. Moreover, even the local debugging may become problematic if the application behavior depends heavily on asynchronous side events, such as a device feedback or another process activity.
+
+This is where logging can help. The application stores all essential information about its execution to a log, and when something goes wrong this information can be used to analyze the program behavior and make the necessary corrections. There are other very useful applications of logging, such as gathering statistical information and highlighting events (i.e. indicating that some situation has occurred or that the application is experiencing some problems). These tasks have proved to be vital for many real-world industrial applications.
+
+This library aims to make logging significantly easier for the application developer. It provides a wide range of out-of-the-box tools along with public interfaces for extending the library. The main goals of the library are:
+
+* Simplicity. A small example code snippet should be enough to get the feel of the library and be ready to use its basic features.
+* Extensibility. A user should be able to extend functionality of the library for collecting and storing information into logs.
+* Performance. The library should have as little performance impact on the user's application as possible.
+
+[endsect]
+
+[section:how_to_read How to read the documentation]
+
+The documentation is oriented to both new and experienced library users. However, users are expected to be familiar with commonly used Boost components, such as `shared_ptr`, `make_shared` (see __boost_smart_ptr__), and `function` (__boost_function__). Some parts of the documentation will refer to other Boost libraries, as needed.
+
+If this is your first experience with the library, it is recommended to read the [link log.design Design overview] section for a first glance at the library's capabilities and architecture. The [link log.installation Installation] and [link log.tutorial Tutorial] sections will help to get started experimenting with the library. The tutorial gives an overview of the library features with sample code snippets. Some tutorial steps are presented in two forms: simple and advanced. The simple form typically describes the most common and easy way to do the task and it is being recommended to be read by new users. The advanced form usually gives an expanded way to do the same thing but with an in-depth explanation and the ability to do some extra customization. This form may come in handy for more experienced users and should generally be read if the easy way does not satisfy your needs.
+
+Besides the tutorial there is a [link log.detailed Detailed features description] chapter. This part describes other tools provided by the library that were not covered by the tutorial. This chapter is best read on a case by case basis.
+
+Last, but not least, there is a reference which gives the formal description of library components.
+
+To keep the code snippets in this documentation simple, the following namespace aliases are assumed to be defined:
+
+ namespace logging = boost::log;
+ namespace sinks = boost::log::sinks;
+ namespace src = boost::log::sources;
+ namespace expr = boost::log::expressions;
+ namespace attrs = boost::log::attributes;
+ namespace keywords = boost::log::keywords;
+
+[endsect]
+
+[section:installation Installation and compatibility]
+
+[section:supported_compilers Supported compilers and platforms]
+
+The library should build and work with a reasonably compliant compiler. The library was successfully built and tested on the following platforms:
+
+* Windows XP, Windows Vista, Windows 7. MSVC 9.0 and newer.
+* Linux. GCC 4.5 and newer. Older versions may work too, but it was not tested.
+* Linux. Intel C++ 13.1.0.146 Build 20130121.
+* Linux. Clang 3.2.
+
+The following compilers/platforms are not supported and will likely fail to compile the library:
+
+* C++11 compilers with non-C++11 standard libraries (like Clang with libstdc++ from GCC 4.2). Please, use a C++11 standard library in C++11 mode.
+* MSVC 8.0 and older.
+* GCC 4.0 and older.
+* Borland C++ 5.5.1 (free version). Newer versions might or might not work.
+* Windows 9x, ME, NT4 and older are not supported.
+
+[heading Notes for MinGW, Cygwin and Visual Studio Express Edition users]
+
+In order to compile the library under these compilers special preparations are needed. First, in case of MinGW or Cygwin make sure you have installed the latest GCC version. The library will most likely fail to compile with GCC 3.x.
+
+Second, at some point the library will require a Message Compiler tool (`mc.exe`), which is not available in MinGW, Cygwin and MSVC Express Edition. You have three options to settle the problem. The recommended solution is to obtain the original `mc.exe`. This tool is available in Windows SDK, which can be downloaded from the Microsoft site freely (for example, [@http://www.microsoft.com/downloads/details.aspx?FamilyID=71deb800-c591-4f97-a900-bea146e4fae1&displaylang=en here]). Also, this tool should be available in Visual Studio 2010 Express Edition. During the compilation, `mc.exe` should be accessible through one of the directories in your `PATH` environment variable.
+
+Another way is to attempt to use the `windmc.exe` tool distributed with MinGW and Cygwin, which is the analogue of the original `mc.exe`. In order to do that you will have to patch Boost.Build files (in particular, the `tools/build/v2/tools/mc.jam` file) as described in [@https://svn.boost.org/trac/boost/ticket/4111 this] ticket. After that you will be able to specify the `mc-compiler=windmc` option to bjam to build the library.
+
+Lastly, you can disable support for event log backend by defining the `BOOST_LOG_WITHOUT_EVENT_LOG` configuration macro when building the library. This will remove the need for the message compiler. See [link log.installation.config this section] for more configuration options.
+
+[heading Additional notes for Cygwin users]
+
+Cygwin support is rather preliminary. Some functionality is not available. In particular, the socket-based syslog backend is not supported, as it is based on __boost_asio__, which doesn't compile on this platform. However, the native syslog support is still in place.
+
+Furthermore, in order to compile the library the following parameters should be explicitly specified in the bjam command line: `target-os=cygwin logapi=unix`.
+
+[endsect]
+
+[section:config Configuring and building the library]
+
+The library has a separately compiled part which should be built as described in the [@http://www.boost.org/doc/libs/release/more/getting_started/ Getting Started guide]. One thing should be noted, though. If your application consists of more than one module (e.g. an exe and one or several dll's) that use Boost.Log, the library _must_ be built as a shared object. If you have a single executable or a single module that works with Boost.Log, you may build the library as a static library.
+
+The library supports a number of configuration macros:
+
+[table Configuration macros
+ [[Macro name] [Effect]]
+ [[`BOOST_LOG_DYN_LINK`] [If defined in user code, the library will assume the binary is built as a dynamically loaded library ("dll" or "so"). Otherwise it is assumed that the library is built in static mode. This macro must be either defined or not defined for all translation units of user application that uses logging. This macro can help with auto-linking on platforms that support it.]]
+ [[`BOOST_ALL_DYN_LINK`] [Same as `BOOST_LOG_DYN_LINK` but also affects other Boost libraries the same way.]]
+ [[`BOOST_LOG_NO_THREADS`] [If defined, disables multithreading support. Affects the compilation of both the library and users' code. The macro is automatically defined if no threading support is detected.]]
+ [[`BOOST_LOG_WITHOUT_CHAR`] [If defined, disables support for narrow character logging. Affects the compilation of both the library and users' code.]]
+ [[`BOOST_LOG_WITHOUT_WCHAR_T`] [If defined, disables support for wide character logging. Affects the compilation of both the library and users' code.]]
+ [[`BOOST_LOG_NO_QUERY_PERFORMANCE_COUNTER`] [This macro is only useful on Windows. It affects the compilation of both the library and users' code. If defined, disables support for the `QueryPerformanceCounter` API in the `timer` attribute. This will result in significantly less accurate time readings. The macro is intended to solve possible problems with earlier revisions of AMD Athlon CPU, described [@http://support.microsoft.com/?scid=kb;en-us;895980 here] and [@http://support.microsoft.com/?id=896256 here]. There are also known chipset hardware failures that may prevent this API from functioning properly (see [@http://support.microsoft.com/kb/274323 here]).]]
+ [[`BOOST_LOG_USE_NATIVE_SYSLOG`] [Affects only the compilation of the library. If for some reason support for the native SysLog API is not detected automatically, define this macro to forcibly enable it]]
+ [[`BOOST_LOG_WITHOUT_SETTINGS_PARSERS`] [Affects only the compilation of the library. If defined, none of the facilities related to the parsers for settings will be built. This can substantially reduce the binary size.]]
+ [[`BOOST_LOG_WITHOUT_DEBUG_OUTPUT`] [Affects only the compilation of the library. If defined, the support for debugger output on Windows will not be built.]]
+ [[`BOOST_LOG_WITHOUT_EVENT_LOG`] [Affects only the compilation of the library. If defined, the support for Windows event log will not be built. Defining the macro also makes Message Compiler toolset unnecessary.]]
+ [[`BOOST_LOG_WITHOUT_SYSLOG`] [Affects only the compilation of the library. If defined, the support for syslog backend will not be built.]]
+ [[`BOOST_LOG_NO_SHORTHAND_NAMES`] [Affects only the compilation of users' code. If defined, some deprecated shorthand macro names will not be available.]]
+ [[`BOOST_LOG_USE_WINNT6_API`] [Affects the compilation of both the library and users' code. This macro is Windows-specific. If defined, the library makes use of the Windows NT 6 (Vista, Server 2008) and later APIs to generate more efficient code. This macro will also enable some experimental features of the library. Note, however, that the resulting binary will not run on Windows prior to NT 6. In order to use this feature Platform SDK 6.0 or later is required.]]
+ [[`BOOST_LOG_USE_COMPILER_TLS`] [Affects only the compilation of the library. This macro enables support for compiler intrinsics for thread-local storage. Defining it may improve performance of Boost.Log if certain usage limitations are acceptable. See below for more comments.]]
+]
+
+You can define configuration macros in the `bjam` command line, like this:
+
+[pre
+ bjam --with-log variant=release define=BOOST_LOG_WITHOUT_EVENT_LOG define=BOOST_LOG_USE_WINNT6_API stage
+]
+
+However, it may be more convenient to define configuration macros in the "boost/config/user.hpp" file in order to automatically define them both for the library and user's projects. If none of the options are specified, the library will try to support the most comprehensive setup, including support for all character types and features available for the target platform.
+
+The logging library uses several other Boost libraries that require building too. These are __boost_filesystem__, __boost_system__, __boost_date_time__ and __boost_thread__. Refer to their documentation for detailed instructions on the building procedure.
+
+One final thing should be added. The library requires run-time type information (RTTI) to be enabled for both the library compilation and user's code compilation. Normally, this won't need anything from you except to verify that RTTI support is not disabled in your project.
+
+[heading Notes about compiler-supplied intrinsics for TLS]
+
+Many widely used compilers support builtin intrinsics for managing thread-local storage, which is used in several parts of the library. This feature is also included in the C++11 standard. Generally, these intrinsics allow for a much more efficient access to the storage than any surrogate implementation, be that __boost_thread__ or even native operating system API. However, this feature has several caveats:
+
+* Some operating systems don't support the use of these intrinsics in case if the TLS is defined in a shared library that is dynamically loaded during the application run time. These systems include Linux and Windows prior to Vista. Windows Vista and later do not have this issue.
+* The TLS may not be reliably accessed from global constructors and destructors. At least MSVC 8.0 on Windows is known to have this problem.
+
+The library provides the `BOOST_LOG_USE_COMPILER_TLS` configuration macro that allows to enable the use of this feature, which will improve the library performance at the cost of these limitations:
+
+* The application executable must be linked with the Boost.Log library. It should not be loaded dynamically during run time.
+* The application must not use logging in global constructors or destructors.
+
+[endsect]
+
+[endsect]
+
+[section:defs Definitions]
+
+Here are definitions of some terms that will be used widely throughout the documentation:
+
+[variablelist
+ [[Log record][A single bundle of information, collected from the user's application, that is a candidate to be put into the log. In a simple case the log record will be represented as a line of text in the log file after being processed by the logging library.]]
+ [[Attribute][An "attribute" is a piece of meta-information that can be used to specialize a log record. In Boost.Log attributes are represented by function objects with a specific interface, which return the actual attribute value when invoked.]]
+ [[Attribute value][Attribute values are the actual data acquired from attributes. This data is attached to the specific log record and processed by the library. Values can have different types (integers, strings and more complex, including user defined types). Some examples of attribute values: current time stamp value, file name, line number, current scope name, etc.. Attribute values are enveloped in a type erasing wrapper, so the actual type of the attribute is not visible in the interface. The actual (erased) type of the value is sometimes called the stored type.]]
+ [[(Attribute) value visitation][A way of processing the attribute value. This approach involves a function object (a visitor) which is applied to the attribute value. The visitor should know the stored type of the attribute value in order to process it.]]
+ [[(Attribute) value extraction][A way of processing the attribute value when the caller attempts to obtain a reference to the stored value. The caller should know the stored type of the attribute value in order to be able to extract it.]]
+ [[Log sink][A target, to which all log records are fed after being collected from the user's application. The sink defines where and how the log records are going to be stored or processed.]]
+ [[Log source][An entry point for the user's application to put log records to. In a simple case it is an object (logger) which maintains a set of attributes that will be used to form a log record upon the user's request. However, one can surely create a source that would emit log records on some side events (for example, by intercepting and parsing console output of another application).]]
+ [[Log filter][A predicate that takes a log record and tells whether this record should be passed through or discarded. The predicate typically forms its decision based on the attribute values attached to the record.]]
+ [[Log formatter][A function object that generates the final textual output from a log record. Some sinks, e.g. a binary logging sink, may not need it, although almost any text-based sink would use a formatter to compose its output.]]
+ [[Logging core][The global entity that maintains connections between sources and sinks and applies filters to records. It is mainly used when the logging library is initialized.]]
+ [[i18n][Internationalization. The ability to manipulate wide characters.]]
+ [[TLS][Thread-local storage. The concept of having a variable that has independent values for each thread that attempts to access it.]]
+ [[RTTI][Run-time type information. This is the C++ language support data structures required for `dynamic_cast` and `typeid` operators to function properly.]]
+]
+
+[endsect]
+
+[include:log design.qbk]
+
+[include:log tutorial.qbk]
+
+[section:detailed Detailed features description]
+
+[include:log core.qbk]
+[include:log sources.qbk]
+[include:log sink_frontends.qbk]
+[include:log sink_backends.qbk]
+[include:log expressions.qbk]
+[include:log attributes.qbk]
+[include:log utilities.qbk]
+
+[endsect]
+
+[include:log extension.qbk]
+[include:log rationale.qbk]
+
+[section:reference Reference]
+
+[xinclude top_level_reference.xml]
+[xinclude core_reference.xml]
+[xinclude attributes_reference.xml]
+[xinclude expressions_reference.xml]
+[xinclude sources_reference.xml]
+[xinclude sinks_reference.xml]
+[xinclude utility_reference.xml]
+[xinclude support_reference.xml]
+
+[endsect]
+
+[include:log changelog.qbk]
+[include:log todo.qbk]
+
+[section:acknowledgments Acknowledgments]
+
+* Vladimir Prus managed the library review in Boost and actually reviewed it in the process.
+* Luca Rigini wrote the initial implementation of the NT event log sink and made a lot of suggestions on how to improve the library with regard to writing user-defined sinks.
+* Jean-Daniel Michaud, Michael Lacher and all others who took part in the discussion of the requirements to the library on [@http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Boost.Logging Wiki].
+* John Torjo, Gennadiy Rozental and others for their discussion on John's logging library on the Boost developers list. It helped a lot to learn the requirements and possible solutions for the library.
+* All authors of the great Boost libraries that were involved in this library (notably, __boost_smart_ptr__, __boost_thread__, __boost_date_time__, __boost_filesystem__, __boost_intrusive__, __boost_spirit2__ and others) and __boost_quickbook__ authors for a simple yet powerful documenting tool.
+* All the reviewers and the users who made suggestions and offered their feedback on the library. Most notably, Steven Watanabe for his in-depth studying the docs and the code, with a lot of fruitful comments on both.
+
+[endsect]

Added: trunk/libs/log/doc/rationale.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/log/doc/rationale.qbk 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,188 @@
+[/
+ Copyright Andrey Semashev 2007 - 2013.
+ 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)
+
+ This document is a part of Boost.Log library documentation.
+/]
+
+[section:rationale Rationale and FAQ]
+
+[section:why_str_lit Why string literals as scope names?]
+
+One may wonder why not allow arbitrary strings to be used as named scope names. The answer is simple: for performance and safety reasons. Named scope support functionality has one significant difference from other attribute-related features of the library. The scope stack is maintained even when no logging is done, so if a function `foo` has a `BOOST_LOG_FUNCTION()` statement in its body, it is always a slowdown. Allowing the scope name to be an arbitrary string would make the slowdown significantly greater because of the need to allocate memory and copy the string (not to mention that there would be a need to previously format it, which also takes its toll).
+
+Dynamic memory allocation also introduces exception safety issues: the `BOOST_LOG_FUNCTION()` statement (and alikes) would become a potential source of exceptions. These issues would complicate user's code if he wants to solve memory allocation problems gracefully.
+
+One possible alternative solution would be pooling pre-formatted and pre-allocated scope names somewhere but this would surely degrade performance even more and introduce the problem of detecting when to update or free pooled strings.
+
+Therefore restricting to string literals seemed to be the optimal decision, which reduced dynamic memory usage and provided enough flexibility for common needs.
+
+[endsect]
+
+[section:why_weak_scoped_attributes Why scoped attributes don't override existing attributes?]
+
+Initially scoped attributes were able to override other attributes with the same name if they were already registered by the time when a scoped attribute encountered. This allowed some interesting use cases like this:
+
+ BOOST_LOG_DECLARE_GLOBAL_LOGGER(my_logger, src::logger_mt)
+
+ void foo()
+ {
+ // This scoped attribute would temporarily replace the existing tag
+ BOOST_LOG_SCOPED_THREAD_TAG("Section", std::string, "In foo");
+
+ // This log record will have a "Section" attribute with value "In foo"
+ BOOST_LOG(get_my_logger()) << "We're in foo section";
+ }
+
+ int main(int, char*[])
+ {
+ BOOST_LOG_SCOPED_THREAD_TAG("Section", std::string, "In main");
+
+ // This log record will have a "Section" attribute with value "In main"
+ BOOST_LOG(get_my_logger()) << "We're in main section";
+
+ foo();
+
+ // This log record will have a "Section" attribute with value "In main" again
+ BOOST_LOG(get_my_logger()) << "We're in main section again";
+
+ return 0;
+ }
+
+However, this feature introduced a number of safety problems, including thread safety issues, that could be difficult to track down. For example, it was no longer safe to use logger-wide scoped attributes on the same logger from different threads, because the resulting attribute would be undefined:
+
+ BOOST_LOG_DECLARE_GLOBAL_LOGGER(my_logger, src::logger_mt)
+
+ void thread1()
+ {
+ BOOST_LOG_SCOPED_LOGGER_TAG(get_my_logger(), "Tag", std::string, "thread1");
+ BOOST_LOG(get_my_logger()) << "We're in thread1";
+ }
+
+ void thread2()
+ {
+ BOOST_LOG_SCOPED_LOGGER_TAG(get_my_logger(), "Tag", int, 10);
+ BOOST_LOG(get_my_logger()) << "We're in thread2";
+ }
+
+ int main(int, char*[])
+ {
+ BOOST_LOG_SCOPED_LOGGER_TAG(get_my_logger(), "Tag", double, -2.2);
+
+ BOOST_LOG(get_my_logger()) << "We're in main";
+
+ boost::thread t1(&thread1);
+ boost::thread t2(&thread2);
+
+ t1.join();
+ t2.join();
+
+ // Which "Tag" is registered here?
+ BOOST_LOG(get_my_logger()) << "We're in main again";
+
+ return 0;
+ }
+
+There were other issues, like having an attribute set iterator that points to one attribute object, then suddenly without seemingly modifying it it becomes pointing to a different attribute object (of, possibly, a different type). Such behavior could lead to tricky failures that would be difficult to investigate. Therefore this feature was eventually dropped, which simplified the scoped attributes implementation significantly.
+
+[endsect]
+
+[section:why_weak_record_ordering Why log records are weakly ordered in a multithreaded application?]
+
+Although the library guarantees that log records made in a given thread are always delivered to sinks in the same order as they were made in, the library cannot provide such guarantee for different threads. For instance, it is possible that thread A emits a log record and gets preempted, then thread B emits its log record and manages to deliver it to a sink before being preempted. The resulting log will contain log record from thread B before the record made in thread A. However, attribute values attached to the records will always be actual with regard to the moment of emitting the record and not the moment of passing the record to the sink. This is the reason for a strange, at first glance, situation when a log record with an earlier time stamp follows a record with a later time stamp. The problem appears quite rarely, usually when thread contention on logging is very high.
+
+There are few possible ways to cope with the problem:
+
+* Enforce strict serialization of log record being made throughout the application. This solution implies a severe performance impact in multithreaded applications because log records that otherwise could be processed concurrently would have to go serial. Since this controverses one of the [link log.moti main library goals], it was rejected.
+* Attempt to maintain log record ordering on the sink level. This solution is more or less viable. On the downside, it would introduce log record buffering, which in turn would compromise logs reliability. In the case of application crash all buffered records would be lost.
+* Bear with the problem and let mis-ordered records appear in log files occasionally. Order log records upon reading the files, if needed.
+
+The second solution was implemented as a special policy for the [link log.detailed.sink_frontends.async asynchronous sink frontend].
+
+[endsect]
+
+[section:why_attribute_manips_dont_affect_filters Why attributes set with stream manipulators do not participate in filtering?]
+
+One can add attributes to log records in the followinf way:
+
+ BOOST_LOG(logger) << logging::add_value("MyInt", 10) << logging::add_value("MyString", "string attribute value")
+ << "Some log message";
+
+However, filters will not be able to use MyInt and MyString attributes. The reason for this behavior is quite simple. The streaming expression is executed /after/ the filtering takes place and only /if/ the filter passed the log record. At this point these attributes have not been added to the record yet. The easiest way to pass attributes to the filter is to use scoped attributes or tags (see [link log.detailed.attributes.related_components.scoped_attributes here]).
+
+[endsect]
+
+[section:why_not_lazy_streaming Why not using lazy streaming?]
+
+One of the possible library implementations would be using lazy expressions to delay log record formatting. In essence, the expression:
+
+ logger << "Hello, world!";
+
+would become a lambda-expression that is only invoked if the filtering is successful. Although this approach has advantages, it must be noted that lazy expression construction is not zero-cost in terms of performance, code size and compile times. The following expression:
+
+ logger << "Received packet from " << ip << " of " << packet.size() << " bytes";
+
+would generate a considerable amount of code (proportional to the number of streaming operators) to be executed before filtering takes place. Another drawback is that the `packet.size()` is always called, whether or not the record is actually written to the log. In order to delay this call, yet more scaffolding is needed, possibly involving __boost_bind__, __boost_lambda__ or __boost_phoenix__. This complication is not acceptable for such a basic use case, like this.
+
+Although lazy streaming is not provided by the library out of the box, nothing prevents developing it in a separate hierarchy of loggers. See the [link log.extension.sources Extending the library] section for more information.
+
+[endsect]
+
+[section:why_not_log4j Why not using hierarchy of loggers, like in log4j? Why not Boost.Log4j? Etc.]
+
+There are enough [@http://logging.apache.org/log4j/ log4j]-like libraries available for C++ already (see [@http://logging.apache.org/log4cxx/ here], [@http://log4cplus.sourceforge.net/ here] and [@http://log4cpp.sourceforge.net/ here]), so there is no point in implementing yet another one. Instead, this library was aimed to solve more complex tasks, including ones that do not directly fall under the common definition of "logging" term as a debugging tool. Additionally, as Boost.Log was to be a generic library, it had to provide more ways of extending itself, while keeping performance as high as possible. Log4j concept seemed too limiting and inappropriate for these tasks and therefore was rejected.
+
+As for hierarchical loggers, there is no need for this feature in the current library design. One of the main benefits it provides in log4j is determining the appenders (sinks, in terms of this library) in which a log record will end up. This library achieves the same result by filtering. The other application of this feature in Boost.Log could be that the loggers in the hierarchy could combine their sets of attributes for each log record, but there was no demand in real world applications for such a feature. It can be added though, if it proves useful.
+
+[endsect]
+
+[section:fork_support Does Boost.Log support process forking?]
+
+No, currently Boost.Log does not support process forking (i.e. `fork` call in UNIX systems). There are several issues with process forking, for instance:
+
+* File sinks do not attempt to reopen log files or synchronize access to files between parent and child processes. The resulting output may be garbled.
+* File collectors do not expect several processes attempting to collect log files to the same target directory. This may result in spurious failures at log file rotation.
+* The [link log.detailed.attributes.process_id current_process_id] attribute value will not update in the child process.
+* In multithreaded applications, one can generally not guarantee that a thread is not executing some Boost.Log code while an other thread forks. Some Boost.Log resources may be left irreversibly locked or broken in the forked process. This reservation is not specific to Boost.Log, other libraries and even the application itself are susceptible to this problem.
+
+There may be other issues as well. It seems unlikely that support for forking will be added to Boost.Log any time soon.
+
+[note This does not preclude the `fork`+`exec` sequence from working. As long as the forked process doesn't try to use any of Boost.Log code, the process should be able to call `exec` or a similar function to load and start another executable.]
+
+[endsect]
+
+[section:init_term_support Does Boost.Log support logging at process initialization and termination?]
+
+It should be fine to use logging during the application initialization (i.e. before `main()` starts). But there are a number of known problems with Boost.Log that prevent it from being used at process termination (i.e. after the `main()` function returns), so the official answer to the second part is no. It may work though, in some very restricted setups, if several rules are followed:
+
+* Do not create any objects at process termination, including loggers, attributes or sinks. Try to create and cache the required objects as soon as the application starts (maybe even before `main()` starts).
+* Do not use global loggers at process termination.
+* Do not call `logging::core::get()` at process termination. Get that pointer as early as possible and keep it until the process terminates.
+* Do not use named scopes in termination code.
+
+These rules don't guarantee that the library will work in termination context but they may help to avoid problems. The library will get improved to support this use case better.
+
+[endsect]
+
+[section:namespace_mangling Why my application fails to link with Boost.Log? What's the fuss about library namespaces?]
+
+The library declares the `boost::log` namespace which should be used in client code to access library components. However, internally the library uses another nested namespace for actual implementation. The namespace name is configuration and platform dependent, it can change between different releases of the library, so it should never be used in the user side code. This is done in order to make the library configuration synchronized with the application as much as possible and eliminate problems caused by configuration mismatch.
+
+Most of the time users won't even notice the existence of this internal namespace, but it often appears in compiler and linker errors and in some cases it is useful to know how to decode its name. Currently, the namespace name is composed from the following elements:
+
+[pre <version><linkage>\_<threading>\_<system>]
+
+* The `<version>` component describes the library major version. It is currently `v2`.
+* The `<linkage>` component tells whether the library is linked statically or dynamically. It is `s` if the library is linked statically and empty otherwise.
+* The `<threading>` component is `st` for single-threaded builds and `mt` for multi-threaded ones.
+* The `<system>` component describes the underlying OS API used by the library. Currently, it is only specified for multi-threaded builds. Depending on the target platform and configuration, it can be `posix`, `nt5` or `nt6`.
+
+As a couple quick examples, `v2s_st` corresponds to v2 static single-threaded build of the library and `v2_mt_posix` - to v2 dynamic multi-threaded build for POSIX system API.
+
+Namespace mangling may lead to linkinkg errors if the application is misconfigured. One common mistake is to build dynamic version of the library and not define `BOOST_LOG_DYN_LINK` or `BOOST_ALL_DYN_LINK` when building the application, so that the library assumes static linking by default. Whenever such linking errors appear, one can decode the namespace name in the missing symbols and the exported symbols of Boost.Log library and adjust library or application [link log.installation.config configuration] accordingly.
+
+[endsect]
+
+[endsect]

Added: trunk/libs/log/doc/sink_backends.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/log/doc/sink_backends.qbk 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,320 @@
+[/
+ Copyright Andrey Semashev 2007 - 2013.
+ 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)
+
+ This document is a part of Boost.Log library documentation.
+/]
+
+[section:sink_backends Sink backends]
+
+[section:text_ostream Text stream backend]
+
+ #include <``[boost_log_sinks_text_ostream_backend_hpp]``>
+
+The text output stream sink backend is the most generic backend provided by the library out of the box. The backend is implemented in the [class_sinks_basic_text_ostream_backend] class template (`text_ostream_backend` and `wtext_ostream_backend` convenience typedefs provided for narrow and wide character support). It supports formatting log records into strings and putting into one or several streams. Each attached stream gets the same result of formatting, so if you need to format log records differently for different streams, you will need to create several sinks - each with its own formatter.
+
+The backend also provides a feature that may come useful when debugging your application. With the `auto_flush` method one can tell the sink to automatically flush the buffers of all attached streams after each log record is written. This will, of course, degrade logging performance, but in case of an application crash there is a good chance that last log records will not be lost.
+
+[example_sinks_ostream]
+
+[endsect]
+
+[section:text_file Text file backend]
+
+ #include <``[boost_log_sinks_text_file_backend_hpp]``>
+
+Although it is possible to write logs into files with the [link log.detailed.sink_backends.text_ostream text stream backend] the library also offers a special sink backend with an extended set of features suitable for file-based logging. The features include:
+
+* Log file rotation based on file size and/or time
+* Flexible log file naming
+* Placing the rotated files into a special location in the file system
+* Deleting the oldest files in order to free more space on the file system
+
+The backend is called [class_sinks_text_file_backend].
+
+[heading File rotation]
+
+File rotation is implemented by the sink backend itself. The file name pattern and rotation thresholds can be specified when the [class_sinks_text_file_backend] backend is constructed.
+
+[example_sinks_file]
+
+[note The file size at rotation can be imprecise. The implementation counts the number of characters written to the file, but the underlying API can introduce additional auxiliary data, which would increase the log file's actual size on disk. For instance, it is well known that Windows and DOS operating systems have a special treatment with regard to new-line characters. Each new-line character is written as a two byte sequence 0x0D 0x0A instead of a single 0x0A. Other platform-specific character translations are also known.]
+
+The time-based rotation is not limited by only time points. There are following options available out of the box:
+
+# Time point rotations: [class_file_rotation_at_time_point] class. This kind of rotation takes place whenever the specified time point is reached. The following variants are available:
+
+ * Every day rotation, at the specified time. This is what was presented in the code snippet above:
+ ``
+ sinks::file::rotation_at_time_point(12, 0, 0)
+ ``
+
+ * Rotation on the specified day of every week, at the specified time. For instance, this will make file rotation to happen every Tuesday, at midnight:
+ ``
+ sinks::file::rotation_at_time_point(date_time::Tuesday, 0, 0, 0)
+ ``
+ in case of midnight, the time can be omitted:
+ ``
+ sinks::file::rotation_at_time_point(date_time::Tuesday)
+ ``
+
+ * Rotation on the specified day of each month, at the specified time. For example, this is how to rotate files on the 1-st of every month:
+ ``
+ sinks::file::rotation_at_time_point(gregorian::greg_day(1), 0, 0, 0)
+ ``
+ like with weekdays, midnight is implied:
+ ``
+ sinks::file::rotation_at_time_point(gregorian::greg_day(1))
+ ``
+
+# Time interval rotations: [class_file_rotation_at_time_interval] class. With this predicate the rotation is not bound to any time points and happens as soon as the specified time interval since the previous rotation elapses. This is how to make rotations every hour:
+``
+ sinks::file::rotation_at_time_interval(posix_time::hours(1))
+``
+
+If none of the above applies, one can specify his own predicate for time-based rotation. The predicate should take no arguments and return `bool` (the `true` value indicates that the rotation should take place). The predicate will be called for every log record being written to the file.
+
+ bool is_it_time_to_rotate();
+
+ void init_logging()
+ {
+ // ...
+
+ boost::shared_ptr< sinks::text_file_backend > backend =
+ boost::make_shared< sinks::text_file_backend >(
+ keywords::file_name = "file_%5N.log",
+ keywords::time_based_rotation = &is_it_time_to_rotate
+ );
+
+ // ...
+ }
+
+[note The log file rotation takes place on an attempt to write a new log record to the file. Thus the time-based rotation is not a strict threshold, either. The rotation will take place as soon as the library detects that the rotation should have happened.]
+
+The file name pattern may contain a number of wildcards, like the one you can see in the example above. Supported placeholders are:
+
+* Current date and time components. The placeholders conform to the ones specified by __boost_date_time__ library.
+* File counter (`%N`) with an optional width specification in the `printf`-like format. The file counter will always be decimal, zero filled to the specified width.
+* A percent sign (`%%`).
+
+A few quick examples:
+
+[table
+ [[Template] [Expands to]]
+ [[file\_%N.log] [file\_1.log, file\_2.log...]]
+ [[file\_%3N.log] [file\_001.log, file\_002.log...]]
+ [[file\_%Y%m%d.log] [file\_20080705.log, file\_20080706.log...]]
+ [[file\_%Y-%m-%d\_%H-%M-%S.%N.log] [file\_2008-07-05\_13-44-23.1.log, file\_2008-07-06\_16-00-10.2.log...]]
+]
+
+[important Although all __boost_date_time__ format specifiers will work, there are restrictions on some of them, if you intend to scan for old log files. This functionality is discussed in the next section.]
+
+The sink backend allows hooking into the file rotation process in order to perform pre- and post-rotation actions. This can be useful to maintain log file validity by writing headers and footers. For example, this is how we could modify the `init_logging` function in order to write logs into XML files:
+
+[example_sinks_xml_file]
+
+[@boost:/libs/log/example/doc/sinks_xml_file.cpp See the complete code].
+
+Finally, the sink backend also supports the auto-flush feature, like the [link log.detailed.sink_backends.text_ostream text stream backend] does.
+
+[heading Managing rotated files]
+
+After being closed, the rotated files can be collected. In order to do so one has to set up a file collector by specifying the target directory where to collect the rotated files and, optionally, size thresholds. For example, we can modify the `init_logging` function to place rotated files into a distinct directory and limit total size of the files. Let's assume the following function is called by `init_logging` with the constructed sink:
+
+[example_sinks_xml_file_collecting]
+
+The `max_size` and `min_free_space` parameters are optional, the corresponding threshold will not be taken into account if the parameter is not specified.
+
+One can create multiple file sink backends that collect files into the same target directory. In this case the most strict thresholds are combined for this target directory. The files from this directory will be erased without regard for which sink backend wrote it, i.e. in the strict chronological order.
+
+[warning The collector does not resolve log file name clashes between different sink backends, so if the clash occurs the behavior is undefined, in general. Depending on the circumstances, the files may overwrite each other or the operation may fail entirely.]
+
+The file collector provides another useful feature. Suppose you ran your application 5 times and you have 5 log files in the "logs" directory. The file sink backend and file collector provide a `scan_for_files` method that searches the target directory for these files and takes them into account. So, if it comes to deleting files, these files are not forgotten. What's more, if the file name pattern in the backend involves a file counter, scanning for older files allows updating the counter to the most recent value. Here is the final version of our `init_logging` function:
+
+[example_sinks_xml_file_final]
+
+There are two methods of file scanning: the scan that involves file name matching with the file name pattern (the default) and the scan that assumes that all files in the target directory are log files. The former applies certain restrictions on the placeholders that can be used within the file name pattern, in particular only file counter placeholder and these placeholders of __boost_date_time__ are supported: `%y`, `%Y`, `%m`, `%d`, `%H`, `%M`, `%S`, `%f`. The latter scanning method, in its turn, has its own drawback: it does not allow updating the file counter in the backend. It is also considered to be more dangerous as it may result in unintended file deletion, so be cautious. The all-files scanning method can be enabled by passing it as an additional parameter to the `scan_for_files` call:
+
+ // Look for all files in the target directory
+ backend->scan_for_files(sinks::file::scan_all);
+
+[endsect]
+
+[section:text_multifile Text multi-file backend]
+
+ #include <``[boost_log_sinks_text_multifile_backend_hpp]``>
+
+While the text stream and file backends are aimed to store all log records into a single file/stream, this backend serves a different purpose. Assume we have a banking request processing application and we want logs related to every single request to be placed into a separate file. If we can associate some attribute with the request identity then the [class_sinks_text_multifile_backend] backend is the way to go.
+
+[example_sinks_multifile]
+
+You can see we used a regular [link log.detailed.expressions.formatters formatter] in order to specify file naming pattern. Now, every log record with a distinct value of the "RequestID" attribute will be stored in a separate file, no matter how many different requests are being processed by the application concurrently. You can also find the [@boost:/libs/log/example/multiple_files/main.cpp `multiple_files`] example in the library distribution, which shows a similar technique to separate logs generated by different threads of the application.
+
+If using formatters is not appropriate for some reason, you can provide your own file name composer. The composer is a mere function object that accepts a log record as a single argument and returns a value of the `text_multifile_backend::path_type` type.
+
+[note The multi-file backend has no knowledge of whether a particular file is going to be used or not. That is, if a log record has been written into file A, the library cannot tell whether there will be more records that fit into the file A or not. This makes it impossible to implement file rotation and removing unused files to free space on the file system. The user will have to implement such functionality himself.]
+
+[endsect]
+
+[section:syslog Syslog backend]
+
+ #include <``[boost_log_sinks_syslog_backend_hpp]``>
+
+The syslog backend, as comes from its name, provides support for the syslog API that is available on virtually any UNIX-like platform. On Windows there exists at least [@http://syslog-win32.sourceforge.net one] public implementation of the syslog client API. However, in order to provide maximum flexibibity and better portability the library offers built-in support for the syslog protocol described in [@http://tools.ietf.org/html/rfc3164 RFC 3164]. Thus on Windows only the built-in implementation is supported, while on UNIX-like systems both built-in and system API based implementations are supported.
+
+The backend is implemented in the [class_sinks_syslog_backend] class. The backend supports formatting log records, and therefore requires thread synchronization in the frontend. The backend also supports severity level translation from the application-specific values to the syslog-defined values. This is achieved with an additional function object, level mapper, that receives a set of attribute values of each log record and returns the appropriate syslog level value. This value is used by the backend to construct the final priority value of the syslog record. The other component of the syslog priority value, the facility, is constant for each backend object and can be specified in the backend constructor arguments.
+
+Level mappers can be written by library users to translate the application log levels to the syslog levels in the best way. However, the library provides two mappers that would fit this need in obvious cases. The [class_syslog_direct_severity_mapping] class template provides a way to directly map values of some integral attribute to syslog levels, without any value conversion. The [class_syslog_custom_severity_mapping] class template adds some flexibility and allows to map arbitrary values of some attribute to syslog levels.
+
+Anyway, one example is better than a thousand words.
+
+[example_sinks_syslog]
+
+Please note that all syslog constants, as well as level extractors, are declared within a nested namespace `syslog`. The library will not accept (and does not declare in the backend interface) native syslog constants, which are macros, actually.
+
+Also note that the backend will default to the built-in implementation and `user` logging facility, if the corresponding constructor parameters are not specified.
+
+[tip The `set_target_address` method will also accept DNS names, which it will resolve to the actual IP address. This featue, however, is not available in single threaded builds.]
+
+[endsect]
+
+[section:debugger Windows debugger output backend]
+
+ #include <``[boost_log_sinks_debug_output_backend_hpp]``>
+
+Windows API has an interesting feature: a process, being run under a debugger, is able to emit messages that will be intercepted and displayed in the debugger window. For example, if an application is run under the Visual Studio IDE it is able to write debug messages to the IDE window. The [class_sinks_basic_debug_output_backend] backend provides a simple way of emitting such messages. Additionally, in order to optimize application performance, a [link log.detailed.expressions.predicates.is_debugger_present special filter] is available that checks whether the application is being run under a debugger. Like many other sink backends, this backend also supports setting a formatter in order to compose the message text.
+
+The usage is quite simple and straightforward:
+
+[example_sinks_debugger]
+
+Note that the sink backend is templated on the character type. This type defines the Windows API version that is used to emit messages. Also, `debug_output_backend` and `wdebug_output_backend` convenience typedefs are provided.
+
+[endsect]
+
+[section:event_log Windows event log backends]
+
+ #include <``[boost/log/sinks/event_log_backend.hpp]``>
+
+Windows operating system provides a special API for publishing events related to application execution. A wide range of applications, including Windows components, use this facility to provide the user with all essential information about computer health in a single place - an event log. There can be more than one event log. However, typically all user-space applications use the common Application log. Records from different applications or their parts can be selected from the log by a record source name. Event logs can be read with a standard utility, an Event Viewer, that comes with Windows.
+
+Although it looks very tempting, the API is quite complicated and intrusive, which makes it difficult to support. The application is required to provide a dynamic library with special resources that describe all events the application supports. This library must be registered in the Windows registry, which pins its location in the file system. The Event Viewer uses this registration to find the resources and compose and display messages. The positive feature of this approach is that since event resources can describe events differently for different languages, it allows the application to support event internationalization in a quite transparent manner: the application simply provides event identifiers and non-localizable event parameters to the API, and it does the rest of the work.
+
+In order to support both the simplistic approach "it just works" and the more elaborate event composition, including internationalization support, the library provides two sink backends that work with event log API.
+
+[heading Simple event log backend]
+
+The [class_sinks_basic_simple_event_log_backend] backend is intended to encapsulate as much of the event log API as possible, leaving interface and usage model very similar to other sink backends. It contains all resources that are needed for the Event Viewer to function properly, and registers the Boost.Log library in the Windows registry in order to populate itself as the container of these resources.
+
+[important The library must be built as a dynamic library in order to use this backend flawlessly. Otherwise event description resources are not linked into the executable, and the Event Viewer is not able to display events properly.]
+
+The only thing user has to do to add Windows event log support to his application is to provide event source and log names (which are optional and can be automatically suggested by the library), set up an appropriate filter, formatter and event severity mapping.
+
+[example_sinks_simple_event_log]
+
+Having done that, all logging records that pass to the sink will be formatted the same way they are in the other sinks. The formatted message will be displayed in the Event Viewer as the event description.
+
+[heading Advanced event log backend]
+
+The [class_sinks_basic_event_log_backend] allows more detailed control over the logging API, but requires considerably more scaffolding during initialization and usage.
+
+First, the user has to build his own library with the event resources (the process is described in [@http://msdn.microsoft.com/en-us/library/aa363681(VS.85).aspx MSDN]). As a part of this process one has to create a message file that describes all events. For the sake of example, let's assume the following contents were used as the message file:
+
+[teletype]
+
+ ; /* --------------------------------------------------------
+ ; HEADER SECTION
+ ; */
+ SeverityNames=(Debug=0x0:MY_SEVERITY_DEBUG
+ Info=0x1:MY_SEVERITY_INFO
+ Warning=0x2:MY_SEVERITY_WARNING
+ Error=0x3:MY_SEVERITY_ERROR
+ )
+
+ ; /* --------------------------------------------------------
+ ; MESSAGE DEFINITION SECTION
+ ; */
+
+ MessageIdTypedef=WORD
+
+ MessageId=0x1
+ SymbolicName=MY_CATEGORY_1
+ Language=English
+ Category 1
+ .
+
+ MessageId=0x2
+ SymbolicName=MY_CATEGORY_2
+ Language=English
+ Category 2
+ .
+
+ MessageId=0x3
+ SymbolicName=MY_CATEGORY_3
+ Language=English
+ Category 3
+ .
+
+ MessageIdTypedef=DWORD
+
+ MessageId=0x100
+ Severity=Warning
+ Facility=Application
+ SymbolicName=LOW_DISK_SPACE_MSG
+ Language=English
+ The drive %1 has low free disk space. At least %2 Mb of free space is recommended.
+ .
+
+ MessageId=0x101
+ Severity=Error
+ Facility=Application
+ SymbolicName=DEVICE_INACCESSIBLE_MSG
+ Language=English
+ The drive %1 is not accessible.
+ .
+
+ MessageId=0x102
+ Severity=Info
+ Facility=Application
+ SymbolicName=SUCCEEDED_MSG
+ Language=English
+ Operation finished successfully in %1 seconds.
+ .
+
+[c++]
+
+After compiling the resource library, the path to this library must be provided to the sink backend constructor, among other parameters used with the simple backend. The path may contain placeholders that will be expanded with the appropriate environment variables.
+
+[example_sinks_event_log_create_backend]
+
+Like the simple backend, [class_sinks_basic_event_log_backend] will register itself in the Windows registry, which will enable the Event Viewer to display the emitted events.
+
+Next, the user will have to provide the mapping between the application logging attributes and event identifiers. These identifiers were provided in the message compiler output as a result of compiling the message file. One can use [class_event_log_basic_event_composer] and one of the event ID mappings, like in the following example:
+
+[example_sinks_event_log_event_composer]
+
+As you can see, one can use regular [link log.detailed.expressions.formatters formatters] to specify which attributes will be inserted instead of placeholders in the final event message. Aside from that, one can specify mappings of attribute values to event types and categories. Suppose our application has the following severity levels:
+
+[example_sinks_event_log_severity]
+
+Then these levels can be mapped onto the values in the message description file:
+
+[example_sinks_event_log_mappings]
+
+[tip As of Windows NT 6 (Vista, Server 2008) it is not needed to specify event type mappings. This information is available in the message definition resources and need not be duplicated in the API call.]
+
+Now that initialization is done, the sink can be registered into the core.
+
+[example_sinks_event_log_register_sink]
+
+In order to emit events it is convenient to create a set of functions that will accept all needed parameters for the corresponding events and announce that the event has occurred.
+
+[example_sinks_event_log_facilities]
+
+Now you are able to call these helper functions to emit events. The complete code from this section is available in the [@boost:/libs/log/example/event_log/main.cpp `event_log`] example in the library distribution.
+
+[endsect]
+
+[endsect]

Added: trunk/libs/log/doc/sink_frontends.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/log/doc/sink_frontends.qbk 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,157 @@
+[/
+ Copyright Andrey Semashev 2007 - 2013.
+ 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)
+
+ This document is a part of Boost.Log library documentation.
+/]
+
+[section:sink_frontends Sink frontends]
+
+Sink frontends are the part of sinks provided by the library, that implements the common functionality shared between all sinks. This includes support for filtering, exception handling and thread synchronization. Also, since formatting is typical for text-based sinks, it is implemented by frontends as well. Every sink frontend receives log records from the logging core and then passes them along to the associated sink backend. The frontend does not define how to process records but rather in what way the core should interact with the backend. It is the backend that defines the processing rules of the log records. You probably won't have to write your own frontend when you need to create a new type of sink, because the library provides a number of frontends that cover most use cases.
+
+Sink frontends derive from the [class_sinks_sink] class template, which is used by the logging core to supply log records. Technically speaking, one can derive his class from the [class_sinks_sink] template and have his new-found sink, but using sink frontends saves from quite an amount of routine work. As every sink frontend is associated with a backend, the corresponding backend will also be constructed by the frontend upon its construction (unless the user provides the backend instance himself), making the sink complete. Therefore, when the frontend is constructed it can be registered in the logging core to begin processing records. See the [link log.detailed.sink_backends Sink Backends] section for more details on interactions between frontends and backends.
+
+Below is a more detailed overview of the services provided by sink frontends.
+
+[section:basic_services Basic sink frontend services]
+
+There are a number of basic functionalities that all sink frontends provide.
+
+[section:filtering Filtering]
+
+All sink frontends support filtering. The user can specify a custom filtering function object or a filter constructed with the [link log.detailed.expressions library-provided tools]. The filter can be set with the `set_filter` method or cleared with the `reset_filter` method. The filter is invoked during the call to the `will_consume` method that is issued by the logging core. If the filter is not set, it is assumed that the sink will accept any log record.
+
+[note Like the logging core, all sink frontends assume it is safe to call filters from multiple threads concurrently. This is fine with the library-provided filters.]
+
+[endsect]
+
+[section:formatting Formatting]
+
+For text-based sink backends, frontends implement record formatting. Like with filters, [link log.detailed.expressions lambda expressions] can be used to construct formatters. The formatter can be set for a text-based sink by calling the `set_formatter` method or cleared by calling `reset_formatter`.
+
+[endsect]
+
+[section:exception_handling Exception handling]
+
+All sink frontends allow setting up exception handlers in order to customize error processing on a per-sink basis. One can install an exception handling function with the `set_exception_handler` method, this function will be called with no arguments from a `catch` block if an exception occurs during record processing in the backend or during the sink-specific filtering. The exception handler is free to rethrow an exception or to suppress it. In the former case the exception is propagated to the core, where another layer of exception handling can come into action.
+
+[tip [link log.detailed.core.core.exception_handling Logging core] and [link log.detailed.sources.exception_handling loggers] also support installing exception handlers.]
+
+The library provides a [link log.detailed.utilities.exception_handlers convenient tool] for dispatching exceptions into an unary polymorphic function object.
+
+[note An exception handler is not allowed to return a value. This means you are not able to alter the filtering result once an exception occurs, and thus filtering will always fail.]
+
+[note All sink frontends assume it is safe to call exception handlers from multiple threads concurrently. This is fine with the library-provided exception dispatchers.]
+
+[endsect]
+
+[endsect]
+
+[section:unlocked Unlocked sink frontend]
+
+ #include <``[boost_log_sinks_unlocked_frontend.hpp]``>
+
+The unlocked sink frontend is implemented with the [class_sinks_unlocked_sink] class template. This frontend provides the most basic service for the backend. The [class_sinks_unlocked_sink] frontend performs no thread synchronization when accessing the backend, assuming that synchronization either is not needed or is implemented by the backend. Nevertheless, setting up a filter is still thread-safe (that is, one can safely change the filter in the [class_sinks_unlocked_sink] frontend while other threads are writing logs through this sink). This is the only sink frontend available in a single threaded environment. The example of use is as follows:
+
+[example_sinks_unlocked]
+
+[@boost:/libs/log/example/doc/sinks_unlocked.cpp See the complete code].
+
+All sink backends provided by the library require thread synchronization on the frontend part. If we tried to instantiate the frontend on the backend that requires more strict threading guarantees than what the frontend provides, the code wouldn't have compiled. Therefore this frontend is mostly useful in single-threaded environments and with custom backends.
+
+[endsect]
+
+[section:sync Synchronous sink frontend]
+
+ #include <``[boost_log_sinks_sync_frontend_hpp]``>
+
+The synchronous sink frontend is implemented with the [class_sinks_synchronous_sink] class template. It is similar to the [class_sinks_unlocked_sink] but additionally provides thread synchronization with a mutex before passing log records to the backend. All sink backends that support formatting currently require thread synchronization in the frontend.
+
+The synchronous sink also introduces the ability to acquire a pointer to the locked backend. As long as the pointer exists, the backend is guaranteed not to be accessed from other threads, unless the access is done through another frontend or a direct reference to the backend. This feature can be useful if there is a need to perform some updates on the sink backend while other threads may be writing logs. Beware, though, that while the backend is locked any other thread that tries to write a log record to the sink gets blocked until the backend is released.
+
+The usage is similar to the [class_sinks_unlocked_sink].
+
+[example_sinks_sync]
+
+[@boost:/libs/log/example/doc/sinks_sync.cpp See the complete code].
+
+[endsect]
+
+[section:async Asynchronous sink frontend]
+
+ #include <``[boost_log_sinks_async_frontend_hpp]``>
+
+ // Related headers
+ #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]``>
+
+The frontend is implemented in the [class_sinks_asynchronous_sink] class template. Like the synchronous one, asynchronous sink frontend provides a way of synchronizing access to the backend. All log records are passed to the backend in a dedicated thread, which makes it suitable for backends that may block for a considerable amount of time (network and other hardware device-related sinks, for example). The internal thread of the frontend is spawned on the frontend constructor and joined on its destructor (which implies that the frontend destruction may block).
+
+[note The current implementation of the asynchronous sink frontend use record queueing. This introduces a certain latency between the fact of record emission and its actual processing (such as writing into a file). This behavior may be inadequate in some contexts, such as debugging an application that is prone to crashes.]
+
+[example_sinks_async_init]
+
+[important If asynchronous logging is used in a multi-module application, one should decide carefully when to unload dynamically loaded modules that write logs. The library has many places where it may end up using resources that reside in the dynamically loaded module. Examples of such resources are virtual tables, string literals and functions. If any of these resources are still used by the library when the module in which they reside gets unloaded, the application will most likely crash. Strictly speaking, this problem exists with any sink type (and is not limited to sinks in the first place), but asynchronous sinks introduce an additional problem. One cannot tell which resources are used by the asynchronous sink because it works in a dedicated thread and uses buffered log records. There is no general solution for this issue. Users are advised to either avoid dynamic module unloading during the application's work time, or to avoid asynchronous logging. As an additional way to cope with the problem, one
may try to shutdown all asynchronous sinks before unloading any modules, and after unloading re-create them. However, avoiding dynamic unloading is the only way to solve the problem completely.]
+
+In order to stop the dedicated thread feeding log records to the backend one can call the `stop` method of the frontend. This method will be called automatically in the frontend destructor. The `stop` method, unlike thread interruption, will only terminate the feeding loop when a log record that is being fed is processed by the backend (i.e. it will not interrupt the record processing that has already started). However, it may happen that some records are still left in the queue after returning from the `stop` method. In order to flush them to the backend an additional call to the `feed_records` method is required. This is useful in the application termination stage.
+
+[example_sinks_async_stop]
+
+[@boost:/libs/log/example/doc/sinks_async.cpp See the complete code].
+
+Spawning the dedicated thread for log record feeding can be suppressed with the optional boolean `start_thread` named parameter of the frontend. In this case the user can select either way of processing records:
+
+* Call the `run` method of the frontend. This call will block in the feeding loop. This loop can be interrupted with the call to `stop`.
+* Periodically call `feed_records`. This method will process all the log records that were in the frontend queue when the call was issued and then return.
+
+[note Users should take care not to mix these two approaches concurrently. Also, none of these methods should be called if the dedicated feeding thread is running (i.e., the `start_thread` was not specified in the construction or had the value of `true`.]
+
+[heading Customizing record queueing strategy]
+
+The [class_sinks_asynchronous_sink] class template can be customized with the record queueing strategy. Several strategies are provided by the library:
+
+* [class_sinks_unbounded_fifo_queue]. This strategy is the default. As the name implies, the queue is not limited in depth and does not order log records.
+* [class_sinks_unbounded_ordering_queue]. Like [class_sinks_unbounded_fifo_queue], the queue has unlimited depth but it applies an order on the queued records. We will return to ordering queues in a moment.
+* [class_sinks_bounded_fifo_queue]. The queue has limited depth specified in a template parameter as well as the overflow handling strategy. No record ordering is applied.
+* [class_sinks_bounded_ordering_queue]. Like [class_sinks_bounded_fifo_queue] but also applies log record ordering.
+
+[warning Be careful with unbounded queueing strategies. Since the queue has unlimited depth, if log records are continuously generated faster than being processed by the backend the queue grows uncontrollably which manifests itself as a memory leak.]
+
+Bounded queues support the following overflow strategies:
+
+* [class_sinks_drop_on_overflow]. When the queue is full, silently drop excessive log records.
+* [class_sinks_block_on_overflow]. When the queue is full, block the logging thread until the backend feeding thread manages to process some of the queued records.
+
+For example, this is how we could modify the previous example to limit the record queue to 100 elements:
+
+[example_sinks_bounded_async_init]
+
+[@boost:/libs/log/example/doc/sinks_async_bounded.cpp See the complete code].
+
+Also see the [@boost:/libs/log/example/bounded_async_log/main.cpp `bounded_async_log`] example in the library distribution.
+
+[heading Ordering log records]
+
+Record ordering can be useful to alleviate the [link log.rationale.why_weak_record_ordering weak record ordering] issue present in multithreaded applications.
+
+Ordering queueing strategies introduce a small latency to the record processing. The latency duration and the ordering predicate can be specified on the frontend construction. It may be useful to employ the [link log.detailed.utilities.record_ordering log record ordering tools] to implement ordering predicates.
+
+[example_sinks_ordering_async_init]
+
+In the code sample above the sink frontend will keep log records in the internal queue for up to one second and apply ordering based on the log record counter of type `unsigned int`. The `ordering_window` parameter is optional and will default to some reasonably small system-specific value that will suffice to maintain chronological flow of log records to the backend.
+
+The ordering window is maintained by the frontend even upon stopping the internal feeding loop, so that it would be possible to reenter the loop without breaking the record ordering. On the other hand, in order to ensure that all log records are flushed to the backend one has to call the `flush` method at the end of the application.
+
+[example_sinks_ordering_async_stop]
+
+This technique is also demonstrated in the [@boost:/libs/log/example/async_log/main.cpp `async_log`] example in the library distribution.
+
+[endsect]
+
+[endsect]

Added: trunk/libs/log/doc/sources.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/log/doc/sources.qbk 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,172 @@
+[/
+ Copyright Andrey Semashev 2007 - 2013.
+ 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)
+
+ This document is a part of Boost.Log library documentation.
+/]
+
+[section:sources Logging sources]
+
+[section:basic_logger Basic loggers]
+
+ #include <``[boost_log_sources_basic_logger_hpp]``>
+
+The simplest logging sources provided by the library are loggers [class_sources_logger] and its thread-safe version, [class_sources_logger_mt] ([class_sources_wlogger] and [class_sources_wlogger_mt] for wide-character logging, accordingly). These loggers only provide the ability to store source-specific attributes within themselves and, of course, to form log records. This type of logger should probably be used when there is no need for advanced features like severity level checks. It may well be used as a tool to collect application statistics and register application events, such as notifications and alarms. In such cases the logger is normally used in conjunction with [link log.detailed.attributes.related_components.scoped_attributes scoped attributes] to attach the needed data to the notification event. Below is an example of usage:
+
+[example_sources_network_connection]
+
+The class `network_connection` in the code snippet above represents an approach to implementing simple logging and statistical information gathering in a network-related application. Each of the presented methods of the class effectively marks a corresponding event that can be tracked and collected on the sinks level. Furthermore, other methods of the class, that are not shown here for simplicity, are able to write logs too. Note that every log record ever made in the connected state of the `network_connection` object will be implicitly marked up with the address of the remote site.
+
+[endsect]
+
+[section:severity_level_logger Loggers with severity level support]
+
+ #include <``[boost_log_sources_severity_feature_hpp]``>
+ #include <``[boost_log_sources_severity_logger_hpp]``>
+
+The ability to distinguish some log records from others based on some kind of level of severity or importance is one of the most frequently requested features. The class templates [class_sources_severity_logger] and [class_sources_severity_logger_mt] (along with their [class_sources_wseverity_logger] and [class_sources_wseverity_logger_mt] wide-character counterparts) provide this functionality.
+
+The loggers automatically register a special source-specific attribute "Severity", which can be set for every record in a compact and efficient manner, with a named argument `severity` that can be passed to the constructor and/or the `open_record` method. If passed to the logger constructor, the `severity` argument sets the default value of the severity level that will be used if none is provided in the `open_record` arguments. The `severity` argument passed to the `open_record` method sets the level of the particular log record being made. The type of the severity level can be provided as a template argument for the logger class template. The default type is `int`.
+
+The actual values of this attribute and their meaning are entirely user-defined. However, it is recommended to use the level of value equivalent to zero as a base point for other values. This is because the default-constructed logger object sets its default severity level to zero. It is also recommended to define the same levels of severity for the entire application in order to avoid confusion in the written logs later. The following code snippet shows the usage of `severity_logger`.
+
+[example_sources_severity]
+[example_sources_default_severity]
+
+Or, if you prefer logging without macros:
+
+[example_sources_severity_manual]
+
+And, of course, severity loggers also provide the same functionality the [link log.detailed.sources.basic_logger basic loggers] do.
+
+[endsect]
+
+[section:channel_logger Loggers with channel support]
+
+ #include <``[boost_log_sources_channel_feature_hpp]``>
+ #include <``[boost_log_sources_channel_logger_hpp]``>
+
+Sometimes it is important to associate log records with some application component, such as the module or class name, the relation of the logged information to some specific domain of application functionality (e.g. network or file system related messages) or some arbitrary tag that can be used later to route these records to a specific sink. This feature is fulfilled with loggers [class_sources_channel_logger], [class_sources_channel_logger_mt] and their wide-char counterparts [class_sources_wchannel_logger], [class_sources_wchannel_logger_mt]. These loggers automatically register an attribute named "Channel". The default channel name can be set in the logger constructor with a named argument `channel`. The type of the channel attribute value can be specified as a template argument for the logger, with `std::string` (`std::wstring` in case of wide character loggers) as a default. Aside from that, the usage is similar to the [link log.detailed.sources.basic_logger basic loggers]:
+
+[example_sources_network_connection_channels]
+
+It is also possible to set the channel name of individual log records. This can be uesful when a [link log.detailed.sources.global_storage global logger] is used instead of an object-specific one. The channel name can be set by calling the `channel` modifier on the logger or by using a special macro for logging. For example:
+
+[example_sources_network_connection_dynamic_channels]
+
+Note that changing the channel name is persistent, so unless the channel name is reset, the subsequent records will also belong to the new channel.
+
+[tip For performance reasons it is advised to avoid dynamically setting the channel name individually for every log record, when possible. Changing the channel name involves dynamic memory allocation. Using distinct loggers for different channels allows to avoid this overhead.]
+
+[endsect]
+
+[section:exception_handling Loggers with exception handling support]
+
+ #include <``[boost_log_sources_exception_handler_feature_hpp]``>
+
+The library provides a logger feature that enables the user to handle and/or suppress exceptions at the logger level. The [class_sources_exception_handler] feature adds a `set_exception_handler` method to the logger that allows setting a function object to be called if an exception is thrown from the logging core during the filtering or processing of log records. One can use the [link log.detailed.utilities.exception_handlers library-provided adapters] to simplify implementing exception handlers. Usage example is as follows:
+
+[example_sources_exception_handler]
+
+[tip [link log.detailed.core.core.exception_handling Logging core] and [link log.detailed.sink_frontends.basic_services.exception_handling sink frontends] also support installing exception handlers.]
+
+[endsect]
+
+[section:mixed_loggers Loggers with mixed features]
+
+ #include <``[boost_log_sources_severity_channel_logger_hpp]``>
+
+If you wonder whether you can use a mixed set of several logger features in one logger, then yes, you certainly can. The library provides [class_sources_severity_channel_logger] and [class_sources_severity_channel_logger_mt] (with their wide-char analogues [class_sources_wseverity_channel_logger] and [class_sources_wseverity_channel_logger_mt]) which combine features of the described loggers with [link log.detailed.sources.severity_level_logger severity level] and [link log.detailed.sources.channel_logger channels] support. The composite loggers are templates, too, which allows you to specify severity level and channel types. You can also design your own logger features and combine them with the ones provided by the library, as described in the [link log.extension.sources Extending the library] section.
+
+The usage of the loggers with several features does not conceptually differ from the usage of the single-featured loggers. For instance, here is how a [class_sources_severity_channel_logger_mt] could be used:
+
+[example_sources_severity_channel]
+
+[endsect]
+
+[section:global_storage Global storage for loggers]
+
+ #include <``[boost_log_sources_global_logger_storage_hpp]``>
+
+Sometimes it is inconvenient to have a logger object to be able to write logs. This issue is often present in functional-style code with no obvious places where a logger could be stored. Another domain where the problem persists is generic libraries that would benefit from logging. In such cases it would be more convenient to have one or several global loggers in order to easily access them in every place when needed. In this regard `std::cout` is a good example of such a logger.
+
+The library provides a way to declare global loggers that can be accessed pretty much like `std::cout`. In fact, this feature can be used with any logger, including user-defined ones. Having declared a global logger, one can be sure to have a thread-safe access to this logger instance from any place of the application code. The library also guarantees that a global logger instance will be unique even across module boundaries. This allows employing logging even in header-only components that may get compiled into different modules.
+
+One may wonder why there is a need for something special in order to create global loggers. Why not just declare a logger variable at namespace scope and use it wherever you need? While technically this is possible, declaring and using global logger variables is complicated for the following reasons:
+
+* Order of initialization of namespace scope variables is not specified by the C++ Standard. This means that generally you cannot use the logger during this stage of initialization (i.e. before `main`).
+* Initialization of namespace scope variables is not thread-safe. You may end up initializing the same logger twice or using an uninitialized logger.
+* Using namespace scope variables in a header-only library is quite complicated. One either has to declare a variable with external linkage and define it only in a single translation unit (that is, in a separate .cpp file, which defeats the "header-only" thesis), or define a variable with internal linkage, or as a special case in an anonymous namespace (this will most likely break ODR and give unexpected results when the header is used in different translation units). There are other compiler-specific and standard tricks to tackle the problem, but they are not quite trivial and portable.
+* On most platforms namespace scope variables are local to the module where they were compiled in. That is, if variable `a` has external linkage and was compiled into modules X and Y, each of these modules has its own copy of variable `a`. To make things worse, on other platforms this variable can be shared between the modules.
+
+Global logger storage is intended to eliminate all these problems.
+
+The easiest way to declare a global logger is to use the following macro:
+
+ ``[macroref BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT]``(my_logger, src::severity_logger_mt< >)
+
+The `my_logger` argument gives the logger a name that may be used to acquire the logger instance. This name acts as a tag of the declared logger. The second parameter denotes the logger type. In multithreaded applications, when the logger can be accessed from different threads, users will normally want to use the thread-safe versions of loggers.
+
+If passing arguments to the logger constructor is needed, there is another macro:
+
+ ``[macroref BOOST_LOG_INLINE_GLOBAL_LOGGER_CTOR_ARGS]``(
+ my_logger,
+ src::severity_channel_logger< >,
+ (keywords::severity = error)(keywords::channel = "my_channel"))
+
+The last macro argument is a __boost_preprocessor__ sequence of arguments passed to the logger constructor. Be careful, however, when using non-constant expressions and references to objects as constructor arguments, since the arguments are evaluated only once and it is often difficult to tell the exact moment when it is done. The logger is constructed on the first request from whichever part of the application that has the knowledge of the logger declaration. It is up to user to make sure that all arguments have valid states at that point.
+
+The third macro of this section provides maximum initialization flexibility, allowing the user to actually define the logic of creating the logger.
+
+ ``[macroref BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT]``(my_logger, src::severity_logger_mt)
+ {
+ // Do something that needs to be done on logger initialization,
+ // e.g. add a stop watch attribute.
+ src::severity_logger_mt< > lg;
+ lg.add_attribute("StopWatch", boost::make_shared< attrs::timer >());
+ // The initializing routine must return the logger instance
+ return lg;
+ }
+
+Like the [macroref BOOST_LOG_INLINE_GLOBAL_LOGGER_CTOR_ARGS] macro, the initialization code is called only once, on the first request of the logger.
+
+[important Beware of One Definition Rule (ODR) issues. Regardless of the way of logger declaration you choose, you should ensure that [_the logger is declared in exactly the same way at all occurrences] and [_all symbol names involved in the declaration resolve to the same entities]. The latter includes the names used within the initialization routine of the [macroref BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT] macro, such as references to external variables, functions and types. The library tries to protect itself from ODR violations to a certain degree, but in general the behavior is undefined if the rule is violated.]
+
+In order to alleviate ODR problems, it is possible to separate the logger declaration and its initialization routine. The library provides the following macros to achieve this:
+
+* [macroref BOOST_LOG_GLOBAL_LOGGER] provides the logger declaration. It can be used in a header, similarly to the `BOOST_LOG_INLINE_GLOBAL_LOGGER*` macros described above.
+* [macroref BOOST_LOG_GLOBAL_LOGGER_INIT], [macroref BOOST_LOG_GLOBAL_LOGGER_DEFAULT] and [macroref BOOST_LOG_GLOBAL_LOGGER_CTOR_ARGS] define the logger initialization routine. Their semantics and usage is similar to the corresponding `BOOST_LOG_INLINE_GLOBAL_LOGGER*` macros, for one exception: these macros should be used in a single .cpp file.
+
+For example:
+
+ // my_logger.h
+ // ===========
+
+ BOOST_LOG_GLOBAL_LOGGER(my_logger, src::severity_logger_mt)
+
+
+ // my_logger.cpp
+ // ===========
+
+ #include "my_logger.h"
+
+ BOOST_LOG_GLOBAL_LOGGER_INIT(my_logger, src::severity_logger_mt)
+ {
+ src::severity_logger_mt< > lg;
+ lg.add_attribute("StopWatch", boost::make_shared< attrs::timer >());
+ return lg;
+ }
+
+Regardless of the macro you used to declare the logger, you can acquire the logger instance with the static `get` function of the logger tag:
+
+ src::severity_logger_mt< >& lg = my_logger::get();
+
+Further usage of the logger is the same as if it was a regular logger object of the corresponding type.
+
+[warning It should be noted that it is not advised to use global loggers during the deinitialization stage of the application. Like any other global object in your application, the global logger may get destroyed before you try to use it. In such cases it's better to have a dedicated logger object that is guaranteed to be available as long as needed.]
+
+[endsect]
+
+[endsect]

Added: trunk/libs/log/doc/todo.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/log/doc/todo.qbk 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,29 @@
+[/
+ Copyright Andrey Semashev 2007 - 2013.
+ 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)
+
+ This document is a part of Boost.Log library documentation.
+/]
+
+[section:todo TODO in future releases]
+
+Points in this section are not necessarily going to be implemented. These are mainly some thoughts on further improvements of the library.
+
+* Optimize single-threaded configuration. In many places dynamic memory allocation can be avoided if multithreading support is disabled.
+* SNMP support. The idea is to implement a sink backend that would emit SNMP traps as a result of processing log records. This needs quite an amount of research and thinking over.
+* Provide a compile-time option to remove all logging from the application (the compiled binary should contain no traces of logging internally). There are two reasons for this request: attempting to achieve maximum performance and concealing internal information, such as function names and internal messages, to prevent reverse engineering in no-logging builds. Effectively, this would require not only all library macros to be redefined to emptiness, but also to provide dummy implementations of many library components. Needs more consideration. Perhaps, suppressing only macros would be sufficient.
+* Provide a macro, like `BOOST_LOG_FUNCTION`, but with ability to automatically log all function arguments.
+* Think over a header-only configuration. Perhaps, with a reduced functionality.
+* Update syslog support to [@http://tools.ietf.org/html/rfc5424 RFC 5424].
+* Provide some kind of shared formatters. The idea is that several sinks may use the same formatter. If a log record passes filtering to multiple such sinks, the formatting is done just once for all sinks that share the formatter. Maybe, it will require refactoring the sinks architecture, transforming them into pipelines with formatter and backends being just steps in log record processing.
+* Allow to change the locale for the file stream in the text file backend. The locale can alter the character code conversion in wide-character logging.
+* Improve file collection in the file sink. Make it possible to (i) rename collected files and (ii) collect files in a dedicated thread.
+* Provide headers with forward declarations of the library components.
+* Make it possible to update library configuration after loading settings from a file. Probably, this will require a new configuration entity that will be able to detect and apply changes between settings.
+* Develop a statistics gathering framework. The basic idea is to provide a specific log source and a pin. The user can pin his data or explicitly indicate events by invoking the log source. The source would automatically collect the data from the pinned variables. This source should have a better integration with filters to be able which pins should be collected and which should not.
+* Allow to specify a process ID in the file name pattern for file-based sinks.
+* Improve support for `format` formatter, implement placeholder format flags.
+
+[endsect]

Added: trunk/libs/log/doc/tutorial.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/log/doc/tutorial.qbk 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,375 @@
+[/
+ Copyright Andrey Semashev 2007 - 2013.
+ 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)
+
+ This document is a part of Boost.Log library documentation.
+/]
+
+[section:tutorial Tutorial]
+
+In this section we shall walk through the essential steps to get started with the library. After reading it you should be able to initialize the library and add logging to your application. The code of this tutorial is also available in examples residing in the `libs/log/examples` directory. Feel free to play with them, compile and see the result.
+
+[section:trivial Trivial logging]
+
+For those who don't want to read tons of clever manuals and just need a simple tool for logging, here you go:
+
+[example_tutorial_trivial]
+
+[@boost:/libs/log/example/doc/tutorial_trivial.cpp See the complete code].
+
+The `BOOST_LOG_TRIVIAL` macro accepts a severity level and results in a stream-like object that supports insertion operator. As a result of this code, the log messages will be printed on the console. As you can see, this library usage pattern is quite similar to what you would do with `std::cout`. However, the library offers a few advantages:
+
+# Besides the record message, each log record in the output contains a timestamp, the current thread identifier and severity level.
+# It is safe to write logs from different threads concurrently, log messages will not be corrupted.
+# As will be shown later, filtering can be applied.
+
+It must be said that the macro, along with other similar macros provided by the library, is not the only interface the library offers. It is possible to issue log records without using any macros at all.
+
+[endsect]
+
+[section:trivial_filtering Trivial logging with filters]
+
+While severity levels can be used for informative purposes, you will normally want to apply filters to output only significant records and ignore the rest. It is easy to do so by setting a global filter in the library core, like this:
+
+[example_tutorial_trivial_with_filtering]
+
+[@boost:/libs/log/example/doc/tutorial_trivial_flt.cpp See the complete code].
+
+Now, if we run this code sample, the first two log records will be ignored, while the remaining four will pass on to the file.
+
+[important Remember that the streaming expression is only executed if the record passed filtering. Don't specify business-critical calls in the streaming expression, as these calls may not get invoked if the record is filtered away.]
+
+A few words must be said about the filter setup expression. Since we're setting up a global filter, we have to acquire the [link log.detailed.core.core logging core] instance. This is what `logging::core::get()` does - it returns a pointer to the core singleton. The `set_filter` method of the logging core sets the global filtering function.
+
+The filter in this example is built as a __boost_phoenix__ lambda expression. In our case, this expression consists of a single logical predicate, whose left argument is a placeholder that describes the attribute to be checked, and the right argument is the value to be checked against. The `severity` keyword is a placeholder provided by the library. This placeholder identifies the severity attribute value in the template expressions; this value is expected to have name "Severity" and type [enumref boost::log::trivial::severity_level `severity_level`]. This attribute is automatically provided by the library in case of trivial logging; the user only has to supply its value in logging statements. The placeholder along with the ordering operator creates a function object that will be called by the logging core to filter log records. As a result, only log records with severity level not less than `info` will pass the filter and end up on the console.
+
+It is possible to build more complex filters, combining logical predicates like this with each other, or even define your own function (including a C++11 lambda function) that would act as a filter. We will return to filtering in the following sections.
+
+[endsect]
+
+[section:sinks Setting up sinks]
+
+Sometimes trivial logging doesn't provide enough flexibility. For example, one may want a more sophisticated logic of log processing, rather than simply printing it on the console. In order to customize this, you have to construct logging sinks and register them with the logging core. This should normally be done only once somewhere in the startup code of your application.
+
+[note It must be mentioned that in the previous sections we did not initialize any sinks, and trivial logging worked somehow anyway. This is because the library contains a ['default] sink that is used as a fallback when the user did not set up any sinks. This sink always prints log records to the console in a fixed format which we saw in our previous examples. The default sink is mostly provided to allow trivial logging to be used right away, without any library initialization whatsoever. Once you add any sinks to the logging core, the default sink will no longer be used. You will still be able to use trivial logging macros though.]
+
+[heading File logging unleashed]
+
+As a starting point, here is how you would initialize logginig to a file:
+
+[example_tutorial_file_simple]
+
+The added piece is the call to the [link log.detailed.utilities.setup.convenience `add_file_log`] function. As the name implies, the function initializes a logging sink that stores log records into a text file. The function also accepts a number of customization options, such as the file rotation interval and size limits. For instance:
+
+[example_tutorial_file_advanced]
+
+[@boost:/libs/log/example/doc/tutorial_file.cpp See the complete code].
+
+You can see that the options are passed to the function in the named form. This approach is also taken in many other places of the library. You'll get used to it. The meaning of the parameters is mostly self-explaining and is documented in this manual (see [link log.detailed.sink_backends.text_file here] for what regards the text file sink). This and other convenience initialization functions are described in [link log.detailed.utilities.setup.convenience this] section.
+
+[note You can register more than one sink. Each sink will receive and process log records as you emit them independently from others.]
+
+[heading Sinks in depth: More sinks]
+
+If you don't want to go into details, you can skip this section and continue reading from the next one. Otherwise, if you need more comprehensive control over sink configuration or want to use more sinks than those available through helper functions, you can register sinks manually.
+
+In the simplest form, the call to the `add_file_log` function in the section above is nearly equivalent to this:
+
+[example_tutorial_file_manual]
+
+[@boost:/libs/log/example/doc/tutorial_file_manual.cpp See the complete code].
+
+Ok, the first thing you may have noticed about sinks is that they are composed of two classes: the frontend and the backend. The frontend (which is the [link log.detailed.sink_frontends.sync `synchronous_sink`] class template in the snippet above) is responsible for various common tasks for all sinks, such as thread synchronization model, filtering and, for text-based sinks, formatting. The backend (the [link log.detailed.sink_backends.text_ostream `text_ostream_backend`] class above) implements everything specific to the sink, such as writing to a file in this case. The library provides a number of frontends and backends that can be used with each other out of the box.
+
+The [link log.detailed.sink_frontends.sync `synchronous_sink`] class template above indicates that the sink is synchronous, that is, it allows for several threads to log simultaneously and will block in case of contention. This means that the backend [link log.detailed.sink_backends.text_ostream `text_ostream_backend`] doesn't have to worry about multithreading at all. There are other sink frontends available, you can read more about them [link log.detailed.sink_frontends here].
+
+The [link log.detailed.sink_backends.text_ostream `text_ostream_backend`] class writes formatted log records into STL-compatible streams. We have used a file stream above but we could have used any type of stream. For example, adding output to console could look as follows:
+
+ #include <``[boost_log_utility_empty_deleter_hpp]``>
+
+ // We have to provide an empty deleter to avoid destroying the global stream object
+ boost::shared_ptr< std::ostream > stream(&std::clog, logging::empty_deleter());
+ sink->locked_backend()->add_stream(stream);
+
+The [link log.detailed.sink_backends.text_ostream `text_ostream_backend`] supports adding several streams. In that case its output will be duplicated to all added streams. It can be useful to duplicate the output to console and file since all the filtering, formatting and other overhead of the library happen only once per record for the sink.
+
+[note Please note the difference between registering several distinct sinks and registering one sink with several target streams. While the former allows for independently customizing output to each sink, the latter would work considerably faster if such customization is not needed. This feature is specific to this particular backend.]
+
+The library provides a number of [link log.detailed.sink_backends backends] that provide different log processing logic. For instance, by specifying the [link log.detailed.sink_backends.syslog syslog] backend you can send log records over the network to the syslog server, or by setting up the [link log.detailed.sink_backends.event_log Windows NT event log] backend you can monitor your application run time with the standard Windows tools.
+
+The last thing worth noting here is the `locked_backend` member function call to access the sink backend. It is used to get thread-safe access to the backend and is provided by all sink frontends. This function returns a smart-pointer to the backend and as long as it exists the backend is locked (which means even if another thread tries to log and the log record is passed to the sink, it will not be logged until you release the backend). The only exception is the [link log.detailed.sink_frontends.unlocked `unlocked_sink`] frontend which does not synchronize at all and simply returns an unlocked pointer to the backend.
+
+[endsect]
+
+[section:sources Creating loggers and writing logs]
+
+[heading Dedicated logger objects]
+
+Now that we have defined where and how the log is to be stored, it's time to go on and try logging. In order to do this one has to create a logging source. This would be a logger object in our case and it is as simple as that:
+
+ src::logger lg;
+
+[note A curious reader could have noticed that we did not create any loggers for trivial logging. In fact the logger is provided by the library and is used behind the scenes.]
+
+Unlike sinks, sources need not be registered anywhere since they interact directly with the logging core. Also note that there are two versions of loggers provided by the library: the thread-safe ones and the non-thread-safe ones. For the non-thread-safe loggers it is safe for different threads to write logs through different instances of loggers and thus there should be a separate logger for each thread that writes logs. The thread-safe counterparts can be accessed from different threads concurrently, but this will involve locking and may slow things down in case of intense logging. The thread-safe logger types have the `_mt` suffix in their name.
+
+Regardless of the thread safety, all loggers provided by the library are default and copy-constructible and support swapping, so there should be no problem in making a logger a member of your class. As you will see later, such approach can give you additional benefits.
+
+The library provides a number of loggers with different features, such as severity and channel support. These features can be combined with each other in order to construct more complex loggers. See [link log.detailed.sources here] for more datails.
+
+[heading Global logger objects]
+
+In case you cannot put a logger into your class (suppose you don't have one), the library provides a way of declaring global loggers like this:
+
+ BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(my_logger, src::logger_mt)
+
+Here `my_logger` is a user-defined tag name that will be used later to retrieve the logger instance and `logger_mt` is the logger type. Any logger type provided by the library or defined by the user can participate in such declaration. However, since the logger will have a single instance, you will normally want to use thread-safe loggers in a multithreaded application as global ones.
+
+[tip There are other macros for more sophisticated cases available. The detailed description is in [link log.detailed.sources.global_storage this] section.]
+
+Later on you can acquire the logger like this:
+
+ src::logger_mt& lg = my_logger::get();
+
+The `lg` will refer to the one and only instance of the logger throughout the application, even if the application consists of multiple modules. The `get` function itself is thread-safe, so there is no need in additional synchronization around it.
+
+[heading Writing logs]
+
+No matter what kind of logger you use (class member or global, thread-safe or not), to write a log record into a logger you can write something like this:
+
+[example_tutorial_logging_manual_logging]
+
+Here the `open_record` function call determines if the record to be constructed is going to be consumed by at least one sink. Filtering is applied at this stage. If the record is to be consumed, the function returns a valid record object, and one can fill in the record message string. After that the record processing can be completed with the call to `push_record`.
+
+Of course, the above syntax can easily be wrapped in a macro and, in fact, users are encouraged to write their own macros instead of using the C++ logger interface directly. The log record above can be written like this:
+
+ BOOST_LOG(lg) << "Hello, World!";
+
+Looks a bit shorter, doesn't it? The `BOOST_LOG` macro, along with other similar ones, is defined by the library. It automatically provides an STL-like stream in order to format the message with ordinary insertion expressions. Having all that code written, compiled and executed you should be able to see the "Hello, World!" record in the "sample.log" file. You will find the full code of this section [@boost:/libs/log/example/doc/tutorial_logging.cpp here].
+
+[endsect]
+
+[section:attributes Adding more information to log: Attributes]
+
+In previous sections we mentioned attributes and attribute values several times. Here we will discover how attributes can be used to add more data to log records.
+
+Each log record can have a number of named attribute values attached. Attributes can represent any essental information about the conditions in which the log record occurred, such as position in the code, executable module name, current date and time, or any piece of data relevant to your particular application and execution environment. An attribute may behave as a value generator, in which case it would return a different value for each log record it's involved in. As soon as the attribute generates the value, the latter becomes independent from the creator and can be used by filters, formatters and sinks. But in order to use the attribute value one has to know its name and type, or at least a set of types it may have. There are a number of commonly used attributes implemented in the library, you can find the types of their values in the documentation.
+
+Aside from that, as described in the [link log.design Design overview] section, there are three possible scopes of attributes: source-specific, thread-specific and global. When a log record is made, attribute values from these three sets are joined into a single set and passed to sinks. This implies that the origin of the attribute makes no difference for sinks. Any attribute can be registered in any scope. When registered, an attribute is given a unique name in order to make it possible to search for it. If it happens that the same named attribute is found in several scopes, the attribute from the most specific scope is taken into consideration in any further processing, including filtering and formatting. Such behavior makes it possible to override global or thread-scoped attributes with the ones registered in your local logger, thus reducing thread interference.
+
+Below is the description of the attribute registration process.
+
+[heading Commonly used attributes]
+
+There are attributes that are likely to be used in nearly any application. Log record counter and a time stamp are good candidates. They can be added with a single function call:
+
+ logging::add_common_attributes();
+
+With this call attributes "LineID", "TimeStamp", "ProcessID" and "ThreadID" are registered globally. The "LineID" attribute is a counter that increments for each record being made, the first record gets identifier 1. The "TimeStamp" attribute always yields the current time (i.e. the time when the log record is created, not the time it was written to a sink). The last two attributes identify the process and the thread in which every log record is emitted.
+
+[note In single-threaded builds the "ThreadID" attribute is not registered.]
+
+[tip By default, when application starts, no attributes are registered in the library. The application has to register all the necessary attributes in the library before it starts writing logs. This can be done as a part of the library initialization. A curious reader could have wondered how trivial logging works then. The answer is that the default sink doesn't really use any attribute values, except for the severity level, to compose its output. This is done to avoid the need for any initialization for trivial logging. Once you use filters or formatters and non-default sinks you will have to register the attributes you need.]
+
+The [funcref boost::log::add_common_attributes `add_common_attributes`] function is one of the several convenience helpers described [link log.detailed.utilities.setup.convenience here].
+
+Some attrubutes are registered automatically on loggers construction. For example, [link log.detailed.sources.severity_level_logger `severity_logger`] registers a source-specific attribute "Severity" which can be used to add a level of emphasis for different log records. For example:
+
+[example_sources_severity]
+
+[tip You can define your own formatting rules for the severity level by defining `operator <<` for this type. It will be automatically used by the library formatters. See [link log.detailed.expressions.attr this] section for more details.]
+
+The `BOOST_LOG_SEV` macro acts pretty much like `BOOST_LOG` except that it takes an additional argument for the `open_record` method of the logger. The `BOOST_LOG_SEV` macro can be replaced with this equivalent:
+
+[example_sources_severity_manual]
+
+You can see here that the `open_record` can take named arguments. Some logger types provided by the library have support for such additional parameters and this approach can certainly be used by users when writing their own loggers.
+
+[heading More attributes]
+
+Let's see what's under the hood of that [link log.detailed.utilities.setup.convenience `add_common_attributes`] function we used in the simple form section. It might look something like this:
+
+ void add_common_attributes()
+ {
+ boost::shared_ptr< logging::core > core = logging::core::get();
+ core->add_global_attribute("LineID", attrs::counter< unsigned int >(1));
+ core->add_global_attribute("TimeStamp", attrs::local_clock());
+
+ // other attributes skipped for brevity
+ }
+
+Here the [link log.detailed.attributes.counter `counter`] and [link log.detailed.attributes.clock `local_clock`] components are attribute classes, they derive from the common attribute interface [class_log_attribute]. The library provides a number of other [link log.detailed.attributes attribute classes], including the [link log.detailed.attributes.function `function`] attribute that calls some function object on value acquisition. For example, we can in a similar way register a [link log.detailed.attributes.named_scope `named_scope`] attrubute:
+
+ core->add_global_attribute("Scope", attrs::named_scope());
+
+This will give us the ability to store scope names in log for every log record the application makes. Here is how it's used:
+
+[example_tutorial_attributes_named_scope]
+
+Logger-specific attributes are no less useful than global ones. Severity levels and channel names are the most obvious candidates to be implemented on the source level. Nothing prevents you from adding more attributes to your loggers, like this:
+
+[example_tutorial_attributes_tagged_logging]
+
+Now all log records made through this logger will be tagged with the specific attribute. This attribute value may be used later in filtering and formatting.
+
+Another good use of attributes is the ability to mark log records made by different parts of application in order to highlight activity related to a single process. One can even implement a rough profiling tool to detect performance bottlenecks. For example:
+
+[example_tutorial_attributes_timed_logging]
+
+Now every log record made from the `logging_function` function, or any other function it calls, will contain the "Timeline" attribute with a high precision time duration passed since the attribute was registered. Based on these readings, one will be able to detect which parts of the code require more or less time to execute. The "Timeline" attribute will be unregistered upon leaving the scope of function `timed_logging`.
+
+See the [link log.detailed.attributes Attributes] section for detailed description of attributes provided by the library. The complete code for this section is available [@boost:/libs/log/example/doc/tutorial_attributes.cpp here].
+
+[heading Defining attribute placeholders]
+
+As we will see in the coming sections, it is useful to define a keyword describing a particular attribute the application uses. This keyword will be able to participate in filtering and formatting expressions, like the `severity` placeholder we have used in previous sections. For example, to define placeholders for some of the attributes we used in the previous examples we can write this:
+
+ BOOST_LOG_ATTRIBUTE_KEYWORD(line_id, "LineID", unsigned int)
+ BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", severity_level)
+ BOOST_LOG_ATTRIBUTE_KEYWORD(tag_attr, "Tag", std::string)
+ BOOST_LOG_ATTRIBUTE_KEYWORD(scope, "Scope", attrs::named_scope::value_type)
+ BOOST_LOG_ATTRIBUTE_KEYWORD(timeline, "Timeline", attrs::timer::value_type)
+
+Each macro defines a keyword. The first argument is the placeholder name, the second is the attribute name and the last parameter is the attribute value type. Once defined, the placeholder can be used in template expressions and some other contexts of the library. More details on defining attribute keywords are available [link log.detailed.expressions.attr_keywords here].
+
+[endsect]
+
+[section:formatters Log record formatting]
+
+If you tried running examples from the previous sections, you may have noticed that only log record messages are written to the files. This is the default behavior of the library when no formatter is set. Even if you added attributes to the logging core or a logger, the attribute values will not reach the output unless you specify a formatter that will use these values.
+
+Returning to one of the examples in previous tutorial sections:
+
+[example_tutorial_file_advanced_no_callouts]
+
+In the case of the `add_file_log` function, the `format` parameter allows to specify format of the log records. If you prefer to set up sinks manually, sink frontends provide the `set_formatter` member function for this purpose.
+
+The format can be specified in a number of ways, as described further.
+
+[heading Lambda-style formatters]
+
+You can create a formatter with a lambda-style expression like this:
+
+[example_tutorial_formatters_stream]
+
+[@boost:/libs/log/example/doc/tutorial_fmt_stream.cpp See the complete code].
+
+Here the `stream` is a placeholder for the stream to format the record in. Other insertion arguments, such as [link log.detailed.expressions.attr `attr`] and [link log.detailed.expressions.message `message`], are manipulators that define what should be stored in the stream. We have already seen the `severity` placeholder in filtering expressions, and here it is used in a formatter. This is a nice unification: you can use the same placeholders in both filters and formatters. The [link log.detailed.expressions.attr `attr`] placeholder is similar to the `severity` placeholder as it represents the attribute value, too. The difference is that the `severity` placeholder represents the particular attribute with the name "Severity" and type `trivial::severity_level` and [link log.detailed.expressions.attr `attr`] can be used to represent any attribute. Otherwise the two placeholders are equivalent. For instance, it is possible to replace `severity` with the following:
+
+ expr::attr< logging::trivial::severity_level >("Severity")
+
+[tip As shown in the previous section, it is possible to define placeholders like `severity` for user's attributes. As an additional benefit to the simpler syntax in the template expressions such placeholders allow to concentrate all the information about the attribute (the name and the value type) in the placeholder definition. This makes coding less error-prone (you won't misspel the attribute name or specify incorrect value type) and therefore is the recommended way of defining new attributes and using them in template expressions.]
+
+There are other [link log.detailed.expressions.formatters formatter manipulators] that provide advanced support for date, time and other types. Some manipulators accept additional arguments that customize their behavior. Most of these arguments are named and can be passed in __boost_parameter__ style.
+
+For a change, let's see how it's done when manually initializing sinks:
+
+[example_tutorial_formatters_stream_manual]
+
+[@boost:/libs/log/example/doc/tutorial_fmt_stream_manual.cpp See the complete code].
+
+You can see that it is possible to bind format changing manipulators in the expression; these manipulators will affect the subsequent attribute value format when log record is formatted, just like with streams. More manipulators are described in the [link log.detailed.expressions Detailed features description] section.
+
+[heading Boost.Format-style formatters]
+
+As an alternative, you can define formatters with with a syntax similar to __boost_format__. The same formatter as described above can be written as follows:
+
+[example_tutorial_formatters_format]
+
+[@boost:/libs/log/example/doc/tutorial_fmt_format.cpp See the complete code].
+
+The `format` placeholder accepts the format string with positional specification of all arguments being formatted. Note that only positional format is currently supported. The same format specification can be used with the `add_file_log` and similar functions.
+
+[heading Specialized formatters]
+
+The library provides specialized formatters for a number of types, such as date, time and named scope. These formatters provide extended control over the formatted values. For example, it is possible to describe date and time format with a format string compatible with __boost_date_time__:
+
+[example_tutorial_formatters_stream_date_time]
+
+[@boost:/libs/log/example/doc/tutorial_fmt_stream.cpp See the complete code].
+
+The same formatter can also be used in the context of a __boost_format__-style formatter.
+
+[heading String templates as formatters]
+
+In some contexts textual templates are accepted as formatters. In this case library initialization support code is invoked in order to parse the template and reconstruct the appropriate formatter. There are a number of caveats to keep in mind when using this approach, but here it will suffice to just briefly describe the template format.
+
+[example_tutorial_formatters_string]
+
+[@boost:/libs/log/example/doc/tutorial_fmt_string.cpp See the complete code].
+
+Here, the `format` parameter accepts such a format template. The template may contain a number of placeholders enclosed with percent signs (`%`). Each placeholder must contain an attribute value name to insert instead of the placeholder. The `%Message%` placeholder will be replaced with the logging record message.
+
+[note Textual format templates are not accepted by sink backends in the `set_formatter` method. In order to parse textual template into a formatter function one has to call `parse_formatter` function. See [link log.detailed.utilities.setup.filter_formatter here] for more details.]
+
+[heading Custom formatting functons]
+
+You can add a custom formatter to a sink backend that supports formatting. The formatter is actually a function object that supports the following signature:
+
+ void (logging::record_view const& rec, logging::basic_formatting_ostream< CharT >& strm);
+
+Here `CharT` is the target character type. The formatter will be invoked whenever a log record view `rec` passes filtering and is to be stored in log.
+
+[tip Record views are very similar to records. The notable distinction is that the view is immutable and implements shallow copy. Formatters and sinks only operate on record views, which prevents them from modifying the record while it can be still in use by other sinks in other threads.]
+
+The formatted record should be composed by insertion into STL-compatible output stream `strm`. Here's an example of a custom formatter function usage:
+
+[example_tutorial_formatters_custom]
+
+[@boost:/libs/log/example/doc/tutorial_fmt_custom.cpp See the complete code].
+
+[endsect]
+
+[section:advanced_filtering Filtering revisited]
+
+We've already touched filtering in the previous sections but we barely scratched the surface. Now that we are able to add attributes to log records and set up sinks, we can build however complex filtering we need. Let's consider this example:
+
+[example_tutorial_filtering]
+
+[@boost:/libs/log/example/doc/tutorial_filtering.cpp See the complete code].
+
+In this sample we initialize two sinks - one for the complete log file and the other for important messages only. Both sinks will be writing to text files with the same log record format, which we initialize first and save to the `fmt` variable. The [classref boost::log::basic_formatter formatter] type is a type-erased function object with the formatter calling signature; in many respects it can be viewed similar to `boost::function` or `std::function` except that it is never empty. There is also [classref boost::log::filter a similar function object] for filters.
+
+Notably, the formatter itself contains a filter here. As you can see, the format contains a conditional part that is only present when log records contain the "Tag" attribute. The [link log.detailed.expressions.predicates.has_attr `has_attr`] predicate checks whether the record containts the "Tag" attribute value and conrtols whether it is put into the file or not. We used the attribute keyword to specify the name and type of the attribute for the predicate, but it is also possible to specify them in the [link log.detailed.expressions.predicates.has_attr `has_attr`] call site. Conditional formatters are explained in more details [link log.detailed.expressions.formatters.conditional here].
+
+Further goes the initialization of the two sinks. The first sink does not have any filter, which means it will save every log record to the file. We call `set_filter` on the second sink to only save log records with severity no less than `warning` or having a "Tag" attribute with value "IMPORTANT_MESSAGE". As you can see, the filter syntax resembles usual C++ very much, especially when attribute keywords are used.
+
+Like with formatters, it is also possible to use custom functions as filters. __boost_phoenix__ can be very helpful in this case as its `bind` implementation is compatible with attribute placeholders. The previous example can be modified in the following way:
+
+[example_tutorial_filtering_bind]
+
+As you can see, the custom formatter receives attribute values wrapped into the [link log.detailed.utilities.value_ref `value_ref`] template. This wrapper contains an optional reference to the attribute value of the specified type; the reference is valid if the log record contains the attribute value of the required type. The relational operators used in `my_filter` can be applied unconditionally because they will automatically return `false` if the reference is not valid. The rest is done with the `bind` expression which will recognize the `severity` and `tag_attr` keywords and extract the corresponding values before passing them to `my_filter`.
+
+You can try how this works by compiling and running the [@boost:/libs/log/example/doc/tutorial_filtering.cpp test].
+
+[endsect]
+
+[section:wide_char Wide character logging]
+
+The library supports logging strings containing national characters. There are basically two ways of doing this. On UNIX-like systems typically some multibyte character encoding (e.g. UTF-8) is used to represent national characters. In this case the library can be used just the way it is used for plain ASCII logging, no additional setup is required.
+
+On Windows the common practice is to use wide strings to represent national characters. Also, most of the system API is wide character oriented, which requires Windows-specific sinks to also support wide strings. On the other hand, generic sinks, like [link log.detailed.sink_backends.text_file text file sink, are byte-oriented (because, well, you store bytes in files, not characters). This forces the library to perform character code conversion when needed by the sink. To set up the library for this one has to imbue the sink with a locale with the appropriate `codecvt` facet. __boost_locale__ can be used to generate such a locale. Let's see an example:
+
+[example_wide_char_logging_initialization]
+
+First let's take a look at the formatter we pass in the `format` parameter. We initialize the sink with a narrow-character formatter because the text file sink processes bytes. It is possible to use wide strings in the formatter, but not in format strings, like the one we used with the [funcref boost::log::expressions::format_date_time `format_date_time`] function. Also note that we used `message` keyword to denote the log record messages. This [link log.detailed.expressions.message placeholder] supports both narrow and wide character messages, so the formatter will work with both. As part of the formatting process, the library will convert wide character messages to multibyte encoding using the imbued locale, which we set to UTF-8.
+
+[tip Attribute values can also contain wide strings. Like log record messages, these strings will be converted with the imbued locale to the target character encoding.]
+
+One thing missing here is our `severity_level` type definition. The type is just an enumeration, but if we want to support its formatting for both narrow and wide character sinks, its streaming operator has to be a template. This may be useful if we create multiple sinks with different character types.
+
+[example_wide_char_severity_level_definition]
+
+Now we can emit log records. We can use loggers with `w` prefix in their names to compose wide character messages.
+
+[example_wide_char_logging]
+
+As you can see, wide character message composition is similar to narrow logging. Note that you can use both narrow and wide character logging at the same time; all records will be processed by our file sink. The complete code of this example can be found [@boost:/libs/log/example/wide_char/main.cpp here].
+
+It must be noted that some sinks (mostly, Windows-specific ones) allow to specify the target character type. When national characters are expected in log records, one should always use `wchar_t` as the target character type in these cases because the sink will use wide character OS API to process log records. In this case all narrow character strings will be widened using the locale imbued into the sink when formatting is performed.
+
+[endsect]
+
+[endsect]

Added: trunk/libs/log/doc/utilities.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/log/doc/utilities.qbk 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,608 @@
+[/
+ Copyright Andrey Semashev 2007 - 2013.
+ 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)
+
+ This document is a part of Boost.Log library documentation.
+/]
+
+[section:utilities Utilities]
+
+[section:string_literal String literals]
+
+ #include <``[boost_log_utility_string_literal_hpp]``>
+
+String literals are used in several places throughout the library. However, this component can be successfully used outside of the library in users' code. It is header-only and does not require linking with the library binary. String literals can improve performance significantly if there is no need to modify stored strings. What is also important, since string literals do not dynamically allocate memory, it is easier to maintain exception safety when using string literals instead of regular strings.
+
+The functionality is implemented in the [class_log_basic_string_literal] class template, which is parametrized with the character and character traits, similar to `std::basic_string`. There are also two convenience typedefs provided: `string_literal` and `wstring_literal`, for narrow and wide character types, respectively. In order to ease string literal construction in generic code there is also a `str_literal` function template that accepts a string literal and returns a [class_log_basic_string_literal] instance for the appropriate character type.
+
+String literals support interface similar to STL strings, except for string modification functions. However, it is possible to assign to or clear string literals, as long as only string literals involved. Relational and stream output operators are also supported.
+
+[endsect]
+
+[section:type_info_wrapper Type information wrapper]
+
+ #include <``[boost_log_utility_type_info_wrapper_hpp]``>
+
+The language support for run time type information is essential for the library. But partially because of limitations that the C++ Standard imposes on this feature, partially because of differences of implementation of different compilers, there was a need for a lightweight wrapper around the `std::type_info` class to fill the gaps. The table below briefly shows the differences between the `std::type_info` and [class_log_type_info_wrapper] classes.
+
+[table Type information classes comparison
+ [[Feature] [`std::type_info`] [`type_info_wrapper`]]
+ [[Is default-constructable] [No] [Yes. The default-constructed wrapper is in an empty state.]]
+ [[Is copy-constructable] [No] [Yes]]
+ [[Is assignable] [No] [Yes]]
+ [[Is swappable] [No] [Yes]]
+ [[Life time duration] [Static, until the application terminates] [Dynamic]]
+ [[Has an empty state] [No] [Yes. In empty state the type info wrapper is never equal to other non-empty type info wrappers. It is equal to other empty type info wrappers and can be ordered with them.]]
+ [[Supports equality comparison] [Yes] [Yes]]
+ [[Supports ordering] [Yes, partial ordering with the `before` method.] [Yes, partial ordering with the complete set of comparison operators. The semantics of ordering is similar to the `std::type_info::before` method.]]
+ [[Supports printable representation of type] [Yes, with the `name` function.] [Yes, with `pretty_name` function. The function does its best to print the type name in a human-readable form. On some platforms it does better than `std::type_info::name`.]]
+]
+
+Given the distinctions above, using type information objects becomes much easier. For example, the ability to copy and order with regular operators allows using [class_log_type_info_wrapper] with containers. The ability to default-construct and assign allows using type information as a regular object and not to resort to pointers which may be unsafe.
+
+[endsect]
+
+[section:type_dispatch Type dispatchers]
+
+ #include <``[boost_log_utility_type_dispatch_type_dispatcher_hpp]``>
+
+Type dispatchers are used throughout the library in order to work with attribute values. Dispatchers allow acquiring the stored attribute value using the Visitor concept. The most notable places where the functionality is used are filters and formatters. However, this mechanism is orthogonal to attributes and can be used for other purposes as well. Most of the time users won't need to dig into the details of type dispatchers, but this information may be useful for those who intend to extend the library and wants to understand what's under the hood.
+
+Every type dispatcher supports the [class_log_type_dispatcher] interface. When an attribute value needs to be extracted, this interface is passed to the attribute value object, which then tries to acquire the callback for the actual type of the value. All callbacks are objects of the [class_type_dispatcher_callback] class template, instantiated on the actual type of the value. If the dispatcher is able to consume the value of the requested type, it must return a non-empty callback object. When (and if) the corresponding callback is acquired, the attribute value object only has to pass the contained value to its `operator ()`.
+
+Happily, there is no need to write type dispatchers from scratch. The library provides two kinds of type dispatchers that implement the [class_log_type_dispatcher] and [class_type_dispatcher_callback] interfaces and encapsulate the callback lookup.
+
+[heading Static type dispatcher]
+
+ #include <``[boost_log_utility_type_dispatch_static_type_dispatcher_hpp]``>
+
+Static type dispatchers are used when the set of types that needs to be supported for extraction is known at compile time. The [class_log_static_type_dispatcher] class template is parametrized with a MPL type sequence of types that need to be supported. The dispatcher inherits from the [class_log_type_dispatcher] interface which provides the `get_callback` method for aquiring the function object to invoke on the stored value. All you need to do is provide a visitor function object to the dispatcher at construction point and invoke the callback when dispatching the stored value:
+
+[example_util_static_type_dispatcher]
+
+[@boost:/libs/log/example/doc/util_static_type_disp.cpp See the complete code].
+
+[heading Dynamic type dispatcher]
+
+ #include <``[boost_log_utility_type_dispatch_dynamic_type_dispatcher_hpp]``>
+
+If the set of types that have to be supported is not available at compile time, the [class_log_dynamic_type_dispatcher] class is there to help. One can use its `register_type` method to add support for a particular type. The user has to pass a function object along with the type, this functor will be called when a visitor for the specified type is invoked. Considering the `my_value` from the code sample for static type dispatcher is intact, the code can be rewritten as follows:
+
+[example_util_dynamic_type_dispatcher]
+
+[@boost:/libs/log/example/doc/util_dynamic_type_disp.cpp See the complete code].
+
+Of course, complex function objects, like those provided by __boost_bind__, are also supported.
+
+[endsect]
+
+[section:predef_types Predefined type sequences]
+
+ #include <``[boost_log_utility_type_dispatch_standard_types_hpp]``>
+ #include <``[boost_log_utility_type_dispatch_date_time_types_hpp]``>
+
+One may notice that when using type dispatchers and defining filters and formatters it may be convenient to have some predefined type sequences to designate frequently used sets of types. The library provides several such sets.
+
+[table Standard types (standard_types.hpp)
+ [[Type sequence] [Meaning]]
+ [[`integral_types`] [All integral types, including `bool`, character and 64 bit integral types, if available]]
+ [[`floating_point_types`] [Floating point types]]
+ [[`numeric_types`] [Includes `integral_types` and `floating_point_types`]]
+ [[`string_types`] [Narrow and wide string types. Currently only includes STL string types and [link log.detailed.utilities.string_literal string literals].]]
+]
+
+There are also a number of time-related type sequences available:
+
+[table Time-related types (date_time_types.hpp)
+ [[Type sequence] [Meaning]]
+ [[`native_date_time_types`] [All types defined in C/C++ standard that have both date and time portions]]
+ [[`boost_date_time_types`] [All types defined in __boost_date_time__ that have both date and time portions]]
+ [[`date_time_types`] [Includes `native_date_time_types` and `boost_date_time_types`]]
+ [[`native_date_types`] [All types defined in C/C++ standard that have date portion. Currently equivalent to `native_date_time_types`.]]
+ [[`boost_date_types`] [All types defined in __boost_date_time__ that have date portion]]
+ [[`date_types`] [Includes `native_date_types` and `boost_date_types`]]
+ [[`native_time_types`] [All types defined in C/C++ standard that have time portion. Currently equivalent to `native_date_time_types`.]]
+ [[`boost_time_types`] [All types defined in __boost_date_time__ that have time portion. Currently equivalent to `boost_date_time_types`.]]
+ [[`time_types`] [Includes `native_time_types` and `boost_time_types`]]
+ [[`native_time_duration_types`] [All types defined in C/C++ standard that are used to represent time duration. Currently only includes `double`, as the result type of the `difftime` standard function.]]
+ [[`boost_time_duration_types`] [All time duration types defined in __boost_date_time__]]
+ [[`time_duration_types`] [Includes `native_time_duration_types` and `boost_time_duration_types`]]
+ [[`boost_time_period_types`] [All time period types defined in __boost_date_time__]]
+ [[`time_period_types`] [Currently equivalent to `boost_time_period_types`]]
+]
+
+[endsect]
+
+[section:value_ref Value reference wrapper]
+
+ #include <``[boost_log_utility_value_ref_hpp]``>
+
+The [class_log_value_ref] class template is an optional reference wrapper which is used by the library to refer to the stored attribute values. To a certain degree it shares features of __boost_optional__ and __boost_variant__ components.
+
+The template has two type parameters. The first is the referred type. It can also be specified as a __boost_mpl__ type sequence, in which case the [class_log_value_ref] wrapper may refer to either type in the sequence. In this case, the `which` method will return the index of the referred type within the sequence. The second template parameter is an optional tag type which can be used to customize formatting behavior. This tag is forwarded to the [link log.detailed.utilities.manipulators.to_log `to_log`] manipulator when the wrapper is put to a [class_log_basic_formatting_ostream] stream, which is used by the library for record formatting. For an example see how attribute value extraction is implemented:
+
+[example_attr_value_extraction_multiple_types]
+
+[@boost:/libs/log/example/doc/attr_value_extraction.cpp See the complete code].
+
+The [class_log_value_ref] wrapper also supports applying a visitor function object to the referred object. This can be done by calling one of the following methods:
+
+* `apply_visitor`. This method should only be used on a valid (non-empty) reference. The method returns the visitor result.
+* `apply_visitor_optional`. The method checks if the reference is valid and applies the visitor to the referred value if it is. The method returns the visitor result wrapped into `boost::optional` which will be filled only if the reference is valid.
+* `apply_visitor_or_default`. If the reference is valid, the method applies the visitor on the referred value and returns its result. Otherwise the method returns a default value passed as the second argument.
+
+[note Regardless of the method used, the visitor function object [_must] define the `result_type` typedef. Polymorphic visitors are not supported as this would complicate the [class_log_value_ref] interface too much. This requirement also precludes free functions and C++11 lambda functions from being used as visitors. Please, use __boost_bind__ or similar wrappers in such cases.]
+
+Here is an example of applying a visitor:
+
+[example_attr_value_extraction_visitor]
+
+[endsect]
+
+[section:record_ordering Log record ordering]
+
+ #include <``[boost_log_utility_record_ordering_hpp]``>
+
+There are cases when log records need to be ordered. One possible use case is storing records in a container or a priority queue. The library provides two types of record ordering predicates out of the box:
+
+[heading Abstract record ordering]
+
+The [class_log_abstract_ordering] class allows application of a quick opaque ordering. The result of this ordering is not stable between different runs of the application and in generag cannot be predicted before the predicate is applied, however it provides the best performance. The [class_log_abstract_ordering] class is a template that is specialized with an optional predicate function that will be able to compare `const void*` pointers. By default an `std::less` equivalent is used.
+
+ // A set of unique records
+ std::set< logging::record_view, logging::abstract_ordering< > > m_Records;
+
+This kind of ordering can be useful if the particular order of log records is not important but nevertheless some order is required.
+
+[heading Attribute value based ordering]
+
+This kind of ordering is implemented with the [class_log_attribute_value_ordering] class and is based on the attribute values attached to the record. The predicate will seek for an attribute value with the specified name in both records being ordered and attempt to compare the attribute values.
+
+ // Ordering type definition
+ typedef logging::attribute_value_ordering<
+ int // attribute value type
+ > ordering;
+
+ // Records organized into a queue based on the "Severity" attribute value
+ std::priority_queue<
+ logging::record_view,
+ std::vector< logging::record_view >,
+ ordering
+ > m_Records(ordering("Severity"));
+
+Like the [class_log_abstract_ordering], [class_log_attribute_value_ordering] also accepts the second optional template parameter, which should be the predicate to compare attribute values (`int`s in the example above). By default, an `std::less` equivalent is used.
+
+You can also use the [funcref boost::log::make_attr_ordering `make_attr_ordering`] generator function to automatically generate the [class_log_attribute_value_ordering] instance based on the attribute value name and the ordering function. This might be useful if the ordering function has a non-trivial type, like the ones __boost_bind__ provides.
+
+[endsect]
+
+[section:exception_handlers Exception handlers]
+
+ #include <``[boost_log_utility_exception_handler_hpp]``>
+
+The library provides exception handling hooks in different places. Tools, defined in this header, provide an easy way of implementing function objects suitable for such hooks.
+
+An exception handler is a function object that accepts no arguments. The result of the exception handler is ignored and thus should generally be `void`. Exception handlers are called from within `catch` sections by the library, therefore in order to reacquire the exception object it has to rethrow it. The header defines an [class_log_exception_handler] template functor that does just that and then forwards the exception object to an unary user-defined functional object. The [funcref boost::log::make_exception_handler `make_exception_handler`] function can be used to simplify the handler construction. All expected exception types should be specified explicitly in the call, in the order they would appear in the `catch` sections (i.e. from most specific ones to the most general ones).
+
+[example_utility_exception_handler]
+
+As you can see, you can either suppress the exception by returning normally from `operator()` in the user-defined handler functor, or rethrow the exception, in which case it will propagate further. If it appears that the exception handler is invoked for an exception type that cannot be caught by any of the specified types, the exception will be propagated without any processing. In order to catch such situations, there exists the [class_log_nothrow_exception_handler] class. It invokes the user-defined functor with no arguments if it cannot determine the exception type.
+
+[example_utility_exception_handler_nothrow]
+
+It is sometimes convenient to completely suppress all exceptions at a certain library level. The [funcref boost::log::make_exception_suppressor `make_exception_suppressor`] function creates an exception handler that simply does nothing upon exception being caught. For example, this way we can disable all exceptions from the logging library:
+
+ void init_logging()
+ {
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ // Disable all exceptions
+ core->set_exception_handler(logging::make_exception_suppressor());
+ }
+
+[endsect]
+
+[section:manipulators Output manipulators]
+
+The library provides a number of stream manipulators that may be useful in some contexts.
+
+[section:to_log Customized logging manipulator]
+
+ #include <``[boost_log_utility_manipulators_to_log_hpp]``>
+
+The [funcref boost::log::to_log `to_log`] function creates a stream manipulator that simply outputs the adopted value to the stream. By default its behavior is equivalent to simply putting the value to the stream. However, the user is able to overload the `operator<<` for the adopted value to override formatting behavior when values are formatted for logging purposes. This is typically desired when the regular `operator<<` is employed for other tasks (such as serialization) and its behavior is neither suitable for logging nor can be easily changed. For example:
+
+[example_utility_manipulators_to_log]
+
+The second streaming statement in the `test_manip` function will invoke our custom stream insertion operator which defines special formatting rules.
+
+It is also possible to define different formatting rules for different value contexts as well. The library uses this feature to allow different formatting ruled for different attribute values, even if the stored value type is the same. To do so one has to specify an explicit template argument for [funcref boost::log::to_log `to_log`], a tag type, which will be embedded into the manipulator type and thus will allow to define different insertion operators:
+
+[example_utility_manipulators_to_log_with_tag]
+
+[@boost:/libs/log/example/doc/util_manip_to_log.cpp See the complete code].
+
+[note The library uses [class_log_basic_formatting_ostream] stream type for record formatting, so when customizing attribute value formatting rules the `operator<<` must use [class_log_basic_formatting_ostream] instead of `std::ostream`.]
+
+[endsect]
+
+[section:add_value Attribute value attaching manipulator]
+
+ #include <``[boost_log_utility_manipulators_add_value_hpp]``>
+
+The [funcref boost::log::add_value `add_value`] function creates a manipulator that attaches an attribute value to a log record. This manipulator can only be used in streaming expressions with the [class_log_basic_record_ostream] stream type (which is the case when log record message is formatted). Since the message text is only formatted after filtering, attribute values attached with this manipulator do not affect filtering and can only be used in formatters and sinks themselves.
+
+In addition to the value itself, the manipulator also requires the attribute name to be provided. For example:
+
+ // Creates a log record with attribute value "MyAttr" of type int attached
+ BOOST_LOG(lg) << logging::add_value("MyAttr", 10) << "Hello world!";
+
+[endsect]
+
+[endsect]
+
+[section:setup Simplified library initialization tools]
+
+This part of the library is provided in order to simplify logging initialization and provide basic tools to develop user-specific initialization mechanisms. It is known that setup capabilities and preferences may vary widely from application to application, therefore the library does not attempt to provide a universal solution for this task. The provided tools are mostly intended to serve as a quick drop-in support for logging setup and a set of instruments to implement something more elaborate and more fitting users' needs.
+
+Some of the features described in this section will require the separate library binary, with name based on "boost_log_setup" substring. This binary depends on the main library.
+
+[section:convenience Convenience functions]
+
+ #include <``[boost_log_utility_setup_console_hpp]``>
+ #include <``[boost_log_utility_setup_file_hpp]``>
+ #include <``[boost_log_utility_setup_common_attributes_hpp]``>
+
+The library provides a number of functions that simplify some common initialization procedures, like sink and commonly used attributes registration. This is not much functionality. However, it saves a couple of minutes of learning the library for a newcomer.
+
+Logging to the application console is the simplest way to see the logging library in action. To achieve this, one can initialize the library with a single function call, like this:
+
+ int main(int, char*[])
+ {
+ // Initialize logging to std::clog
+ logging::add_console_log();
+
+ // Here we go, we can write logs right away
+ src::logger lg;
+ BOOST_LOG(lg) << "Hello world!";
+
+ return 0;
+ }
+
+Pretty easy, isn't it? There is also the `wadd_console_log` function for wide-character console. If you want to put logs to some other standard stream, you can pass the stream to the [funcref boost::log::add_console_log `add_console_log`] function as an argument. E.g. enabling logging to `std::cout` instead of `std::clog` would look like this:
+
+ logging::add_console_log(std::cout);
+
+What's important, is that you can further manage the console sink if you save the `shared_ptr` to the sink that this function returns. This allows you to set up things like filter, formatter and auto-flush flag.
+
+ int main(int, char*[])
+ {
+ // Initialize logging to std::clog
+ boost::shared_ptr<
+ sinks::synchronous_sink< sinks::text_ostream_backend >
+ > sink = logging::add_console_log();
+
+ sink->set_filter(expr::attr< int >("Severity") >= 3);
+ sink->locked_backend()->auto_flush(true);
+
+ // Here we go, we can write logs right away
+ src::logger lg;
+ BOOST_LOG(lg) << "Hello world!";
+
+ return 0;
+ }
+
+Similarly to console, one can use a single function call to enable logging to a file. All you have to do is to provide the file name:
+
+ int main(int, char*[])
+ {
+ // Initialize logging to the "test.log" file
+ logging::add_file_log("test.log");
+
+ // Here we go, we can write logs right away
+ src::logger lg;
+ BOOST_LOG(lg) << "Hello world!";
+
+ return 0;
+ }
+
+The [funcref boost::log::add_console_log `add_console_log`] and [funcref boost::log::add_file_log `add_file_log`] functions do not conflict and may be combined freely, so it is possible to set up logging to the console and a couple of files, including filtering and formatting, in about 10 lines of code.
+
+Lastly, there is an [funcref boost::log::add_common_attributes `add_common_attributes`] function that registers two frequently used attributes: "LineID" and "TimeStamp". The former counts log record being made and has attribute value `unsigned int`. The latter, as its name implies, provides the current time for each log record, in the form of `boost::posix_time::ptime` (see __boost_date_time__). These two attributes are registered globally, so they will remain available in all threads and loggers. This makes the final version of our code sample look something like this:
+
+ int main(int, char*[])
+ {
+ // Initialize sinks
+ logging::add_console_log()->set_filter(expr::attr< int >("Severity") >= 4);
+
+ logging::formatter formatter =
+ expr::stream
+ << expr::attr< unsigned int >("LineID") << ": "
+ << expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S") << " *"
+ << expr::attr< int >("Severity") << "* "
+ << expr::message;
+
+ logging::add_file_log("complete.log")->set_formatter(formatter);
+
+ boost::shared_ptr<
+ sinks::synchronous_sink< sinks::text_ostream_backend >
+ > sink = logging::add_file_log("essential.log");
+ sink->set_formatter(formatter);
+ sink->set_filter(expr::attr< int >("Severity") >= 1);
+
+ // Register common attributes
+ logging::add_common_attributes();
+
+ // Here we go, we can write logs
+ src::logger lg;
+ BOOST_LOG(lg) << "Hello world!";
+
+ return 0;
+ }
+
+[endsect]
+
+[section:filter_formatter Filter and formatter parsers]
+
+ #include <``[boost_log_utility_setup_filter_parser_hpp]``>
+ #include <``[boost_log_utility_setup_formatter_parser_hpp]``>
+
+Filter and formatter parsers allow constructing filters and formatters from a descriptive string. The function `parse_filter` is responsible for recognizing filters and `parse_formatter` - for recognizing formatters.
+
+In the case of filters the string is formed of a sequence of condition expressions, interconnected with boolean operations. There are two operations supported: conjunction (designated as "&" or "and") and disjunction ("|" or "or"). Each condition itself may be either a single condition or a sub-filter, taken in round brackets. Each condition can be negated with the "!" sign or "not" keyword. The condition, if it's not a sub-filter, usually consists of an attribute name enclosed in percent characters ("%"), a relation keyword and an operand. The relation and operand may be omitted, in which case the condition is assumed to be the requirement of the attribute presence (with any type).
+
+[teletype]
+
+ filter:
+ condition { op condition }
+
+ op:
+ &
+ and
+ |
+ or
+
+ condition:
+ !condition
+ not condition
+ (filter)
+ %attribute_name%
+ %attribute_name% relation operand
+
+ relation:
+ >
+ <
+ =
+ !=
+ >=
+ <=
+ begins_with
+ ends_with
+ contains
+ matches
+
+[c++]
+
+Below are some examples of filters:
+
+[table Examples of filters
+[[Filter string] [Description]]
+[[`%Severity%`] [The filter returns `true` if an attribute value with name "Severity" is found in a log record.]]
+[[`%Severity% > 3`] [The filter returns `true` if an attribute value with name "Severity" is found and it is greater than 3. The attribute value must be of one of the [link log.detailed.utilities.predef_types integral types].]]
+[[!(`%Ratio% > 0.0 & %Ratio% <= 0.5)`] [The filter returns `true` if an attribute value with name "Ratio" of one of the [link log.detailed.utilities.predef_types floating point types] is not found or it is not between 0 and 0.5.]]
+[[`%Tag% contains "net" or %Tag% contains "io" and not %StatFlow%`] [The filter returns `true` if an attribute value with name "Tag" is found and contains words "net" or "io" and if an attribute value "StatFlow" is not found. The "Tag" attribute value must be of one of the [link log.detailed.utilities.predef_types string types], the "StatFlow" attribute value type is not considered.]]
+]
+
+The formatter string syntax is even simpler and pretty much resembles __boost_format__ format string syntax. The string must contain attribute names enclosed in percent signs ("%"), the corresponding attribute value will replace these placeholders. The placeholder "%Message%" will be replaced with the log record text. For instance, `[%TimeStamp%] *%Severity%* %Message%` formatter string will make log records look like this: `[2008-07-05 13:44:23] *0* Hello world`.
+
+[note Previous releases of the library also supported the "%\_%" placeholder for the message text. This placeholder is deprecated now, although it still works for backward compatibility. Its support will be removed in future releases.]
+
+It must be noted, though, that by default the library only supports those attribute value types [link log.detailed.utilities.predef_types which are known] at the library build time. User-defined types will not work properly in parsed filters and formatters until registered in the library. More on this is available in the [link log.extension.settings Extending the library] section.
+
+[note The parsed formatters and filters are generally less optimal than the equivalent ones written in code. This is because of two reasons: (\*) the programmer usually knows more about types of the attribute values that may be involved in formatting or filtering and (\*) the compiler has a better chance to optimize the formatter or filter if it is known in compile time. Therefore, if the performance matters, it is advised to avoid parsed filters and formatters.]
+
+[endsect]
+
+[section:settings Library initialization from a settings container]
+
+ #include <``[boost_log_utility_setup_settings_hpp]``>
+ #include <``[boost_log_utility_setup_from_settings_hpp]``>
+
+The headers define components for library initialization from a settings container. The settings container is basically a set of named parameters divided into sections. The container is implemented with the [class_log_basic_settings] class template. There are several constraints on how parameters are stored in the container:
+
+* Every parameter must reside in a section. There can be no parameters that do not belong to a section.
+* Parameters must have names unique within the section they belong to. Parameters from different sections may have the same name.
+* Sections can nest. When read from a file or accessed from the code, section names can express arbitrary hierarchy by separating the parent and child section names with '.' (e.g. "\[Parent.Child.ChildChild\]").
+* Sections must have names unique within the enclosing section (or global scope, if the section is top level).
+
+So basically, settings container is a layered associative container, with string keys and values. In some respect it is similar to __boost_property_tree__, and in fact it supports construction from `boost::ptree`. The supported parameters are described below.
+
+[tip In the tables below, the `CharT` type denotes the character type that is used with the settings container.]
+
+[table Section "Core". Logging core settings.
+[[Parameter] [Format] [Description]]
+[[Filter] [Filter string as described [link log.detailed.utilities.setup.filter_formatter here]]
+ [Global filter to be installed to the core. If not specified, the global filter is not set.]
+]
+[[DisableLogging] ["true" or "false"]
+ [If `true`, results in calling `set_logging_enabled(false)` on the core. By default, value `false` is assumed.]
+]
+]
+
+Sink settings are divided into separate subsections within the common top-level section "Sinks" - one subsection for each sink. The subsection names should denote a user-defined sink name. For example, "MyFile".
+
+[note Previous versions of the library also supported top-level sections starting with the "Sink:" prefix to describe sink parameters. This syntax is deprecated now, although it still works when parsing a settings file for backward compatibility. The parser will automatically put these sections under the "Sinks" top-level section in the resulting settings contsiner. Support for this syntax will be removed in future releases.]
+
+[table Sections under the "Sinks" section. Common sink settings.
+[[Parameter] [Format] [Description]]
+[[Destination] [Sink target, see description]
+ [Sink backend type. Mandatory parameter. May have one of these values: [link log.detailed.sink_backends.text_ostream Console], [link log.detailed.sink_backends.text_file TextFile], [link log.detailed.sink_backends.syslog Syslog]. On Windows the following values are additionally supported: [link log.detailed.sink_backends.event_log SimpleEventLog], [link log.detailed.sink_backends.debugger Debugger]. Also, user-defined sink names may also be supported if registered by calling `register_sink_factory`.]
+]
+[[Filter] [Filter string as described [link log.detailed.utilities.setup.filter_formatter here]]
+ [Sink-specific filter. If not specified, the filter is not set.]
+]
+[[Asynchronous] ["true" or "false"]
+ [If `true`, the [link log.detailed.sink_frontends.async asynchronous sink frontend] will be used. Otherwise the [link log.detailed.sink_frontends.sync synchronous sink frontend] will be used. By default, value `false` is assumed. In single-threaded builds this parameter is not used, as [link log.detailed.sink_frontends.unlocked unlocked sink frontend] is always used.]
+]
+]
+
+Besides the common settings that all sinks support, some sink backends also accept a number of specific parameters. These parameters should be specified in the same section.
+
+[table "Console" sink settings
+[[Parameter] [Format] [Description]]
+[[Format] [Format string as described [link log.detailed.utilities.setup.filter_formatter here]]
+ [Log record formatter to be used by the sink. If not specified, the default formatter is used.]
+]
+[[AutoFlush] ["true" or "false"]
+ [Enables or disables the auto-flush feature of the backend. If not specified, the default value `false` is assumed.]
+]
+]
+
+[table "TextFile" sink settings
+[[Parameter] [Format] [Description]]
+[[FileName] [File name pattern]
+ [The file name pattern for the sink backend. This parameter is mandatory.]
+]
+[[Format] [Format string as described [link log.detailed.utilities.setup.filter_formatter here]]
+ [Log record formatter to be used by the sink. If not specified, the default formatter is used.]
+]
+[[AutoFlush] ["true" or "false"]
+ [Enables or disables the auto-flush feature of the backend. If not specified, the default value `false` is assumed.]
+]
+[[RotationSize] [Unsigned integer]
+ [File size, in bytes, upon which file rotation will be performed. If not specified, no size-based rotation will be made.]
+]
+[[RotationInterval] [Unsigned integer]
+ [Time interval, in seconds, upon which file rotation will be performed. See also the RotationTimePoint parameter and the note below.]
+]
+[[RotationTimePoint] [Time point format string, see below]
+ [Time point or a predicate that detects at what moment of time to perform log file rotation. See also the RotationInterval parameter and the note below.]
+]
+[[Target] [File system path to a directory]
+ [Target directory name, in which the rotated files will be stored. If this parameter is specified, rotated file collection is enabled. Otherwise the feature is not enabled, and all corresponding parameters are ignored.]
+]
+[[MaxSize] [Unsigned integer]
+ [Total size of files in the target directory, in bytes, upon which the oldest file will be deleted. If not specified, no size-based file cleanup will be performed.]
+]
+[[MinFreeSpace] [Unsigned integer]
+ [Minimum free space in the target directory, in bytes, upon which the oldest file will be deleted. If not specified, no space-based file cleanup will be performed.]
+]
+[[ScanForFiles] ["All" or "Matching"]
+ [Mode of scanning for old files in the target directory, see [enumref boost::log::sinks::file::scan_method `scan_method`]. If not specified, no scanning will be performed.]
+]
+]
+
+The time-based rotation can be set up with one of the two parameters: RotationInterval or RotationTimePoint. Not more than one of these parameters should be specified for a given sink. If none is specified, no time-based rotation will be performed.
+
+The RotationTimePoint parameter should have one of the following formats, according to the __boost_date_time_format__ format notation:
+
+* "%H:%M:%S". In this case, file rotation will be performed on a daily basis, at the specified time. For example, "12:00:00".
+* "%a %H:%M:%S" or "%A %H:%M:%S". File rotation takes place every week, on the weekday specified in the long or short form, at the specified time. For example, "Saturday 09:00:00".
+* "%d %H:%M:%S". File rotation takes place every month, on the specified day of month, at the specified time. For example, "01 23:30:00".
+
+[table "Syslog" sink settings
+[[Parameter] [Format] [Description]]
+[[LocalAddress] [An IP address]
+ [Local address to initiate connection to the syslog server. If not specified, the default local address will be used.]
+]
+[[TargetAddress] [An IP address]
+ [Remote address of the syslog server. If not specified, the local address will be used.]
+]
+]
+
+[table "SimpleEventLog" sink settings
+[[Parameter] [Format] [Description]]
+[[LogName] [A string]
+ [Log name to write events into. If not specified, the default log name will be used.]
+]
+[[LogSource] [A string]
+ [Log source to write events from. If not specified, the default source will be used.]
+]
+[[Registration] ["Never", "OnDemand" or "Forced"]
+ [Mode of log source registration in Windows registry, see [enumref boost::log::sinks::event_log::registration_mode `registration_mode`]. If not specified, on-demand registration will be performed.]
+]
+]
+
+The user is free to fill the settings container from whatever settings source he needs. The usage example is below:
+
+ void init_logging()
+ {
+ logging::settings setts;
+
+ setts["Core"]["Filter"] = "%Severity% >= warning";
+ setts["Core"]["DisableLogging"] = false;
+
+ // Subsections can be referred to with a single path
+ setts["Sinks.Console"]["Destination"] = "Console";
+ setts["Sinks.Console"]["Filter"] = "%Severity% >= fatal";
+ setts["Sinks.Console"]["AutoFlush"] = true;
+
+ // ...as well as the individual parameters
+ setts["Sinks.File.Destination"] = "TextFile";
+ setts["Sinks.File.FileName"] = "MyApp_%3N.log";
+ setts["Sinks.File.AutoFlush"] = true;
+ setts["Sinks.File.RotationSize"] = 10 * 1024 * 1024; // 10 MiB
+
+ logging::init_from_settings(setts);
+ }
+
+The settings reader also allows to be extended to support custom sink types. See the [link log.extension.settings Extending the library] section for more information.
+
+[endsect]
+
+[section:settings_file Library initialization from a settings file]
+
+ #include <``[boost_log_utility_setup_from_stream_hpp]``>
+
+Support for configuration files is a frequently requested feature of the library. And despite the fact there is no ultimately convenient and flexible format of the library settings, the library provides preliminary support for this feature. The functionality is implemented with a simple function [funcref boost::log::init_from_stream `init_from_stream`], which accepts an STL input stream and reads the library settings from it. The function then passes on the read settings to the [funcref boost::log::init_from_settings `init_from_settings`] function, described [link log.detailed.utilities.setup.settings above]. Therefore the parameter names and their meaning is the same as for the [funcref boost::log::init_from_settings `init_from_settings`] function.
+
+The settings format is quite simple and widely used. Below is the description of syntax and parameters.
+
+[teletype]
+
+ # Comments are allowed. Comment line begins with the '#' character
+ # and spans until the end of the line.
+
+ # Logging core settings section. May be omitted if no parameters specified within it.
+ [Core]
+ DisableLogging=false
+ Filter="%Severity% > 3"
+
+ # Sink settings sections
+ [Sinks.MySink1]
+
+ # Sink destination type
+ Destination=Console
+
+ # Sink-specific filter. Optional, by default no filter is applied.
+ Filter="%Target% contains \"MySink1\""
+
+ # Formatter string. Optional, by default only log record message text is written.
+ Format="<%TimeStamp%> - %Message%"
+
+ # The flag shows whether the sink should be asynchronous
+ Asynchronous=false
+
+ # Enables automatic stream flush after each log record.
+ AutoFlush=true
+
+[c++]
+
+Here's the usage example:
+
+ int main(int, char*[])
+ {
+ // Read logging settings from a file
+ std::ifstream file("settings.ini");
+ logging::init_from_stream(file);
+
+ return 0;
+ }
+
+[endsect]
+
+[endsect]
+
+[endsect]

Added: trunk/libs/log/example/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/Jamfile.v2 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,23 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+
+build-project ./advanced_usage ;
+build-project ./async_log ;
+build-project ./bounded_async_log ;
+build-project ./basic_usage ;
+build-project ./event_log ;
+build-project ./multiple_files ;
+build-project ./multiple_threads ;
+build-project ./rotating_file ;
+build-project ./settings_file ;
+build-project ./settings_file_formatter_factory ;
+build-project ./syslog ;
+build-project ./native_syslog ;
+build-project ./wide_char ;
+build-project ./keywords ;
+build-project ./trivial ;
+build-project ./doc ;

Added: trunk/libs/log/example/advanced_usage/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/advanced_usage/Jamfile.v2 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,32 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+
+project
+ : requirements
+ <link>shared:<define>BOOST_ALL_DYN_LINK
+ <logapi>unix:<define>BOOST_LOG_USE_NATIVE_SYSLOG=1
+ <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>gcc:<cxxflags>-fno-strict-aliasing # avoids strict aliasing violations in other Boost components
+ <toolset>gcc:<cxxflags>-ftemplate-depth-1024
+ <library>/boost/log//boost_log
+ <library>/boost/date_time//boost_date_time
+ <library>/boost/filesystem//boost_filesystem
+ <library>/boost/system//boost_system
+ <library>/boost/thread//boost_thread
+ <threading>multi
+ ;
+
+exe advanced_usage
+ : main.cpp
+ ;

Added: trunk/libs/log/example/advanced_usage/main.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/advanced_usage/main.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,300 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 main.cpp
+ * \author Andrey Semashev
+ * \date 11.11.2007
+ *
+ * \brief An example of in-depth library usage. See the library tutorial for expanded
+ * comments on this code. It may also be worthwhile reading the Wiki requirements page:
+ * http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Boost.Logging
+ */
+
+// #define BOOST_LOG_USE_CHAR
+// #define BOOST_ALL_DYN_LINK 1
+// #define BOOST_LOG_DYN_LINK 1
+
+#include <cassert>
+#include <iostream>
+#include <fstream>
+#include <boost/shared_ptr.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/log/common.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/attributes.hpp>
+#include <boost/log/sinks.hpp>
+#include <boost/log/sources/logger.hpp>
+#include <boost/log/utility/empty_deleter.hpp>
+#include <boost/log/utility/manipulators/add_value.hpp>
+#include <boost/log/attributes/scoped_attribute.hpp>
+#include <boost/log/support/date_time.hpp>
+
+namespace logging = boost::log;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace attrs = boost::log::attributes;
+namespace src = boost::log::sources;
+namespace keywords = boost::log::keywords;
+
+using boost::shared_ptr;
+
+// Here we define our application severity levels.
+enum severity_level
+{
+ normal,
+ notification,
+ warning,
+ error,
+ critical
+};
+
+// The formatting logic for the severity level
+template< typename CharT, typename TraitsT >
+inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, severity_level lvl)
+{
+ static const char* const str[] =
+ {
+ "normal",
+ "notification",
+ "warning",
+ "error",
+ "critical"
+ };
+ if (static_cast< std::size_t >(lvl) < (sizeof(str) / sizeof(*str)))
+ strm << str[lvl];
+ else
+ strm << static_cast< int >(lvl);
+ return strm;
+}
+
+int foo(src::logger& lg)
+{
+ BOOST_LOG_FUNCTION();
+ BOOST_LOG(lg) << "foo is being called";
+ return 10;
+}
+
+int main(int argc, char* argv[])
+{
+ // This is a in-depth tutorial/example of Boost.Log usage
+
+ // The first thing we have to do to get using the library is
+ // to set up the logging sinks - i.e. where the logs will be written to.
+ // Each sink is composed from frontend and backend. Frontend deals with
+ // general sink behavior, like filtering (see below) and threading model.
+ // Backend implements formatting and, actually, storing log records.
+ // Not every frontend/backend combinations are compatible (mostly because of
+ // threading models incompatibilities), but if they are not, the code will
+ // simply not compile.
+
+ // For now we only create a text output sink:
+ typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;
+ shared_ptr< text_sink > pSink(new text_sink);
+
+ // Here synchronous_sink is a sink frontend that performs thread synchronization
+ // before passing log records to the backend (the text_ostream_backend class).
+ // The backend formats each record and outputs it to one or several streams.
+ // This approach makes implementing backends a lot simplier, because you don't
+ // need to worry about multithreading.
+
+ {
+ // The good thing about sink frontends is that they are provided out-of-box and
+ // take away thread-safety burden from the sink backend implementors. Even if you
+ // have to call a custom backend method, the frontend gives you a convenient way
+ // to do it in a thread safe manner. All you need is to acquire a locking pointer
+ // to the backend.
+ text_sink::locked_backend_ptr pBackend = pSink->locked_backend();
+
+ // Now, as long as pBackend lives, you may work with the backend without
+ // interference of other threads that might be trying to log.
+
+ // Next we add streams to which logging records should be output
+ shared_ptr< std::ostream > pStream(&std::clog, logging::empty_deleter());
+ pBackend->add_stream(pStream);
+
+ // We can add more than one stream to the sink backend
+ shared_ptr< std::ofstream > pStream2(new std::ofstream("sample.log"));
+ assert(pStream2->is_open());
+ pBackend->add_stream(pStream2);
+ }
+
+ // Ok, we're ready to add the sink to the logging library
+ logging::core::get()->add_sink(pSink);
+
+ // Now our logs will be written both to the console and to the file.
+ // Let's do a quick test and output something. We have to create a logger for this.
+ src::logger lg;
+
+ // And output...
+ BOOST_LOG(lg) << "Hello, World!";
+
+ // Nice, huh? That's pretty much equivalent to writing the string to both the file
+ // and the console. Now let's define the different way of formatting log records.
+ // Each logging record may have a number of attributes in addition to the
+ // message body itself. By setting up formatter we define which of them
+ // will be written to log and in what way they will look there.
+ pSink->set_formatter(expr::stream
+ << expr::attr< unsigned int >("RecordID") // First an attribute "RecordID" is written to the log
+ << " [" << expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%d.%m.%Y %H:%M:%S.%f")
+ << "] [" << expr::attr< severity_level >("Severity")
+ << "] [" << expr::attr< boost::posix_time::time_duration >("Uptime")
+ << "] [" // then this delimiter separates it from the rest of the line
+ << expr::if_(expr::has_attr("Tag"))
+ [
+ expr::stream << expr::attr< std::string >("Tag") // then goes another attribute named "Tag"
+ // Note here we explicitly stated that its type
+ // should be std::string. We could omit it just
+ // like we did it with the "RecordID", but in this case
+ // library would have to detect the actual attribute value
+ // type in run time which has the following consequences:
+ // - On the one hand, the attribute would have been output
+ // even if it has another type (not std::string).
+ // - On the other, this detection does not come for free
+ // and will result in performance decrease.
+ //
+ // In general it's better you to specify explicitly which
+ // type should an attribute have wherever it is possible.
+ // You may specify an MPL sequence of types if the attribute
+ // may have more than one type. And you will have to specify
+ // it anyway if the library is not familiar with it (see
+ // boost/log/utility/type_dispatch/standard_types.hpp for the list
+ // of the supported out-of-the-box types).
+ << "] [" // yet another delimiter
+ ]
+ << expr::format_named_scope("Scope", keywords::format = "%n", keywords::iteration = expr::reverse) << "] "
+ << expr::smessage); // here goes the log record text
+
+/*
+ // There is an alternative way of specifying formatters
+ pSink->set_formatter(
+ expr::format("%1% @ %2% [%3%] >%4%< Scope: %5%: %6%")
+ % expr::attr< unsigned int >("RecordID")
+ % expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%d.%m.%Y %H:%M:%S.%f")
+ % expr::attr< boost::posix_time::time_duration >("Uptime")
+ % expr::attr< std::string >("Tag")
+ % expr::format_named_scope("Scope", keywords::format = "%n", keywords::iteration = expr::reverse, keywords::depth = 2)
+ % expr::smessage);
+*/
+
+ // Now the sink will output in the following format:
+ // 1 [Current time] [Tag value] Hello World!
+ // The output will be the same for all streams we add to the sink. If you want something different,
+ // you may create another sink for that purpose.
+
+ // Now we're going to set up the attributes.
+ // Remember that "RecordID" attribute in the formatter? There is a counter
+ // attribute in the library that increments or decrements the value each time
+ // it is output. Let's create it with a starting value 1.
+ attrs::counter< unsigned int > RecordID(1);
+
+ // Since we intend to count all logging records ever made by the application,
+ // this attribute should clearly be global.
+ logging::core::get()->add_global_attribute("RecordID", RecordID);
+
+ // And similarly add a time stamp
+ attrs::local_clock TimeStamp;
+ logging::core::get()->add_global_attribute("TimeStamp", TimeStamp);
+
+ // And an up time stopwatch
+ BOOST_LOG_SCOPED_THREAD_ATTR("Uptime", attrs::timer());
+
+ // Attributes may have two other scopes: thread scope and source scope. Attributes of thread
+ // scope are output with each record made by the thread (regardless of the logger object), and
+ // attributes of the source scope are output with each record made by the logger. On output
+ // all attributes of global, thread and source scopes are merged into a one record and passed to
+ // the sinks as one view. There is no difference between attributes of different scopes from the
+ // sinks' perspective.
+
+ // Let's also track the execution scope from which the records are made
+ attrs::named_scope Scope;
+ logging::core::get()->add_thread_attribute("Scope", Scope);
+
+ // We can mark the current execution scope now - it's the 'main' function
+ BOOST_LOG_FUNCTION();
+
+ // Let's try out the counter attribute and formatting
+ BOOST_LOG(lg) << "Some log line with a counter";
+ BOOST_LOG(lg) << "Another log line with the counter";
+
+ // Ok, remember the "Tag" attribute we added in the formatter? It is absent in these
+ // two lines above, so it is empty in the output. Let's try to tag some log records with it.
+ {
+ BOOST_LOG_NAMED_SCOPE("Tagging scope");
+
+ // Here we add a temporary attribute to the logger lg.
+ // Every log record being written in the current scope with logger lg
+ // will have a string attribute "Tag" with value "Tagged line" attached.
+ BOOST_LOG_SCOPED_LOGGER_TAG(lg, "Tag", "Tagged line");
+
+ // The above line is roughly equivalent to the following:
+ // attrs::constant< std::string > TagAttr("Tagged line");
+ // logging::scoped_attribute _ =
+ // logging::add_scoped_logger_attribute(lg, "Tag", TagAttr);
+
+ // Now these lines will be highlighted with the tag
+ BOOST_LOG(lg) << "Some tagged log line";
+ BOOST_LOG(lg) << "Another tagged log line";
+ }
+
+ // And this line is not highlighted anymore
+ BOOST_LOG(lg) << "Now the tag is removed";
+ BOOST_LOG(lg) << logging::add_value("Tag", "Tagged line") << "Some lines can also be selectively tagged";
+
+ // Now let's try to apply filtering to the output. Filtering is based on
+ // attributes being output with the record. One of the common filtering use cases
+ // is filtering based on the record severity level. We've already defined severity levels.
+ // Now we can set the filter. A filter is essentially a functor that returns
+ // boolean value that tells whether to write the record or not.
+ pSink->set_filter(
+ expr::attr< severity_level >("Severity").or_default(normal) >= warning // Write all records with "warning" severity or higher
+ || expr::begins_with(expr::attr< std::string >("Tag").or_default(std::string()), "IMPORTANT")); // ...or specifically tagged
+
+ // The "attr" placeholder here acts pretty much like the "attr" placeholder in formatters, except
+ // that it requires the attribute type (or types in MPL-sequence) to be specified.
+ // In case of a single std::string or std::wstring type of attribute the "attr" placeholder
+ // provides a number of extended predicates which include "begins_with", "ends_with", "contains"
+ // and "matches" (the last one performs RegEx matching).
+ // There are other placeholders to be used for filter composition in the "boost/log/filters"
+ // directory. Additionally, you are not restricted to them and may provide your own filtering
+ // functors.
+
+ // It must be noted that filters may be applied on per-sink basis and/or globally.
+ // Above we set a filter for this particular sink. Had we another sink, the filter would
+ // not influence it. To set a global filter one should call the set_filter method of the
+ // logging system like that:
+ // logging::core::get()->set_filter(...);
+
+ // Now, to set logging severity we could perfectly use our previously created logger "lg".
+ // But no make it more convenient and efficient there is a special extended logger class.
+ // Its implementation may serve as an example of extending basic library functionality.
+ // You may add your specific capabilities to the logger by deriving your class from it.
+ src::severity_logger< severity_level > slg;
+
+ // These two lines test filtering based on severity
+ BOOST_LOG_SEV(slg, normal) << "A normal severity message, will not pass to the output";
+ BOOST_LOG_SEV(slg, error) << "An error severity message, will pass to the output";
+
+ {
+ // Next we try if the second condition of the filter works
+ // We mark following lines with a tag
+ BOOST_LOG_SCOPED_THREAD_TAG("Tag", "IMPORTANT MESSAGES");
+
+ // We may omit the severity and use the shorter BOOST_LOG macro. The logger "slg"
+ // has the default severity that may be specified on its construction. We didn't
+ // do it, so it is 0 by default. Therefore this record will have "normal" severity.
+ // The only reason this record will be output is the "Tag" attribute we added above.
+ BOOST_LOG(slg) << "Some really urgent line";
+ }
+
+ pSink->reset_filter();
+
+ // And moreover, it is possible to nest logging records. For example, this will
+ // be processed in the order of evaluation:
+ BOOST_LOG(lg) << "The result of foo is " << foo(lg);
+
+ return 0;
+}

Added: trunk/libs/log/example/async_log/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/async_log/Jamfile.v2 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,32 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+
+project
+ : requirements
+ <link>shared:<define>BOOST_ALL_DYN_LINK
+ <logapi>unix:<define>BOOST_LOG_USE_NATIVE_SYSLOG=1
+ <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>gcc:<cxxflags>-fno-strict-aliasing # avoids strict aliasing violations in other Boost components
+ <toolset>gcc:<cxxflags>-ftemplate-depth-1024
+ <library>/boost/log//boost_log
+ <library>/boost/date_time//boost_date_time
+ <library>/boost/filesystem//boost_filesystem
+ <library>/boost/system//boost_system
+ <library>/boost/thread//boost_thread
+ <threading>multi
+ ;
+
+exe async_log
+ : main.cpp
+ ;

Added: trunk/libs/log/example/async_log/main.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/async_log/main.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,130 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 main.cpp
+ * \author Andrey Semashev
+ * \date 30.08.2009
+ *
+ * \brief An example of asynchronous logging in multiple threads.
+ */
+
+// #define BOOST_LOG_DYN_LINK 1
+
+#include <stdexcept>
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <functional>
+#include <boost/ref.hpp>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/barrier.hpp>
+
+#include <boost/log/common.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/attributes.hpp>
+#include <boost/log/sinks.hpp>
+#include <boost/log/sources/logger.hpp>
+#include <boost/log/utility/empty_deleter.hpp>
+#include <boost/log/utility/record_ordering.hpp>
+
+namespace logging = boost::log;
+namespace attrs = boost::log::attributes;
+namespace src = boost::log::sources;
+namespace sinks = boost::log::sinks;
+namespace expr = boost::log::expressions;
+namespace keywords = boost::log::keywords;
+
+using boost::shared_ptr;
+
+enum
+{
+ LOG_RECORDS_TO_WRITE = 10000,
+ THREAD_COUNT = 2
+};
+
+BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(test_lg, src::logger_mt)
+
+//! This function is executed in multiple threads
+void thread_fun(boost::barrier& bar)
+{
+ // Wait until all threads are created
+ bar.wait();
+
+ // Here we go. First, identfy the thread.
+ BOOST_LOG_SCOPED_THREAD_TAG("ThreadID", boost::this_thread::get_id());
+
+ // Now, do some logging
+ for (unsigned int i = 0; i < LOG_RECORDS_TO_WRITE; ++i)
+ {
+ BOOST_LOG(test_lg::get()) << "Log record " << i;
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ // Open a rotating text file
+ shared_ptr< std::ostream > strm(new std::ofstream("test.log"));
+ if (!strm->good())
+ throw std::runtime_error("Failed to open a text log file");
+
+ // Create a text file sink
+ typedef sinks::text_ostream_backend backend_t;
+ typedef sinks::asynchronous_sink<
+ backend_t,
+ sinks::unbounded_ordering_queue<
+ logging::attribute_value_ordering< unsigned int, std::less< unsigned int > >
+ >
+ > sink_t;
+ shared_ptr< sink_t > sink(new sink_t(
+ boost::make_shared< backend_t >(),
+ // We'll apply record ordering to ensure that records from different threads go sequentially in the file
+ keywords::order = logging::make_attr_ordering("RecordID", std::less< unsigned int >())));
+
+ sink->locked_backend()->add_stream(strm);
+
+ sink->set_formatter
+ (
+ expr::format("%1%: [%2%] [%3%] - %4%")
+ % expr::attr< unsigned int >("RecordID")
+ % expr::attr< boost::posix_time::ptime >("TimeStamp")
+ % expr::attr< boost::thread::id >("ThreadID")
+ % expr::smessage
+ );
+
+ // Add it to the core
+ logging::core::get()->add_sink(sink);
+
+ // Add some attributes too
+ logging::core::get()->add_global_attribute("TimeStamp", attrs::local_clock());
+ logging::core::get()->add_global_attribute("RecordID", attrs::counter< unsigned int >());
+
+ // Create logging threads
+ boost::barrier bar(THREAD_COUNT);
+ boost::thread_group threads;
+ for (unsigned int i = 0; i < THREAD_COUNT; ++i)
+ threads.create_thread(boost::bind(&thread_fun, boost::ref(bar)));
+
+ // Wait until all action ends
+ threads.join_all();
+
+ // Flush all buffered records
+ sink->stop();
+ sink->flush();
+
+ return 0;
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "FAILURE: " << e.what() << std::endl;
+ return 1;
+ }
+}

Added: trunk/libs/log/example/basic_usage/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/basic_usage/Jamfile.v2 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,33 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+
+project
+ : requirements
+ <link>shared:<define>BOOST_ALL_DYN_LINK
+ <logapi>unix:<define>BOOST_LOG_USE_NATIVE_SYSLOG=1
+ <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>gcc:<cxxflags>-fno-strict-aliasing # avoids strict aliasing violations in other Boost components
+ <toolset>gcc:<cxxflags>-ftemplate-depth-1024
+ <library>/boost/log//boost_log
+ <library>/boost/log//boost_log_setup
+ <library>/boost/date_time//boost_date_time
+ <library>/boost/filesystem//boost_filesystem
+ <library>/boost/system//boost_system
+ <threading>single:<define>BOOST_LOG_NO_THREADS
+ <threading>multi:<library>/boost/thread//boost_thread
+ ;
+
+exe basic_usage
+ : main.cpp
+ ;

Added: trunk/libs/log/example/basic_usage/main.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/basic_usage/main.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,129 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 main.cpp
+ * \author Andrey Semashev
+ * \date 11.11.2007
+ *
+ * \brief An example of basic library usage. See the library tutorial for expanded
+ * comments on this code. It may also be worthwhile reading the Wiki requirements page:
+ * http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Boost.Logging
+ */
+
+// #define BOOST_LOG_USE_CHAR
+// #define BOOST_ALL_DYN_LINK 1
+// #define BOOST_LOG_DYN_LINK 1
+
+#include <iostream>
+
+#include <boost/log/common.hpp>
+#include <boost/log/expressions.hpp>
+
+#include <boost/log/utility/setup/file.hpp>
+#include <boost/log/utility/setup/console.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+
+#include <boost/log/attributes/timer.hpp>
+#include <boost/log/attributes/named_scope.hpp>
+
+#include <boost/log/sources/logger.hpp>
+
+#include <boost/log/support/date_time.hpp>
+
+namespace logging = boost::log;
+namespace sinks = boost::log::sinks;
+namespace attrs = boost::log::attributes;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace keywords = boost::log::keywords;
+
+using boost::shared_ptr;
+
+// Here we define our application severity levels.
+enum severity_level
+{
+ normal,
+ notification,
+ warning,
+ error,
+ critical
+};
+
+// The formatting logic for the severity level
+template< typename CharT, typename TraitsT >
+inline std::basic_ostream< CharT, TraitsT >& operator<< (
+ std::basic_ostream< CharT, TraitsT >& strm, severity_level lvl)
+{
+ static const char* const str[] =
+ {
+ "normal",
+ "notification",
+ "warning",
+ "error",
+ "critical"
+ };
+ if (static_cast< std::size_t >(lvl) < (sizeof(str) / sizeof(*str)))
+ strm << str[lvl];
+ else
+ strm << static_cast< int >(lvl);
+ return strm;
+}
+
+int main(int argc, char* argv[])
+{
+ // This is a simple tutorial/example of Boost.Log usage
+
+ // The first thing we have to do to get using the library is
+ // to set up the logging sinks - i.e. where the logs will be written to.
+ logging::add_console_log(std::clog, keywords::format = "%TimeStamp%: %Message%");
+
+ // One can also use lambda expressions to setup filters and formatters
+ logging::add_file_log
+ (
+ "sample.log",
+ keywords::filter = expr::attr< severity_level >("Severity") >= warning,
+ keywords::format = expr::stream
+ << expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d, %H:%M:%S.%f")
+ << " [" << expr::format_date_time< attrs::timer::value_type >("Uptime", "%O:%M:%S")
+ << "] [" << expr::format_named_scope("Scope", keywords::format = "%n (%f:%l)")
+ << "] <" << expr::attr< severity_level >("Severity")
+ << "> " << expr::message
+/*
+ keywords::format = expr::format("%1% [%2%] [%3%] <%4%> %5%")
+ % expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d, %H:%M:%S.%f")
+ % expr::format_date_time< attrs::timer::value_type >("Uptime", "%O:%M:%S")
+ % expr::format_named_scope("Scope", keywords::format = "%n (%f:%l)")
+ % expr::attr< severity_level >("Severity")
+ % expr::message
+*/
+ );
+
+ // Also let's add some commonly used attributes, like timestamp and record counter.
+ logging::add_common_attributes();
+ logging::core::get()->add_thread_attribute("Scope", attrs::named_scope());
+
+ BOOST_LOG_FUNCTION();
+
+ // Now our logs will be written both to the console and to the file.
+ // Let's do a quick test and output something. We have to create a logger for this.
+ src::logger lg;
+
+ // And output...
+ BOOST_LOG(lg) << "Hello, World!";
+
+ // Now, let's try logging with severity
+ src::severity_logger< severity_level > slg;
+
+ // Let's pretend we also want to profile our code, so add a special timer attribute.
+ slg.add_attribute("Uptime", attrs::timer());
+
+ BOOST_LOG_SEV(slg, normal) << "A normal severity message, will not pass to the file";
+ BOOST_LOG_SEV(slg, warning) << "A warning severity message, will pass to the file";
+ BOOST_LOG_SEV(slg, error) << "An error severity message, will pass to the file";
+
+ return 0;
+}

Added: trunk/libs/log/example/bounded_async_log/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/bounded_async_log/Jamfile.v2 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,32 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+
+project
+ : requirements
+ <link>shared:<define>BOOST_ALL_DYN_LINK
+ <logapi>unix:<define>BOOST_LOG_USE_NATIVE_SYSLOG=1
+ <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>gcc:<cxxflags>-fno-strict-aliasing # avoids strict aliasing violations in other Boost components
+ <toolset>gcc:<cxxflags>-ftemplate-depth-1024
+ <library>/boost/log//boost_log
+ <library>/boost/date_time//boost_date_time
+ <library>/boost/filesystem//boost_filesystem
+ <library>/boost/system//boost_system
+ <library>/boost/thread//boost_thread
+ <threading>multi
+ ;
+
+exe bounded_async_log
+ : main.cpp
+ ;

Added: trunk/libs/log/example/bounded_async_log/main.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/bounded_async_log/main.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,132 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 main.cpp
+ * \author Andrey Semashev
+ * \date 30.08.2009
+ *
+ * \brief An example of asynchronous logging with bounded log record queue in multiple threads.
+ */
+
+// #define BOOST_LOG_DYN_LINK 1
+
+#include <stdexcept>
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <functional>
+#include <boost/ref.hpp>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/barrier.hpp>
+
+#include <boost/log/common.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/attributes.hpp>
+#include <boost/log/sinks.hpp>
+#include <boost/log/sources/logger.hpp>
+#include <boost/log/utility/empty_deleter.hpp>
+#include <boost/log/utility/record_ordering.hpp>
+
+namespace logging = boost::log;
+namespace attrs = boost::log::attributes;
+namespace src = boost::log::sources;
+namespace sinks = boost::log::sinks;
+namespace expr = boost::log::expressions;
+namespace keywords = boost::log::keywords;
+
+using boost::shared_ptr;
+
+enum
+{
+ LOG_RECORDS_TO_WRITE = 10000,
+ THREAD_COUNT = 2
+};
+
+BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(test_lg, src::logger_mt)
+
+//! This function is executed in multiple threads
+void thread_fun(boost::barrier& bar)
+{
+ // Wait until all threads are created
+ bar.wait();
+
+ // Here we go. First, identfy the thread.
+ BOOST_LOG_SCOPED_THREAD_TAG("ThreadID", boost::this_thread::get_id());
+
+ // Now, do some logging
+ for (unsigned int i = 0; i < LOG_RECORDS_TO_WRITE; ++i)
+ {
+ BOOST_LOG(test_lg::get()) << "Log record " << i;
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ // Open a rotating text file
+ shared_ptr< std::ostream > strm(new std::ofstream("test.log"));
+ if (!strm->good())
+ throw std::runtime_error("Failed to open a text log file");
+
+ // Create a text file sink
+ typedef sinks::text_ostream_backend backend_t;
+ typedef sinks::asynchronous_sink<
+ backend_t,
+ sinks::bounded_ordering_queue<
+ logging::attribute_value_ordering< unsigned int, std::less< unsigned int > >,
+ 128, // queue no more than 128 log records
+ sinks::block_on_overflow // wait until records are processed
+ >
+ > sink_t;
+ shared_ptr< sink_t > sink(new sink_t(
+ boost::make_shared< backend_t >(),
+ // We'll apply record ordering to ensure that records from different threads go sequentially in the file
+ keywords::order = logging::make_attr_ordering("RecordID", std::less< unsigned int >())));
+
+ sink->locked_backend()->add_stream(strm);
+
+ sink->set_formatter
+ (
+ expr::format("%1%: [%2%] [%3%] - %4%")
+ % expr::attr< unsigned int >("RecordID")
+ % expr::attr< boost::posix_time::ptime >("TimeStamp")
+ % expr::attr< boost::thread::id >("ThreadID")
+ % expr::smessage
+ );
+
+ // Add it to the core
+ logging::core::get()->add_sink(sink);
+
+ // Add some attributes too
+ logging::core::get()->add_global_attribute("TimeStamp", attrs::local_clock());
+ logging::core::get()->add_global_attribute("RecordID", attrs::counter< unsigned int >());
+
+ // Create logging threads
+ boost::barrier bar(THREAD_COUNT);
+ boost::thread_group threads;
+ for (unsigned int i = 0; i < THREAD_COUNT; ++i)
+ threads.create_thread(boost::bind(&thread_fun, boost::ref(bar)));
+
+ // Wait until all action ends
+ threads.join_all();
+
+ // Flush all buffered records
+ sink->stop();
+ sink->flush();
+
+ return 0;
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "FAILURE: " << e.what() << std::endl;
+ return 1;
+ }
+}

Added: trunk/libs/log/example/doc/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/Jamfile.v2 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,49 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+
+import path ;
+
+project
+ : requirements
+ <link>shared:<define>BOOST_ALL_DYN_LINK
+ <logapi>unix:<define>BOOST_LOG_USE_NATIVE_SYSLOG=1
+ <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>gcc:<cxxflags>-fno-strict-aliasing # avoids strict aliasing violations in other Boost components
+ <toolset>gcc:<cxxflags>-ftemplate-depth-1024
+ <library>/boost/log//boost_log
+ <library>/boost/log//boost_log_setup
+ <library>/boost/date_time//boost_date_time
+ <library>/boost/filesystem//boost_filesystem
+ <library>/boost/system//boost_system
+ <threading>single:<define>BOOST_LOG_NO_THREADS
+ <threading>multi:<library>/boost/thread//boost_thread
+ ;
+
+# Compiles each .cpp file in this directory into a separate executable
+rule compile_all
+{
+ #ECHO executing compile_all rule ;
+ local all_rules = ;
+ for local file in [ glob *.cpp ]
+ {
+ local exename = [ MATCH "([^.]*).cpp$" : [ path.basename $(file) ] ] ;
+ #ECHO "exename = $(exename)" ;
+ all_rules += [ exe $(exename) : $(file) ] ;
+ }
+
+ #ECHO $(all_rules) ;
+ return $(all_rules) ;
+}
+
+compile_all ;

Added: trunk/libs/log/example/doc/attr_value_extraction.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/attr_value_extraction.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,134 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <cstddef>
+#include <string>
+#include <utility>
+#include <iostream>
+#include <boost/mpl/vector.hpp>
+#include <boost/log/attributes/value_extraction.hpp>
+#include <boost/log/attributes/attribute_value_impl.hpp>
+#include <boost/log/utility/value_ref.hpp>
+
+namespace logging = boost::log;
+namespace attrs = boost::log::attributes;
+
+//[ example_attr_value_extraction
+void print_value(logging::attribute_value const& attr)
+{
+ // Extract a reference to the stored value
+ logging::value_ref< int > val = logging::extract< int >(attr);
+
+ // Check the result
+ if (val)
+ std::cout << "Extraction succeeded: " << val.get() << std::endl;
+ else
+ std::cout << "Extraction failed" << std::endl;
+}
+//]
+
+//[ example_attr_value_extraction_multiple_types
+void print_value_multiple_types(logging::attribute_value const& attr)
+{
+ // Define the set of expected types of the stored value
+ typedef boost::mpl::vector< int, std::string > types;
+
+ // Extract a reference to the stored value
+ logging::value_ref< types > val = logging::extract< types >(attr);
+
+ // Check the result
+ if (val)
+ {
+ std::cout << "Extraction succeeded" << std::endl;
+ switch (val.which())
+ {
+ case 0:
+ std::cout << "int: " << val.get< int >() << std::endl;
+ break;
+
+ case 1:
+ std::cout << "string: " << val.get< std::string >() << std::endl;
+ break;
+ }
+ }
+ else
+ std::cout << "Extraction failed" << std::endl;
+}
+//]
+
+//[ example_attr_value_extraction_visitor
+struct hash_visitor
+{
+ typedef std::size_t result_type;
+
+ result_type operator() (int val) const
+ {
+ std::size_t h = val;
+ h = (h << 15) + h;
+ h ^= (h >> 6) + (h << 7);
+ return h;
+ }
+
+ result_type operator() (std::string const& val) const
+ {
+ std::size_t h = 0;
+ for (std::string::const_iterator it = val.begin(), end = val.end(); it != end; ++it)
+ h += *it;
+
+ h = (h << 15) + h;
+ h ^= (h >> 6) + (h << 7);
+ return h;
+ }
+};
+
+void hash_value(logging::attribute_value const& attr)
+{
+ // Define the set of expected types of the stored value
+ typedef boost::mpl::vector< int, std::string > types;
+
+ // Extract the stored value
+ logging::value_ref< types > val = logging::extract< types >(attr);
+
+ // Check the result
+ if (val)
+ std::cout << "Extraction succeeded, hash value: " << val.apply_visitor(hash_visitor()) << std::endl;
+ else
+ std::cout << "Extraction failed" << std::endl;
+}
+//]
+
+#if 0
+//[ example_attr_value_extraction_visitor_rec
+void hash_value(logging::record_view const& rec, logging::attribute_name name)
+{
+ // Define the set of expected types of the stored value
+ typedef boost::mpl::vector< int, std::string > types;
+
+ // Extract the stored value
+ logging::value_ref< types > val = logging::extract< types >(name, rec);
+
+ // Check the result
+ if (val)
+ std::cout << "Extraction succeeded, hash value: " << val.apply_visitor(hash_visitor()) << std::endl;
+ else
+ std::cout << "Extraction failed" << std::endl;
+}
+//]
+#endif
+
+int main(int, char*[])
+{
+ print_value(attrs::make_attribute_value(10));
+
+ print_value_multiple_types(attrs::make_attribute_value(10));
+ print_value_multiple_types(attrs::make_attribute_value(std::string("Hello")));
+
+ hash_value(attrs::make_attribute_value(10));
+ hash_value(attrs::make_attribute_value(std::string("Hello")));
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/attr_value_visitation.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/attr_value_visitation.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,123 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <cstddef>
+#include <string>
+#include <iostream>
+#include <boost/mpl/vector.hpp>
+#include <boost/log/attributes/value_visitation.hpp>
+#include <boost/log/attributes/attribute_value_impl.hpp>
+#include <boost/log/utility/functional/save_result.hpp>
+
+namespace logging = boost::log;
+namespace attrs = boost::log::attributes;
+
+//[ example_attr_value_visitation
+// Our attribute value visitor
+struct print_visitor
+{
+ typedef void result_type;
+
+ result_type operator() (int val) const
+ {
+ std::cout << "Visited value is int: " << val << std::endl;
+ }
+
+ result_type operator() (std::string const& val) const
+ {
+ std::cout << "Visited value is string: " << val << std::endl;
+ }
+};
+
+void print_value(logging::attribute_value const& attr)
+{
+ // Define the set of expected types of the stored value
+ typedef boost::mpl::vector< int, std::string > types;
+
+ // Apply our visitor
+ logging::visitation_result result = logging::visit< types >(attr, print_visitor());
+
+ // Check the result
+ if (result)
+ std::cout << "Visitation succeeded" << std::endl;
+ else
+ std::cout << "Visitation failed" << std::endl;
+}
+//]
+
+//[ example_attr_value_visitation_with_retval
+struct hash_visitor
+{
+ typedef std::size_t result_type;
+
+ result_type operator() (int val) const
+ {
+ std::size_t h = val;
+ h = (h << 15) + h;
+ h ^= (h >> 6) + (h << 7);
+ return h;
+ }
+
+ result_type operator() (std::string const& val) const
+ {
+ std::size_t h = 0;
+ for (std::string::const_iterator it = val.begin(), end = val.end(); it != end; ++it)
+ h += *it;
+
+ h = (h << 15) + h;
+ h ^= (h >> 6) + (h << 7);
+ return h;
+ }
+};
+
+void hash_value(logging::attribute_value const& attr)
+{
+ // Define the set of expected types of the stored value
+ typedef boost::mpl::vector< int, std::string > types;
+
+ // Apply our visitor
+ std::size_t h = 0;
+ logging::visitation_result result = logging::visit< types >(attr, logging::save_result(hash_visitor(), h));
+
+ // Check the result
+ if (result)
+ std::cout << "Visitation succeeded, hash value: " << h << std::endl;
+ else
+ std::cout << "Visitation failed" << std::endl;
+}
+//]
+
+#if 0
+//[ example_attr_value_visitation_with_retval_rec
+void hash_value(logging::record_view const& rec, logging::attribute_name name)
+{
+ // Define the set of expected types of the stored value
+ typedef boost::mpl::vector< int, std::string > types;
+
+ // Apply our visitor
+ std::size_t h = 0;
+ logging::visitation_result result = logging::visit< types >(name, rec, logging::save_result(hash_visitor(), h));
+
+ // Check the result
+ if (result)
+ std::cout << "Visitation succeeded, hash value: " << h << std::endl;
+ else
+ std::cout << "Visitation failed" << std::endl;
+}
+//]
+#endif
+
+int main(int, char*[])
+{
+ print_value(attrs::make_attribute_value(10));
+ print_value(attrs::make_attribute_value(std::string("Hello")));
+
+ hash_value(attrs::make_attribute_value(10));
+ hash_value(attrs::make_attribute_value(std::string("Hello")));
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/core_core_manual.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/core_core_manual.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/shared_ptr.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+
+namespace logging = boost::log;
+
+//[ example_core_core_manual_logging
+void logging_function(logging::attribute_set const& attrs)
+{
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ // Attempt to open a log record
+ logging::record rec = core->open_record(attrs);
+ if (rec)
+ {
+ // Ok, the record is accepted. Compose the message now.
+ logging::record_ostream strm(rec);
+ strm << "Hello, World!";
+ strm.flush();
+
+ // Deliver the record to the sinks.
+ core->push_record(boost::move(rec));
+ }
+}
+//]
+
+int main(int, char*[])
+{
+ logging_function(logging::attribute_set());
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/core_record.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/core_record.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,122 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <cstddef>
+#include <iostream>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/attributes.hpp>
+#include <boost/log/utility/value_ref.hpp>
+
+namespace logging = boost::log;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace attrs = boost::log::attributes;
+namespace keywords = boost::log::keywords;
+
+// We define our own severity levels
+enum severity_level
+{
+ normal,
+ notification,
+ warning,
+ error,
+ critical
+};
+
+// The operator puts a human-friendly representation of the severity level to the stream
+std::ostream& operator<< (std::ostream& strm, severity_level level)
+{
+ static const char* strings[] =
+ {
+ "normal",
+ "notification",
+ "warning",
+ "error",
+ "critical"
+ };
+
+ if (static_cast< std::size_t >(level) < sizeof(strings) / sizeof(*strings))
+ strm << strings[level];
+ else
+ strm << static_cast< int >(level);
+
+ return strm;
+}
+
+//[ example_core_record_visitation_extraction
+//=enum severity_level { ... };
+//=std::ostream& operator<< (std::ostream& strm, severity_level level);
+
+struct print_visitor
+{
+ typedef void result_type;
+ result_type operator() (severity_level level) const
+ {
+ std::cout << level << std::endl;
+ };
+};
+
+// Prints severity level through visitation API
+void print_severity_visitation(logging::record const& rec)
+{
+ logging::visit< severity_level >("Severity", rec, print_visitor());
+}
+
+// Prints severity level through extraction API
+void print_severity_extraction(logging::record const& rec)
+{
+ logging::value_ref< severity_level > level = logging::extract< severity_level >("Severity", rec);
+ std::cout << level << std::endl;
+}
+//]
+
+//[ example_core_record_attr_value_lookup
+// Prints severity level by searching the attribute values
+void print_severity_lookup(logging::record const& rec)
+{
+ logging::attribute_value_set const& values = rec.attribute_values();
+ logging::attribute_value_set::const_iterator it = values.find("Severity");
+ if (it != values.end())
+ {
+ logging::attribute_value const& value = it->second;
+
+ // A single attribute value can also be visited or extracted
+ std::cout << value.extract< severity_level >() << std::endl;
+ }
+}
+//]
+
+//[ example_core_record_subscript
+BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", severity_level)
+
+// Prints severity level by using the subscript opereator
+void print_severity_subscript(logging::record const& rec)
+{
+ // Use the attribute keyword to communicate the name and type of the value
+ logging::value_ref< severity_level, tag::severity > level = rec[severity];
+ std::cout << level << std::endl;
+}
+//]
+
+
+int main(int, char*[])
+{
+ logging::attribute_set attrs;
+ attrs.insert("Severity", attrs::make_constant(notification));
+
+ logging::record rec = logging::core::get()->open_record(attrs);
+ if (rec)
+ {
+ print_severity_visitation(rec);
+ print_severity_extraction(rec);
+ print_severity_lookup(rec);
+ print_severity_subscript(rec);
+ }
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/exception_handling.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/exception_handling.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,163 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <cstddef>
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <stdexcept>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sources/basic_logger.hpp>
+#include <boost/log/sources/severity_feature.hpp>
+#include <boost/log/sources/exception_handler_feature.hpp>
+#include <boost/log/sources/features.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/sources/global_logger_storage.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/attributes/scoped_attribute.hpp>
+#include <boost/log/utility/exception_handler.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace attrs = boost::log::attributes;
+namespace keywords = boost::log::keywords;
+
+//[ example_sources_exception_handler
+enum severity_level
+{
+ normal,
+ warning,
+ error
+};
+
+// A logger class that allows to intercept exceptions and supports severity level
+class my_logger_mt :
+ public src::basic_composite_logger<
+ char,
+ my_logger_mt,
+ src::multi_thread_model< boost::shared_mutex >,
+ src::features<
+ src::severity< severity_level >,
+ src::exception_handler
+ >
+ >
+{
+ BOOST_LOG_FORWARD_LOGGER_MEMBERS(my_logger_mt)
+};
+
+BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(my_logger, my_logger_mt)
+{
+ my_logger_mt lg;
+
+ // Set up exception handler: all exceptions that occur while
+ // logging through this logger, will be suppressed
+ lg.set_exception_handler(logging::make_exception_suppressor());
+
+ return lg;
+}
+
+void logging_function()
+{
+ // This will not throw
+ BOOST_LOG_SEV(my_logger::get(), normal) << "Hello, world";
+}
+//]
+
+//[ example_utility_exception_handler
+struct my_handler
+{
+ typedef void result_type;
+
+ void operator() (std::runtime_error const& e) const
+ {
+ std::cout << "std::runtime_error: " << e.what() << std::endl;
+ }
+ void operator() (std::logic_error const& e) const
+ {
+ std::cout << "std::logic_error: " << e.what() << std::endl;
+ throw;
+ }
+};
+
+void init_exception_handler()
+{
+ // Setup a global exception handler that will call my_handler::operator()
+ // for the specified exception types
+ logging::core::get()->set_exception_handler(logging::make_exception_handler<
+ std::runtime_error,
+ std::logic_error
+ >(my_handler()));
+}
+//]
+
+//[ example_utility_exception_handler_nothrow
+struct my_handler_nothrow
+{
+ typedef void result_type;
+
+ void operator() (std::runtime_error const& e) const
+ {
+ std::cout << "std::runtime_error: " << e.what() << std::endl;
+ }
+ void operator() (std::logic_error const& e) const
+ {
+ std::cout << "std::logic_error: " << e.what() << std::endl;
+ throw;
+ }
+ void operator() () const
+ {
+ std::cout << "unknown exception" << std::endl;
+ }
+};
+
+void init_exception_handler_nothrow()
+{
+ // Setup a global exception handler that will call my_handler::operator()
+ // for the specified exception types. Note the std::nothrow argument that
+ // specifies that all other exceptions should also be passed to the functor.
+ logging::core::get()->set_exception_handler(logging::make_exception_handler<
+ std::runtime_error,
+ std::logic_error
+ >(my_handler_nothrow(), std::nothrow));
+}
+//]
+
+void init()
+{
+ typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;
+ boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();
+
+ sink->locked_backend()->add_stream(
+ boost::make_shared< std::ofstream >("sample.log"));
+
+ sink->set_formatter
+ (
+ expr::stream
+ << expr::attr< unsigned int >("LineID")
+ << ": <" << expr::attr< severity_level >("Severity")
+ << "> " << expr::smessage
+ );
+
+ logging::core::get()->add_sink(sink);
+
+ init_exception_handler();
+}
+
+int main(int, char*[])
+{
+ init();
+ logging_function();
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/expressions_attr_fmt_tag.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/expressions_attr_fmt_tag.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,119 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <cstddef>
+#include <iostream>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sources/severity_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/utility/manipulators/to_log.hpp>
+#include <boost/log/utility/setup/console.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace keywords = boost::log::keywords;
+
+//[ example_expressions_attr_formatter_stream_tag
+// We define our own severity levels
+enum severity_level
+{
+ normal,
+ notification,
+ warning,
+ error,
+ critical
+};
+
+// The operator is used for regular stream formatting
+std::ostream& operator<< (std::ostream& strm, severity_level level)
+{
+ static const char* strings[] =
+ {
+ "normal",
+ "notification",
+ "warning",
+ "error",
+ "critical"
+ };
+
+ if (static_cast< std::size_t >(level) < sizeof(strings) / sizeof(*strings))
+ strm << strings[level];
+ else
+ strm << static_cast< int >(level);
+
+ return strm;
+}
+
+// Attribute value tag type
+struct severity_tag;
+
+// The operator is used when putting the severity level to log
+logging::formatting_ostream& operator<<
+(
+ logging::formatting_ostream& strm,
+ logging::to_log_manip< severity_level, severity_tag > const& manip
+)
+{
+ static const char* strings[] =
+ {
+ "NORM",
+ "NTFY",
+ "WARN",
+ "ERRR",
+ "CRIT"
+ };
+
+ severity_level level = manip.get();
+ if (static_cast< std::size_t >(level) < sizeof(strings) / sizeof(*strings))
+ strm << strings[level];
+ else
+ strm << static_cast< int >(level);
+
+ return strm;
+}
+
+void init()
+{
+ logging::add_console_log
+ (
+ std::clog,
+ // This makes the sink to write log records that look like this:
+ // 1: <NORM> A normal severity message
+ // 2: <ERRR> An error severity message
+ keywords::format =
+ (
+ expr::stream
+ << expr::attr< unsigned int >("LineID")
+ << ": <" << expr::attr< severity_level, severity_tag >("Severity")
+ << "> " << expr::smessage
+ )
+ );
+}
+//]
+
+int main(int, char*[])
+{
+ init();
+ logging::add_common_attributes();
+
+ src::severity_logger< severity_level > lg;
+
+ // These messages will be written with CAPS severity levels
+ BOOST_LOG_SEV(lg, normal) << "A normal severity message";
+ BOOST_LOG_SEV(lg, notification) << "A notification severity message";
+ BOOST_LOG_SEV(lg, warning) << "A warning severity message";
+ BOOST_LOG_SEV(lg, error) << "An error severity message";
+ BOOST_LOG_SEV(lg, critical) << "A critical severity message";
+
+ // This line will still use lower-case severity levels
+ std::cout << "The regular output still uses lower-case formatting: " << normal << std::endl;
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/expressions_channel_severity_filter.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/expressions_channel_severity_filter.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,109 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <cstddef>
+#include <iostream>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sources/severity_channel_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/utility/setup/console.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace keywords = boost::log::keywords;
+
+//[ example_expressions_channel_severity_filter
+// We define our own severity levels
+enum severity_level
+{
+ normal,
+ notification,
+ warning,
+ error,
+ critical
+};
+
+// Define the attribute keywords
+BOOST_LOG_ATTRIBUTE_KEYWORD(line_id, "LineID", unsigned int)
+BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", severity_level)
+BOOST_LOG_ATTRIBUTE_KEYWORD(channel, "Channel", std::string)
+
+//<-
+std::ostream& operator<< (std::ostream& strm, severity_level level)
+{
+ static const char* strings[] =
+ {
+ "normal",
+ "notification",
+ "warning",
+ "error",
+ "critical"
+ };
+
+ if (static_cast< std::size_t >(level) < sizeof(strings) / sizeof(*strings))
+ strm << strings[level];
+ else
+ strm << static_cast< int >(level);
+
+ return strm;
+}
+//->
+
+void init()
+{
+ // Create a minimal severity table filter
+ typedef expr::channel_severity_filter_actor< std::string, severity_level > min_severity_filter;
+ min_severity_filter min_severity = expr::channel_severity_filter(channel, severity);
+
+ // Set up the minimum severity levels for different channels
+ min_severity["general"] = notification;
+ min_severity["network"] = warning;
+ min_severity["gui"] = error;
+
+ logging::add_console_log
+ (
+ std::clog,
+ keywords::filter = min_severity || severity >= critical,
+ keywords::format =
+ (
+ expr::stream
+ << line_id
+ << ": <" << severity
+ << "> [" << channel << "] "
+ << expr::smessage
+ )
+ );
+}
+
+// Define our logger type
+typedef src::severity_channel_logger< severity_level, std::string > logger_type;
+
+void test_logging(logger_type& lg, std::string const& channel_name)
+{
+ BOOST_LOG_CHANNEL_SEV(lg, channel_name, normal) << "A normal severity level message";
+ BOOST_LOG_CHANNEL_SEV(lg, channel_name, notification) << "A notification severity level message";
+ BOOST_LOG_CHANNEL_SEV(lg, channel_name, warning) << "A warning severity level message";
+ BOOST_LOG_CHANNEL_SEV(lg, channel_name, error) << "An error severity level message";
+ BOOST_LOG_CHANNEL_SEV(lg, channel_name, critical) << "A critical severity level message";
+}
+//]
+
+int main(int, char*[])
+{
+ init();
+ logging::add_common_attributes();
+
+ logger_type lg;
+ test_logging(lg, "general");
+ test_logging(lg, "network");
+ test_logging(lg, "gui");
+ test_logging(lg, "filesystem");
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/expressions_has_attr_stat_accum.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/expressions_has_attr_stat_accum.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,133 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <cstddef>
+#include <string>
+#include <map>
+#include <iostream>
+#include <fstream>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/log/sinks.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/attributes/scoped_attribute.hpp>
+#include <boost/log/sources/logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/utility/value_ref.hpp>
+#include <boost/log/utility/manipulators/add_value.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace keywords = boost::log::keywords;
+
+//[ example_expressions_has_attr_stat_accumulator
+// Declare attribute keywords
+BOOST_LOG_ATTRIBUTE_KEYWORD(stat_stream, "StatisticStream", std::string)
+BOOST_LOG_ATTRIBUTE_KEYWORD(change, "Change", int)
+
+// A simple sink backend to accumulate statistic information
+class my_stat_accumulator :
+ public sinks::basic_sink_backend< sinks::synchronized_feeding >
+{
+ // A map of accumulated statistic values,
+ // ordered by the statistic information stream name
+ typedef std::map< std::string, int > stat_info_map;
+ stat_info_map m_stat_info;
+
+public:
+ // Destructor
+ ~my_stat_accumulator()
+ {
+ // Display the accumulated data
+ stat_info_map::const_iterator it = m_stat_info.begin(), end = m_stat_info.end();
+ for (; it != end; ++it)
+ {
+ std::cout << "Statistic stream: " << it->first
+ << ", accumulated value: " << it->second << "\n";
+ }
+ std::cout.flush();
+ }
+
+ // The method is called for every log record being put into the sink backend
+ void consume(logging::record_view const& rec)
+ {
+ // First, acquire statistic information stream name
+ logging::value_ref< std::string, tag::stat_stream > name = rec[stat_stream];
+ if (name)
+ {
+ // Next, get the statistic value change
+ logging::value_ref< int, tag::change > change_amount = rec[change];
+ if (change_amount)
+ {
+ // Accumulate the statistic data
+ m_stat_info[name.get()] += change_amount.get();
+ }
+ }
+ }
+};
+
+// The function registers two sinks - one for statistic information,
+// and another one for other records
+void init()
+{
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ // Create a backend and attach a stream to it
+ boost::shared_ptr< sinks::text_ostream_backend > backend =
+ boost::make_shared< sinks::text_ostream_backend >();
+ backend->add_stream(
+ boost::shared_ptr< std::ostream >(new std::ofstream("test.log")));
+
+ // Create a frontend and setup filtering
+ typedef sinks::synchronous_sink< sinks::text_ostream_backend > log_sink_type;
+ boost::shared_ptr< log_sink_type > log_sink(new log_sink_type(backend));
+ // All records that don't have a "StatisticStream" attribute attached
+ // will go to the "test.log" file
+ log_sink->set_filter(!expr::has_attr(stat_stream));
+
+ core->add_sink(log_sink);
+
+ // Create another sink that will receive all statistic data
+ typedef sinks::synchronous_sink< my_stat_accumulator > stat_sink_type;
+ boost::shared_ptr< stat_sink_type > stat_sink(new stat_sink_type());
+ // All records with a "StatisticStream" string attribute attached
+ // will go to the my_stat_accumulator sink
+ stat_sink->set_filter(expr::has_attr(stat_stream));
+
+ core->add_sink(stat_sink);
+}
+
+// This simple macro will simplify putting statistic data into a logger
+#define PUT_STAT(lg, stat_stream_name, change)\
+ if (true) {\
+ BOOST_LOG_SCOPED_LOGGER_TAG(lg, "StatisticStream", stat_stream_name);\
+ BOOST_LOG(lg) << logging::add_value("Change", (int)(change));\
+ } else ((void)0)
+
+void logging_function()
+{
+ src::logger lg;
+
+ // Put a regular log record, it will go to the "test.log" file
+ BOOST_LOG(lg) << "A regular log record";
+
+ // Put some statistic data
+ PUT_STAT(lg, "StreamOne", 10);
+ PUT_STAT(lg, "StreamTwo", 20);
+ PUT_STAT(lg, "StreamOne", -5);
+}
+//]
+
+int main(int, char*[])
+{
+ init();
+ logging_function();
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/expressions_keyword_fmt_tag.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/expressions_keyword_fmt_tag.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,129 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <cstddef>
+#include <iostream>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sources/severity_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/utility/manipulators/to_log.hpp>
+#include <boost/log/utility/setup/console.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace keywords = boost::log::keywords;
+
+//[ example_expressions_keyword_formatter_stream_tag
+// We define our own severity levels
+enum severity_level
+{
+ normal,
+ notification,
+ warning,
+ error,
+ critical
+};
+
+// Define the attribute keywords
+BOOST_LOG_ATTRIBUTE_KEYWORD(line_id, "LineID", unsigned int)
+BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", severity_level)
+
+// The operator is used for regular stream formatting
+std::ostream& operator<< (std::ostream& strm, severity_level level)
+{
+ static const char* strings[] =
+ {
+ "normal",
+ "notification",
+ "warning",
+ "error",
+ "critical"
+ };
+
+ if (static_cast< std::size_t >(level) < sizeof(strings) / sizeof(*strings))
+ strm << strings[level];
+ else
+ strm << static_cast< int >(level);
+
+ return strm;
+}
+
+// The operator is used when putting the severity level to log
+logging::formatting_ostream& operator<<
+(
+ logging::formatting_ostream& strm,
+ logging::to_log_manip< severity_level, tag::severity > const& manip
+)
+{
+ static const char* strings[] =
+ {
+ "NORM",
+ "NTFY",
+ "WARN",
+ "ERRR",
+ "CRIT"
+ };
+
+ severity_level level = manip.get();
+ if (static_cast< std::size_t >(level) < sizeof(strings) / sizeof(*strings))
+ strm << strings[level];
+ else
+ strm << static_cast< int >(level);
+
+ return strm;
+}
+
+void init()
+{
+ logging::add_console_log
+ (
+ std::clog,
+ // This makes the sink to write log records that look like this:
+ // 1: <NORM> A normal severity message
+ // 2: <ERRR> An error severity message
+ keywords::format =
+ (
+ expr::stream
+ << line_id
+ << ": <" << severity
+ << "> " << expr::smessage
+ )
+ );
+}
+//]
+
+//[ example_expressions_keyword_lookup
+void print_severity(logging::record_view const& rec)
+{
+ logging::value_ref< severity_level, tag::severity > level = rec[severity];
+ std::cout << level << std::endl;
+}
+//]
+
+
+int main(int, char*[])
+{
+ init();
+ logging::add_common_attributes();
+
+ src::severity_logger< severity_level > lg;
+
+ // These messages will be written with CAPS severity levels
+ BOOST_LOG_SEV(lg, normal) << "A normal severity message";
+ BOOST_LOG_SEV(lg, notification) << "A notification severity message";
+ BOOST_LOG_SEV(lg, warning) << "A warning severity message";
+ BOOST_LOG_SEV(lg, error) << "An error severity message";
+ BOOST_LOG_SEV(lg, critical) << "A critical severity message";
+
+ // This line will still use lower-case severity levels
+ std::cout << "The regular output still uses lower-case formatting: " << normal << std::endl;
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/extension_app_launcher.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/extension_app_launcher.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,123 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <cstdlib>
+#include <string>
+#include <utility>
+#include <stdexcept>
+#include <boost/shared_ptr.hpp>
+#include <boost/phoenix.hpp>
+#include <boost/log/trivial.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/attributes/current_process_name.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/basic_sink_backend.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/utility/value_ref.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/utility/manipulators/add_value.hpp>
+
+namespace logging = boost::log;
+namespace attrs = boost::log::attributes;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace keywords = boost::log::keywords;
+
+//[ example_extension_app_launcher_definition
+// The backend starts an external application to display notifications
+class app_launcher :
+ public sinks::basic_formatted_sink_backend<
+ char, /*< target character type >*/
+ sinks::synchronized_feeding /*< in order not to spawn too many application instances we require records to be processed serial >*/
+ >
+{
+public:
+ // The function consumes the log records that come from the frontend
+ void consume(logging::record_view const& rec, string_type const& command_line);
+};
+//]
+
+//[ example_extension_app_launcher_consume
+// The function consumes the log records that come from the frontend
+void app_launcher::consume(logging::record_view const& rec, string_type const& command_line)
+{
+ std::system(command_line.c_str());
+}
+//]
+
+//[ example_extension_app_launcher_formatting
+BOOST_LOG_ATTRIBUTE_KEYWORD(process_name, "ProcessName", std::string)
+BOOST_LOG_ATTRIBUTE_KEYWORD(caption, "Caption", std::string)
+
+// Custom severity level formatting function
+std::string severity_level_as_urgency(
+ logging::value_ref< logging::trivial::severity_level, logging::trivial::tag::severity > const& level)
+{
+ if (!level || level.get() == logging::trivial::info)
+ return "normal";
+ logging::trivial::severity_level lvl = level.get();
+ if (lvl < logging::trivial::info)
+ return "low";
+ else
+ return "critical";
+}
+
+// The function initializes the logging library
+void init_logging()
+{
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ typedef sinks::synchronous_sink< app_launcher > sink_t;
+ boost::shared_ptr< sink_t > sink(new sink_t());
+
+ const std::pair< const char*, const char* > shell_decorations[] =
+ {
+ std::pair< const char*, const char* >("\"", "\\\""),
+ std::pair< const char*, const char* >("$", "\\$"),
+ std::pair< const char*, const char* >("!", "\\!")
+ };
+
+ // Make the formatter generate the command line for notify-send
+ sink->set_formatter
+ (
+ expr::stream << "notify-send -t 2000 -u "
+ << boost::phoenix::bind(&severity_level_as_urgency, logging::trivial::severity.or_none())
+ << expr::if_(expr::has_attr(process_name))
+ [
+ expr::stream << " -a '" << process_name << "'"
+ ]
+ << expr::if_(expr::has_attr(caption))
+ [
+ expr::stream << " \"" << expr::char_decor(shell_decorations)[ expr::stream << caption ] << "\""
+ ]
+ << " \"" << expr::char_decor(shell_decorations)[ expr::stream << expr::message ] << "\""
+ );
+
+ core->add_sink(sink);
+
+ // Add attributes that we will use
+ core->add_global_attribute("ProcessName", attrs::current_process_name());
+}
+//]
+
+//[ example_extension_app_launcher_logging
+void test_notifications()
+{
+ BOOST_LOG_TRIVIAL(debug) << "Hello, it's a simple notification";
+ BOOST_LOG_TRIVIAL(info) << logging::add_value(caption, "Caption text") << "And this notification has caption as well";
+}
+//]
+
+int main(int, char*[])
+{
+ init_logging();
+ test_notifications();
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/extension_filter_parser.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/extension_filter_parser.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,162 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <string>
+#include <iostream>
+#include <stdexcept>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/phoenix.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/scoped_attribute.hpp>
+#include <boost/log/sources/logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/utility/value_ref.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/utility/manipulators/add_value.hpp>
+#include <boost/log/utility/setup/filter_parser.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+#include <boost/log/utility/setup/console.hpp>
+
+namespace logging = boost::log;
+namespace attrs = boost::log::attributes;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace keywords = boost::log::keywords;
+
+//[ example_extension_filter_parser_point_definition
+struct point
+{
+ float m_x, m_y;
+
+ point() : m_x(0.0f), m_y(0.0f) {}
+ point(float x, float y) : m_x(x), m_y(y) {}
+};
+
+bool operator== (point const& left, point const& right);
+bool operator!= (point const& left, point const& right);
+
+template< typename CharT, typename TraitsT >
+std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, point const& p);
+template< typename CharT, typename TraitsT >
+std::basic_istream< CharT, TraitsT >& operator>> (std::basic_istream< CharT, TraitsT >& strm, point& p);
+//]
+
+const float epsilon = 0.0001f;
+
+bool operator== (point const& left, point const& right)
+{
+ return (left.m_x - epsilon <= right.m_x && left.m_x + epsilon >= right.m_x) &&
+ (left.m_y - epsilon <= right.m_y && left.m_y + epsilon >= right.m_y);
+}
+
+bool operator!= (point const& left, point const& right)
+{
+ return !(left == right);
+}
+
+template< typename CharT, typename TraitsT >
+std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, point const& p)
+{
+ if (strm.good())
+ strm << "(" << p.m_x << ", " << p.m_y << ")";
+ return strm;
+}
+
+template< typename CharT, typename TraitsT >
+std::basic_istream< CharT, TraitsT >& operator>> (std::basic_istream< CharT, TraitsT >& strm, point& p)
+{
+ if (strm.good())
+ {
+ CharT left_brace = static_cast< CharT >(0), comma = static_cast< CharT >(0), right_brace = static_cast< CharT >(0);
+ strm.setf(std::ios_base::skipws);
+ strm >> left_brace >> p.m_x >> comma >> p.m_y >> right_brace;
+ if (left_brace != '(' || comma != ',' || right_brace != ')')
+ strm.setstate(std::ios_base::failbit);
+ }
+ return strm;
+}
+
+#if 0
+//[ example_extension_simple_filter_factory
+void init_factories()
+{
+ //<-
+ logging::register_simple_formatter_factory< point, char >("Coordinates");
+ //->
+ logging::register_simple_filter_factory< point, char >("Coordinates");
+}
+//]
+#endif
+
+//[ example_extension_custom_filter_factory
+// Custom point filter factory
+class point_filter_factory :
+ public logging::filter_factory< char >
+{
+public:
+ logging::filter on_exists_test(logging::attribute_name const& name)
+ {
+ return expr::has_attr< point >(name);
+ }
+
+ logging::filter on_equality_relation(logging::attribute_name const& name, string_type const& arg)
+ {
+ return expr::attr< point >(name) == boost::lexical_cast< point >(arg);
+ }
+
+ logging::filter on_inequality_relation(logging::attribute_name const& name, string_type const& arg)
+ {
+ return expr::attr< point >(name) != boost::lexical_cast< point >(arg);
+ }
+};
+
+void init_factories()
+{
+ //<-
+ logging::register_simple_formatter_factory< point, char >("Coordinates");
+ //->
+ logging::register_filter_factory("Coordinates", boost::make_shared< point_filter_factory >());
+}
+//]
+
+void init_logging()
+{
+ init_factories();
+
+ logging::add_console_log
+ (
+ std::clog,
+ keywords::filter = "%Coordinates% = \"(10, 10)\"",
+ keywords::format = "%TimeStamp% %Coordinates% %Message%"
+ );
+
+ logging::add_common_attributes();
+}
+
+int main(int, char*[])
+{
+ init_logging();
+
+ src::logger lg;
+
+ // We have to use scoped attributes in order coordinates to be passed to filters
+ {
+ BOOST_LOG_SCOPED_LOGGER_TAG(lg, "Coordinates", point(10, 10));
+ BOOST_LOG(lg) << "Hello, world with coordinates (10, 10)!";
+ }
+ {
+ BOOST_LOG_SCOPED_LOGGER_TAG(lg, "Coordinates", point(20, 20));
+ BOOST_LOG(lg) << "Hello, world with coordinates (20, 20)!"; // this message will be suppressed by filter
+ }
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/extension_filter_parser_custom_rel.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/extension_filter_parser_custom_rel.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,203 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <string>
+#include <iostream>
+#include <stdexcept>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/phoenix.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/scoped_attribute.hpp>
+#include <boost/log/sources/logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/utility/value_ref.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/utility/manipulators/add_value.hpp>
+#include <boost/log/utility/setup/filter_parser.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+#include <boost/log/utility/setup/console.hpp>
+
+namespace logging = boost::log;
+namespace attrs = boost::log::attributes;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace keywords = boost::log::keywords;
+
+struct point
+{
+ float m_x, m_y;
+
+ point() : m_x(0.0f), m_y(0.0f) {}
+ point(float x, float y) : m_x(x), m_y(y) {}
+};
+
+bool operator== (point const& left, point const& right);
+bool operator!= (point const& left, point const& right);
+
+template< typename CharT, typename TraitsT >
+std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, point const& p);
+template< typename CharT, typename TraitsT >
+std::basic_istream< CharT, TraitsT >& operator>> (std::basic_istream< CharT, TraitsT >& strm, point& p);
+
+const float epsilon = 0.0001f;
+
+bool operator== (point const& left, point const& right)
+{
+ return (left.m_x - epsilon <= right.m_x && left.m_x + epsilon >= right.m_x) &&
+ (left.m_y - epsilon <= right.m_y && left.m_y + epsilon >= right.m_y);
+}
+
+bool operator!= (point const& left, point const& right)
+{
+ return !(left == right);
+}
+
+template< typename CharT, typename TraitsT >
+std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, point const& p)
+{
+ if (strm.good())
+ strm << "(" << p.m_x << ", " << p.m_y << ")";
+ return strm;
+}
+
+template< typename CharT, typename TraitsT >
+std::basic_istream< CharT, TraitsT >& operator>> (std::basic_istream< CharT, TraitsT >& strm, point& p)
+{
+ if (strm.good())
+ {
+ CharT left_brace = static_cast< CharT >(0), comma = static_cast< CharT >(0), right_brace = static_cast< CharT >(0);
+ strm.setf(std::ios_base::skipws);
+ strm >> left_brace >> p.m_x >> comma >> p.m_y >> right_brace;
+ if (left_brace != '(' || comma != ',' || right_brace != ')')
+ strm.setstate(std::ios_base::failbit);
+ }
+ return strm;
+}
+
+//[ example_extension_filter_parser_rectangle_definition
+struct rectangle
+{
+ point m_top_left, m_bottom_right;
+};
+
+template< typename CharT, typename TraitsT >
+std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, rectangle const& r);
+template< typename CharT, typename TraitsT >
+std::basic_istream< CharT, TraitsT >& operator>> (std::basic_istream< CharT, TraitsT >& strm, rectangle& r);
+//]
+
+template< typename CharT, typename TraitsT >
+std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, rectangle const& r)
+{
+ if (strm.good())
+ strm << "{" << r.m_top_left << " - " << r.m_bottom_right << "}";
+ return strm;
+}
+
+template< typename CharT, typename TraitsT >
+std::basic_istream< CharT, TraitsT >& operator>> (std::basic_istream< CharT, TraitsT >& strm, rectangle& r)
+{
+ if (strm.good())
+ {
+ CharT left_brace = static_cast< CharT >(0), dash = static_cast< CharT >(0), right_brace = static_cast< CharT >(0);
+ strm.setf(std::ios_base::skipws);
+ strm >> left_brace >> r.m_top_left >> dash >> r.m_bottom_right >> right_brace;
+ if (left_brace != '{' || dash != '-' || right_brace != '}')
+ strm.setstate(std::ios_base::failbit);
+ }
+ return strm;
+}
+
+
+//[ example_extension_custom_filter_factory_with_custom_rel
+// The function checks if the point is inside the rectangle
+bool is_in_rect(logging::value_ref< point > const& p, rectangle const& r)
+{
+ if (p)
+ {
+ return p->m_x >= r.m_top_left.m_x && p->m_x <= r.m_bottom_right.m_x &&
+ p->m_y >= r.m_top_left.m_y && p->m_y <= r.m_bottom_right.m_y;
+ }
+ return false;
+}
+
+// Custom point filter factory
+class point_filter_factory :
+ public logging::filter_factory< char >
+{
+public:
+ logging::filter on_exists_test(logging::attribute_name const& name)
+ {
+ return expr::has_attr< point >(name);
+ }
+
+ logging::filter on_equality_relation(logging::attribute_name const& name, string_type const& arg)
+ {
+ return expr::attr< point >(name) == boost::lexical_cast< point >(arg);
+ }
+
+ logging::filter on_inequality_relation(logging::attribute_name const& name, string_type const& arg)
+ {
+ return expr::attr< point >(name) != boost::lexical_cast< point >(arg);
+ }
+
+ logging::filter on_custom_relation(logging::attribute_name const& name, string_type const& rel, string_type const& arg)
+ {
+ if (rel == "is_in_rect")
+ {
+ return boost::phoenix::bind(&is_in_rect, expr::attr< point >(name), boost::lexical_cast< rectangle >(arg));
+ }
+ throw std::runtime_error("Unsupported filter relation: " + rel);
+ }
+};
+
+void init_factories()
+{
+ //<-
+ logging::register_simple_formatter_factory< point, char >("Coordinates");
+ //->
+ logging::register_filter_factory("Coordinates", boost::make_shared< point_filter_factory >());
+}
+//]
+
+void init_logging()
+{
+ init_factories();
+
+ logging::add_console_log
+ (
+ std::clog,
+ keywords::filter = "%Coordinates% is_in_rect \"{(0, 0) - (20, 20)}\"",
+ keywords::format = "%TimeStamp% %Coordinates% %Message%"
+ );
+
+ logging::add_common_attributes();
+}
+
+int main(int, char*[])
+{
+ init_logging();
+
+ src::logger lg;
+
+ // We have to use scoped attributes in order coordinates to be passed to filters
+ {
+ BOOST_LOG_SCOPED_LOGGER_TAG(lg, "Coordinates", point(10, 10));
+ BOOST_LOG(lg) << "Hello, world with coordinates (10, 10)!";
+ }
+ {
+ BOOST_LOG_SCOPED_LOGGER_TAG(lg, "Coordinates", point(50, 50));
+ BOOST_LOG(lg) << "Hello, world with coordinates (50, 50)!"; // this message will be suppressed by filter
+ }
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/extension_formatter_parser.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/extension_formatter_parser.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,125 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <string>
+#include <iostream>
+#include <stdexcept>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/format.hpp>
+#include <boost/phoenix.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/sources/logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/utility/value_ref.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/utility/manipulators/add_value.hpp>
+#include <boost/log/utility/setup/formatter_parser.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+#include <boost/log/utility/setup/console.hpp>
+
+namespace logging = boost::log;
+namespace attrs = boost::log::attributes;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace keywords = boost::log::keywords;
+
+//[ example_extension_formatter_parser_point_definition
+struct point
+{
+ float m_x, m_y;
+
+ point() : m_x(0.0f), m_y(0.0f) {}
+ point(float x, float y) : m_x(x), m_y(y) {}
+};
+
+template< typename CharT, typename TraitsT >
+std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, point const& p)
+{
+ strm << "(" << p.m_x << ", " << p.m_y << ")";
+ return strm;
+}
+//]
+
+#if 0
+//[ example_extension_simple_formatter_factory
+void init_factories()
+{
+ logging::register_simple_formatter_factory< point, char >("Coordinates");
+}
+//]
+#endif
+
+//[ example_extension_custom_formatter_factory
+// Custom point formatter
+class point_formatter
+{
+public:
+ typedef void result_type;
+
+public:
+ explicit point_formatter(std::string const& fmt) : m_format(fmt)
+ {
+ }
+
+ void operator() (logging::formatting_ostream& strm, logging::value_ref< point > const& value)
+ {
+ if (value)
+ {
+ point const& p = value.get();
+ m_format % p.m_x % p.m_y;
+ strm << m_format;
+ m_format.clear();
+ }
+ }
+
+private:
+ boost::format m_format;
+};
+
+// Custom point formatter factory
+class point_formatter_factory :
+ public logging::basic_formatter_factory< char, point >
+{
+public:
+ formatter_type create_formatter(logging::attribute_name const& name, args_map const& args)
+ {
+ args_map::const_iterator it = args.find("format");
+ if (it != args.end())
+ return boost::phoenix::bind(point_formatter(it->second), expr::stream, expr::attr< point >(name));
+ else
+ return expr::stream << expr::attr< point >(name);
+ }
+};
+
+void init_factories()
+{
+ logging::register_formatter_factory("Coordinates", boost::make_shared< point_formatter_factory >());
+}
+//]
+
+void init_logging()
+{
+ init_factories();
+
+ logging::add_console_log(std::clog, keywords::format = "%TimeStamp% %Coordinates(format=\"{%0.3f; %0.3f}\")% %Message%");
+
+ logging::add_common_attributes();
+}
+
+int main(int, char*[])
+{
+ init_logging();
+
+ src::logger lg;
+ BOOST_LOG(lg) << logging::add_value("Coordinates", point(10.5f, 20.2f)) << "Hello, world with coordinates!";
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/extension_record_tagger.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/extension_record_tagger.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,247 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <string>
+#include <ostream>
+#include <fstream>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/scope_exit.hpp>
+#include <boost/mpl/quote.hpp>
+#include <boost/parameter/keyword.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/attributes/constant.hpp>
+#include <boost/log/sources/features.hpp>
+#include <boost/log/sources/basic_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/sources/severity_logger.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/utility/strictest_lock.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace attrs = boost::log::attributes;
+namespace keywords = boost::log::keywords;
+
+//[ example_extension_record_tagger_keyword
+namespace my_keywords {
+
+ BOOST_PARAMETER_KEYWORD(tag_ns, tag)
+
+}
+//]
+
+//[ example_extension_record_tagger_declaration
+template< typename BaseT >
+class record_tagger_feature :
+ public BaseT /*< the feature should derive from other features or the basic_logger class >*/
+{
+public:
+ // Let's import some types that we will need. These imports should be public,
+ // in order to allow other features that may derive from record_tagger to do the same.
+ typedef typename BaseT::char_type char_type;
+ typedef typename BaseT::threading_model threading_model;
+
+public:
+ // Default constructor. Initializes m_Tag to an invalid value.
+ record_tagger_feature();
+ // Copy constructor. Initializes m_Tag to a value, equivalent to that.m_Tag.
+ record_tagger_feature(record_tagger_feature const& that);
+ // Forwarding constructor with named parameters
+ template< typename ArgsT >
+ record_tagger_feature(ArgsT const& args);
+
+ // The method will require locking, so we have to define locking requirements for it.
+ // We use the strictest_lock trait in order to choose the most restricting lock type.
+ typedef typename logging::strictest_lock<
+ boost::lock_guard< threading_model >,
+ typename BaseT::open_record_lock,
+ typename BaseT::add_attribute_lock,
+ typename BaseT::remove_attribute_lock
+ >::type open_record_lock;
+
+protected:
+ // Lock-less implementation of operations
+ template< typename ArgsT >
+ logging::record open_record_unlocked(ArgsT const& args);
+};
+
+// A convenience metafunction to specify the feature
+// in the list of features of the final logger later
+struct record_tagger :
+ public boost::mpl::quote1< record_tagger_feature >
+{
+};
+//]
+
+//[ example_extension_record_tagger_structors
+template< typename BaseT >
+record_tagger_feature< BaseT >::record_tagger_feature()
+{
+}
+
+template< typename BaseT >
+record_tagger_feature< BaseT >::record_tagger_feature(record_tagger_feature const& that) :
+ BaseT(static_cast< BaseT const& >(that))
+{
+}
+
+template< typename BaseT >
+template< typename ArgsT >
+record_tagger_feature< BaseT >::record_tagger_feature(ArgsT const& args) : BaseT(args)
+{
+}
+//]
+
+//[ example_extension_record_tagger_open_record
+template< typename BaseT >
+template< typename ArgsT >
+logging::record record_tagger_feature< BaseT >::open_record_unlocked(ArgsT const& args)
+{
+ // Extract the named argument from the parameters pack
+ std::string tag_value = args[my_keywords::tag | std::string()];
+
+ logging::attribute_set& attrs = BaseT::attributes();
+ logging::attribute_set::iterator tag = attrs.end();
+ if (!tag_value.empty())
+ {
+ // Add the tag as a new attribute
+ std::pair<
+ logging::attribute_set::iterator,
+ bool
+ > res = BaseT::add_attribute_unlocked("Tag",
+ attrs::constant< std::string >(tag_value));
+ if (res.second)
+ tag = res.first;
+ }
+
+ // In any case, after opening a record remove the tag from the attributes
+ BOOST_SCOPE_EXIT_TPL((&tag)(&attrs))
+ {
+ if (tag != attrs.end())
+ attrs.erase(tag);
+ }
+ BOOST_SCOPE_EXIT_END
+
+ // Forward the call to the base feature
+ return BaseT::open_record_unlocked(args);
+}
+//]
+
+//[ example_extension_record_tagger_my_logger
+template< typename LevelT = int >
+class my_logger :
+ public src::basic_composite_logger<
+ char, /*< character type for the logger >*/
+ my_logger< LevelT >, /*< final logger type >*/
+ src::single_thread_model, /*< the logger does not perform thread synchronization; use `multi_thread_model` to declare a thread-safe logger >*/
+ src::features< /*< the list of features we want to combine >*/
+ src::severity< LevelT >,
+ record_tagger
+ >
+ >
+{
+ // The following line will automatically generate forwarding constructors that
+ // will call to the corresponding constructors of the base class
+ BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(my_logger)
+};
+//]
+
+//[ example_extension_record_tagger_severity
+enum severity_level
+{
+ normal,
+ warning,
+ error
+};
+//]
+
+inline std::ostream& operator<< (std::ostream& strm, severity_level level)
+{
+ const char* levels[] =
+ {
+ "normal",
+ "warning",
+ "error"
+ };
+
+ if (static_cast< std::size_t >(level) < sizeof(levels) / sizeof(*levels))
+ strm << levels[level];
+ else
+ strm << static_cast< int >(level);
+
+ return strm;
+}
+
+//[ example_extension_record_tagger_manual_logging
+void manual_logging()
+{
+ my_logger< severity_level > logger;
+
+ logging::record rec = logger.open_record((keywords::severity = normal, my_keywords::tag = "GUI"));
+ if (rec)
+ {
+ logging::record_ostream strm(rec);
+ strm << "The user has confirmed his choice";
+ strm.flush();
+ logger.push_record(boost::move(rec));
+ }
+}
+//]
+
+//[ example_extension_record_tagger_macro_logging
+#define LOG_WITH_TAG(lg, sev, tg) \
+ BOOST_LOG_WITH_PARAMS((lg), (keywords::severity = (sev))(my_keywords::tag = (tg)))
+
+void logging_function()
+{
+ my_logger< severity_level > logger;
+
+ LOG_WITH_TAG(logger, normal, "GUI") << "The user has confirmed his choice";
+}
+//]
+
+void init()
+{
+ typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;
+ boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();
+
+ sink->locked_backend()->add_stream(
+ boost::make_shared< std::ofstream >("sample.log"));
+
+ sink->set_formatter
+ (
+ expr::stream
+ << expr::attr< unsigned int >("LineID")
+ << ": <" << expr::attr< severity_level >("Severity")
+ << "> [" << expr::attr< std::string >("Tag") << "]\t"
+ << expr::smessage
+ );
+
+ logging::core::get()->add_sink(sink);
+
+ // Add attributes
+ logging::add_common_attributes();
+}
+
+
+int main(int, char*[])
+{
+ init();
+
+ logging_function();
+ manual_logging();
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/extension_stat_collector.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/extension_stat_collector.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,171 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <string>
+#include <fstream>
+#include <iostream>
+#include <stdexcept>
+#include <boost/shared_ptr.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/phoenix.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/basic_sink_backend.hpp>
+#include <boost/log/sources/logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/attributes/value_visitation.hpp>
+#include <boost/log/utility/manipulators/add_value.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace keywords = boost::log::keywords;
+
+//[ example_extension_stat_collector_definition
+// The backend collects statistical information about network activity of the application
+class stat_collector :
+ public sinks::basic_sink_backend<
+ sinks::combine_requirements<
+ sinks::synchronized_feeding, /*< we will have to store internal data, so let's require frontend to synchronize feeding calls to the backend >*/
+ sinks::flushing /*< also enable flushing support >*/
+ >::type
+ >
+{
+private:
+ // The file to write the collected information to
+ std::ofstream m_csv_file;
+
+ // Here goes the data collected so far:
+ // Active connections
+ unsigned int m_active_connections;
+ // Sent bytes
+ unsigned int m_sent_bytes;
+ // Received bytes
+ unsigned int m_received_bytes;
+
+ // The number of collected records since the last write to the file
+ unsigned int m_collected_count;
+ // The time when the collected data has been written to the file last time
+ boost::posix_time::ptime m_last_store_time;
+
+public:
+ // The constructor initializes the internal data
+ explicit stat_collector(const char* file_name);
+
+ // The function consumes the log records that come from the frontend
+ void consume(logging::record_view const& rec);
+ // The function flushes the file
+ void flush();
+
+private:
+ // The function resets statistical accumulators to initial values
+ void reset_accumulators();
+ // The function writes the collected data to the file
+ void write_data();
+};
+//]
+
+// The constructor initializes the internal data
+stat_collector::stat_collector(const char* file_name) :
+ m_csv_file(file_name, std::ios::app),
+ m_active_connections(0),
+ m_last_store_time(boost::posix_time::microsec_clock::universal_time())
+{
+ reset_accumulators();
+ if (!m_csv_file.is_open())
+ throw std::runtime_error("could not open the CSV file");
+}
+
+//[ example_extension_stat_collector_consume
+BOOST_LOG_ATTRIBUTE_KEYWORD(sent, "Sent", unsigned int)
+BOOST_LOG_ATTRIBUTE_KEYWORD(received, "Received", unsigned int)
+
+// The function consumes the log records that come from the frontend
+void stat_collector::consume(logging::record_view const& rec)
+{
+ // Accumulate statistical readings
+ if (rec.attribute_values().count("Connected"))
+ ++m_active_connections;
+ else if (rec.attribute_values().count("Disconnected"))
+ --m_active_connections;
+ else
+ {
+ namespace phoenix = boost::phoenix;
+ logging::visit(sent, rec, phoenix::ref(m_sent_bytes) += phoenix::placeholders::_1);
+ logging::visit(received, rec, phoenix::ref(m_received_bytes) += phoenix::placeholders::_1);
+ }
+ ++m_collected_count;
+
+ // Check if it's time to write the accumulated data to the file
+ boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time();
+ if (now - m_last_store_time >= boost::posix_time::minutes(1))
+ {
+ write_data();
+ m_last_store_time = now;
+ }
+}
+
+// The function writes the collected data to the file
+void stat_collector::write_data()
+{
+ m_csv_file << m_active_connections
+ << ',' << m_sent_bytes
+ << ',' << m_received_bytes
+ << std::endl;
+ reset_accumulators();
+}
+
+// The function resets statistical accumulators to initial values
+void stat_collector::reset_accumulators()
+{
+ m_sent_bytes = m_received_bytes = 0;
+ m_collected_count = 0;
+}
+//]
+
+//[ example_extension_stat_collector_flush
+// The function flushes the file
+void stat_collector::flush()
+{
+ // Store any data that may have been collected since the list write to the file
+ if (m_collected_count > 0)
+ {
+ write_data();
+ m_last_store_time = boost::posix_time::microsec_clock::universal_time();
+ }
+
+ m_csv_file.flush();
+}
+//]
+
+// Complete sink type
+typedef sinks::synchronous_sink< stat_collector > sink_t;
+
+void init_logging()
+{
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ boost::shared_ptr< stat_collector > backend(new stat_collector("stat.csv"));
+ boost::shared_ptr< sink_t > sink(new sink_t(backend));
+ core->add_sink(sink);
+}
+
+int main(int, char*[])
+{
+ init_logging();
+
+ src::logger lg;
+ BOOST_LOG(lg) << logging::add_value("Connected", true);
+ BOOST_LOG(lg) << logging::add_value("Sent", 100u);
+ BOOST_LOG(lg) << logging::add_value("Received", 200u);
+
+ logging::core::get()->flush();
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/extension_stat_collector_settings.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/extension_stat_collector_settings.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,222 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <string>
+#include <fstream>
+#include <sstream>
+#include <iostream>
+#include <stdexcept>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/optional/optional.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/phoenix.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sinks/basic_sink_backend.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sources/logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/attributes/value_visitation.hpp>
+#include <boost/log/utility/manipulators/add_value.hpp>
+#include <boost/log/utility/setup/filter_parser.hpp>
+#include <boost/log/utility/setup/from_stream.hpp>
+#include <boost/log/utility/setup/from_settings.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace keywords = boost::log::keywords;
+
+//[ example_extension_stat_collector_settings_definition
+// The backend collects statistical information about network activity of the application
+class stat_collector :
+ public sinks::basic_sink_backend<
+ sinks::combine_requirements<
+ sinks::synchronized_feeding,
+ sinks::flushing
+ >::type
+ >
+{
+private:
+ // The file to write the collected information to
+ std::ofstream m_csv_file;
+
+ // Here goes the data collected so far:
+ // Active connections
+ unsigned int m_active_connections;
+ // Sent bytes
+ unsigned int m_sent_bytes;
+ // Received bytes
+ unsigned int m_received_bytes;
+
+ // The number of collected records since the last write to the file
+ unsigned int m_collected_count;
+ // The time when the collected data has been written to the file last time
+ boost::posix_time::ptime m_last_store_time;
+ // The collected data writing interval
+ boost::posix_time::time_duration m_write_interval;
+
+public:
+ // The constructor initializes the internal data
+ stat_collector(const char* file_name, boost::posix_time::time_duration write_interval);
+
+ // The function consumes the log records that come from the frontend
+ void consume(logging::record_view const& rec);
+ // The function flushes the file
+ void flush();
+
+private:
+ // The function resets statistical accumulators to initial values
+ void reset_accumulators();
+ // The function writes the collected data to the file
+ void write_data();
+};
+//]
+
+// The constructor initializes the internal data
+stat_collector::stat_collector(const char* file_name, boost::posix_time::time_duration write_interval) :
+ m_csv_file(file_name, std::ios::app),
+ m_active_connections(0),
+ m_last_store_time(boost::posix_time::microsec_clock::universal_time()),
+ m_write_interval(write_interval)
+{
+ reset_accumulators();
+ if (!m_csv_file.is_open())
+ throw std::runtime_error("could not open the CSV file");
+}
+
+BOOST_LOG_ATTRIBUTE_KEYWORD(sent, "Sent", unsigned int)
+BOOST_LOG_ATTRIBUTE_KEYWORD(received, "Received", unsigned int)
+
+// The function consumes the log records that come from the frontend
+void stat_collector::consume(logging::record_view const& rec)
+{
+ // Accumulate statistical readings
+ if (rec.attribute_values().count("Connected"))
+ ++m_active_connections;
+ else if (rec.attribute_values().count("Disconnected"))
+ --m_active_connections;
+ else
+ {
+ namespace phoenix = boost::phoenix;
+ logging::visit(sent, rec, phoenix::ref(m_sent_bytes) += phoenix::placeholders::_1);
+ logging::visit(received, rec, phoenix::ref(m_received_bytes) += phoenix::placeholders::_1);
+ }
+ ++m_collected_count;
+
+ // Check if it's time to write the accumulated data to the file
+ boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time();
+ if (now - m_last_store_time >= m_write_interval)
+ {
+ write_data();
+ m_last_store_time = now;
+ }
+}
+
+// The function writes the collected data to the file
+void stat_collector::write_data()
+{
+ m_csv_file << m_active_connections
+ << ',' << m_sent_bytes
+ << ',' << m_received_bytes
+ << std::endl;
+ reset_accumulators();
+}
+
+// The function resets statistical accumulators to initial values
+void stat_collector::reset_accumulators()
+{
+ m_sent_bytes = m_received_bytes = 0;
+ m_collected_count = 0;
+}
+
+// The function flushes the file
+void stat_collector::flush()
+{
+ // Store any data that may have been collected since the list write to the file
+ if (m_collected_count > 0)
+ {
+ write_data();
+ m_last_store_time = boost::posix_time::microsec_clock::universal_time();
+ }
+
+ m_csv_file.flush();
+}
+
+//[ example_extension_stat_collector_factory
+// Factory for the stat_collector sink
+class stat_collector_factory :
+ public logging::sink_factory< char >
+{
+public:
+ // Creates the sink with the provided parameters
+ boost::shared_ptr< sinks::sink > create_sink(settings_section const& settings)
+ {
+ // Read sink parameters
+ std::string file_name;
+ if (boost::optional< std::string > param = settings["FileName"])
+ file_name = param.get();
+ else
+ throw std::runtime_error("No target file name specified in settings");
+
+ boost::posix_time::time_duration write_interval = boost::posix_time::minutes(1);
+ if (boost::optional< std::string > param = settings["WriteInterval"])
+ {
+ unsigned int sec = boost::lexical_cast< unsigned int >(param.get());
+ write_interval = boost::posix_time::seconds(sec);
+ }
+
+ // Create the sink
+ boost::shared_ptr< stat_collector > backend = boost::make_shared< stat_collector >(file_name.c_str(), write_interval);
+ boost::shared_ptr< sinks::synchronous_sink< stat_collector > > sink = boost::make_shared< sinks::synchronous_sink< stat_collector > >(backend);
+
+ if (boost::optional< std::string > param = settings["Filter"])
+ {
+ sink->set_filter(logging::parse_filter(param.get()));
+ }
+
+ return sink;
+ }
+};
+
+void init_factories()
+{
+ logging::register_sink_factory("StatCollector", boost::make_shared< stat_collector_factory >());
+}
+//]
+
+const char settings[] =
+ "[Sinks.MyStat]\n"
+ "Destination=StatCollector\n"
+ "FileName=stat.csv\n"
+ "WriteInterval=30\n"
+;
+
+void init_logging()
+{
+ init_factories();
+
+ std::istringstream strm(settings);
+ logging::init_from_stream(strm);
+}
+
+int main(int, char*[])
+{
+ init_logging();
+
+ src::logger lg;
+ BOOST_LOG(lg) << logging::add_value("Connected", true);
+ BOOST_LOG(lg) << logging::add_value("Sent", 100u);
+ BOOST_LOG(lg) << logging::add_value("Received", 200u);
+
+ logging::core::get()->flush();
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/extension_system_uptime_attr.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/extension_system_uptime_attr.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,133 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <string>
+#include <iostream>
+#include <stdexcept>
+#include <boost/config.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/sources/logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/attributes/attribute_value.hpp>
+#include <boost/log/attributes/attribute_value_impl.hpp>
+#include <boost/log/attributes/attribute_cast.hpp>
+#include <boost/log/utility/empty_deleter.hpp>
+
+// Includes for get_uptime()
+#include <boost/throw_exception.hpp>
+#if defined(BOOST_WINDOWS)
+#include <windows.h>
+#elif defined(__linux__) || defined(__linux) || defined(linux)
+#include <sys/sysinfo.h>
+#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
+#include <time.h>
+#include <errno.h>
+#include <sys/sysctl.h>
+#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
+#include <time.h>
+#endif
+
+namespace logging = boost::log;
+namespace attrs = boost::log::attributes;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace keywords = boost::log::keywords;
+
+//[ example_extension_system_uptime_attr_impl
+// The function returns the system uptime, in seconds
+unsigned int get_uptime();
+
+// Attribute implementation class
+class system_uptime_impl :
+ public logging::attribute::impl
+{
+public:
+ // The method generates a new attribute value
+ logging::attribute_value get_value()
+ {
+ return attrs::make_attribute_value(get_uptime());
+ }
+};
+//]
+
+//[ example_extension_system_uptime_attr
+// Attribute interface class
+class system_uptime :
+ public logging::attribute
+{
+public:
+ system_uptime() : logging::attribute(new system_uptime_impl())
+ {
+ }
+ // Attribute casting support
+ explicit system_uptime(attrs::cast_source const& source) : logging::attribute(source.as< system_uptime_impl >())
+ {
+ }
+};
+//]
+
+//[ example_extension_system_uptime_use
+void init_logging()
+{
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ //<-
+ // Initialize the sink
+ typedef sinks::synchronous_sink< sinks::text_ostream_backend > sink_t;
+ boost::shared_ptr< sink_t > sink(new sink_t());
+ sink->locked_backend()->add_stream(boost::shared_ptr< std::ostream >(&std::clog, logging::empty_deleter()));
+ sink->set_formatter(expr::stream << expr::attr< unsigned int >("SystemUptime") << ": " << expr::smessage);
+ core->add_sink(sink);
+ //->
+ // ...
+
+ // Add the uptime attribute to the core
+ core->add_global_attribute("SystemUptime", system_uptime());
+}
+//]
+
+unsigned int get_uptime()
+{
+#if defined(BOOST_WINDOWS)
+ return GetTickCount() / 1000u;
+#elif defined(__linux__) || defined(__linux) || defined(linux)
+ struct sysinfo info;
+ if (sysinfo(&info) != 0)
+ BOOST_THROW_EXCEPTION(std::runtime_error("Could not acquire uptime"));
+ return info.uptime;
+#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
+ struct timeval boottime;
+ std::size_t len = sizeof(boottime);
+ int mib[2] = { CTL_KERN, KERN_BOOTTIME };
+ if (sysctl(mib, 2, &boottime, &len, NULL, 0) < 0)
+ BOOST_THROW_EXCEPTION(std::runtime_error("Could not acquire uptime"));
+ return time(NULL) - boottime.tv_sec;
+#elif (defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)) && defined(CLOCK_UPTIME)
+ struct timespec ts;
+ if (clock_gettime(CLOCK_UPTIME, &ts) != 0)
+ BOOST_THROW_EXCEPTION(std::runtime_error("Could not acquire uptime"));
+ return ts.tv_sec;
+#else
+ return 0;
+#endif
+}
+
+int main(int, char*[])
+{
+ init_logging();
+
+ src::logger lg;
+ BOOST_LOG(lg) << "Hello, world with uptime!";
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/sinks_async.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/sinks_async.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,98 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <string>
+#include <fstream>
+#include <iostream>
+#include <boost/shared_ptr.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sinks/async_frontend.hpp>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/sources/severity_channel_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/utility/empty_deleter.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace keywords = boost::log::keywords;
+
+//[ example_sinks_async_init
+enum severity_level
+{
+ normal,
+ warning,
+ error
+};
+
+// Complete sink type
+typedef sinks::asynchronous_sink< sinks::text_ostream_backend > sink_t;
+
+boost::shared_ptr< sink_t > init_logging()
+{
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ // Create a backend and initialize it with a stream
+ boost::shared_ptr< sinks::text_ostream_backend > backend =
+ boost::make_shared< sinks::text_ostream_backend >();
+ backend->add_stream(
+ boost::shared_ptr< std::ostream >(&std::clog, logging::empty_deleter()));
+
+ // Wrap it into the frontend and register in the core
+ boost::shared_ptr< sink_t > sink(new sink_t(backend));
+ core->add_sink(sink);
+
+ // You can manage filtering and formatting through the sink interface
+ sink->set_filter(expr::attr< severity_level >("Severity") >= warning);
+ sink->set_formatter
+ (
+ expr::stream
+ << "Level: " << expr::attr< severity_level >("Severity")
+ << " Message: " << expr::message
+ );
+
+ // You can also manage backend in a thread-safe manner
+ {
+ sink_t::locked_backend_ptr p = sink->locked_backend();
+ p->add_stream(boost::make_shared< std::ofstream >("sample.log"));
+ } // the backend gets released here
+
+ return sink;
+}
+//]
+
+//[ example_sinks_async_stop
+void stop_logging(boost::shared_ptr< sink_t >& sink)
+{
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ // Remove the sink from the core, so that no records are passed to it
+ core->remove_sink(sink);
+
+ // Break the feeding loop
+ sink->stop();
+
+ // Flush all log records that may have left buffered
+ sink->flush();
+
+ sink.reset();
+}
+//]
+
+int main(int, char*[])
+{
+ boost::shared_ptr< sink_t > sink = init_logging();
+
+ src::severity_channel_logger< severity_level > lg(keywords::channel = "net");
+ BOOST_LOG_SEV(lg, warning) << "Hello world!";
+
+ stop_logging(sink);
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/sinks_async_bounded.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/sinks_async_bounded.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,107 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <string>
+#include <fstream>
+#include <iostream>
+#include <boost/shared_ptr.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sinks/async_frontend.hpp>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/sinks/bounded_fifo_queue.hpp>
+#include <boost/log/sinks/drop_on_overflow.hpp>
+#include <boost/log/sources/severity_channel_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/utility/empty_deleter.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace keywords = boost::log::keywords;
+
+enum severity_level
+{
+ normal,
+ warning,
+ error
+};
+
+//[ example_sinks_bounded_async_init
+// Complete sink type
+typedef sinks::asynchronous_sink<
+ sinks::text_ostream_backend,
+ sinks::bounded_fifo_queue< /*< log record queueing strategy >*/
+ 100, /*< record queue capacity >*/
+ sinks::drop_on_overflow /*< overflow handling policy >*/
+ >
+> sink_t;
+
+boost::shared_ptr< sink_t > init_logging()
+{
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ // Create a backend and initialize it with a stream
+ boost::shared_ptr< sinks::text_ostream_backend > backend =
+ boost::make_shared< sinks::text_ostream_backend >();
+ backend->add_stream(
+ boost::shared_ptr< std::ostream >(&std::clog, logging::empty_deleter()));
+
+ // Wrap it into the frontend and register in the core
+ boost::shared_ptr< sink_t > sink(new sink_t(backend));
+ core->add_sink(sink);
+
+ // ...
+ //<-
+ // You can manage filtering and formatting through the sink interface
+ sink->set_filter(expr::attr< severity_level >("Severity") >= warning);
+ sink->set_formatter
+ (
+ expr::stream
+ << "Level: " << expr::attr< severity_level >("Severity")
+ << " Message: " << expr::message
+ );
+
+ // You can also manage backend in a thread-safe manner
+ {
+ sink_t::locked_backend_ptr p = sink->locked_backend();
+ p->add_stream(boost::make_shared< std::ofstream >("sample.log"));
+ }
+ //->
+
+ return sink;
+}
+//]
+
+void stop_logging(boost::shared_ptr< sink_t >& sink)
+{
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ // Remove the sink from the core, so that no records are passed to it
+ core->remove_sink(sink);
+
+ // Break the feeding loop
+ sink->stop();
+
+ // Flush all log records that may have left buffered
+ sink->flush();
+
+ sink.reset();
+}
+
+int main(int, char*[])
+{
+ boost::shared_ptr< sink_t > sink = init_logging();
+
+ src::severity_channel_logger< severity_level > lg(keywords::channel = "net");
+ BOOST_LOG_SEV(lg, warning) << "Hello world!";
+
+ stop_logging(sink);
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/sinks_async_ordering.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/sinks_async_ordering.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,117 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <string>
+#include <fstream>
+#include <iostream>
+#include <functional>
+#include <boost/shared_ptr.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sinks/async_frontend.hpp>
+#include <boost/log/sinks/unbounded_ordering_queue.hpp>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/sources/severity_channel_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/utility/empty_deleter.hpp>
+#include <boost/log/utility/record_ordering.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace keywords = boost::log::keywords;
+
+enum severity_level
+{
+ normal,
+ warning,
+ error
+};
+
+//[ example_sinks_ordering_async_init
+// Complete sink type
+typedef sinks::asynchronous_sink<
+ sinks::text_ostream_backend,
+ sinks::unbounded_ordering_queue< /*< log record queueing strategy >*/
+ logging::attribute_value_ordering< /*< log record ordering predicate type >*/
+ unsigned int, /*< attribute value type >*/
+ std::less< unsigned int > /*< optional, attribute value comparison predicate; `std::less` equivalent is used by default >*/
+ >
+ >
+> sink_t;
+
+boost::shared_ptr< sink_t > init_logging()
+{
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ // Create a backend and initialize it with a stream
+ boost::shared_ptr< sinks::text_ostream_backend > backend =
+ boost::make_shared< sinks::text_ostream_backend >();
+ backend->add_stream(
+ boost::shared_ptr< std::ostream >(&std::clog, logging::empty_deleter()));
+
+ // Wrap it into the frontend and register in the core
+ boost::shared_ptr< sink_t > sink(new sink_t(
+ backend, /*< pointer to the pre-initialized backend >*/
+ keywords::order =
+ logging::make_attr_ordering("LineID", std::less< unsigned int >()), /*< log record ordering predicate >*/
+ keywords::ordering_window = boost::posix_time::seconds(1) /*< latency of log record processing >*/
+ ));
+ core->add_sink(sink);
+
+ // You can manage filtering and formatting through the sink interface
+ sink->set_filter(expr::attr< severity_level >("Severity") >= warning);
+ sink->set_formatter
+ (
+ expr::stream
+ << "Level: " << expr::attr< severity_level >("Severity")
+ << " Message: " << expr::smessage
+ );
+
+ // You can also manage backend in a thread-safe manner
+ {
+ sink_t::locked_backend_ptr p = sink->locked_backend();
+ p->add_stream(boost::make_shared< std::ofstream >("sample.log"));
+ } // the backend gets released here
+
+ return sink;
+}
+//]
+
+//[ example_sinks_ordering_async_stop
+void stop_logging(boost::shared_ptr< sink_t >& sink)
+{
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ // Remove the sink from the core, so that no records are passed to it
+ core->remove_sink(sink);
+
+ // Break the feeding loop
+ sink->stop();
+
+ // Flush all log records that may have left buffered
+ sink->flush();
+
+ sink.reset();
+}
+//]
+
+int main(int, char*[])
+{
+ boost::shared_ptr< sink_t > sink = init_logging();
+ logging::add_common_attributes();
+
+ src::severity_channel_logger< severity_level > lg(keywords::channel = "net");
+ BOOST_LOG_SEV(lg, warning) << "Hello world!";
+
+ stop_logging(sink);
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/sinks_debugger.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/sinks_debugger.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,59 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/shared_ptr.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions/predicates/is_debugger_present.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/debug_output_backend.hpp>
+#include <boost/log/sources/logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+
+#if defined(BOOST_WINDOWS)
+
+namespace logging = boost::log;
+namespace expr = boost::log::expressions;
+namespace src = boost::log::sources;
+namespace sinks = boost::log::sinks;
+
+//[ example_sinks_debugger
+// Complete sink type
+typedef sinks::synchronous_sink< sinks::debug_output_backend > sink_t;
+
+void init_logging()
+{
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ // Create the sink. The backend requires synchronization in the frontend.
+ boost::shared_ptr< sink_t > sink(new sink_t());
+
+ // Set the special filter to the frontend
+ // in order to skip the sink when no debugger is available
+ sink->set_filter(expr::is_debugger_present());
+
+ core->add_sink(sink);
+}
+//]
+
+int main(int, char*[])
+{
+ init_logging();
+
+ src::logger lg;
+ BOOST_LOG(lg) << "Hello world!";
+
+ return 0;
+}
+
+#else
+
+int main(int, char*[])
+{
+ return 0;
+}
+
+#endif

Added: trunk/libs/log/example/doc/sinks_file.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/sinks_file.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,53 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <string>
+#include <fstream>
+#include <iostream>
+#include <boost/shared_ptr.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/text_file_backend.hpp>
+#include <boost/log/sources/severity_channel_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/utility/empty_deleter.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace sinks = boost::log::sinks;
+namespace keywords = boost::log::keywords;
+
+//[ example_sinks_file
+void init_logging()
+{
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ boost::shared_ptr< sinks::text_file_backend > backend =
+ boost::make_shared< sinks::text_file_backend >(
+ keywords::file_name = "file_%5N.log", /*< file name pattern >*/
+ keywords::rotation_size = 5 * 1024 * 1024, /*< rotate the file upon reaching 5 MiB size... >*/
+ keywords::time_based_rotation = sinks::file::rotation_at_time_point(12, 0, 0) /*< ...or every day, at noon, whichever comes first >*/
+ );
+
+ // Wrap it into the frontend and register in the core.
+ // The backend requires synchronization in the frontend.
+ typedef sinks::synchronous_sink< sinks::text_file_backend > sink_t;
+ boost::shared_ptr< sink_t > sink(new sink_t(backend));
+
+ core->add_sink(sink);
+}
+//]
+
+int main(int, char*[])
+{
+ init_logging();
+
+ src::severity_channel_logger< > lg(keywords::channel = "net");
+ BOOST_LOG_SEV(lg, 3) << "Hello world!";
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/sinks_multifile.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/sinks_multifile.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,77 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <string>
+#include <iostream>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/text_multifile_backend.hpp>
+#include <boost/log/sources/logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/attributes/scoped_attribute.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace keywords = boost::log::keywords;
+
+//[ example_sinks_multifile
+void init_logging()
+{
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ boost::shared_ptr< sinks::text_multifile_backend > backend =
+ boost::make_shared< sinks::text_multifile_backend >();
+
+ // Set up the file naming pattern
+ backend->set_file_name_composer
+ (
+ sinks::file::as_file_name_composer(expr::stream << "logs/" << expr::attr< std::string >("RequestID") << ".log")
+ );
+
+ // Wrap it into the frontend and register in the core.
+ // The backend requires synchronization in the frontend.
+ typedef sinks::synchronous_sink< sinks::text_multifile_backend > sink_t;
+ boost::shared_ptr< sink_t > sink(new sink_t(backend));
+
+ // Set the formatter
+ sink->set_formatter
+ (
+ expr::stream
+ << "[RequestID: " << expr::attr< std::string >("RequestID")
+ << "] " << expr::smessage
+ );
+
+ core->add_sink(sink);
+}
+//]
+
+void logging_function()
+{
+ src::logger lg;
+ BOOST_LOG(lg) << "Hello, world!";
+}
+
+int main(int, char*[])
+{
+ init_logging();
+
+ {
+ BOOST_LOG_SCOPED_THREAD_TAG("RequestID", "Request1");
+ logging_function();
+ }
+ {
+ BOOST_LOG_SCOPED_THREAD_TAG("RequestID", "Request2");
+ logging_function();
+ }
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/sinks_ostream.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/sinks_ostream.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,56 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <string>
+#include <fstream>
+#include <iostream>
+#include <boost/shared_ptr.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/sources/severity_channel_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/utility/empty_deleter.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace sinks = boost::log::sinks;
+namespace keywords = boost::log::keywords;
+
+//[ example_sinks_ostream
+void init_logging()
+{
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ // Create a backend and attach a couple of streams to it
+ boost::shared_ptr< sinks::text_ostream_backend > backend =
+ boost::make_shared< sinks::text_ostream_backend >();
+ backend->add_stream(
+ boost::shared_ptr< std::ostream >(&std::clog, logging::empty_deleter()));
+ backend->add_stream(
+ boost::shared_ptr< std::ostream >(new std::ofstream("sample.log")));
+
+ // Enable auto-flushing after each log record written
+ backend->auto_flush(true);
+
+ // Wrap it into the frontend and register in the core.
+ // The backend requires synchronization in the frontend.
+ typedef sinks::synchronous_sink< sinks::text_ostream_backend > sink_t;
+ boost::shared_ptr< sink_t > sink(new sink_t(backend));
+ core->add_sink(sink);
+}
+//]
+
+int main(int, char*[])
+{
+ init_logging();
+
+ src::severity_channel_logger< > lg(keywords::channel = "net");
+ BOOST_LOG_SEV(lg, 3) << "Hello world!";
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/sinks_simple_event_log.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/sinks_simple_event_log.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,100 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <stdexcept>
+#include <string>
+#include <iostream>
+#include <boost/shared_ptr.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+#include <boost/log/common.hpp>
+#include <boost/log/attributes.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/event_log_backend.hpp>
+
+#if defined(BOOST_WINDOWS)
+
+namespace logging = boost::log;
+namespace attrs = boost::log::attributes;
+namespace src = boost::log::sources;
+namespace sinks = boost::log::sinks;
+namespace expr = boost::log::expressions;
+namespace keywords = boost::log::keywords;
+
+//[ example_sinks_simple_event_log
+// Complete sink type
+typedef sinks::synchronous_sink< sinks::simple_event_log_backend > sink_t;
+
+// Define application-specific severity levels
+enum severity_level
+{
+ normal,
+ warning,
+ error
+};
+
+void init_logging()
+{
+ // Create an event log sink
+ boost::shared_ptr< sink_t > sink(new sink_t());
+
+ sink->set_formatter
+ (
+ expr::format("%1%: [%2%] - %3%")
+ % expr::attr< unsigned int >("LineID")
+ % expr::attr< boost::posix_time::ptime >("TimeStamp")
+ % expr::smessage
+ );
+
+ // We'll have to map our custom levels to the event log event types
+ sinks::event_log::custom_event_type_mapping< severity_level > mapping("Severity");
+ mapping[normal] = sinks::event_log::info;
+ mapping[warning] = sinks::event_log::warning;
+ mapping[error] = sinks::event_log::error;
+
+ sink->locked_backend()->set_event_type_mapper(mapping);
+
+ // Add the sink to the core
+ logging::core::get()->add_sink(sink);
+}
+//]
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ // Initialize logging library
+ init_logging();
+
+ // Add some attributes too
+ logging::core::get()->add_global_attribute("TimeStamp", attrs::local_clock());
+ logging::core::get()->add_global_attribute("LineID", attrs::counter< unsigned int >());
+
+ // Do some logging
+ src::severity_logger< severity_level > lg(keywords::severity = normal);
+ BOOST_LOG_SEV(lg, normal) << "Some record for NT event log with normal level";
+ BOOST_LOG_SEV(lg, warning) << "Some record for NT event log with warning level";
+ BOOST_LOG_SEV(lg, error) << "Some record for NT event log with error level";
+
+ return 0;
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "FAILURE: " << e.what() << std::endl;
+ return 1;
+ }
+}
+
+#else
+
+int main(int, char*[])
+{
+ return 0;
+}
+
+#endif

Added: trunk/libs/log/example/doc/sinks_sync.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/sinks_sync.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,76 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <string>
+#include <fstream>
+#include <iostream>
+#include <boost/shared_ptr.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/sources/severity_channel_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/utility/empty_deleter.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace keywords = boost::log::keywords;
+
+//[ example_sinks_sync
+enum severity_level
+{
+ normal,
+ warning,
+ error
+};
+
+// Complete sink type
+typedef sinks::synchronous_sink< sinks::text_ostream_backend > sink_t;
+
+void init_logging()
+{
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ // Create a backend and initialize it with a stream
+ boost::shared_ptr< sinks::text_ostream_backend > backend =
+ boost::make_shared< sinks::text_ostream_backend >();
+ backend->add_stream(
+ boost::shared_ptr< std::ostream >(&std::clog, logging::empty_deleter()));
+
+ // Wrap it into the frontend and register in the core
+ boost::shared_ptr< sink_t > sink(new sink_t(backend));
+ core->add_sink(sink);
+
+ // You can manage filtering and formatting through the sink interface
+ sink->set_filter(expr::attr< severity_level >("Severity") >= warning);
+ sink->set_formatter
+ (
+ expr::stream
+ << "Level: " << expr::attr< severity_level >("Severity")
+ << " Message: " << expr::smessage
+ );
+
+ // You can also manage backend in a thread-safe manner
+ {
+ sink_t::locked_backend_ptr p = sink->locked_backend();
+ p->add_stream(boost::make_shared< std::ofstream >("sample.log"));
+ } // the backend gets released here
+}
+//]
+
+int main(int, char*[])
+{
+ init_logging();
+
+ src::severity_channel_logger< severity_level > lg(keywords::channel = "net");
+ BOOST_LOG_SEV(lg, warning) << "Hello world!";
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/sinks_syslog.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/sinks_syslog.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,96 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <string>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/syslog_backend.hpp>
+#include <boost/log/sources/severity_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/attributes/scoped_attribute.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace sinks = boost::log::sinks;
+namespace keywords = boost::log::keywords;
+
+//[ example_sinks_syslog
+// Complete sink type
+typedef sinks::synchronous_sink< sinks::syslog_backend > sink_t;
+
+//<-
+#if defined(BOOST_LOG_USE_NATIVE_SYSLOG)
+//->
+void init_native_syslog()
+{
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ // Create a backend
+ boost::shared_ptr< sinks::syslog_backend > backend(new sinks::syslog_backend(
+ keywords::facility = sinks::syslog::user, /*< the logging facility >*/
+ keywords::use_impl = sinks::syslog::native /*< the native syslog API should be used >*/
+ ));
+
+ // Set the straightforward level translator for the "Severity" attribute of type int
+ backend->set_severity_mapper(sinks::syslog::direct_severity_mapping< int >("Severity"));
+
+ // Wrap it into the frontend and register in the core.
+ // The backend requires synchronization in the frontend.
+ core->add_sink(boost::make_shared< sink_t >(backend));
+}
+//<-
+#endif
+//->
+
+//<-
+#if !defined(BOOST_LOG_NO_ASIO)
+//->
+void init_builtin_syslog()
+{
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ // Create a new backend
+ boost::shared_ptr< sinks::syslog_backend > backend(new sinks::syslog_backend(
+ keywords::facility = sinks::syslog::local0, /*< the logging facility >*/
+ keywords::use_impl = sinks::syslog::udp_socket_based /*< the built-in socket-based implementation should be used >*/
+ ));
+
+ // Setup the target address and port to send syslog messages to
+ backend->set_target_address("192.164.1.10", 514);
+
+ // Create and fill in another level translator for "MyLevel" attribute of type string
+ sinks::syslog::custom_severity_mapping< std::string > mapping("MyLevel");
+ mapping["debug"] = sinks::syslog::debug;
+ mapping["normal"] = sinks::syslog::info;
+ mapping["warning"] = sinks::syslog::warning;
+ mapping["failure"] = sinks::syslog::critical;
+ backend->set_severity_mapper(mapping);
+
+ // Wrap it into the frontend and register in the core.
+ core->add_sink(boost::make_shared< sink_t >(backend));
+}
+//<-
+#endif
+//->
+//]
+
+int main(int, char*[])
+{
+#if defined(BOOST_LOG_USE_NATIVE_SYSLOG)
+ init_native_syslog();
+#elif !defined(BOOST_LOG_NO_ASIO)
+ init_builtin_syslog();
+#endif
+
+ BOOST_LOG_SCOPED_THREAD_TAG("MyLevel", "warning");
+ src::severity_logger< > lg;
+ BOOST_LOG_SEV(lg, 3) << "Hello world!";
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/sinks_unlocked.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/sinks_unlocked.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,76 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <string>
+#include <iostream>
+#include <boost/shared_ptr.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sinks/unlocked_frontend.hpp>
+#include <boost/log/sinks/basic_sink_backend.hpp>
+#include <boost/log/sinks/frontend_requirements.hpp>
+#include <boost/log/sources/severity_channel_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace keywords = boost::log::keywords;
+
+//[ example_sinks_unlocked
+enum severity_level
+{
+ normal,
+ warning,
+ error
+};
+
+// A trivial sink backend that requires no thread synchronization
+class my_backend :
+ public sinks::basic_sink_backend< sinks::concurrent_feeding >
+{
+public:
+ // The function is called for every log record to be written to log
+ void consume(logging::record_view const& rec)
+ {
+ // We skip the actual synchronization code for brevity
+ std::cout << rec[expr::smessage] << std::endl;
+ }
+};
+
+// Complete sink type
+typedef sinks::unlocked_sink< my_backend > sink_t;
+
+void init_logging()
+{
+ boost::shared_ptr< logging::core > core = logging::core::get();
+
+ // The simplest way, the backend is default-constructed
+ boost::shared_ptr< sink_t > sink1(new sink_t());
+ core->add_sink(sink1);
+
+ // One can construct backend separately and pass it to the frontend
+ boost::shared_ptr< my_backend > backend(new my_backend());
+ boost::shared_ptr< sink_t > sink2(new sink_t(backend));
+ core->add_sink(sink2);
+
+ // You can manage filtering through the sink interface
+ sink1->set_filter(expr::attr< severity_level >("Severity") >= warning);
+ sink2->set_filter(expr::attr< std::string >("Channel") == "net");
+}
+//]
+
+int main(int, char*[])
+{
+ init_logging();
+
+ src::severity_channel_logger< severity_level > lg(keywords::channel = "net");
+ BOOST_LOG_SEV(lg, normal) << "Hello world!";
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/sinks_xml_file.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/sinks_xml_file.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,152 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <stdexcept>
+#include <string>
+#include <iostream>
+#include <boost/shared_ptr.hpp>
+#include <boost/lambda/lambda.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+#include <boost/log/common.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/attributes.hpp>
+#include <boost/log/sinks.hpp>
+#include <boost/log/sources/logger.hpp>
+
+namespace logging = boost::log;
+namespace attrs = boost::log::attributes;
+namespace src = boost::log::sources;
+namespace sinks = boost::log::sinks;
+namespace expr = boost::log::expressions;
+namespace keywords = boost::log::keywords;
+
+typedef sinks::synchronous_sink< sinks::text_file_backend > file_sink;
+
+//[ example_sinks_xml_file_collecting
+void init_file_collecting(boost::shared_ptr< file_sink > sink)
+{
+ sink->locked_backend()->set_file_collector(sinks::file::make_collector(
+ keywords::target = "logs", /*< the target directory >*/
+ keywords::max_size = 16 * 1024 * 1024, /*< maximum total size of the stored files, in bytes >*/
+ keywords::min_free_space = 100 * 1024 * 1024 /*< minimum free space on the drive, in bytes >*/
+ ));
+}
+//]
+
+#if 0
+//[ example_sinks_xml_file
+// Complete file sink type
+typedef sinks::synchronous_sink< sinks::text_file_backend > file_sink;
+
+void write_header(sinks::text_file_backend::stream_type& file)
+{
+ file << "<?xml version=\"1.0\"?>\n<log>\n";
+}
+
+void write_footer(sinks::text_file_backend::stream_type& file)
+{
+ file << "</log>\n";
+}
+
+void init_logging()
+{
+ // Create a text file sink
+ boost::shared_ptr< file_sink > sink(new file_sink(
+ keywords::file_name = "%Y%m%d_%H%M%S_%5N.xml", /*< the resulting file name pattern >*/
+ keywords::rotation_size = 16384 /*< rotation size, in characters >*/
+ ));
+
+ sink->set_formatter
+ (
+ expr::format("\t<record id=\"%1%\" timestamp=\"%2%\">%3%</record>")
+ % expr::attr< unsigned int >("RecordID")
+ % expr::attr< boost::posix_time::ptime >("TimeStamp")
+ % expr::xml_decor[ expr::stream << expr::smessage ] /*< the log message has to be decorated, if it contains special characters >*/
+ );
+
+ // Set header and footer writing functors
+ sink->locked_backend()->set_open_handler(&write_header);
+ sink->locked_backend()->set_close_handler(&write_footer);
+
+ // Add the sink to the core
+ logging::core::get()->add_sink(sink);
+}
+//]
+#endif
+
+//[ example_sinks_xml_file_final
+void init_logging()
+{
+ // Create a text file sink
+ boost::shared_ptr< file_sink > sink(new file_sink(
+ keywords::file_name = "%Y%m%d_%H%M%S_%5N.xml",
+ keywords::rotation_size = 16384
+ ));
+
+ // Set up where the rotated files will be stored
+ init_file_collecting(sink);
+
+ // Upon restart, scan the directory for files matching the file_name pattern
+ sink->locked_backend()->scan_for_files();
+
+ sink->set_formatter
+ (
+ expr::format("\t<record id=\"%1%\" timestamp=\"%2%\">%3%</record>")
+ % expr::attr< unsigned int >("RecordID")
+ % expr::attr< boost::posix_time::ptime >("TimeStamp")
+ % expr::xml_decor[ expr::stream << expr::smessage ]
+ );
+
+ // Set header and footer writing functors
+ namespace bll = boost::lambda;
+
+ sink->locked_backend()->set_open_handler
+ (
+ bll::_1 << "<?xml version=\"1.0\"?>\n<log>\n"
+ );
+ sink->locked_backend()->set_close_handler
+ (
+ bll::_1 << "</log>\n"
+ );
+
+ // Add the sink to the core
+ logging::core::get()->add_sink(sink);
+}
+//]
+
+enum { LOG_RECORDS_TO_WRITE = 2000 };
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ // Initialize logging library
+ init_logging();
+
+ // And also add some attributes
+ logging::core::get()->add_global_attribute("TimeStamp", attrs::local_clock());
+ logging::core::get()->add_global_attribute("RecordID", attrs::counter< unsigned int >());
+
+ // Do some logging
+ src::logger lg;
+ for (unsigned int i = 0; i < LOG_RECORDS_TO_WRITE; ++i)
+ {
+ BOOST_LOG(lg) << "XML log record " << i;
+ }
+
+ // Test that XML character decoration works
+ BOOST_LOG(lg) << "Special XML characters: &, <, >, '";
+
+ return 0;
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "FAILURE: " << e.what() << std::endl;
+ return 1;
+ }
+}

Added: trunk/libs/log/example/doc/sources_net_connection.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/sources_net_connection.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,123 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <cstddef>
+#include <string>
+#include <fstream>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/attributes/constant.hpp>
+#include <boost/log/attributes/scoped_attribute.hpp>
+#include <boost/log/attributes/attribute_value_impl.hpp>
+#include <boost/log/sources/logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+#include <boost/log/utility/manipulators/add_value.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace attrs = boost::log::attributes;
+
+BOOST_LOG_ATTRIBUTE_KEYWORD(line_id, "LineID", unsigned int)
+BOOST_LOG_ATTRIBUTE_KEYWORD(remote_address, "RemoteAddress", std::string)
+BOOST_LOG_ATTRIBUTE_KEYWORD(received_size, "ReceivedSize", std::size_t)
+BOOST_LOG_ATTRIBUTE_KEYWORD(sent_size, "SentSize", std::size_t)
+
+//[ example_sources_network_connection
+class network_connection
+{
+ src::logger m_logger;
+ logging::attribute_set::iterator m_remote_addr;
+
+public:
+ void on_connected(std::string const& remote_addr)
+ {
+ // Put the remote address into the logger to automatically attach it
+ // to every log record written through the logger
+ m_remote_addr = m_logger.add_attribute("RemoteAddress",
+ attrs::constant< std::string >(remote_addr)).first;
+
+ // The straightforward way of logging
+ if (logging::record rec = m_logger.open_record())
+ {
+ rec.attribute_values().insert("Message",
+ attrs::make_attribute_value(std::string("Connection established")));
+ m_logger.push_record(boost::move(rec));
+ }
+ }
+ void on_disconnected()
+ {
+ // The simpler way of logging: the above "if" condition is wrapped into a neat macro
+ BOOST_LOG(m_logger) << "Connection shut down";
+
+ // Remove the attribute with the remote address
+ m_logger.remove_attribute(m_remote_addr);
+ }
+ void on_data_received(std::size_t size)
+ {
+ // Put the size as an additional attribute
+ // so it can be collected and accumulated later if needed.
+ // The attribute will be attached only to this log record.
+ BOOST_LOG(m_logger) << logging::add_value("ReceivedSize", size) << "Some data received";
+ }
+ void on_data_sent(std::size_t size)
+ {
+ BOOST_LOG(m_logger) << logging::add_value("SentSize", size) << "Some data sent";
+ }
+};
+//]
+
+int main(int, char*[])
+{
+ // Construct the sink
+ typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;
+ boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();
+
+ // Add a stream to write log to
+ sink->locked_backend()->add_stream(
+ boost::make_shared< std::ofstream >("sample.log"));
+
+ // Set the formatter
+ sink->set_formatter
+ (
+ expr::stream
+ << line_id
+ << ": [" << remote_address << "] "
+ << expr::if_(expr::has_attr(received_size))
+ [
+ expr::stream << "[Received: " << received_size << "] "
+ ]
+ << expr::if_(expr::has_attr(sent_size))
+ [
+ expr::stream << "[Sent: " << sent_size << "] "
+ ]
+ << expr::smessage
+ );
+
+ // Register the sink in the logging core
+ logging::core::get()->add_sink(sink);
+
+ // Register other common attributes, such as time stamp and record counter
+ logging::add_common_attributes();
+
+ // Emulate network activity
+ network_connection conn;
+
+ conn.on_connected("11.22.33.44");
+ conn.on_data_received(123);
+ conn.on_data_sent(321);
+ conn.on_disconnected();
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/sources_net_connection_chan.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/sources_net_connection_chan.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,142 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <cstddef>
+#include <string>
+#include <fstream>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/attributes/constant.hpp>
+#include <boost/log/attributes/scoped_attribute.hpp>
+#include <boost/log/sources/channel_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+#include <boost/log/utility/manipulators/add_value.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace attrs = boost::log::attributes;
+namespace keywords = boost::log::keywords;
+
+BOOST_LOG_ATTRIBUTE_KEYWORD(line_id, "LineID", unsigned int)
+BOOST_LOG_ATTRIBUTE_KEYWORD(channel, "Channel", std::string)
+BOOST_LOG_ATTRIBUTE_KEYWORD(remote_address, "RemoteAddress", std::string)
+BOOST_LOG_ATTRIBUTE_KEYWORD(received_size, "ReceivedSize", std::size_t)
+BOOST_LOG_ATTRIBUTE_KEYWORD(sent_size, "SentSize", std::size_t)
+
+//[ example_sources_network_connection_channels
+class network_connection
+{
+ src::channel_logger< > m_net, m_stat;
+ logging::attribute_set::iterator m_net_remote_addr, m_stat_remote_addr;
+
+public:
+ network_connection() :
+ // We can dump network-related messages through this logger
+ // and be able to filter them later
+ m_net(keywords::channel = "net"),
+ // We also can separate statistic records in a different channel
+ // in order to route them to a different sink
+ m_stat(keywords::channel = "stat")
+ {
+ }
+
+ void on_connected(std::string const& remote_addr)
+ {
+ // Add the remote address to both channels
+ attrs::constant< std::string > addr(remote_addr);
+ m_net_remote_addr = m_net.add_attribute("RemoteAddress", addr).first;
+ m_stat_remote_addr = m_stat.add_attribute("RemoteAddress", addr).first;
+
+ // Put message to the "net" channel
+ BOOST_LOG(m_net) << "Connection established";
+ }
+
+ void on_disconnected()
+ {
+ // Put message to the "net" channel
+ BOOST_LOG(m_net) << "Connection shut down";
+
+ // Remove the attribute with the remote address
+ m_net.remove_attribute(m_net_remote_addr);
+ m_stat.remove_attribute(m_stat_remote_addr);
+ }
+
+ void on_data_received(std::size_t size)
+ {
+ BOOST_LOG(m_stat) << logging::add_value("ReceivedSize", size) << "Some data received";
+ }
+
+ void on_data_sent(std::size_t size)
+ {
+ BOOST_LOG(m_stat) << logging::add_value("SentSize", size) << "Some data sent";
+ }
+};
+//]
+
+int main(int, char*[])
+{
+ // Construct the sink for the "net" channel
+ typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;
+ boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();
+
+ sink->locked_backend()->add_stream(
+ boost::make_shared< std::ofstream >("net.log"));
+
+ sink->set_formatter
+ (
+ expr::stream << line_id << ": [" << remote_address << "] " << expr::smessage
+ );
+
+ sink->set_filter(channel == "net");
+
+ logging::core::get()->add_sink(sink);
+
+ // Construct the sink for the "stat" channel
+ sink = boost::make_shared< text_sink >();
+
+ sink->locked_backend()->add_stream(
+ boost::make_shared< std::ofstream >("stat.log"));
+
+ sink->set_formatter
+ (
+ expr::stream
+ << remote_address
+ << expr::if_(expr::has_attr(received_size))
+ [
+ expr::stream << " -> " << received_size << " bytes: "
+ ]
+ << expr::if_(expr::has_attr(sent_size))
+ [
+ expr::stream << " <- " << sent_size << " bytes: "
+ ]
+ << expr::smessage
+ );
+
+ sink->set_filter(channel == "stat");
+
+ logging::core::get()->add_sink(sink);
+
+ // Register other common attributes, such as time stamp and record counter
+ logging::add_common_attributes();
+
+ // Emulate network activity
+ network_connection conn;
+
+ conn.on_connected("11.22.33.44");
+ conn.on_data_received(123);
+ conn.on_data_sent(321);
+ conn.on_disconnected();
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/sources_net_connection_dynamic_chan.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/sources_net_connection_dynamic_chan.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,140 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <cstddef>
+#include <string>
+#include <fstream>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/attributes/constant.hpp>
+#include <boost/log/attributes/scoped_attribute.hpp>
+#include <boost/log/sources/channel_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/sources/global_logger_storage.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+#include <boost/log/utility/manipulators/add_value.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace attrs = boost::log::attributes;
+namespace keywords = boost::log::keywords;
+
+BOOST_LOG_ATTRIBUTE_KEYWORD(line_id, "LineID", unsigned int)
+BOOST_LOG_ATTRIBUTE_KEYWORD(channel, "Channel", std::string)
+BOOST_LOG_ATTRIBUTE_KEYWORD(remote_address, "RemoteAddress", std::string)
+BOOST_LOG_ATTRIBUTE_KEYWORD(received_size, "ReceivedSize", std::size_t)
+BOOST_LOG_ATTRIBUTE_KEYWORD(sent_size, "SentSize", std::size_t)
+
+//[ example_sources_network_connection_dynamic_channels
+// Define a global logger
+BOOST_LOG_INLINE_GLOBAL_LOGGER_CTOR_ARGS(my_logger, src::channel_logger_mt< >, (keywords::channel = "general"))
+
+class network_connection
+{
+ std::string m_remote_addr;
+
+public:
+ void on_connected(std::string const& remote_addr)
+ {
+ m_remote_addr = remote_addr;
+
+ // Put message to the "net" channel
+ BOOST_LOG_CHANNEL(my_logger::get(), "net")
+ << logging::add_value("RemoteAddress", m_remote_addr)
+ << "Connection established";
+ }
+
+ void on_disconnected()
+ {
+ // Put message to the "net" channel
+ BOOST_LOG_CHANNEL(my_logger::get(), "net")
+ << logging::add_value("RemoteAddress", m_remote_addr)
+ << "Connection shut down";
+
+ m_remote_addr.clear();
+ }
+
+ void on_data_received(std::size_t size)
+ {
+ BOOST_LOG_CHANNEL(my_logger::get(), "stat")
+ << logging::add_value("RemoteAddress", m_remote_addr)
+ << logging::add_value("ReceivedSize", size)
+ << "Some data received";
+ }
+
+ void on_data_sent(std::size_t size)
+ {
+ BOOST_LOG_CHANNEL(my_logger::get(), "stat")
+ << logging::add_value("RemoteAddress", m_remote_addr)
+ << logging::add_value("SentSize", size)
+ << "Some data sent";
+ }
+};
+//]
+
+int main(int, char*[])
+{
+ // Construct the sink for the "net" channel
+ typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;
+ boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();
+
+ sink->locked_backend()->add_stream(
+ boost::make_shared< std::ofstream >("net.log"));
+
+ sink->set_formatter
+ (
+ expr::stream << line_id << ": [" << remote_address << "] " << expr::smessage
+ );
+
+ sink->set_filter(channel == "net");
+
+ logging::core::get()->add_sink(sink);
+
+ // Construct the sink for the "stat" channel
+ sink = boost::make_shared< text_sink >();
+
+ sink->locked_backend()->add_stream(
+ boost::make_shared< std::ofstream >("stat.log"));
+
+ sink->set_formatter
+ (
+ expr::stream
+ << remote_address
+ << expr::if_(expr::has_attr(received_size))
+ [
+ expr::stream << " -> " << received_size << " bytes: "
+ ]
+ << expr::if_(expr::has_attr(sent_size))
+ [
+ expr::stream << " <- " << sent_size << " bytes: "
+ ]
+ << expr::smessage
+ );
+
+ sink->set_filter(channel == "stat");
+
+ logging::core::get()->add_sink(sink);
+
+ // Register other common attributes, such as time stamp and record counter
+ logging::add_common_attributes();
+
+ // Emulate network activity
+ network_connection conn;
+
+ conn.on_connected("11.22.33.44");
+ conn.on_data_received(123);
+ conn.on_data_sent(321);
+ conn.on_disconnected();
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/sources_severity.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/sources_severity.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,134 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <cstddef>
+#include <string>
+#include <ostream>
+#include <fstream>
+#include <boost/move/utility.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sources/severity_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace attrs = boost::log::attributes;
+namespace keywords = boost::log::keywords;
+
+//[ example_sources_severity
+// We define our own severity levels
+enum severity_level
+{
+ normal,
+ notification,
+ warning,
+ error,
+ critical
+};
+
+void logging_function()
+{
+ // The logger implicitly adds a source-specific attribute 'Severity'
+ // of type 'severity_level' on construction
+ src::severity_logger< severity_level > slg;
+
+ BOOST_LOG_SEV(slg, normal) << "A regular message";
+ BOOST_LOG_SEV(slg, warning) << "Something bad is going on but I can handle it";
+ BOOST_LOG_SEV(slg, critical) << "Everything crumbles, shoot me now!";
+}
+//]
+
+//[ example_sources_default_severity
+void default_severity()
+{
+ // The default severity can be specified in constructor.
+ src::severity_logger< severity_level > error_lg(keywords::severity = error);
+
+ BOOST_LOG(error_lg) << "An error level log record (by default)";
+
+ // The explicitly specified level overrides the default
+ BOOST_LOG_SEV(error_lg, warning) << "A warning level log record (overrode the default)";
+}
+//]
+
+//[ example_sources_severity_manual
+void manual_logging()
+{
+ src::severity_logger< severity_level > slg;
+
+ logging::record rec = slg.open_record(keywords::severity = normal);
+ if (rec)
+ {
+ logging::record_ostream strm(rec);
+ strm << "A regular message";
+ strm.flush();
+ slg.push_record(boost::move(rec));
+ }
+}
+//]
+
+// The operator puts a human-friendly representation of the severity level to the stream
+std::ostream& operator<< (std::ostream& strm, severity_level level)
+{
+ static const char* strings[] =
+ {
+ "normal",
+ "notification",
+ "warning",
+ "error",
+ "critical"
+ };
+
+ if (static_cast< std::size_t >(level) < sizeof(strings) / sizeof(*strings))
+ strm << strings[level];
+ else
+ strm << static_cast< int >(level);
+
+ return strm;
+}
+
+void init()
+{
+ typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;
+ boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();
+
+ sink->locked_backend()->add_stream(
+ boost::make_shared< std::ofstream >("sample.log"));
+
+ sink->set_formatter
+ (
+ expr::stream
+ << expr::attr< unsigned int >("LineID")
+ << ": <" << expr::attr< severity_level >("Severity")
+ << ">\t"
+ << expr::smessage
+ );
+
+ logging::core::get()->add_sink(sink);
+
+ // Add attributes
+ logging::add_common_attributes();
+}
+
+int main(int, char*[])
+{
+ init();
+
+ logging_function();
+ default_severity();
+ manual_logging();
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/sources_severity_channel.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/sources_severity_channel.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,110 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <cstddef>
+#include <string>
+#include <ostream>
+#include <fstream>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sources/severity_channel_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/sources/global_logger_storage.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace attrs = boost::log::attributes;
+namespace keywords = boost::log::keywords;
+
+//[ example_sources_severity_channel
+enum severity_level
+{
+ normal,
+ notification,
+ warning,
+ error,
+ critical
+};
+
+typedef src::severity_channel_logger_mt<
+ severity_level, // the type of the severity level
+ std::string // the type of the channel name
+> my_logger_mt;
+
+
+BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(my_logger, my_logger_mt)
+{
+ // Specify the channel name on construction, similarly as with the channel_logger
+ return my_logger_mt(keywords::channel = "my_logger");
+}
+
+void logging_function()
+{
+ // Do logging with the severity level. The record will have both
+ // the severity level and the channel name attached.
+ BOOST_LOG_SEV(my_logger::get(), normal) << "Hello, world!";
+}
+//]
+
+// The operator puts a human-friendly representation of the severity level to the stream
+std::ostream& operator<< (std::ostream& strm, severity_level level)
+{
+ static const char* strings[] =
+ {
+ "normal",
+ "notification",
+ "warning",
+ "error",
+ "critical"
+ };
+
+ if (static_cast< std::size_t >(level) < sizeof(strings) / sizeof(*strings))
+ strm << strings[level];
+ else
+ strm << static_cast< int >(level);
+
+ return strm;
+}
+
+void init()
+{
+ typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;
+ boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();
+
+ sink->locked_backend()->add_stream(
+ boost::make_shared< std::ofstream >("sample.log"));
+
+ sink->set_formatter
+ (
+ expr::stream
+ << expr::attr< unsigned int >("LineID")
+ << ": <" << expr::attr< severity_level >("Severity")
+ << ">\t"
+ << "[" << expr::attr< std::string >("Channel") << "] "
+ << expr::smessage
+ );
+
+ logging::core::get()->add_sink(sink);
+
+ // Add attributes
+ logging::add_common_attributes();
+}
+
+int main(int, char*[])
+{
+ init();
+ logging_function();
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/tutorial_attributes.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/tutorial_attributes.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,155 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <cstddef>
+#include <string>
+#include <ostream>
+#include <fstream>
+#include <iomanip>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/attributes.hpp>
+#include <boost/log/sources/basic_logger.hpp>
+#include <boost/log/sources/severity_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/attributes/scoped_attribute.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace attrs = boost::log::attributes;
+namespace keywords = boost::log::keywords;
+
+// We define our own severity levels
+enum severity_level
+{
+ normal,
+ notification,
+ warning,
+ error,
+ critical
+};
+
+BOOST_LOG_ATTRIBUTE_KEYWORD(line_id, "LineID", unsigned int)
+BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", severity_level)
+BOOST_LOG_ATTRIBUTE_KEYWORD(tag_attr, "Tag", std::string)
+BOOST_LOG_ATTRIBUTE_KEYWORD(scope, "Scope", attrs::named_scope::value_type)
+BOOST_LOG_ATTRIBUTE_KEYWORD(timeline, "Timeline", attrs::timer::value_type)
+
+void logging_function()
+{
+ src::severity_logger< severity_level > slg;
+
+ BOOST_LOG_SEV(slg, normal) << "A regular message";
+ BOOST_LOG_SEV(slg, warning) << "Something bad is going on but I can handle it";
+ BOOST_LOG_SEV(slg, critical) << "Everything crumbles, shoot me now!";
+}
+
+//[ example_tutorial_attributes_named_scope
+void named_scope_logging()
+{
+ BOOST_LOG_NAMED_SCOPE("named_scope_logging");
+
+ src::severity_logger< severity_level > slg;
+
+ BOOST_LOG_SEV(slg, normal) << "Hello from the function named_scope_logging!";
+}
+//]
+
+//[ example_tutorial_attributes_tagged_logging
+void tagged_logging()
+{
+ src::severity_logger< severity_level > slg;
+ slg.add_attribute("Tag", attrs::constant< std::string >("My tag value"));
+
+ BOOST_LOG_SEV(slg, normal) << "Here goes the tagged record";
+}
+//]
+
+//[ example_tutorial_attributes_timed_logging
+void timed_logging()
+{
+ BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
+
+ src::severity_logger< severity_level > slg;
+ BOOST_LOG_SEV(slg, normal) << "Starting to time nested functions";
+
+ logging_function();
+
+ BOOST_LOG_SEV(slg, normal) << "Stopping to time nested functions";
+}
+//]
+
+// The operator puts a human-friendly representation of the severity level to the stream
+std::ostream& operator<< (std::ostream& strm, severity_level level)
+{
+ static const char* strings[] =
+ {
+ "normal",
+ "notification",
+ "warning",
+ "error",
+ "critical"
+ };
+
+ if (static_cast< std::size_t >(level) < sizeof(strings) / sizeof(*strings))
+ strm << strings[level];
+ else
+ strm << static_cast< int >(level);
+
+ return strm;
+}
+
+void init()
+{
+ typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;
+ boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();
+
+ sink->locked_backend()->add_stream(
+ boost::make_shared< std::ofstream >("sample.log"));
+
+ sink->set_formatter
+ (
+ expr::stream
+ << std::hex << std::setw(8) << std::setfill('0') << line_id << std::dec << std::setfill(' ')
+ << ": <" << severity << ">\t"
+ << "(" << scope << ") "
+ << expr::if_(expr::has_attr(tag_attr))
+ [
+ expr::stream << "[" << tag_attr << "] "
+ ]
+ << expr::if_(expr::has_attr(timeline))
+ [
+ expr::stream << "[" << timeline << "] "
+ ]
+ << expr::smessage
+ );
+
+ logging::core::get()->add_sink(sink);
+
+ // Add attributes
+ logging::add_common_attributes();
+ logging::core::get()->add_global_attribute("Scope", attrs::named_scope());
+}
+
+int main(int, char*[])
+{
+ init();
+
+ named_scope_logging();
+ tagged_logging();
+ timed_logging();
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/tutorial_file.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/tutorial_file.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,93 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/log/core.hpp>
+#include <boost/log/trivial.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sinks/text_file_backend.hpp>
+#include <boost/log/utility/setup/file.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+#include <boost/log/sources/severity_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace sinks = boost::log::sinks;
+namespace keywords = boost::log::keywords;
+
+#if 0
+
+//[ example_tutorial_file_simple
+void init()
+{
+ logging::add_file_log("sample.log");
+
+ logging::core::get()->set_filter
+ (
+ logging::trivial::severity >= logging::trivial::info
+ );
+}
+//]
+
+// We need this due to this bug: https://svn.boost.org/trac/boost/ticket/4416
+//[ example_tutorial_file_advanced_no_callouts
+void init()
+{
+ logging::add_file_log
+ (
+ keywords::file_name = "sample_%N.log",
+ keywords::rotation_size = 10 * 1024 * 1024,
+ keywords::time_based_rotation = sinks::file::rotation_at_time_point(0, 0, 0),
+ keywords::format = "[%TimeStamp%]: %Message%"
+ );
+
+ logging::core::get()->set_filter
+ (
+ logging::trivial::severity >= logging::trivial::info
+ );
+}
+//]
+
+#else
+
+//[ example_tutorial_file_advanced
+void init()
+{
+ logging::add_file_log
+ (
+ keywords::file_name = "sample_%N.log", /*< file name pattern >*/
+ keywords::rotation_size = 10 * 1024 * 1024, /*< rotate files every 10 MiB... >*/
+ keywords::time_based_rotation = sinks::file::rotation_at_time_point(0, 0, 0), /*< ...or at midnight >*/
+ keywords::format = "[%TimeStamp%]: %Message%" /*< log record format >*/
+ );
+
+ logging::core::get()->set_filter
+ (
+ logging::trivial::severity >= logging::trivial::info
+ );
+}
+//]
+
+#endif
+
+int main(int, char*[])
+{
+ init();
+ logging::add_common_attributes();
+
+ using namespace logging::trivial;
+ src::severity_logger< severity_level > lg;
+
+ BOOST_LOG_SEV(lg, trace) << "A trace severity message";
+ BOOST_LOG_SEV(lg, debug) << "A debug severity message";
+ BOOST_LOG_SEV(lg, info) << "An informational severity message";
+ BOOST_LOG_SEV(lg, warning) << "A warning severity message";
+ BOOST_LOG_SEV(lg, error) << "An error severity message";
+ BOOST_LOG_SEV(lg, fatal) << "A fatal severity message";
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/tutorial_file_manual.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/tutorial_file_manual.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,46 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <fstream>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/trivial.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/sources/logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace sinks = boost::log::sinks;
+
+//[ example_tutorial_file_manual
+void init()
+{
+ // Construct the sink
+ typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;
+ boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();
+
+ // Add a stream to write log to
+ sink->locked_backend()->add_stream(
+ boost::make_shared< std::ofstream >("sample.log"));
+
+ // Register the sink in the logging core
+ logging::core::get()->add_sink(sink);
+}
+//]
+
+int main(int, char*[])
+{
+ init();
+
+ src::logger lg;
+ BOOST_LOG(lg) << "Hello world!";
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/tutorial_filtering.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/tutorial_filtering.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,192 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <cstddef>
+#include <string>
+#include <ostream>
+#include <fstream>
+#include <iomanip>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/phoenix/bind.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/attributes.hpp>
+#include <boost/log/sources/basic_logger.hpp>
+#include <boost/log/sources/severity_logger.hpp>
+#include <boost/log/sources/severity_channel_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/attributes/scoped_attribute.hpp>
+#include <boost/log/utility/value_ref.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace attrs = boost::log::attributes;
+namespace keywords = boost::log::keywords;
+
+// We define our own severity levels
+enum severity_level
+{
+ normal,
+ notification,
+ warning,
+ error,
+ critical
+};
+
+// The operator puts a human-friendly representation of the severity level to the stream
+std::ostream& operator<< (std::ostream& strm, severity_level level)
+{
+ static const char* strings[] =
+ {
+ "normal",
+ "notification",
+ "warning",
+ "error",
+ "critical"
+ };
+
+ if (static_cast< std::size_t >(level) < sizeof(strings) / sizeof(*strings))
+ strm << strings[level];
+ else
+ strm << static_cast< int >(level);
+
+ return strm;
+}
+
+//[ example_tutorial_filtering
+BOOST_LOG_ATTRIBUTE_KEYWORD(line_id, "LineID", unsigned int)
+BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", severity_level)
+BOOST_LOG_ATTRIBUTE_KEYWORD(tag_attr, "Tag", std::string)
+
+void init()
+{
+ // Setup the common formatter for all sinks
+ logging::formatter fmt = expr::stream
+ << std::setw(6) << std::setfill('0') << line_id << std::setfill(' ')
+ << ": <" << severity << ">\t"
+ << expr::if_(expr::has_attr(tag_attr))
+ [
+ expr::stream << "[" << tag_attr << "] "
+ ]
+ << expr::smessage;
+
+ // Initialize sinks
+ typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;
+ boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();
+
+ sink->locked_backend()->add_stream(
+ boost::make_shared< std::ofstream >("full.log"));
+
+ sink->set_formatter(fmt);
+
+ logging::core::get()->add_sink(sink);
+
+ sink = boost::make_shared< text_sink >();
+
+ sink->locked_backend()->add_stream(
+ boost::make_shared< std::ofstream >("important.log"));
+
+ sink->set_formatter(fmt);
+
+ sink->set_filter(severity >= warning || (expr::has_attr(tag_attr) && tag_attr == "IMPORTANT_MESSAGE"));
+
+ logging::core::get()->add_sink(sink);
+
+ // Add attributes
+ logging::add_common_attributes();
+}
+//]
+
+#if 0
+
+//[ example_tutorial_filtering_bind
+bool my_filter(logging::value_ref< severity_level > const& level, logging::value_ref< std::string > const& tag)
+{
+ return level >= warning || tag == "IMPORTANT_MESSAGE";
+}
+
+void init()
+{
+ //<-
+
+ // Setup the common formatter for all sinks
+ logging::formatter fmt = expr::stream
+ << std::setw(6) << std::setfill('0') << line_id << std::setfill(' ')
+ << ": <" << severity << ">\t"
+ << expr::if_(expr::has_attr(tag_attr))
+ [
+ expr::stream << "[" << tag_attr << "] "
+ ]
+ << expr::smessage;
+
+ // Initialize sinks
+ typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;
+ boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();
+
+ sink->locked_backend()->add_stream(
+ boost::make_shared< std::ofstream >("full.log"));
+
+ sink->set_formatter(fmt);
+
+ logging::core::get()->add_sink(sink);
+
+ sink = boost::make_shared< text_sink >();
+
+ sink->locked_backend()->add_stream(
+ boost::make_shared< std::ofstream >("important.log"));
+
+ sink->set_formatter(fmt);
+
+ //->
+ // ...
+
+ namespace phoenix = boost::phoenix;
+ sink->set_filter(phoenix::bind(&my_filter, severity, tag_attr));
+
+ // ...
+ //<-
+
+ logging::core::get()->add_sink(sink);
+
+ // Add attributes
+ logging::add_common_attributes();
+
+ //->
+}
+//]
+
+#endif
+
+void logging_function()
+{
+ src::severity_logger< severity_level > slg;
+
+ BOOST_LOG_SEV(slg, normal) << "A regular message";
+ BOOST_LOG_SEV(slg, warning) << "Something bad is going on but I can handle it";
+ BOOST_LOG_SEV(slg, critical) << "Everything crumbles, shoot me now!";
+
+ {
+ BOOST_LOG_SCOPED_THREAD_TAG("Tag", "IMPORTANT_MESSAGE");
+ BOOST_LOG_SEV(slg, normal) << "An important message";
+ }
+}
+
+int main(int, char*[])
+{
+ init();
+
+ logging_function();
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/tutorial_fmt_custom.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/tutorial_fmt_custom.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,73 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <ostream>
+#include <fstream>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/optional.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/trivial.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/sources/severity_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+#include <boost/log/attributes/value_extraction.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+
+//[ example_tutorial_formatters_custom
+void my_formatter(logging::record_view const& rec, logging::formatting_ostream& strm)
+{
+ // Get the LineID attribute value and put it into the stream
+ strm << logging::extract< unsigned int >("LineID", rec) << ": ";
+
+ // The same for the severity level.
+ // The simplified syntax is possible if attribute keywords are used.
+ strm << "<" << rec[logging::trivial::severity] << "> ";
+
+ // Finally, put the record message to the stream
+ strm << rec[expr::smessage];
+}
+
+void init()
+{
+ typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;
+ boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();
+
+ sink->locked_backend()->add_stream(
+ boost::make_shared< std::ofstream >("sample.log"));
+
+ sink->set_formatter(&my_formatter);
+
+ logging::core::get()->add_sink(sink);
+}
+//]
+
+int main(int, char*[])
+{
+ init();
+ logging::add_common_attributes();
+
+ using namespace logging::trivial;
+ src::severity_logger< severity_level > lg;
+
+ BOOST_LOG_SEV(lg, trace) << "A trace severity message";
+ BOOST_LOG_SEV(lg, debug) << "A debug severity message";
+ BOOST_LOG_SEV(lg, info) << "An informational severity message";
+ BOOST_LOG_SEV(lg, warning) << "A warning severity message";
+ BOOST_LOG_SEV(lg, error) << "An error severity message";
+ BOOST_LOG_SEV(lg, fatal) << "A fatal severity message";
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/tutorial_fmt_format.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/tutorial_fmt_format.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,66 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <fstream>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/trivial.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/sources/severity_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace keywords = boost::log::keywords;
+
+//[ example_tutorial_formatters_format
+void init()
+{
+ typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;
+ boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();
+
+ sink->locked_backend()->add_stream(
+ boost::make_shared< std::ofstream >("sample.log"));
+
+ // This makes the sink to write log records that look like this:
+ // 1: <normal> A normal severity message
+ // 2: <error> An error severity message
+ sink->set_formatter
+ (
+ expr::format("%1%: <%2%> %3%")
+ % expr::attr< unsigned int >("LineID")
+ % logging::trivial::severity
+ % expr::smessage
+ );
+
+ logging::core::get()->add_sink(sink);
+}
+//]
+
+int main(int, char*[])
+{
+ init();
+ logging::add_common_attributes();
+
+ using namespace logging::trivial;
+ src::severity_logger< severity_level > lg;
+
+ BOOST_LOG_SEV(lg, trace) << "A trace severity message";
+ BOOST_LOG_SEV(lg, debug) << "A debug severity message";
+ BOOST_LOG_SEV(lg, info) << "An informational severity message";
+ BOOST_LOG_SEV(lg, warning) << "A warning severity message";
+ BOOST_LOG_SEV(lg, error) << "An error severity message";
+ BOOST_LOG_SEV(lg, fatal) << "A fatal severity message";
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/tutorial_fmt_stream.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/tutorial_fmt_stream.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,80 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/log/trivial.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sources/severity_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/utility/setup/file.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace keywords = boost::log::keywords;
+
+//[ example_tutorial_formatters_stream
+void init()
+{
+ logging::add_file_log
+ (
+ keywords::file_name = "sample_%N.log",
+ // This makes the sink to write log records that look like this:
+ // 1: <normal> A normal severity message
+ // 2: <error> An error severity message
+ keywords::format =
+ (
+ expr::stream
+ << expr::attr< unsigned int >("LineID")
+ << ": <" << logging::trivial::severity
+ << "> " << expr::smessage
+ )
+ );
+}
+//]
+
+#if 0
+
+//[ example_tutorial_formatters_stream_date_time
+void init()
+{
+ logging::add_file_log
+ (
+ keywords::file_name = "sample_%N.log",
+ // This makes the sink to write log records that look like this:
+ // YYYY-MM-DD HH:MI:SS: <normal> A normal severity message
+ // YYYY-MM-DD HH:MI:SS: <error> An error severity message
+ keywords::format =
+ (
+ expr::stream
+ << expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S")
+ << ": <" << logging::trivial::severity
+ << "> " << expr::smessage
+ )
+ );
+}
+//]
+
+#endif
+
+int main(int, char*[])
+{
+ init();
+ logging::add_common_attributes();
+
+ using namespace logging::trivial;
+ src::severity_logger< severity_level > lg;
+
+ BOOST_LOG_SEV(lg, trace) << "A trace severity message";
+ BOOST_LOG_SEV(lg, debug) << "A debug severity message";
+ BOOST_LOG_SEV(lg, info) << "An informational severity message";
+ BOOST_LOG_SEV(lg, warning) << "A warning severity message";
+ BOOST_LOG_SEV(lg, error) << "An error severity message";
+ BOOST_LOG_SEV(lg, fatal) << "A fatal severity message";
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/tutorial_fmt_stream_manual.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/tutorial_fmt_stream_manual.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,65 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <fstream>
+#include <iomanip>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/trivial.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/sources/severity_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace keywords = boost::log::keywords;
+
+//[ example_tutorial_formatters_stream_manual
+void init()
+{
+ typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;
+ boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();
+
+ sink->locked_backend()->add_stream(
+ boost::make_shared< std::ofstream >("sample.log"));
+
+ sink->set_formatter
+ (
+ expr::stream
+ // line id will be written in hex, 8-digits, zero-filled
+ << std::hex << std::setw(8) << std::setfill('0') << expr::attr< unsigned int >("LineID")
+ << ": <" << logging::trivial::severity
+ << "> " << expr::smessage
+ );
+
+ logging::core::get()->add_sink(sink);
+}
+//]
+
+int main(int, char*[])
+{
+ init();
+ logging::add_common_attributes();
+
+ using namespace logging::trivial;
+ src::severity_logger< severity_level > lg;
+
+ BOOST_LOG_SEV(lg, trace) << "A trace severity message";
+ BOOST_LOG_SEV(lg, debug) << "A debug severity message";
+ BOOST_LOG_SEV(lg, info) << "An informational severity message";
+ BOOST_LOG_SEV(lg, warning) << "A warning severity message";
+ BOOST_LOG_SEV(lg, error) << "An error severity message";
+ BOOST_LOG_SEV(lg, fatal) << "A fatal severity message";
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/tutorial_fmt_string.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/tutorial_fmt_string.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,45 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/log/trivial.hpp>
+#include <boost/log/sources/severity_logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/utility/setup/file.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace keywords = boost::log::keywords;
+
+//[ example_tutorial_formatters_string
+void init()
+{
+ logging::add_file_log
+ (
+ keywords::file_name = "sample_%N.log",
+ keywords::format = "[%TimeStamp%]: %Message%"
+ );
+}
+//]
+
+int main(int, char*[])
+{
+ init();
+ logging::add_common_attributes();
+
+ using namespace logging::trivial;
+ src::severity_logger< severity_level > lg;
+
+ BOOST_LOG_SEV(lg, trace) << "A trace severity message";
+ BOOST_LOG_SEV(lg, debug) << "A debug severity message";
+ BOOST_LOG_SEV(lg, info) << "An informational severity message";
+ BOOST_LOG_SEV(lg, warning) << "A warning severity message";
+ BOOST_LOG_SEV(lg, error) << "An error severity message";
+ BOOST_LOG_SEV(lg, fatal) << "A fatal severity message";
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/tutorial_logging.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/tutorial_logging.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,52 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/move/utility.hpp>
+#include <boost/log/sources/logger.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/sources/global_logger_storage.hpp>
+#include <boost/log/utility/setup/file.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace keywords = boost::log::keywords;
+
+BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(my_logger, src::logger_mt)
+
+void logging_function1()
+{
+ src::logger lg;
+
+//[ example_tutorial_logging_manual_logging
+ logging::record rec = lg.open_record();
+ if (rec)
+ {
+ logging::record_ostream strm(rec);
+ strm << "Hello, World!";
+ strm.flush();
+ lg.push_record(boost::move(rec));
+ }
+//]
+}
+
+void logging_function2()
+{
+ src::logger_mt& lg = my_logger::get();
+ BOOST_LOG(lg) << "Greetings from the global logger!";
+}
+
+int main(int, char*[])
+{
+ logging::add_file_log("sample.log");
+ logging::add_common_attributes();
+
+ logging_function1();
+ logging_function2();
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/tutorial_trivial.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/tutorial_trivial.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,22 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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)
+ */
+
+//[ example_tutorial_trivial
+#include <boost/log/trivial.hpp>
+
+int main(int, char*[])
+{
+ BOOST_LOG_TRIVIAL(trace) << "A trace severity message";
+ BOOST_LOG_TRIVIAL(debug) << "A debug severity message";
+ BOOST_LOG_TRIVIAL(info) << "An informational severity message";
+ BOOST_LOG_TRIVIAL(warning) << "A warning severity message";
+ BOOST_LOG_TRIVIAL(error) << "An error severity message";
+ BOOST_LOG_TRIVIAL(fatal) << "A fatal severity message";
+
+ return 0;
+}
+//]

Added: trunk/libs/log/example/doc/tutorial_trivial_flt.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/tutorial_trivial_flt.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,36 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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/log/core.hpp>
+#include <boost/log/trivial.hpp>
+#include <boost/log/expressions.hpp>
+
+namespace logging = boost::log;
+
+//[ example_tutorial_trivial_with_filtering
+void init()
+{
+ logging::core::get()->set_filter
+ (
+ logging::trivial::severity >= logging::trivial::info
+ );
+}
+
+int main(int, char*[])
+{
+ init();
+
+ BOOST_LOG_TRIVIAL(trace) << "A trace severity message";
+ BOOST_LOG_TRIVIAL(debug) << "A debug severity message";
+ BOOST_LOG_TRIVIAL(info) << "An informational severity message";
+ BOOST_LOG_TRIVIAL(warning) << "A warning severity message";
+ BOOST_LOG_TRIVIAL(error) << "An error severity message";
+ BOOST_LOG_TRIVIAL(fatal) << "A fatal severity message";
+
+ return 0;
+}
+//]

Added: trunk/libs/log/example/doc/util_dynamic_type_disp.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/util_dynamic_type_disp.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,97 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <cassert>
+#include <cstddef>
+#include <string>
+#include <iostream>
+#include <boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp>
+
+namespace logging = boost::log;
+
+// Base interface for the custom opaque value
+struct my_value_base
+{
+ virtual ~my_value_base() {}
+ virtual bool dispatch(logging::type_dispatcher& dispatcher) const = 0;
+};
+
+// A simple attribute value
+template< typename T >
+struct my_value :
+ public my_value_base
+{
+ T m_value;
+
+ explicit my_value(T const& value) : m_value(value) {}
+
+ // The function passes the contained type into the dispatcher
+ bool dispatch(logging::type_dispatcher& dispatcher) const
+ {
+ logging::type_dispatcher::callback< T > cb = dispatcher.get_callback< T >();
+ if (cb)
+ {
+ cb(m_value);
+ return true;
+ }
+ else
+ return false;
+ }
+};
+
+//[ example_util_dynamic_type_dispatcher
+// Visitor functions for the supported types
+void on_int(int const& value)
+{
+ std::cout << "Received int value = " << value << std::endl;
+}
+
+void on_double(double const& value)
+{
+ std::cout << "Received double value = " << value << std::endl;
+}
+
+void on_string(std::string const& value)
+{
+ std::cout << "Received string value = " << value << std::endl;
+}
+
+logging::dynamic_type_dispatcher disp;
+
+// The function initializes the dispatcher object
+void init_disp()
+{
+ // Register type visitors
+ disp.register_type< int >(&on_int);
+ disp.register_type< double >(&on_double);
+ disp.register_type< std::string >(&on_string);
+}
+
+// Prints the supplied value
+bool print(my_value_base const& val)
+{
+ return val.dispatch(disp);
+}
+//]
+
+int main(int, char*[])
+{
+ init_disp();
+
+ // These two attributes are supported by the dispatcher
+ bool res = print(my_value< std::string >("Hello world!"));
+ assert(res);
+
+ res = print(my_value< double >(1.2));
+ assert(res);
+
+ // This one is not
+ res = print(my_value< float >(-4.3f));
+ assert(!res);
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/util_manip_to_log.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/util_manip_to_log.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,73 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <cstddef>
+#include <iomanip>
+#include <iostream>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/utility/manipulators/to_log.hpp>
+
+namespace logging = boost::log;
+
+//[ example_utility_manipulators_to_log
+std::ostream& operator<<
+(
+ std::ostream& strm,
+ logging::to_log_manip< int > const& manip
+)
+{
+ strm << std::setw(4) << std::setfill('0') << std::hex << manip.get() << std::dec;
+ return strm;
+}
+
+void test_manip()
+{
+ std::cout << "Regular output: " << 1010 << std::endl;
+ std::cout << "Log output: " << logging::to_log(1010) << std::endl;
+}
+//]
+
+//[ example_utility_manipulators_to_log_with_tag
+struct tag_A;
+struct tag_B;
+
+std::ostream& operator<<
+(
+ std::ostream& strm,
+ logging::to_log_manip< int, tag_A > const& manip
+)
+{
+ strm << "A[" << manip.get() << "]";
+ return strm;
+}
+
+std::ostream& operator<<
+(
+ std::ostream& strm,
+ logging::to_log_manip< int, tag_B > const& manip
+)
+{
+ strm << "B[" << manip.get() << "]";
+ return strm;
+}
+
+void test_manip_with_tag()
+{
+ std::cout << "Regular output: " << 1010 << std::endl;
+ std::cout << "Log output A: " << logging::to_log< tag_A >(1010) << std::endl;
+ std::cout << "Log output B: " << logging::to_log< tag_B >(1010) << std::endl;
+}
+//]
+
+
+int main(int, char*[])
+{
+ test_manip();
+ test_manip_with_tag();
+
+ return 0;
+}

Added: trunk/libs/log/example/doc/util_static_type_disp.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/doc/util_static_type_disp.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,94 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 <cassert>
+#include <cstddef>
+#include <string>
+#include <iostream>
+#include <boost/mpl/vector.hpp>
+#include <boost/log/utility/type_dispatch/static_type_dispatcher.hpp>
+
+namespace logging = boost::log;
+
+//[ example_util_static_type_dispatcher
+// Base interface for the custom opaque value
+struct my_value_base
+{
+ virtual ~my_value_base() {}
+ virtual bool dispatch(logging::type_dispatcher& dispatcher) const = 0;
+};
+
+// A simple attribute value
+template< typename T >
+struct my_value :
+ public my_value_base
+{
+ T m_value;
+
+ explicit my_value(T const& value) : m_value(value) {}
+
+ // The function passes the contained type into the dispatcher
+ bool dispatch(logging::type_dispatcher& dispatcher) const
+ {
+ logging::type_dispatcher::callback< T > cb = dispatcher.get_callback< T >();
+ if (cb)
+ {
+ cb(m_value);
+ return true;
+ }
+ else
+ return false;
+ }
+};
+
+// Value visitor for the supported types
+struct print_visitor
+{
+ typedef void result_type;
+
+ // Implement visitation logic for all supported types
+ void operator() (int const& value) const
+ {
+ std::cout << "Received int value = " << value << std::endl;
+ }
+ void operator() (double const& value) const
+ {
+ std::cout << "Received double value = " << value << std::endl;
+ }
+ void operator() (std::string const& value) const
+ {
+ std::cout << "Received string value = " << value << std::endl;
+ }
+};
+
+// Prints the supplied value
+bool print(my_value_base const& val)
+{
+ typedef boost::mpl::vector< int, double, std::string > types;
+
+ print_visitor visitor;
+ logging::static_type_dispatcher< types > disp(visitor);
+
+ return val.dispatch(disp);
+}
+//]
+
+int main(int, char*[])
+{
+ // These two attributes are supported by the dispatcher
+ bool res = print(my_value< std::string >("Hello world!"));
+ assert(res);
+
+ res = print(my_value< double >(1.2));
+ assert(res);
+
+ // This one is not
+ res = print(my_value< float >(-4.3f));
+ assert(!res);
+
+ return 0;
+}

Added: trunk/libs/log/example/event_log/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/event_log/Jamfile.v2 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,44 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+
+import os ;
+
+project
+ : requirements
+ <link>shared
+ <logapi>unix:<define>BOOST_LOG_USE_NATIVE_SYSLOG=1
+ <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>gcc:<cxxflags>-fno-strict-aliasing # avoids strict aliasing violations in other Boost components
+ <toolset>gcc:<cxxflags>-ftemplate-depth-1024
+ <library>/boost/log//boost_log
+ <library>/boost/date_time//boost_date_time
+ <library>/boost/filesystem//boost_filesystem
+ <library>/boost/system//boost_system
+ <library>/boost/thread//boost_thread
+ <threading>multi
+ ;
+
+if [ os.name ] = "NT"
+{
+ lib event_log_messages
+ : event_log_messages.mc
+ : <linkflags>-noentry
+# <name>event_log_messages
+ ;
+
+ exe event_log
+ : main.cpp
+ : <implicit-dependency>event_log_messages
+ ;
+}

Added: trunk/libs/log/example/event_log/event_log_messages.mc
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/event_log/event_log_messages.mc 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,58 @@
+; /* --------------------------------------------------------
+; HEADER SECTION
+; */
+SeverityNames=(Debug=0x0:MY_SEVERITY_DEBUG
+ Info=0x1:MY_SEVERITY_INFO
+ Warning=0x2:MY_SEVERITY_WARNING
+ Error=0x3:MY_SEVERITY_ERROR
+ )
+
+; /* --------------------------------------------------------
+; MESSAGE DEFINITION SECTION
+; */
+
+MessageIdTypedef=WORD
+
+MessageId=0x1
+SymbolicName=MY_CATEGORY_1
+Language=English
+Category 1
+.
+
+MessageId=0x2
+SymbolicName=MY_CATEGORY_2
+Language=English
+Category 2
+.
+
+MessageId=0x3
+SymbolicName=MY_CATEGORY_3
+Language=English
+Category 3
+.
+
+MessageIdTypedef=DWORD
+
+MessageId=0x100
+Severity=Warning
+Facility=Application
+SymbolicName=LOW_DISK_SPACE_MSG
+Language=English
+The drive %1 has low free disk space. At least %2 Mb of free space is recommended.
+.
+
+MessageId=0x101
+Severity=Error
+Facility=Application
+SymbolicName=DEVICE_INACCESSIBLE_MSG
+Language=English
+The drive %1 is not accessible.
+.
+
+MessageId=0x102
+Severity=Info
+Facility=Application
+SymbolicName=SUCCEEDED_MSG
+Language=English
+Operation finished successfully in %1 seconds.
+.

Added: trunk/libs/log/example/event_log/main.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/event_log/main.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,190 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 main.cpp
+ * \author Andrey Semashev
+ * \date 16.11.2008
+ *
+ * \brief An example of logging into Windows event log.
+ *
+ * The example shows the basic usage of the Windows NT event log backend.
+ * The code defines custom severity levels, initializes the sink and a couple of
+ * attributes to test with, and writes several records at different levels.
+ * As a result the written records should appear in the Application log, and
+ * should be displayed correctly with the Windows event log viewer.
+ */
+
+#include <stdexcept>
+#include <string>
+#include <iostream>
+#include <boost/shared_ptr.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+
+#include <boost/log/common.hpp>
+#include <boost/log/attributes.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/event_log_backend.hpp>
+
+#if !defined(WIN32_LEAN_AND_MEAN)
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+#include <windows.h>
+#include "event_log_messages.h"
+
+namespace logging = boost::log;
+namespace attrs = boost::log::attributes;
+namespace src = boost::log::sources;
+namespace sinks = boost::log::sinks;
+namespace expr = boost::log::expressions;
+namespace keywords = boost::log::keywords;
+
+//[ example_sinks_event_log_severity
+// Define application-specific severity levels
+enum severity_level
+{
+ normal,
+ warning,
+ error
+};
+//]
+
+void init_logging()
+{
+ //[ example_sinks_event_log_create_backend
+ // Create an event log sink
+ boost::shared_ptr< sinks::event_log_backend > backend(
+ new sinks::event_log_backend((
+ keywords::message_file = "%SystemDir%\\event_log_messages.dll",
+ keywords::log_name = "My Application",
+ keywords::log_source = "My Source"
+ ))
+ );
+ //]
+
+ //[ example_sinks_event_log_event_composer
+ // Create an event composer. It is initialized with the event identifier mapping.
+ sinks::event_log::event_composer composer(
+ sinks::event_log::direct_event_id_mapping< int >("EventID"));
+
+ // For each event described in the message file, set up the insertion string formatters
+ composer[LOW_DISK_SPACE_MSG]
+ // the first placeholder in the message
+ // will be replaced with contents of the "Drive" attribute
+ % expr::attr< std::string >("Drive")
+ // the second placeholder in the message
+ // will be replaced with contents of the "Size" attribute
+ % expr::attr< boost::uintmax_t >("Size");
+
+ composer[DEVICE_INACCESSIBLE_MSG]
+ % expr::attr< std::string >("Drive");
+
+ composer[SUCCEEDED_MSG]
+ % expr::attr< unsigned int >("Duration");
+
+ // Then put the composer to the backend
+ backend->set_event_composer(composer);
+ //]
+
+ //[ example_sinks_event_log_mappings
+ // We'll have to map our custom levels to the event log event types
+ sinks::event_log::custom_event_type_mapping< severity_level > type_mapping("Severity");
+ type_mapping[normal] = sinks::event_log::make_event_type(MY_SEVERITY_INFO);
+ type_mapping[warning] = sinks::event_log::make_event_type(MY_SEVERITY_WARNING);
+ type_mapping[error] = sinks::event_log::make_event_type(MY_SEVERITY_ERROR);
+
+ backend->set_event_type_mapper(type_mapping);
+
+ // Same for event categories.
+ // Usually event categories can be restored by the event identifier.
+ sinks::event_log::custom_event_category_mapping< int > cat_mapping("EventID");
+ cat_mapping[LOW_DISK_SPACE_MSG] = sinks::event_log::make_event_category(MY_CATEGORY_1);
+ cat_mapping[DEVICE_INACCESSIBLE_MSG] = sinks::event_log::make_event_category(MY_CATEGORY_2);
+ cat_mapping[SUCCEEDED_MSG] = sinks::event_log::make_event_category(MY_CATEGORY_3);
+
+ backend->set_event_category_mapper(cat_mapping);
+ //]
+
+ //[ example_sinks_event_log_register_sink
+ // Create the frontend for the sink
+ boost::shared_ptr< sinks::synchronous_sink< sinks::event_log_backend > > sink(
+ new sinks::synchronous_sink< sinks::event_log_backend >(backend));
+
+ // Set up filter to pass only records that have the necessary attribute
+ sink->set_filter(expr::has_attr< int >("EventID"));
+
+ logging::core::get()->add_sink(sink);
+ //]
+}
+
+//[ example_sinks_event_log_facilities
+BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(event_logger, src::severity_logger_mt< severity_level >)
+
+// The function raises an event of the disk space depletion
+void announce_low_disk_space(std::string const& drive, boost::uintmax_t size)
+{
+ BOOST_LOG_SCOPED_THREAD_TAG("EventID", (int)LOW_DISK_SPACE_MSG);
+ BOOST_LOG_SCOPED_THREAD_TAG("Drive", drive);
+ BOOST_LOG_SCOPED_THREAD_TAG("Size", size);
+ // Since this record may get accepted by other sinks,
+ // this message is not completely useless
+ BOOST_LOG_SEV(event_logger::get(), warning) << "Low disk " << drive
+ << " space, " << size << " Mb is recommended";
+}
+
+// The function raises an event of inaccessible disk drive
+void announce_device_inaccessible(std::string const& drive)
+{
+ BOOST_LOG_SCOPED_THREAD_TAG("EventID", (int)DEVICE_INACCESSIBLE_MSG);
+ BOOST_LOG_SCOPED_THREAD_TAG("Drive", drive);
+ BOOST_LOG_SEV(event_logger::get(), error) << "Cannot access drive " << drive;
+}
+
+// The structure is an activity guard that will emit an event upon the activity completion
+struct activity_guard
+{
+ activity_guard()
+ {
+ // Add a stop watch attribute to measure the activity duration
+ m_it = event_logger::get().add_attribute("Duration", attrs::timer()).first;
+ }
+ ~activity_guard()
+ {
+ BOOST_LOG_SCOPED_THREAD_TAG("EventID", (int)SUCCEEDED_MSG);
+ BOOST_LOG_SEV(event_logger::get(), normal) << "Activity ended";
+ event_logger::get().remove_attribute(m_it);
+ }
+
+private:
+ logging::attribute_set::iterator m_it;
+};
+//]
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ // Initialize the library
+ init_logging();
+
+ // Make some events
+ {
+ activity_guard activity;
+
+ announce_low_disk_space("C:", 2 * 1024 * 1024);
+ announce_device_inaccessible("D:");
+ }
+
+ return 0;
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "FAILURE: " << e.what() << std::endl;
+ return 1;
+ }
+}

Added: trunk/libs/log/example/keywords/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/keywords/Jamfile.v2 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,33 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+
+project
+ : requirements
+ <link>shared:<define>BOOST_ALL_DYN_LINK
+ <logapi>unix:<define>BOOST_LOG_USE_NATIVE_SYSLOG=1
+ <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>gcc:<cxxflags>-fno-strict-aliasing # avoids strict aliasing violations in other Boost components
+ <toolset>gcc:<cxxflags>-ftemplate-depth-1024
+ <library>/boost/log//boost_log
+ <library>/boost/log//boost_log_setup
+ <library>/boost/date_time//boost_date_time
+ <library>/boost/filesystem//boost_filesystem
+ <library>/boost/system//boost_system
+ <threading>single:<define>BOOST_LOG_NO_THREADS
+ <threading>multi:<library>/boost/thread//boost_thread
+ ;
+
+exe keywords
+ : main.cpp
+ ;

Added: trunk/libs/log/example/keywords/main.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/keywords/main.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,133 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 main.cpp
+ * \author Andrey Semashev
+ * \date 01.12.2012
+ *
+ * \brief An example of using attribute keywords.
+ */
+
+// #define BOOST_LOG_USE_CHAR
+// #define BOOST_ALL_DYN_LINK 1
+// #define BOOST_LOG_DYN_LINK 1
+
+#include <iostream>
+
+#include <boost/log/common.hpp>
+#include <boost/log/expressions.hpp>
+
+#include <boost/log/utility/setup/file.hpp>
+#include <boost/log/utility/setup/console.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+
+#include <boost/log/attributes/timer.hpp>
+#include <boost/log/attributes/named_scope.hpp>
+
+#include <boost/log/sources/logger.hpp>
+
+#include <boost/log/support/date_time.hpp>
+
+namespace logging = boost::log;
+namespace sinks = boost::log::sinks;
+namespace attrs = boost::log::attributes;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace keywords = boost::log::keywords;
+
+using boost::shared_ptr;
+
+// Here we define our application severity levels.
+enum severity_level
+{
+ normal,
+ notification,
+ warning,
+ error,
+ critical
+};
+
+// The formatting logic for the severity level
+template< typename CharT, typename TraitsT >
+inline std::basic_ostream< CharT, TraitsT >& operator<< (
+ std::basic_ostream< CharT, TraitsT >& strm, severity_level lvl)
+{
+ static const char* const str[] =
+ {
+ "normal",
+ "notification",
+ "warning",
+ "error",
+ "critical"
+ };
+ if (static_cast< std::size_t >(lvl) < (sizeof(str) / sizeof(*str)))
+ strm << str[lvl];
+ else
+ strm << static_cast< int >(lvl);
+ return strm;
+}
+
+// Declare attribute keywords
+BOOST_LOG_ATTRIBUTE_KEYWORD(_severity, "Severity", severity_level)
+BOOST_LOG_ATTRIBUTE_KEYWORD(_timestamp, "TimeStamp", boost::posix_time::ptime)
+BOOST_LOG_ATTRIBUTE_KEYWORD(_uptime, "Uptime", attrs::timer::value_type)
+BOOST_LOG_ATTRIBUTE_KEYWORD(_scope, "Scope", attrs::named_scope::value_type)
+
+int main(int argc, char* argv[])
+{
+ // This is a simple tutorial/example of Boost.Log usage
+
+ // The first thing we have to do to get using the library is
+ // to set up the logging sinks - i.e. where the logs will be written to.
+ logging::add_console_log(std::clog, keywords::format = "%TimeStamp%: %_%");
+
+ // One can also use lambda expressions to setup filters and formatters
+ logging::add_file_log
+ (
+ "sample.log",
+ keywords::filter = _severity >= warning,
+ keywords::format = expr::stream
+ << expr::format_date_time(_timestamp, "%Y-%m-%d, %H:%M:%S.%f")
+ << " [" << expr::format_date_time(_uptime, "%O:%M:%S")
+ << "] [" << expr::format_named_scope(_scope, keywords::format = "%n (%f:%l)")
+ << "] <" << _severity
+ << "> " << expr::message
+/*
+ keywords::format = expr::format("%1% [%2%] [%3%] <%4%> %5%")
+ % expr::format_date_time(_timestamp, "%Y-%m-%d, %H:%M:%S.%f")
+ % expr::format_date_time(_uptime, "%O:%M:%S")
+ % expr::format_named_scope(_scope, keywords::format = "%n (%f:%l)")
+ % _severity
+ % expr::message
+*/
+ );
+
+ // Also let's add some commonly used attributes, like timestamp and record counter.
+ logging::add_common_attributes();
+ logging::core::get()->add_thread_attribute("Scope", attrs::named_scope());
+
+ BOOST_LOG_FUNCTION();
+
+ // Now our logs will be written both to the console and to the file.
+ // Let's do a quick test and output something. We have to create a logger for this.
+ src::logger lg;
+
+ // And output...
+ BOOST_LOG(lg) << "Hello, World!";
+
+ // Now, let's try logging with severity
+ src::severity_logger< severity_level > slg;
+
+ // Let's pretend we also want to profile our code, so add a special timer attribute.
+ slg.add_attribute("Uptime", attrs::timer());
+
+ BOOST_LOG_SEV(slg, normal) << "A normal severity message, will not pass to the file";
+ BOOST_LOG_SEV(slg, warning) << "A warning severity message, will pass to the file";
+ BOOST_LOG_SEV(slg, error) << "An error severity message, will pass to the file";
+
+ return 0;
+}

Added: trunk/libs/log/example/multiple_files/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/multiple_files/Jamfile.v2 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,32 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+
+project
+ : requirements
+ <link>shared:<define>BOOST_ALL_DYN_LINK
+ <logapi>unix:<define>BOOST_LOG_USE_NATIVE_SYSLOG=1
+ <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>gcc:<cxxflags>-fno-strict-aliasing # avoids strict aliasing violations in other Boost components
+ <toolset>gcc:<cxxflags>-ftemplate-depth-1024
+ <library>/boost/log//boost_log
+ <library>/boost/date_time//boost_date_time
+ <library>/boost/filesystem//boost_filesystem
+ <library>/boost/system//boost_system
+ <library>/boost/thread//boost_thread
+ <threading>multi
+ ;
+
+exe multiple_files
+ : main.cpp
+ ;

Added: trunk/libs/log/example/multiple_files/main.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/multiple_files/main.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,105 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 main.cpp
+ * \author Andrey Semashev
+ * \date 26.04.2008
+ *
+ * \brief This example shows how to perform logging to several files simultaneously,
+ * with files being created on an attribute value basis - thread identifier in this case.
+ * In the example the application creates a number of threads and registers thread
+ * identifiers as attributes. Every thread performs logging, and the sink separates
+ * log records from different threads into different files.
+ */
+
+// #define BOOST_LOG_DYN_LINK 1
+
+#include <stdexcept>
+#include <string>
+#include <iostream>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+#include <boost/log/common.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/attributes.hpp>
+#include <boost/log/sources/logger.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/text_multifile_backend.hpp>
+
+namespace logging = boost::log;
+namespace attrs = boost::log::attributes;
+namespace src = boost::log::sources;
+namespace sinks = boost::log::sinks;
+namespace expr = boost::log::expressions;
+namespace keywords = boost::log::keywords;
+
+using boost::shared_ptr;
+
+enum
+{
+ THREAD_COUNT = 5,
+ LOG_RECORDS_TO_WRITE = 10
+};
+
+// Global logger declaration
+BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(my_logger, src::logger_mt)
+
+// This function is executed in a separate thread
+void thread_foo()
+{
+ BOOST_LOG_SCOPED_THREAD_TAG("ThreadID", boost::this_thread::get_id());
+ for (unsigned int i = 0; i < LOG_RECORDS_TO_WRITE; ++i)
+ {
+ BOOST_LOG(my_logger::get()) << "Log record " << i;
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ // Create a text file sink
+ typedef sinks::synchronous_sink< sinks::text_multifile_backend > file_sink;
+ shared_ptr< file_sink > sink(new file_sink);
+
+ // Set up how the file names will be generated
+ sink->locked_backend()->set_file_name_composer(sinks::file::as_file_name_composer(
+ expr::stream << "logs/" << expr::attr< boost::thread::id >("ThreadID") << ".log"));
+
+ // Set the log record formatter
+ sink->set_formatter
+ (
+ expr::format("%1%: [%2%] - %3%")
+ % expr::attr< unsigned int >("RecordID")
+ % expr::attr< boost::posix_time::ptime >("TimeStamp")
+ % expr::smessage
+ );
+
+ // Add it to the core
+ logging::core::get()->add_sink(sink);
+
+ // Add some attributes too
+ logging::core::get()->add_global_attribute("TimeStamp", attrs::local_clock());
+ logging::core::get()->add_global_attribute("RecordID", attrs::counter< unsigned int >());
+
+ // Create threads and make some logs
+ boost::thread_group threads;
+ for (unsigned int i = 0; i < THREAD_COUNT; ++i)
+ threads.create_thread(&thread_foo);
+
+ threads.join_all();
+
+ return 0;
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "FAILURE: " << e.what() << std::endl;
+ return 1;
+ }
+}

Added: trunk/libs/log/example/multiple_threads/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/multiple_threads/Jamfile.v2 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,32 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+
+project
+ : requirements
+ <link>shared:<define>BOOST_ALL_DYN_LINK
+ <logapi>unix:<define>BOOST_LOG_USE_NATIVE_SYSLOG=1
+ <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>gcc:<cxxflags>-fno-strict-aliasing # avoids strict aliasing violations in other Boost components
+ <toolset>gcc:<cxxflags>-ftemplate-depth-1024
+ <library>/boost/log//boost_log
+ <library>/boost/date_time//boost_date_time
+ <library>/boost/filesystem//boost_filesystem
+ <library>/boost/system//boost_system
+ <library>/boost/thread//boost_thread
+ <threading>multi
+ ;
+
+exe multiple_threads
+ : main.cpp
+ ;

Added: trunk/libs/log/example/multiple_threads/main.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/multiple_threads/main.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,116 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 main.cpp
+ * \author Andrey Semashev
+ * \date 10.06.2008
+ *
+ * \brief An example of logging in multiple threads.
+ * See the library tutorial for expanded comments on this code.
+ * It may also be worthwhile reading the Wiki requirements page:
+ * http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Boost.Logging
+ */
+
+// #define BOOST_LOG_DYN_LINK 1
+
+#include <stdexcept>
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <boost/ref.hpp>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/barrier.hpp>
+
+#include <boost/log/common.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/attributes.hpp>
+#include <boost/log/sinks.hpp>
+#include <boost/log/sources/logger.hpp>
+#include <boost/log/utility/empty_deleter.hpp>
+
+namespace logging = boost::log;
+namespace attrs = boost::log::attributes;
+namespace src = boost::log::sources;
+namespace sinks = boost::log::sinks;
+namespace expr = boost::log::expressions;
+namespace keywords = boost::log::keywords;
+
+using boost::shared_ptr;
+
+enum
+{
+ LOG_RECORDS_TO_WRITE = 10000,
+ THREAD_COUNT = 2
+};
+
+BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(test_lg, src::logger_mt)
+
+//! This function is executed in multiple threads
+void thread_fun(boost::barrier& bar)
+{
+ // Wait until all threads are created
+ bar.wait();
+
+ // Now, do some logging
+ for (unsigned int i = 0; i < LOG_RECORDS_TO_WRITE; ++i)
+ {
+ BOOST_LOG(test_lg::get()) << "Log record " << i;
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ // Open a rotating text file
+ shared_ptr< std::ostream > strm(new std::ofstream("test.log"));
+ if (!strm->good())
+ throw std::runtime_error("Failed to open a text log file");
+
+ // Create a text file sink
+ shared_ptr< sinks::synchronous_sink< sinks::text_ostream_backend > > sink(
+ new sinks::synchronous_sink< sinks::text_ostream_backend >);
+
+ sink->locked_backend()->add_stream(strm);
+
+ sink->set_formatter
+ (
+ expr::format("%1%: [%2%] [%3%] - %4%")
+ % expr::attr< unsigned int >("RecordID")
+ % expr::attr< boost::posix_time::ptime >("TimeStamp")
+ % expr::attr< attrs::current_thread_id::value_type >("ThreadID")
+ % expr::smessage
+ );
+
+ // Add it to the core
+ logging::core::get()->add_sink(sink);
+
+ // Add some attributes too
+ logging::core::get()->add_global_attribute("TimeStamp", attrs::local_clock());
+ logging::core::get()->add_global_attribute("RecordID", attrs::counter< unsigned int >());
+ logging::core::get()->add_global_attribute("ThreadID", attrs::current_thread_id());
+
+ // Create logging threads
+ boost::barrier bar(THREAD_COUNT);
+ boost::thread_group threads;
+ for (unsigned int i = 0; i < THREAD_COUNT; ++i)
+ threads.create_thread(boost::bind(&thread_fun, boost::ref(bar)));
+
+ // Wait until all action ends
+ threads.join_all();
+
+ return 0;
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "FAILURE: " << e.what() << std::endl;
+ return 1;
+ }
+}

Added: trunk/libs/log/example/native_syslog/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/native_syslog/Jamfile.v2 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,32 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+
+project
+ : requirements
+ <link>shared:<define>BOOST_ALL_DYN_LINK
+ <logapi>unix:<define>BOOST_LOG_USE_NATIVE_SYSLOG=1
+ <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>gcc:<cxxflags>-fno-strict-aliasing # avoids strict aliasing violations in other Boost components
+ <toolset>gcc:<cxxflags>-ftemplate-depth-1024
+ <library>/boost/log//boost_log
+ <library>/boost/date_time//boost_date_time
+ <library>/boost/filesystem//boost_filesystem
+ <library>/boost/system//boost_system
+ <library>/boost/thread//boost_thread
+ <threading>multi
+ ;
+
+exe native_syslog
+ : main.cpp
+ ;

Added: trunk/libs/log/example/native_syslog/main.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/native_syslog/main.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,104 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 main.cpp
+ * \author Andrey Semashev
+ * \date 07.03.2009
+ *
+ * \brief An example of logging to a syslog server (syslogd, for example).
+ *
+ * The example shows how to initialize logging to a local syslog server.
+ * The code creates a sink that will use native syslog API to emit messages.
+ */
+
+// #define BOOST_LOG_DYN_LINK 1
+
+#include <stdexcept>
+#include <string>
+#include <iostream>
+#include <boost/shared_ptr.hpp>
+
+#include <boost/log/common.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/attributes.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/syslog_backend.hpp>
+
+#if defined(BOOST_LOG_USE_NATIVE_SYSLOG)
+
+namespace logging = boost::log;
+namespace attrs = boost::log::attributes;
+namespace src = boost::log::sources;
+namespace sinks = boost::log::sinks;
+namespace expr = boost::log::expressions;
+namespace keywords = boost::log::keywords;
+
+using boost::shared_ptr;
+
+//! Define application-specific severity levels
+enum severity_levels
+{
+ normal,
+ warning,
+ error
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ // Create a syslog sink
+ shared_ptr< sinks::synchronous_sink< sinks::syslog_backend > > sink(
+ new sinks::synchronous_sink< sinks::syslog_backend >(
+ keywords::use_impl = sinks::syslog::native,
+ keywords::facility = sinks::syslog::local7));
+
+ sink->set_formatter
+ (
+ expr::format("native_syslog: %1%: %2%")
+ % expr::attr< unsigned int >("RecordID")
+ % expr::smessage
+ );
+
+ // We'll have to map our custom levels to the syslog levels
+ sinks::syslog::custom_severity_mapping< severity_levels > mapping("Severity");
+ mapping[normal] = sinks::syslog::info;
+ mapping[warning] = sinks::syslog::warning;
+ mapping[error] = sinks::syslog::critical;
+
+ sink->locked_backend()->set_severity_mapper(mapping);
+
+ // Add the sink to the core
+ logging::core::get()->add_sink(sink);
+
+ // Add some attributes too
+ logging::core::get()->add_global_attribute("RecordID", attrs::counter< unsigned int >());
+
+ // Do some logging
+ src::severity_logger< severity_levels > lg(keywords::severity = normal);
+ BOOST_LOG_SEV(lg, normal) << "A syslog record with normal level";
+ BOOST_LOG_SEV(lg, warning) << "A syslog record with warning level";
+ BOOST_LOG_SEV(lg, error) << "A syslog record with error level";
+
+ return 0;
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "FAILURE: " << e.what() << std::endl;
+ return 1;
+ }
+}
+
+#else // defined(BOOST_LOG_USE_NATIVE_SYSLOG)
+
+int main (int, char*[])
+{
+ std::cout << "Native syslog API is not supported on this platform" << std::endl;
+ return 0;
+}
+
+#endif // defined(BOOST_LOG_USE_NATIVE_SYSLOG)

Added: trunk/libs/log/example/rotating_file/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/rotating_file/Jamfile.v2 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,32 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+
+project
+ : requirements
+ <link>shared:<define>BOOST_ALL_DYN_LINK
+ <logapi>unix:<define>BOOST_LOG_USE_NATIVE_SYSLOG=1
+ <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>gcc:<cxxflags>-fno-strict-aliasing # avoids strict aliasing violations in other Boost components
+ <toolset>gcc:<cxxflags>-ftemplate-depth-1024
+ <library>/boost/log//boost_log
+ <library>/boost/date_time//boost_date_time
+ <library>/boost/filesystem//boost_filesystem
+ <library>/boost/system//boost_system
+ <library>/boost/thread//boost_thread
+ <threading>multi
+ ;
+
+exe rotating_file
+ : main.cpp
+ ;

Added: trunk/libs/log/example/rotating_file/main.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/rotating_file/main.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,94 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 main.cpp
+ * \author Andrey Semashev
+ * \date 26.04.2008
+ *
+ * \brief An example of logging into a rotating text file.
+ * See the library tutorial for expanded comments on this code.
+ * It may also be worthwhile reading the Wiki requirements page:
+ * http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Boost.Logging
+ */
+
+// #define BOOST_LOG_DYN_LINK 1
+
+#include <stdexcept>
+#include <string>
+#include <iostream>
+#include <boost/shared_ptr.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+#include <boost/log/common.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/attributes.hpp>
+#include <boost/log/sources/logger.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/text_file_backend.hpp>
+
+namespace logging = boost::log;
+namespace attrs = boost::log::attributes;
+namespace src = boost::log::sources;
+namespace sinks = boost::log::sinks;
+namespace expr = boost::log::expressions;
+namespace keywords = boost::log::keywords;
+
+using boost::shared_ptr;
+
+enum { LOG_RECORDS_TO_WRITE = 10000 };
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ // Create a text file sink
+ typedef sinks::synchronous_sink< sinks::text_file_backend > file_sink;
+ shared_ptr< file_sink > sink(new file_sink(
+ keywords::file_name = "%Y%m%d_%H%M%S_%5N.log", // file name pattern
+ keywords::rotation_size = 16384 // rotation size, in characters
+ ));
+
+ // Set up where the rotated files will be stored
+ sink->locked_backend()->set_file_collector(sinks::file::make_collector(
+ keywords::target = "logs", // where to store rotated files
+ keywords::max_size = 16 * 1024 * 1024, // maximum total size of the stored files, in bytes
+ keywords::min_free_space = 100 * 1024 * 1024 // minimum free space on the drive, in bytes
+ ));
+
+ // Upon restart, scan the target directory for files matching the file_name pattern
+ sink->locked_backend()->scan_for_files();
+
+ sink->set_formatter
+ (
+ expr::format("%1%: [%2%] - %3%")
+ % expr::attr< unsigned int >("RecordID")
+ % expr::attr< boost::posix_time::ptime >("TimeStamp")
+ % expr::smessage
+ );
+
+ // Add it to the core
+ logging::core::get()->add_sink(sink);
+
+ // Add some attributes too
+ logging::core::get()->add_global_attribute("TimeStamp", attrs::local_clock());
+ logging::core::get()->add_global_attribute("RecordID", attrs::counter< unsigned int >());
+
+ // Do some logging
+ src::logger lg;
+ for (unsigned int i = 0; i < LOG_RECORDS_TO_WRITE; ++i)
+ {
+ BOOST_LOG(lg) << "Some log record";
+ }
+
+ return 0;
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "FAILURE: " << e.what() << std::endl;
+ return 1;
+ }
+}

Added: trunk/libs/log/example/settings_file/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/settings_file/Jamfile.v2 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,33 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+
+project
+ : requirements
+ <link>shared:<define>BOOST_ALL_DYN_LINK
+ <logapi>unix:<define>BOOST_LOG_USE_NATIVE_SYSLOG=1
+ <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>gcc:<cxxflags>-fno-strict-aliasing # avoids strict aliasing violations in other Boost components
+ <toolset>gcc:<cxxflags>-ftemplate-depth-1024
+ <library>/boost/log//boost_log
+ <library>/boost/log//boost_log_setup
+ <library>/boost/date_time//boost_date_time
+ <library>/boost/filesystem//boost_filesystem
+ <library>/boost/system//boost_system
+ <threading>single:<define>BOOST_LOG_NO_THREADS
+ <threading>multi:<library>/boost/thread//boost_thread
+ ;
+
+exe settings_file
+ : main.cpp
+ ;

Added: trunk/libs/log/example/settings_file/main.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/settings_file/main.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,90 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 main.cpp
+ * \author Andrey Semashev
+ * \date 26.04.2008
+ *
+ * \brief An example of initializing the library from a settings file.
+ * See the library tutorial for expanded comments on this code.
+ * It may also be worthwhile reading the Wiki requirements page:
+ * http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Boost.Logging
+ */
+
+// #define BOOST_ALL_DYN_LINK 1
+
+#include <exception>
+#include <string>
+#include <iostream>
+#include <fstream>
+
+#include <boost/log/common.hpp>
+#include <boost/log/attributes.hpp>
+#include <boost/log/utility/setup/from_stream.hpp>
+
+namespace logging = boost::log;
+namespace attrs = boost::log::attributes;
+namespace src = boost::log::sources;
+
+using boost::shared_ptr;
+
+// Here we define our application severity levels.
+enum severity_level
+{
+ normal,
+ notification,
+ warning,
+ error,
+ critical
+};
+
+// Global logger declaration
+BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(test_lg, src::severity_logger< >)
+
+void try_logging()
+{
+ src::severity_logger< >& lg = test_lg::get();
+ BOOST_LOG_SEV(lg, normal) << "This is a normal severity record";
+ BOOST_LOG_SEV(lg, notification) << "This is a notification severity record";
+ BOOST_LOG_SEV(lg, warning) << "This is a warning severity record";
+ BOOST_LOG_SEV(lg, error) << "This is a error severity record";
+ BOOST_LOG_SEV(lg, critical) << "This is a critical severity record";
+}
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ // Open the file
+ std::ifstream settings("settings.txt");
+ if (!settings.is_open())
+ {
+ std::cout << "Could not open settings.txt file" << std::endl;
+ return 1;
+ }
+
+ // Read the settings and initialize logging library
+ logging::init_from_stream(settings);
+
+ // Add some attributes
+ logging::core::get()->add_global_attribute("TimeStamp", attrs::local_clock());
+
+ // Try logging
+ try_logging();
+
+ // Now enable tagging and try again
+ BOOST_LOG_SCOPED_THREAD_TAG("Tag", "TAGGED");
+ try_logging();
+
+ return 0;
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "FAILURE: " << e.what() << std::endl;
+ return 1;
+ }
+}

Added: trunk/libs/log/example/settings_file/settings.txt
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/settings_file/settings.txt 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,25 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+
+[Core]
+
+Filter="%Severity% >= 2"
+
+
+[Sinks.1]
+
+Destination=Console
+Format="%TimeStamp% *** %Message%"
+Filter="%Tag% | %Severity% > 3"
+
+
+[Sinks.2]
+
+Destination=TextFile
+FileName=test.log
+AutoFlush=true
+Format="[%TimeStamp%] %Tag% %Message%"

Added: trunk/libs/log/example/settings_file_formatter_factory/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/settings_file_formatter_factory/Jamfile.v2 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,34 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+
+project
+ : requirements
+ <link>shared:<define>BOOST_ALL_DYN_LINK
+ <logapi>unix:<define>BOOST_LOG_USE_NATIVE_SYSLOG=1
+ <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>gcc:<cxxflags>-fno-strict-aliasing # avoids strict aliasing violations in other Boost components
+ <toolset>gcc:<cxxflags>-ftemplate-depth-1024
+ <library>/boost/log//boost_log
+ <library>/boost/log//boost_log_setup
+ <library>/boost/date_time//boost_date_time
+ <library>/boost/filesystem//boost_filesystem
+ <library>/boost/system//boost_system
+ <threading>single:<define>BOOST_LOG_NO_THREADS
+ <threading>multi:<library>/boost/thread//boost_thread
+ ;
+
+exe settings_file_formatter_factory
+ : main.cpp
+ ;
+

Added: trunk/libs/log/example/settings_file_formatter_factory/main.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/settings_file_formatter_factory/main.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,145 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 main.cpp
+ * \author Andrey Semashev
+ * \date 12.05.2010
+ *
+ * \brief An example of initializing the library from a settings file,
+ * with a custom formatter for an attribute.
+ */
+
+// #define BOOST_ALL_DYN_LINK 1
+
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <stdexcept>
+#include <boost/ref.hpp>
+#include <boost/bind.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/common.hpp>
+#include <boost/log/attributes.hpp>
+#include <boost/log/core/record.hpp>
+#include <boost/log/attributes/value_visitation.hpp>
+#include <boost/log/utility/setup/from_stream.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+#include <boost/log/utility/setup/formatter_parser.hpp>
+
+namespace logging = boost::log;
+namespace attrs = boost::log::attributes;
+namespace src = boost::log::sources;
+
+enum severity_level
+{
+ normal,
+ notification,
+ warning,
+ error,
+ critical
+};
+
+BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(test_lg, src::severity_logger< >)
+
+//! Our custom formatter for the scope list
+struct scope_list_formatter
+{
+ typedef void result_type;
+ typedef attrs::named_scope::value_type scope_stack;
+
+ explicit scope_list_formatter(logging::attribute_name const& name) :
+ name_(name)
+ {
+ }
+ void operator()(logging::record_view const& rec, logging::formatting_ostream& strm) const
+ {
+ // We need to acquire the attribute value from the log record
+ logging::visit< scope_stack >
+ (
+ name_,
+ rec.attribute_values(),
+ boost::bind(&scope_list_formatter::format, _1, boost::ref(strm))
+ );
+ }
+
+private:
+ //! This is where our custom formatting takes place
+ static void format(scope_stack const& scopes, logging::formatting_ostream& strm)
+ {
+ scope_stack::const_iterator it = scopes.begin(), end = scopes.end();
+ for (; it != end; ++it)
+ {
+ strm << "\t" << it->scope_name << " [" << it->file_name << ":" << it->line << "]\n";
+ }
+ }
+
+private:
+ logging::attribute_name name_;
+};
+
+class my_scopes_formatter_factory :
+ public logging::formatter_factory< char >
+{
+public:
+ /*!
+ * This function creates a formatter for the MyScopes attribute.
+ * It effectively associates the attribute with the scope_list_formatter class
+ */
+ formatter_type create_formatter(
+ logging::attribute_name const& attr_name, args_map const& args)
+ {
+ return formatter_type(scope_list_formatter(attr_name));
+ }
+};
+
+//! The function initializes the logging library
+void init_logging()
+{
+ // First thing - register the custom formatter for MyScopes
+ logging::register_formatter_factory("MyScopes", boost::make_shared< my_scopes_formatter_factory >());
+
+ // Then load the settings from the file
+ std::ifstream settings("settings.txt");
+ if (!settings.is_open())
+ throw std::runtime_error("Could not open settings.txt file");
+ logging::init_from_stream(settings);
+
+ // Add some attributes
+ logging::add_common_attributes();
+
+ logging::core::get()->add_global_attribute("MyScopes", attrs::named_scope());
+}
+
+//! The function tests logging
+void try_logging()
+{
+ BOOST_LOG_FUNCTION();
+
+ src::severity_logger< >& lg = test_lg::get();
+
+ BOOST_LOG_SEV(lg, critical) << "This is a critical severity record";
+
+ BOOST_LOG_NAMED_SCOPE("random name");
+ BOOST_LOG_SEV(lg, error) << "This is a error severity record";
+}
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ init_logging();
+ try_logging();
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "FAILURE: " << e.what() << std::endl;
+ return -1;
+ }
+
+ return 0;
+}

Added: trunk/libs/log/example/settings_file_formatter_factory/settings.txt
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/settings_file_formatter_factory/settings.txt 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,13 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+
+[Sinks.TextFileSettings]
+Destination=TextFile
+FileName=test.log
+AutoFlush=true
+Format="[%TimeStamp%] [%Severity%]\n%MyScopes%\n\t:: %Message%"
+Asynchronous=false

Added: trunk/libs/log/example/syslog/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/syslog/Jamfile.v2 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,32 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+
+project
+ : requirements
+ <link>shared:<define>BOOST_ALL_DYN_LINK
+ <logapi>unix:<define>BOOST_LOG_USE_NATIVE_SYSLOG=1
+ <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>gcc:<cxxflags>-fno-strict-aliasing # avoids strict aliasing violations in other Boost components
+ <toolset>gcc:<cxxflags>-ftemplate-depth-1024
+ <library>/boost/log//boost_log
+ <library>/boost/date_time//boost_date_time
+ <library>/boost/filesystem//boost_filesystem
+ <library>/boost/system//boost_system
+ <library>/boost/thread//boost_thread
+ <threading>multi
+ ;
+
+exe syslog
+ : main.cpp
+ ;

Added: trunk/libs/log/example/syslog/main.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/syslog/main.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,93 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 main.cpp
+ * \author Andrey Semashev
+ * \date 07.03.2009
+ *
+ * \brief An example of logging to a syslog server (syslogd, for example).
+ *
+ * The example shows how to initialize logging to a remote syslog server.
+ * The code creates a sink that will send syslog messages to local port 514.
+ */
+
+// #define BOOST_LOG_DYN_LINK 1
+
+#include <stdexcept>
+#include <string>
+#include <iostream>
+#include <boost/shared_ptr.hpp>
+
+#include <boost/log/common.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/attributes.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/syslog_backend.hpp>
+
+namespace logging = boost::log;
+namespace attrs = boost::log::attributes;
+namespace src = boost::log::sources;
+namespace sinks = boost::log::sinks;
+namespace expr = boost::log::expressions;
+namespace keywords = boost::log::keywords;
+
+using boost::shared_ptr;
+
+//! Define application-specific severity levels
+enum severity_levels
+{
+ normal,
+ warning,
+ error
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ // Create a syslog sink
+ shared_ptr< sinks::synchronous_sink< sinks::syslog_backend > > sink(
+ new sinks::synchronous_sink< sinks::syslog_backend >());
+
+ sink->set_formatter
+ (
+ expr::format("syslog.exe: %1%: %2%")
+ % expr::attr< unsigned int >("RecordID")
+ % expr::smessage
+ );
+
+ // We'll have to map our custom levels to the syslog levels
+ sinks::syslog::custom_severity_mapping< severity_levels > mapping("Severity");
+ mapping[normal] = sinks::syslog::info;
+ mapping[warning] = sinks::syslog::warning;
+ mapping[error] = sinks::syslog::critical;
+
+ sink->locked_backend()->set_severity_mapper(mapping);
+
+ // Set the remote address to sent syslog messages to
+ sink->locked_backend()->set_target_address("localhost");
+
+ // Add the sink to the core
+ logging::core::get()->add_sink(sink);
+
+ // Add some attributes too
+ logging::core::get()->add_global_attribute("RecordID", attrs::counter< unsigned int >());
+
+ // Do some logging
+ src::severity_logger< severity_levels > lg(keywords::severity = normal);
+ BOOST_LOG_SEV(lg, normal) << "A syslog record with normal level";
+ BOOST_LOG_SEV(lg, warning) << "A syslog record with warning level";
+ BOOST_LOG_SEV(lg, error) << "A syslog record with error level";
+
+ return 0;
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "FAILURE: " << e.what() << std::endl;
+ return 1;
+ }
+}

Added: trunk/libs/log/example/trivial/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/trivial/Jamfile.v2 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,32 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+
+project
+ : requirements
+ <link>shared:<define>BOOST_ALL_DYN_LINK
+ <logapi>unix:<define>BOOST_LOG_USE_NATIVE_SYSLOG=1
+ <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>gcc:<cxxflags>-fno-strict-aliasing # avoids strict aliasing violations in other Boost components
+ <toolset>gcc:<cxxflags>-ftemplate-depth-1024
+ <library>/boost/log//boost_log
+ <library>/boost/date_time//boost_date_time
+ <library>/boost/filesystem//boost_filesystem
+ <library>/boost/system//boost_system
+ <threading>single:<define>BOOST_LOG_NO_THREADS
+ <threading>multi:<library>/boost/thread//boost_thread
+ ;
+
+exe trivial
+ : main.cpp
+ ;

Added: trunk/libs/log/example/trivial/main.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/trivial/main.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,49 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 main.cpp
+ * \author Andrey Semashev
+ * \date 07.11.2009
+ *
+ * \brief An example of trivial logging.
+ */
+
+// #define BOOST_ALL_DYN_LINK 1
+// #define BOOST_LOG_DYN_LINK 1
+
+#include <boost/log/trivial.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+
+int main(int argc, char* argv[])
+{
+ // Trivial logging: all log records are written into a file
+ BOOST_LOG_TRIVIAL(trace) << "A trace severity message";
+ BOOST_LOG_TRIVIAL(debug) << "A debug severity message";
+ BOOST_LOG_TRIVIAL(info) << "An informational severity message";
+ BOOST_LOG_TRIVIAL(warning) << "A warning severity message";
+ BOOST_LOG_TRIVIAL(error) << "An error severity message";
+ BOOST_LOG_TRIVIAL(fatal) << "A fatal severity message";
+
+ // Filtering can also be applied
+ using namespace boost::log;
+
+ core::get()->set_filter
+ (
+ trivial::severity >= trivial::info
+ );
+
+ // Now the first two lines will not pass the filter
+ BOOST_LOG_TRIVIAL(trace) << "A trace severity message";
+ BOOST_LOG_TRIVIAL(debug) << "A debug severity message";
+ BOOST_LOG_TRIVIAL(info) << "An informational severity message";
+ BOOST_LOG_TRIVIAL(warning) << "A warning severity message";
+ BOOST_LOG_TRIVIAL(error) << "An error severity message";
+ BOOST_LOG_TRIVIAL(fatal) << "A fatal severity message";
+
+ return 0;
+}

Added: trunk/libs/log/example/wide_char/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/wide_char/Jamfile.v2 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,34 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+
+project
+ : requirements
+ <link>shared:<define>BOOST_ALL_DYN_LINK
+ <logapi>unix:<define>BOOST_LOG_USE_NATIVE_SYSLOG=1
+ <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>gcc:<cxxflags>-fno-strict-aliasing # avoids strict aliasing violations in other Boost components
+ <toolset>gcc:<cxxflags>-ftemplate-depth-1024
+ <library>/boost/log//boost_log
+ <library>/boost/log//boost_log_setup
+ <library>/boost/date_time//boost_date_time
+ <library>/boost/filesystem//boost_filesystem
+ <library>/boost/system//boost_system
+ <library>/boost/locale//boost_locale
+ <threading>single:<define>BOOST_LOG_NO_THREADS
+ <threading>multi:<library>/boost/thread//boost_thread
+ ;
+
+exe wide_char
+ : main.cpp
+ ;

Added: trunk/libs/log/example/wide_char/main.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/example/wide_char/main.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,121 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 main.cpp
+ * \author Andrey Semashev
+ * \date 01.12.2012
+ *
+ * \brief An example of wide character logging.
+ */
+
+#include <iostream>
+#include <boost/locale/generator.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+
+#include <boost/log/common.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/utility/setup/file.hpp>
+#include <boost/log/utility/setup/console.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+#include <boost/log/sources/logger.hpp>
+#include <boost/log/support/date_time.hpp>
+
+namespace logging = boost::log;
+namespace sinks = boost::log::sinks;
+namespace attrs = boost::log::attributes;
+namespace src = boost::log::sources;
+namespace expr = boost::log::expressions;
+namespace keywords = boost::log::keywords;
+
+//[ example_wide_char_severity_level_definition
+enum severity_level
+{
+ normal,
+ notification,
+ warning,
+ error,
+ critical
+};
+
+template< typename CharT, typename TraitsT >
+inline std::basic_ostream< CharT, TraitsT >& operator<< (
+ std::basic_ostream< CharT, TraitsT >& strm, severity_level lvl)
+{
+ static const char* const str[] =
+ {
+ "normal",
+ "notification",
+ "warning",
+ "error",
+ "critical"
+ };
+ if (static_cast< std::size_t >(lvl) < (sizeof(str) / sizeof(*str)))
+ strm << str[lvl];
+ else
+ strm << static_cast< int >(lvl);
+ return strm;
+}
+//]
+
+//[ example_wide_char_logging_initialization
+// Declare attribute keywords
+BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", severity_level)
+BOOST_LOG_ATTRIBUTE_KEYWORD(timestamp, "TimeStamp", boost::posix_time::ptime)
+
+void init_logging()
+{
+ boost::shared_ptr< sinks::synchronous_sink< sinks::text_file_backend > > sink = logging::add_file_log
+ (
+ "sample.log",
+ keywords::format = expr::stream
+ << expr::format_date_time(timestamp, "%Y-%m-%d, %H:%M:%S.%f")
+ << " <" << severity.or_default(normal)
+ << "> " << expr::message
+ );
+
+ // The sink will perform character code conversion as needed, according to the locale set with imbue()
+ std::locale loc = boost::locale::generator()("en_US.UTF-8");
+ sink->imbue(loc);
+
+ // Let's add some commonly used attributes, like timestamp and record counter.
+ logging::add_common_attributes();
+}
+//]
+
+//[ example_wide_char_logging
+void test_narrow_char_logging()
+{
+ // Narrow character logging still works
+ src::logger lg;
+ BOOST_LOG(lg) << "Hello, World! This is a narrow character message.";
+}
+
+void test_wide_char_logging()
+{
+ src::wlogger lg;
+ BOOST_LOG(lg) << L"Hello, World! This is a wide character message.";
+
+ // National characters are also supported
+ const wchar_t national_chars[] = { 0x041f, 0x0440, 0x0438, 0x0432, 0x0435, 0x0442, L',', L' ', 0x043c, 0x0438, 0x0440, L'!', 0 };
+ BOOST_LOG(lg) << national_chars;
+
+ // Now, let's try logging with severity
+ src::wseverity_logger< severity_level > slg;
+ BOOST_LOG_SEV(slg, normal) << L"A normal severity message, will not pass to the file";
+ BOOST_LOG_SEV(slg, warning) << L"A warning severity message, will pass to the file";
+ BOOST_LOG_SEV(slg, error) << L"An error severity message, will pass to the file";
+}
+//]
+
+int main(int argc, char* argv[])
+{
+ init_logging();
+ test_narrow_char_logging();
+ test_wide_char_logging();
+
+ return 0;
+}

Added: trunk/libs/log/index.html
==============================================================================
--- (empty file)
+++ trunk/libs/log/index.html 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,13 @@
+<html>
+<head>
+<meta http-equiv="refresh" content="0; URL=../../doc/html/log.html">
+</head>
+<body>
+Automatic redirection failed, please go to
+../../doc/html/log.html &nbsp;<hr>
+<p>&copy; Copyright Beman Dawes, 2001</p>
+<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
+file LICENSE_1_0.txt or copy
+at www.boost.org/LICENSE_1_0.txt)</p>
+</body>
+</html>

Added: trunk/libs/log/src/alignment_gap_between.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/alignment_gap_between.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,50 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 alignment_gap_between.hpp
+ * \author Andrey Semashev
+ * \date 20.11.2007
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#ifndef BOOST_LOG_ALIGNMENT_GAP_BETWEEN_HPP_INCLUDED_
+#define BOOST_LOG_ALIGNMENT_GAP_BETWEEN_HPP_INCLUDED_
+
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! The metafunction computes the minimal gap between objects t1 and t2 of types T1 and T2
+//! that would be needed to maintain the alignment of t2 if it's placed right after t1
+template< typename T1, typename T2 >
+struct alignment_gap_between
+{
+ enum _
+ {
+ T2_alignment = boost::alignment_of< T2 >::value,
+ tail_size = sizeof(T1) % T2_alignment,
+ value = tail_size > 0 ? T2_alignment - tail_size : 0
+ };
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ALIGNMENT_GAP_BETWEEN_HPP_INCLUDED_

Added: trunk/libs/log/src/atomic_queue.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/atomic_queue.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,262 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 atomic_queue.hpp
+ * \author Andrey Semashev
+ * \date 14.07.2009
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#ifndef BOOST_LOG_ATOMIC_QUEUE_HPP_INCLUDED_
+#define BOOST_LOG_ATOMIC_QUEUE_HPP_INCLUDED_
+
+#include <new>
+#include <memory>
+#include <utility>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+// Detect if atomic CAS is supported
+#if defined(__GNUC__)
+#if (__SIZEOF_POINTER__ == 1 && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1)) ||\
+ (__SIZEOF_POINTER__ == 2 && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)) ||\
+ (__SIZEOF_POINTER__ == 4 && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)) ||\
+ (__SIZEOF_POINTER__ == 8 && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)) ||\
+ (__SIZEOF_POINTER__ == 16 && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16))
+
+#define BOOST_LOG_CAS_PTR(expected, new_value, pointer)\
+ __sync_bool_compare_and_swap(pointer, expected, new_value)
+
+#endif // __SIZEOF_POINTER__ == N && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_N)
+#endif // defined(__GNUC__)
+
+// For sake of older GCC versions on Windows, this section should go after GCC
+#if !defined(BOOST_LOG_CAS_PTR) && defined(BOOST_WINDOWS)
+
+#include <boost/detail/interlocked.hpp>
+
+#define BOOST_LOG_CAS_PTR(expected, new_value, pointer)\
+ (BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER((void**)(pointer), (void*)(new_value), (void*)(expected)) == (expected))
+
+#endif // !defined(BOOST_LOG_CAS_PTR) && defined(BOOST_WINDOWS)
+
+#if !defined(BOOST_LOG_CAS_PTR)
+#include <boost/thread/locks.hpp>
+#include <boost/log/detail/spin_mutex.hpp>
+#endif // !defined(BOOST_LOG_CAS_PTR)
+
+#if defined(__GNUC__)
+#define BOOST_LOG_ALIGN(x) __attribute__((aligned(x)))
+#elif defined(_MSC_VER)
+#define BOOST_LOG_ALIGN(x) __declspec(align(x))
+#else
+#define BOOST_LOG_ALIGN(x)
+#endif
+
+#define BOOST_LOG_CPU_CACHE_LINE_SIZE 64
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+/*!
+ * A simple atomic queue class. Allows to put and eject elements from different threads concurrently.
+ */
+template< typename T, typename AllocatorT = std::allocator< T > >
+class BOOST_LOG_ALIGN(BOOST_LOG_CPU_CACHE_LINE_SIZE) atomic_queue
+{
+public:
+ typedef typename AllocatorT::BOOST_NESTED_TEMPLATE rebind< T >::other allocator;
+ typedef typename allocator::value_type value_type;
+ typedef typename allocator::reference reference;
+ typedef typename allocator::pointer pointer;
+ typedef typename allocator::const_reference const_reference;
+ typedef typename allocator::const_pointer const_pointer;
+ typedef typename allocator::difference_type difference_type;
+
+ struct node;
+ friend struct node;
+ struct node
+ {
+ node* m_pPrev;
+ node* m_pNext;
+ value_type m_Value;
+
+ node() : m_pPrev(NULL), m_pNext(NULL)
+ {
+ }
+ explicit node(value_type const& val) : m_pPrev(NULL), m_pNext(NULL), m_Value(val)
+ {
+ }
+
+ static void* operator new(std::size_t size)
+ {
+ BOOST_ASSERT(size == sizeof(node));
+ return atomic_queue::g_Allocator.allocate(1);
+ }
+ static void operator delete(void* p)
+ {
+ atomic_queue::g_Allocator.deallocate(reinterpret_cast< node* >(p), 1);
+ }
+ };
+
+private:
+ typedef typename AllocatorT::BOOST_NESTED_TEMPLATE rebind< node >::other internal_allocator;
+
+ struct implementation
+ {
+ node* m_pLast;
+#if !defined(BOOST_LOG_CAS_PTR)
+ spin_mutex m_Mutex;
+#endif // !defined(BOOST_LOG_CAS_PTR)
+ };
+
+private:
+ implementation m_Impl;
+
+ // Padding to avoid false aliasing
+ unsigned char padding
+ [
+ ((sizeof(implementation) + BOOST_LOG_CPU_CACHE_LINE_SIZE - 1) / BOOST_LOG_CPU_CACHE_LINE_SIZE)
+ * BOOST_LOG_CPU_CACHE_LINE_SIZE - sizeof(implementation)
+ ];
+
+ static internal_allocator g_Allocator;
+
+public:
+ //! Constructor. Creates an empty queue.
+ atomic_queue()
+ {
+ m_Impl.m_pLast = NULL;
+ }
+ //! Destructor. Destroys all contained elements, if any.
+ ~atomic_queue()
+ {
+ register node* p = m_Impl.m_pLast;
+ while (p != NULL)
+ {
+ register node* prev = p->m_pPrev;
+ delete p;
+ p = prev;
+ }
+ }
+
+ //! Puts an element to the queue.
+ void push(value_type const& val)
+ {
+#if !defined(BOOST_LOG_CAS_PTR)
+
+ register node* p = new node(val);
+ lock_guard< spin_mutex > _(m_Impl.m_Mutex);
+ p->m_pPrev = m_Impl.m_pLast;
+ m_Impl.m_pLast = p;
+
+#else // !defined(BOOST_LOG_CAS_PTR)
+
+ register node* p = new node(val);
+ register node* last;
+ do
+ {
+ last = static_cast< node* volatile& >(m_Impl.m_pLast);
+ p->m_pPrev = last;
+ }
+ while (!BOOST_LOG_CAS_PTR(last, p, &m_Impl.m_pLast));
+
+#endif // !defined(BOOST_LOG_CAS_PTR)
+ }
+
+ //! Attempts to put an element to the queue.
+ bool try_push(value_type const& val)
+ {
+#if !defined(BOOST_LOG_CAS_PTR)
+
+ unique_lock< spin_mutex > lock(m_Impl.m_Mutex, try_to_lock);
+ if (lock)
+ {
+ register node* p = new node(val);
+ p->m_pPrev = m_Impl.m_pLast;
+ m_Impl.m_pLast = p;
+ return true;
+ }
+ else
+ return false;
+
+#else // !defined(BOOST_LOG_CAS_PTR)
+
+/*
+ register node* p = new node(val);
+ register node* last;
+ last = static_cast< node* volatile& >(m_Impl.m_pLast);
+ p->m_pPrev = last;
+ register bool done = BOOST_LOG_CAS_PTR(last, p, &m_Impl.m_pLast);
+ if (!done)
+ delete p;
+ return done;
+*/
+ // No point for the backoff scheme since we'll most likely lose more
+ // on memory (de)allocation than on one or several loops of trial to CAS.
+ push(val);
+ return true;
+
+#endif // !defined(BOOST_LOG_CAS_PTR)
+ }
+
+ //! Removes all elements from the queue and returns a reference to the first element.
+ std::pair< node*, node* > eject_nodes()
+ {
+ register node* p;
+
+#if !defined(BOOST_LOG_CAS_PTR)
+
+ {
+ lock_guard< spin_mutex > _(m_Impl.m_Mutex);
+ p = m_Impl.m_pLast;
+ m_Impl.m_pLast = NULL;
+ }
+
+#else // !defined(BOOST_LOG_CAS_PTR)
+
+ do
+ {
+ p = static_cast< node* volatile& >(m_Impl.m_pLast);
+ }
+ while (!BOOST_LOG_CAS_PTR(p, static_cast< node* >(NULL), &m_Impl.m_pLast));
+
+#endif // !defined(BOOST_LOG_CAS_PTR)
+
+ // Reconstruct forward references
+ std::pair< node*, node* > res(static_cast< node* >(NULL), p);
+ if (p)
+ {
+ for (register node* prev = p->m_pPrev; prev != NULL; prev = p->m_pPrev)
+ {
+ prev->m_pNext = p;
+ p = prev;
+ }
+ res.first = p;
+ }
+
+ return res;
+ }
+};
+
+template< typename T, typename AllocatorT >
+typename atomic_queue< T, AllocatorT >::internal_allocator atomic_queue< T, AllocatorT >::g_Allocator;
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATOMIC_QUEUE_HPP_INCLUDED_

Added: trunk/libs/log/src/attribute_name.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/attribute_name.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,231 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 28.06.2010
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#include <deque>
+#include <ostream>
+#include <stdexcept>
+#include <boost/assert.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/intrusive/set.hpp>
+#include <boost/intrusive/set_hook.hpp>
+#include <boost/intrusive/options.hpp>
+#include <boost/log/exceptions.hpp>
+#include <boost/log/detail/singleton.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/log/detail/locks.hpp>
+#include <boost/log/detail/light_rw_mutex.hpp>
+#endif
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+//! A global container of all known attribute names
+class attribute_name::repository :
+ public log::aux::lazy_singleton<
+ repository,
+ shared_ptr< repository >
+ >
+{
+ typedef log::aux::lazy_singleton<
+ repository,
+ shared_ptr< repository >
+ > base_type;
+
+#if !defined(BOOST_LOG_BROKEN_FRIEND_TEMPLATE_INSTANTIATIONS)
+ friend class log::aux::lazy_singleton<
+ repository,
+ shared_ptr< repository >
+ >;
+#else
+ friend class base_type;
+#endif
+
+public:
+ // Import types from the basic_attribute_name template
+ typedef attribute_name::id_type id_type;
+ typedef attribute_name::string_type string_type;
+
+ //! A base hook for arranging the attribute names into a set
+ typedef intrusive::set_base_hook<
+ intrusive::link_mode< intrusive::safe_link >,
+ intrusive::optimize_size< true >
+ > node_by_name_hook;
+
+private:
+ //! An element of the attribute names repository
+ struct node :
+ public node_by_name_hook
+ {
+ typedef node_by_name_hook base_type;
+
+ public:
+ //! A predicate for name-based ordering
+ struct order_by_name
+ {
+ typedef bool result_type;
+ typedef string_type::traits_type traits_type;
+
+ bool operator() (node const& left, node const& right) const
+ {
+ // Include terminating 0 into comparison to also check the length match
+ return traits_type::compare(
+ left.m_name.c_str(), right.m_name.c_str(), left.m_name.size() + 1) < 0;
+ }
+ bool operator() (node const& left, const char* right) const
+ {
+ // Include terminating 0 into comparison to also check the length match
+ return traits_type::compare(left.m_name.c_str(), right, left.m_name.size() + 1) < 0;
+ }
+ bool operator() (const char* left, node const& right) const
+ {
+ // Include terminating 0 into comparison to also check the length match
+ return traits_type::compare(left, right.m_name.c_str(), right.m_name.size() + 1) < 0;
+ }
+ };
+
+ public:
+ id_type m_id;
+ string_type m_name;
+
+ public:
+ node() : m_id(0), m_name() {}
+ node(id_type i, string_type const& n) :
+ base_type(),
+ m_id(i),
+ m_name(n)
+ {
+ }
+ node(node const& that) :
+ base_type(),
+ m_id(that.m_id),
+ m_name(that.m_name)
+ {
+ }
+ };
+
+ //! The container that provides storage for nodes
+ typedef std::deque< node > node_list;
+ //! The conainer that provides name-based lookup
+ typedef intrusive::set<
+ node,
+ intrusive::base_hook< node_by_name_hook >,
+ intrusive::constant_time_size< false >,
+ intrusive::compare< node::order_by_name >
+ > node_set;
+
+private:
+#if !defined(BOOST_LOG_NO_THREADS)
+ typedef log::aux::light_rw_mutex mutex_type;
+ log::aux::light_rw_mutex m_Mutex;
+#endif
+ node_list m_NodeList;
+ node_set m_NodeSet;
+
+public:
+ //! Converts attribute name string to id
+ id_type get_id_from_string(const char* name)
+ {
+ BOOST_ASSERT(name != NULL);
+
+#if !defined(BOOST_LOG_NO_THREADS)
+ {
+ // Do a non-blocking lookup first
+ log::aux::shared_lock_guard< mutex_type > _(m_Mutex);
+ node_set::const_iterator it =
+ m_NodeSet.find(name, node::order_by_name());
+ if (it != m_NodeSet.end())
+ return it->m_id;
+ }
+#endif // !defined(BOOST_LOG_NO_THREADS)
+
+ BOOST_LOG_EXPR_IF_MT(log::aux::exclusive_lock_guard< mutex_type > _(m_Mutex);)
+ node_set::iterator it =
+ m_NodeSet.lower_bound(name, node::order_by_name());
+ if (it == m_NodeSet.end() || it->m_name != name)
+ {
+ const std::size_t new_id = m_NodeList.size();
+ if (new_id >= static_cast< id_type >(attribute_name::uninitialized))
+ BOOST_THROW_EXCEPTION(limitation_error("Too many log attribute names"));
+
+ m_NodeList.push_back(node(static_cast< id_type >(new_id), name));
+ it = m_NodeSet.insert(it, m_NodeList.back());
+ }
+ return it->m_id;
+ }
+
+ //! Converts id to the attribute name string
+ string_type const& get_string_from_id(id_type id)
+ {
+ BOOST_LOG_EXPR_IF_MT(log::aux::shared_lock_guard< mutex_type > _(m_Mutex);)
+ BOOST_ASSERT(id < m_NodeList.size());
+ return m_NodeList[id].m_name;
+ }
+
+private:
+ //! Initializes the singleton instance
+ static void init_instance()
+ {
+ base_type::get_instance() = boost::make_shared< repository >();
+ }
+};
+
+BOOST_LOG_API attribute_name::id_type
+attribute_name::get_id_from_string(const char* name)
+{
+ return repository::get()->get_id_from_string(name);
+}
+
+BOOST_LOG_API attribute_name::string_type const&
+attribute_name::get_string_from_id(id_type id)
+{
+ return repository::get()->get_string_from_id(id);
+}
+
+template< typename CharT, typename TraitsT >
+BOOST_LOG_API std::basic_ostream< CharT, TraitsT >& operator<< (
+ std::basic_ostream< CharT, TraitsT >& strm,
+ attribute_name const& name)
+{
+ if (!!name)
+ strm << name.string().c_str();
+ else
+ strm << "[uninitialized]";
+ return strm;
+}
+
+// Explicitly instantiate attribute name implementation
+#ifdef BOOST_LOG_USE_CHAR
+template BOOST_LOG_API std::basic_ostream< char, std::char_traits< char > >&
+ operator<< < char, std::char_traits< char > >(
+ std::basic_ostream< char, std::char_traits< char > >& strm,
+ attribute_name const& name);
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+template BOOST_LOG_API std::basic_ostream< wchar_t, std::char_traits< wchar_t > >&
+ operator<< < wchar_t, std::char_traits< wchar_t > >(
+ std::basic_ostream< wchar_t, std::char_traits< wchar_t > >& strm,
+ attribute_name const& name);
+#endif
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>

Added: trunk/libs/log/src/attribute_set.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/attribute_set.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,147 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 19.04.2007
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#include <deque>
+#include <boost/assert.hpp>
+#include <boost/intrusive/options.hpp>
+#include <boost/intrusive/list.hpp>
+#include <boost/intrusive/link_mode.hpp>
+#include <boost/intrusive/derivation_value_traits.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/attributes/attribute_set.hpp>
+#include "attribute_set_impl.hpp"
+#include "stateless_allocator.hpp"
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+BOOST_LOG_API void* attribute::impl::operator new (std::size_t size)
+{
+ return aux::stateless_allocator< unsigned char >().allocate(size);
+}
+
+BOOST_LOG_API void attribute::impl::operator delete (void* p, std::size_t size) BOOST_NOEXCEPT
+{
+ aux::stateless_allocator< unsigned char >().deallocate(static_cast< unsigned char* >(p), size);
+}
+
+inline attribute_set::node_base::node_base() :
+ m_pPrev(NULL),
+ m_pNext(NULL)
+{
+}
+
+inline attribute_set::node::node(key_type const& key, mapped_type const& data) :
+ node_base(),
+ m_Value(key, data)
+{
+}
+
+//! Default constructor
+BOOST_LOG_API attribute_set::attribute_set() :
+ m_pImpl(new implementation())
+{
+}
+
+//! Copy constructor
+BOOST_LOG_API attribute_set::attribute_set(attribute_set const& that) :
+ m_pImpl(new implementation(*that.m_pImpl))
+{
+}
+
+//! Destructor
+BOOST_LOG_API attribute_set::~attribute_set() BOOST_NOEXCEPT
+{
+ delete m_pImpl;
+}
+
+// Iterator generators
+BOOST_LOG_API attribute_set::iterator attribute_set::begin() BOOST_NOEXCEPT
+{
+ return m_pImpl->begin();
+}
+BOOST_LOG_API attribute_set::iterator attribute_set::end() BOOST_NOEXCEPT
+{
+ return m_pImpl->end();
+}
+BOOST_LOG_API attribute_set::const_iterator attribute_set::begin() const BOOST_NOEXCEPT
+{
+ return const_iterator(m_pImpl->begin());
+}
+BOOST_LOG_API attribute_set::const_iterator attribute_set::end() const BOOST_NOEXCEPT
+{
+ return const_iterator(m_pImpl->end());
+}
+
+//! The method returns number of elements in the container
+BOOST_LOG_API attribute_set::size_type attribute_set::size() const BOOST_NOEXCEPT
+{
+ return m_pImpl->size();
+}
+
+//! Insertion method
+BOOST_LOG_API std::pair< attribute_set::iterator, bool >
+attribute_set::insert(key_type key, mapped_type const& data)
+{
+ return m_pImpl->insert(key, data);
+}
+
+//! The method erases all attributes with the specified name
+BOOST_LOG_API attribute_set::size_type attribute_set::erase(key_type key) BOOST_NOEXCEPT
+{
+ iterator it = m_pImpl->find(key);
+ if (it != end())
+ {
+ m_pImpl->erase(it);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+//! The method erases the specified attribute
+BOOST_LOG_API void attribute_set::erase(iterator it) BOOST_NOEXCEPT
+{
+ m_pImpl->erase(it);
+}
+
+//! The method erases all attributes within the specified range
+BOOST_LOG_API void attribute_set::erase(iterator begin, iterator end) BOOST_NOEXCEPT
+{
+ while (begin != end)
+ {
+ m_pImpl->erase(begin++);
+ }
+}
+
+//! The method clears the container
+BOOST_LOG_API void attribute_set::clear() BOOST_NOEXCEPT
+{
+ m_pImpl->clear();
+}
+
+//! Internal lookup implementation
+BOOST_LOG_API attribute_set::iterator attribute_set::find(key_type key) BOOST_NOEXCEPT
+{
+ return m_pImpl->find(key);
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>

Added: trunk/libs/log/src/attribute_set_impl.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/attribute_set_impl.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,382 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_impl.hpp
+ * \author Andrey Semashev
+ * \date 03.07.2010
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#ifndef BOOST_LOG_ATTRIBUTE_SET_IMPL_HPP_INCLUDED_
+#define BOOST_LOG_ATTRIBUTE_SET_IMPL_HPP_INCLUDED_
+
+#include <new>
+#include <memory>
+#include <limits>
+#include <utility>
+#include <algorithm>
+#include <cstddef>
+#include <boost/assert.hpp>
+#include <boost/array.hpp>
+#include <boost/intrusive/options.hpp>
+#include <boost/intrusive/list.hpp>
+#include <boost/intrusive/link_mode.hpp>
+#include <boost/intrusive/derivation_value_traits.hpp>
+#include <boost/log/attributes/attribute_set.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifndef BOOST_LOG_HASH_TABLE_SIZE_LOG
+// Hash table size will be 2 ^ this value
+#define BOOST_LOG_HASH_TABLE_SIZE_LOG 4
+#endif
+
+#ifndef BOOST_LOG_ATTRIBUTE_SET_MAX_POOL_SIZE
+// Maximum pool size that each attribute set maintains
+#define BOOST_LOG_ATTRIBUTE_SET_MAX_POOL_SIZE 8
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+//! A simple pooling allocator
+template< typename T >
+class pool_allocator :
+ public std::allocator< T >
+{
+public:
+ template< typename U >
+ struct rebind
+ {
+ typedef pool_allocator< U > other;
+ };
+
+ typedef std::allocator< T > base_type;
+
+#if BOOST_LOG_ATTRIBUTE_SET_MAX_POOL_SIZE > 0
+
+ typedef typename base_type::value_type value_type;
+ typedef typename base_type::size_type size_type;
+ typedef typename base_type::difference_type difference_type;
+ typedef typename base_type::pointer pointer;
+ typedef typename base_type::const_pointer const_pointer;
+ typedef typename base_type::reference reference;
+ typedef typename base_type::const_reference const_reference;
+
+private:
+ array< pointer, BOOST_LOG_ATTRIBUTE_SET_MAX_POOL_SIZE > m_Pool;
+ size_type m_PooledCount;
+
+public:
+ pool_allocator() : m_PooledCount(0)
+ {
+ }
+
+ pool_allocator(pool_allocator const& that) :
+ base_type(static_cast< base_type const& >(that)),
+ m_PooledCount(0)
+ {
+ }
+
+ template< typename U >
+ pool_allocator(pool_allocator< U > const& that) :
+ base_type(static_cast< typename pool_allocator< U >::base_type const& >(that)),
+ m_PooledCount(0)
+ {
+ }
+
+ ~pool_allocator()
+ {
+ for (register size_type i = 0; i < m_PooledCount; ++i)
+ {
+ base_type::deallocate(m_Pool[i], 1);
+ }
+ }
+
+ pool_allocator& operator= (pool_allocator const& that)
+ {
+ base_type::operator= (static_cast< base_type const& >(that));
+ return *this;
+ }
+
+ template< typename U >
+ pool_allocator& operator= (pool_allocator< U > const& that)
+ {
+ base_type::operator= (
+ static_cast< typename pool_allocator< U >::base_type const& >(that));
+ return *this;
+ }
+
+ pointer allocate(size_type n, const void* hint = NULL)
+ {
+ if (m_PooledCount > 0)
+ {
+ --m_PooledCount;
+ return m_Pool[m_PooledCount];
+ }
+ else
+ return base_type::allocate(n, hint);
+ }
+
+ void deallocate(pointer p, size_type n)
+ {
+ if (m_PooledCount < m_Pool.size())
+ {
+ m_Pool[m_PooledCount] = p;
+ ++m_PooledCount;
+ }
+ else
+ base_type::deallocate(p, n);
+ }
+
+#else
+
+ template< typename U >
+ pool_allocator(pool_allocator< U > const& that) :
+ base_type(static_cast< typename pool_allocator< U >::base_type const& >(that))
+ {
+ }
+
+#endif // BOOST_LOG_ATTRIBUTE_SET_MAX_POOL_SIZE > 0
+};
+
+//! Attribute set implementation
+struct attribute_set::implementation
+{
+public:
+ //! Attribute name identifier type
+ typedef key_type::id_type id_type;
+
+ //! Allocator type
+ typedef pool_allocator< node > node_allocator;
+
+ //! Node base class traits for the intrusive list
+ struct node_traits
+ {
+ typedef node_base node;
+ typedef node* node_ptr;
+ typedef node const* const_node_ptr;
+ static node* get_next(const node* n) { return n->m_pNext; }
+ static void set_next(node* n, node* next) { n->m_pNext = next; }
+ static node* get_previous(const node* n) { return n->m_pPrev; }
+ static void set_previous(node* n, node* prev) { n->m_pPrev = prev; }
+ };
+
+ //! Contained node traits for the intrusive list
+ typedef intrusive::derivation_value_traits<
+ node,
+ node_traits,
+ intrusive::normal_link
+ > value_traits;
+
+ //! The container that allows to iterate through elements
+ typedef intrusive::list<
+ node,
+ intrusive::value_traits< value_traits >,
+ intrusive::constant_time_size< true >
+ > node_list;
+
+ //! A hash table bucket
+ struct bucket
+ {
+ //! Points to the first element in the bucket
+ node* first;
+ //! Points to the last element in the bucket (not the one after the last!)
+ node* last;
+
+ bucket() : first(NULL), last(NULL) {}
+ };
+
+ //! A list of buckets
+ typedef boost::array< bucket, 1U << BOOST_LOG_HASH_TABLE_SIZE_LOG > buckets;
+
+ //! Cleanup function object used to erase elements from the container
+ struct disposer
+ {
+ typedef void result_type;
+
+ explicit disposer(node_allocator& alloc) : m_Allocator(alloc)
+ {
+ }
+ void operator() (node* p) const
+ {
+ p->~node();
+ m_Allocator.deallocate(p, 1);
+ }
+
+ private:
+ node_allocator& m_Allocator;
+ };
+
+private:
+ //! List of nodes
+ node_list m_Nodes;
+ //! Node allocator
+ node_allocator m_Allocator;
+ //! Hash table buckets
+ buckets m_Buckets;
+
+public:
+ implementation()
+ {
+ }
+
+ implementation(implementation const& that) : m_Allocator(that.m_Allocator)
+ {
+ node_list::const_iterator it = that.m_Nodes.begin(), end = that.m_Nodes.end();
+ for (; it != end; ++it)
+ {
+ node* const n = m_Allocator.allocate(1, NULL);
+ new (n) node(it->m_Value.first, it->m_Value.second);
+ m_Nodes.push_back(*n);
+
+ bucket& b = get_bucket(it->m_Value.first.id());
+ if (b.first == NULL)
+ b.first = b.last = n;
+ else
+ b.last = n;
+ }
+ }
+
+ ~implementation()
+ {
+ m_Nodes.clear_and_dispose(disposer(m_Allocator));
+ }
+
+ size_type size() const { return m_Nodes.size(); }
+ iterator begin() { return iterator(m_Nodes.begin().pointed_node()); }
+ iterator end() { return iterator(m_Nodes.end().pointed_node()); }
+
+ void clear()
+ {
+ m_Nodes.clear_and_dispose(disposer(m_Allocator));
+ std::fill_n(m_Buckets.begin(), m_Buckets.size(), bucket());
+ }
+
+ std::pair< iterator, bool > insert(key_type key, mapped_type const& data)
+ {
+ BOOST_ASSERT(!!key);
+
+ bucket& b = get_bucket(key.id());
+ register node* p = b.first;
+ if (p)
+ {
+ // The bucket is not empty, search among the elements
+ p = find_in_bucket(key, b);
+ if (p->m_Value.first == key)
+ return std::make_pair(iterator(p), false);
+ }
+
+ node* const n = m_Allocator.allocate(1, NULL);
+ new (n) node(key, data);
+
+ if (b.first == NULL)
+ {
+ // The bucket is empty
+ b.first = b.last = n;
+ m_Nodes.push_back(*n);
+ }
+ else if (p == b.last && key.id() > p->m_Value.first.id())
+ {
+ // The new element should become the last element of the bucket
+ node_list::iterator it = m_Nodes.iterator_to(*p);
+ ++it;
+ m_Nodes.insert(it, *n);
+ b.last = n;
+ }
+ else
+ {
+ // The new element should be within the bucket
+ node_list::iterator it = m_Nodes.iterator_to(*p);
+ m_Nodes.insert(it, *n);
+ }
+
+ return std::make_pair(iterator(n), true);
+ }
+
+ void erase(iterator it)
+ {
+ typedef node_list::node_traits node_traits;
+ typedef node_list::value_traits value_traits;
+
+ node* p = static_cast< node* >(it.base());
+
+ // Adjust bucket boundaries, if needed
+ bucket& b = get_bucket(it->first.id());
+ unsigned int choice = (static_cast< unsigned int >(p == b.first) << 1) |
+ static_cast< unsigned int >(p == b.last);
+ switch (choice)
+ {
+ case 1: // The erased element is the last one in the bucket
+ b.last = value_traits::to_value_ptr(node_traits::get_previous(b.last));
+ break;
+
+ case 2: // The erased element is the first one in the bucket
+ b.first = value_traits::to_value_ptr(node_traits::get_next(b.first));
+ break;
+
+ case 3: // The erased element is the only one in the bucket
+ b.first = b.last = NULL;
+ break;
+
+ default: // The erased element is somewhere in the middle of the bucket
+ break;
+ }
+
+ m_Nodes.erase_and_dispose(m_Nodes.iterator_to(*p), disposer(m_Allocator));
+ }
+
+ iterator find(key_type key)
+ {
+ bucket& b = get_bucket(key.id());
+ register node* p = b.first;
+ if (p)
+ {
+ // The bucket is not empty, search among the elements
+ p = find_in_bucket(key, b);
+ if (p->m_Value.first == key)
+ return iterator(p);
+ }
+
+ return end();
+ }
+
+private:
+ implementation& operator= (implementation const&);
+
+ //! The function returns a bucket for the specified element
+ bucket& get_bucket(id_type id)
+ {
+ return m_Buckets[id & (buckets::static_size - 1)];
+ }
+
+ //! Attempts to find an element with the specified key in the bucket
+ node* find_in_bucket(key_type key, bucket const& b)
+ {
+ typedef node_list::node_traits node_traits;
+ typedef node_list::value_traits value_traits;
+
+ // All elements within the bucket are sorted to speedup the search.
+ register node* p = b.first;
+ while (p != b.last && p->m_Value.first.id() < key.id())
+ {
+ p = value_traits::to_value_ptr(node_traits::get_next(p));
+ }
+
+ return p;
+ }
+};
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ATTRIBUTE_SET_IMPL_HPP_INCLUDED_

Added: trunk/libs/log/src/attribute_value_set.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/attribute_value_set.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,565 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 19.04.2007
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#include <new>
+#include <memory>
+#include <boost/array.hpp>
+#include <boost/intrusive/options.hpp>
+#include <boost/intrusive/list.hpp>
+#include <boost/intrusive/link_mode.hpp>
+#include <boost/intrusive/derivation_value_traits.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/attribute_value.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include "alignment_gap_between.hpp"
+#include "attribute_set_impl.hpp"
+#include "stateless_allocator.hpp"
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+BOOST_LOG_FORCEINLINE attribute_value_set::node_base::node_base() :
+ m_pPrev(NULL),
+ m_pNext(NULL)
+{
+}
+
+BOOST_LOG_FORCEINLINE attribute_value_set::node::node(key_type const& key, mapped_type& data, bool dynamic) :
+ node_base(),
+ m_Value(key, mapped_type()),
+ m_DynamicallyAllocated(dynamic)
+{
+ m_Value.second.swap(data);
+}
+
+//! Container implementation
+struct attribute_value_set::implementation
+{
+public:
+ typedef key_type::id_type id_type;
+
+private:
+ typedef attribute_set::implementation attribute_set_impl_type;
+ typedef boost::log::aux::stateless_allocator< char > stateless_allocator;
+
+ //! Node base class traits for the intrusive list
+ struct node_traits
+ {
+ typedef node_base node;
+ typedef node* node_ptr;
+ typedef node const* const_node_ptr;
+ static node* get_next(const node* n) { return n->m_pNext; }
+ static void set_next(node* n, node* next) { n->m_pNext = next; }
+ static node* get_previous(const node* n) { return n->m_pPrev; }
+ static void set_previous(node* n, node* prev) { n->m_pPrev = prev; }
+ };
+
+ //! Contained node traits for the intrusive list
+ typedef intrusive::derivation_value_traits<
+ node,
+ node_traits,
+ intrusive::normal_link
+ > value_traits;
+
+ //! A container that provides iteration through elements of the container
+ typedef intrusive::list<
+ node,
+ intrusive::value_traits< value_traits >,
+ intrusive::constant_time_size< false >
+ > node_list;
+
+ //! A hash table bucket
+ struct bucket
+ {
+ //! Points to the first element in the bucket
+ node* first;
+ //! Points to the last element in the bucket (not the one after the last!)
+ node* last;
+
+ bucket() : first(NULL), last(NULL) {}
+ };
+
+ //! A list of buckets
+ typedef boost::array< bucket, 1U << BOOST_LOG_HASH_TABLE_SIZE_LOG > buckets;
+
+ //! Element disposer
+ struct disposer
+ {
+ typedef void result_type;
+ void operator() (node* p) const
+ {
+ if (!p->m_DynamicallyAllocated)
+ p->~node();
+ else
+ delete p;
+ }
+ };
+
+private:
+ //! Pointer to the source-specific attributes
+ attribute_set_impl_type* m_pSourceAttributes;
+ //! Pointer to the thread-specific attributes
+ attribute_set_impl_type* m_pThreadAttributes;
+ //! Pointer to the global attributes
+ attribute_set_impl_type* m_pGlobalAttributes;
+
+ //! The container with elements
+ node_list m_Nodes;
+ //! The pointer to the beginning of the storage of the elements
+ node* m_pStorage;
+ //! The pointer to the end of the allocated elements within the storage
+ node* m_pEnd;
+ //! The pointer to the end of storage
+ node* m_pEOS;
+
+ //! Hash table buckets
+ buckets m_Buckets;
+
+private:
+ //! Constructor
+ implementation(
+ node* storage,
+ node* eos,
+ attribute_set_impl_type* source_attrs,
+ attribute_set_impl_type* thread_attrs,
+ attribute_set_impl_type* global_attrs
+ ) :
+ m_pSourceAttributes(source_attrs),
+ m_pThreadAttributes(thread_attrs),
+ m_pGlobalAttributes(global_attrs),
+ m_pStorage(storage),
+ m_pEnd(storage),
+ m_pEOS(eos)
+ {
+ }
+
+ //! Destructor
+ ~implementation()
+ {
+ m_Nodes.clear_and_dispose(disposer());
+ }
+
+ //! The function allocates memory and creates the object
+ static implementation* create(
+ size_type element_count,
+ attribute_set_impl_type* source_attrs,
+ attribute_set_impl_type* thread_attrs,
+ attribute_set_impl_type* global_attrs)
+ {
+ // Calculate the buffer size
+ const size_type header_size = sizeof(implementation) +
+ aux::alignment_gap_between< implementation, node >::value;
+ const size_type buffer_size = header_size + element_count * sizeof(node);
+
+ implementation* p = reinterpret_cast< implementation* >(stateless_allocator().allocate(buffer_size));
+ node* const storage = reinterpret_cast< node* >(reinterpret_cast< char* >(p) + header_size);
+ new (p) implementation(storage, storage + element_count, source_attrs, thread_attrs, global_attrs);
+
+ return p;
+ }
+
+public:
+ //! The function allocates memory and creates the object
+ static implementation* create(
+ attribute_set const& source_attrs,
+ attribute_set const& thread_attrs,
+ attribute_set const& global_attrs,
+ size_type reserve_count)
+ {
+ return create(
+ source_attrs.m_pImpl->size() + thread_attrs.m_pImpl->size() + global_attrs.m_pImpl->size() + reserve_count,
+ source_attrs.m_pImpl,
+ thread_attrs.m_pImpl,
+ global_attrs.m_pImpl);
+ }
+
+ //! The function allocates memory and creates the object
+ static implementation* create(
+ attribute_value_set const& source_attrs,
+ attribute_set const& thread_attrs,
+ attribute_set const& global_attrs,
+ size_type reserve_count)
+ {
+ implementation* p = create(
+ source_attrs.m_pImpl->size() + thread_attrs.m_pImpl->size() + global_attrs.m_pImpl->size() + reserve_count,
+ NULL,
+ thread_attrs.m_pImpl,
+ global_attrs.m_pImpl);
+ p->copy_nodes_from(source_attrs.m_pImpl);
+ return p;
+ }
+
+ //! The function allocates memory and creates the object
+ static implementation* create(
+ BOOST_RV_REF(attribute_value_set) source_attrs,
+ attribute_set const& thread_attrs,
+ attribute_set const& global_attrs,
+ size_type reserve_count)
+ {
+ implementation* p = source_attrs.m_pImpl;
+ source_attrs.m_pImpl = NULL;
+ p->m_pThreadAttributes = thread_attrs.m_pImpl;
+ p->m_pGlobalAttributes = global_attrs.m_pImpl;
+ return p;
+ }
+
+ //! The function allocates memory and creates the object
+ static implementation* create(size_type reserve_count)
+ {
+ return create(reserve_count, NULL, NULL, NULL);
+ }
+
+ //! Creates a copy of the object
+ static implementation* copy(implementation* that)
+ {
+ // Create new object
+ implementation* p = create(that->size(), NULL, NULL, NULL);
+
+ // Copy all elements
+ p->copy_nodes_from(that);
+
+ return p;
+ }
+
+ //! Destroys the object and releases the memory
+ static void destroy(implementation* p)
+ {
+ const size_type buffer_size = reinterpret_cast< char* >(p->m_pEOS) - reinterpret_cast< char* >(p);
+ p->~implementation();
+ stateless_allocator().deallocate(reinterpret_cast< stateless_allocator::pointer >(p), buffer_size);
+ }
+
+ //! Returns the pointer to the first element
+ node_base* begin()
+ {
+ freeze();
+ return m_Nodes.begin().pointed_node();
+ }
+ //! Returns the pointer after the last element
+ node_base* end()
+ {
+ return m_Nodes.end().pointed_node();
+ }
+
+ //! Returns the number of elements in the container
+ size_type size()
+ {
+ freeze();
+ return (m_pEnd - m_pStorage);
+ }
+
+ //! Looks for the element with an equivalent key
+ node_base* find(key_type key)
+ {
+ // First try to find an acquired element
+ bucket& b = get_bucket(key.id());
+ register node* p = b.first;
+ if (p)
+ {
+ // The bucket is not empty, search among the elements
+ p = find_in_bucket(key, b);
+ if (p->m_Value.first == key)
+ return p;
+ }
+
+ // Element not found, try to acquire the value from attribute sets
+ return freeze_node(key, b, p);
+ }
+
+ //! Freezes all elements of the container
+ void freeze()
+ {
+ if (m_pSourceAttributes)
+ {
+ freeze_nodes_from(m_pSourceAttributes);
+ m_pSourceAttributes = NULL;
+ }
+ if (m_pThreadAttributes)
+ {
+ freeze_nodes_from(m_pThreadAttributes);
+ m_pThreadAttributes = NULL;
+ }
+ if (m_pGlobalAttributes)
+ {
+ freeze_nodes_from(m_pGlobalAttributes);
+ m_pGlobalAttributes = NULL;
+ }
+ }
+
+ //! Inserts an element
+ std::pair< node*, bool > insert(key_type key, mapped_type const& mapped)
+ {
+ bucket& b = get_bucket(key.id());
+ node* p = find_in_bucket(key, b);
+ if (!p || p->m_Value.first != key)
+ {
+ p = insert_node(key, b, p, mapped);
+ return std::pair< node*, bool >(p, true);
+ }
+ else
+ {
+ return std::pair< node*, bool >(p, false);
+ }
+ }
+
+private:
+ //! The function returns a bucket for the specified element
+ bucket& get_bucket(id_type id)
+ {
+ return m_Buckets[id & (buckets::static_size - 1)];
+ }
+
+ //! Attempts to find an element with the specified key in the bucket
+ node* find_in_bucket(key_type key, bucket const& b)
+ {
+ typedef node_list::node_traits node_traits;
+ typedef node_list::value_traits value_traits;
+
+ // All elements within the bucket are sorted to speedup the search.
+ register node* p = b.first;
+ while (p != b.last && p->m_Value.first.id() < key.id())
+ {
+ p = value_traits::to_value_ptr(node_traits::get_next(p));
+ }
+
+ return p;
+ }
+
+ //! Acquires the attribute value from the attribute sets
+ node_base* freeze_node(key_type key, bucket& b, node* where)
+ {
+ attribute_set::iterator it;
+ if (m_pSourceAttributes)
+ {
+ it = m_pSourceAttributes->find(key);
+ if (it != m_pSourceAttributes->end())
+ {
+ // The attribute is found, acquiring the value
+ return insert_node(key, b, where, it->second.get_value());
+ }
+ }
+
+ if (m_pThreadAttributes)
+ {
+ it = m_pThreadAttributes->find(key);
+ if (it != m_pThreadAttributes->end())
+ {
+ // The attribute is found, acquiring the value
+ return insert_node(key, b, where, it->second.get_value());
+ }
+ }
+
+ if (m_pGlobalAttributes)
+ {
+ it = m_pGlobalAttributes->find(key);
+ if (it != m_pGlobalAttributes->end())
+ {
+ // The attribute is found, acquiring the value
+ return insert_node(key, b, where, it->second.get_value());
+ }
+ }
+
+ // The attribute is not found
+ return m_Nodes.end().pointed_node();
+ }
+
+ //! The function inserts a node into the container
+ node* insert_node(key_type key, bucket& b, node* where, mapped_type data)
+ {
+ node* p;
+ if (m_pEnd != m_pEOS)
+ {
+ p = m_pEnd++;
+ new (p) node(key, data, false);
+ }
+ else
+ {
+ p = new node(key, data, true);
+ }
+
+ if (b.first == NULL)
+ {
+ // The bucket is empty
+ b.first = b.last = p;
+ m_Nodes.push_back(*p);
+ }
+ else if (where == b.last && key.id() > where->m_Value.first.id())
+ {
+ // The new element should become the last element of the bucket
+ node_list::iterator it = m_Nodes.iterator_to(*where);
+ ++it;
+ m_Nodes.insert(it, *p);
+ b.last = p;
+ }
+ else
+ {
+ // The new element should be within the bucket
+ node_list::iterator it = m_Nodes.iterator_to(*where);
+ m_Nodes.insert(it, *p);
+ }
+
+ return p;
+ }
+
+ //! Acquires attribute values from the set of attributes
+ void freeze_nodes_from(attribute_set_impl_type* attrs)
+ {
+ attribute_set::const_iterator it = attrs->begin(), end = attrs->end();
+ for (; it != end; ++it)
+ {
+ key_type key = it->first;
+ bucket& b = get_bucket(key.id());
+ register node* p = b.first;
+ if (p)
+ {
+ p = find_in_bucket(key, b);
+ if (p->m_Value.first == key)
+ continue; // the element is already frozen
+ }
+
+ insert_node(key, b, p, it->second.get_value());
+ }
+ }
+
+ //! Copies nodes of the container
+ void copy_nodes_from(implementation* from)
+ {
+ // Copy all elements
+ node_list::iterator it = from->m_Nodes.begin(), end = from->m_Nodes.end();
+ for (; it != end; ++it)
+ {
+ node* n = m_pEnd++;
+ mapped_type data = it->m_Value.second;
+ new (n) node(it->m_Value.first, data, false);
+ m_Nodes.push_back(*n);
+
+ // Since nodes within buckets are ordered, we can simply append the node to the end of the bucket
+ bucket& b = get_bucket(n->m_Value.first.id());
+ if (b.first == NULL)
+ b.first = b.last = n;
+ else
+ b.last = n;
+ }
+ }
+};
+
+//! The constructor creates an empty set
+BOOST_LOG_API attribute_value_set::attribute_value_set(
+ size_type reserve_count
+) :
+ m_pImpl(implementation::create(reserve_count))
+{
+}
+
+//! The constructor adopts three attribute sets to the set
+BOOST_LOG_API attribute_value_set::attribute_value_set(
+ attribute_set const& source_attrs,
+ attribute_set const& thread_attrs,
+ attribute_set const& global_attrs,
+ size_type reserve_count
+) :
+ m_pImpl(implementation::create(source_attrs, thread_attrs, global_attrs, reserve_count))
+{
+}
+
+//! The constructor adopts three attribute sets to the set
+BOOST_LOG_API attribute_value_set::attribute_value_set(
+ attribute_value_set const& source_attrs,
+ attribute_set const& thread_attrs,
+ attribute_set const& global_attrs,
+ size_type reserve_count
+) :
+ m_pImpl(implementation::create(source_attrs, thread_attrs, global_attrs, reserve_count))
+{
+}
+
+//! The constructor adopts three attribute sets to the set
+BOOST_LOG_API void attribute_value_set::construct(
+ attribute_value_set& source_attrs,
+ attribute_set const& thread_attrs,
+ attribute_set const& global_attrs,
+ size_type reserve_count
+)
+{
+ m_pImpl = implementation::create(boost::move(source_attrs), thread_attrs, global_attrs, reserve_count);
+}
+
+//! Copy constructor
+BOOST_LOG_API attribute_value_set::attribute_value_set(attribute_value_set const& that)
+{
+ if (that.m_pImpl)
+ m_pImpl = implementation::copy(that.m_pImpl);
+ else
+ m_pImpl = NULL;
+}
+
+//! Destructor
+BOOST_LOG_API attribute_value_set::~attribute_value_set() BOOST_NOEXCEPT
+{
+ if (m_pImpl)
+ {
+ implementation::destroy(m_pImpl);
+ m_pImpl = NULL;
+ }
+}
+
+// Iterator generators
+BOOST_LOG_API attribute_value_set::const_iterator
+attribute_value_set::begin() const
+{
+ return const_iterator(m_pImpl->begin(), const_cast< attribute_value_set* >(this));
+}
+
+BOOST_LOG_API attribute_value_set::const_iterator
+attribute_value_set::end() const
+{
+ return const_iterator(m_pImpl->end(), const_cast< attribute_value_set* >(this));
+}
+
+//! The method returns number of elements in the container
+BOOST_LOG_API attribute_value_set::size_type
+attribute_value_set::size() const
+{
+ return m_pImpl->size();
+}
+
+//! Internal lookup implementation
+BOOST_LOG_API attribute_value_set::const_iterator
+attribute_value_set::find(key_type key) const
+{
+ return const_iterator(m_pImpl->find(key), const_cast< attribute_value_set* >(this));
+}
+
+//! The method acquires values of all adopted attributes. Users don't need to call it, since will always get an already frozen set.
+BOOST_LOG_API void attribute_value_set::freeze()
+{
+ m_pImpl->freeze();
+}
+
+//! Inserts an element into the set
+BOOST_LOG_API std::pair< attribute_value_set::const_iterator, bool >
+attribute_value_set::insert(key_type key, mapped_type const& mapped)
+{
+ std::pair< node*, bool > res = m_pImpl->insert(key, mapped);
+ return std::pair< const_iterator, bool >(const_iterator(res.first, this), res.second);
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>

Added: trunk/libs/log/src/code_conversion.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/code_conversion.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,166 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \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/libs/log/doc/log.html.
+ */
+
+#include <locale>
+#include <string>
+#include <stdexcept>
+#include <algorithm>
+#include <boost/log/exceptions.hpp>
+#include <boost/log/detail/code_conversion.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+ //! The function performs character conversion with the specified facet
+ template< typename LocalCharT >
+ inline std::codecvt_base::result convert(
+ std::codecvt< LocalCharT, char, std::mbstate_t > const& fac,
+ std::mbstate_t& state,
+ const char*& pSrcBegin,
+ const char* pSrcEnd,
+ LocalCharT*& pDstBegin,
+ LocalCharT* pDstEnd)
+ {
+ return fac.in(state, pSrcBegin, pSrcEnd, pSrcBegin, pDstBegin, pDstEnd, pDstBegin);
+ }
+
+ //! The function performs character conversion with the specified facet
+ template< typename LocalCharT >
+ inline std::codecvt_base::result convert(
+ std::codecvt< LocalCharT, char, std::mbstate_t > const& fac,
+ std::mbstate_t& state,
+ const LocalCharT*& pSrcBegin,
+ const LocalCharT* pSrcEnd,
+ char*& pDstBegin,
+ char* pDstEnd)
+ {
+ return fac.out(state, pSrcBegin, pSrcEnd, pSrcBegin, pDstBegin, pDstEnd, pDstBegin);
+ }
+
+} // namespace
+
+template< typename SourceCharT, typename TargetCharT, typename FacetT >
+inline void code_convert(const SourceCharT* begin, const SourceCharT* end, std::basic_string< TargetCharT >& converted, FacetT const& fac)
+{
+ typedef typename FacetT::state_type state_type;
+ TargetCharT converted_buffer[256];
+
+ state_type state = state_type();
+ while (begin != end)
+ {
+ TargetCharT* dest = converted_buffer;
+ std::codecvt_base::result res = convert(
+ fac,
+ state,
+ begin,
+ end,
+ dest,
+ dest + sizeof(converted_buffer) / sizeof(*converted_buffer));
+
+ switch (res)
+ {
+ case std::codecvt_base::ok:
+ // All characters were successfully converted
+ // NOTE: MSVC 11 also returns ok when the source buffer was only partially consumed, so we also check that the begin pointer has reached the end.
+ converted.append(converted_buffer, dest);
+ break;
+
+ case std::codecvt_base::partial:
+ // Some characters were converted, some were not
+ if (dest != converted_buffer)
+ {
+ // Some conversion took place, so it seems like
+ // the destination buffer might not have been long enough
+ converted.append(converted_buffer, dest);
+
+ // ...and go on for the next part
+ break;
+ }
+ else
+ {
+ // Nothing was converted, looks like the tail of the
+ // source buffer contains only part of the last character.
+ // Leave it as it is.
+ return;
+ }
+
+ case std::codecvt_base::noconv:
+ // Not possible, unless both character types are actually equivalent
+ converted.append(reinterpret_cast< const TargetCharT* >(begin), reinterpret_cast< const TargetCharT* >(end));
+ return;
+
+ default: // std::codecvt_base::error
+ BOOST_LOG_THROW_DESCR(conversion_error, "Could not convert character encoding");
+ }
+ }
+}
+
+//! 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)
+{
+ code_convert(str1, str1 + len, str2, std::use_facet< std::codecvt< wchar_t, char, std::mbstate_t > >(loc));
+}
+
+//! 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)
+{
+ code_convert(str1, str1 + len, str2, std::use_facet< std::codecvt< wchar_t, char, std::mbstate_t > >(loc));
+}
+
+#if !defined(BOOST_NO_CHAR16_T) && !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)
+{
+ code_convert(str1, str1 + len, str2, std::use_facet< std::codecvt< char16_t, char, std::mbstate_t > >(loc));
+}
+
+//! 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)
+{
+ code_convert(str1, str1 + len, str2, std::use_facet< std::codecvt< char16_t, char, std::mbstate_t > >(loc));
+}
+
+#endif
+
+#if !defined(BOOST_NO_CHAR32_T) && !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)
+{
+ code_convert(str1, str1 + len, str2, std::use_facet< std::codecvt< char32_t, char, std::mbstate_t > >(loc));
+}
+
+//! 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)
+{
+ code_convert(str1, str1 + len, str2, std::use_facet< std::codecvt< char32_t, char, std::mbstate_t > >(loc));
+}
+
+#endif
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>

Added: trunk/libs/log/src/core.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/core.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,698 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 19.04.2007
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#include <cstddef>
+#include <new>
+#include <memory>
+#include <vector>
+#include <algorithm>
+#include <boost/cstdint.hpp>
+#include <boost/assert.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/range/iterator_range_core.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/log/core/core.hpp>
+#include <boost/log/core/record.hpp>
+#include <boost/log/core/record_view.hpp>
+#include <boost/log/sinks/sink.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include <boost/log/detail/singleton.hpp>
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/thread/tss.hpp>
+#include <boost/thread/exceptions.hpp>
+#include <boost/log/detail/locks.hpp>
+#include <boost/log/detail/light_rw_mutex.hpp>
+#endif
+#include "default_sink.hpp"
+#include "stateless_allocator.hpp"
+#include "alignment_gap_between.hpp"
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+//! Private record data information, with core-specific structures
+struct record_view::private_data :
+ public public_data
+{
+ //! Underlying memory allocator
+ typedef boost::log::aux::stateless_allocator< char > stateless_allocator;
+ //! Sink pointer type
+ typedef weak_ptr< sinks::sink > sink_ptr;
+ //! Iterator range with pointers to the accepting sinks
+ typedef iterator_range< sink_ptr* > sink_list;
+
+private:
+ //! Number of sinks accepting the record
+ uint32_t m_accepting_sink_count;
+ //! Maximum number of sinks accepting the record
+ const uint32_t m_accepting_sink_capacity;
+ //! The flag indicates that the record has to be detached from the current thread
+ bool m_detach_from_thread_needed;
+
+private:
+ //! Initializing constructor
+ private_data(BOOST_RV_REF(attribute_value_set) values, uint32_t capacity) :
+ public_data(boost::move(values)),
+ m_accepting_sink_count(0),
+ m_accepting_sink_capacity(capacity),
+ m_detach_from_thread_needed(false)
+ {
+ }
+
+public:
+ //! Creates the object with the specified capacity
+ static private_data* create(BOOST_RV_REF(attribute_value_set) values, uint32_t capacity)
+ {
+ private_data* p = reinterpret_cast< private_data* >(stateless_allocator().allocate
+ (
+ sizeof(private_data) +
+ boost::log::aux::alignment_gap_between< private_data, sink_ptr >::value +
+ capacity * sizeof(sink_ptr)
+ ));
+ new (p) private_data(boost::move(values), capacity);
+ return p;
+ }
+
+ //! Destroys the object and frees the underlying storage
+ void destroy() BOOST_NOEXCEPT
+ {
+ sink_list s = get_accepting_sinks();
+ for (sink_list::iterator it = s.begin(), end = s.end(); it != end; ++it)
+ {
+ it->~sink_ptr();
+ }
+
+ const uint32_t capacity = m_accepting_sink_capacity;
+ this->~private_data();
+
+ stateless_allocator().deallocate
+ (
+ reinterpret_cast< stateless_allocator::pointer >(this),
+ sizeof(private_data) +
+ boost::log::aux::alignment_gap_between< private_data, sink_ptr >::value +
+ capacity * sizeof(sink_ptr)
+ );
+ }
+
+ //! Returns iterator range with the pointers to the accepting sinks
+ sink_list get_accepting_sinks() BOOST_NOEXCEPT
+ {
+ sink_ptr* p = begin();
+ return sink_list(p, p + m_accepting_sink_count);
+ }
+
+ //! Adds an accepting sink
+ void push_back_accepting_sink(shared_ptr< sinks::sink > const& sink)
+ {
+ BOOST_ASSERT(m_accepting_sink_count < m_accepting_sink_capacity);
+ sink_ptr* p = begin() + m_accepting_sink_count;
+ new (p) sink_ptr(sink);
+ ++m_accepting_sink_count;
+ m_detach_from_thread_needed |= sink->is_cross_thread();
+ }
+
+ //! Returns the number of accepting sinks
+ uint32_t accepting_sink_count() const BOOST_NOEXCEPT { return m_accepting_sink_count; }
+
+ //! Returns the flag indicating whether it is needed to detach the record from the current thread
+ bool is_detach_from_thread_needed() const BOOST_NOEXCEPT { return m_detach_from_thread_needed; }
+
+ BOOST_LOG_DELETED_FUNCTION(private_data(private_data const&))
+ BOOST_LOG_DELETED_FUNCTION(private_data& operator= (private_data const&))
+
+private:
+ //! Returns a pointer to the first accepting sink
+ sink_ptr* begin() BOOST_NOEXCEPT
+ {
+ return reinterpret_cast< sink_ptr* >
+ (
+ reinterpret_cast< char* >(this) +
+ sizeof(private_data) +
+ boost::log::aux::alignment_gap_between< private_data, sink_ptr >::value
+ );
+ }
+};
+
+//! Destructor
+BOOST_LOG_API void record_view::public_data::destroy(const public_data* p) BOOST_NOEXCEPT
+{
+ const_cast< private_data* >(static_cast< const private_data* >(p))->destroy();
+}
+
+//! The function ensures that the log record does not depend on any thread-specific data.
+BOOST_LOG_API record_view record::lock()
+{
+ BOOST_ASSERT(m_impl != NULL);
+
+ record_view::private_data* const impl = static_cast< record_view::private_data* >(m_impl);
+ if (impl->is_detach_from_thread_needed())
+ {
+ attribute_value_set::const_iterator
+ it = impl->m_attribute_values.begin(),
+ end = impl->m_attribute_values.end();
+ for (; it != end; ++it)
+ {
+ // Yep, a bit hackish. I'll need a better backdoor to do it gracefully.
+ const_cast< attribute_value_set::mapped_type& >(it->second).detach_from_thread();
+ }
+ }
+
+ // Move the implementation to the view
+ m_impl = NULL;
+ return record_view(impl);
+}
+
+//! Logging system implementation
+struct core::implementation :
+ public log::aux::lazy_singleton<
+ implementation,
+ core_ptr
+ >
+{
+public:
+ //! Base type of singleton holder
+ typedef log::aux::lazy_singleton<
+ implementation,
+ core_ptr
+ > base_type;
+
+#if !defined(BOOST_LOG_NO_THREADS)
+ //! Read lock type
+ typedef log::aux::shared_lock_guard< log::aux::light_rw_mutex > scoped_read_lock;
+ //! Write lock type
+ typedef log::aux::exclusive_lock_guard< log::aux::light_rw_mutex > scoped_write_lock;
+#endif
+
+ //! Sinks container type
+ typedef std::vector< shared_ptr< sinks::sink > > sink_list;
+
+ //! Thread-specific data
+ struct thread_data
+ {
+ //! Thread-specific attribute set
+ attribute_set m_thread_attributes;
+ };
+
+public:
+#if !defined(BOOST_LOG_NO_THREADS)
+ //! Synchronization mutex
+ log::aux::light_rw_mutex m_mutex;
+#endif
+
+ //! List of sinks involved into output
+ sink_list m_sinks;
+ //! Default sink
+ const shared_ptr< sinks::sink > m_default_sink;
+
+ //! Global attribute set
+ attribute_set m_global_attributes;
+#if !defined(BOOST_LOG_NO_THREADS)
+ //! Thread-specific data
+ thread_specific_ptr< thread_data > m_thread_data;
+
+#if defined(BOOST_LOG_USE_COMPILER_TLS)
+ //! Cached pointer to the thread-specific data
+ static BOOST_LOG_TLS thread_data* m_thread_data_cache;
+#endif
+
+#else
+ //! Thread-specific data
+ std::auto_ptr< thread_data > m_thread_data;
+#endif
+
+ //! The global state of logging
+ volatile bool m_enabled;
+ //! Global filter
+ filter m_filter;
+
+ //! Exception handler
+ exception_handler_type m_exception_handler;
+
+public:
+ //! Constructor
+ implementation() :
+ m_default_sink(boost::make_shared< sinks::aux::default_sink >()),
+ m_enabled(true)
+ {
+ }
+
+ //! Invokes sink-specific filter and adds the sink to the record if the filter passes the log record
+ void apply_sink_filter(shared_ptr< sinks::sink > const& sink, record& rec, attribute_value_set*& attr_values, uint32_t remaining_capacity)
+ {
+ try
+ {
+ if (sink->will_consume(*attr_values))
+ {
+ // If at least one sink accepts the record, it's time to create it
+ if (!rec.m_impl)
+ {
+ rec.m_impl = record_view::private_data::create(boost::move(*attr_values), remaining_capacity);
+ attr_values = &rec.m_impl->m_attribute_values;
+ }
+
+ static_cast< record_view::private_data* >(rec.m_impl)->push_back_accepting_sink(sink);
+ }
+ }
+#if !defined(BOOST_LOG_NO_THREADS)
+ catch (thread_interrupted&)
+ {
+ throw;
+ }
+#endif // !defined(BOOST_LOG_NO_THREADS)
+ catch (...)
+ {
+ if (m_exception_handler.empty())
+ throw;
+ m_exception_handler();
+ }
+ }
+
+ //! Opens a record
+ template< typename SourceAttributesT >
+ BOOST_LOG_FORCEINLINE record open_record(BOOST_FWD_REF(SourceAttributesT) source_attributes)
+ {
+ // Try a quick win first
+ if (m_enabled) try
+ {
+ thread_data* tsd = get_thread_data();
+
+ // Lock the core to be safe against any attribute or sink set modifications
+ BOOST_LOG_EXPR_IF_MT(scoped_read_lock lock(m_mutex);)
+
+ if (m_enabled)
+ {
+ // Compose a view of attribute values (unfrozen, yet)
+ attribute_value_set attr_values(boost::forward< SourceAttributesT >(source_attributes), tsd->m_thread_attributes, m_global_attributes);
+ if (m_filter(attr_values))
+ {
+ // The global filter passed, trying the sinks
+ record rec;
+ attribute_value_set* values = &attr_values;
+
+ if (!m_sinks.empty())
+ {
+ uint32_t remaining_capacity = static_cast< uint32_t >(m_sinks.size());
+ sink_list::iterator it = m_sinks.begin(), end = m_sinks.end();
+ for (; it != end; ++it, --remaining_capacity)
+ {
+ apply_sink_filter(*it, rec, values, remaining_capacity);
+ }
+ }
+ else
+ {
+ // Use the default sink
+ apply_sink_filter(m_default_sink, rec, values, 1);
+ }
+
+ record_view::private_data* rec_impl = static_cast< record_view::private_data* >(rec.m_impl);
+ if (rec_impl && rec_impl->accepting_sink_count() == 0)
+ {
+ // No sinks accepted the record
+ return record();
+ }
+
+ // Some sinks have accepted the record
+ values->freeze();
+
+ return boost::move(rec);
+ }
+ }
+ }
+ #if !defined(BOOST_LOG_NO_THREADS)
+ catch (thread_interrupted&)
+ {
+ throw;
+ }
+ #endif // !defined(BOOST_LOG_NO_THREADS)
+ catch (...)
+ {
+ // Lock the core to be safe against any attribute or sink set modifications
+ BOOST_LOG_EXPR_IF_MT(scoped_read_lock lock(m_mutex);)
+ if (m_exception_handler.empty())
+ throw;
+
+ m_exception_handler();
+ }
+
+ return record();
+ }
+
+ //! The method returns the current thread-specific data
+ thread_data* get_thread_data()
+ {
+#if defined(BOOST_LOG_USE_COMPILER_TLS)
+ thread_data* p = m_thread_data_cache;
+#else
+ thread_data* p = m_thread_data.get();
+#endif
+ if (!p)
+ {
+ init_thread_data();
+#if defined(BOOST_LOG_USE_COMPILER_TLS)
+ p = m_thread_data_cache;
+#else
+ p = m_thread_data.get();
+#endif
+ }
+ return p;
+ }
+
+ //! The function initializes the logging system
+ static void init_instance()
+ {
+ base_type::get_instance().reset(new core());
+ }
+
+private:
+ //! The method initializes thread-specific data
+ void init_thread_data()
+ {
+ BOOST_LOG_EXPR_IF_MT(scoped_write_lock lock(m_mutex);)
+ if (!m_thread_data.get())
+ {
+ std::auto_ptr< thread_data > p(new thread_data());
+ m_thread_data.reset(p.get());
+#if defined(BOOST_LOG_USE_COMPILER_TLS)
+ m_thread_data_cache = p.release();
+#else
+ p.release();
+#endif
+ }
+ }
+};
+
+#if defined(BOOST_LOG_USE_COMPILER_TLS)
+//! Cached pointer to the thread-specific data
+BOOST_LOG_TLS core::implementation::thread_data* core::implementation::m_thread_data_cache = NULL;
+#endif // defined(BOOST_LOG_USE_COMPILER_TLS)
+
+//! Logging system constructor
+core::core() :
+ m_impl(new implementation())
+{
+}
+
+//! Logging system destructor
+core::~core()
+{
+ delete m_impl;
+ m_impl = NULL;
+}
+
+//! The method returns a pointer to the logging system instance
+BOOST_LOG_API core_ptr core::get()
+{
+ return implementation::get();
+}
+
+//! The method enables or disables logging and returns the previous state of logging flag
+BOOST_LOG_API bool core::set_logging_enabled(bool enabled)
+{
+ BOOST_LOG_EXPR_IF_MT(implementation::scoped_write_lock lock(m_impl->m_mutex);)
+ const bool old_value = m_impl->m_enabled;
+ m_impl->m_enabled = enabled;
+ return old_value;
+}
+
+//! The method allows to detect if logging is enabled
+BOOST_LOG_API bool core::get_logging_enabled() const
+{
+ // Should have a read barrier here, but for performance reasons it is omitted.
+ // The function should be used as a quick check and doesn't need to be reliable.
+ return m_impl->m_enabled;
+}
+
+//! The method adds a new sink
+BOOST_LOG_API void core::add_sink(shared_ptr< sinks::sink > const& s)
+{
+ BOOST_LOG_EXPR_IF_MT(implementation::scoped_write_lock lock(m_impl->m_mutex);)
+ implementation::sink_list::iterator it =
+ std::find(m_impl->m_sinks.begin(), m_impl->m_sinks.end(), s);
+ if (it == m_impl->m_sinks.end())
+ m_impl->m_sinks.push_back(s);
+}
+
+//! The method removes the sink from the output
+BOOST_LOG_API void core::remove_sink(shared_ptr< sinks::sink > const& s)
+{
+ BOOST_LOG_EXPR_IF_MT(implementation::scoped_write_lock lock(m_impl->m_mutex);)
+ implementation::sink_list::iterator it =
+ std::find(m_impl->m_sinks.begin(), m_impl->m_sinks.end(), s);
+ if (it != m_impl->m_sinks.end())
+ m_impl->m_sinks.erase(it);
+}
+
+//! The method removes all registered sinks from the output
+BOOST_LOG_API void core::remove_all_sinks()
+{
+ BOOST_LOG_EXPR_IF_MT(implementation::scoped_write_lock lock(m_impl->m_mutex);)
+ m_impl->m_sinks.clear();
+}
+
+
+//! The method adds an attribute to the global attribute set
+BOOST_LOG_API std::pair< attribute_set::iterator, bool >
+core::add_global_attribute(attribute_name const& name, attribute const& attr)
+{
+ BOOST_LOG_EXPR_IF_MT(implementation::scoped_write_lock lock(m_impl->m_mutex);)
+ return m_impl->m_global_attributes.insert(name, attr);
+}
+
+//! The method removes an attribute from the global attribute set
+BOOST_LOG_API void core::remove_global_attribute(attribute_set::iterator it)
+{
+ BOOST_LOG_EXPR_IF_MT(implementation::scoped_write_lock lock(m_impl->m_mutex);)
+ m_impl->m_global_attributes.erase(it);
+}
+
+//! The method returns the complete set of currently registered global attributes
+BOOST_LOG_API attribute_set core::get_global_attributes() const
+{
+ BOOST_LOG_EXPR_IF_MT(implementation::scoped_read_lock lock(m_impl->m_mutex);)
+ return m_impl->m_global_attributes;
+}
+
+//! The method replaces the complete set of currently registered global attributes with the provided set
+BOOST_LOG_API void core::set_global_attributes(attribute_set const& attrs)
+{
+ BOOST_LOG_EXPR_IF_MT(implementation::scoped_write_lock lock(m_impl->m_mutex);)
+ m_impl->m_global_attributes = attrs;
+}
+
+//! The method adds an attribute to the thread-specific attribute set
+BOOST_LOG_API std::pair< attribute_set::iterator, bool >
+core::add_thread_attribute(attribute_name const& name, attribute const& attr)
+{
+ implementation::thread_data* p = m_impl->get_thread_data();
+ return p->m_thread_attributes.insert(name, attr);
+}
+
+//! The method removes an attribute from the thread-specific attribute set
+BOOST_LOG_API void core::remove_thread_attribute(attribute_set::iterator it)
+{
+ implementation::thread_data* p = m_impl->get_thread_data();
+ p->m_thread_attributes.erase(it);
+}
+
+//! The method returns the complete set of currently registered thread-specific attributes
+BOOST_LOG_API attribute_set core::get_thread_attributes() const
+{
+ implementation::thread_data* p = m_impl->get_thread_data();
+ return p->m_thread_attributes;
+}
+//! The method replaces the complete set of currently registered thread-specific attributes with the provided set
+BOOST_LOG_API void core::set_thread_attributes(attribute_set const& attrs)
+{
+ implementation::thread_data* p = m_impl->get_thread_data();
+ p->m_thread_attributes = attrs;
+}
+
+//! An internal method to set the global filter
+BOOST_LOG_API void core::set_filter(filter const& filter)
+{
+ BOOST_LOG_EXPR_IF_MT(implementation::scoped_write_lock lock(m_impl->m_mutex);)
+ m_impl->m_filter = filter;
+}
+
+//! The method removes the global logging filter
+BOOST_LOG_API void core::reset_filter()
+{
+ BOOST_LOG_EXPR_IF_MT(implementation::scoped_write_lock lock(m_impl->m_mutex);)
+ m_impl->m_filter.reset();
+}
+
+//! The method sets exception handler function
+BOOST_LOG_API void core::set_exception_handler(exception_handler_type const& handler)
+{
+ BOOST_LOG_EXPR_IF_MT(implementation::scoped_write_lock lock(m_impl->m_mutex);)
+ m_impl->m_exception_handler = handler;
+}
+
+//! The method performs flush on all registered sinks.
+BOOST_LOG_API void core::flush()
+{
+ // Acquire exclusive lock to prevent any logging attempts while flushing
+ BOOST_LOG_EXPR_IF_MT(implementation::scoped_write_lock lock(m_impl->m_mutex);)
+ implementation::sink_list::iterator it = m_impl->m_sinks.begin(), end = m_impl->m_sinks.end();
+ for (; it != end; ++it)
+ {
+ try
+ {
+ it->get()->flush();
+ }
+#if !defined(BOOST_LOG_NO_THREADS)
+ catch (thread_interrupted&)
+ {
+ throw;
+ }
+#endif // !defined(BOOST_LOG_NO_THREADS)
+ catch (...)
+ {
+ if (m_impl->m_exception_handler.empty())
+ throw;
+ m_impl->m_exception_handler();
+ }
+ }
+}
+
+//! The method attempts to open a new record to be written
+BOOST_LOG_API record core::open_record(attribute_set const& source_attributes)
+{
+ return m_impl->open_record(source_attributes);
+}
+
+//! The method attempts to open a new record to be written
+BOOST_LOG_API record core::open_record(attribute_value_set const& source_attributes)
+{
+ return m_impl->open_record(source_attributes);
+}
+
+//! The method attempts to open a new record to be written.
+BOOST_LOG_API record core::open_record_move(attribute_value_set& source_attributes)
+{
+ return m_impl->open_record(boost::move(source_attributes));
+}
+
+//! The method pushes the record
+BOOST_LOG_API void core::push_record_move(record& rec)
+{
+ try
+ {
+ record_view rec_view(rec.lock());
+ record_view::private_data* data = static_cast< record_view::private_data* >(rec_view.m_impl.get());
+
+ typedef std::vector< shared_ptr< sinks::sink > > accepting_sinks_t;
+ accepting_sinks_t accepting_sinks(data->accepting_sink_count());
+ shared_ptr< sinks::sink >* const begin = &*accepting_sinks.begin();
+ register shared_ptr< sinks::sink >* end = begin;
+
+ // Lock sinks that are willing to consume the record
+ record_view::private_data::sink_list weak_sinks = data->get_accepting_sinks();
+ record_view::private_data::sink_list::iterator
+ weak_it = weak_sinks.begin(),
+ weak_end = weak_sinks.end();
+ for (; weak_it != weak_end; ++weak_it)
+ {
+ shared_ptr< sinks::sink >& last = *end;
+ weak_it->lock().swap(last);
+ if (last.get())
+ ++end;
+ }
+
+ bool shuffled = (end - begin) <= 1;
+ register shared_ptr< sinks::sink >* it = begin;
+ while (true) try
+ {
+ // First try to distribute load between different sinks
+ register bool all_locked = true;
+ while (it != end)
+ {
+ if (it->get()->try_consume(rec_view))
+ {
+ --end;
+ end->swap(*it);
+ all_locked = false;
+ }
+ else
+ ++it;
+ }
+
+ it = begin;
+ if (begin != end)
+ {
+ if (all_locked)
+ {
+ // If all sinks are busy then block on any
+ if (!shuffled)
+ {
+ std::random_shuffle(begin, end);
+ shuffled = true;
+ }
+
+ it->get()->consume(rec_view);
+ --end;
+ end->swap(*it);
+ }
+ }
+ else
+ break;
+ }
+#if !defined(BOOST_LOG_NO_THREADS)
+ catch (thread_interrupted&)
+ {
+ throw;
+ }
+#endif // !defined(BOOST_LOG_NO_THREADS)
+ catch (...)
+ {
+ // Lock the core to be safe against any attribute or sink set modifications
+ BOOST_LOG_EXPR_IF_MT(implementation::scoped_read_lock lock(m_impl->m_mutex);)
+ if (m_impl->m_exception_handler.empty())
+ throw;
+
+ m_impl->m_exception_handler();
+
+ // Skip the sink that failed to consume the record
+ --end;
+ end->swap(*it);
+ }
+ }
+#if !defined(BOOST_LOG_NO_THREADS)
+ catch (thread_interrupted&)
+ {
+ throw;
+ }
+#endif // !defined(BOOST_LOG_NO_THREADS)
+ catch (...)
+ {
+ // Lock the core to be safe against any attribute or sink set modifications
+ BOOST_LOG_EXPR_IF_MT(implementation::scoped_read_lock lock(m_impl->m_mutex);)
+ if (m_impl->m_exception_handler.empty())
+ throw;
+
+ m_impl->m_exception_handler();
+ }
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>

Added: trunk/libs/log/src/date_time_format_parser.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/date_time_format_parser.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,422 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 30.09.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#include <cstring>
+#include <string>
+#include <algorithm>
+#include <boost/spirit/include/karma_uint.hpp>
+#include <boost/spirit/include/karma_generate.hpp>
+#include <boost/range/iterator_range_core.hpp>
+#include <boost/log/detail/date_time_format_parser.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace karma = boost::spirit::karma;
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+template< typename CharT >
+struct string_constants;
+
+#ifdef BOOST_LOG_USE_CHAR
+
+template< >
+struct string_constants< char >
+{
+ typedef char char_type;
+
+ static const char_type* iso_date_format() { return "%Y%m%d"; }
+ static const char_type* extended_iso_date_format() { return "%Y-%m-%d"; }
+
+ static const char_type* iso_time_format() { return "%H%M%S"; }
+ static const char_type* extended_iso_time_format() { return "%H:%M:%S"; }
+ static const char_type* default_time_format() { return "%H:%M:%S.%f"; }
+};
+
+#endif // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+
+template< >
+struct string_constants< wchar_t >
+{
+ typedef wchar_t char_type;
+
+ static const char_type* iso_date_format() { return L"%Y%m%d"; }
+ static const char_type* extended_iso_date_format() { return L"%Y-%m-%d"; }
+
+ static const char_type* iso_time_format() { return L"%H%M%S"; }
+ static const char_type* extended_iso_time_format() { return L"%H:%M:%S"; }
+ static const char_type* default_time_format() { return L"%H:%M:%S.%f"; }
+};
+
+#endif // BOOST_LOG_USE_WCHAR_T
+
+template< typename CallbackT >
+struct common_flags
+{
+ typedef CallbackT callback_type;
+ typedef typename callback_type::char_type char_type;
+ typedef std::basic_string< char_type > string_type;
+
+ const char_type* parse(const char_type* begin, const char_type* end, callback_type& callback)
+ {
+ switch (begin[1])
+ {
+ case '%':
+ m_literal.push_back('%');
+ break;
+
+ default:
+ flush(callback);
+ callback.on_placeholder(iterator_range< const char_type* >(begin, begin + 2));
+ break;
+ }
+
+ return begin + 2;
+ }
+
+ void add_literal(const char_type* begin, const char_type* end)
+ {
+ m_literal.append(begin, end);
+ }
+
+ void flush(callback_type& callback)
+ {
+ if (!m_literal.empty())
+ {
+ const char_type* p = m_literal.c_str();
+ callback.on_literal(iterator_range< const char_type* >(p, p + m_literal.size()));
+ m_literal.clear();
+ }
+ }
+
+private:
+ string_type m_literal;
+};
+
+template< typename BaseT >
+struct date_flags :
+ public BaseT
+{
+ typedef typename BaseT::callback_type callback_type;
+ typedef typename BaseT::char_type char_type;
+
+ const char_type* parse(const char_type* begin, const char_type* end, callback_type& callback)
+ {
+ typedef string_constants< char_type > constants;
+
+ switch (begin[1])
+ {
+ case 'Y':
+ {
+ this->flush(callback);
+
+ std::size_t len = end - begin;
+ if (len >= 8 && std::memcmp(begin, constants::extended_iso_date_format(), 8 * sizeof(char_type)) == 0)
+ {
+ callback.on_extended_iso_date();
+ return begin + 8;
+ }
+ else if (len >= 6 && std::memcmp(begin, constants::iso_date_format(), 6 * sizeof(char_type)) == 0)
+ {
+ callback.on_iso_date();
+ return begin + 6;
+ }
+ else
+ {
+ callback.on_full_year();
+ }
+ }
+ break;
+
+ case 'y':
+ this->flush(callback);
+ callback.on_short_year();
+ break;
+
+ case 'm':
+ this->flush(callback);
+ callback.on_numeric_month();
+ break;
+
+ case 'B':
+ this->flush(callback);
+ callback.on_full_month();
+ break;
+
+ case 'b':
+ this->flush(callback);
+ callback.on_short_month();
+ break;
+
+ case 'd':
+ this->flush(callback);
+ callback.on_month_day(true);
+ break;
+
+ case 'e':
+ this->flush(callback);
+ callback.on_month_day(false);
+ break;
+
+ case 'w':
+ this->flush(callback);
+ callback.on_numeric_week_day();
+ break;
+
+ case 'A':
+ this->flush(callback);
+ callback.on_full_week_day();
+ break;
+
+ case 'a':
+ this->flush(callback);
+ callback.on_short_week_day();
+ break;
+
+ default:
+ return BaseT::parse(begin, end, callback);
+ }
+
+ return begin + 2;
+ }
+};
+
+template< typename BaseT >
+struct time_flags :
+ public BaseT
+{
+ typedef typename BaseT::callback_type callback_type;
+ typedef typename BaseT::char_type char_type;
+
+ const char_type* parse(const char_type* begin, const char_type* end, callback_type& callback)
+ {
+ typedef string_constants< char_type > constants;
+
+ switch (begin[1])
+ {
+ case 'O':
+ case 'H':
+ {
+ this->flush(callback);
+
+ std::size_t len = end - begin;
+ if (len >= 11 && std::memcmp(begin, constants::default_time_format(), 11 * sizeof(char_type)) == 0)
+ {
+ callback.on_default_time();
+ return begin + 11;
+ }
+ else if (len >= 8 && std::memcmp(begin, constants::extended_iso_time_format(), 8 * sizeof(char_type)) == 0)
+ {
+ callback.on_extended_iso_time();
+ return begin + 8;
+ }
+ else if (len >= 6 && std::memcmp(begin, constants::iso_time_format(), 6 * sizeof(char_type)) == 0)
+ {
+ callback.on_iso_time();
+ return begin + 6;
+ }
+ else
+ {
+ callback.on_hours(true);
+ }
+ }
+ break;
+
+ case 'T':
+ this->flush(callback);
+ callback.on_extended_iso_time();
+ break;
+
+ case 'k':
+ this->flush(callback);
+ callback.on_hours(false);
+ break;
+
+ case 'I':
+ this->flush(callback);
+ callback.on_hours_12(true);
+ break;
+
+ case 'l':
+ this->flush(callback);
+ callback.on_hours_12(false);
+ break;
+
+ case 'M':
+ this->flush(callback);
+ callback.on_minutes();
+ break;
+
+ case 'S':
+ this->flush(callback);
+ callback.on_seconds();
+ break;
+
+ case 'f':
+ this->flush(callback);
+ callback.on_fractional_seconds();
+ break;
+
+ case 'P':
+ this->flush(callback);
+ callback.on_am_pm(false);
+ break;
+
+ case 'p':
+ this->flush(callback);
+ callback.on_am_pm(true);
+ break;
+
+ case 'Q':
+ this->flush(callback);
+ callback.on_extended_iso_time_zone();
+ break;
+
+ case 'q':
+ this->flush(callback);
+ callback.on_iso_time_zone();
+ break;
+
+ case '-':
+ this->flush(callback);
+ callback.on_duration_sign(false);
+ break;
+
+ case '+':
+ this->flush(callback);
+ callback.on_duration_sign(true);
+ break;
+
+ default:
+ return BaseT::parse(begin, end, callback);
+ }
+
+ return begin + 2;
+ }
+};
+
+template< typename CharT, typename ParserT, typename CallbackT >
+inline void parse_format(const CharT* begin, const CharT* end, ParserT& parser, CallbackT& callback)
+{
+ typedef CharT char_type;
+ typedef CallbackT callback_type;
+
+ while (begin != end)
+ {
+ const char_type* p = std::find(begin, end, static_cast< char_type >('%'));
+ parser.add_literal(begin, p);
+
+ if ((end - p) >= 2)
+ {
+ begin = parser.parse(p, end, callback);
+ }
+ else
+ {
+ if (p != end)
+ parser.add_literal(p, end); // a single '%' character at the end of the string
+ begin = end;
+ }
+ }
+
+ parser.flush(callback);
+}
+
+} // namespace
+
+//! Parses the date format string and invokes the callback object
+template< typename CharT >
+void parse_date_format(const CharT* begin, const CharT* end, date_format_parser_callback< CharT >& callback)
+{
+ typedef CharT char_type;
+ typedef date_format_parser_callback< char_type > callback_type;
+ date_flags< common_flags< callback_type > > parser;
+ parse_format(begin, end, parser, callback);
+}
+
+//! Parses the time format string and invokes the callback object
+template< typename CharT >
+void parse_time_format(const CharT* begin, const CharT* end, time_format_parser_callback< CharT >& callback)
+{
+ typedef CharT char_type;
+ typedef time_format_parser_callback< char_type > callback_type;
+ time_flags< common_flags< callback_type > > parser;
+ parse_format(begin, end, parser, callback);
+}
+
+//! Parses the date and time format string and invokes the callback object
+template< typename CharT >
+void parse_date_time_format(const CharT* begin, const CharT* end, date_time_format_parser_callback< CharT >& callback)
+{
+ typedef CharT char_type;
+ typedef date_time_format_parser_callback< char_type > callback_type;
+ date_flags< time_flags< common_flags< callback_type > > > parser;
+ parse_format(begin, end, parser, callback);
+}
+
+template< typename CharT >
+void put_integer(std::basic_string< CharT >& str, uint32_t value, unsigned int width, CharT fill_char)
+{
+ typedef CharT char_type;
+ char_type buf[std::numeric_limits< uint32_t >::digits10 + 2];
+ char_type* p = buf;
+
+ typedef karma::uint_generator< uint32_t, 10 > uint_gen;
+ karma::generate(p, uint_gen(), value);
+ const std::size_t len = p - buf;
+ if (len < width)
+ str.insert(str.end(), width - len, fill_char);
+ str.append(buf, p);
+}
+
+#ifdef BOOST_LOG_USE_CHAR
+
+template BOOST_LOG_API
+void parse_date_format(const char* begin, const char* end, date_format_parser_callback< char >& callback);
+template BOOST_LOG_API
+void parse_time_format(const char* begin, const char* end, time_format_parser_callback< char >& callback);
+template BOOST_LOG_API
+void parse_date_time_format(const char* begin, const char* end, date_time_format_parser_callback< char >& callback);
+template BOOST_LOG_API
+void put_integer(std::basic_string< char >& str, uint32_t value, unsigned int width, char fill_char);
+
+#endif // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+
+template BOOST_LOG_API
+void parse_date_format(const wchar_t* begin, const wchar_t* end, date_format_parser_callback< wchar_t >& callback);
+template BOOST_LOG_API
+void parse_time_format(const wchar_t* begin, const wchar_t* end, time_format_parser_callback< wchar_t >& callback);
+template BOOST_LOG_API
+void parse_date_time_format(const wchar_t* begin, const wchar_t* end, date_time_format_parser_callback< wchar_t >& callback);
+template BOOST_LOG_API
+void put_integer(std::basic_string< wchar_t >& str, uint32_t value, unsigned int width, wchar_t fill_char);
+
+#endif // BOOST_LOG_USE_WCHAR_T
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>

Added: trunk/libs/log/src/debug_output_backend.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/debug_output_backend.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,78 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 08.11.2008
+ *
+ * \brief A logging sink backend that uses debugger output
+ */
+
+#ifndef BOOST_LOG_WITHOUT_DEBUG_OUTPUT
+
+#include "windows_version.hpp"
+#include <string>
+#include <boost/log/sinks/debug_output_backend.hpp>
+#include <windows.h>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+#if defined(BOOST_LOG_USE_CHAR)
+ inline void output_debug_string(const char* str)
+ {
+ OutputDebugStringA(str);
+ }
+#endif // defined(BOOST_LOG_USE_CHAR)
+#if defined(BOOST_LOG_USE_WCHAR_T)
+ inline void output_debug_string(const wchar_t* str)
+ {
+ OutputDebugStringW(str);
+ }
+#endif // defined(BOOST_LOG_USE_WCHAR_T)
+
+} // namespace
+
+template< typename CharT >
+BOOST_LOG_API basic_debug_output_backend< CharT >::basic_debug_output_backend()
+{
+}
+
+template< typename CharT >
+BOOST_LOG_API basic_debug_output_backend< CharT >::~basic_debug_output_backend()
+{
+}
+
+//! The method puts the formatted message to the event log
+template< typename CharT >
+BOOST_LOG_API void basic_debug_output_backend< CharT >::consume(record_view const&, string_type const& formatted_message)
+{
+ output_debug_string(formatted_message.c_str());
+}
+
+#ifdef BOOST_LOG_USE_CHAR
+template class basic_debug_output_backend< char >;
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+template class basic_debug_output_backend< wchar_t >;
+#endif
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // !defined(BOOST_LOG_WITHOUT_DEBUG_OUTPUT)

Added: trunk/libs/log/src/default_attribute_names.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/default_attribute_names.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,121 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 13.07.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#include <boost/shared_ptr.hpp>
+#include <boost/log/detail/default_attribute_names.hpp>
+#include <boost/log/detail/singleton.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+namespace default_attribute_names {
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+ class names :
+ public lazy_singleton< names, shared_ptr< names > >
+ {
+ private:
+ typedef lazy_singleton< names, shared_ptr< names > > base_type;
+
+#if !defined(BOOST_LOG_BROKEN_FRIEND_TEMPLATE_INSTANTIATIONS)
+ friend class lazy_singleton< names, shared_ptr< names > >;
+#else
+ friend class base_type;
+#endif
+
+ public:
+ const attribute_name severity;
+ const attribute_name channel;
+ const attribute_name message;
+ const attribute_name line_id;
+ const attribute_name timestamp;
+ const attribute_name process_id;
+ const attribute_name thread_id;
+
+ private:
+ names() :
+ severity("Severity"),
+ channel("Channel"),
+ message("Message"),
+ line_id("LineID"),
+ timestamp("TimeStamp"),
+ process_id("ProcessID"),
+ thread_id("ThreadID")
+ {
+ }
+
+ static void init_instance()
+ {
+ get_instance().reset(new names());
+ }
+
+ public:
+ static names& get()
+ {
+ return *base_type::get();
+ }
+ };
+
+} // namespace
+
+BOOST_LOG_API attribute_name severity()
+{
+ return names::get().severity;
+}
+
+BOOST_LOG_API attribute_name channel()
+{
+ return names::get().channel;
+}
+
+BOOST_LOG_API attribute_name message()
+{
+ return names::get().message;
+}
+
+BOOST_LOG_API attribute_name line_id()
+{
+ return names::get().line_id;
+}
+
+BOOST_LOG_API attribute_name timestamp()
+{
+ return names::get().timestamp;
+}
+
+BOOST_LOG_API attribute_name process_id()
+{
+ return names::get().process_id;
+}
+
+BOOST_LOG_API attribute_name thread_id()
+{
+ return names::get().thread_id;
+}
+
+} // namespace default_attribute_names
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>

Added: trunk/libs/log/src/default_filter_factory.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/default_filter_factory.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,397 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_filter_factory.hpp
+ * \author Andrey Semashev
+ * \date 29.05.2010
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#include <string>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/spirit/include/qi_core.hpp>
+#include <boost/spirit/include/qi_eoi.hpp>
+#include <boost/spirit/include/qi_as.hpp>
+#include <boost/log/exceptions.hpp>
+#include <boost/log/attributes/value_visitation.hpp>
+#include <boost/log/expressions/predicates/has_attr.hpp>
+#include <boost/log/utility/type_dispatch/standard_types.hpp>
+#include <boost/log/utility/string_literal.hpp>
+#include <boost/log/utility/functional/logical.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/bind.hpp>
+#include <boost/log/utility/functional/as_action.hpp>
+#include <boost/log/utility/functional/save_result.hpp>
+#include <boost/log/detail/code_conversion.hpp>
+#include <boost/log/support/xpressive.hpp>
+#include <boost/xpressive/xpressive_dynamic.hpp>
+#if defined(BOOST_LOG_USE_CHAR) && defined(BOOST_LOG_USE_WCHAR_T)
+#include <boost/fusion/container/set.hpp>
+#include <boost/fusion/sequence/intrinsic/at_key.hpp>
+#include <boost/fusion/algorithm/iteration/for_each.hpp>
+#endif
+#include "default_filter_factory.hpp"
+#include "parser_utils.hpp"
+#include "spirit_encoding.hpp"
+#include <boost/log/detail/header.hpp>
+
+namespace qi = boost::spirit::qi;
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+template< typename CharT >
+template< typename ValueT, typename PredicateT >
+struct default_filter_factory< CharT >::predicate_wrapper
+{
+ typedef typename PredicateT::result_type result_type;
+
+ explicit predicate_wrapper(attribute_name const& name, PredicateT const& pred) : m_name(name), m_visitor(pred)
+ {
+ }
+
+ template< typename T >
+ result_type operator() (T const& arg) const
+ {
+ bool res = false;
+ boost::log::visit< ValueT >(m_name, arg, save_result_wrapper< PredicateT const&, bool >(m_visitor, res));
+ return res;
+ }
+
+private:
+ attribute_name m_name;
+ const PredicateT m_visitor;
+};
+
+template< typename CharT >
+template< typename RelationT >
+struct default_filter_factory< CharT >::on_integral_argument
+{
+ typedef void result_type;
+
+ on_integral_argument(attribute_name const& name, filter& f) : m_name(name), m_filter(f)
+ {
+ }
+
+ result_type operator() (long val) const
+ {
+ typedef binder2nd< RelationT, long > predicate;
+ m_filter = predicate_wrapper< log::integral_types::type, predicate >(m_name, predicate(RelationT(), val));
+ }
+
+private:
+ attribute_name m_name;
+ filter& m_filter;
+};
+
+template< typename CharT >
+template< typename RelationT >
+struct default_filter_factory< CharT >::on_fp_argument
+{
+ typedef void result_type;
+
+ on_fp_argument(attribute_name const& name, filter& f) : m_name(name), m_filter(f)
+ {
+ }
+
+ result_type operator() (double val) const
+ {
+ typedef binder2nd< RelationT, double > predicate;
+ m_filter = predicate_wrapper< log::floating_point_types::type, predicate >(m_name, predicate(RelationT(), val));
+ }
+
+private:
+ attribute_name m_name;
+ filter& m_filter;
+};
+
+template< typename CharT >
+template< typename RelationT >
+struct default_filter_factory< CharT >::on_string_argument
+{
+ typedef void result_type;
+
+#if defined(BOOST_LOG_USE_CHAR) && defined(BOOST_LOG_USE_WCHAR_T)
+ //! A special filtering predicate that adopts the string operand to the attribute value character type
+ struct predicate :
+ public RelationT
+ {
+ struct initializer
+ {
+ typedef void result_type;
+
+ explicit initializer(string_type const& val) : m_initializer(val)
+ {
+ }
+
+ template< typename T >
+ result_type operator() (T& val) const
+ {
+ try
+ {
+ log::aux::code_convert(m_initializer, val);
+ }
+ catch (...)
+ {
+ val.clear();
+ }
+ }
+
+ private:
+ string_type const& m_initializer;
+ };
+
+ typedef typename RelationT::result_type result_type;
+
+ explicit predicate(RelationT const& rel, string_type const& operand) : RelationT(rel)
+ {
+ fusion::for_each(m_operands, initializer(operand));
+ }
+
+ template< typename T >
+ result_type operator() (T const& val) const
+ {
+ typedef std::basic_string< typename T::value_type > operand_type;
+ return RelationT::operator() (val, fusion::at_key< operand_type >(m_operands));
+ }
+
+ private:
+ fusion::set< std::string, std::wstring > m_operands;
+ };
+#else
+ typedef binder2nd< RelationT, string_type > predicate;
+#endif
+
+ on_string_argument(attribute_name const& name, filter& f) : m_name(name), m_filter(f)
+ {
+ }
+
+ result_type operator() (string_type const& val) const
+ {
+ m_filter = predicate_wrapper< log::string_types::type, predicate >(m_name, predicate(RelationT(), val));
+ }
+
+private:
+ attribute_name m_name;
+ filter& m_filter;
+};
+
+template< typename CharT >
+template< typename RelationT >
+struct default_filter_factory< CharT >::on_regex_argument
+{
+ typedef void result_type;
+
+#if defined(BOOST_LOG_USE_CHAR) && defined(BOOST_LOG_USE_WCHAR_T)
+ //! A special filtering predicate that adopts the string operand to the attribute value character type
+ struct predicate :
+ public RelationT
+ {
+ struct initializer
+ {
+ typedef void result_type;
+
+ explicit initializer(string_type const& val) : m_initializer(val)
+ {
+ }
+
+ template< typename T >
+ result_type operator() (T& val) const
+ {
+ try
+ {
+ typedef typename T::char_type char_type;
+ std::basic_string< char_type > str;
+ log::aux::code_convert(m_initializer, str);
+ val = T::compile(str.c_str(), str.size(), T::ECMAScript | T::optimize);
+ }
+ catch (...)
+ {
+ }
+ }
+
+ private:
+ string_type const& m_initializer;
+ };
+
+ typedef typename RelationT::result_type result_type;
+
+ explicit predicate(RelationT const& rel, string_type const& operand) : RelationT(rel)
+ {
+ fusion::for_each(m_operands, initializer(operand));
+ }
+
+ template< typename T >
+ result_type operator() (T const& val) const
+ {
+ typedef typename T::value_type char_type;
+ typedef xpressive::basic_regex< const char_type* > regex_type;
+ return RelationT::operator() (val, fusion::at_key< regex_type >(m_operands));
+ }
+
+ private:
+ fusion::set< xpressive::cregex, xpressive::wcregex > m_operands;
+ };
+#else
+ //! A special filtering predicate that adopts the string operand to the attribute value character type
+ struct predicate :
+ public RelationT
+ {
+ typedef typename RelationT::result_type result_type;
+ typedef xpressive::basic_regex< typename string_type::value_type const* > regex_type;
+
+ explicit predicate(RelationT const& rel, string_type const& operand) :
+ RelationT(rel),
+ m_operand(regex_type::compile(operand.c_str(), operand.size(), regex_type::ECMAScript | regex_type::optimize))
+ {
+ }
+
+ template< typename T >
+ result_type operator() (T const& val) const
+ {
+ return RelationT::operator() (val, m_operand);
+ }
+
+ private:
+ regex_type m_operand;
+ };
+#endif
+
+ on_regex_argument(attribute_name const& name, filter& f) : m_name(name), m_filter(f)
+ {
+ }
+
+ result_type operator() (string_type const& val) const
+ {
+ m_filter = predicate_wrapper< log::string_types::type, predicate >(m_name, predicate(RelationT(), val));
+ }
+
+private:
+ attribute_name m_name;
+ filter& m_filter;
+};
+
+
+//! The callback for equality relation filter
+template< typename CharT >
+filter default_filter_factory< CharT >::on_equality_relation(attribute_name const& name, string_type const& arg)
+{
+ return parse_argument< equal_to >(name, arg);
+}
+
+//! The callback for inequality relation filter
+template< typename CharT >
+filter default_filter_factory< CharT >::on_inequality_relation(attribute_name const& name, string_type const& arg)
+{
+ return parse_argument< not_equal_to >(name, arg);
+}
+
+//! The callback for less relation filter
+template< typename CharT >
+filter default_filter_factory< CharT >::on_less_relation(attribute_name const& name, string_type const& arg)
+{
+ return parse_argument< less >(name, arg);
+}
+
+//! The callback for greater relation filter
+template< typename CharT >
+filter default_filter_factory< CharT >::on_greater_relation(attribute_name const& name, string_type const& arg)
+{
+ return parse_argument< greater >(name, arg);
+}
+
+//! The callback for less or equal relation filter
+template< typename CharT >
+filter default_filter_factory< CharT >::on_less_or_equal_relation(attribute_name const& name, string_type const& arg)
+{
+ return parse_argument< less_equal >(name, arg);
+}
+
+//! The callback for greater or equal relation filter
+template< typename CharT >
+filter default_filter_factory< CharT >::on_greater_or_equal_relation(attribute_name const& name, string_type const& arg)
+{
+ return parse_argument< greater_equal >(name, arg);
+}
+
+//! The callback for custom relation filter
+template< typename CharT >
+filter default_filter_factory< CharT >::on_custom_relation(attribute_name const& name, string_type const& rel, string_type const& arg)
+{
+ typedef log::aux::char_constants< char_type > constants;
+
+ filter f;
+ if (rel == constants::begins_with_keyword())
+ on_string_argument< begins_with_fun >(name, f)(arg);
+ else if (rel == constants::ends_with_keyword())
+ on_string_argument< ends_with_fun >(name, f)(arg);
+ else if (rel == constants::contains_keyword())
+ on_string_argument< contains_fun >(name, f)(arg);
+ else if (rel == constants::matches_keyword())
+ on_regex_argument< matches_fun >(name, f)(arg);
+ else
+ {
+ BOOST_LOG_THROW_DESCR(parse_error, "The custom attribute relation \"" + log::aux::to_narrow(rel) + "\" is not supported");
+ }
+
+ return boost::move(f);
+}
+
+
+//! The function parses the argument value for a binary relation and constructs the corresponding filter
+template< typename CharT >
+template< typename RelationT >
+filter default_filter_factory< CharT >::parse_argument(attribute_name const& name, string_type const& arg)
+{
+ typedef log::aux::encoding_specific< typename log::aux::encoding< char_type >::type > encoding_specific;
+ const qi::real_parser< double, qi::strict_real_policies< double > > real_;
+
+ filter f;
+ const on_fp_argument< RelationT > on_fp(name, f);
+ const on_integral_argument< RelationT > on_int(name, f);
+ const on_string_argument< RelationT > on_str(name, f);
+
+ const bool res = qi::parse
+ (
+ arg.c_str(), arg.c_str() + arg.size(),
+ (
+ real_[boost::log::as_action(on_fp)] |
+ qi::long_[boost::log::as_action(on_int)] |
+ qi::as< string_type >()[ +encoding_specific::print ][boost::log::as_action(on_str)]
+ ) >> qi::eoi
+ );
+
+ if (!res)
+ BOOST_LOG_THROW_DESCR(parse_error, "Failed to parse relation operand");
+
+ return boost::move(f);
+}
+
+// Explicitly instantiate factory implementation
+#ifdef BOOST_LOG_USE_CHAR
+template class default_filter_factory< char >;
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+template class default_filter_factory< wchar_t >;
+#endif
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>

Added: trunk/libs/log/src/default_filter_factory.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/default_filter_factory.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,84 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_filter_factory.hpp
+ * \author Andrey Semashev
+ * \date 29.05.2010
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#ifndef BOOST_DEFAULT_FILTER_FACTORY_HPP_INCLUDED_
+#define BOOST_DEFAULT_FILTER_FACTORY_HPP_INCLUDED_
+
+#include <boost/log/utility/setup/filter_parser.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! The default filter factory that supports creating filters for the standard types (see utility/type_dispatch/standard_types.hpp)
+template< typename CharT >
+class default_filter_factory :
+ public filter_factory< CharT >
+{
+ //! Base type
+ typedef filter_factory< CharT > base_type;
+ //! Self type
+ typedef default_filter_factory< CharT > this_type;
+
+ template< typename ValueT, typename PredicateT >
+ struct predicate_wrapper;
+
+ template< typename RelationT >
+ struct on_integral_argument;
+ template< typename RelationT >
+ struct on_fp_argument;
+ template< typename RelationT >
+ struct on_string_argument;
+ template< typename RelationT >
+ struct on_regex_argument;
+
+public:
+ // Type imports
+ typedef typename base_type::char_type char_type;
+ typedef typename base_type::string_type string_type;
+
+ //! The callback for equality relation filter
+ virtual filter on_equality_relation(attribute_name const& name, string_type const& arg);
+ //! The callback for inequality relation filter
+ virtual filter on_inequality_relation(attribute_name const& name, string_type const& arg);
+ //! The callback for less relation filter
+ virtual filter on_less_relation(attribute_name const& name, string_type const& arg);
+ //! The callback for greater relation filter
+ virtual filter on_greater_relation(attribute_name const& name, string_type const& arg);
+ //! The callback for less or equal relation filter
+ virtual filter on_less_or_equal_relation(attribute_name const& name, string_type const& arg);
+ //! The callback for greater or equal relation filter
+ virtual filter on_greater_or_equal_relation(attribute_name const& name, string_type const& arg);
+
+ //! The callback for custom relation filter
+ virtual filter on_custom_relation(attribute_name const& name, string_type const& rel, string_type const& arg);
+
+ //! The function parses the argument value for a binary relation and constructs the corresponding filter
+ template< typename RelationT >
+ static filter parse_argument(attribute_name const& name, string_type const& arg);
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_DEFAULT_FILTER_FACTORY_HPP_INCLUDED_

Added: trunk/libs/log/src/default_sink.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/default_sink.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,207 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_sink.cpp
+ * \author Andrey Semashev
+ * \date 19.04.2007
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#include <cstdio>
+#include <boost/optional/optional.hpp>
+#include <boost/log/detail/config.hpp>
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/thread/locks.hpp>
+#include <boost/log/detail/thread_id.hpp>
+#endif
+#include <boost/log/detail/default_attribute_names.hpp>
+#include <boost/date_time/microsec_time_clock.hpp>
+#include <boost/date_time/time_resolution_traits.hpp>
+#include <boost/date_time/gregorian/gregorian_types.hpp>
+#include "default_sink.hpp"
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+namespace aux {
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+//! A special time point type that contains decomposed date and time to avoid excessive calculations
+struct decomposed_time_point
+{
+ struct date_type :
+ public gregorian::greg_year_month_day
+ {
+ date_type(year_type y, month_type m, day_type d) :
+ gregorian::greg_year_month_day(y, m, d)
+ {
+ }
+ };
+
+ struct time_duration_type :
+ public date_time::micro_res
+ {
+ typedef date_time::micro_res rep_type;
+
+ hour_type hours;
+ min_type minutes;
+ sec_type seconds;
+ fractional_seconds_type useconds;
+
+ time_duration_type(hour_type h, min_type m, sec_type s, fractional_seconds_type u) :
+ hours(h),
+ minutes(m),
+ seconds(s),
+ useconds(u)
+ {
+ }
+ };
+
+ date_type date;
+ time_duration_type time;
+
+ decomposed_time_point(date_type const& d, time_duration_type const& t) :
+ date(d),
+ time(t)
+ {
+ }
+};
+
+inline const char* severity_level_to_string(boost::log::trivial::severity_level lvl)
+{
+ switch (lvl)
+ {
+ case boost::log::trivial::trace:
+ return "[trace] ";
+ case boost::log::trivial::debug:
+ return "[debug] ";
+ case boost::log::trivial::info:
+ return "[info] ";
+ case boost::log::trivial::warning:
+ return "[warning]";
+ case boost::log::trivial::error:
+ return "[error] ";
+ case boost::log::trivial::fatal:
+ return "[fatal] ";
+ default:
+ return "[-] ";
+ }
+}
+
+struct message_printer
+{
+ typedef void result_type;
+
+ explicit message_printer(boost::log::trivial::severity_level lvl) : m_level(lvl)
+ {
+ }
+
+#ifdef BOOST_LOG_USE_CHAR
+
+ result_type operator() (std::string const& msg) const
+ {
+ const decomposed_time_point now = date_time::microsec_clock< decomposed_time_point >::local_time();
+
+ std::printf("[%04u-%02u-%02u %02u:%02u:%02u.%06u] "
+#if !defined(BOOST_LOG_NO_THREADS)
+ "[0x%08x] "
+#endif
+ "%s %s\n",
+ static_cast< unsigned int >(now.date.year),
+ static_cast< unsigned int >(now.date.month),
+ static_cast< unsigned int >(now.date.day),
+ static_cast< unsigned int >(now.time.hours),
+ static_cast< unsigned int >(now.time.minutes),
+ static_cast< unsigned int >(now.time.seconds),
+ static_cast< unsigned int >(now.time.useconds),
+#if !defined(BOOST_LOG_NO_THREADS)
+ static_cast< unsigned int >(boost::log::aux::this_thread::get_id().native_id()),
+#endif
+ severity_level_to_string(m_level),
+ msg.c_str());
+ }
+
+#endif
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+
+ result_type operator() (std::wstring const& msg) const
+ {
+ const decomposed_time_point now = date_time::microsec_clock< decomposed_time_point >::local_time();
+
+ std::printf("[%04u-%02u-%02u %02u:%02u:%02u.%06u] "
+#if !defined(BOOST_LOG_NO_THREADS)
+ "[0x%08x] "
+#endif
+ "%s %ls\n",
+ static_cast< unsigned int >(now.date.year),
+ static_cast< unsigned int >(now.date.month),
+ static_cast< unsigned int >(now.date.day),
+ static_cast< unsigned int >(now.time.hours),
+ static_cast< unsigned int >(now.time.minutes),
+ static_cast< unsigned int >(now.time.seconds),
+ static_cast< unsigned int >(now.time.useconds),
+#if !defined(BOOST_LOG_NO_THREADS)
+ static_cast< unsigned int >(boost::log::aux::this_thread::get_id().native_id()),
+#endif
+ severity_level_to_string(m_level),
+ msg.c_str());
+ }
+
+#endif
+
+private:
+ const boost::log::trivial::severity_level m_level;
+};
+
+} // namespace
+
+default_sink::default_sink() :
+ sink(false),
+ m_severity_name(boost::log::aux::default_attribute_names::severity()),
+ m_message_name(boost::log::aux::default_attribute_names::message()),
+ m_severity_extractor(boost::log::trivial::info)
+{
+}
+
+default_sink::~default_sink()
+{
+}
+
+bool default_sink::will_consume(attribute_value_set const&)
+{
+ return true;
+}
+
+void default_sink::consume(record_view const& rec)
+{
+ BOOST_LOG_EXPR_IF_MT(lock_guard< mutex_type > lock(m_mutex);)
+ m_message_visitor(m_message_name, rec.attribute_values(), message_printer(m_severity_extractor(m_severity_name, rec).get()));
+}
+
+void default_sink::flush()
+{
+ BOOST_LOG_EXPR_IF_MT(lock_guard< mutex_type > lock(m_mutex);)
+ fflush(stdout);
+}
+
+} // namespace aux
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>

Added: trunk/libs/log/src/default_sink.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/default_sink.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,75 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_sink.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/libs/log/doc/log.html.
+ */
+
+#ifndef BOOST_LOG_DEFAULT_SINK_HPP_INCLUDED_
+#define BOOST_LOG_DEFAULT_SINK_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/sinks/sink.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/value_extraction.hpp>
+#include <boost/log/attributes/value_visitation.hpp>
+#include <boost/log/attributes/fallback_policy.hpp>
+#include <boost/log/expressions/message.hpp>
+#include <boost/log/trivial.hpp>
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/thread/mutex.hpp>
+#endif
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+namespace aux {
+
+//! The default sink to be used when no sinks are registered in the logging core
+class default_sink :
+ public sink
+{
+private:
+#if !defined(BOOST_LOG_NO_THREADS)
+ typedef mutex mutex_type;
+ mutex_type m_mutex;
+#endif
+ attribute_name const m_severity_name, m_message_name;
+ value_extractor< boost::log::trivial::severity_level, fallback_to_default< boost::log::trivial::severity_level > > const m_severity_extractor;
+ value_visitor_invoker< expressions::tag::message::value_type > m_message_visitor;
+
+public:
+ default_sink();
+ ~default_sink();
+ bool will_consume(attribute_value_set const&);
+ void consume(record_view const& rec);
+ void flush();
+};
+
+} // namespace aux
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DEFAULT_SINK_HPP_INCLUDED_

Added: trunk/libs/log/src/event.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/event.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,201 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 24.07.2011
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#include <boost/log/detail/config.hpp>
+
+#ifndef BOOST_LOG_NO_THREADS
+
+#include <boost/cstdint.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/log/detail/event.hpp>
+
+#if defined(BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE)
+
+#if defined(__GNUC__) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
+#define BOOST_LOG_EVENT_TRY_SET(ref) (__sync_lock_test_and_set(&ref, 1U) == 0U)
+#define BOOST_LOG_EVENT_RESET(ref) __sync_lock_release(&ref)
+#else
+#error Boost.Log internal error: BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE must only be defined when atomic ops are available
+#endif
+#include <errno.h>
+#include <semaphore.h>
+
+#elif defined(BOOST_LOG_EVENT_USE_WINAPI)
+
+#include "windows_version.hpp"
+#include <windows.h>
+#include <boost/detail/interlocked.hpp>
+
+#else
+
+#include <boost/thread/locks.hpp>
+
+#endif
+
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+#if defined(BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE)
+
+//! Default constructor
+BOOST_LOG_API sem_based_event::sem_based_event() : m_state(0U)
+{
+ if (sem_init(&m_semaphore, 0, 0) != 0)
+ {
+ BOOST_THROW_EXCEPTION(system::system_error(
+ errno, system::system_category(), "Failed to initialize semaphore"));
+ }
+}
+
+//! Destructor
+BOOST_LOG_API sem_based_event::~sem_based_event()
+{
+ sem_destroy(&m_semaphore);
+}
+
+//! Waits for the object to become signalled
+BOOST_LOG_API void sem_based_event::wait()
+{
+ while (true)
+ {
+ if (sem_wait(&m_semaphore) != 0)
+ {
+ if (errno != EINTR)
+ {
+ BOOST_THROW_EXCEPTION(system::system_error(
+ errno, system::system_category(), "Failed to block on the semaphore"));
+ }
+ }
+ else
+ break;
+ }
+ BOOST_LOG_EVENT_RESET(m_state);
+}
+
+//! Sets the object to a signalled state
+BOOST_LOG_API void sem_based_event::set_signalled()
+{
+ if (BOOST_LOG_EVENT_TRY_SET(m_state))
+ {
+ if (sem_post(&m_semaphore) != 0)
+ {
+ BOOST_LOG_EVENT_RESET(m_state);
+ BOOST_THROW_EXCEPTION(system::system_error(
+ errno, system::system_category(), "Failed to wake the blocked thread"));
+ }
+ }
+}
+
+#elif defined(BOOST_LOG_EVENT_USE_WINAPI)
+
+//! Default constructor
+BOOST_LOG_API winapi_based_event::winapi_based_event() :
+ m_state(0),
+ m_event(CreateEventA(NULL, false, false, NULL))
+{
+ if (!m_event)
+ {
+ BOOST_THROW_EXCEPTION(system::system_error(
+ GetLastError(), system::system_category(), "Failed to create Windows event"));
+ }
+}
+
+//! Destructor
+BOOST_LOG_API winapi_based_event::~winapi_based_event()
+{
+ CloseHandle(m_event);
+}
+
+//! Waits for the object to become signalled
+BOOST_LOG_API void winapi_based_event::wait()
+{
+ // On Windows we assume that memory view is always actual (Intel x86 and x86_64 arch)
+ if (const_cast< volatile boost::uint32_t& >(m_state) == 0)
+ {
+ if (WaitForSingleObject(m_event, INFINITE) != 0)
+ {
+ BOOST_THROW_EXCEPTION(system::system_error(
+ GetLastError(), system::system_category(), "Failed to block on Windows event"));
+ }
+ }
+ const_cast< volatile boost::uint32_t& >(m_state) = 0;
+}
+
+//! Sets the object to a signalled state
+BOOST_LOG_API void winapi_based_event::set_signalled()
+{
+ if (BOOST_INTERLOCKED_COMPARE_EXCHANGE(reinterpret_cast< long* >(&m_state), 1, 0) == 0)
+ {
+ if (SetEvent(m_event) == 0)
+ {
+ const_cast< volatile boost::uint32_t& >(m_state) = 0;
+ BOOST_THROW_EXCEPTION(system::system_error(
+ GetLastError(), system::system_category(), "Failed to wake the blocked thread"));
+ }
+ }
+}
+
+#else
+
+//! Default constructor
+BOOST_LOG_API generic_event::generic_event() : m_state(false)
+{
+}
+
+//! Destructor
+BOOST_LOG_API generic_event::~generic_event()
+{
+}
+
+//! Waits for the object to become signalled
+BOOST_LOG_API void generic_event::wait()
+{
+ boost::unique_lock< boost::mutex > lock(m_mutex);
+ while (!m_state)
+ {
+ m_cond.wait(lock);
+ }
+ m_state = false;
+}
+
+//! Sets the object to a signalled state
+BOOST_LOG_API void generic_event::set_signalled()
+{
+ boost::lock_guard< boost::mutex > lock(m_mutex);
+ if (!m_state)
+ {
+ m_state = true;
+ m_cond.notify_one();
+ }
+}
+
+#endif
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_NO_THREADS

Added: trunk/libs/log/src/event_log_backend.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/event_log_backend.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,624 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 07.11.2008
+ *
+ * \brief A logging sink backend that uses Windows NT event log API
+ * for signalling application events.
+ */
+
+#ifndef BOOST_LOG_WITHOUT_EVENT_LOG
+
+#include "windows_version.hpp"
+#include <memory>
+#include <string>
+#include <vector>
+#include <ostream>
+#include <stdexcept>
+#include <boost/scoped_array.hpp>
+#include <boost/log/exceptions.hpp>
+#include <boost/log/sinks/event_log_backend.hpp>
+#include <boost/log/sinks/event_log_constants.hpp>
+#include <boost/log/utility/once_block.hpp>
+#include <boost/log/detail/cleanup_scope_guard.hpp>
+#include <boost/log/detail/attachable_sstream_buf.hpp>
+#include <boost/log/detail/code_conversion.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include "event_log_registry.hpp"
+#include <windows.h>
+#include <psapi.h>
+#include "simple_event_log.h"
+#include <boost/log/detail/header.hpp>
+
+#ifdef _MSC_VER
+#pragma comment(lib, "psapi.lib")
+#pragma comment(lib, "advapi32.lib")
+#endif
+
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+namespace event_log {
+
+ //! The function constructs log record level from an integer
+ BOOST_LOG_API event_type make_event_type(unsigned short lev)
+ {
+ switch (lev)
+ {
+ case success: return success;
+ case info: return info;
+ case warning: return warning;
+ case error: return error;
+ default:
+ BOOST_THROW_EXCEPTION(std::out_of_range("Windows NT event type is out of range"));
+ BOOST_LOG_UNREACHABLE();
+ return info; // to get rid of warnings
+ }
+ }
+
+} // namespace event_log
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+#ifdef BOOST_LOG_USE_CHAR
+ //! A simple forwarder to the ReportEvent API
+ inline BOOL report_event(
+ HANDLE hEventLog,
+ WORD wType,
+ WORD wCategory,
+ DWORD dwEventID,
+ PSID lpUserSid,
+ WORD wNumStrings,
+ DWORD dwDataSize,
+ const char** lpStrings,
+ LPVOID lpRawData)
+ {
+ return ReportEventA(hEventLog, wType, wCategory, dwEventID, lpUserSid, wNumStrings, dwDataSize, lpStrings, lpRawData);
+ }
+ //! A simple forwarder to the GetModuleFileName API
+ inline DWORD get_module_file_name(HMODULE hModule, char* lpFilename, DWORD nSize)
+ {
+ return GetModuleFileNameA(hModule, lpFilename, nSize);
+ }
+ //! A simple forwarder to the RegisterEventSource API
+ inline HANDLE register_event_source(const char* lpUNCServerName, const char* lpSourceName)
+ {
+ return RegisterEventSourceA(lpUNCServerName, lpSourceName);
+ }
+ //! The function completes default source name for the sink backend
+ inline void complete_default_simple_event_log_source_name(std::string& name)
+ {
+ name += " simple event source";
+ }
+ //! The function completes default source name for the sink backend
+ inline void complete_default_event_log_source_name(std::string& name)
+ {
+ name += " event source";
+ }
+#endif // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+ //! A simple forwarder to the ReportEvent API
+ inline BOOL report_event(
+ HANDLE hEventLog,
+ WORD wType,
+ WORD wCategory,
+ DWORD dwEventID,
+ PSID lpUserSid,
+ WORD wNumStrings,
+ DWORD dwDataSize,
+ const wchar_t** lpStrings,
+ LPVOID lpRawData)
+ {
+ return ReportEventW(hEventLog, wType, wCategory, dwEventID, lpUserSid, wNumStrings, dwDataSize, lpStrings, lpRawData);
+ }
+ //! A simple forwarder to the GetModuleFileName API
+ inline DWORD get_module_file_name(HMODULE hModule, wchar_t* lpFilename, DWORD nSize)
+ {
+ return GetModuleFileNameW(hModule, lpFilename, nSize);
+ }
+ //! A simple forwarder to the RegisterEventSource API
+ inline HANDLE register_event_source(const wchar_t* lpUNCServerName, const wchar_t* lpSourceName)
+ {
+ return RegisterEventSourceW(lpUNCServerName, lpSourceName);
+ }
+ //! The function completes default source name for the sink backend
+ inline void complete_default_simple_event_log_source_name(std::wstring& name)
+ {
+ name += L" simple event source";
+ }
+ //! The function completes default source name for the sink backend
+ inline void complete_default_event_log_source_name(std::wstring& name)
+ {
+ name += L" event source";
+ }
+#endif // BOOST_LOG_USE_WCHAR_T
+
+ //! The function finds the handle for the current module
+ void init_self_module_handle(HMODULE& handle)
+ {
+ // Acquire all modules of the current process
+ HANDLE hProcess = GetCurrentProcess();
+ std::vector< HMODULE > modules;
+ DWORD module_count = 1024;
+ do
+ {
+ modules.resize(module_count, HMODULE(0));
+ BOOL res = EnumProcessModules(
+ hProcess,
+ &modules[0],
+ static_cast< DWORD >(modules.size() * sizeof(HMODULE)),
+ &module_count);
+ module_count /= sizeof(HMODULE);
+
+ if (!res)
+ BOOST_LOG_THROW_DESCR(system_error, "Could not enumerate process modules");
+ }
+ while (module_count > modules.size());
+ modules.resize(module_count, HMODULE(0));
+
+ // Now find the current module among them
+ void* p = (void*)&init_self_module_handle;
+ for (std::size_t i = 0, n = modules.size(); i < n; ++i)
+ {
+ MODULEINFO info;
+ if (!GetModuleInformation(hProcess, modules[i], &info, sizeof(info)))
+ BOOST_LOG_THROW_DESCR(system_error, "Could not acquire module information");
+
+ if (info.lpBaseOfDll <= p && (static_cast< unsigned char* >(info.lpBaseOfDll) + info.SizeOfImage) > p)
+ {
+ // Found it
+ handle = modules[i];
+ break;
+ }
+ }
+
+ if (!handle)
+ BOOST_LOG_THROW_DESCR(system_error, "Could not find self module information");
+ }
+
+ //! Retrieves the full name of the current module (be that dll or exe)
+ template< typename CharT >
+ std::basic_string< CharT > get_current_module_name()
+ {
+ static HMODULE hSelfModule = 0;
+
+ BOOST_LOG_ONCE_BLOCK()
+ {
+ init_self_module_handle(hSelfModule);
+ }
+
+ // Get the module file name
+ CharT buf[MAX_PATH];
+ DWORD size = get_module_file_name(hSelfModule, buf, sizeof(buf) / sizeof(*buf));
+ if (size == 0)
+ BOOST_LOG_THROW_DESCR(system_error, "Could not get module file name");
+
+ return std::basic_string< CharT >(buf, buf + size);
+ }
+
+} // namespace
+
+//////////////////////////////////////////////////////////////////////////
+// Simple event log backend implementation
+//////////////////////////////////////////////////////////////////////////
+//! Sink backend implementation
+template< typename CharT >
+struct basic_simple_event_log_backend< CharT >::implementation
+{
+ //! A handle for the registered event provider
+ HANDLE m_SourceHandle;
+ //! A level mapping functor
+ event_type_mapper_type m_LevelMapper;
+
+ implementation() : m_SourceHandle(0)
+ {
+ }
+};
+
+//! Default constructor. Registers event source Boost.Log <Boost version> in the Application log.
+template< typename CharT >
+BOOST_LOG_API basic_simple_event_log_backend< CharT >::basic_simple_event_log_backend()
+{
+ construct(log::aux::empty_arg_list());
+}
+
+//! Destructor
+template< typename CharT >
+BOOST_LOG_API basic_simple_event_log_backend< CharT >::~basic_simple_event_log_backend()
+{
+ DeregisterEventSource(m_pImpl->m_SourceHandle);
+ delete m_pImpl;
+}
+
+//! Constructs backend implementation
+template< typename CharT >
+BOOST_LOG_API void basic_simple_event_log_backend< CharT >::construct(
+ string_type const& target, string_type const& log_name, string_type const& source_name, event_log::registration_mode reg_mode)
+{
+ if (reg_mode != event_log::never)
+ {
+ aux::registry_params< char_type > reg_params;
+ reg_params.event_message_file = get_current_module_name< char_type >();
+ reg_params.types_supported = DWORD(
+ EVENTLOG_SUCCESS |
+ EVENTLOG_INFORMATION_TYPE |
+ EVENTLOG_WARNING_TYPE |
+ EVENTLOG_ERROR_TYPE);
+ aux::init_event_log_registry(log_name, source_name, reg_mode == event_log::forced, reg_params);
+ }
+
+ std::auto_ptr< implementation > p(new implementation());
+
+ const char_type* target_unc = NULL;
+ if (!target.empty())
+ target_unc = target.c_str();
+
+ HANDLE hSource = register_event_source(target_unc, source_name.c_str());
+ if (!hSource)
+ BOOST_LOG_THROW_DESCR(system_error, "Could not register event source");
+
+ p->m_SourceHandle = hSource;
+
+ m_pImpl = p.release();
+}
+
+//! Returns default log name
+template< typename CharT >
+BOOST_LOG_API typename basic_simple_event_log_backend< CharT >::string_type
+basic_simple_event_log_backend< CharT >::get_default_log_name()
+{
+ return aux::registry_traits< char_type >::make_default_log_name();
+}
+
+//! Returns default source name
+template< typename CharT >
+BOOST_LOG_API typename basic_simple_event_log_backend< CharT >::string_type
+basic_simple_event_log_backend< CharT >::get_default_source_name()
+{
+ string_type source_name = aux::registry_traits< char_type >::make_default_source_name();
+ complete_default_simple_event_log_source_name(source_name);
+ return source_name;
+}
+
+//! The method installs the function object that maps application severity levels to WinAPI event types
+template< typename CharT >
+BOOST_LOG_API void basic_simple_event_log_backend< CharT >::set_event_type_mapper(event_type_mapper_type const& mapper)
+{
+ m_pImpl->m_LevelMapper = mapper;
+}
+
+//! The method puts the formatted message to the event log
+template< typename CharT >
+BOOST_LOG_API void basic_simple_event_log_backend< CharT >::consume(record_view const& rec, string_type const& formatted_message)
+{
+ const char_type* message = formatted_message.c_str();
+ event_log::event_type evt_type = event_log::info;
+ if (!m_pImpl->m_LevelMapper.empty())
+ evt_type = m_pImpl->m_LevelMapper(rec);
+
+ DWORD event_id;
+ switch (evt_type)
+ {
+ case event_log::success:
+ event_id = BOOST_LOG_MSG_DEBUG; break;
+ case event_log::warning:
+ event_id = BOOST_LOG_MSG_WARNING; break;
+ case event_log::error:
+ event_id = BOOST_LOG_MSG_ERROR; break;
+ default:
+ event_id = BOOST_LOG_MSG_INFO; break;
+ }
+
+ report_event(
+ m_pImpl->m_SourceHandle, // Event log handle.
+ static_cast< WORD >(evt_type), // Event type.
+ 0, // Event category.
+ event_id, // Event identifier.
+ NULL, // No user security identifier.
+ 1, // Number of substitution strings.
+ 0, // No data.
+ &message, // Pointer to strings.
+ NULL); // No data.
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Customizable event log backend implementation
+//////////////////////////////////////////////////////////////////////////
+namespace event_log {
+
+ template< typename CharT >
+ class basic_event_composer< CharT >::insertion_composer
+ {
+ public:
+ //! Function object result type
+ typedef void result_type;
+
+ private:
+ //! The list of insertion composers (in backward order)
+ typedef std::vector< formatter_type > formatters;
+
+ private:
+ //! The insertion string composers
+ formatters m_Formatters;
+
+ public:
+ //! Default constructor
+ insertion_composer() {}
+ //! Composition operator
+ void operator() (record_view const& rec, insertion_list& insertions) const
+ {
+ std::size_t size = m_Formatters.size();
+ insertions.resize(size);
+ for (std::size_t i = 0; i < size; ++i)
+ {
+ typename formatter_type::stream_type strm(insertions[i]);
+ m_Formatters[i](rec, strm);
+ strm.flush();
+ }
+ }
+ //! Adds a new formatter to the list
+ void add_formatter(formatter_type const& fmt)
+ {
+ m_Formatters.push_back(formatter_type(fmt));
+ }
+ };
+
+ //! Default constructor
+ template< typename CharT >
+ basic_event_composer< CharT >::basic_event_composer(event_id_mapper_type const& id_mapper) :
+ m_EventIDMapper(id_mapper)
+ {
+ }
+ //! Copy constructor
+ template< typename CharT >
+ basic_event_composer< CharT >::basic_event_composer(basic_event_composer const& that) :
+ m_EventIDMapper(that.m_EventIDMapper),
+ m_EventMap(that.m_EventMap)
+ {
+ }
+ //! Destructor
+ template< typename CharT >
+ basic_event_composer< CharT >::~basic_event_composer()
+ {
+ }
+
+ //! Assignment
+ template< typename CharT >
+ basic_event_composer< CharT >& basic_event_composer< CharT >::operator= (basic_event_composer that)
+ {
+ swap(that);
+ return *this;
+ }
+ //! Swapping
+ template< typename CharT >
+ void basic_event_composer< CharT >::swap(basic_event_composer& that)
+ {
+ m_EventIDMapper.swap(that.m_EventIDMapper);
+ m_EventMap.swap(that.m_EventMap);
+ }
+ //! Creates a new entry for a message
+ template< typename CharT >
+ typename basic_event_composer< CharT >::event_map_reference
+ basic_event_composer< CharT >::operator[] (event_id id)
+ {
+ return event_map_reference(id, *this);
+ }
+ //! Creates a new entry for a message
+ template< typename CharT >
+ typename basic_event_composer< CharT >::event_map_reference
+ basic_event_composer< CharT >::operator[] (int id)
+ {
+ return event_map_reference(make_event_id(id), *this);
+ }
+
+ //! Event composition operator
+ template< typename CharT >
+ event_id basic_event_composer< CharT >::operator() (record_view const& rec, insertion_list& insertions) const
+ {
+ event_id id = m_EventIDMapper(rec);
+ typename event_map::const_iterator it = m_EventMap.find(id);
+ if (it != m_EventMap.end())
+ it->second(rec, insertions);
+ return id;
+ }
+
+ //! Adds a formatter to the insertion composers list
+ template< typename CharT >
+ typename basic_event_composer< CharT >::insertion_composer*
+ basic_event_composer< CharT >::add_formatter(event_id id, insertion_composer* composer, formatter_type const& fmt)
+ {
+ if (!composer)
+ composer = &m_EventMap[id];
+ composer->add_formatter(fmt);
+ return composer;
+ }
+
+#ifdef BOOST_LOG_USE_CHAR
+ template class BOOST_LOG_API basic_event_composer< char >;
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+ template class BOOST_LOG_API basic_event_composer< wchar_t >;
+#endif
+
+} // namespace event_log
+
+
+//! Backend implementation
+template< typename CharT >
+struct basic_event_log_backend< CharT >::implementation
+{
+ // NOTE: This order of data members is critical for MSVC 9.0 in debug mode,
+ // as it ICEs if boost::functions are not the first members. Doh!
+
+ //! An event category mapper
+ event_category_mapper_type m_CategoryMapper;
+ //! A level mapping functor
+ event_type_mapper_type m_LevelMapper;
+
+ //! A handle for the registered event provider
+ HANDLE m_SourceHandle;
+ //! A functor that composes an event
+ event_composer_type m_EventComposer;
+ //! An array of formatted insertions
+ insertion_list m_Insertions;
+
+ implementation() : m_SourceHandle(0)
+ {
+ }
+};
+
+//! Destructor
+template< typename CharT >
+BOOST_LOG_API basic_event_log_backend< CharT >::~basic_event_log_backend()
+{
+ DeregisterEventSource(m_pImpl->m_SourceHandle);
+ delete m_pImpl;
+}
+
+//! Constructs backend implementation
+template< typename CharT >
+BOOST_LOG_API void basic_event_log_backend< CharT >::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)
+{
+ if (reg_mode != event_log::never)
+ {
+ aux::registry_params< char_type > reg_params;
+ string_type file_name;
+ log::aux::code_convert(message_file_name.string(), file_name);
+ reg_params.event_message_file = file_name;
+ reg_params.types_supported = DWORD(
+ EVENTLOG_SUCCESS |
+ EVENTLOG_INFORMATION_TYPE |
+ EVENTLOG_WARNING_TYPE |
+ EVENTLOG_ERROR_TYPE);
+ aux::init_event_log_registry(log_name, source_name, reg_mode == event_log::forced, reg_params);
+ }
+
+ std::auto_ptr< implementation > p(new implementation());
+
+ const char_type* target_unc = NULL;
+ if (!target.empty())
+ target_unc = target.c_str();
+
+ HANDLE hSource = register_event_source(target_unc, source_name.c_str());
+ if (!hSource)
+ BOOST_LOG_THROW_DESCR(system_error, "Could not register event source");
+
+ p->m_SourceHandle = hSource;
+
+ m_pImpl = p.release();
+}
+
+//! The method puts the formatted message to the event log
+template< typename CharT >
+BOOST_LOG_API void basic_event_log_backend< CharT >::consume(record_view const& rec)
+{
+ if (!m_pImpl->m_EventComposer.empty())
+ {
+ log::aux::cleanup_guard< insertion_list > cleaner(m_pImpl->m_Insertions);
+
+ // Get event ID and construct insertions
+ DWORD id = m_pImpl->m_EventComposer(rec, m_pImpl->m_Insertions);
+ WORD string_count = static_cast< WORD >(m_pImpl->m_Insertions.size());
+ scoped_array< const char_type* > strings(new const char_type*[string_count]);
+ for (WORD i = 0; i < string_count; ++i)
+ strings[i] = m_pImpl->m_Insertions[i].c_str();
+
+ // Get event type
+ WORD event_type = EVENTLOG_INFORMATION_TYPE;
+ if (!m_pImpl->m_LevelMapper.empty())
+ event_type = static_cast< WORD >(m_pImpl->m_LevelMapper(rec));
+
+ WORD event_category = 0;
+ if (!m_pImpl->m_CategoryMapper.empty())
+ event_category = static_cast< WORD >(m_pImpl->m_CategoryMapper(rec));
+
+ report_event(
+ m_pImpl->m_SourceHandle, // Event log handle.
+ event_type, // Event type.
+ event_category, // Event category.
+ id, // Event identifier.
+ NULL, // No user security identifier.
+ string_count, // Number of substitution strings.
+ 0, // No data.
+ strings.get(), // Pointer to strings.
+ NULL); // No data.
+ }
+}
+
+//! Returns default log name
+template< typename CharT >
+BOOST_LOG_API typename basic_event_log_backend< CharT >::string_type
+basic_event_log_backend< CharT >::get_default_log_name()
+{
+ return aux::registry_traits< char_type >::make_default_log_name();
+}
+
+//! Returns default source name
+template< typename CharT >
+BOOST_LOG_API typename basic_event_log_backend< CharT >::string_type
+basic_event_log_backend< CharT >::get_default_source_name()
+{
+ string_type source_name = aux::registry_traits< char_type >::make_default_source_name();
+ complete_default_event_log_source_name(source_name);
+ return source_name;
+}
+
+//! The method installs the function object that maps application severity levels to WinAPI event types
+template< typename CharT >
+BOOST_LOG_API void basic_event_log_backend< CharT >::set_event_type_mapper(event_type_mapper_type const& mapper)
+{
+ m_pImpl->m_LevelMapper = mapper;
+}
+
+//! The method installs the function object that extracts event category from attribute values
+template< typename CharT >
+BOOST_LOG_API void basic_event_log_backend< CharT >::set_event_category_mapper(event_category_mapper_type const& mapper)
+{
+ m_pImpl->m_CategoryMapper = 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.
+ */
+template< typename CharT >
+BOOST_LOG_API void basic_event_log_backend< CharT >::set_event_composer(event_composer_type const& composer)
+{
+ m_pImpl->m_EventComposer = composer;
+}
+
+
+#ifdef BOOST_LOG_USE_CHAR
+template class basic_simple_event_log_backend< char >;
+template class basic_event_log_backend< char >;
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+template class basic_simple_event_log_backend< wchar_t >;
+template class basic_event_log_backend< wchar_t >;
+#endif
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // !defined(BOOST_LOG_WITHOUT_EVENT_LOG)

Added: trunk/libs/log/src/event_log_registry.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/event_log_registry.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,492 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_registry.hpp
+ * \author Andrey Semashev
+ * \date 16.11.2008
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#ifndef BOOST_LOG_EVENT_LOG_REGISTRY_HPP_INCLUDED_
+#define BOOST_LOG_EVENT_LOG_REGISTRY_HPP_INCLUDED_
+
+#include <cwchar>
+#include <cstring>
+#include <string>
+#include <sstream>
+#include <stdexcept>
+#include <boost/version.hpp>
+#include <boost/optional.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/code_conversion.hpp>
+#include <boost/log/exceptions.hpp>
+#include "windows_version.hpp"
+#include <windows.h>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+namespace aux {
+
+ // MSVC versions up to 2008 (or their Platform SDKs, to be more precise) don't define LSTATUS.
+ // Perhaps, that is also the case for MinGW and Cygwin (untested).
+ typedef DWORD LSTATUS;
+
+ // Max registry string size, in characters (for security reasons)
+ const DWORD max_string_size = 64u * 1024u;
+
+ //! Helper traits to integrate with WinAPI
+ template< typename CharT >
+ struct registry_traits;
+
+#ifdef BOOST_LOG_USE_CHAR
+ template< >
+ struct registry_traits< char >
+ {
+ static std::string make_event_log_key(std::string const& log_name, std::string const& source_name)
+ {
+ return "SYSTEM\\CurrentControlSet\\Services\\EventLog\\" + log_name + "\\" + source_name;
+ }
+
+ static std::string make_default_log_name()
+ {
+ return "Application";
+ }
+
+ static std::string make_default_source_name()
+ {
+ char buf[MAX_PATH];
+ DWORD size = GetModuleFileNameA(NULL, buf, sizeof(buf) / sizeof(*buf));
+
+ std::string source_name(buf, buf + size);
+ if (source_name.empty())
+ {
+ // In case of error we provide artifical application name
+ std::ostringstream strm;
+ strm << "Boost.Log "
+ << static_cast< unsigned int >(BOOST_VERSION / 100000)
+ << "."
+ << static_cast< unsigned int >(BOOST_VERSION / 100 % 1000)
+ << "."
+ << static_cast< unsigned int >(BOOST_VERSION % 100);
+ source_name = strm.str();
+ }
+ else
+ {
+ // Cut off the path and extension
+ std::size_t backslash_pos = source_name.rfind('\\');
+ if (backslash_pos == std::string::npos || backslash_pos >= source_name.size() - 1)
+ backslash_pos = 0;
+ else
+ ++backslash_pos;
+ std::size_t dot_pos = source_name.rfind('.');
+ if (dot_pos == std::string::npos || dot_pos < backslash_pos)
+ dot_pos = source_name.size();
+ source_name = source_name.substr(backslash_pos, dot_pos - backslash_pos);
+ }
+
+ return source_name;
+ }
+
+ static LSTATUS create_key(
+ HKEY hKey,
+ const char* lpSubKey,
+ DWORD Reserved,
+ char* lpClass,
+ DWORD dwOptions,
+ REGSAM samDesired,
+ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+ PHKEY phkResult,
+ LPDWORD lpdwDisposition)
+ {
+ return RegCreateKeyExA(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
+ }
+
+ static LSTATUS open_key(
+ HKEY hKey,
+ const char* lpSubKey,
+ DWORD dwOptions,
+ REGSAM samDesired,
+ PHKEY phkResult)
+ {
+ return RegOpenKeyExA(hKey, lpSubKey, dwOptions, samDesired, phkResult);
+ }
+
+ static LSTATUS set_value(
+ HKEY hKey,
+ const char* lpValueName,
+ DWORD Reserved,
+ DWORD dwType,
+ const BYTE* lpData,
+ DWORD cbData)
+ {
+ return RegSetValueExA(hKey, lpValueName, Reserved, dwType, lpData, cbData);
+ }
+
+ static LSTATUS get_value(HKEY hKey, const char* lpValueName, DWORD& value)
+ {
+ DWORD type = REG_NONE, size = sizeof(value);
+ LSTATUS res = RegQueryValueExA(hKey, lpValueName, NULL, &type, reinterpret_cast< LPBYTE >(&value), &size);
+ if (res == ERROR_SUCCESS && type != REG_DWORD && type != REG_BINARY)
+ res = ERROR_INVALID_DATA;
+ return res;
+ }
+
+ static LSTATUS get_value(HKEY hKey, const char* lpValueName, std::string& value)
+ {
+ DWORD type = REG_NONE, size = 0;
+ LSTATUS res = RegQueryValueExA(hKey, lpValueName, NULL, &type, NULL, &size);
+ if (res == ERROR_SUCCESS && ((type != REG_EXPAND_SZ && type != REG_SZ) || size > max_string_size))
+ return ERROR_INVALID_DATA;
+ if (size == 0)
+ return res;
+
+ value.resize(size);
+ res = RegQueryValueExA(hKey, lpValueName, NULL, &type, reinterpret_cast< LPBYTE >(&value[0]), &size);
+ value.resize(std::strlen(value.c_str())); // remove extra terminating zero
+
+ return res;
+ }
+
+ static const char* get_event_message_file_param_name() { return "EventMessageFile"; }
+ static const char* get_category_message_file_param_name() { return "CategoryMessageFile"; }
+ static const char* get_category_count_param_name() { return "CategoryCount"; }
+ static const char* get_types_supported_param_name() { return "TypesSupported"; }
+ };
+#endif // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+ template< >
+ struct registry_traits< wchar_t >
+ {
+ static std::wstring make_event_log_key(std::wstring const& log_name, std::wstring const& source_name)
+ {
+ return L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\" + log_name + L"\\" + source_name;
+ }
+
+ static std::wstring make_default_log_name()
+ {
+ return L"Application";
+ }
+
+ static std::wstring make_default_source_name()
+ {
+ wchar_t buf[MAX_PATH];
+ DWORD size = GetModuleFileNameW(NULL, buf, sizeof(buf) / sizeof(*buf));
+
+ std::wstring source_name(buf, buf + size);
+ if (source_name.empty())
+ {
+ // In case of error we provide artifical application name
+ std::wostringstream strm;
+ strm << L"Boost.Log "
+ << static_cast< unsigned int >(BOOST_VERSION / 100000)
+ << L"."
+ << static_cast< unsigned int >(BOOST_VERSION / 100 % 1000)
+ << L"."
+ << static_cast< unsigned int >(BOOST_VERSION % 100);
+ source_name = strm.str();
+ }
+ else
+ {
+ // Cut off the path and extension
+ std::size_t backslash_pos = source_name.rfind(L'\\');
+ if (backslash_pos == std::wstring::npos || backslash_pos >= source_name.size() - 1)
+ backslash_pos = 0;
+ else
+ ++backslash_pos;
+ std::size_t dot_pos = source_name.rfind(L'.');
+ if (dot_pos == std::wstring::npos || dot_pos < backslash_pos)
+ dot_pos = source_name.size();
+ source_name = source_name.substr(backslash_pos, dot_pos - backslash_pos);
+ }
+
+ return source_name;
+ }
+
+ static LSTATUS create_key(
+ HKEY hKey,
+ const wchar_t* lpSubKey,
+ DWORD Reserved,
+ wchar_t* lpClass,
+ DWORD dwOptions,
+ REGSAM samDesired,
+ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+ PHKEY phkResult,
+ LPDWORD lpdwDisposition)
+ {
+ return RegCreateKeyExW(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
+ }
+
+ static LSTATUS open_key(
+ HKEY hKey,
+ const wchar_t* lpSubKey,
+ DWORD dwOptions,
+ REGSAM samDesired,
+ PHKEY phkResult)
+ {
+ return RegOpenKeyExW(hKey, lpSubKey, dwOptions, samDesired, phkResult);
+ }
+
+ static LSTATUS set_value(
+ HKEY hKey,
+ const wchar_t* lpValueName,
+ DWORD Reserved,
+ DWORD dwType,
+ const BYTE* lpData,
+ DWORD cbData)
+ {
+ return RegSetValueExW(hKey, lpValueName, Reserved, dwType, lpData, cbData);
+ }
+
+ static LSTATUS get_value(HKEY hKey, const wchar_t* lpValueName, DWORD& value)
+ {
+ DWORD type = REG_NONE, size = sizeof(value);
+ LSTATUS res = RegQueryValueExW(hKey, lpValueName, NULL, &type, reinterpret_cast< LPBYTE >(&value), &size);
+ if (res == ERROR_SUCCESS && type != REG_DWORD && type != REG_BINARY)
+ res = ERROR_INVALID_DATA;
+ return res;
+ }
+
+ static LSTATUS get_value(HKEY hKey, const wchar_t* lpValueName, std::wstring& value)
+ {
+ DWORD type = REG_NONE, size = 0;
+ LSTATUS res = RegQueryValueExW(hKey, lpValueName, NULL, &type, NULL, &size);
+ size /= sizeof(wchar_t);
+ if (res == ERROR_SUCCESS && ((type != REG_EXPAND_SZ && type != REG_SZ) || size > max_string_size))
+ return ERROR_INVALID_DATA;
+ if (size == 0)
+ return res;
+
+ value.resize(size);
+ res = RegQueryValueExW(hKey, lpValueName, NULL, &type, reinterpret_cast< LPBYTE >(&value[0]), &size);
+ value.resize(std::wcslen(value.c_str())); // remove extra terminating zero
+
+ return res;
+ }
+
+ static const wchar_t* get_event_message_file_param_name() { return L"EventMessageFile"; }
+ static const wchar_t* get_category_message_file_param_name() { return L"CategoryMessageFile"; }
+ static const wchar_t* get_category_count_param_name() { return L"CategoryCount"; }
+ static const wchar_t* get_types_supported_param_name() { return L"TypesSupported"; }
+
+ };
+#endif // BOOST_LOG_USE_WCHAR_T
+
+ //! The structure with parameters that have to be registered in the event log registry key
+ template< typename CharT >
+ struct registry_params
+ {
+ typedef std::basic_string< CharT > string_type;
+
+ optional< string_type > event_message_file;
+ optional< string_type > category_message_file;
+ optional< DWORD > category_count;
+ optional< DWORD > types_supported;
+ };
+
+ //! A simple guard that closes the registry key on destruction
+ struct auto_hkey_close
+ {
+ explicit auto_hkey_close(HKEY hk) : hk_(hk) {}
+ ~auto_hkey_close() { RegCloseKey(hk_); }
+
+ private:
+ HKEY hk_;
+ };
+
+ //! The function checks if the event log is already registered
+ template< typename CharT >
+ bool verify_event_log_registry(std::basic_string< CharT > const& reg_key, bool force, registry_params< CharT > const& params)
+ {
+ typedef std::basic_string< CharT > string_type;
+ typedef registry_traits< CharT > registry;
+
+ // Open the key
+ HKEY hkey = 0;
+ LSTATUS res = registry::open_key(
+ HKEY_LOCAL_MACHINE,
+ reg_key.c_str(),
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ,
+ &hkey);
+ if (res != ERROR_SUCCESS)
+ return false;
+
+ auto_hkey_close hkey_guard(hkey);
+
+ if (force)
+ {
+ // Verify key values
+ if (!!params.event_message_file)
+ {
+ string_type module_name;
+ res = registry::get_value(hkey, registry::get_event_message_file_param_name(), module_name);
+ if (res != ERROR_SUCCESS || module_name != params.event_message_file.get())
+ return false;
+ }
+
+ if (!!params.category_message_file)
+ {
+ string_type module_name;
+ res = registry::get_value(hkey, registry::get_category_message_file_param_name(), module_name);
+ if (res != ERROR_SUCCESS || module_name != params.category_message_file.get())
+ return false;
+ }
+
+ if (!!params.category_count)
+ {
+ // Set number of categories
+ DWORD category_count = 0;
+ res = registry::get_value(hkey, registry::get_category_count_param_name(), category_count);
+ if (res != ERROR_SUCCESS || category_count != params.category_count.get())
+ return false;
+ }
+
+ if (!!params.types_supported)
+ {
+ // Set the supported event types
+ DWORD event_types = 0;
+ res = registry::get_value(hkey, registry::get_types_supported_param_name(), event_types);
+ if (res != ERROR_SUCCESS || event_types != params.types_supported.get())
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ //! The function initializes the event log registry key
+ template< typename CharT >
+ void init_event_log_registry(
+ std::basic_string< CharT > const& log_name,
+ std::basic_string< CharT > const& source_name,
+ bool force,
+ registry_params< CharT > const& params)
+ {
+ typedef std::basic_string< CharT > string_type;
+ typedef registry_traits< CharT > registry;
+ // Registry key name that contains log description
+ string_type reg_key = registry::make_event_log_key(log_name, source_name);
+
+ // First check the registry keys and values in read-only mode.
+ // This allows to avoid UAC asking for elevated permissions to modify HKLM registry when no modification is actually needed.
+ if (verify_event_log_registry(reg_key, force, params))
+ return;
+
+ // Create or open the key
+ HKEY hkey = 0;
+ DWORD disposition = 0;
+ LSTATUS res = registry::create_key(
+ HKEY_LOCAL_MACHINE,
+ reg_key.c_str(),
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_WRITE,
+ NULL,
+ &hkey,
+ &disposition);
+ if (res != ERROR_SUCCESS)
+ BOOST_LOG_THROW_DESCR(system_error, "Could not create registry key for the event log");
+
+ auto_hkey_close hkey_guard(hkey);
+
+ if (disposition != REG_OPENED_EXISTING_KEY || force)
+ {
+ // Fill registry values
+ if (!!params.event_message_file)
+ {
+ // Set the module file name that contains event resources
+ string_type const& module_name = params.event_message_file.get();
+ res = registry::set_value(
+ hkey,
+ registry::get_event_message_file_param_name(),
+ 0,
+ REG_EXPAND_SZ,
+ reinterpret_cast< LPBYTE >(const_cast< CharT* >(module_name.c_str())),
+ static_cast< DWORD >((module_name.size() + 1) * sizeof(CharT)));
+ if (res != ERROR_SUCCESS)
+ {
+ BOOST_LOG_THROW_DESCR(system_error, "Could not create registry value "
+ + log::aux::to_narrow(string_type(registry::get_event_message_file_param_name())));
+ }
+ }
+
+ if (!!params.category_message_file)
+ {
+ // Set the module file name that contains event category resources
+ string_type const& module_name = params.category_message_file.get();
+ res = registry::set_value(
+ hkey,
+ registry::get_category_message_file_param_name(),
+ 0,
+ REG_SZ,
+ reinterpret_cast< LPBYTE >(const_cast< CharT* >(module_name.c_str())),
+ static_cast< DWORD >((module_name.size() + 1) * sizeof(CharT)));
+ if (res != ERROR_SUCCESS)
+ {
+ BOOST_LOG_THROW_DESCR(system_error, "Could not create registry value "
+ + log::aux::to_narrow(string_type(registry::get_category_message_file_param_name())));
+ }
+ }
+
+ if (!!params.category_count)
+ {
+ // Set number of categories
+ DWORD category_count = params.category_count.get();
+ res = registry::set_value(
+ hkey,
+ registry::get_category_count_param_name(),
+ 0,
+ REG_DWORD,
+ reinterpret_cast< LPBYTE >(&category_count),
+ static_cast< DWORD >(sizeof(category_count)));
+ if (res != ERROR_SUCCESS)
+ {
+ BOOST_LOG_THROW_DESCR(system_error, "Could not create registry value "
+ + log::aux::to_narrow(string_type(registry::get_category_count_param_name())));
+ }
+ }
+
+ if (!!params.types_supported)
+ {
+ // Set the supported event types
+ DWORD event_types = params.types_supported.get();
+ res = registry::set_value(
+ hkey,
+ registry::get_types_supported_param_name(),
+ 0,
+ REG_DWORD,
+ reinterpret_cast< LPBYTE >(&event_types),
+ static_cast< DWORD >(sizeof(event_types)));
+ if (res != ERROR_SUCCESS)
+ {
+ BOOST_LOG_THROW_DESCR(system_error, "Could not create registry value "
+ + log::aux::to_narrow(string_type(registry::get_types_supported_param_name())));
+ }
+ }
+ }
+ }
+
+} // namespace aux
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EVENT_LOG_REGISTRY_HPP_INCLUDED_

Added: trunk/libs/log/src/exceptions.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/exceptions.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,426 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 exceptions.cpp
+ * \author Andrey Semashev
+ * \date 31.10.2009
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#include <boost/throw_exception.hpp>
+#include <boost/exception/exception.hpp>
+#include <boost/exception/errinfo_at_line.hpp>
+#include <boost/exception/info.hpp>
+#include <boost/log/exceptions.hpp>
+#include <boost/log/support/exception.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef _MSC_VER
+#pragma warning(push)
+// conversion from 'size_t' to 'boost::error_info<boost::throw_line_,int>::value_type', possible loss of data
+// No idea why line number is stored as a signed integer in the error info...
+#pragma warning(disable: 4267)
+#endif
+
+namespace boost {
+
+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)
+{
+ e << attribute_name_info(name);
+}
+
+} // namespace aux
+
+runtime_error::runtime_error(std::string const& descr) :
+ std::runtime_error(descr)
+{
+}
+
+runtime_error::~runtime_error() throw()
+{
+}
+
+missing_value::missing_value() :
+ runtime_error("Requested value not found")
+{
+}
+
+missing_value::missing_value(std::string const& descr) :
+ runtime_error(descr)
+{
+}
+
+missing_value::~missing_value() throw()
+{
+}
+
+void missing_value::throw_(const char* file, std::size_t line)
+{
+ boost::throw_exception(boost::enable_error_info(missing_value())
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ );
+}
+
+void missing_value::throw_(const char* file, std::size_t line, std::string const& descr)
+{
+ boost::throw_exception(boost::enable_error_info(missing_value(descr))
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ );
+}
+
+void missing_value::throw_(const char* file, std::size_t line, std::string const& descr, attribute_name const& name)
+{
+ boost::throw_exception(boost::enable_error_info(missing_value(descr))
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ << attribute_name_info(name)
+ );
+}
+
+invalid_type::invalid_type() :
+ runtime_error("Requested value has invalid type")
+{
+}
+
+invalid_type::invalid_type(std::string const& descr) :
+ runtime_error(descr)
+{
+}
+
+invalid_type::~invalid_type() throw()
+{
+}
+
+void invalid_type::throw_(const char* file, std::size_t line)
+{
+ boost::throw_exception(boost::enable_error_info(invalid_type())
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ );
+}
+
+void invalid_type::throw_(const char* file, std::size_t line, std::string const& descr)
+{
+ boost::throw_exception(boost::enable_error_info(invalid_type(descr))
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ );
+}
+
+void invalid_type::throw_(const char* file, std::size_t line, std::string const& descr, attribute_name const& name)
+{
+ boost::throw_exception(boost::enable_error_info(invalid_type(descr))
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ << attribute_name_info(name)
+ );
+}
+
+void invalid_type::throw_(const char* file, std::size_t line, std::string const& descr, type_info_wrapper const& type)
+{
+ boost::throw_exception(boost::enable_error_info(invalid_type(descr))
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ << type_info_info(type)
+ );
+}
+
+void invalid_type::throw_(const char* file, std::size_t line, std::string const& descr, attribute_name const& name, type_info_wrapper const& type)
+{
+ boost::throw_exception(boost::enable_error_info(invalid_type(descr))
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ << attribute_name_info(name)
+ << type_info_info(type)
+ );
+}
+
+invalid_value::invalid_value() :
+ runtime_error("The value is invalid")
+{
+}
+
+invalid_value::invalid_value(std::string const& descr) :
+ runtime_error(descr)
+{
+}
+
+invalid_value::~invalid_value() throw()
+{
+}
+
+void invalid_value::throw_(const char* file, std::size_t line)
+{
+ boost::throw_exception(boost::enable_error_info(invalid_value())
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ );
+}
+
+void invalid_value::throw_(const char* file, std::size_t line, std::string const& descr)
+{
+ boost::throw_exception(boost::enable_error_info(invalid_value(descr))
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ );
+}
+
+parse_error::parse_error() :
+ runtime_error("Failed to parse content")
+{
+}
+
+parse_error::parse_error(std::string const& descr) :
+ runtime_error(descr)
+{
+}
+
+parse_error::~parse_error() throw()
+{
+}
+
+void parse_error::throw_(const char* file, std::size_t line)
+{
+ boost::throw_exception(boost::enable_error_info(parse_error())
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ );
+}
+
+void parse_error::throw_(const char* file, std::size_t line, std::string const& descr)
+{
+ boost::throw_exception(boost::enable_error_info(parse_error(descr))
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ );
+}
+
+void parse_error::throw_(const char* file, std::size_t line, std::string const& descr, std::size_t content_line)
+{
+ boost::throw_exception(boost::enable_error_info(parse_error(descr))
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ << boost::errinfo_at_line(content_line)
+ );
+}
+
+void parse_error::throw_(const char* file, std::size_t line, std::string const& descr, attribute_name const& name)
+{
+ boost::throw_exception(boost::enable_error_info(parse_error(descr))
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ << attribute_name_info(name)
+ );
+}
+
+conversion_error::conversion_error() :
+ runtime_error("Failed to perform conversion")
+{
+}
+
+conversion_error::conversion_error(std::string const& descr) :
+ runtime_error(descr)
+{
+}
+
+conversion_error::~conversion_error() throw()
+{
+}
+
+void conversion_error::throw_(const char* file, std::size_t line)
+{
+ boost::throw_exception(boost::enable_error_info(conversion_error())
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ );
+}
+
+void conversion_error::throw_(const char* file, std::size_t line, std::string const& descr)
+{
+ boost::throw_exception(boost::enable_error_info(conversion_error(descr))
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ );
+}
+
+system_error::system_error() :
+ runtime_error("Underlying API operation failed")
+{
+}
+
+system_error::system_error(std::string const& descr) :
+ runtime_error(descr)
+{
+}
+
+system_error::~system_error() throw()
+{
+}
+
+void system_error::throw_(const char* file, std::size_t line)
+{
+ boost::throw_exception(boost::enable_error_info(system_error())
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ );
+}
+
+void system_error::throw_(const char* file, std::size_t line, std::string const& descr)
+{
+ boost::throw_exception(boost::enable_error_info(system_error(descr))
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ );
+}
+
+logic_error::logic_error(std::string const& descr) :
+ std::logic_error(descr)
+{
+}
+
+logic_error::~logic_error() throw()
+{
+}
+
+odr_violation::odr_violation() :
+ logic_error("ODR violation detected")
+{
+}
+
+odr_violation::odr_violation(std::string const& descr) :
+ logic_error(descr)
+{
+}
+
+odr_violation::~odr_violation() throw()
+{
+}
+
+void odr_violation::throw_(const char* file, std::size_t line)
+{
+ boost::throw_exception(boost::enable_error_info(odr_violation())
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ );
+}
+
+void odr_violation::throw_(const char* file, std::size_t line, std::string const& descr)
+{
+ boost::throw_exception(boost::enable_error_info(odr_violation(descr))
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ );
+}
+
+unexpected_call::unexpected_call() :
+ logic_error("Invalid call sequence")
+{
+}
+
+unexpected_call::unexpected_call(std::string const& descr) :
+ logic_error(descr)
+{
+}
+
+unexpected_call::~unexpected_call() throw()
+{
+}
+
+void unexpected_call::throw_(const char* file, std::size_t line)
+{
+ boost::throw_exception(boost::enable_error_info(unexpected_call())
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ );
+}
+
+void unexpected_call::throw_(const char* file, std::size_t line, std::string const& descr)
+{
+ boost::throw_exception(boost::enable_error_info(unexpected_call(descr))
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ );
+}
+
+setup_error::setup_error() :
+ logic_error("The library is not initialized properly")
+{
+}
+
+setup_error::setup_error(std::string const& descr) :
+ logic_error(descr)
+{
+}
+
+setup_error::~setup_error() throw()
+{
+}
+
+void setup_error::throw_(const char* file, std::size_t line)
+{
+ boost::throw_exception(boost::enable_error_info(setup_error())
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ );
+}
+
+void setup_error::throw_(const char* file, std::size_t line, std::string const& descr)
+{
+ boost::throw_exception(boost::enable_error_info(setup_error(descr))
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ );
+}
+
+limitation_error::limitation_error() :
+ logic_error("Boost.Log library limit reached")
+{
+}
+
+limitation_error::limitation_error(std::string const& descr) :
+ logic_error(descr)
+{
+}
+
+limitation_error::~limitation_error() throw()
+{
+}
+
+void limitation_error::throw_(const char* file, std::size_t line)
+{
+ boost::throw_exception(boost::enable_error_info(limitation_error())
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ );
+}
+
+void limitation_error::throw_(const char* file, std::size_t line, std::string const& descr)
+{
+ boost::throw_exception(boost::enable_error_info(limitation_error(descr))
+ << boost::throw_file(file)
+ << boost::throw_line(line)
+ );
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#include <boost/log/detail/footer.hpp>

Added: trunk/libs/log/src/filter_parser.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/filter_parser.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,462 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 31.03.2008
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#ifndef BOOST_LOG_WITHOUT_SETTINGS_PARSERS
+
+#include <cstddef>
+#include <map>
+#include <stack>
+#include <string>
+#include <sstream>
+#include <stdexcept>
+#include <utility>
+#include <boost/assert.hpp>
+#include <boost/bind.hpp>
+#include <boost/none.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/optional/optional.hpp>
+#include <boost/utility/in_place_factory.hpp>
+#include <boost/spirit/include/qi_core.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_lit.hpp>
+#include <boost/spirit/include/qi_raw.hpp>
+#include <boost/spirit/include/qi_lexeme.hpp>
+#include <boost/spirit/include/qi_as.hpp>
+#include <boost/spirit/include/qi_symbols.hpp>
+#include <boost/phoenix/core.hpp>
+#include <boost/phoenix/bind/bind_function_object.hpp>
+#include <boost/phoenix/operator/logical.hpp>
+#include <boost/range/iterator_range_core.hpp>
+#include <boost/log/detail/singleton.hpp>
+#include <boost/log/exceptions.hpp>
+#include <boost/log/utility/setup/filter_parser.hpp>
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/log/detail/locks.hpp>
+#include <boost/log/detail/light_rw_mutex.hpp>
+#endif // !defined(BOOST_LOG_NO_THREADS)
+#include "parser_utils.hpp"
+#include "default_filter_factory.hpp"
+#include "spirit_encoding.hpp"
+#include <boost/log/detail/header.hpp>
+
+namespace qi = boost::spirit::qi;
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+//! Filter factories repository
+template< typename CharT >
+struct filters_repository :
+ public log::aux::lazy_singleton< filters_repository< CharT > >
+{
+ typedef CharT char_type;
+ typedef log::aux::lazy_singleton< filters_repository< char_type > > base_type;
+ typedef std::basic_string< char_type > string_type;
+ typedef filter_factory< char_type > filter_factory_type;
+
+ //! Attribute name ordering predicate
+ struct attribute_name_order
+ {
+ typedef bool result_type;
+ result_type operator() (attribute_name const& left, attribute_name const& right) const
+ {
+ return left.id() < right.id();
+ }
+ };
+
+ typedef std::map< attribute_name, shared_ptr< filter_factory_type >, attribute_name_order > factories_map;
+
+#if !defined(BOOST_LOG_BROKEN_FRIEND_TEMPLATE_INSTANTIATIONS)
+ friend class log::aux::lazy_singleton< filters_repository< char_type > >;
+#else
+ friend class base_type;
+#endif
+
+#if !defined(BOOST_LOG_NO_THREADS)
+ //! Synchronization mutex
+ mutable log::aux::light_rw_mutex m_Mutex;
+#endif
+ //! The map of filter factories
+ factories_map m_Map;
+ //! Default factory
+ mutable aux::default_filter_factory< char_type > m_DefaultFactory;
+
+ //! The method returns the filter factory for the specified attribute name
+ filter_factory_type& get_factory(attribute_name const& name) const
+ {
+ typename factories_map::const_iterator it = m_Map.find(name);
+ if (it != m_Map.end())
+ return *it->second;
+ else
+ return m_DefaultFactory;
+ }
+
+private:
+ filters_repository()
+ {
+ }
+};
+
+//! Filter parsing grammar
+template< typename CharT >
+class filter_grammar :
+ public qi::grammar<
+ const CharT*,
+ typename log::aux::encoding_specific< typename log::aux::encoding< CharT >::type >::space_type
+ >
+{
+private:
+ typedef CharT char_type;
+ typedef const char_type* iterator_type;
+ typedef log::aux::encoding_specific< typename log::aux::encoding< char_type >::type > encoding_specific;
+ typedef std::basic_string< char_type > string_type;
+ typedef log::aux::char_constants< char_type > constants;
+ typedef filter_grammar< char_type > this_type;
+ typedef qi::grammar< iterator_type, typename encoding_specific::space_type > base_type;
+ typedef typename base_type::start_type rule_type;
+ typedef filter_factory< char_type > filter_factory_type;
+
+ typedef filter (filter_factory_type::*comparison_relation_handler_t)(attribute_name const&, string_type const&);
+
+ template< typename ScannerT >
+ struct definition;
+
+private:
+ //! Parsed attribute name
+ mutable attribute_name m_AttributeName;
+ //! The second operand of a relation
+ mutable optional< string_type > m_Operand;
+ //! Comparison relation handler
+ comparison_relation_handler_t m_ComparisonRelation;
+ //! The custom relation string
+ mutable string_type m_CustomRelation;
+
+ //! Filter subexpressions as they are parsed
+ mutable std::stack< filter > m_Subexpressions;
+
+ //! A parser for an attribute name in a single relation
+ rule_type attr_name;
+ //! A parser for a quoted string
+ rule_type quoted_string_operand;
+ //! A parser for an operand in a single relation
+ rule_type operand;
+ //! A parser for a single relation that consists of two operands and an operation between them
+ rule_type relation;
+ //! A set of comparison relation symbols with corresponding pointers to callbacks
+ qi::symbols< char_type, comparison_relation_handler_t > comparison_relation;
+ //! A parser for a custom relation word
+ rule_type custom_relation;
+ //! A parser for a term, which can be a relation, an expression in parenthesis or a negation thereof
+ rule_type term;
+ //! A parser for the complete filter expression that consists of one or several terms with boolean operations between them
+ rule_type expression;
+
+public:
+ //! Constructor
+ filter_grammar() :
+ base_type(expression),
+ m_ComparisonRelation(NULL)
+ {
+ attr_name = qi::lexeme
+ [
+ // An attribute name in form %name%
+ qi::as< string_type >()[ qi::lit(constants::char_percent) >> +(encoding_specific::print - constants::char_percent) >> qi::lit(constants::char_percent) ]
+ [boost::bind(&filter_grammar::on_attribute_name, this, _1)]
+ ];
+
+ quoted_string_operand = qi::raw
+ [
+ qi::lexeme
+ [
+ // A quoted string with C-style escape sequences support
+ qi::lit(constants::char_quote) >>
+ *(
+ (qi::lit(constants::char_backslash) >> qi::char_) |
+ (qi::char_ - qi::lit(constants::char_quote))
+ ) >>
+ qi::lit(constants::char_quote)
+ ]
+ ]
+ [boost::bind(&filter_grammar::on_quoted_string_operand, this, _1)];
+
+ operand =
+ (
+ quoted_string_operand |
+ // A single word, enclosed with white spaces. It cannot contain parenthesis, since is is used by the filter parser.
+ qi::raw[ qi::lexeme[ +(encoding_specific::graph - qi::lit(constants::char_paren_bracket_left) - qi::lit(constants::char_paren_bracket_right)) ] ]
+ [boost::bind(&filter_grammar::on_operand, this, _1)]
+ );
+
+ // Custom relation is a keyword that may contain either alphanumeric characters or an underscore
+ custom_relation = qi::as< string_type >()[ qi::lexeme[ +(encoding_specific::alnum | qi::char_(constants::char_underline)) ] ]
+ [boost::bind(&filter_grammar::set_custom_relation, this, _1)];
+
+ comparison_relation.add
+ (constants::equal_keyword(), &filter_factory_type::on_equality_relation)
+ (constants::not_equal_keyword(), &filter_factory_type::on_inequality_relation)
+ (constants::greater_keyword(), &filter_factory_type::on_greater_relation)
+ (constants::less_keyword(), &filter_factory_type::on_less_relation)
+ (constants::greater_or_equal_keyword(), &filter_factory_type::on_greater_or_equal_relation)
+ (constants::less_or_equal_keyword(), &filter_factory_type::on_less_or_equal_relation);
+
+ relation =
+ (
+ attr_name >> // The relation may be as simple as a sole attribute name, in which case the filter checks for the attribute value presence
+ -(
+ (comparison_relation[boost::bind(&filter_grammar::set_comparison_relation, this, _1)] >> operand) |
+ (custom_relation >> operand)
+ )
+ )
+ [boost::bind(&filter_grammar::on_relation_complete, this)];
+
+ term =
+ (
+ (qi::lit(constants::char_paren_bracket_left) >> expression >> constants::char_paren_bracket_right) |
+ ((qi::lit(constants::not_keyword()) | constants::char_exclamation) >> term)[boost::bind(&filter_grammar::on_negation, this)] |
+ relation
+ );
+
+ expression =
+ (
+ term >>
+ *(
+ ((qi::lit(constants::and_keyword()) | constants::char_and) >> term)[boost::bind(&filter_grammar::on_and, this)] |
+ ((qi::lit(constants::or_keyword()) | constants::char_or) >> term)[boost::bind(&filter_grammar::on_or, this)]
+ )
+ );
+ }
+
+ //! The method returns the cinstructed filter
+ filter get_filter()
+ {
+ BOOST_ASSERT(!m_Subexpressions.empty());
+ return boost::move(m_Subexpressions.top());
+ }
+
+private:
+ //! The attribute name handler
+ void on_attribute_name(string_type const& name)
+ {
+ m_AttributeName = attribute_name(log::aux::to_narrow(name));
+ }
+
+ //! The operand string handler
+ void on_operand(iterator_range< iterator_type > const& arg)
+ {
+ // An attribute name should have been parsed at this point
+ if (!m_AttributeName)
+ BOOST_LOG_THROW_DESCR(parse_error, "Invalid filter definition: operand is not expected");
+
+ m_Operand = boost::in_place(arg.begin(), arg.end());
+ }
+
+ //! The quoted string handler
+ void on_quoted_string_operand(iterator_range< iterator_type > const& arg)
+ {
+ // An attribute name should have been parsed at this point
+ if (!m_AttributeName)
+ BOOST_LOG_THROW_DESCR(parse_error, "Invalid filter definition: quoted string operand is not expected");
+
+ // Cut off the quotes
+ string_type str(arg.begin() + 1, arg.end() - 1);
+
+ // Translate escape sequences
+ constants::translate_escape_sequences(str);
+ m_Operand = str;
+ }
+
+ //! The method saves the relation word into an internal string
+ void set_comparison_relation(comparison_relation_handler_t rel)
+ {
+ m_ComparisonRelation = rel;
+ }
+
+ //! The method saves the relation word into an internal string
+ void set_custom_relation(string_type const& rel)
+ {
+ m_CustomRelation = rel;
+ }
+
+ //! The comparison relation handler
+ void on_relation_complete()
+ {
+ if (!!m_AttributeName)
+ {
+ filters_repository< char_type > const& repo = filters_repository< char_type >::get();
+ filter_factory_type& factory = repo.get_factory(m_AttributeName);
+
+ if (!!m_Operand)
+ {
+ if (!!m_ComparisonRelation)
+ {
+ m_Subexpressions.push((factory.*m_ComparisonRelation)(m_AttributeName, m_Operand.get()));
+ m_ComparisonRelation = NULL;
+ }
+ else if (!m_CustomRelation.empty())
+ {
+ m_Subexpressions.push(factory.on_custom_relation(m_AttributeName, m_CustomRelation, m_Operand.get()));
+ m_CustomRelation.clear();
+ }
+ else
+ {
+ // This should never happen
+ BOOST_ASSERT_MSG(false, "Filter parser internal error: the attribute name or subexpression operation is not set while trying to construct a relation");
+ BOOST_LOG_THROW_DESCR(parse_error, "Filter parser internal error: the attribute name or subexpression operation is not set while trying to construct a subexpression");
+ }
+
+ m_Operand = none;
+ }
+ else
+ {
+ // This branch is taken if the relation is a single attribute name, which is recognized as the attribute presence check
+ BOOST_ASSERT_MSG(!m_ComparisonRelation && m_CustomRelation.empty(), "Filter parser internal error: the relation operation is set while operand is not");
+ m_Subexpressions.push(factory.on_exists_test(m_AttributeName));
+ }
+
+ m_AttributeName = attribute_name();
+ }
+ else
+ {
+ // This should never happen
+ BOOST_ASSERT_MSG(false, "Filter parser internal error: the attribute name is not set while trying to construct a relation");
+ BOOST_LOG_THROW_DESCR(parse_error, "Filter parser internal error: the attribute name is not set while trying to construct a relation");
+ }
+ }
+
+ //! The negation operation handler
+ void on_negation()
+ {
+ if (!m_Subexpressions.empty())
+ {
+ m_Subexpressions.top() = !phoenix::bind(m_Subexpressions.top(), phoenix::placeholders::_1);
+ }
+ else
+ {
+ // This would happen if a filter consists of a single '!'
+ BOOST_LOG_THROW_DESCR(parse_error, "Filter parsing error: a negation operator applied to nothingness");
+ }
+ }
+
+ //! The logical AND operation handler
+ void on_and()
+ {
+ if (!m_Subexpressions.empty())
+ {
+ filter right = boost::move(m_Subexpressions.top());
+ m_Subexpressions.pop();
+ if (!m_Subexpressions.empty())
+ {
+ filter const& left = m_Subexpressions.top();
+ m_Subexpressions.top() = phoenix::bind(left, phoenix::placeholders::_1) && phoenix::bind(right, phoenix::placeholders::_1);
+ return;
+ }
+ }
+
+ // This should never happen
+ BOOST_LOG_THROW_DESCR(parse_error, "Filter parser internal error: the subexpression is not set while trying to construct a filter");
+ }
+
+ //! The logical OR operation handler
+ void on_or()
+ {
+ if (!m_Subexpressions.empty())
+ {
+ filter right = boost::move(m_Subexpressions.top());
+ m_Subexpressions.pop();
+ if (!m_Subexpressions.empty())
+ {
+ filter const& left = m_Subexpressions.top();
+ m_Subexpressions.top() = phoenix::bind(left, phoenix::placeholders::_1) || phoenix::bind(right, phoenix::placeholders::_1);
+ return;
+ }
+ }
+
+ // This should never happen
+ BOOST_LOG_THROW_DESCR(parse_error, "Filter parser internal error: the subexpression is not set while trying to construct a filter");
+ }
+
+ // Assignment and copying are prohibited
+ BOOST_LOG_DELETED_FUNCTION(filter_grammar(filter_grammar const&))
+ BOOST_LOG_DELETED_FUNCTION(filter_grammar& operator= (filter_grammar const&))
+};
+
+} // namespace
+
+//! The function registers a filter factory object for the specified attribute name
+template< typename CharT >
+void register_filter_factory(attribute_name const& name, shared_ptr< filter_factory< CharT > > const& factory)
+{
+ BOOST_ASSERT(!!name);
+ BOOST_ASSERT(!!factory);
+
+ filters_repository< CharT >& repo = filters_repository< CharT >::get();
+
+ BOOST_LOG_EXPR_IF_MT(log::aux::exclusive_lock_guard< log::aux::light_rw_mutex > lock(repo.m_Mutex);)
+ repo.m_Map[name] = factory;
+}
+
+//! The function parses a filter from the string
+template< typename CharT >
+filter parse_filter(const CharT* begin, const CharT* end)
+{
+ typedef CharT char_type;
+ typedef log::aux::encoding_specific< typename log::aux::encoding< char_type >::type > encoding_specific;
+
+ filter_grammar< char_type > gram;
+ const char_type* p = begin;
+
+ BOOST_LOG_EXPR_IF_MT(filters_repository< CharT >& repo = filters_repository< CharT >::get();)
+ BOOST_LOG_EXPR_IF_MT(log::aux::shared_lock_guard< log::aux::light_rw_mutex > lock(repo.m_Mutex);)
+
+ bool result = qi::phrase_parse(p, end, gram, encoding_specific::space);
+ if (!result || p != end)
+ {
+ std::ostringstream strm;
+ strm << "Could not parse the filter, parsing stopped at position " << p - begin;
+ BOOST_LOG_THROW_DESCR(parse_error, strm.str());
+ }
+
+ return gram.get_filter();
+}
+
+#ifdef BOOST_LOG_USE_CHAR
+
+template BOOST_LOG_SETUP_API
+void register_filter_factory< char >(attribute_name const& name, shared_ptr< filter_factory< char > > const& factory);
+template BOOST_LOG_SETUP_API
+filter parse_filter< char >(const char* begin, const char* end);
+
+#endif // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+
+template BOOST_LOG_SETUP_API
+void register_filter_factory< wchar_t >(attribute_name const& name, shared_ptr< filter_factory< wchar_t > > const& factory);
+template BOOST_LOG_SETUP_API
+filter parse_filter< wchar_t >(const wchar_t* begin, const wchar_t* end);
+
+#endif // BOOST_LOG_USE_WCHAR_T
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_WITHOUT_SETTINGS_PARSERS

Added: trunk/libs/log/src/format_parser.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/format_parser.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,153 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_parser.cpp
+ * \author Andrey Semashev
+ * \date 16.11.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#include <string>
+#include <algorithm>
+#include <boost/throw_exception.hpp>
+#include <boost/exception/exception.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/spirit/include/qi_uint.hpp>
+#include <boost/spirit/include/qi_parse.hpp>
+#include <boost/log/detail/format.hpp>
+#include <boost/log/exceptions.hpp>
+#include <boost/log/support/exception.hpp>
+#include "spirit_encoding.hpp"
+#include <boost/log/detail/header.hpp>
+
+namespace qi = boost::spirit::qi;
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+template< typename CharT >
+format_description< CharT > parse_format(const CharT* begin, const CharT* end)
+{
+ typedef CharT char_type;
+ typedef format_description< char_type > description;
+ typedef typename encoding< char_type >::type traits;
+
+ const char_type* original_begin = begin;
+ description descr;
+ unsigned int literal_start_pos = 0;
+
+ while (begin != end)
+ {
+ const char_type* p = std::find(begin, end, static_cast< char_type >('%'));
+ descr.literal_chars.append(begin, p);
+
+ if ((end - p) >= 2)
+ {
+ // Check for a percent placeholder
+ char_type c = p[1];
+ if (c == static_cast< char_type >('%'))
+ {
+ descr.literal_chars.push_back(static_cast< char_type >('%'));
+ begin = p + 2;
+ continue;
+ }
+
+ // From here on, no more literals are possible. Append the literal element.
+ {
+ const unsigned int literal_chars_size = static_cast< unsigned int >(descr.literal_chars.size());
+ if (literal_start_pos < literal_chars_size)
+ {
+ descr.format_elements.push_back(format_element::literal(literal_start_pos, literal_chars_size - literal_start_pos));
+ literal_start_pos = literal_chars_size;
+ }
+ }
+
+ // Check if this is a positional argument
+ if (traits::isdigit(c))
+ {
+ if (c != static_cast< char_type >('0'))
+ {
+ // Positional argument in the form "%N%"
+ unsigned int n = 0;
+ const char_type* pp = p + 1;
+ qi::parse(pp, end, qi::uint_, n);
+ if (n == 0 || pp == end || *pp != static_cast< char_type >('%'))
+ {
+ boost::throw_exception(boost::enable_error_info(parse_error("Invalid positional format placeholder")) << boost::throw_file(__FILE__) << boost::throw_line(__LINE__)
+ << boost::log::position_info(static_cast< unsigned int >(p - original_begin))
+ );
+ }
+
+ // Safety check against ridiculously large argument numbers which would lead to excessive memory consumption.
+ // This could be useful if the format string is gathered from an external source (e.g. a config file).
+ if (n > 1000)
+ {
+ boost::throw_exception(boost::enable_error_info(limitation_error("Positional format placeholder too big")) << boost::throw_file(__FILE__) << boost::throw_line(__LINE__)
+ << boost::log::position_info(static_cast< unsigned int >(p - original_begin))
+ );
+ }
+
+ // We count positional arguments from 0, not from 1 as in format strings
+ descr.format_elements.push_back(format_element::positional_argument(n - 1));
+ begin = pp + 1; // skip the closing '%'
+
+ continue;
+ }
+ else
+ {
+ // This must be the filler character, not supported yet
+ }
+ }
+
+ // This must be something else, not supported yet
+ boost::throw_exception(boost::enable_error_info(parse_error("Unsupported format placeholder")) << boost::throw_file(__FILE__) << boost::throw_line(__LINE__)
+ << boost::log::position_info(static_cast< unsigned int >(p - original_begin))
+ );
+ }
+ else
+ {
+ if (p != end)
+ descr.literal_chars.push_back(static_cast< char_type >('%')); // a single '%' character at the end of the string
+ begin = end;
+ }
+ }
+
+ const unsigned int literal_chars_size = static_cast< unsigned int >(descr.literal_chars.size());
+ if (literal_start_pos < literal_chars_size)
+ descr.format_elements.push_back(format_element::literal(literal_start_pos, literal_chars_size - literal_start_pos));
+
+ return boost::move(descr);
+}
+
+
+#ifdef BOOST_LOG_USE_CHAR
+
+template BOOST_LOG_API
+format_description< char > parse_format(const char* begin, const char* end);
+
+#endif // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+
+template BOOST_LOG_API
+format_description< wchar_t > parse_format(const wchar_t* begin, const wchar_t* end);
+
+#endif // BOOST_LOG_USE_WCHAR_T
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>

Added: trunk/libs/log/src/formatter_parser.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/formatter_parser.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,458 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 07.04.2008
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#ifndef BOOST_LOG_WITHOUT_SETTINGS_PARSERS
+
+#undef BOOST_MPL_LIMIT_VECTOR_SIZE
+#define BOOST_MPL_LIMIT_VECTOR_SIZE 50
+
+#include <ctime>
+#include <map>
+#include <string>
+#include <sstream>
+#include <stdexcept>
+#include <boost/assert.hpp>
+#include <boost/bind.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/push_back.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/optional/optional.hpp>
+#include <boost/utility/in_place_factory.hpp>
+#include <boost/range/iterator_range_core.hpp>
+#include <boost/spirit/include/qi_core.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_lit.hpp>
+#include <boost/spirit/include/qi_raw.hpp>
+#include <boost/spirit/include/qi_lexeme.hpp>
+#include <boost/spirit/include/qi_as.hpp>
+#include <boost/spirit/include/qi_symbols.hpp>
+#include <boost/phoenix/core.hpp>
+#include <boost/phoenix/operator.hpp>
+#include <boost/date_time/gregorian/gregorian.hpp>
+#include <boost/date_time/local_time/local_time.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/log/expressions/attr.hpp>
+#include <boost/log/expressions/message.hpp>
+#include <boost/log/expressions/formatters/stream.hpp>
+#include <boost/log/attributes/attribute_name.hpp>
+#include <boost/log/attributes/named_scope.hpp>
+#include <boost/log/exceptions.hpp>
+#include <boost/log/detail/singleton.hpp>
+#include <boost/log/detail/process_id.hpp>
+#include <boost/log/detail/code_conversion.hpp>
+#include <boost/log/detail/default_attribute_names.hpp>
+#include <boost/log/utility/functional/nop.hpp>
+#include <boost/log/utility/setup/formatter_parser.hpp>
+#include <boost/log/utility/type_dispatch/standard_types.hpp>
+#include <boost/log/utility/type_dispatch/date_time_types.hpp>
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/log/detail/thread_id.hpp>
+#include <boost/log/detail/locks.hpp>
+#include <boost/log/detail/light_rw_mutex.hpp>
+#endif
+#include "parser_utils.hpp"
+#include "spirit_encoding.hpp"
+#include <boost/log/detail/header.hpp>
+
+namespace qi = boost::spirit::qi;
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+//! The structure contains formatter factories repository
+template< typename CharT >
+struct formatters_repository :
+ public log::aux::lazy_singleton< formatters_repository< CharT > >
+{
+ //! Base class type
+ typedef log::aux::lazy_singleton< formatters_repository< CharT > > base_type;
+
+#if !defined(BOOST_LOG_BROKEN_FRIEND_TEMPLATE_INSTANTIATIONS)
+ friend class log::aux::lazy_singleton< formatters_repository< CharT > >;
+#else
+ friend class base_type;
+#endif
+
+ typedef formatter_factory< CharT > formatter_factory_type;
+
+ //! Attribute name ordering predicate
+ struct attribute_name_order
+ {
+ typedef bool result_type;
+ result_type operator() (attribute_name const& left, attribute_name const& right) const
+ {
+ return left.id() < right.id();
+ }
+ };
+
+ //! Map of formatter factories
+ typedef std::map< attribute_name, shared_ptr< formatter_factory_type >, attribute_name_order > factories_map;
+
+
+#if !defined(BOOST_LOG_NO_THREADS)
+ //! Synchronization mutex
+ mutable log::aux::light_rw_mutex m_Mutex;
+#endif
+ //! The map of formatter factories
+ factories_map m_Map;
+
+private:
+ formatters_repository()
+ {
+ }
+};
+
+//! Function object for formatter chaining
+template< typename CharT, typename SecondT >
+struct chained_formatter
+{
+ typedef void result_type;
+ typedef basic_formatter< CharT > formatter_type;
+ typedef typename formatter_type::stream_type stream_type;
+
+#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ explicit chained_formatter(formatter_type&& first, SecondT&& second) :
+#else
+ template< typename T >
+ explicit chained_formatter(BOOST_RV_REF(formatter_type) first, T const& second) :
+#endif
+ m_first(boost::move(first)), m_second(boost::move(second))
+ {
+ }
+
+ result_type operator() (record_view const& rec, stream_type& strm) const
+ {
+ m_first(rec, strm);
+ m_second(rec, strm);
+ }
+
+private:
+ formatter_type m_first;
+ SecondT m_second;
+};
+
+//! Formatter parsing grammar
+template< typename CharT >
+class formatter_grammar :
+ public qi::grammar< const CharT* >
+{
+private:
+ typedef CharT char_type;
+ typedef const char_type* iterator_type;
+ typedef qi::grammar< iterator_type > base_type;
+ typedef typename base_type::start_type rule_type;
+ typedef std::basic_string< char_type > string_type;
+ typedef basic_formatter< char_type > formatter_type;
+ typedef boost::log::aux::char_constants< char_type > constants;
+ typedef log::aux::encoding_specific< typename log::aux::encoding< char_type >::type > encoding_specific;
+ typedef formatter_factory< char_type > formatter_factory_type;
+ typedef typename formatter_factory_type::args_map args_map;
+
+private:
+ //! The formatter being constructed
+ optional< formatter_type > m_Formatter;
+
+ //! Attribute name
+ attribute_name m_AttrName;
+ //! Formatter factory arguments
+ args_map m_FactoryArgs;
+
+ //! Formatter argument name
+ mutable string_type m_ArgName;
+ //! Argument value
+ mutable string_type m_ArgValue;
+
+ //! A parser for a quoted string argument value
+ rule_type quoted_string_arg_value;
+ //! A parser for an argument value
+ rule_type arg_value;
+ //! A parser for a named argument
+ rule_type arg;
+ //! A parser for an optional argument list for a formatter
+ rule_type arg_list;
+ //! A parser for an attribute placeholder
+ rule_type attr_name;
+ //! A parser for the complete formatter expression
+ rule_type expression;
+
+public:
+ //! Constructor
+ formatter_grammar() :
+ base_type(expression)
+ {
+ quoted_string_arg_value = qi::raw
+ [
+ // A quoted string with C-style escape sequences support
+ qi::lit(constants::char_quote) >>
+ *(
+ (qi::lit(constants::char_backslash) >> qi::char_) |
+ (qi::char_ - qi::lit(constants::char_quote))
+ ) >>
+ qi::lit(constants::char_quote)
+ ]
+ [boost::bind(&formatter_grammar::on_quoted_string_arg_value, this, _1)];
+
+ arg_value =
+ (
+ quoted_string_arg_value |
+ qi::raw[ *(encoding_specific::graph - constants::char_comma - constants::char_paren_bracket_left - constants::char_paren_bracket_right) ]
+ [boost::bind(&formatter_grammar::on_arg_value, this, _1)]
+ );
+
+ arg =
+ (
+ *encoding_specific::space >>
+ qi::raw[ encoding_specific::alpha >> *encoding_specific::alnum ][boost::bind(&formatter_grammar::on_arg_name, this, _1)] >>
+ *encoding_specific::space >>
+ constants::char_equal >>
+ *encoding_specific::space >>
+ arg_value >>
+ *encoding_specific::space
+ );
+
+ arg_list =
+ (
+ qi::lit(constants::char_paren_bracket_left) >>
+ (arg[boost::bind(&formatter_grammar::push_arg, this)] % qi::lit(constants::char_comma)) >>
+ qi::lit(constants::char_paren_bracket_right)
+ );
+
+ attr_name =
+ (
+ qi::lit(constants::char_percent) >>
+ (
+ qi::raw[ qi::lit(constants::message_text_keyword()) ]
+ [boost::bind(&formatter_grammar::on_attr_name, this, _1)] |
+ (
+ qi::raw[ +(encoding_specific::print - constants::char_paren_bracket_left - constants::char_percent) ]
+ [boost::bind(&formatter_grammar::on_attr_name, this, _1)] >>
+ -arg_list
+ )
+ ) >>
+ qi::lit(constants::char_percent)
+ )
+ [boost::bind(&formatter_grammar::push_attr, this)];
+
+ expression =
+ (
+ qi::raw
+ [
+ *(
+ (qi::lit(constants::char_backslash) >> qi::char_) |
+ (qi::char_ - qi::lit(constants::char_quote) - qi::lit(constants::char_percent))
+ )
+ ][boost::bind(&formatter_grammar::push_string, this, _1)] %
+ attr_name
+ );
+ }
+
+ //! Returns the parsed formatter
+ formatter_type get_formatter()
+ {
+ if (!m_Formatter)
+ {
+ // This may happen if parser input is an empty string
+ return formatter_type(nop());
+ }
+
+ return boost::move(m_Formatter.get());
+ }
+
+private:
+ //! The method is called when an argument name is discovered
+ void on_arg_name(iterator_range< iterator_type > const& name)
+ {
+ m_ArgName.assign(name.begin(), name.end());
+ }
+ //! The method is called when an argument value is discovered
+ void on_quoted_string_arg_value(iterator_range< iterator_type > const& value)
+ {
+ // Cut off the quotes
+ m_ArgValue.assign(value.begin() + 1, value.end() - 1);
+ constants::translate_escape_sequences(m_ArgValue);
+ }
+ //! The method is called when an argument value is discovered
+ void on_arg_value(iterator_range< iterator_type > const& value)
+ {
+ m_ArgValue.assign(value.begin(), value.end());
+ }
+ //! The method is called when an argument is filled
+ void push_arg()
+ {
+ m_FactoryArgs[m_ArgName] = m_ArgValue;
+ m_ArgName.clear();
+ m_ArgValue.clear();
+ }
+
+ //! The method is called when an attribute name is discovered
+ void on_attr_name(iterator_range< iterator_type > const& name)
+ {
+ if (name.empty())
+ BOOST_LOG_THROW_DESCR(parse_error, "Empty attribute name encountered");
+
+ // For compatibility with Boost.Log v1 we recognize %_% as the message attribute name
+ if (std::char_traits< char_type >::compare(constants::message_text_keyword(), name.begin(), name.size()) == 0)
+ m_AttrName = log::aux::default_attribute_names::message();
+ else
+ m_AttrName = attribute_name(log::aux::to_narrow(string_type(name.begin(), name.end())));
+ }
+ //! The method is called when an attribute is filled
+ void push_attr()
+ {
+ BOOST_ASSERT_MSG(!!m_AttrName, "Attribute name is not set");
+
+ if (m_AttrName == log::aux::default_attribute_names::message())
+ {
+ // We make a special treatment for the message text formatter
+ append_formatter(expressions::stream << expressions::message);
+ }
+ else
+ {
+ formatters_repository< char_type > const& repo = formatters_repository< char_type >::get();
+ typename formatters_repository< char_type >::factories_map::const_iterator it = repo.m_Map.find(m_AttrName);
+ if (it != repo.m_Map.end())
+ {
+ // We've found a user-defined factory for this attribute
+ append_formatter(it->second->create_formatter(m_AttrName, m_FactoryArgs));
+ }
+ else
+ {
+ // No user-defined factory, shall use the most generic formatter we can ever imagine at this point
+ typedef mpl::copy<
+ // We have to exclude std::time_t since it's an integral type and will conflict with one of the standard types
+ boost_time_period_types,
+ mpl::back_inserter<
+ mpl::copy<
+ boost_time_duration_types,
+ mpl::back_inserter< boost_date_time_types >
+ >::type
+ >
+ >::type time_related_types;
+
+ typedef mpl::copy<
+ mpl::copy<
+ mpl::vector<
+ attributes::named_scope_list,
+#if !defined(BOOST_LOG_NO_THREADS)
+ log::aux::thread::id,
+#endif
+ log::aux::process::id
+ >,
+ mpl::back_inserter< time_related_types >
+ >::type,
+ mpl::back_inserter< default_attribute_types >
+ >::type supported_types;
+
+ append_formatter(expressions::stream << expressions::attr< supported_types::type >(m_AttrName));
+ }
+ }
+
+ // Eventually, clear all the auxiliary data
+ m_AttrName = attribute_name();
+ m_FactoryArgs.clear();
+ }
+
+ //! The method is called when a string literal is discovered
+ void push_string(iterator_range< iterator_type > const& str)
+ {
+ if (!str.empty())
+ {
+ string_type s(str.begin(), str.end());
+ constants::translate_escape_sequences(s);
+ append_formatter(expressions::stream << s);
+ }
+ }
+
+ //! The method appends a formatter part to the final formatter
+ template< typename FormatterT >
+ void append_formatter(FormatterT fmt)
+ {
+ if (!!m_Formatter)
+ m_Formatter = boost::in_place(chained_formatter< char_type, FormatterT >(boost::move(m_Formatter.get()), boost::move(fmt)));
+ else
+ m_Formatter = boost::in_place(boost::move(fmt));
+ }
+
+ // Assignment and copying are prohibited
+ BOOST_LOG_DELETED_FUNCTION(formatter_grammar(formatter_grammar const&))
+ BOOST_LOG_DELETED_FUNCTION(formatter_grammar& operator= (formatter_grammar const&))
+};
+
+} // namespace
+
+//! The function registers a user-defined formatter factory
+template< typename CharT >
+void register_formatter_factory(attribute_name const& name, shared_ptr< formatter_factory< CharT > > const& factory)
+{
+ BOOST_ASSERT(!!name);
+ BOOST_ASSERT(!!factory);
+
+ formatters_repository< CharT >& repo = formatters_repository< CharT >::get();
+ BOOST_LOG_EXPR_IF_MT(log::aux::exclusive_lock_guard< log::aux::light_rw_mutex > _(repo.m_Mutex);)
+ repo.m_Map[name] = factory;
+}
+
+//! The function parses a formatter from the string
+template< typename CharT >
+basic_formatter< CharT > parse_formatter(const CharT* begin, const CharT* end)
+{
+ typedef CharT char_type;
+
+ formatter_grammar< char_type > gram;
+ const char_type* p = begin;
+
+ BOOST_LOG_EXPR_IF_MT(formatters_repository< CharT >& repo = formatters_repository< CharT >::get();)
+ BOOST_LOG_EXPR_IF_MT(log::aux::shared_lock_guard< log::aux::light_rw_mutex > _(repo.m_Mutex);)
+
+ bool result = qi::parse(p, end, gram);
+ if (!result || p != end)
+ {
+ std::ostringstream strm;
+ strm << "Could not parse the formatter, parsing stopped at position " << p - begin;
+ BOOST_LOG_THROW_DESCR(parse_error, strm.str());
+ }
+
+ return gram.get_formatter();
+}
+
+#ifdef BOOST_LOG_USE_CHAR
+template BOOST_LOG_SETUP_API
+void register_formatter_factory< char >(
+ attribute_name const& attr_name, shared_ptr< formatter_factory< char > > const& factory);
+template BOOST_LOG_SETUP_API
+basic_formatter< char > parse_formatter< char >(const char* begin, const char* end);
+#endif // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+template BOOST_LOG_SETUP_API
+void register_formatter_factory< wchar_t >(
+ attribute_name const& attr_name, shared_ptr< formatter_factory< wchar_t > > const& factory);
+template BOOST_LOG_SETUP_API
+basic_formatter< wchar_t > parse_formatter< wchar_t >(const wchar_t* begin, const wchar_t* end);
+#endif // BOOST_LOG_USE_WCHAR_T
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_WITHOUT_SETTINGS_PARSERS

Added: trunk/libs/log/src/global_logger_storage.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/global_logger_storage.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,109 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 21.04.2008
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#include <map>
+#include <string>
+#include <boost/limits.hpp>
+#include <boost/log/exceptions.hpp>
+#include <boost/log/detail/snprintf.hpp>
+#include <boost/log/detail/singleton.hpp>
+#include <boost/log/utility/type_info_wrapper.hpp>
+#include <boost/log/sources/global_logger_storage.hpp>
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/thread/mutex.hpp>
+#include <boost/log/detail/locks.hpp>
+#endif
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sources {
+
+namespace aux {
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+//! The loggers repository singleton
+struct loggers_repository :
+ public log::aux::lazy_singleton< loggers_repository >
+{
+ //! Repository map type
+ typedef std::map< type_info_wrapper, shared_ptr< logger_holder_base > > loggers_map_t;
+
+#if !defined(BOOST_LOG_NO_THREADS)
+ //! Synchronization primitive
+ mutable mutex m_Mutex;
+#endif
+ //! Map of logger holders
+ loggers_map_t m_Loggers;
+};
+
+} // namespace
+
+//! Finds or creates the logger and returns its holder
+BOOST_LOG_API shared_ptr< logger_holder_base > global_storage::get_or_init(std::type_info const& key, initializer_t initializer)
+{
+ typedef loggers_repository::loggers_map_t loggers_map_t;
+ loggers_repository& repo = loggers_repository::get();
+ type_info_wrapper wrapped_key = key;
+
+ BOOST_LOG_EXPR_IF_MT(log::aux::exclusive_lock_guard< mutex > lock(repo.m_Mutex);)
+ loggers_map_t::iterator it = repo.m_Loggers.find(wrapped_key);
+ if (it != repo.m_Loggers.end())
+ {
+ // There is an instance
+ return it->second;
+ }
+ else
+ {
+ // We have to create a logger instance
+ shared_ptr< logger_holder_base > inst = initializer();
+ repo.m_Loggers[wrapped_key] = inst;
+ return inst;
+ }
+}
+
+//! 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)
+{
+ char buf[std::numeric_limits< unsigned int >::digits10 + 3];
+ log::aux::snprintf(buf, sizeof(buf), "%u", registered.m_RegistrationLine);
+ std::string str =
+ std::string("Could not initialize global logger with tag \"") +
+ type_info_wrapper(tag_type).pretty_name() +
+ "\" and type \"" +
+ type_info_wrapper(logger_type).pretty_name() +
+ "\". A logger of type \"" +
+ type_info_wrapper(registered.logger_type()).pretty_name() +
+ "\" with the same tag has already been registered at " +
+ registered.m_RegistrationFile + ":" + buf + ".";
+
+ BOOST_LOG_THROW_DESCR(odr_violation, str);
+}
+
+} // namespace aux
+
+} // namespace sources
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>

Added: trunk/libs/log/src/init_from_settings.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/init_from_settings.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,756 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 init_from_settings.cpp
+ * \author Andrey Semashev
+ * \date 11.10.2009
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#ifndef BOOST_LOG_WITHOUT_SETTINGS_PARSERS
+
+#include "windows_version.hpp"
+#include <ios>
+#include <map>
+#include <vector>
+#include <string>
+#include <utility>
+#include <iostream>
+#include <typeinfo>
+#include <stdexcept>
+#include <algorithm>
+#include <boost/type.hpp>
+#include <boost/bind.hpp>
+#include <boost/limits.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/optional.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/date_time/date_defs.hpp>
+#include <boost/property_tree/ptree.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_unsigned.hpp>
+#include <boost/spirit/include/qi_core.hpp>
+#include <boost/spirit/include/qi_lit.hpp>
+#include <boost/spirit/include/qi_eoi.hpp>
+#include <boost/spirit/include/qi_symbols.hpp>
+#include <boost/log/detail/code_conversion.hpp>
+#include <boost/log/detail/singleton.hpp>
+#include <boost/log/detail/default_attribute_names.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/sinks.hpp>
+#include <boost/log/exceptions.hpp>
+#include <boost/log/sinks/frontend_requirements.hpp>
+#include <boost/log/expressions/filter.hpp>
+#include <boost/log/expressions/formatter.hpp>
+#include <boost/log/utility/empty_deleter.hpp>
+#include <boost/log/utility/setup/from_settings.hpp>
+#include <boost/log/utility/setup/filter_parser.hpp>
+#include <boost/log/utility/setup/formatter_parser.hpp>
+#include <boost/log/utility/functional/bind_assign.hpp>
+#include <boost/log/utility/functional/as_action.hpp>
+#if !defined(BOOST_LOG_NO_ASIO)
+#include <boost/asio/ip/address.hpp>
+#endif
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/log/detail/locks.hpp>
+#include <boost/log/detail/light_rw_mutex.hpp>
+#endif
+#include "parser_utils.hpp"
+#include "spirit_encoding.hpp"
+#include <boost/log/detail/header.hpp>
+
+namespace qi = boost::spirit::qi;
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+//! Throws an exception when a parameter value is not valid
+BOOST_LOG_NORETURN void throw_invalid_value(const char* param_name)
+{
+ std::string descr = std::string("Invalid parameter \"")
+ + param_name
+ + "\" value";
+ BOOST_LOG_THROW_DESCR(invalid_value, descr);
+}
+
+//! Extracts an integral value from parameter value
+template< typename IntT, typename CharT >
+inline IntT param_cast_to_int(const char* param_name, std::basic_string< CharT > const& value)
+{
+ IntT res = 0;
+ typedef typename mpl::if_<
+ is_unsigned< IntT >,
+ qi::uint_parser< IntT >,
+ qi::int_parser< IntT >
+ >::type int_parser_t;
+ if (qi::parse(value.begin(), value.end(), int_parser_t() >> qi::eoi, res))
+ return res;
+ else
+ throw_invalid_value(param_name);
+}
+
+//! Extracts a boolean value from parameter value
+template< typename CharT >
+inline bool param_cast_to_bool(const char* param_name, std::basic_string< CharT > const& value)
+{
+ typedef boost::log::aux::encoding_specific< typename boost::log::aux::encoding< CharT >::type > encoding_specific;
+
+ unsigned int res = 0;
+ if (qi::parse(value.begin(), value.end(), encoding_specific::no_case[ qi::uint_ | qi::bool_ ] >> qi::eoi, res))
+ return res != 0;
+ else
+ throw_invalid_value(param_name);
+}
+
+#if !defined(BOOST_LOG_NO_ASIO)
+//! Extracts a network address from parameter value
+template< typename CharT >
+inline std::string param_cast_to_address(const char* param_name, std::basic_string< CharT > const& value)
+{
+ return log::aux::to_narrow(value);
+}
+#endif // !defined(BOOST_LOG_NO_ASIO)
+
+//! The function extracts the file rotation time point predicate from the parameter
+template< typename CharT >
+sinks::file::rotation_at_time_point param_cast_to_rotation_time_point(const char* param_name, std::basic_string< CharT > const& value)
+{
+ typedef CharT char_type;
+ typedef boost::log::aux::encoding_specific< typename boost::log::aux::encoding< char_type >::type > encoding_specific;
+ typedef boost::log::aux::char_constants< char_type > constants;
+ typedef std::basic_string< char_type > string_type;
+
+ const char_type colon = static_cast< char_type >(':');
+ qi::uint_parser< unsigned char, 10, 2, 2 > time_component_p;
+ qi::uint_parser< unsigned short, 10, 1, 2 > day_p;
+
+ qi::symbols< CharT, date_time::weekdays > weekday_p;
+ weekday_p.add
+ (constants::monday_keyword(), date_time::Monday)
+ (constants::tuesday_keyword(), date_time::Tuesday)
+ (constants::wednesday_keyword(), date_time::Wednesday)
+ (constants::thursday_keyword(), date_time::Thursday)
+ (constants::friday_keyword(), date_time::Friday)
+ (constants::saturday_keyword(), date_time::Saturday)
+ (constants::sunday_keyword(), date_time::Sunday);
+ weekday_p.add
+ (constants::short_monday_keyword(), date_time::Monday)
+ (constants::short_tuesday_keyword(), date_time::Tuesday)
+ (constants::short_wednesday_keyword(), date_time::Wednesday)
+ (constants::short_thursday_keyword(), date_time::Thursday)
+ (constants::short_friday_keyword(), date_time::Friday)
+ (constants::short_saturday_keyword(), date_time::Saturday)
+ (constants::short_sunday_keyword(), date_time::Sunday);
+
+ optional< date_time::weekdays > weekday;
+ optional< unsigned short > day;
+ unsigned char hour = 0, minute = 0, second = 0;
+
+ bool result = qi::parse
+ (
+ value.begin(), value.end(),
+ (
+ -(
+ (
+ // First check for a weekday
+ weekday_p[boost::log::as_action(boost::log::bind_assign(weekday))] |
+ // ... or a day in month
+ day_p[boost::log::as_action(boost::log::bind_assign(day))]
+ ) >>
+ (+encoding_specific::space)
+ ) >>
+ // Then goes the time of day
+ (
+ time_component_p[boost::log::as_action(boost::log::bind_assign(hour))] >> colon >>
+ time_component_p[boost::log::as_action(boost::log::bind_assign(minute))] >> colon >>
+ time_component_p[boost::log::as_action(boost::log::bind_assign(second))]
+ ) >>
+ qi::eoi
+ )
+ );
+
+ if (!result)
+ throw_invalid_value(param_name);
+
+ if (weekday)
+ return sinks::file::rotation_at_time_point(weekday.get(), hour, minute, second);
+ else if (day)
+ return sinks::file::rotation_at_time_point(gregorian::greg_day(day.get()), hour, minute, second);
+ else
+ return sinks::file::rotation_at_time_point(hour, minute, second);
+}
+
+//! Base class for default sink factories
+template< typename CharT >
+class basic_default_sink_factory :
+ public sink_factory< CharT >
+{
+public:
+ typedef sink_factory< CharT > base_type;
+ typedef typename base_type::char_type char_type;
+ typedef typename base_type::string_type string_type;
+ typedef typename base_type::settings_section settings_section;
+ typedef boost::log::aux::char_constants< char_type > constants;
+
+protected:
+ //! Sink backend character selection function
+ template< typename InitializerT >
+ static shared_ptr< sinks::sink > select_backend_character_type(settings_section const& params, InitializerT initializer)
+ {
+#if defined(BOOST_LOG_USE_CHAR) && defined(BOOST_LOG_USE_WCHAR_T)
+ if (optional< string_type > wide_param = params["Wide"])
+ {
+ if (param_cast_to_bool("Wide", wide_param.get()))
+ return initializer(params, type< wchar_t >());
+ }
+
+ return initializer(params, type< char >());
+#elif defined(BOOST_LOG_USE_CHAR)
+ return initializer(params, type< char >());
+#elif defined(BOOST_LOG_USE_WCHAR_T)
+ return initializer(params, type< wchar_t >());
+#endif
+ }
+
+ //! The function initializes common parameters of a formatting sink and returns the constructed sink
+ template< typename BackendT >
+ static shared_ptr< sinks::sink > init_sink(shared_ptr< BackendT > const& backend, settings_section const& params)
+ {
+ typedef BackendT backend_t;
+ typedef typename sinks::has_requirement<
+ typename backend_t::frontend_requirements,
+ sinks::formatted_records
+ >::type is_formatting_t;
+
+ // Filter
+ filter filt;
+ if (optional< string_type > filter_param = params["Filter"])
+ {
+ filt = parse_filter(filter_param.get());
+ }
+
+ shared_ptr< sinks::basic_sink_frontend > p;
+
+#if !defined(BOOST_LOG_NO_THREADS)
+ // Asynchronous. TODO: make it more flexible.
+ bool async = false;
+ if (optional< string_type > async_param = params["Asynchronous"])
+ {
+ async = param_cast_to_bool("Asynchronous", async_param.get());
+ }
+
+ // Construct the frontend, considering Asynchronous parameter
+ if (!async)
+ p = init_formatter(boost::make_shared< sinks::synchronous_sink< backend_t > >(backend), params, is_formatting_t());
+ else
+ p = init_formatter(boost::make_shared< sinks::asynchronous_sink< backend_t > >(backend), params, is_formatting_t());
+#else
+ // When multithreading is disabled we always use the unlocked sink frontend
+ p = init_formatter(boost::make_shared< sinks::unlocked_sink< backend_t > >(backend), params, is_formatting_t());
+#endif
+
+ p->set_filter(filt);
+
+ return p;
+ }
+
+private:
+ //! The function initializes formatter for the sinks that support formatting
+ template< typename SinkT >
+ static shared_ptr< SinkT > init_formatter(shared_ptr< SinkT > const& sink, settings_section const& params, mpl::true_)
+ {
+ // Formatter
+ if (optional< string_type > format_param = params["Format"])
+ {
+ typedef typename SinkT::char_type sink_char_type;
+ std::basic_string< sink_char_type > format_str;
+ log::aux::code_convert(format_param.get(), format_str);
+ sink->set_formatter(parse_formatter(format_str));
+ }
+ return sink;
+ }
+ template< typename SinkT >
+ static shared_ptr< SinkT > init_formatter(shared_ptr< SinkT > const& sink, settings_section const& params, mpl::false_)
+ {
+ return sink;
+ }
+};
+
+//! Default console sink factory
+template< typename CharT >
+class default_console_sink_factory :
+ public basic_default_sink_factory< CharT >
+{
+public:
+ typedef basic_default_sink_factory< CharT > base_type;
+ typedef typename base_type::char_type char_type;
+ typedef typename base_type::string_type string_type;
+ typedef typename base_type::settings_section settings_section;
+ typedef typename base_type::constants constants;
+
+private:
+ struct impl;
+ friend struct impl;
+ struct impl
+ {
+ typedef shared_ptr< sinks::sink > result_type;
+
+ template< typename BackendCharT >
+ result_type operator() (settings_section const& params, type< BackendCharT >) const
+ {
+ // Construct the backend
+ typedef boost::log::aux::char_constants< BackendCharT > constants;
+ typedef sinks::basic_text_ostream_backend< BackendCharT > backend_t;
+ shared_ptr< backend_t > backend = boost::make_shared< backend_t >();
+ backend->add_stream(shared_ptr< typename backend_t::stream_type >(&constants::get_console_log_stream(), empty_deleter()));
+
+ // Auto flush
+ if (optional< string_type > auto_flush_param = params["AutoFlush"])
+ {
+ backend->auto_flush(param_cast_to_bool("AutoFlush", auto_flush_param.get()));
+ }
+
+ return base_type::init_sink(backend, params);
+ }
+ };
+
+public:
+ //! The function constructs a sink that writes log records to the console
+ shared_ptr< sinks::sink > create_sink(settings_section const& params)
+ {
+ return base_type::select_backend_character_type(params, impl());
+ }
+};
+
+//! Default text file sink factory
+template< typename CharT >
+class default_text_file_sink_factory :
+ public basic_default_sink_factory< CharT >
+{
+public:
+ typedef basic_default_sink_factory< CharT > base_type;
+ typedef typename base_type::char_type char_type;
+ typedef typename base_type::string_type string_type;
+ typedef typename base_type::settings_section settings_section;
+ typedef typename base_type::constants constants;
+
+public:
+ //! The function constructs a sink that writes log records to a text file
+ shared_ptr< sinks::sink > create_sink(settings_section const& params)
+ {
+ typedef sinks::text_file_backend backend_t;
+ shared_ptr< backend_t > backend = boost::make_shared< backend_t >();
+
+ // FileName
+ if (optional< string_type > file_name_param = params["FileName"])
+ {
+ backend->set_file_name_pattern(filesystem::path(file_name_param.get()));
+ }
+ else
+ BOOST_LOG_THROW_DESCR(missing_value, "File name is not specified");
+
+ // File rotation size
+ if (optional< string_type > rotation_size_param = params["RotationSize"])
+ {
+ backend->set_rotation_size(param_cast_to_int< uintmax_t >("RotationSize", rotation_size_param.get()));
+ }
+
+ // File rotation interval
+ if (optional< string_type > rotation_interval_param = params["RotationInterval"])
+ {
+ backend->set_time_based_rotation(sinks::file::rotation_at_time_interval(
+ posix_time::seconds(param_cast_to_int< unsigned int >("RotationInterval", rotation_interval_param.get()))));
+ }
+ else if (optional< string_type > rotation_time_point_param = params["RotationTimePoint"])
+ {
+ // File rotation time point
+ backend->set_time_based_rotation(param_cast_to_rotation_time_point("RotationTimePoint", rotation_time_point_param.get()));
+ }
+
+ // Auto flush
+ if (optional< string_type > auto_flush_param = params["AutoFlush"])
+ {
+ backend->auto_flush(param_cast_to_bool("AutoFlush", auto_flush_param.get()));
+ }
+
+ // Append
+ if (optional< string_type > append_param = params["Append"])
+ {
+ if (param_cast_to_bool("Append", append_param.get()))
+ backend->set_open_mode(std::ios_base::out | std::ios_base::app);
+ }
+
+ // File collector parameters
+ // Target directory
+ if (optional< string_type > target_param = params["Target"])
+ {
+ filesystem::path target_dir(target_param.get());
+
+ // Max total size
+ uintmax_t max_size = (std::numeric_limits< uintmax_t >::max)();
+ if (optional< string_type > max_size_param = params["MaxSize"])
+ max_size = param_cast_to_int< uintmax_t >("MaxSize", max_size_param.get());
+
+ // Min free space
+ uintmax_t space = 0;
+ if (optional< string_type > min_space_param = params["MinFreeSpace"])
+ space = param_cast_to_int< uintmax_t >("MinFreeSpace", min_space_param.get());
+
+ backend->set_file_collector(sinks::file::make_collector(
+ keywords::target = target_dir,
+ keywords::max_size = max_size,
+ keywords::min_free_space = space));
+
+ // Scan for log files
+ if (optional< string_type > scan_param = params["ScanForFiles"])
+ {
+ string_type const& value = scan_param.get();
+ if (value == constants::scan_method_all())
+ backend->scan_for_files(sinks::file::scan_all);
+ else if (value == constants::scan_method_matching())
+ backend->scan_for_files(sinks::file::scan_matching);
+ else
+ {
+ BOOST_LOG_THROW_DESCR(invalid_value,
+ "File scan method \"" + boost::log::aux::to_narrow(value) + "\" is not supported");
+ }
+ }
+ }
+
+ return base_type::init_sink(backend, params);
+ }
+};
+
+#ifndef BOOST_LOG_WITHOUT_SYSLOG
+
+//! Default syslog sink factory
+template< typename CharT >
+class default_syslog_sink_factory :
+ public basic_default_sink_factory< CharT >
+{
+public:
+ typedef basic_default_sink_factory< CharT > base_type;
+ typedef typename base_type::char_type char_type;
+ typedef typename base_type::string_type string_type;
+ typedef typename base_type::settings_section settings_section;
+ typedef typename base_type::constants constants;
+
+public:
+ //! The function constructs a sink that writes log records to syslog
+ shared_ptr< sinks::sink > create_sink(settings_section const& params)
+ {
+ // Construct the backend
+ typedef sinks::syslog_backend backend_t;
+ shared_ptr< backend_t > backend = boost::make_shared< backend_t >();
+
+ // For now we use only the default level mapping. Will add support for configuration later.
+ backend->set_severity_mapper(sinks::syslog::direct_severity_mapping< >(log::aux::default_attribute_names::severity()));
+
+#if !defined(BOOST_LOG_NO_ASIO)
+ // Setup local and remote addresses
+ if (optional< string_type > local_address_param = params["LocalAddress"])
+ backend->set_local_address(param_cast_to_address("LocalAddress", local_address_param.get()));
+
+ if (optional< string_type > target_address_param = params["TargetAddress"])
+ backend->set_target_address(param_cast_to_address("TargetAddress", target_address_param.get()));
+#endif // !defined(BOOST_LOG_NO_ASIO)
+
+ return base_type::init_sink(backend, params);
+ }
+};
+
+#endif // !defined(BOOST_LOG_WITHOUT_SYSLOG)
+
+#ifndef BOOST_LOG_WITHOUT_DEBUG_OUTPUT
+
+//! Default debugger sink factory
+template< typename CharT >
+class default_debugger_sink_factory :
+ public basic_default_sink_factory< CharT >
+{
+public:
+ typedef basic_default_sink_factory< CharT > base_type;
+ typedef typename base_type::char_type char_type;
+ typedef typename base_type::string_type string_type;
+ typedef typename base_type::settings_section settings_section;
+ typedef typename base_type::constants constants;
+
+private:
+ struct impl;
+ friend struct impl;
+ struct impl
+ {
+ typedef shared_ptr< sinks::sink > result_type;
+
+ template< typename BackendCharT >
+ result_type operator() (settings_section const& params, type< BackendCharT >) const
+ {
+ // Construct the backend
+ typedef sinks::basic_debug_output_backend< BackendCharT > backend_t;
+ shared_ptr< backend_t > backend = boost::make_shared< backend_t >();
+
+ return base_type::init_sink(backend, params);
+ }
+ };
+
+public:
+ //! The function constructs a sink that writes log records to the debugger
+ shared_ptr< sinks::sink > create_sink(settings_section const& params)
+ {
+ return base_type::select_backend_character_type(params, impl());
+ }
+};
+
+#endif // !defined(BOOST_LOG_WITHOUT_DEBUG_OUTPUT)
+
+#ifndef BOOST_LOG_WITHOUT_EVENT_LOG
+
+//! Default simple event log sink factory
+template< typename CharT >
+class default_simple_event_log_sink_factory :
+ public basic_default_sink_factory< CharT >
+{
+public:
+ typedef basic_default_sink_factory< CharT > base_type;
+ typedef typename base_type::char_type char_type;
+ typedef typename base_type::string_type string_type;
+ typedef typename base_type::settings_section settings_section;
+ typedef typename base_type::constants constants;
+
+private:
+ struct impl;
+ friend struct impl;
+ struct impl
+ {
+ typedef shared_ptr< sinks::sink > result_type;
+
+ template< typename BackendCharT >
+ result_type operator() (settings_section const& params, type< BackendCharT >) const
+ {
+ typedef sinks::basic_simple_event_log_backend< BackendCharT > backend_t;
+ typedef typename backend_t::string_type backend_string_type;
+
+ // Determine the log name
+ backend_string_type log_name;
+ if (optional< string_type > log_name_param = params["LogName"])
+ log::aux::code_convert(log_name_param.get(), log_name);
+ else
+ log_name = backend_t::get_default_log_name();
+
+ // Determine the log source name
+ backend_string_type source_name;
+ if (optional< string_type > log_source_param = params["LogSource"])
+ log::aux::code_convert(log_source_param.get(), source_name);
+ else
+ source_name = backend_t::get_default_source_name();
+
+ // Determine the registration mode
+ sinks::event_log::registration_mode reg_mode = sinks::event_log::on_demand;
+ if (optional< string_type > registration_param = params["Registration"])
+ {
+ string_type const& value = registration_param.get();
+ if (value == constants::registration_never())
+ reg_mode = sinks::event_log::never;
+ else if (value == constants::registration_on_demand())
+ reg_mode = sinks::event_log::on_demand;
+ else if (value == constants::registration_forced())
+ reg_mode = sinks::event_log::forced;
+ else
+ {
+ BOOST_LOG_THROW_DESCR(invalid_value,
+ "The registration mode \"" + log::aux::to_narrow(value) + "\" is not supported");
+ }
+ }
+
+ // Construct the backend
+ shared_ptr< backend_t > backend(boost::make_shared< backend_t >((
+ keywords::log_name = log_name,
+ keywords::log_source = source_name,
+ keywords::registration = reg_mode)));
+
+ // For now we use only the default event type mapping. Will add support for configuration later.
+ backend->set_event_type_mapper(sinks::event_log::direct_event_type_mapping< >(log::aux::default_attribute_names::severity()));
+
+ return base_type::init_sink(backend, params);
+ }
+ };
+
+public:
+ //! The function constructs a sink that writes log records to the Windows NT Event Log
+ shared_ptr< sinks::sink > create_sink(settings_section const& params)
+ {
+ return base_type::select_backend_character_type(params, impl());
+ }
+};
+
+#endif // !defined(BOOST_LOG_WITHOUT_EVENT_LOG)
+
+
+//! The supported sinks repository
+template< typename CharT >
+struct sinks_repository :
+ public log::aux::lazy_singleton< sinks_repository< CharT > >
+{
+ typedef log::aux::lazy_singleton< sinks_repository< CharT > > base_type;
+
+#if !defined(BOOST_LOG_BROKEN_FRIEND_TEMPLATE_INSTANTIATIONS)
+ friend class log::aux::lazy_singleton< sinks_repository< CharT > >;
+#else
+ friend class base_type;
+#endif
+
+ typedef CharT char_type;
+ typedef std::basic_string< char_type > string_type;
+ typedef basic_settings_section< char_type > settings_section;
+ typedef boost::log::aux::char_constants< char_type > constants;
+ typedef boost::shared_ptr< sink_factory< char_type > > sink_factory_ptr;
+ typedef std::map< std::string, sink_factory_ptr > sink_factories;
+
+#if !defined(BOOST_LOG_NO_THREADS)
+ //! Synchronization mutex
+ log::aux::light_rw_mutex m_Mutex;
+#endif
+ //! Map of the sink factories
+ sink_factories m_Factories;
+
+ //! The function constructs a sink from the settings
+ shared_ptr< sinks::sink > construct_sink_from_settings(settings_section const& params)
+ {
+ typedef typename settings_section::const_reference param_const_reference;
+ if (param_const_reference dest_node = params["Destination"])
+ {
+ std::string dest = log::aux::to_narrow(dest_node.get().get());
+
+ BOOST_LOG_EXPR_IF_MT(log::aux::shared_lock_guard< log::aux::light_rw_mutex > lock(m_Mutex);)
+ typename sink_factories::const_iterator it = m_Factories.find(dest);
+ if (it != m_Factories.end())
+ {
+ return it->second->create_sink(params);
+ }
+ else
+ {
+ BOOST_LOG_THROW_DESCR(invalid_value, "The sink destination is not supported: " + dest);
+ }
+ }
+ else
+ {
+ BOOST_LOG_THROW_DESCR(missing_value, "The sink destination is not set");
+ }
+ }
+
+ static void init_instance()
+ {
+ sinks_repository& instance = base_type::get_instance();
+ instance.m_Factories["TextFile"] = boost::make_shared< default_text_file_sink_factory< char_type > >();
+ instance.m_Factories["Console"] = boost::make_shared< default_console_sink_factory< char_type > >();
+#ifndef BOOST_LOG_WITHOUT_SYSLOG
+ instance.m_Factories["Syslog"] = boost::make_shared< default_syslog_sink_factory< char_type > >();
+#endif
+#ifndef BOOST_LOG_WITHOUT_DEBUG_OUTPUT
+ instance.m_Factories["Debugger"] = boost::make_shared< default_debugger_sink_factory< char_type > >();
+#endif
+#ifndef BOOST_LOG_WITHOUT_EVENT_LOG
+ instance.m_Factories["SimpleEventLog"] = boost::make_shared< default_simple_event_log_sink_factory< char_type > >();
+#endif
+ }
+
+private:
+ sinks_repository() {}
+};
+
+//! The function applies the settings to the logging core
+template< typename CharT >
+void apply_core_settings(basic_settings_section< CharT > const& params)
+{
+ typedef CharT char_type;
+ typedef std::basic_string< char_type > string_type;
+
+ core_ptr core = boost::log::core::get();
+
+ // Filter
+ if (optional< string_type > filter_param = params["Filter"])
+ core->set_filter(parse_filter(filter_param.get()));
+ else
+ core->reset_filter();
+
+ // DisableLogging
+ if (optional< string_type > disable_logging_param = params["DisableLogging"])
+ core->set_logging_enabled(!param_cast_to_bool("DisableLogging", disable_logging_param.get()));
+ else
+ core->set_logging_enabled(true);
+}
+
+} // namespace
+
+
+//! The function initializes the logging library from a settings container
+template< typename CharT >
+void init_from_settings(basic_settings_section< CharT > const& setts)
+{
+ typedef basic_settings_section< CharT > section;
+ typedef typename section::char_type char_type;
+ typedef typename section::string_type string_type;
+ typedef sinks_repository< char_type > sinks_repo_t;
+
+ // Apply core settings
+ if (section core_params = setts["Core"])
+ apply_core_settings(core_params);
+
+ // Construct and initialize sinks
+ if (section sink_params = setts["Sinks"])
+ {
+ sinks_repo_t& sinks_repo = sinks_repo_t::get();
+ std::vector< shared_ptr< sinks::sink > > new_sinks;
+
+ for (typename section::const_iterator it = sink_params.begin(), end = sink_params.end(); it != end; ++it)
+ {
+ section sink_params = *it;
+
+ // Ignore empty sections as they are most likely individual parameters (which should not be here anyway)
+ if (!sink_params.empty())
+ {
+ new_sinks.push_back(sinks_repo.construct_sink_from_settings(sink_params));
+ }
+ }
+
+ std::for_each(new_sinks.begin(), new_sinks.end(), boost::bind(&core::add_sink, core::get(), _1));
+ }
+}
+
+
+//! The function registers a factory for a sink
+template< typename CharT >
+void register_sink_factory(const char* sink_name, shared_ptr< sink_factory< CharT > > const& factory)
+{
+ sinks_repository< CharT >& repo = sinks_repository< CharT >::get();
+ BOOST_LOG_EXPR_IF_MT(lock_guard< log::aux::light_rw_mutex > lock(repo.m_Mutex);)
+ repo.m_Factories[sink_name] = factory;
+}
+
+#ifdef BOOST_LOG_USE_CHAR
+template BOOST_LOG_SETUP_API void register_sink_factory< char >(const char* sink_name, shared_ptr< sink_factory< char > > const& factory);
+template BOOST_LOG_SETUP_API void init_from_settings< char >(basic_settings_section< char > const& setts);
+#endif
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+template BOOST_LOG_SETUP_API void register_sink_factory< wchar_t >(const char* sink_name, shared_ptr< sink_factory< wchar_t > > const& factory);
+template BOOST_LOG_SETUP_API void init_from_settings< wchar_t >(basic_settings_section< wchar_t > const& setts);
+#endif
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_WITHOUT_SETTINGS_PARSERS

Added: trunk/libs/log/src/init_from_stream.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/init_from_stream.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,47 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 init_from_stream.cpp
+ * \author Andrey Semashev
+ * \date 22.03.2008
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#ifndef BOOST_LOG_WITHOUT_SETTINGS_PARSERS
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/utility/setup/from_settings.hpp>
+#include <boost/log/utility/setup/settings_parser.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+//! The function initializes the logging library from a stream containing logging settings
+template< typename CharT >
+void init_from_stream(std::basic_istream< CharT >& strm)
+{
+ init_from_settings(parse_settings(strm));
+}
+
+#ifdef BOOST_LOG_USE_CHAR
+template BOOST_LOG_SETUP_API void init_from_stream< char >(std::basic_istream< char >& strm);
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+template BOOST_LOG_SETUP_API void init_from_stream< wchar_t >(std::basic_istream< wchar_t >& strm);
+#endif
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_WITHOUT_SETTINGS_PARSERS

Added: trunk/libs/log/src/light_rw_mutex.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/light_rw_mutex.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,210 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 19.06.2010
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+// This first include is to ensure that __MSVCRT_VERSION__ is defined properly
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/light_rw_mutex.hpp>
+
+#if !defined(BOOST_LOG_NO_THREADS)
+
+#if !defined(BOOST_LOG_LWRWMUTEX_USE_PTHREAD) && !defined(BOOST_LOG_LWRWMUTEX_USE_SRWLOCK)
+
+#include <new>
+#include <boost/assert.hpp>
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/log/utility/once_block.hpp>
+
+#include "windows_version.hpp"
+#include <windows.h>
+#include <malloc.h>
+
+#include <boost/log/detail/header.hpp>
+
+#if defined(__MINGW32__) && __MSVCRT_VERSION__ < 0x0700
+// MinGW doesn't declare aligned memory allocation routines for MSVC 6 runtime
+inline void* _aligned_malloc(size_t size, size_t) { return malloc(size); }
+inline void _aligned_free(void* p) { free(p); }
+#endif
+
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+struct mutex_impl { void* p; }; // has the same layout as SRWLOCK and light_rw_mutex::m_Mutex
+
+typedef void (__stdcall *init_fun_t)(mutex_impl*);
+typedef void (__stdcall *destroy_fun_t)(mutex_impl*);
+typedef void (__stdcall *lock_exclusive_fun_t)(mutex_impl*);
+typedef void (__stdcall *lock_shared_fun_t)(mutex_impl*);
+typedef void (__stdcall *unlock_exclusive_fun_t)(mutex_impl*);
+typedef void (__stdcall *unlock_shared_fun_t)(mutex_impl*);
+
+//! A complement stub function for InitializeSRWLock
+void __stdcall DeinitializeSRWLock(mutex_impl*)
+{
+}
+
+// The Boost.Thread-based implementation
+void __stdcall InitializeSharedMutex(mutex_impl* mtx)
+{
+ // To avoid cache line aliasing we do aligned memory allocation here
+ enum
+ {
+ // Cache line size on x86
+ cache_line_size = 64,
+ // Allocation size is the minimum number of cache lines to accommodate shared_mutex
+ size =
+ (
+ sizeof(shared_mutex) / cache_line_size
+ + ((sizeof(shared_mutex) % cache_line_size) != 0)
+ )
+ * cache_line_size
+ };
+ mtx->p = _aligned_malloc(size, cache_line_size);
+ BOOST_ASSERT(mtx->p != NULL);
+ new (mtx->p) shared_mutex();
+}
+
+void __stdcall DeinitializeSharedMutex(mutex_impl* mtx)
+{
+ static_cast< shared_mutex* >(mtx->p)->~shared_mutex();
+ _aligned_free(mtx->p);
+ mtx->p = NULL;
+}
+
+void __stdcall ExclusiveLockSharedMutex(mutex_impl* mtx)
+{
+ static_cast< shared_mutex* >(mtx->p)->lock();
+}
+
+void __stdcall SharedLockSharedMutex(mutex_impl* mtx)
+{
+ static_cast< shared_mutex* >(mtx->p)->lock_shared();
+}
+
+void __stdcall ExclusiveUnlockSharedMutex(mutex_impl* mtx)
+{
+ static_cast< shared_mutex* >(mtx->p)->unlock();
+}
+
+void __stdcall SharedUnlockSharedMutex(mutex_impl* mtx)
+{
+ static_cast< shared_mutex* >(mtx->p)->unlock_shared();
+}
+
+// Pointers to the actual implementation functions
+init_fun_t g_pInitializeLWRWMutex = NULL;
+destroy_fun_t g_pDestroyLWRWMutex = NULL;
+lock_exclusive_fun_t g_pLockExclusiveLWRWMutex = NULL;
+lock_shared_fun_t g_pLockSharedLWRWMutex = NULL;
+unlock_exclusive_fun_t g_pUnlockExclusiveLWRWMutex = NULL;
+unlock_shared_fun_t g_pUnlockSharedLWRWMutex = NULL;
+
+//! The function dynamically initializes the implementation pointers
+void init_light_rw_mutex_impl()
+{
+ HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
+ if (hKernel32)
+ {
+ g_pInitializeLWRWMutex =
+ (init_fun_t)GetProcAddress(hKernel32, "InitializeSRWLock");
+ if (g_pInitializeLWRWMutex)
+ {
+ g_pLockExclusiveLWRWMutex =
+ (lock_exclusive_fun_t)GetProcAddress(hKernel32, "AcquireSRWLockExclusive");
+ if (g_pLockExclusiveLWRWMutex)
+ {
+ g_pUnlockExclusiveLWRWMutex =
+ (unlock_exclusive_fun_t)GetProcAddress(hKernel32, "ReleaseSRWLockExclusive");
+ if (g_pUnlockExclusiveLWRWMutex)
+ {
+ g_pLockSharedLWRWMutex =
+ (lock_shared_fun_t)GetProcAddress(hKernel32, "AcquireSRWLockShared");
+ if (g_pLockSharedLWRWMutex)
+ {
+ g_pUnlockSharedLWRWMutex =
+ (unlock_shared_fun_t)GetProcAddress(hKernel32, "ReleaseSRWLockShared");
+ if (g_pUnlockSharedLWRWMutex)
+ {
+ g_pDestroyLWRWMutex = &DeinitializeSRWLock;
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Current OS doesn't have support for SRWLOCK, use Boost.Thread instead
+ g_pInitializeLWRWMutex = &InitializeSharedMutex;
+ g_pDestroyLWRWMutex = &DeinitializeSharedMutex;
+ g_pLockExclusiveLWRWMutex = &ExclusiveLockSharedMutex;
+ g_pUnlockExclusiveLWRWMutex = &ExclusiveUnlockSharedMutex;
+ g_pLockSharedLWRWMutex = &SharedLockSharedMutex;
+ g_pUnlockSharedLWRWMutex = &SharedUnlockSharedMutex;
+}
+
+} // namespace
+
+BOOST_LOG_API light_rw_mutex::light_rw_mutex()
+{
+ BOOST_LOG_ONCE_BLOCK()
+ {
+ init_light_rw_mutex_impl();
+ }
+ g_pInitializeLWRWMutex((mutex_impl*)&m_Mutex);
+}
+
+BOOST_LOG_API light_rw_mutex::~light_rw_mutex()
+{
+ g_pDestroyLWRWMutex((mutex_impl*)&m_Mutex);
+}
+
+BOOST_LOG_API void light_rw_mutex::lock_shared()
+{
+ g_pLockSharedLWRWMutex((mutex_impl*)&m_Mutex);
+}
+
+BOOST_LOG_API void light_rw_mutex::unlock_shared()
+{
+ g_pUnlockSharedLWRWMutex((mutex_impl*)&m_Mutex);
+}
+
+BOOST_LOG_API void light_rw_mutex::lock()
+{
+ g_pLockExclusiveLWRWMutex((mutex_impl*)&m_Mutex);
+}
+
+BOOST_LOG_API void light_rw_mutex::unlock()
+{
+ g_pUnlockExclusiveLWRWMutex((mutex_impl*)&m_Mutex);
+}
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // !defined(BOOST_LOG_LWRWMUTEX_USE_PTHREAD) && !defined(BOOST_LOG_LWRWMUTEX_USE_SRWLOCK)
+
+#endif // !defined(BOOST_LOG_NO_THREADS)

Added: trunk/libs/log/src/named_scope.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/named_scope.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,316 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 named_scope.cpp
+ * \author Andrey Semashev
+ * \date 24.06.2007
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#include <memory>
+#include <algorithm>
+#include <boost/optional.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/attributes/attribute_value.hpp>
+#include <boost/log/attributes/named_scope.hpp>
+#include <boost/log/utility/type_dispatch/type_dispatcher.hpp>
+#include <boost/log/detail/singleton.hpp>
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/thread/tss.hpp>
+#endif
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace attributes {
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+ //! Actual implementation of the named scope list
+ class writeable_named_scope_list :
+ public named_scope_list
+ {
+ //! Base type
+ typedef named_scope_list base_type;
+
+ public:
+ //! Const reference type
+ typedef base_type::const_reference const_reference;
+
+ public:
+ //! The method pushes the scope to the back of the list
+ BOOST_LOG_FORCEINLINE void push_back(const_reference entry) BOOST_NOEXCEPT
+ {
+ register aux::named_scope_list_node* top = this->m_RootNode._m_pPrev;
+ entry._m_pPrev = top;
+ entry._m_pNext = &this->m_RootNode;
+
+ BOOST_LOG_ASSUME(&entry != 0);
+ this->m_RootNode._m_pPrev = top->_m_pNext =
+ const_cast< aux::named_scope_list_node* >(
+ static_cast< const aux::named_scope_list_node* >(&entry));
+
+ ++this->m_Size;
+ }
+ //! The method removes the top scope entry from the list
+ BOOST_LOG_FORCEINLINE void pop_back() BOOST_NOEXCEPT
+ {
+ register aux::named_scope_list_node* top = this->m_RootNode._m_pPrev;
+ top->_m_pPrev->_m_pNext = top->_m_pNext;
+ top->_m_pNext->_m_pPrev = top->_m_pPrev;
+ --this->m_Size;
+ }
+ };
+
+ //! Named scope attribute value
+ class named_scope_value :
+ public attribute_value::impl
+ {
+ //! Scope names stack
+ typedef named_scope_list scope_stack;
+
+ //! Pointer to the actual scope value
+ scope_stack* m_pValue;
+ //! A thread-independent value
+ optional< scope_stack > m_DetachedValue;
+
+ public:
+ //! Constructor
+ explicit named_scope_value(scope_stack* p) : m_pValue(p) {}
+
+ //! The method dispatches the value to the given object. It returns true if the
+ //! object was capable to consume the real attribute value type and false otherwise.
+ bool dispatch(type_dispatcher& dispatcher)
+ {
+ type_dispatcher::callback< scope_stack > callback =
+ dispatcher.get_callback< scope_stack >();
+ if (callback)
+ {
+ callback(*m_pValue);
+ return true;
+ }
+ else
+ return false;
+ }
+
+ /*!
+ * \return The attribute value type
+ */
+ type_info_wrapper get_type() const { return type_info_wrapper(typeid(scope_stack)); }
+
+ //! 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.
+ intrusive_ptr< attribute_value::impl > detach_from_thread()
+ {
+ if (!m_DetachedValue)
+ {
+ m_DetachedValue = *m_pValue;
+ m_pValue = m_DetachedValue.get_ptr();
+ }
+
+ return this;
+ }
+ };
+
+} // namespace
+
+//! Named scope attribute implementation
+struct BOOST_LOG_VISIBLE named_scope::impl :
+ public attribute::impl,
+ public log::aux::singleton<
+ impl,
+ intrusive_ptr< impl >
+ >
+{
+ //! Singleton base type
+ typedef log::aux::singleton<
+ impl,
+ intrusive_ptr< impl >
+ > singleton_base_type;
+
+ //! Writable scope list type
+ typedef writeable_named_scope_list scope_list;
+
+#if !defined(BOOST_LOG_NO_THREADS)
+ //! Pointer to the thread-specific scope stack
+ thread_specific_ptr< scope_list > pScopes;
+
+#if defined(BOOST_LOG_USE_COMPILER_TLS)
+ //! Cached pointer to the thread-specific scope stack
+ static BOOST_LOG_TLS scope_list* pScopesCache;
+#endif
+
+#else
+ //! Pointer to the scope stack
+ std::auto_ptr< scope_list > pScopes;
+#endif
+
+ //! The method returns current thread scope stack
+ scope_list& get_scope_list()
+ {
+#if defined(BOOST_LOG_USE_COMPILER_TLS)
+ register scope_list* p = pScopesCache;
+#else
+ register scope_list* p = pScopes.get();
+#endif
+ if (!p)
+ {
+ std::auto_ptr< scope_list > pNew(new scope_list());
+ pScopes.reset(pNew.get());
+#if defined(BOOST_LOG_USE_COMPILER_TLS)
+ pScopesCache = p = pNew.release();
+#else
+ p = pNew.release();
+#endif
+ }
+
+ return *p;
+ }
+
+ //! Instance initializer
+ static void init_instance()
+ {
+ singleton_base_type::get_instance().reset(new impl());
+ }
+
+ //! The method returns the actual attribute value. It must not return NULL.
+ attribute_value get_value()
+ {
+ return attribute_value(new named_scope_value(&get_scope_list()));
+ }
+
+private:
+ impl() {}
+};
+
+#if defined(BOOST_LOG_USE_COMPILER_TLS)
+//! Cached pointer to the thread-specific scope stack
+BOOST_LOG_TLS named_scope::implementation::scope_list*
+named_scope::implementation::pScopesCache = NULL;
+#endif // defined(BOOST_LOG_USE_COMPILER_TLS)
+
+
+//! Copy constructor
+BOOST_LOG_API named_scope_list::named_scope_list(named_scope_list const& that) :
+ allocator_type(static_cast< allocator_type const& >(that)),
+ m_Size(that.size()),
+ m_fNeedToDeallocate(!that.empty())
+{
+ if (m_Size > 0)
+ {
+ // Copy the container contents
+ register pointer p = allocator_type::allocate(that.size());
+ register aux::named_scope_list_node* prev = &m_RootNode;
+ for (const_iterator src = that.begin(), end = that.end(); src != end; ++src, ++p)
+ {
+ allocator_type::construct(p, *src); // won't throw
+ p->_m_pPrev = prev;
+ prev->_m_pNext = p;
+ prev = p;
+ }
+ m_RootNode._m_pPrev = prev;
+ prev->_m_pNext = &m_RootNode;
+ }
+}
+
+//! Destructor
+BOOST_LOG_API named_scope_list::~named_scope_list()
+{
+ if (m_fNeedToDeallocate)
+ {
+ iterator it(m_RootNode._m_pNext);
+ iterator end(&m_RootNode);
+ while (it != end)
+ allocator_type::destroy(&*(it++));
+ allocator_type::deallocate(static_cast< pointer >(m_RootNode._m_pNext), m_Size);
+ }
+}
+
+//! Swaps two instances of the container
+BOOST_LOG_API void named_scope_list::swap(named_scope_list& that)
+{
+ using std::swap;
+
+ unsigned int choice =
+ static_cast< unsigned int >(this->empty()) | (static_cast< unsigned int >(that.empty()) << 1);
+ switch (choice)
+ {
+ case 0: // both containers are not empty
+ swap(m_RootNode._m_pNext->_m_pPrev, that.m_RootNode._m_pNext->_m_pPrev);
+ swap(m_RootNode._m_pPrev->_m_pNext, that.m_RootNode._m_pPrev->_m_pNext);
+ swap(m_RootNode, that.m_RootNode);
+ swap(m_Size, that.m_Size);
+ swap(m_fNeedToDeallocate, that.m_fNeedToDeallocate);
+ break;
+
+ case 1: // that is not empty
+ that.m_RootNode._m_pNext->_m_pPrev = that.m_RootNode._m_pPrev->_m_pNext = &m_RootNode;
+ m_RootNode = that.m_RootNode;
+ that.m_RootNode._m_pNext = that.m_RootNode._m_pPrev = &that.m_RootNode;
+ swap(m_Size, that.m_Size);
+ swap(m_fNeedToDeallocate, that.m_fNeedToDeallocate);
+ break;
+
+ case 2: // this is not empty
+ m_RootNode._m_pNext->_m_pPrev = m_RootNode._m_pPrev->_m_pNext = &that.m_RootNode;
+ that.m_RootNode = m_RootNode;
+ m_RootNode._m_pNext = m_RootNode._m_pPrev = &m_RootNode;
+ swap(m_Size, that.m_Size);
+ swap(m_fNeedToDeallocate, that.m_fNeedToDeallocate);
+ break;
+
+ default: // both containers are empty, nothing to do here
+ break;
+ }
+}
+
+//! Constructor
+named_scope::named_scope() :
+ attribute(impl::instance)
+{
+}
+
+//! Constructor for casting support
+named_scope::named_scope(cast_source const& source) :
+ attribute(source.as< impl >())
+{
+}
+
+//! The method pushes the scope to the stack
+void named_scope::push_scope(scope_entry const& entry) BOOST_NOEXCEPT
+{
+ impl::scope_list& s = impl::instance->get_scope_list();
+ s.push_back(entry);
+}
+
+//! The method pops the top scope
+void named_scope::pop_scope() BOOST_NOEXCEPT
+{
+ impl::scope_list& s = impl::instance->get_scope_list();
+ s.pop_back();
+}
+
+//! Returns the current thread's scope stack
+named_scope::value_type const& named_scope::get_scopes()
+{
+ return impl::instance->get_scope_list();
+}
+
+} // namespace attributes
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>

Added: trunk/libs/log/src/named_scope_format_parser.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/named_scope_format_parser.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,245 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 named_scope_format_parser.cpp
+ * \author Andrey Semashev
+ * \date 14.11.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#include <string>
+#include <vector>
+#include <limits>
+#include <algorithm>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/spirit/include/karma_uint.hpp>
+#include <boost/spirit/include/karma_generate.hpp>
+#include <boost/log/attributes/named_scope.hpp>
+#include <boost/log/expressions/formatters/named_scope.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace karma = boost::spirit::karma;
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+namespace aux {
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+template< typename CharT >
+class named_scope_formatter
+{
+ BOOST_COPYABLE_AND_MOVABLE_ALT(named_scope_formatter)
+
+public:
+ typedef void result_type;
+
+ typedef CharT char_type;
+ typedef std::basic_string< char_type > string_type;
+ typedef basic_formatting_ostream< char_type > stream_type;
+ typedef attributes::named_scope::value_type::value_type value_type;
+
+ struct literal
+ {
+ typedef void result_type;
+
+ explicit literal(string_type& lit) { m_literal.swap(lit); }
+
+ result_type operator() (stream_type& strm, value_type const&) const
+ {
+ strm << m_literal;
+ }
+
+ private:
+ string_type m_literal;
+ };
+
+ struct scope_name
+ {
+ typedef void result_type;
+
+ result_type operator() (stream_type& strm, value_type const& value) const
+ {
+ strm << value.scope_name;
+ }
+ };
+
+ struct file_name
+ {
+ typedef void result_type;
+
+ result_type operator() (stream_type& strm, value_type const& value) const
+ {
+ strm << value.file_name;
+ }
+ };
+
+ struct line_number
+ {
+ typedef void result_type;
+
+ result_type operator() (stream_type& strm, value_type const& value) const
+ {
+ strm.flush();
+ typedef typename stream_type::streambuf_type streambuf_type;
+ string_type& str = *static_cast< streambuf_type* >(strm.rdbuf())->storage();
+
+ char_type buf[std::numeric_limits< unsigned int >::digits10 + 2];
+ char_type* p = buf;
+
+ typedef karma::uint_generator< unsigned int, 10 > uint_gen;
+ karma::generate(p, uint_gen(), value.line);
+ str.append(buf, p);
+ }
+ };
+
+private:
+ typedef boost::log::aux::light_function< void (stream_type&, value_type const&) > formatter_type;
+ typedef std::vector< formatter_type > formatters;
+
+private:
+ formatters m_formatters;
+
+public:
+ BOOST_LOG_DEFAULTED_FUNCTION(named_scope_formatter(), {})
+ named_scope_formatter(named_scope_formatter const& that) : m_formatters(that.m_formatters) {}
+ named_scope_formatter(BOOST_RV_REF(named_scope_formatter) that) { m_formatters.swap(that.m_formatters); }
+
+ named_scope_formatter& operator= (named_scope_formatter that)
+ {
+ this->swap(that);
+ return *this;
+ }
+
+ result_type operator() (stream_type& strm, value_type const& value) const
+ {
+ for (typename formatters::const_iterator it = m_formatters.begin(), end = m_formatters.end(); strm.good() && it != end; ++it)
+ {
+ (*it)(strm, value);
+ }
+ }
+
+#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template< typename FunT >
+ void add_formatter(FunT&& fun)
+ {
+ m_formatters.emplace_back(boost::forward< FunT >(fun));
+ }
+#else
+ template< typename FunT >
+ void add_formatter(FunT const& fun)
+ {
+ m_formatters.push_back(formatter_type(fun));
+ }
+#endif
+
+ void swap(named_scope_formatter& that)
+ {
+ m_formatters.swap(that.m_formatters);
+ }
+};
+
+} // namespace
+
+//! Parses the named scope format string and constructs the formatter function
+template< typename CharT >
+boost::log::aux::light_function< void (basic_formatting_ostream< CharT >&, attributes::named_scope::value_type::value_type const&) >
+parse_named_scope_format(const CharT* begin, const CharT* end)
+{
+ typedef CharT char_type;
+ typedef boost::log::aux::light_function< void (basic_formatting_ostream< char_type >&, attributes::named_scope::value_type::value_type const&) > result_type;
+ typedef named_scope_formatter< char_type > formatter_type;
+ formatter_type fmt;
+
+ std::basic_string< char_type > literal;
+
+ while (begin != end)
+ {
+ const char_type* p = std::find(begin, end, static_cast< char_type >('%'));
+ literal.append(begin, p);
+
+ if ((end - p) >= 2)
+ {
+ switch (p[1])
+ {
+ case '%':
+ literal.push_back(static_cast< char_type >('%'));
+ break;
+
+ case 'n':
+ if (!literal.empty())
+ fmt.add_formatter(typename formatter_type::literal(literal));
+ fmt.add_formatter(typename formatter_type::scope_name());
+ break;
+
+ case 'f':
+ if (!literal.empty())
+ fmt.add_formatter(typename formatter_type::literal(literal));
+ fmt.add_formatter(typename formatter_type::file_name());
+ break;
+
+ case 'l':
+ if (!literal.empty())
+ fmt.add_formatter(typename formatter_type::literal(literal));
+ fmt.add_formatter(typename formatter_type::line_number());
+ break;
+
+ default:
+ literal.append(p, p + 2);
+ break;
+ }
+
+ begin = p + 2;
+ }
+ else
+ {
+ if (p != end)
+ literal.push_back(static_cast< char_type >('%')); // a single '%' character at the end of the string
+ begin = end;
+ }
+ }
+
+ if (!literal.empty())
+ fmt.add_formatter(typename formatter_type::literal(literal));
+
+ return result_type(boost::move(fmt));
+}
+
+
+#ifdef BOOST_LOG_USE_CHAR
+
+template 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 // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+
+template 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 // BOOST_LOG_USE_WCHAR_T
+
+} // namespace aux
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>

Added: trunk/libs/log/src/once_block.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/once_block.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,461 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 23.06.2010
+ *
+ * \brief This file is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ *
+ * The code in this file is based on the \c call_once function implementation in Boost.Thread.
+ */
+
+#include <boost/log/utility/once_block.hpp>
+#ifndef BOOST_LOG_NO_THREADS
+
+#include <boost/assert.hpp>
+
+#if defined(BOOST_THREAD_PLATFORM_WIN32)
+
+#include "windows_version.hpp"
+#include <windows.h>
+
+#if defined(BOOST_LOG_USE_WINNT6_API)
+
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+ SRWLOCK g_OnceBlockMutex = SRWLOCK_INIT;
+ CONDITION_VARIABLE g_OnceBlockCond = CONDITION_VARIABLE_INIT;
+
+} // namespace
+
+BOOST_LOG_API bool once_block_sentry::enter_once_block() const
+{
+ AcquireSRWLockExclusive(&g_OnceBlockMutex);
+
+ once_block_flag volatile& flag = m_Flag;
+ while (flag.status != once_block_flag::initialized)
+ {
+ if (flag.status == once_block_flag::uninitialized)
+ {
+ flag.status = once_block_flag::being_initialized;
+ ReleaseSRWLockExclusive(&g_OnceBlockMutex);
+
+ // Invoke the initializer block
+ return false;
+ }
+ else
+ {
+ while (flag.status == once_block_flag::being_initialized)
+ {
+ BOOST_VERIFY(SleepConditionVariableSRW(
+ &g_OnceBlockCond, &g_OnceBlockMutex, INFINITE, 0));
+ }
+ }
+ }
+
+ ReleaseSRWLockExclusive(&g_OnceBlockMutex);
+
+ return true;
+}
+
+BOOST_LOG_API void once_block_sentry::commit()
+{
+ AcquireSRWLockExclusive(&g_OnceBlockMutex);
+
+ // The initializer executed successfully
+ m_Flag.status = once_block_flag::initialized;
+
+ ReleaseSRWLockExclusive(&g_OnceBlockMutex);
+ WakeAllConditionVariable(&g_OnceBlockCond);
+}
+
+BOOST_LOG_API void once_block_sentry::rollback()
+{
+ AcquireSRWLockExclusive(&g_OnceBlockMutex);
+
+ // The initializer failed, marking the flag as if it hasn't run at all
+ m_Flag.status = once_block_flag::uninitialized;
+
+ ReleaseSRWLockExclusive(&g_OnceBlockMutex);
+ WakeAllConditionVariable(&g_OnceBlockCond);
+}
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#else // defined(BOOST_LOG_USE_WINNT6_API)
+
+#include <cstdlib> // atexit
+#include <boost/detail/interlocked.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/condition_variable.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+ struct BOOST_LOG_NO_VTABLE once_block_impl_base
+ {
+ virtual ~once_block_impl_base() {}
+ virtual bool enter_once_block(once_block_flag volatile& flag) = 0;
+ virtual void commit(once_block_flag& flag) = 0;
+ virtual void rollback(once_block_flag& flag) = 0;
+ };
+
+ class once_block_impl_nt6 :
+ public once_block_impl_base
+ {
+ public:
+ struct SRWLOCK { void* p; };
+ struct CONDITION_VARIABLE { void* p; };
+
+ typedef void (__stdcall *InitializeSRWLock_t)(SRWLOCK*);
+ typedef void (__stdcall *AcquireSRWLockExclusive_t)(SRWLOCK*);
+ typedef void (__stdcall *ReleaseSRWLockExclusive_t)(SRWLOCK*);
+ typedef void (__stdcall *InitializeConditionVariable_t)(CONDITION_VARIABLE*);
+ typedef BOOL (__stdcall *SleepConditionVariableSRW_t)(CONDITION_VARIABLE*, SRWLOCK*, DWORD, ULONG);
+ typedef void (__stdcall *WakeAllConditionVariable_t)(CONDITION_VARIABLE*);
+
+ private:
+ SRWLOCK m_Mutex;
+ CONDITION_VARIABLE m_Cond;
+
+ AcquireSRWLockExclusive_t m_pAcquireSRWLockExclusive;
+ ReleaseSRWLockExclusive_t m_pReleaseSRWLockExclusive;
+ SleepConditionVariableSRW_t m_pSleepConditionVariableSRW;
+ WakeAllConditionVariable_t m_pWakeAllConditionVariable;
+
+ public:
+ once_block_impl_nt6(
+ InitializeSRWLock_t pInitializeSRWLock,
+ AcquireSRWLockExclusive_t pAcquireSRWLockExclusive,
+ ReleaseSRWLockExclusive_t pReleaseSRWLockExclusive,
+ InitializeConditionVariable_t pInitializeConditionVariable,
+ SleepConditionVariableSRW_t pSleepConditionVariableSRW,
+ WakeAllConditionVariable_t pWakeAllConditionVariable
+ ) :
+ m_pAcquireSRWLockExclusive(pAcquireSRWLockExclusive),
+ m_pReleaseSRWLockExclusive(pReleaseSRWLockExclusive),
+ m_pSleepConditionVariableSRW(pSleepConditionVariableSRW),
+ m_pWakeAllConditionVariable(pWakeAllConditionVariable)
+ {
+ pInitializeSRWLock(&m_Mutex);
+ pInitializeConditionVariable(&m_Cond);
+ }
+
+ bool enter_once_block(once_block_flag volatile& flag)
+ {
+ m_pAcquireSRWLockExclusive(&m_Mutex);
+
+ while (flag.status != once_block_flag::initialized)
+ {
+ if (flag.status == once_block_flag::uninitialized)
+ {
+ flag.status = once_block_flag::being_initialized;
+ m_pReleaseSRWLockExclusive(&m_Mutex);
+
+ // Invoke the initializer block
+ return false;
+ }
+ else
+ {
+ while (flag.status == once_block_flag::being_initialized)
+ {
+ BOOST_VERIFY(m_pSleepConditionVariableSRW(
+ &m_Cond, &m_Mutex, INFINITE, 0));
+ }
+ }
+ }
+
+ m_pReleaseSRWLockExclusive(&m_Mutex);
+
+ return true;
+ }
+
+ void commit(once_block_flag& flag)
+ {
+ m_pAcquireSRWLockExclusive(&m_Mutex);
+
+ // The initializer executed successfully
+ flag.status = once_block_flag::initialized;
+
+ m_pReleaseSRWLockExclusive(&m_Mutex);
+ m_pWakeAllConditionVariable(&m_Cond);
+ }
+
+ void rollback(once_block_flag& flag)
+ {
+ m_pAcquireSRWLockExclusive(&m_Mutex);
+
+ // The initializer failed, marking the flag as if it hasn't run at all
+ flag.status = once_block_flag::uninitialized;
+
+ m_pReleaseSRWLockExclusive(&m_Mutex);
+ m_pWakeAllConditionVariable(&m_Cond);
+ }
+ };
+
+ class once_block_impl_nt5 :
+ public once_block_impl_base
+ {
+ private:
+ mutex m_Mutex;
+ condition_variable m_Cond;
+
+ public:
+ bool enter_once_block(once_block_flag volatile& flag)
+ {
+ unique_lock< mutex > lock(m_Mutex);
+
+ while (flag.status != once_block_flag::initialized)
+ {
+ if (flag.status == once_block_flag::uninitialized)
+ {
+ flag.status = once_block_flag::being_initialized;
+
+ // Invoke the initializer block
+ return false;
+ }
+ else
+ {
+ while (flag.status == once_block_flag::being_initialized)
+ {
+ m_Cond.wait(lock);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ void commit(once_block_flag& flag)
+ {
+ {
+ lock_guard< mutex > _(m_Mutex);
+ flag.status = once_block_flag::initialized;
+ }
+ m_Cond.notify_all();
+ }
+
+ void rollback(once_block_flag& flag)
+ {
+ {
+ lock_guard< mutex > _(m_Mutex);
+ flag.status = once_block_flag::uninitialized;
+ }
+ m_Cond.notify_all();
+ }
+ };
+
+ once_block_impl_base* create_once_block_impl()
+ {
+ HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
+ if (hKernel32)
+ {
+ once_block_impl_nt6::InitializeSRWLock_t pInitializeSRWLock =
+ (once_block_impl_nt6::InitializeSRWLock_t)GetProcAddress(hKernel32, "InitializeSRWLock");
+ if (pInitializeSRWLock)
+ {
+ once_block_impl_nt6::AcquireSRWLockExclusive_t pAcquireSRWLockExclusive =
+ (once_block_impl_nt6::AcquireSRWLockExclusive_t)GetProcAddress(hKernel32, "AcquireSRWLockExclusive");
+ if (pAcquireSRWLockExclusive)
+ {
+ once_block_impl_nt6::ReleaseSRWLockExclusive_t pReleaseSRWLockExclusive =
+ (once_block_impl_nt6::ReleaseSRWLockExclusive_t)GetProcAddress(hKernel32, "ReleaseSRWLockExclusive");
+ if (pReleaseSRWLockExclusive)
+ {
+ once_block_impl_nt6::InitializeConditionVariable_t pInitializeConditionVariable =
+ (once_block_impl_nt6::InitializeConditionVariable_t)GetProcAddress(hKernel32, "InitializeConditionVariable");
+ if (pInitializeConditionVariable)
+ {
+ once_block_impl_nt6::SleepConditionVariableSRW_t pSleepConditionVariableSRW =
+ (once_block_impl_nt6::SleepConditionVariableSRW_t)GetProcAddress(hKernel32, "SleepConditionVariableSRW");
+ if (pSleepConditionVariableSRW)
+ {
+ once_block_impl_nt6::WakeAllConditionVariable_t pWakeAllConditionVariable =
+ (once_block_impl_nt6::WakeAllConditionVariable_t)GetProcAddress(hKernel32, "WakeAllConditionVariable");
+ if (pWakeAllConditionVariable)
+ {
+ return new once_block_impl_nt6(
+ pInitializeSRWLock,
+ pAcquireSRWLockExclusive,
+ pReleaseSRWLockExclusive,
+ pInitializeConditionVariable,
+ pSleepConditionVariableSRW,
+ pWakeAllConditionVariable);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return new once_block_impl_nt5();
+ }
+
+ once_block_impl_base* g_pOnceBlockImpl = NULL;
+
+ void destroy_once_block_impl()
+ {
+ once_block_impl_base* impl = (once_block_impl_base*)
+ BOOST_INTERLOCKED_EXCHANGE_POINTER((void**)&g_pOnceBlockImpl, NULL);
+ delete impl;
+ }
+
+ once_block_impl_base* get_once_block_impl()
+ {
+ once_block_impl_base* impl = g_pOnceBlockImpl;
+ if (!impl)
+ {
+ once_block_impl_base* new_impl = create_once_block_impl();
+ impl = (once_block_impl_base*)
+ BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER((void**)&g_pOnceBlockImpl, (void*)new_impl, NULL);
+ if (impl)
+ {
+ delete new_impl;
+ }
+ else
+ {
+ std::atexit(&destroy_once_block_impl);
+ return new_impl;
+ }
+ }
+
+ return impl;
+ }
+
+} // namespace
+
+BOOST_LOG_API bool once_block_sentry::enter_once_block() const
+{
+ return get_once_block_impl()->enter_once_block(m_Flag);
+}
+
+BOOST_LOG_API void once_block_sentry::commit()
+{
+ get_once_block_impl()->commit(m_Flag);
+}
+
+BOOST_LOG_API void once_block_sentry::rollback()
+{
+ get_once_block_impl()->rollback(m_Flag);
+}
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // defined(BOOST_LOG_USE_WINNT6_API)
+
+#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
+
+#include <pthread.h>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+static pthread_mutex_t g_OnceBlockMutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t g_OnceBlockCond = PTHREAD_COND_INITIALIZER;
+
+} // namespace
+
+BOOST_LOG_API bool once_block_sentry::enter_once_block() const
+{
+ BOOST_VERIFY(!pthread_mutex_lock(&g_OnceBlockMutex));
+
+ once_block_flag volatile& flag = m_Flag;
+ while (flag.status != once_block_flag::initialized)
+ {
+ if (flag.status == once_block_flag::uninitialized)
+ {
+ flag.status = once_block_flag::being_initialized;
+ BOOST_VERIFY(!pthread_mutex_unlock(&g_OnceBlockMutex));
+
+ // Invoke the initializer block
+ return false;
+ }
+ else
+ {
+ while (flag.status == once_block_flag::being_initialized)
+ {
+ BOOST_VERIFY(!pthread_cond_wait(&g_OnceBlockCond, &g_OnceBlockMutex));
+ }
+ }
+ }
+
+ BOOST_VERIFY(!pthread_mutex_unlock(&g_OnceBlockMutex));
+
+ return true;
+}
+
+BOOST_LOG_API void once_block_sentry::commit()
+{
+ BOOST_VERIFY(!pthread_mutex_lock(&g_OnceBlockMutex));
+
+ // The initializer executed successfully
+ m_Flag.status = once_block_flag::initialized;
+
+ BOOST_VERIFY(!pthread_mutex_unlock(&g_OnceBlockMutex));
+ BOOST_VERIFY(!pthread_cond_broadcast(&g_OnceBlockCond));
+}
+
+BOOST_LOG_API void once_block_sentry::rollback()
+{
+ BOOST_VERIFY(!pthread_mutex_lock(&g_OnceBlockMutex));
+
+ // The initializer failed, marking the flag as if it hasn't run at all
+ m_Flag.status = once_block_flag::uninitialized;
+
+ BOOST_VERIFY(!pthread_mutex_unlock(&g_OnceBlockMutex));
+ BOOST_VERIFY(!pthread_cond_broadcast(&g_OnceBlockCond));
+}
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#else
+#error Boost.Log: unsupported threading API
+#endif
+
+#endif // BOOST_LOG_NO_THREADS

Added: trunk/libs/log/src/parser_utils.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/parser_utils.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,247 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 parser_utils.cpp
+ * \author Andrey Semashev
+ * \date 31.03.2008
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#ifndef BOOST_LOG_WITHOUT_SETTINGS_PARSERS
+
+#include <iterator>
+#include <algorithm>
+#include "parser_utils.hpp"
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+#ifdef BOOST_LOG_USE_CHAR
+
+#ifndef BOOST_LOG_BROKEN_STATIC_CONSTANTS_LINKAGE
+
+const char_constants< char >::char_type char_constants< char >::char_comment;
+const char_constants< char >::char_type char_constants< char >::char_comma;
+const char_constants< char >::char_type char_constants< char >::char_quote;
+const char_constants< char >::char_type char_constants< char >::char_percent;
+const char_constants< char >::char_type char_constants< char >::char_exclamation;
+const char_constants< char >::char_type char_constants< char >::char_and;
+const char_constants< char >::char_type char_constants< char >::char_or;
+const char_constants< char >::char_type char_constants< char >::char_equal;
+const char_constants< char >::char_type char_constants< char >::char_greater;
+const char_constants< char >::char_type char_constants< char >::char_less;
+const char_constants< char >::char_type char_constants< char >::char_underline;
+const char_constants< char >::char_type char_constants< char >::char_backslash;
+const char_constants< char >::char_type char_constants< char >::char_section_bracket_left;
+const char_constants< char >::char_type char_constants< char >::char_section_bracket_right;
+const char_constants< char >::char_type char_constants< char >::char_paren_bracket_left;
+const char_constants< char >::char_type char_constants< char >::char_paren_bracket_right;
+
+#endif // BOOST_LOG_BROKEN_STATIC_CONSTANTS_LINKAGE
+
+void char_constants< char >::translate_escape_sequences(std::basic_string< char_type >& str)
+{
+ using namespace std; // to make sure we can use C functions unqualified
+
+ std::basic_string< char_type >::iterator it = str.begin();
+ while (it != str.end())
+ {
+ it = std::find(it, str.end(), '\\');
+ if (std::distance(it, str.end()) >= 2)
+ {
+ it = str.erase(it);
+ switch (*it)
+ {
+ case 'n':
+ *it = '\n'; break;
+ case 'r':
+ *it = '\r'; break;
+ case 'a':
+ *it = '\a'; break;
+ case '\\':
+ ++it; break;
+ case 't':
+ *it = '\t'; break;
+ case 'b':
+ *it = '\b'; break;
+ case 'x':
+ {
+ std::basic_string< char_type >::iterator b = it;
+ if (std::distance(++b, str.end()) >= 2)
+ {
+ char_type c1 = *b++, c2 = *b++;
+ if (isxdigit(c1) && isxdigit(c2))
+ {
+ *it++ = char_type((to_number(c1) << 4) | to_number(c2));
+ it = str.erase(it, b);
+ }
+ }
+ break;
+ }
+ default:
+ {
+ if (*it >= '0' && *it <= '7')
+ {
+ std::basic_string< char_type >::iterator b = it;
+ int c = (*b++) - '0';
+ if (*b >= '0' && *b <= '7')
+ c = c * 8 + (*b++) - '0';
+ if (*b >= '0' && *b <= '7')
+ c = c * 8 + (*b++) - '0';
+
+ *it++ = char_type(c);
+ it = str.erase(it, b);
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
+#endif // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+
+#ifndef BOOST_LOG_BROKEN_STATIC_CONSTANTS_LINKAGE
+
+const char_constants< wchar_t >::char_type char_constants< wchar_t >::char_comment;
+const char_constants< wchar_t >::char_type char_constants< wchar_t >::char_comma;
+const char_constants< wchar_t >::char_type char_constants< wchar_t >::char_quote;
+const char_constants< wchar_t >::char_type char_constants< wchar_t >::char_percent;
+const char_constants< wchar_t >::char_type char_constants< wchar_t >::char_exclamation;
+const char_constants< wchar_t >::char_type char_constants< wchar_t >::char_and;
+const char_constants< wchar_t >::char_type char_constants< wchar_t >::char_or;
+const char_constants< wchar_t >::char_type char_constants< wchar_t >::char_equal;
+const char_constants< wchar_t >::char_type char_constants< wchar_t >::char_greater;
+const char_constants< wchar_t >::char_type char_constants< wchar_t >::char_less;
+const char_constants< wchar_t >::char_type char_constants< wchar_t >::char_underline;
+const char_constants< wchar_t >::char_type char_constants< wchar_t >::char_backslash;
+const char_constants< wchar_t >::char_type char_constants< wchar_t >::char_section_bracket_left;
+const char_constants< wchar_t >::char_type char_constants< wchar_t >::char_section_bracket_right;
+const char_constants< wchar_t >::char_type char_constants< wchar_t >::char_paren_bracket_left;
+const char_constants< wchar_t >::char_type char_constants< wchar_t >::char_paren_bracket_right;
+
+#endif // BOOST_LOG_BROKEN_STATIC_CONSTANTS_LINKAGE
+
+void char_constants< wchar_t >::translate_escape_sequences(std::basic_string< char_type >& str)
+{
+ std::basic_string< char_type >::iterator it = str.begin();
+ while (it != str.end())
+ {
+ it = std::find(it, str.end(), L'\\');
+ if (std::distance(it, str.end()) >= 2)
+ {
+ it = str.erase(it);
+ switch (*it)
+ {
+ case L'n':
+ *it = L'\n'; break;
+ case L'r':
+ *it = L'\r'; break;
+ case L'a':
+ *it = L'\a'; break;
+ case L'\\':
+ ++it; break;
+ case L't':
+ *it = L'\t'; break;
+ case L'b':
+ *it = L'\b'; break;
+ case L'x':
+ {
+ std::basic_string< char_type >::iterator b = it;
+ if (std::distance(++b, str.end()) >= 2)
+ {
+ char_type c1 = *b++, c2 = *b++;
+ if (iswxdigit(c1) && iswxdigit(c2))
+ {
+ *it++ = char_type((to_number(c1) << 4) | to_number(c2));
+ it = str.erase(it, b);
+ }
+ }
+ break;
+ }
+ case L'u':
+ {
+ std::basic_string< char_type >::iterator b = it;
+ if (std::distance(++b, str.end()) >= 4)
+ {
+ char_type c1 = *b++, c2 = *b++, c3 = *b++, c4 = *b++;
+ if (iswxdigit(c1) && iswxdigit(c2) && iswxdigit(c3) && iswxdigit(c4))
+ {
+ *it++ = char_type(
+ (to_number(c1) << 12) |
+ (to_number(c2) << 8) |
+ (to_number(c3) << 4) |
+ to_number(c4));
+ it = str.erase(it, b);
+ }
+ }
+ break;
+ }
+ case L'U':
+ {
+ std::basic_string< char_type >::iterator b = it;
+ if (std::distance(++b, str.end()) >= 8)
+ {
+ char_type c1 = *b++, c2 = *b++, c3 = *b++, c4 = *b++;
+ char_type c5 = *b++, c6 = *b++, c7 = *b++, c8 = *b++;
+ if (iswxdigit(c1) && iswxdigit(c2) && iswxdigit(c3) && iswxdigit(c4) &&
+ iswxdigit(c5) && iswxdigit(c6) && iswxdigit(c7) && iswxdigit(c8))
+ {
+ *it++ = char_type(
+ (to_number(c1) << 28) |
+ (to_number(c2) << 24) |
+ (to_number(c3) << 20) |
+ (to_number(c4) << 16) |
+ (to_number(c5) << 12) |
+ (to_number(c6) << 8) |
+ (to_number(c7) << 4) |
+ to_number(c8));
+ it = str.erase(it, b);
+ }
+ }
+ break;
+ }
+ default:
+ {
+ if (*it >= L'0' && *it <= L'7')
+ {
+ std::basic_string< char_type >::iterator b = it;
+ int c = (*b++) - L'0';
+ if (*b >= L'0' && *b <= L'7')
+ c = c * 8 + (*b++) - L'0';
+ if (*b >= L'0' && *b <= L'7')
+ c = c * 8 + (*b++) - L'0';
+
+ *it++ = char_type(c);
+ it = str.erase(it, b);
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
+#endif // BOOST_LOG_USE_WCHAR_T
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_WITHOUT_SETTINGS_PARSERS

Added: trunk/libs/log/src/parser_utils.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/parser_utils.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,282 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 parser_utils.hpp
+ * \author Andrey Semashev
+ * \date 31.03.2008
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#ifndef BOOST_LOG_PARSER_UTILS_HPP_INCLUDED_
+#define BOOST_LOG_PARSER_UTILS_HPP_INCLUDED_
+
+#include <string>
+#include <iostream>
+#include <cctype>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! Some constants and algorithms needed for parsing
+template< typename > struct char_constants;
+
+#ifdef BOOST_LOG_USE_CHAR
+template< >
+struct char_constants< char >
+{
+ typedef char char_type;
+ static const char_type char_comment = '#';
+ static const char_type char_comma = ',';
+ static const char_type char_quote = '"';
+ static const char_type char_percent = '%';
+ static const char_type char_exclamation = '!';
+ static const char_type char_and = '&';
+ static const char_type char_or = '|';
+ static const char_type char_equal = '=';
+ static const char_type char_greater = '>';
+ static const char_type char_less = '<';
+ static const char_type char_underline = '_';
+ static const char_type char_backslash = '\\';
+ static const char_type char_section_bracket_left = '[';
+ static const char_type char_section_bracket_right = ']';
+ static const char_type char_paren_bracket_left = '(';
+ static const char_type char_paren_bracket_right = ')';
+
+ static const char_type* not_keyword() { return "not"; }
+ static const char_type* and_keyword() { return "and"; }
+ static const char_type* or_keyword() { return "or"; }
+ static const char_type* equal_keyword() { return "="; }
+ static const char_type* greater_keyword() { return ">"; }
+ static const char_type* less_keyword() { return "<"; }
+ static const char_type* not_equal_keyword() { return "!="; }
+ static const char_type* greater_or_equal_keyword() { return ">="; }
+ static const char_type* less_or_equal_keyword() { return "<="; }
+ static const char_type* begins_with_keyword() { return "begins_with"; }
+ static const char_type* ends_with_keyword() { return "ends_with"; }
+ static const char_type* contains_keyword() { return "contains"; }
+ static const char_type* matches_keyword() { return "matches"; }
+
+ static const char_type* message_text_keyword() { return "_"; }
+
+ static const char_type* true_keyword() { return "true"; }
+ static const char_type* false_keyword() { return "false"; }
+
+ static const char_type* default_level_attribute_name() { return "Severity"; }
+
+ static const char_type* core_section_name() { return "Core"; }
+ static const char_type* sink_section_name_prefix() { return "Sink:"; }
+
+ static const char_type* core_disable_logging_param_name() { return "DisableLogging"; }
+ static const char_type* filter_param_name() { return "Filter"; }
+
+ static const char_type* sink_destination_param_name() { return "Destination"; }
+ static const char_type* file_name_param_name() { return "FileName"; }
+ static const char_type* rotation_size_param_name() { return "RotationSize"; }
+ static const char_type* rotation_interval_param_name() { return "RotationInterval"; }
+ static const char_type* rotation_time_point_param_name() { return "RotationTimePoint"; }
+ static const char_type* append_param_name() { return "Append"; }
+ static const char_type* auto_flush_param_name() { return "AutoFlush"; }
+ static const char_type* asynchronous_param_name() { return "Asynchronous"; }
+ static const char_type* format_param_name() { return "Format"; }
+ static const char_type* provider_id_param_name() { return "ProviderID"; }
+ static const char_type* log_name_param_name() { return "LogName"; }
+ static const char_type* source_name_param_name() { return "LogSource"; }
+ static const char_type* registration_param_name() { return "Registration"; }
+ static const char_type* local_address_param_name() { return "LocalAddress"; }
+ static const char_type* target_address_param_name() { return "TargetAddress"; }
+ static const char_type* target_param_name() { return "Target"; }
+ static const char_type* max_size_param_name() { return "MaxSize"; }
+ static const char_type* min_free_space_param_name() { return "MinFreeSpace"; }
+ static const char_type* scan_for_files_param_name() { return "ScanForFiles"; }
+
+ static const char_type* scan_method_all() { return "All"; }
+ static const char_type* scan_method_matching() { return "Matching"; }
+
+ static const char_type* registration_never() { return "Never"; }
+ static const char_type* registration_on_demand() { return "OnDemand"; }
+ static const char_type* registration_forced() { return "Forced"; }
+
+ static const char_type* text_file_destination() { return "TextFile"; }
+ static const char_type* console_destination() { return "Console"; }
+ static const char_type* syslog_destination() { return "Syslog"; }
+ static const char_type* simple_event_log_destination() { return "SimpleEventLog"; }
+ static const char_type* debugger_destination() { return "Debugger"; }
+
+ static const char_type* monday_keyword() { return "Monday"; }
+ static const char_type* short_monday_keyword() { return "Mon"; }
+ static const char_type* tuesday_keyword() { return "Tuesday"; }
+ static const char_type* short_tuesday_keyword() { return "Tue"; }
+ static const char_type* wednesday_keyword() { return "Wednesday"; }
+ static const char_type* short_wednesday_keyword() { return "Wed"; }
+ static const char_type* thursday_keyword() { return "Thursday"; }
+ static const char_type* short_thursday_keyword() { return "Thu"; }
+ static const char_type* friday_keyword() { return "Friday"; }
+ static const char_type* short_friday_keyword() { return "Fri"; }
+ static const char_type* saturday_keyword() { return "Saturday"; }
+ static const char_type* short_saturday_keyword() { return "Sat"; }
+ static const char_type* sunday_keyword() { return "Sunday"; }
+ static const char_type* short_sunday_keyword() { return "Sun"; }
+
+ static std::ostream& get_console_log_stream() { return std::clog; }
+
+ static int to_number(char_type c)
+ {
+ using namespace std; // to make sure we can use C functions unqualified
+ int n = 0;
+ if (isdigit(c))
+ n = c - '0';
+ else if (c >= 'a' && c <= 'f')
+ n = c - 'a' + 10;
+ else if (c >= 'A' && c <= 'F')
+ n = c - 'A' + 10;
+ return n;
+ }
+
+ static void translate_escape_sequences(std::basic_string< char_type >& str);
+};
+#endif
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+template< >
+struct char_constants< wchar_t >
+{
+ typedef wchar_t char_type;
+ static const char_type char_comment = L'#';
+ static const char_type char_comma = L',';
+ static const char_type char_quote = L'"';
+ static const char_type char_percent = L'%';
+ static const char_type char_exclamation = L'!';
+ static const char_type char_and = L'&';
+ static const char_type char_or = L'|';
+ static const char_type char_equal = L'=';
+ static const char_type char_greater = L'>';
+ static const char_type char_less = L'<';
+ static const char_type char_underline = L'_';
+ static const char_type char_backslash = L'\\';
+ static const char_type char_section_bracket_left = L'[';
+ static const char_type char_section_bracket_right = L']';
+ static const char_type char_paren_bracket_left = L'(';
+ static const char_type char_paren_bracket_right = L')';
+
+ static const char_type* not_keyword() { return L"not"; }
+ static const char_type* and_keyword() { return L"and"; }
+ static const char_type* or_keyword() { return L"or"; }
+ static const char_type* equal_keyword() { return L"="; }
+ static const char_type* greater_keyword() { return L">"; }
+ static const char_type* less_keyword() { return L"<"; }
+ static const char_type* not_equal_keyword() { return L"!="; }
+ static const char_type* greater_or_equal_keyword() { return L">="; }
+ static const char_type* less_or_equal_keyword() { return L"<="; }
+ static const char_type* begins_with_keyword() { return L"begins_with"; }
+ static const char_type* ends_with_keyword() { return L"ends_with"; }
+ static const char_type* contains_keyword() { return L"contains"; }
+ static const char_type* matches_keyword() { return L"matches"; }
+
+ static const char_type* message_text_keyword() { return L"_"; }
+
+ static const char_type* true_keyword() { return L"true"; }
+ static const char_type* false_keyword() { return L"false"; }
+
+ static const char_type* default_level_attribute_name() { return L"Severity"; }
+
+ static const char_type* core_section_name() { return L"Core"; }
+ static const char_type* sink_section_name_prefix() { return L"Sink:"; }
+
+ static const char_type* core_disable_logging_param_name() { return L"DisableLogging"; }
+ static const char_type* filter_param_name() { return L"Filter"; }
+
+ static const char_type* sink_destination_param_name() { return L"Destination"; }
+ static const char_type* file_name_param_name() { return L"FileName"; }
+ static const char_type* rotation_size_param_name() { return L"RotationSize"; }
+ static const char_type* rotation_interval_param_name() { return L"RotationInterval"; }
+ static const char_type* rotation_time_point_param_name() { return L"RotationTimePoint"; }
+ static const char_type* append_param_name() { return L"Append"; }
+ static const char_type* auto_flush_param_name() { return L"AutoFlush"; }
+ static const char_type* asynchronous_param_name() { return L"Asynchronous"; }
+ static const char_type* format_param_name() { return L"Format"; }
+ static const char_type* provider_id_param_name() { return L"ProviderID"; }
+ static const char_type* log_name_param_name() { return L"LogName"; }
+ static const char_type* source_name_param_name() { return L"LogSource"; }
+ static const char_type* registration_param_name() { return L"Registration"; }
+ static const char_type* local_address_param_name() { return L"LocalAddress"; }
+ static const char_type* target_address_param_name() { return L"TargetAddress"; }
+ static const char_type* target_param_name() { return L"Target"; }
+ static const char_type* max_size_param_name() { return L"MaxSize"; }
+ static const char_type* min_free_space_param_name() { return L"MinFreeSpace"; }
+ static const char_type* scan_for_files_param_name() { return L"ScanForFiles"; }
+
+ static const char_type* scan_method_all() { return L"All"; }
+ static const char_type* scan_method_matching() { return L"Matching"; }
+
+ static const char_type* registration_never() { return L"Never"; }
+ static const char_type* registration_on_demand() { return L"OnDemand"; }
+ static const char_type* registration_forced() { return L"Forced"; }
+
+ static const char_type* text_file_destination() { return L"TextFile"; }
+ static const char_type* console_destination() { return L"Console"; }
+ static const char_type* syslog_destination() { return L"Syslog"; }
+ static const char_type* simple_event_log_destination() { return L"SimpleEventLog"; }
+ static const char_type* debugger_destination() { return L"Debugger"; }
+
+ static const char_type* monday_keyword() { return L"Monday"; }
+ static const char_type* short_monday_keyword() { return L"Mon"; }
+ static const char_type* tuesday_keyword() { return L"Tuesday"; }
+ static const char_type* short_tuesday_keyword() { return L"Tue"; }
+ static const char_type* wednesday_keyword() { return L"Wednesday"; }
+ static const char_type* short_wednesday_keyword() { return L"Wed"; }
+ static const char_type* thursday_keyword() { return L"Thursday"; }
+ static const char_type* short_thursday_keyword() { return L"Thu"; }
+ static const char_type* friday_keyword() { return L"Friday"; }
+ static const char_type* short_friday_keyword() { return L"Fri"; }
+ static const char_type* saturday_keyword() { return L"Saturday"; }
+ static const char_type* short_saturday_keyword() { return L"Sat"; }
+ static const char_type* sunday_keyword() { return L"Sunday"; }
+ static const char_type* short_sunday_keyword() { return L"Sun"; }
+
+ static std::wostream& get_console_log_stream() { return std::wclog; }
+
+ static int to_number(char_type c)
+ {
+ int n = 0;
+ if (c >= L'0' && c <= L'9')
+ n = c - L'0';
+ else if (c >= L'a' && c <= L'f')
+ n = c - L'a' + 10;
+ else if (c >= L'A' && c <= L'F')
+ n = c - L'A' + 10;
+ return n;
+ }
+
+ static bool iswxdigit(char_type c)
+ {
+ return (c >= L'0' && c <= L'9') || (c >= L'a' && c <= L'f') || (c >= L'A' && c <= L'F');
+ }
+
+ static void translate_escape_sequences(std::basic_string< char_type >& str);
+};
+#endif
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_PARSER_UTILS_HPP_INCLUDED_

Added: trunk/libs/log/src/process_id.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/process_id.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,126 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \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/libs/log/doc/log.html.
+ */
+
+#include <iostream>
+#include <boost/integer.hpp>
+#include <boost/io/ios_state.hpp>
+#include <boost/log/detail/process_id.hpp>
+#include <boost/log/detail/header.hpp>
+
+#if defined(BOOST_WINDOWS)
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "windows_version.hpp"
+#include <windows.h>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+enum { pid_size = sizeof(GetCurrentProcessId()) };
+
+namespace this_process {
+
+ //! The function returns current process identifier
+ BOOST_LOG_API process::id get_id()
+ {
+ return process::id(GetCurrentProcessId());
+ }
+
+} // namespace this_process
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#else // defined(BOOST_WINDOWS)
+
+#include <unistd.h>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+namespace this_process {
+
+ //! The function returns current process identifier
+ BOOST_LOG_API process::id get_id()
+ {
+ // According to POSIX, pid_t should always be an integer type:
+ // http://pubs.opengroup.org/onlinepubs/009695399/basedefs/sys/types.h.html
+ return process::id(getpid());
+ }
+
+} // namespace this_process
+
+enum { pid_size = sizeof(pid_t) };
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // defined(BOOST_WINDOWS)
+
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+template< typename CharT, typename TraitsT >
+std::basic_ostream< CharT, TraitsT >&
+operator<< (std::basic_ostream< CharT, TraitsT >& strm, process::id const& pid)
+{
+ if (strm.good())
+ {
+ io::ios_flags_saver flags_saver(strm, std::ios_base::hex | std::ios_base::showbase);
+ // The width is set calculated to accomodate pid in hex + "0x" prefix
+ io::ios_width_saver width_saver(strm, static_cast< std::streamsize >(pid_size * 2 + 2));
+ io::basic_ios_fill_saver< CharT, TraitsT > fill_saver(strm, static_cast< CharT >('0'));
+ strm << static_cast< uint_t< pid_size * 8 >::least >(pid.native_id());
+ }
+
+ return strm;
+}
+
+#if defined(BOOST_LOG_USE_CHAR)
+template BOOST_LOG_API
+std::basic_ostream< char, std::char_traits< char > >&
+operator<< (std::basic_ostream< char, std::char_traits< char > >& strm, process::id const& pid);
+#endif // defined(BOOST_LOG_USE_CHAR)
+
+#if defined(BOOST_LOG_USE_WCHAR_T)
+template BOOST_LOG_API
+std::basic_ostream< wchar_t, std::char_traits< wchar_t > >&
+operator<< (std::basic_ostream< wchar_t, std::char_traits< wchar_t > >& strm, process::id const& pid);
+#endif // defined(BOOST_LOG_USE_WCHAR_T)
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>

Added: trunk/libs/log/src/process_name.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/process_name.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,189 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_name.cpp
+ * \author Andrey Semashev
+ * \date 29.07.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ *
+ * The code in this file is based on information on this page:
+ *
+ * http://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe
+ */
+
+#include <climits> // PATH_MAX
+#include <boost/log/attributes/current_process_name.hpp>
+#include <boost/filesystem/path.hpp>
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+#if defined(BOOST_WINDOWS)
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "windows_version.hpp"
+#include <windows.h>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! The function returns the current process name
+BOOST_LOG_API std::string get_process_name()
+{
+ std::wstring buf;
+ buf.resize(PATH_MAX);
+ do
+ {
+ unsigned int len = GetModuleFileNameW(NULL, &buf[0], static_cast< unsigned int >(buf.size()));
+ if (len < buf.size())
+ {
+ buf.resize(len);
+ break;
+ }
+
+ buf.resize(buf.size() * 2);
+ }
+ while (buf.size() < 65536);
+
+ return filesystem::path(buf).filename().string();
+}
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
+
+#include <cstring>
+#include <mach-o/dyld.h>
+#include <boost/cstdint.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! The function returns the current process name
+BOOST_LOG_API std::string get_process_name()
+{
+ std::string buf;
+ buf.resize(PATH_MAX);
+ while (true)
+ {
+ uint32_t size = static_cast< uint32_t >(buf.size());
+ if (_NSGetExecutablePath(&buf[0], &size) == 0)
+ {
+ buf.resize(std::strlen(&buf[0]));
+ break;
+ }
+
+ buf.resize(size);
+ }
+
+ return filesystem::path(buf).filename().string();
+}
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#elif defined(__FreeBSD__)
+
+#include <stddef.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <boost/lexical_cast.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! The function returns the current process name
+BOOST_LOG_API std::string get_process_name()
+{
+#if defined(KERN_PROC_PATHNAME)
+ int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
+ char buf[PATH_MAX] = {};
+ size_t cb = sizeof(buf);
+ if (sysctl(mib, 4, buf, &cb, NULL, 0) == 0)
+ return filesystem::path(buf).filename().string();
+#endif
+
+ if (filesystem::exists("/proc/curproc/file"))
+ return filesystem::read_symlink("/proc/curproc/file").filename().string();
+
+ return boost::lexical_cast< std::string >(getpid());
+}
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#else
+
+#include <unistd.h>
+#include <boost/lexical_cast.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! The function returns the current process name
+BOOST_LOG_API std::string get_process_name()
+{
+ if (filesystem::exists("/proc/self/exe"))
+ return filesystem::read_symlink("/proc/self/exe").filename().string();
+
+ if (filesystem::exists("/proc/curproc/file"))
+ return filesystem::read_symlink("/proc/curproc/file").filename().string();
+
+ if (filesystem::exists("/proc/curproc/exe"))
+ return filesystem::read_symlink("/proc/curproc/exe").filename().string();
+
+ return boost::lexical_cast< std::string >(getpid());
+}
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif

Added: trunk/libs/log/src/record_ostream.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/record_ostream.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,180 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 17.04.2008
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#include <memory>
+#include <locale>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/detail/singleton.hpp>
+#include <boost/log/attributes/attribute_value_impl.hpp>
+#include <boost/log/expressions/message.hpp>
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/thread/tss.hpp>
+#endif
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+//! The function initializes the stream and the stream buffer
+template< typename CharT >
+BOOST_LOG_API void basic_record_ostream< CharT >::init_stream()
+{
+ base_type::imbue(std::locale());
+ if (m_record)
+ {
+ typedef attributes::attribute_value_impl< string_type > message_impl_type;
+ intrusive_ptr< message_impl_type > p = new message_impl_type(string_type());
+ attribute_value value(p);
+
+ // This may fail if the record already has Message attribute
+ std::pair< attribute_value_set::const_iterator, bool > res =
+ m_record->attribute_values().insert(expressions::tag::message::get_name(), value);
+ if (!res.second)
+ const_cast< attribute_value& >(res.first->second).swap(value);
+
+ base_type::attach(const_cast< string_type& >(p->get()));
+ }
+}
+//! The function resets the stream into a detached (default initialized) state
+template< typename CharT >
+BOOST_LOG_API void basic_record_ostream< CharT >::detach_from_record() BOOST_NOEXCEPT
+{
+ if (m_record)
+ {
+ base_type::detach();
+ m_record = NULL;
+ base_type::exceptions(stream_type::goodbit);
+ }
+}
+
+namespace aux {
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+//! The pool of stream compounds
+template< typename CharT >
+class stream_compound_pool :
+ public log::aux::lazy_singleton<
+ stream_compound_pool< CharT >,
+#if !defined(BOOST_LOG_NO_THREADS)
+ thread_specific_ptr< stream_compound_pool< CharT > >
+#else
+ std::auto_ptr< stream_compound_pool< CharT > >
+#endif
+ >
+{
+ //! Self type
+ typedef stream_compound_pool< CharT > this_type;
+#if !defined(BOOST_LOG_NO_THREADS)
+ //! Thread-specific pointer type
+ typedef thread_specific_ptr< this_type > tls_ptr_type;
+#else
+ //! Thread-specific pointer type
+ typedef std::auto_ptr< this_type > tls_ptr_type;
+#endif
+ //! Singleton base type
+ typedef log::aux::lazy_singleton<
+ this_type,
+ tls_ptr_type
+ > base_type;
+ //! Stream compound type
+ typedef typename stream_provider< CharT >::stream_compound stream_compound_t;
+
+public:
+ //! Pooled stream compounds
+ stream_compound_t* m_Top;
+
+ ~stream_compound_pool()
+ {
+ register stream_compound_t* p = NULL;
+ while ((p = m_Top) != NULL)
+ {
+ m_Top = p->next;
+ delete p;
+ }
+ }
+
+ //! The method returns pool instance
+ static stream_compound_pool& get()
+ {
+ tls_ptr_type& ptr = base_type::get();
+ register this_type* p = ptr.get();
+ if (!p)
+ {
+ std::auto_ptr< this_type > pNew(new this_type());
+ ptr.reset(pNew.get());
+ p = pNew.release();
+ }
+ return *p;
+ }
+
+private:
+ stream_compound_pool() : m_Top(NULL) {}
+};
+
+} // namespace
+
+//! The method returns an allocated stream compound
+template< typename CharT >
+BOOST_LOG_API typename stream_provider< CharT >::stream_compound*
+stream_provider< CharT >::allocate_compound(record& rec)
+{
+ stream_compound_pool< char_type >& pool = stream_compound_pool< char_type >::get();
+ if (pool.m_Top)
+ {
+ register stream_compound* p = pool.m_Top;
+ pool.m_Top = p->next;
+ p->next = NULL;
+ p->stream.attach_record(rec);
+ return p;
+ }
+ else
+ return new stream_compound(rec);
+}
+
+//! The method releases a compound
+template< typename CharT >
+BOOST_LOG_API void stream_provider< CharT >::release_compound(stream_compound* compound) BOOST_NOEXCEPT
+{
+ stream_compound_pool< char_type >& pool = stream_compound_pool< char_type >::get();
+ compound->next = pool.m_Top;
+ pool.m_Top = compound;
+ compound->stream.detach_from_record();
+}
+
+//! Explicitly instantiate stream_provider implementation
+#ifdef BOOST_LOG_USE_CHAR
+template struct stream_provider< char >;
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+template struct stream_provider< wchar_t >;
+#endif
+
+} // namespace aux
+
+//! Explicitly instantiate basic_record_ostream implementation
+#ifdef BOOST_LOG_USE_CHAR
+template class basic_record_ostream< char >;
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+template class basic_record_ostream< wchar_t >;
+#endif
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>

Added: trunk/libs/log/src/settings_parser.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/settings_parser.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,249 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 20.07.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#ifndef BOOST_LOG_WITHOUT_SETTINGS_PARSERS
+
+#include <string>
+#include <iostream>
+#include <locale>
+#include <memory>
+#include <stdexcept>
+#include <boost/ref.hpp>
+#include <boost/bind.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/io/ios_state.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/algorithm/string/trim.hpp>
+#include <boost/spirit/include/qi_core.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_lit.hpp>
+#include <boost/spirit/include/qi_eoi.hpp>
+#include <boost/spirit/include/qi_eol.hpp>
+#include <boost/spirit/include/qi_raw.hpp>
+#include <boost/spirit/include/qi_lexeme.hpp>
+#include <boost/range/iterator_range_core.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/code_conversion.hpp>
+#include <boost/log/exceptions.hpp>
+#include <boost/log/utility/setup/settings_parser.hpp>
+#include "parser_utils.hpp"
+#include "spirit_encoding.hpp"
+#include <boost/log/detail/header.hpp>
+
+namespace qi = boost::spirit::qi;
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+//! Settings parsing grammar
+template< typename CharT >
+class settings_grammar :
+ public qi::grammar<
+ const CharT*,
+ typename log::aux::encoding_specific< typename log::aux::encoding< CharT >::type >::space_type
+ >
+{
+private:
+ typedef CharT char_type;
+ typedef const char_type* iterator_type;
+ typedef log::aux::encoding_specific< typename log::aux::encoding< char_type >::type > encoding_specific;
+ typedef settings_grammar< char_type > this_type;
+ typedef qi::grammar< iterator_type, typename encoding_specific::space_type > base_type;
+ typedef typename base_type::start_type rule_type;
+
+ typedef std::basic_string< char_type > string_type;
+ typedef log::aux::char_constants< char_type > constants;
+ typedef basic_settings< char_type > settings_type;
+
+private:
+ //! Current section name
+ std::string m_SectionName;
+ //! Current parameter name
+ std::string m_ParameterName;
+ //! Settings instance
+ settings_type& m_Settings;
+ //! Locale from the source stream
+ std::locale m_Locale;
+ //! Current line number
+ unsigned int& m_LineCounter;
+
+ //! A parser for a comment
+ rule_type comment;
+ //! A parser for a section name
+ rule_type section_name;
+ //! A parser for a quoted string
+ rule_type quoted_string;
+ //! A parser for a parameter name and value
+ rule_type parameter;
+ //! A parser for a single line
+ rule_type line;
+
+public:
+ //! Constructor
+ explicit settings_grammar(settings_type& setts, unsigned int& line_counter, std::locale const& loc) :
+ base_type(line, "settings_grammar"),
+ m_Settings(setts),
+ m_Locale(loc),
+ m_LineCounter(line_counter)
+ {
+ comment = qi::lit(constants::char_comment) >> *qi::char_;
+
+ section_name =
+ qi::raw[ qi::lit(constants::char_section_bracket_left) >> +(encoding_specific::graph - constants::char_section_bracket_right) >> constants::char_section_bracket_right ]
+ [boost::bind(&this_type::set_section_name, this, _1)] >>
+ -comment;
+
+ quoted_string = qi::lexeme
+ [
+ qi::lit(constants::char_quote) >>
+ *(
+ (qi::lit(constants::char_backslash) >> qi::char_) |
+ (qi::char_ - qi::lit(constants::char_quote))
+ ) >>
+ qi::lit(constants::char_quote)
+ ];
+
+ parameter =
+ // Parameter name
+ qi::raw[ qi::lexeme[ encoding_specific::alpha >> *(encoding_specific::graph - constants::char_equal) ] ]
+ [boost::bind(&this_type::set_parameter_name, this, _1)] >>
+ qi::lit(constants::char_equal) >>
+ // Parameter value
+ (
+ qi::raw[ quoted_string ][boost::bind(&this_type::set_parameter_quoted_value, this, _1)] |
+ qi::raw[ +encoding_specific::graph ][boost::bind(&this_type::set_parameter_value, this, _1)]
+ ) >>
+ -comment;
+
+ line = (comment | section_name | parameter) >> qi::eoi;
+ }
+
+private:
+ //! The method sets the parsed section name
+ void set_section_name(iterator_range< iterator_type > const& sec)
+ {
+ // Trim square brackets
+ m_SectionName = log::aux::to_narrow(string_type(sec.begin() + 1, sec.end() - 1), m_Locale);
+ algorithm::trim(m_SectionName, m_Locale);
+ if (m_SectionName.empty())
+ {
+ // The section starter is broken
+ BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The section header is invalid.", (m_LineCounter));
+ }
+
+ // For compatibility with Boost.Log v1, we replace the "Sink:" prefix with "Sinks."
+ // so that all sink parameters are placed in the common Sinks section.
+ if (m_SectionName.compare(0, 5, "Sink:") == 0)
+ m_SectionName = "Sinks." + m_SectionName.substr(5);
+ }
+
+ //! The method sets the parsed parameter name
+ void set_parameter_name(iterator_range< iterator_type > const& name)
+ {
+ if (m_SectionName.empty())
+ {
+ // The parameter encountered before any section starter
+ BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "Parameters are only allowed within sections.", (m_LineCounter));
+ }
+
+ m_ParameterName = log::aux::to_narrow(string_type(name.begin(), name.end()), m_Locale);
+ }
+
+ //! The method sets the parsed parameter value (non-quoted)
+ void set_parameter_value(iterator_range< iterator_type > const& value)
+ {
+ string_type val(value.begin(), value.end());
+ m_Settings[m_SectionName][m_ParameterName] = val;
+ m_ParameterName.clear();
+ }
+
+ //! The method sets the parsed parameter value (quoted)
+ void set_parameter_quoted_value(iterator_range< iterator_type > const& value)
+ {
+ // Cut off the quotes
+ string_type val(value.begin() + 1, value.end() - 1);
+ constants::translate_escape_sequences(val);
+ m_Settings[m_SectionName][m_ParameterName] = val;
+ m_ParameterName.clear();
+ }
+
+ // Assignment and copying are prohibited
+ BOOST_LOG_DELETED_FUNCTION(settings_grammar(settings_grammar const&))
+ BOOST_LOG_DELETED_FUNCTION(settings_grammar& operator= (settings_grammar const&))
+};
+
+} // namespace
+
+//! The function parses library settings from an input stream
+template< typename CharT >
+basic_settings< CharT > parse_settings(std::basic_istream< CharT >& strm)
+{
+ typedef CharT char_type;
+ typedef std::basic_string< char_type > string_type;
+ typedef settings_grammar< char_type > settings_grammar_type;
+ typedef basic_settings< char_type > settings_type;
+ typedef log::aux::encoding_specific< typename log::aux::encoding< char_type >::type > encoding_specific;
+
+ if (!strm.good())
+ BOOST_THROW_EXCEPTION(std::invalid_argument("The input stream for parsing settings is not valid"));
+
+ io::basic_ios_exception_saver< char_type > exceptions_guard(strm, std::ios_base::badbit);
+
+ // Engage parsing
+ settings_type settings;
+ unsigned int line_number = 1;
+ std::locale loc = strm.getloc();
+ settings_grammar_type gram(settings, line_number, loc);
+
+ string_type line;
+ while (!strm.eof())
+ {
+ std::getline(strm, line);
+ algorithm::trim(line, loc);
+
+ if (!line.empty())
+ {
+ if (!qi::phrase_parse(line.c_str(), line.c_str() + line.size(), gram, encoding_specific::space))
+ {
+ BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "Could not parse settings from stream.", (line_number));
+ }
+ line.clear();
+ }
+
+ ++line_number;
+ }
+
+ return boost::move(settings);
+}
+
+
+#ifdef BOOST_LOG_USE_CHAR
+template BOOST_LOG_SETUP_API basic_settings< char > parse_settings< char >(std::basic_istream< char >& strm);
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+template BOOST_LOG_SETUP_API basic_settings< wchar_t > parse_settings< wchar_t >(std::basic_istream< wchar_t >& strm);
+#endif
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_WITHOUT_SETTINGS_PARSERS

Added: trunk/libs/log/src/severity_level.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/severity_level.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,92 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_level.cpp
+ * \author Andrey Semashev
+ * \date 10.05.2008
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#include <boost/cstdint.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/sources/severity_feature.hpp>
+
+#if !defined(BOOST_LOG_NO_THREADS) && !defined(BOOST_LOG_USE_COMPILER_TLS)
+#include <memory>
+#include <boost/bind.hpp>
+#include <boost/checked_delete.hpp>
+#include <boost/thread/thread.hpp> // at_thread_exit
+#include <boost/log/detail/singleton.hpp>
+#include <boost/log/detail/thread_specific.hpp>
+#endif
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sources {
+
+namespace aux {
+
+#if defined(BOOST_LOG_NO_THREADS)
+
+static uintmax_t g_Severity = 0;
+
+#elif defined(BOOST_LOG_USE_COMPILER_TLS)
+
+static BOOST_LOG_TLS uintmax_t g_Severity = 0;
+
+#else
+
+//! Severity level storage class
+class severity_level_holder :
+ public boost::log::aux::lazy_singleton< severity_level_holder, boost::log::aux::thread_specific< uintmax_t* > >
+{
+};
+
+#endif
+
+
+#if !defined(BOOST_LOG_NO_THREADS) && !defined(BOOST_LOG_USE_COMPILER_TLS)
+
+//! The method returns the severity level for the current thread
+BOOST_LOG_API uintmax_t& get_severity_level()
+{
+ boost::log::aux::thread_specific< uintmax_t* >& tss = severity_level_holder::get();
+ uintmax_t* p = tss.get();
+ if (!p)
+ {
+ std::auto_ptr< uintmax_t > ptr(new uintmax_t(0));
+ tss.set(ptr.get());
+ p = ptr.release();
+ boost::this_thread::at_thread_exit(boost::bind(checked_deleter< uintmax_t >(), p));
+ }
+ return *p;
+}
+
+#else // !defined(BOOST_LOG_NO_THREADS) && !defined(BOOST_LOG_USE_COMPILER_TLS)
+
+//! The method returns the severity level for the current thread
+BOOST_LOG_API uintmax_t& get_severity_level()
+{
+ return g_Severity;
+}
+
+#endif // !defined(BOOST_LOG_NO_THREADS) && !defined(BOOST_LOG_USE_COMPILER_TLS)
+
+} // namespace aux
+
+} // namespace sources
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>

Added: trunk/libs/log/src/simple_event_log.mc
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/simple_event_log.mc 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,58 @@
+;/*
+; * Copyright Andrey Semashev 2007 - 2013.
+; * 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)
+; *
+; * This file is the Boost.Log library implementation, see the library documentation
+; * at http://www.boost.org/libs/log/doc/log.html.
+; */
+;
+;/* --------------------------------------------------------
+; * HEADER SECTION
+; */
+SeverityNames=(Debug=0x0:BOOST_LOG_SEVERITY_DEBUG
+ Info=0x1:BOOST_LOG_SEVERITY_INFO
+ Warning=0x2:BOOST_LOG_SEVERITY_WARNING
+ Error=0x3:BOOST_LOG_SEVERITY_ERROR
+ )
+;
+;
+;
+;/* ------------------------------------------------------------------
+; * MESSAGE DEFINITION SECTION
+; */
+
+MessageIdTypedef=DWORD
+
+MessageId=0x100
+Severity=Debug
+Facility=Application
+SymbolicName=BOOST_LOG_MSG_DEBUG
+Language=English
+%1
+.
+
+MessageId=0x101
+Severity=Info
+Facility=Application
+SymbolicName=BOOST_LOG_MSG_INFO
+Language=English
+%1
+.
+
+MessageId=0x102
+Severity=Warning
+Facility=Application
+SymbolicName=BOOST_LOG_MSG_WARNING
+Language=English
+%1
+.
+
+MessageId=0x103
+Severity=Error
+Facility=Application
+SymbolicName=BOOST_LOG_MSG_ERROR
+Language=English
+%1
+.

Added: trunk/libs/log/src/spirit_encoding.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/spirit_encoding.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,47 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 spirit_encoding.cpp
+ * \author Andrey Semashev
+ * \date 20.07.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#include <boost/preprocessor/tuple/elem.hpp>
+#include <boost/preprocessor/seq/for_each.hpp>
+#include "spirit_encoding.hpp"
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+#define BOOST_LOG_DEFINE_CHARSET_PARSER(r, charset, parser)\
+ BOOST_LOG_API encoding_specific< spirit::char_encoding::charset >::BOOST_PP_TUPLE_ELEM(2, 0, parser) const&\
+ encoding_specific< spirit::char_encoding::charset >::BOOST_PP_TUPLE_ELEM(2, 1, parser) =\
+ spirit::charset::BOOST_PP_TUPLE_ELEM(2, 1, parser);
+
+#define BOOST_LOG_DEFINE_CHARSET_PARSERS(charset)\
+ BOOST_PP_SEQ_FOR_EACH(BOOST_LOG_DEFINE_CHARSET_PARSER, charset, BOOST_LOG_CHARSET_PARSERS)
+
+BOOST_LOG_DEFINE_CHARSET_PARSERS(standard)
+BOOST_LOG_DEFINE_CHARSET_PARSERS(standard_wide)
+
+#undef BOOST_LOG_DEFINE_CHARSET_PARSERS
+#undef BOOST_LOG_DEFINE_CHARSET_PARSER
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>

Added: trunk/libs/log/src/spirit_encoding.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/spirit_encoding.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,104 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 spirit_encoding.hpp
+ * \author Andrey Semashev
+ * \date 20.07.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#ifndef BOOST_LOG_SPIRIT_ENCODING_HPP_INCLUDED_
+#define BOOST_LOG_SPIRIT_ENCODING_HPP_INCLUDED_
+
+#include <boost/preprocessor/tuple/elem.hpp>
+#include <boost/preprocessor/seq/for_each.hpp>
+#include <boost/spirit/include/support_standard.hpp>
+#include <boost/spirit/include/support_standard_wide.hpp>
+#include <boost/spirit/home/support/common_terminals.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+template< typename >
+struct encoding;
+
+template< >
+struct encoding< char >
+{
+ typedef spirit::char_encoding::standard type;
+};
+template< >
+struct encoding< wchar_t >
+{
+ typedef spirit::char_encoding::standard_wide type;
+};
+
+//! A simple trait that allows to use charset-specific Qi parsers in a generic way
+template< typename EncodingT >
+struct encoding_specific;
+
+#define BOOST_LOG_CHARSET_PARSERS\
+ ((char_type, char_))\
+ ((string_type, string))\
+ ((alnum_type, alnum))\
+ ((alpha_type, alpha))\
+ ((blank_type, blank))\
+ ((cntrl_type, cntrl))\
+ ((digit_type, digit))\
+ ((graph_type, graph))\
+ ((print_type, print))\
+ ((punct_type, punct))\
+ ((space_type, space))\
+ ((xdigit_type, xdigit))\
+ ((no_case_type, no_case))\
+ ((lower_type, lower))\
+ ((upper_type, upper))\
+ ((lowernum_type, lowernum))\
+ ((uppernum_type, uppernum))
+
+#define BOOST_LOG_DECLARE_CHARSET_PARSER(r, charset, parser)\
+ typedef spirit::charset::BOOST_PP_TUPLE_ELEM(2, 0, parser) BOOST_PP_TUPLE_ELEM(2, 0, parser);\
+ BOOST_LOG_API static BOOST_PP_TUPLE_ELEM(2, 0, parser) const& BOOST_PP_TUPLE_ELEM(2, 1, parser);
+
+#define BOOST_LOG_DECLARE_CHARSET_PARSERS(charset)\
+ BOOST_PP_SEQ_FOR_EACH(BOOST_LOG_DECLARE_CHARSET_PARSER, charset, BOOST_LOG_CHARSET_PARSERS)
+
+template< >
+struct encoding_specific< spirit::char_encoding::standard >
+{
+ BOOST_LOG_DECLARE_CHARSET_PARSERS(standard)
+};
+
+template< >
+struct encoding_specific< spirit::char_encoding::standard_wide >
+{
+ BOOST_LOG_DECLARE_CHARSET_PARSERS(standard_wide)
+};
+
+#undef BOOST_LOG_DECLARE_CHARSET_PARSERS
+#undef BOOST_LOG_DECLARE_CHARSET_PARSER
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SPIRIT_ENCODING_HPP_INCLUDED_

Added: trunk/libs/log/src/stateless_allocator.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/stateless_allocator.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,95 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 stateless_allocator.hpp
+ * \author Andrey Semashev
+ * \date 11.02.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#ifndef BOOST_LOG_STATELESS_ALLOCATOR_HPP_INCLUDED_
+#define BOOST_LOG_STATELESS_ALLOCATOR_HPP_INCLUDED_
+
+#include <cstddef>
+#include <cstdlib>
+#include <memory>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_LOG_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+#if defined(_STLPORT_VERSION)
+
+#if !defined(BOOST_NO_TEMPLATE_ALIASES) && !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template< typename T >
+using stateless_allocator = std::allocator< T >;
+
+#else
+
+template< typename T >
+struct stateless_allocator :
+ public std::allocator< T >
+{
+};
+
+#endif
+
+#else
+
+template< typename T >
+struct stateless_allocator
+{
+ template< typename U >
+ struct rebind
+ {
+ typedef stateless_allocator< U > other;
+ };
+
+ typedef T value_type;
+ typedef value_type* pointer;
+ typedef value_type const* const_pointer;
+ typedef value_type& reference;
+ typedef value_type const& const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ static pointer allocate(size_type n, const void* = NULL)
+ {
+ pointer p = static_cast< pointer >(std::malloc(n * sizeof(value_type)));
+ if (p)
+ return p;
+ else
+ throw std::bad_alloc();
+ }
+ static void deallocate(pointer p, size_type)
+ {
+ std::free(p);
+ }
+};
+
+#endif
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_STATELESS_ALLOCATOR_HPP_INCLUDED_

Added: trunk/libs/log/src/syslog_backend.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/syslog_backend.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,591 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 08.01.2008
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#ifndef BOOST_LOG_WITHOUT_SYSLOG
+
+#include "windows_version.hpp"
+#include <boost/log/detail/config.hpp>
+#include <memory>
+#include <algorithm>
+#include <stdexcept>
+#include <boost/limits.hpp>
+#include <boost/assert.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/throw_exception.hpp>
+#if !defined(BOOST_LOG_NO_ASIO)
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/socket_base.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/ip/udp.hpp>
+#include <boost/asio/ip/address.hpp>
+#include <boost/asio/ip/host_name.hpp>
+#endif
+#include <boost/system/error_code.hpp>
+#include <boost/date_time/c_time.hpp>
+#include <ctime>
+#include <boost/log/sinks/syslog_backend.hpp>
+#include <boost/log/detail/singleton.hpp>
+#include <boost/log/detail/snprintf.hpp>
+#include <boost/log/exceptions.hpp>
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/thread/locks.hpp>
+#include <boost/thread/mutex.hpp>
+#endif
+
+#ifdef BOOST_LOG_USE_NATIVE_SYSLOG
+#include <syslog.h>
+#endif // BOOST_LOG_USE_NATIVE_SYSLOG
+
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+namespace syslog {
+
+ //! The function constructs log record level from an integer
+ BOOST_LOG_API level make_level(int lev)
+ {
+ if (static_cast< unsigned int >(lev) >= 8)
+ BOOST_THROW_EXCEPTION(std::out_of_range("syslog level value is out of range"));
+ return static_cast< level >(lev);
+ }
+
+ //! The function constructs log source facility from an integer
+ BOOST_LOG_API facility make_facility(int fac)
+ {
+ if ((static_cast< unsigned int >(fac) & 7U) != 0
+ || static_cast< unsigned int >(fac) > (23U * 8U))
+ {
+ BOOST_THROW_EXCEPTION(std::out_of_range("syslog facility code value is out of range"));
+ }
+ return static_cast< facility >(fac);
+ }
+
+} // namespace syslog
+
+////////////////////////////////////////////////////////////////////////////////
+//! Syslog sink backend implementation
+////////////////////////////////////////////////////////////////////////////////
+struct syslog_backend::implementation
+{
+#ifdef BOOST_LOG_USE_NATIVE_SYSLOG
+ struct native;
+#endif // BOOST_LOG_USE_NATIVE_SYSLOG
+#if !defined(BOOST_LOG_NO_ASIO)
+ struct udp_socket_based;
+#endif
+
+ //! Level mapper
+ severity_mapper_type m_LevelMapper;
+
+ //! Logging facility (portable or native, depending on the backend implementation)
+ const int m_Facility;
+
+ //! Constructor
+ explicit implementation(int facility) :
+ m_Facility(facility)
+ {
+ }
+ //! Virtual destructor
+ virtual ~implementation() {}
+
+ //! The method sends the formatted message to the syslog host
+ virtual void send(syslog::level lev, string_type const& formatted_message) = 0;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Native syslog API support
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef BOOST_LOG_USE_NATIVE_SYSLOG
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+ //! Syslog service initializer (implemented as a weak singleton)
+#if !defined(BOOST_LOG_NO_THREADS)
+ class native_syslog_initializer :
+ private log::aux::lazy_singleton< native_syslog_initializer, mutex >
+#else
+ class native_syslog_initializer
+#endif
+ {
+#if !defined(BOOST_LOG_NO_THREADS)
+ friend class log::aux::lazy_singleton< native_syslog_initializer, mutex >;
+ typedef log::aux::lazy_singleton< native_syslog_initializer, mutex > mutex_holder;
+#endif
+
+ public:
+ native_syslog_initializer(std::string const& ident, int facility)
+ {
+ ::openlog((ident.empty() ? static_cast< const char* >(NULL) : ident.c_str()), 0, facility);
+ }
+ ~native_syslog_initializer()
+ {
+ ::closelog();
+ }
+
+ static shared_ptr< native_syslog_initializer > get_instance(std::string const& ident, int facility)
+ {
+#if !defined(BOOST_LOG_NO_THREADS)
+ lock_guard< mutex > lock(mutex_holder::get());
+#endif
+ static weak_ptr< native_syslog_initializer > instance;
+ shared_ptr< native_syslog_initializer > p(instance.lock());
+ if (!p)
+ {
+ p = boost::make_shared< native_syslog_initializer >(ident, facility);
+ instance = p;
+ }
+ return p;
+ }
+ };
+
+} // namespace
+
+struct syslog_backend::implementation::native :
+ public implementation
+{
+ //! Reference to the syslog service initializer
+ const shared_ptr< native_syslog_initializer > m_pSyslogInitializer;
+
+ //! Constructor
+ native(syslog::facility const& fac, std::string const& ident) :
+ implementation(convert_facility(fac)),
+ m_pSyslogInitializer(native_syslog_initializer::get_instance(ident, this->m_Facility))
+ {
+ }
+
+ //! The method sends the formatted message to the syslog host
+ void send(syslog::level lev, string_type const& formatted_message)
+ {
+ int native_level;
+ switch (lev)
+ {
+ case syslog::emergency:
+ native_level = LOG_EMERG; break;
+ case syslog::alert:
+ native_level = LOG_ALERT; break;
+ case syslog::critical:
+ native_level = LOG_CRIT; break;
+ case syslog::error:
+ native_level = LOG_ERR; break;
+ case syslog::warning:
+ native_level = LOG_WARNING; break;
+ case syslog::notice:
+ native_level = LOG_NOTICE; break;
+ case syslog::debug:
+ native_level = LOG_DEBUG; break;
+ default:
+ native_level = LOG_INFO; break;
+ }
+
+ ::syslog(this->m_Facility | native_level, "%s", formatted_message.c_str());
+ }
+
+private:
+ //! The function converts portable facility codes to the native codes
+ static int convert_facility(syslog::facility const& fac)
+ {
+ // POSIX does not specify anything except for LOG_USER and LOG_LOCAL*
+ #ifndef LOG_KERN
+ #define LOG_KERN LOG_USER
+ #endif
+ #ifndef LOG_DAEMON
+ #define LOG_DAEMON LOG_KERN
+ #endif
+ #ifndef LOG_MAIL
+ #define LOG_MAIL LOG_USER
+ #endif
+ #ifndef LOG_AUTH
+ #define LOG_AUTH LOG_DAEMON
+ #endif
+ #ifndef LOG_SYSLOG
+ #define LOG_SYSLOG LOG_DAEMON
+ #endif
+ #ifndef LOG_LPR
+ #define LOG_LPR LOG_DAEMON
+ #endif
+ #ifndef LOG_NEWS
+ #define LOG_NEWS LOG_USER
+ #endif
+ #ifndef LOG_UUCP
+ #define LOG_UUCP LOG_USER
+ #endif
+ #ifndef LOG_CRON
+ #define LOG_CRON LOG_DAEMON
+ #endif
+ #ifndef LOG_AUTHPRIV
+ #define LOG_AUTHPRIV LOG_AUTH
+ #endif
+ #ifndef LOG_FTP
+ #define LOG_FTP LOG_DAEMON
+ #endif
+
+ static const int native_facilities[24] =
+ {
+ LOG_KERN,
+ LOG_USER,
+ LOG_MAIL,
+ LOG_DAEMON,
+ LOG_AUTH,
+ LOG_SYSLOG,
+ LOG_LPR,
+ LOG_NEWS,
+ LOG_UUCP,
+ LOG_CRON,
+ LOG_AUTHPRIV,
+ LOG_FTP,
+
+ // reserved values
+ LOG_USER,
+ LOG_USER,
+ LOG_USER,
+ LOG_USER,
+
+ LOG_LOCAL0,
+ LOG_LOCAL1,
+ LOG_LOCAL2,
+ LOG_LOCAL3,
+ LOG_LOCAL4,
+ LOG_LOCAL5,
+ LOG_LOCAL6,
+ LOG_LOCAL7
+ };
+
+ register std::size_t n = static_cast< unsigned int >(fac) / 8U;
+ BOOST_ASSERT(n < sizeof(native_facilities) / sizeof(*native_facilities));
+ return native_facilities[n];
+ }
+};
+
+#endif // BOOST_LOG_USE_NATIVE_SYSLOG
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Socket-based implementation
+////////////////////////////////////////////////////////////////////////////////
+
+#if !defined(BOOST_LOG_NO_ASIO)
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+ //! The shared UDP socket
+ struct syslog_udp_socket
+ {
+ private:
+ //! The socket primitive
+ asio::ip::udp::socket m_Socket;
+
+ public:
+ //! The constructor creates a socket bound to the specified local address and port
+ explicit syslog_udp_socket(asio::io_service& service, asio::ip::udp const& protocol, asio::ip::udp::endpoint const& local_address) :
+ m_Socket(service)
+ {
+ m_Socket.open(protocol);
+ m_Socket.set_option(asio::socket_base::reuse_address(true));
+ m_Socket.bind(local_address);
+ }
+ //! The destructor closes the socket
+ ~syslog_udp_socket()
+ {
+ boost::system::error_code ec;
+ m_Socket.shutdown(asio::socket_base::shutdown_both, ec);
+ m_Socket.close(ec);
+ }
+
+ //! The method sends the syslog message to the specified endpoint
+ void send_message(int pri, const char* local_host_name, asio::ip::udp::endpoint const& target, const char* message);
+
+ private:
+ syslog_udp_socket(syslog_udp_socket const&);
+ syslog_udp_socket& operator= (syslog_udp_socket const&);
+ };
+
+ //! The class contains the UDP service for syslog sockets to function
+ class syslog_udp_service :
+ public log::aux::lazy_singleton< syslog_udp_service, shared_ptr< syslog_udp_service > >
+ {
+ friend class log::aux::lazy_singleton< syslog_udp_service, shared_ptr< syslog_udp_service > >;
+ typedef log::aux::lazy_singleton< syslog_udp_service, shared_ptr< syslog_udp_service > > base_type;
+
+ public:
+ //! The core IO service instance
+ asio::io_service m_IOService;
+ //! The local host name to put into log message
+ std::string m_LocalHostName;
+
+#if !defined(BOOST_LOG_NO_THREADS)
+ //! A synchronization primitive to protect the host name resolver
+ mutex m_Mutex;
+ //! The resolver is used to acquire connection endpoints
+ asio::ip::udp::resolver m_HostNameResolver;
+#endif // !defined(BOOST_LOG_NO_THREADS)
+
+ private:
+ //! Default constructor
+ syslog_udp_service()
+#if !defined(BOOST_LOG_NO_THREADS)
+ : m_HostNameResolver(m_IOService)
+#endif // !defined(BOOST_LOG_NO_THREADS)
+ {
+ boost::system::error_code err;
+ m_LocalHostName = asio::ip::host_name(err);
+ }
+ //! Initializes the singleton instance
+ static void init_instance()
+ {
+ base_type::get_instance().reset(new syslog_udp_service());
+ }
+ };
+
+ //! The method sends the syslog message to the specified endpoint
+ void syslog_udp_socket::send_message(
+ int pri, const char* local_host_name, asio::ip::udp::endpoint const& target, const char* message)
+ {
+ std::time_t t = std::time(NULL);
+ std::tm ts;
+ std::tm* time_stamp = boost::date_time::c_time::localtime(&t, &ts);
+
+ // Month will have to be injected separately, as involving locale won't do here
+ static const char months[12][4] =
+ {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+ };
+
+ // The packet size is mandated in RFC3164, plus one for the terminating zero
+ char packet[1025];
+ std::size_t packet_size = boost::log::aux::snprintf
+ (
+ packet,
+ sizeof(packet),
+ "<%d> %s % 2d %02d:%02d:%02d %s %s",
+ pri,
+ months[time_stamp->tm_mon],
+ time_stamp->tm_mday,
+ time_stamp->tm_hour,
+ time_stamp->tm_min,
+ time_stamp->tm_sec,
+ local_host_name,
+ message
+ );
+
+ m_Socket.send_to(asio::buffer(packet, packet_size), target);
+ }
+
+} // namespace
+
+struct syslog_backend::implementation::udp_socket_based :
+ public implementation
+{
+ //! Protocol to be used
+ asio::ip::udp m_Protocol;
+ //! Pointer to the list of sockets
+ shared_ptr< syslog_udp_service > m_pService;
+ //! Pointer to the socket being used
+ std::auto_ptr< syslog_udp_socket > m_pSocket;
+ //! The target host to send packets to
+ asio::ip::udp::endpoint m_TargetHost;
+
+ //! Constructor
+ explicit udp_socket_based(syslog::facility const& fac, asio::ip::udp const& protocol) :
+ implementation(fac),
+ m_Protocol(protocol),
+ m_pService(syslog_udp_service::get())
+ {
+ if (m_Protocol == asio::ip::udp::v4())
+ {
+ m_TargetHost = asio::ip::udp::endpoint(asio::ip::address_v4(0x7F000001), 514); // 127.0.0.1:514
+ }
+ else
+ {
+ // ::1, port 514
+ asio::ip::address_v6::bytes_type addr;
+ std::fill_n(addr.data(), addr.size() - 1, static_cast< unsigned char >(0));
+ addr[addr.size() - 1] = 1;
+ m_TargetHost = asio::ip::udp::endpoint(asio::ip::address_v6(addr), 514);
+ }
+ }
+
+ //! The method sends the formatted message to the syslog host
+ void send(syslog::level lev, string_type const& formatted_message)
+ {
+ if (!m_pSocket.get())
+ {
+ asio::ip::udp::endpoint any_local_address;
+ m_pSocket.reset(new syslog_udp_socket(m_pService->m_IOService, m_Protocol, any_local_address));
+ }
+
+ m_pSocket->send_message(
+ this->m_Facility | static_cast< int >(lev),
+ m_pService->m_LocalHostName.c_str(),
+ m_TargetHost,
+ formatted_message.c_str());
+ }
+};
+
+#endif // !defined(BOOST_LOG_NO_ASIO)
+
+////////////////////////////////////////////////////////////////////////////////
+// Sink backend implementation
+////////////////////////////////////////////////////////////////////////////////
+BOOST_LOG_API syslog_backend::syslog_backend()
+{
+ construct(log::aux::empty_arg_list());
+}
+
+//! Destructor
+BOOST_LOG_API syslog_backend::~syslog_backend()
+{
+ delete m_pImpl;
+}
+
+//! The method installs the function object that maps application severity levels to Syslog levels
+BOOST_LOG_API void syslog_backend::set_severity_mapper(severity_mapper_type const& mapper)
+{
+ m_pImpl->m_LevelMapper = mapper;
+}
+
+//! The method writes the message to the sink
+BOOST_LOG_API void syslog_backend::consume(record_view const& rec, string_type const& formatted_message)
+{
+ m_pImpl->send(
+ m_pImpl->m_LevelMapper.empty() ? syslog::info : m_pImpl->m_LevelMapper(rec),
+ formatted_message);
+}
+
+
+//! The method creates the backend implementation
+BOOST_LOG_API void syslog_backend::construct(syslog::facility fac, syslog::impl_types use_impl, ip_versions ip_version, std::string const& ident)
+{
+#ifdef BOOST_LOG_USE_NATIVE_SYSLOG
+ if (use_impl == syslog::native)
+ {
+ typedef implementation::native native_impl;
+ m_pImpl = new native_impl(fac, ident);
+ return;
+ }
+#endif // BOOST_LOG_USE_NATIVE_SYSLOG
+
+#if !defined(BOOST_LOG_NO_ASIO)
+ typedef implementation::udp_socket_based udp_socket_based_impl;
+ switch (ip_version)
+ {
+ case v4:
+ m_pImpl = new udp_socket_based_impl(fac, asio::ip::udp::v4());
+ break;
+ case v6:
+ m_pImpl = new udp_socket_based_impl(fac, asio::ip::udp::v6());
+ break;
+ default:
+ BOOST_LOG_THROW_DESCR(setup_error, "Incorrect IP version specified");
+ }
+#endif
+}
+
+#if !defined(BOOST_LOG_NO_ASIO)
+
+//! The method sets the local address which log records will be sent from.
+BOOST_LOG_API void syslog_backend::set_local_address(std::string const& addr, unsigned short port)
+{
+#if !defined(BOOST_LOG_NO_THREADS)
+ typedef implementation::udp_socket_based udp_socket_based_impl;
+ if (udp_socket_based_impl* impl = dynamic_cast< udp_socket_based_impl* >(m_pImpl))
+ {
+ char service_name[std::numeric_limits< int >::digits10 + 3];
+ boost::log::aux::snprintf(service_name, sizeof(service_name), "%d", static_cast< int >(port));
+ asio::ip::udp::resolver::query q(
+ impl->m_Protocol,
+ addr,
+ service_name,
+ asio::ip::resolver_query_base::address_configured | asio::ip::resolver_query_base::passive);
+ asio::ip::udp::endpoint local_address;
+
+ {
+ lock_guard< mutex > _(impl->m_pService->m_Mutex);
+ local_address = *impl->m_pService->m_HostNameResolver.resolve(q);
+ }
+
+ impl->m_pSocket.reset(new syslog_udp_socket(impl->m_pService->m_IOService, impl->m_Protocol, local_address));
+ }
+#else
+ // Boost.ASIO requires threads for the host name resolver,
+ // so without threads wi simply assume the string already contains IP address
+ set_local_address(boost::asio::ip::address::from_string(addr), port);
+#endif // !defined(BOOST_LOG_NO_THREADS)
+}
+//! The method sets the local address which log records will be sent from.
+BOOST_LOG_API void syslog_backend::set_local_address(boost::asio::ip::address const& addr, unsigned short port)
+{
+ typedef implementation::udp_socket_based udp_socket_based_impl;
+ if (udp_socket_based_impl* impl = dynamic_cast< udp_socket_based_impl* >(m_pImpl))
+ {
+ impl->m_pSocket.reset(new syslog_udp_socket(
+ impl->m_pService->m_IOService, impl->m_Protocol, asio::ip::udp::endpoint(addr, port)));
+ }
+}
+
+//! The method sets the address of the remote host where log records will be sent to.
+BOOST_LOG_API void syslog_backend::set_target_address(std::string const& addr, unsigned short port)
+{
+#if !defined(BOOST_LOG_NO_THREADS)
+ typedef implementation::udp_socket_based udp_socket_based_impl;
+ if (udp_socket_based_impl* impl = dynamic_cast< udp_socket_based_impl* >(m_pImpl))
+ {
+ char service_name[std::numeric_limits< int >::digits10 + 3];
+ boost::log::aux::snprintf(service_name, sizeof(service_name), "%d", static_cast< int >(port));
+ asio::ip::udp::resolver::query q(impl->m_Protocol, addr, service_name, asio::ip::resolver_query_base::address_configured);
+ asio::ip::udp::endpoint remote_address;
+
+ {
+ lock_guard< mutex > _(impl->m_pService->m_Mutex);
+ remote_address = *impl->m_pService->m_HostNameResolver.resolve(q);
+ }
+
+ impl->m_TargetHost = remote_address;
+ }
+#else
+ // Boost.ASIO requires threads for the host name resolver,
+ // so without threads wi simply assume the string already contains IP address
+ set_target_address(boost::asio::ip::address::from_string(addr), port);
+#endif // !defined(BOOST_LOG_NO_THREADS)
+}
+//! The method sets the address of the remote host where log records will be sent to.
+BOOST_LOG_API void syslog_backend::set_target_address(boost::asio::ip::address const& addr, unsigned short port)
+{
+ typedef implementation::udp_socket_based udp_socket_based_impl;
+ if (udp_socket_based_impl* impl = dynamic_cast< udp_socket_based_impl* >(m_pImpl))
+ {
+ impl->m_TargetHost = asio::ip::udp::endpoint(addr, port);
+ }
+}
+
+#endif // !defined(BOOST_LOG_NO_ASIO)
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // !defined(BOOST_LOG_WITHOUT_SYSLOG)

Added: trunk/libs/log/src/text_file_backend.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/text_file_backend.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,1373 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 09.06.2009
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#include <ctime>
+#include <cctype>
+#include <cwctype>
+#include <ctime>
+#include <cstdio>
+#include <cstdlib>
+#include <cstddef>
+#include <list>
+#include <memory>
+#include <string>
+#include <locale>
+#include <ostream>
+#include <sstream>
+#include <iterator>
+#include <algorithm>
+#include <stdexcept>
+#include <boost/ref.hpp>
+#include <boost/bind.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/filesystem/fstream.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/convenience.hpp>
+#include <boost/intrusive/list.hpp>
+#include <boost/intrusive/list_hook.hpp>
+#include <boost/intrusive/options.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/date_time/gregorian/gregorian_types.hpp>
+#include <boost/spirit/include/qi_core.hpp>
+#include <boost/spirit/include/qi_lit.hpp>
+#include <boost/log/detail/snprintf.hpp>
+#include <boost/log/detail/singleton.hpp>
+#include <boost/log/detail/light_function.hpp>
+#include <boost/log/utility/functional/bind_assign.hpp>
+#include <boost/log/utility/functional/as_action.hpp>
+#include <boost/log/exceptions.hpp>
+#include <boost/log/attributes/time_traits.hpp>
+#include <boost/log/sinks/text_file_backend.hpp>
+#include <boost/log/sinks/text_multifile_backend.hpp>
+
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/thread/locks.hpp>
+#include <boost/thread/mutex.hpp>
+#endif // !defined(BOOST_LOG_NO_THREADS)
+
+#include <boost/log/detail/header.hpp>
+
+namespace qi = boost::spirit::qi;
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+ //! A possible Boost.Filesystem extension - renames or moves the file to the target storage
+ inline void move_file(
+ filesystem::path const& from,
+ filesystem::path const& to)
+ {
+#if defined(BOOST_WINDOWS_API)
+ // On Windows MoveFile already does what we need
+ filesystem::rename(from, to);
+#else
+ // On POSIX rename fails if the target points to a different device
+ try
+ {
+ filesystem::rename(from, to);
+ }
+ catch (system::system_error& e)
+ {
+ if (e.code().value() == system::errc::cross_device_link)
+ {
+ // Attempt to manually move the file instead
+ filesystem::copy_file(from, to);
+ filesystem::remove(from);
+ }
+ else
+ throw;
+ }
+#endif
+ }
+
+ typedef filesystem::path::string_type path_string_type;
+ typedef path_string_type::value_type path_char_type;
+
+ typedef filesystem::filesystem_error filesystem_error;
+
+ //! An auxiliary traits that contain various constants and functions regarding string and character operations
+ template< typename CharT >
+ struct file_char_traits;
+
+ template< >
+ struct file_char_traits< char >
+ {
+ typedef char char_type;
+
+ static const char_type percent = '%';
+ static const char_type number_placeholder = 'N';
+ static const char_type day_placeholder = 'd';
+ static const char_type month_placeholder = 'm';
+ static const char_type year_placeholder = 'y';
+ static const char_type full_year_placeholder = 'Y';
+ static const char_type frac_sec_placeholder = 'f';
+ static const char_type seconds_placeholder = 'S';
+ static const char_type minutes_placeholder = 'M';
+ static const char_type hours_placeholder = 'H';
+ static const char_type space = ' ';
+ static const char_type plus = '+';
+ static const char_type minus = '-';
+ static const char_type zero = '0';
+ static const char_type dot = '.';
+ static const char_type newline = '\n';
+
+ static bool is_digit(char c) { return (isdigit(c) != 0); }
+ static std::string default_file_name_pattern() { return "%5N.log"; }
+ };
+
+#ifndef BOOST_LOG_BROKEN_STATIC_CONSTANTS_LINKAGE
+ const file_char_traits< char >::char_type file_char_traits< char >::percent;
+ const file_char_traits< char >::char_type file_char_traits< char >::number_placeholder;
+ const file_char_traits< char >::char_type file_char_traits< char >::day_placeholder;
+ const file_char_traits< char >::char_type file_char_traits< char >::month_placeholder;
+ const file_char_traits< char >::char_type file_char_traits< char >::year_placeholder;
+ const file_char_traits< char >::char_type file_char_traits< char >::full_year_placeholder;
+ const file_char_traits< char >::char_type file_char_traits< char >::frac_sec_placeholder;
+ const file_char_traits< char >::char_type file_char_traits< char >::seconds_placeholder;
+ const file_char_traits< char >::char_type file_char_traits< char >::minutes_placeholder;
+ const file_char_traits< char >::char_type file_char_traits< char >::hours_placeholder;
+ const file_char_traits< char >::char_type file_char_traits< char >::space;
+ const file_char_traits< char >::char_type file_char_traits< char >::plus;
+ const file_char_traits< char >::char_type file_char_traits< char >::minus;
+ const file_char_traits< char >::char_type file_char_traits< char >::zero;
+ const file_char_traits< char >::char_type file_char_traits< char >::dot;
+ const file_char_traits< char >::char_type file_char_traits< char >::newline;
+#endif // BOOST_LOG_BROKEN_STATIC_CONSTANTS_LINKAGE
+
+ template< >
+ struct file_char_traits< wchar_t >
+ {
+ typedef wchar_t char_type;
+
+ static const char_type percent = L'%';
+ static const char_type number_placeholder = L'N';
+ static const char_type day_placeholder = L'd';
+ static const char_type month_placeholder = L'm';
+ static const char_type year_placeholder = L'y';
+ static const char_type full_year_placeholder = L'Y';
+ static const char_type frac_sec_placeholder = L'f';
+ static const char_type seconds_placeholder = L'S';
+ static const char_type minutes_placeholder = L'M';
+ static const char_type hours_placeholder = L'H';
+ static const char_type space = L' ';
+ static const char_type plus = L'+';
+ static const char_type minus = L'-';
+ static const char_type zero = L'0';
+ static const char_type dot = L'.';
+ static const char_type newline = L'\n';
+
+ static bool is_digit(wchar_t c) { return (iswdigit(c) != 0); }
+ static std::wstring default_file_name_pattern() { return L"%5N.log"; }
+ };
+
+#ifndef BOOST_LOG_BROKEN_STATIC_CONSTANTS_LINKAGE
+ const file_char_traits< wchar_t >::char_type file_char_traits< wchar_t >::percent;
+ const file_char_traits< wchar_t >::char_type file_char_traits< wchar_t >::number_placeholder;
+ const file_char_traits< wchar_t >::char_type file_char_traits< wchar_t >::day_placeholder;
+ const file_char_traits< wchar_t >::char_type file_char_traits< wchar_t >::month_placeholder;
+ const file_char_traits< wchar_t >::char_type file_char_traits< wchar_t >::year_placeholder;
+ const file_char_traits< wchar_t >::char_type file_char_traits< wchar_t >::full_year_placeholder;
+ const file_char_traits< wchar_t >::char_type file_char_traits< wchar_t >::frac_sec_placeholder;
+ const file_char_traits< wchar_t >::char_type file_char_traits< wchar_t >::seconds_placeholder;
+ const file_char_traits< wchar_t >::char_type file_char_traits< wchar_t >::minutes_placeholder;
+ const file_char_traits< wchar_t >::char_type file_char_traits< wchar_t >::hours_placeholder;
+ const file_char_traits< wchar_t >::char_type file_char_traits< wchar_t >::space;
+ const file_char_traits< wchar_t >::char_type file_char_traits< wchar_t >::plus;
+ const file_char_traits< wchar_t >::char_type file_char_traits< wchar_t >::minus;
+ const file_char_traits< wchar_t >::char_type file_char_traits< wchar_t >::zero;
+ const file_char_traits< wchar_t >::char_type file_char_traits< wchar_t >::dot;
+ const file_char_traits< wchar_t >::char_type file_char_traits< wchar_t >::newline;
+#endif // BOOST_LOG_BROKEN_STATIC_CONSTANTS_LINKAGE
+
+ //! Date and time formatter
+ class date_and_time_formatter
+ {
+ public:
+ typedef path_string_type result_type;
+
+ private:
+ typedef date_time::time_facet< posix_time::ptime, path_char_type > time_facet_type;
+
+ private:
+ time_facet_type* m_pFacet;
+ mutable std::basic_ostringstream< path_char_type > m_Stream;
+
+ public:
+ //! Constructor
+ date_and_time_formatter() : m_pFacet(NULL)
+ {
+ std::auto_ptr< time_facet_type > pFacet(new time_facet_type());
+ m_pFacet = pFacet.get();
+ std::locale loc(m_Stream.getloc(), m_pFacet);
+ pFacet.release();
+ m_Stream.imbue(loc);
+ }
+ //! Copy constructor
+ date_and_time_formatter(date_and_time_formatter const& that) :
+ m_pFacet(that.m_pFacet)
+ {
+ m_Stream.imbue(that.m_Stream.getloc());
+ }
+ //! The method formats the current date and time according to the format string str and writes the result into it
+ path_string_type operator()(path_string_type const& pattern, unsigned int counter) const
+ {
+ m_pFacet->format(pattern.c_str());
+ m_Stream.str(path_string_type());
+ m_Stream << boost::log::attributes::local_time_traits::get_clock();
+ if (m_Stream.good())
+ {
+ return m_Stream.str();
+ }
+ else
+ {
+ m_Stream.clear();
+ return pattern;
+ }
+ }
+ };
+
+ //! The functor formats the file counter into the file name
+ class file_counter_formatter
+ {
+ public:
+ typedef path_string_type result_type;
+
+ private:
+ //! The position in the pattern where the file counter placeholder is
+ path_string_type::size_type m_FileCounterPosition;
+ //! File counter width
+ std::streamsize m_Width;
+ //! The file counter formatting stream
+ mutable std::basic_ostringstream< path_char_type > m_Stream;
+
+ public:
+ //! Initializing constructor
+ file_counter_formatter(path_string_type::size_type pos, unsigned int width) :
+ m_FileCounterPosition(pos),
+ m_Width(width)
+ {
+ typedef file_char_traits< path_char_type > traits_t;
+ m_Stream.fill(traits_t::zero);
+ }
+ //! Copy constructor
+ file_counter_formatter(file_counter_formatter const& that) :
+ m_FileCounterPosition(that.m_FileCounterPosition),
+ m_Width(that.m_Width)
+ {
+ m_Stream.fill(that.m_Stream.fill());
+ }
+
+ //! The function formats the file counter into the file name
+ path_string_type operator()(path_string_type const& pattern, unsigned int counter) const
+ {
+ path_string_type file_name = pattern;
+
+ m_Stream.str(path_string_type());
+ m_Stream.width(m_Width);
+ m_Stream << counter;
+ file_name.insert(m_FileCounterPosition, m_Stream.str());
+
+ return file_name;
+ }
+ };
+
+ //! The function returns the pattern as the file name
+ class empty_formatter
+ {
+ public:
+ typedef path_string_type result_type;
+
+ private:
+ path_string_type m_Pattern;
+
+ public:
+ //! Initializing constructor
+ explicit empty_formatter(path_string_type const& pattern) : m_Pattern(pattern)
+ {
+ }
+ //! Copy constructor
+ empty_formatter(empty_formatter const& that) : m_Pattern(that.m_Pattern)
+ {
+ }
+
+ //! The function returns the pattern as the file name
+ path_string_type const& operator() (unsigned int) const
+ {
+ return m_Pattern;
+ }
+ };
+
+ //! The function parses the format placeholder for file counter
+ bool parse_counter_placeholder(path_string_type::const_iterator& it, path_string_type::const_iterator end, unsigned int& width)
+ {
+ typedef file_char_traits< path_char_type > traits_t;
+ return qi::parse
+ (
+ it, end,
+ (
+ -(
+ qi::lit(traits_t::zero) |
+ qi::lit(traits_t::plus) |
+ qi::lit(traits_t::minus) |
+ qi::lit(traits_t::space)
+ ) >>
+ -(qi::uint_[boost::log::as_action(boost::log::bind_assign(width))]) >>
+ -(qi::lit(traits_t::dot) >> qi::uint_) >>
+ qi::lit(traits_t::number_placeholder)
+ )
+ );
+ }
+
+ //! The function matches the file name and the pattern
+ bool match_pattern(path_string_type const& file_name, path_string_type const& pattern, unsigned int& file_counter)
+ {
+ typedef file_char_traits< path_char_type > traits_t;
+
+ struct local
+ {
+ // Verifies that the string contains exactly n digits
+ static bool scan_digits(path_string_type::const_iterator& it, path_string_type::const_iterator end, std::ptrdiff_t n)
+ {
+ for (; n > 0; --n)
+ {
+ path_char_type c = *it++;
+ if (!traits_t::is_digit(c) || it == end)
+ return false;
+ }
+ return true;
+ }
+ };
+
+ path_string_type::const_iterator
+ f_it = file_name.begin(),
+ f_end = file_name.end(),
+ p_it = pattern.begin(),
+ p_end = pattern.end();
+ bool placeholder_expected = false;
+ while (f_it != f_end && p_it != p_end)
+ {
+ path_char_type p_c = *p_it, f_c = *f_it;
+ if (!placeholder_expected)
+ {
+ if (p_c == traits_t::percent)
+ {
+ placeholder_expected = true;
+ ++p_it;
+ }
+ else if (p_c == f_c)
+ {
+ ++p_it;
+ ++f_it;
+ }
+ else
+ return false;
+ }
+ else
+ {
+ switch (p_c)
+ {
+ case traits_t::percent: // An escaped '%'
+ if (p_c == f_c)
+ {
+ ++p_it;
+ ++f_it;
+ break;
+ }
+ else
+ return false;
+
+ case traits_t::seconds_placeholder: // Date/time components with 2-digits width
+ case traits_t::minutes_placeholder:
+ case traits_t::hours_placeholder:
+ case traits_t::day_placeholder:
+ case traits_t::month_placeholder:
+ case traits_t::year_placeholder:
+ if (!local::scan_digits(f_it, f_end, 2))
+ return false;
+ ++p_it;
+ break;
+
+ case traits_t::full_year_placeholder: // Date/time components with 4-digits width
+ if (!local::scan_digits(f_it, f_end, 4))
+ return false;
+ ++p_it;
+ break;
+
+ case traits_t::frac_sec_placeholder: // Fraction seconds width is configuration-dependent
+ typedef posix_time::time_res_traits posix_resolution_traits;
+ if (!local::scan_digits(f_it, f_end, posix_resolution_traits::num_fractional_digits()))
+ {
+ return false;
+ }
+ ++p_it;
+ break;
+
+ default: // This should be the file counter placeholder or some unsupported placeholder
+ {
+ path_string_type::const_iterator p = p_it;
+ unsigned int width = 0;
+ if (!parse_counter_placeholder(p, p_end, width))
+ {
+ BOOST_LOG_THROW_DESCR(invalid_value, "Unsupported placeholder used in pattern for file scanning");
+ }
+
+ // Find where the file number ends
+ path_string_type::const_iterator f = f_it;
+ if (!local::scan_digits(f, f_end, width))
+ return false;
+ for (; f != f_end && traits_t::is_digit(*f); ++f);
+
+ if (!qi::parse(f_it, f, qi::uint_, file_counter))
+ return false;
+
+ p_it = p;
+ }
+ break;
+ }
+
+ placeholder_expected = false;
+ }
+ }
+
+ if (p_it == p_end)
+ {
+ if (f_it != f_end)
+ {
+ // The actual file name may end with an additional counter
+ // that is added by the collector in case if file name clash
+ return local::scan_digits(f_it, f_end, std::distance(f_it, f_end));
+ }
+ else
+ return true;
+ }
+ else
+ return false;
+ }
+
+
+ class file_collector_repository;
+
+ //! Type of the hook used for sequencing file collectors
+ typedef intrusive::list_base_hook<
+ intrusive::link_mode< intrusive::safe_link >
+ > file_collector_hook;
+
+ //! Log file collector implementation
+ class file_collector :
+ public file::collector,
+ public file_collector_hook,
+ public enable_shared_from_this< file_collector >
+ {
+ private:
+ //! Information about a single stored file
+ struct file_info
+ {
+ uintmax_t m_Size;
+ std::time_t m_TimeStamp;
+ filesystem::path m_Path;
+ };
+ //! A list of the stored files
+ typedef std::list< file_info > file_list;
+ //! The string type compatible with the universal path type
+ typedef filesystem::path::string_type path_string_type;
+
+ private:
+ //! A reference to the repository this collector belongs to
+ shared_ptr< file_collector_repository > m_pRepository;
+
+#if !defined(BOOST_LOG_NO_THREADS)
+ //! Synchronization mutex
+ mutex m_Mutex;
+#endif // !defined(BOOST_LOG_NO_THREADS)
+
+ //! Total file size upper limit
+ uintmax_t m_MaxSize;
+ //! Free space lower limit
+ uintmax_t m_MinFreeSpace;
+ //! The current path at the point when the collector is created
+ /*
+ * The special member is required to calculate absolute paths with no
+ * dependency on the current path for the application, which may change
+ */
+ const filesystem::path m_BasePath;
+ //! Target directory to store files to
+ filesystem::path m_StorageDir;
+
+ //! The list of stored files
+ file_list m_Files;
+ //! Total size of the stored files
+ uintmax_t m_TotalSize;
+
+ public:
+ //! Constructor
+ file_collector(
+ shared_ptr< file_collector_repository > const& repo,
+ filesystem::path const& target_dir,
+ uintmax_t max_size,
+ uintmax_t min_free_space);
+
+ //! Destructor
+ ~file_collector();
+
+ //! The function stores the specified file in the storage
+ void store_file(filesystem::path const& file_name);
+
+ //! Scans the target directory for the files that have already been stored
+ uintmax_t scan_for_files(
+ file::scan_method method, filesystem::path const& pattern, unsigned int* counter);
+
+ //! The function updates storage restrictions
+ void update(uintmax_t max_size, uintmax_t min_free_space);
+
+ //! The function checks if the directory is governed by this collector
+ bool is_governed(filesystem::path const& dir) const
+ {
+ return filesystem::equivalent(m_StorageDir, dir);
+ }
+
+ private:
+ //! Makes relative path absolute with respect to the base path
+ filesystem::path make_absolute(filesystem::path const& p)
+ {
+ return filesystem::absolute(p, m_BasePath);
+ }
+ //! Acquires file name string from the path
+ static path_string_type filename_string(filesystem::path const& p)
+ {
+ return p.filename().string< path_string_type >();
+ }
+ };
+
+
+ //! The singleton of the list of file collectors
+ class file_collector_repository :
+ public log::aux::lazy_singleton< file_collector_repository, shared_ptr< file_collector_repository > >
+ {
+ private:
+ //! Base type
+ typedef log::aux::lazy_singleton< file_collector_repository, shared_ptr< file_collector_repository > > base_type;
+
+#if !defined(BOOST_LOG_BROKEN_FRIEND_TEMPLATE_INSTANTIATIONS)
+ friend class log::aux::lazy_singleton< file_collector_repository, shared_ptr< file_collector_repository > >;
+#else
+ friend class base_type;
+#endif
+
+ //! The type of the list of collectors
+ typedef intrusive::list<
+ file_collector,
+ intrusive::base_hook< file_collector_hook >
+ > file_collectors;
+
+ private:
+#if !defined(BOOST_LOG_NO_THREADS)
+ //! Synchronization mutex
+ mutex m_Mutex;
+#endif // !defined(BOOST_LOG_NO_THREADS)
+ //! The list of file collectors
+ file_collectors m_Collectors;
+
+ public:
+ //! Finds or creates a file collector
+ shared_ptr< file::collector > get_collector(
+ filesystem::path const& target_dir, uintmax_t max_size, uintmax_t min_free_space);
+
+ //! Removes the file collector from the list
+ void remove_collector(file_collector* p);
+
+ private:
+ //! Initializes the singleton instance
+ static void init_instance()
+ {
+ base_type::get_instance() = boost::make_shared< file_collector_repository >();
+ }
+ };
+
+ //! Constructor
+ file_collector::file_collector(
+ shared_ptr< file_collector_repository > const& repo,
+ filesystem::path const& target_dir,
+ uintmax_t max_size,
+ uintmax_t min_free_space
+ ) :
+ m_pRepository(repo),
+ m_MaxSize(max_size),
+ m_MinFreeSpace(min_free_space),
+ m_BasePath(filesystem::current_path()),
+ m_TotalSize(0)
+ {
+ m_StorageDir = make_absolute(target_dir);
+ filesystem::create_directories(m_StorageDir);
+ }
+
+ //! Destructor
+ file_collector::~file_collector()
+ {
+ m_pRepository->remove_collector(this);
+ }
+
+ //! The function stores the specified file in the storage
+ void file_collector::store_file(filesystem::path const& src_path)
+ {
+ // Let's construct the new file name
+ file_info info;
+ info.m_TimeStamp = filesystem::last_write_time(src_path);
+ info.m_Size = filesystem::file_size(src_path);
+
+ path_string_type file_name = filename_string(src_path);
+ info.m_Path = m_StorageDir / file_name;
+
+ // Check if the file is already in the target directory
+ filesystem::path src_dir = src_path.has_parent_path() ?
+ filesystem::system_complete(src_path.parent_path()) :
+ m_BasePath;
+ const bool is_in_target_dir = filesystem::equivalent(src_dir, m_StorageDir);
+ if (!is_in_target_dir)
+ {
+ if (filesystem::exists(info.m_Path))
+ {
+ // If the file already exists, try to mangle the file name
+ // to ensure there's no conflict. I'll need to make this customizable some day.
+ file_counter_formatter formatter(file_name.size(), 5);
+ unsigned int n = 0;
+ do
+ {
+ path_string_type alt_file_name = formatter(file_name, n++);
+ info.m_Path = m_StorageDir / alt_file_name;
+ }
+ while (filesystem::exists(info.m_Path) && n < (std::numeric_limits< unsigned int >::max)());
+ }
+
+ // The directory should have been created in constructor, but just in case it got deleted since then...
+ filesystem::create_directories(m_StorageDir);
+ }
+
+ BOOST_LOG_EXPR_IF_MT(lock_guard< mutex > lock(m_Mutex);)
+
+ // Check if an old file should be erased
+ uintmax_t free_space = m_MinFreeSpace ? filesystem::space(m_StorageDir).available : static_cast< uintmax_t >(0);
+ file_list::iterator it = m_Files.begin(), end = m_Files.end();
+ while (it != end &&
+ (m_TotalSize + info.m_Size > m_MaxSize || (m_MinFreeSpace && m_MinFreeSpace > free_space)))
+ {
+ file_info& old_info = *it;
+ if (filesystem::exists(old_info.m_Path) && filesystem::is_regular_file(old_info.m_Path))
+ {
+ try
+ {
+ filesystem::remove(old_info.m_Path);
+ // Free space has to be queried as it may not increase equally
+ // to the erased file size on compressed filesystems
+ if (m_MinFreeSpace)
+ free_space = filesystem::space(m_StorageDir).available;
+ m_TotalSize -= old_info.m_Size;
+ m_Files.erase(it++);
+ }
+ catch (system::system_error&)
+ {
+ // Can't erase the file. Maybe it's locked? Never mind...
+ ++it;
+ }
+ }
+ else
+ {
+ // If it's not a file or is absent, just remove it from the list
+ m_TotalSize -= old_info.m_Size;
+ m_Files.erase(it++);
+ }
+ }
+
+ if (!is_in_target_dir)
+ {
+ // Move/rename the file to the target storage
+ move_file(src_path, info.m_Path);
+ }
+
+ m_Files.push_back(info);
+ m_TotalSize += info.m_Size;
+ }
+
+ //! Scans the target directory for the files that have already been stored
+ uintmax_t file_collector::scan_for_files(
+ file::scan_method method, filesystem::path const& pattern, unsigned int* counter)
+ {
+ uintmax_t file_count = 0;
+ if (method != file::no_scan)
+ {
+ filesystem::path dir = m_StorageDir;
+ path_string_type mask;
+ if (method == file::scan_matching)
+ {
+ mask = filename_string(pattern);
+ if (pattern.has_parent_path())
+ dir = make_absolute(pattern.parent_path());
+ }
+ else
+ {
+ counter = NULL;
+ }
+
+ if (filesystem::exists(dir) && filesystem::is_directory(dir))
+ {
+ BOOST_LOG_EXPR_IF_MT(lock_guard< mutex > lock(m_Mutex);)
+
+ if (counter)
+ *counter = 0;
+
+ file_list files;
+ filesystem::directory_iterator it(dir), end;
+ uintmax_t total_size = 0;
+ for (; it != end; ++it)
+ {
+ file_info info;
+ info.m_Path = *it;
+ if (filesystem::is_regular_file(info.m_Path))
+ {
+ // Check that there are no duplicates in the resulting list
+ struct local
+ {
+ static bool equivalent(filesystem::path const& left, file_info const& right)
+ {
+ return filesystem::equivalent(left, right.m_Path);
+ }
+ };
+ if (std::find_if(m_Files.begin(), m_Files.end(),
+ boost::bind(&local::equivalent, boost::cref(info.m_Path), _1)) == m_Files.end())
+ {
+ // Check that the file name matches the pattern
+ unsigned int file_number = 0;
+ if (method != file::scan_matching ||
+ match_pattern(filename_string(info.m_Path), mask, file_number))
+ {
+ info.m_Size = filesystem::file_size(info.m_Path);
+ total_size += info.m_Size;
+ info.m_TimeStamp = filesystem::last_write_time(info.m_Path);
+ files.push_back(info);
+ ++file_count;
+
+ if (counter && file_number >= *counter)
+ *counter = file_number + 1;
+ }
+ }
+ }
+ }
+
+ // Sort files chronologically
+ m_Files.splice(m_Files.end(), files);
+ m_TotalSize += total_size;
+ m_Files.sort(boost::bind(&file_info::m_TimeStamp, _1) < boost::bind(&file_info::m_TimeStamp, _2));
+ }
+ }
+
+ return file_count;
+ }
+
+ //! The function updates storage restrictions
+ void file_collector::update(uintmax_t max_size, uintmax_t min_free_space)
+ {
+ BOOST_LOG_EXPR_IF_MT(lock_guard< mutex > lock(m_Mutex);)
+
+ m_MaxSize = (std::min)(m_MaxSize, max_size);
+ m_MinFreeSpace = (std::max)(m_MinFreeSpace, min_free_space);
+ }
+
+
+ //! Finds or creates a file collector
+ shared_ptr< file::collector > file_collector_repository::get_collector(
+ filesystem::path const& target_dir, uintmax_t max_size, uintmax_t min_free_space)
+ {
+ BOOST_LOG_EXPR_IF_MT(lock_guard< mutex > lock(m_Mutex);)
+
+ file_collectors::iterator it = std::find_if(m_Collectors.begin(), m_Collectors.end(),
+ boost::bind(&file_collector::is_governed, _1, boost::cref(target_dir)));
+ shared_ptr< file_collector > p;
+ if (it != m_Collectors.end()) try
+ {
+ // This may throw if the collector is being currently destroyed
+ p = it->shared_from_this();
+ p->update(max_size, min_free_space);
+ }
+ catch (bad_weak_ptr&)
+ {
+ }
+
+ if (!p)
+ {
+ p = boost::make_shared< file_collector >(
+ file_collector_repository::get(), target_dir, max_size, min_free_space);
+ m_Collectors.push_back(*p);
+ }
+
+ return p;
+ }
+
+ //! Removes the file collector from the list
+ void file_collector_repository::remove_collector(file_collector* p)
+ {
+ BOOST_LOG_EXPR_IF_MT(lock_guard< mutex > lock(m_Mutex);)
+ m_Collectors.erase(m_Collectors.iterator_to(*p));
+ }
+
+ //! Checks if the time point is valid
+ void check_time_point_validity(unsigned char hour, unsigned char minute, unsigned char second)
+ {
+ if (hour >= 24)
+ {
+ std::ostringstream strm;
+ strm << "Time point hours value is out of range: " << static_cast< unsigned int >(hour);
+ BOOST_THROW_EXCEPTION(std::out_of_range(strm.str()));
+ }
+ if (minute >= 60)
+ {
+ std::ostringstream strm;
+ strm << "Time point minutes value is out of range: " << static_cast< unsigned int >(minute);
+ BOOST_THROW_EXCEPTION(std::out_of_range(strm.str()));
+ }
+ if (second >= 60)
+ {
+ std::ostringstream strm;
+ strm << "Time point seconds value is out of range: " << static_cast< unsigned int >(second);
+ BOOST_THROW_EXCEPTION(std::out_of_range(strm.str()));
+ }
+ }
+
+} // namespace
+
+namespace file {
+
+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)
+ {
+ return file_collector_repository::get()->get_collector(target_dir, max_size, min_free_space);
+ }
+
+} // namespace aux
+
+//! Creates a rotation time point of every day at the specified time
+BOOST_LOG_API rotation_at_time_point::rotation_at_time_point(
+ unsigned char hour,
+ unsigned char minute,
+ unsigned char second
+) :
+ m_DayKind(not_specified),
+ m_Day(0),
+ m_Hour(hour),
+ m_Minute(minute),
+ m_Second(second),
+ m_Previous(date_time::not_a_date_time)
+{
+ check_time_point_validity(hour, minute, second);
+}
+
+//! Creates a rotation time point of each specified weekday at the specified time
+BOOST_LOG_API rotation_at_time_point::rotation_at_time_point(
+ date_time::weekdays wday,
+ unsigned char hour,
+ unsigned char minute,
+ unsigned char second
+) :
+ m_DayKind(weekday),
+ m_Day(static_cast< unsigned char >(wday)),
+ m_Hour(hour),
+ m_Minute(minute),
+ m_Second(second),
+ m_Previous(date_time::not_a_date_time)
+{
+ check_time_point_validity(hour, minute, second);
+}
+
+//! Creates a rotation time point of each specified day of month at the specified time
+BOOST_LOG_API rotation_at_time_point::rotation_at_time_point(
+ gregorian::greg_day mday,
+ unsigned char hour,
+ unsigned char minute,
+ unsigned char second
+) :
+ m_DayKind(monthday),
+ m_Day(static_cast< unsigned char >(mday.as_number())),
+ m_Hour(hour),
+ m_Minute(minute),
+ m_Second(second),
+ m_Previous(date_time::not_a_date_time)
+{
+ check_time_point_validity(hour, minute, second);
+}
+
+//! Checks if it's time to rotate the file
+BOOST_LOG_API bool rotation_at_time_point::operator()() const
+{
+ bool result = false;
+ posix_time::time_duration rotation_time(
+ static_cast< posix_time::time_duration::hour_type >(m_Hour),
+ static_cast< posix_time::time_duration::min_type >(m_Minute),
+ static_cast< posix_time::time_duration::sec_type >(m_Second));
+ posix_time::ptime now = posix_time::second_clock::local_time();
+
+ if (m_Previous.is_special())
+ {
+ m_Previous = now;
+ return false;
+ }
+
+ const bool time_of_day_passed = rotation_time.total_seconds() <= m_Previous.time_of_day().total_seconds();
+ switch (m_DayKind)
+ {
+ case not_specified:
+ {
+ // The rotation takes place every day at the specified time
+ gregorian::date previous_date = m_Previous.date();
+ if (time_of_day_passed)
+ previous_date += gregorian::days(1);
+ posix_time::ptime next(previous_date, rotation_time);
+ result = (now >= next);
+ }
+ break;
+
+ case weekday:
+ {
+ // The rotation takes place on the specified week day at the specified time
+ gregorian::date previous_date = m_Previous.date(), next_date = previous_date;
+ int weekday = m_Day, previous_weekday = static_cast< int >(previous_date.day_of_week().as_number());
+ next_date += gregorian::days(weekday - previous_weekday);
+ if (weekday < previous_weekday || (weekday == previous_weekday && time_of_day_passed))
+ {
+ next_date += gregorian::weeks(1);
+ }
+
+ posix_time::ptime next(next_date, rotation_time);
+ result = (now >= next);
+ }
+ break;
+
+ case monthday:
+ {
+ // The rotation takes place on the specified day of month at the specified time
+ gregorian::date previous_date = m_Previous.date();
+ gregorian::date::day_type monthday = static_cast< gregorian::date::day_type >(m_Day),
+ previous_monthday = previous_date.day();
+ gregorian::date next_date(previous_date.year(), previous_date.month(), monthday);
+ if (monthday < previous_monthday || (monthday == previous_monthday && time_of_day_passed))
+ {
+ next_date += gregorian::months(1);
+ }
+
+ posix_time::ptime next(next_date, rotation_time);
+ result = (now >= next);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (result)
+ m_Previous = now;
+
+ return result;
+}
+
+//! Checks if it's time to rotate the file
+BOOST_LOG_API bool rotation_at_time_interval::operator()() const
+{
+ bool result = false;
+ posix_time::ptime now = posix_time::second_clock::universal_time();
+ if (m_Previous.is_special())
+ {
+ m_Previous = now;
+ return false;
+ }
+
+ result = (now - m_Previous) >= m_Interval;
+
+ if (result)
+ m_Previous = now;
+
+ return result;
+}
+
+} // namespace file
+
+////////////////////////////////////////////////////////////////////////////////
+// File sink backend implementation
+////////////////////////////////////////////////////////////////////////////////
+//! Sink implementation data
+struct text_file_backend::implementation
+{
+ //! File open mode
+ std::ios_base::openmode m_FileOpenMode;
+
+ //! File name pattern
+ filesystem::path m_FileNamePattern;
+ //! Directory to store files in
+ filesystem::path m_StorageDir;
+ //! File name generator (according to m_FileNamePattern)
+ boost::log::aux::light_function< path_string_type (unsigned int) > m_FileNameGenerator;
+
+ //! Stored files counter
+ unsigned int m_FileCounter;
+
+ //! Current file name
+ filesystem::path m_FileName;
+ //! File stream
+ filesystem::ofstream m_File;
+ //! Characters written
+ uintmax_t m_CharactersWritten;
+
+ //! File collector functional object
+ shared_ptr< file::collector > m_pFileCollector;
+ //! File open handler
+ open_handler_type m_OpenHandler;
+ //! File close handler
+ close_handler_type m_CloseHandler;
+
+ //! The maximum temp file size, in characters written to the stream
+ uintmax_t m_FileRotationSize;
+ //! Time-based rotation predicate
+ time_based_rotation_predicate m_TimeBasedRotation;
+ //! The flag shows if every written record should be flushed
+ bool m_AutoFlush;
+
+ implementation(uintmax_t rotation_size, bool auto_flush) :
+ m_FileOpenMode(std::ios_base::trunc | std::ios_base::out),
+ m_FileCounter(0),
+ m_CharactersWritten(0),
+ m_FileRotationSize(rotation_size),
+ m_AutoFlush(auto_flush)
+ {
+ }
+};
+
+//! Constructor. No streams attached to the constructed backend, auto flush feature disabled.
+BOOST_LOG_API text_file_backend::text_file_backend()
+{
+ construct(log::aux::empty_arg_list());
+}
+
+//! Destructor
+BOOST_LOG_API text_file_backend::~text_file_backend()
+{
+ try
+ {
+ // Attempt to put the temporary file into storage
+ if (m_pImpl->m_File.is_open() && m_pImpl->m_CharactersWritten > 0)
+ rotate_file();
+ }
+ catch (...)
+ {
+ }
+
+ delete m_pImpl;
+}
+
+//! Constructor implementation
+BOOST_LOG_API void text_file_backend::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)
+{
+ m_pImpl = new implementation(rotation_size, auto_flush);
+ set_file_name_pattern_internal(pattern);
+ set_time_based_rotation(time_based_rotation);
+ set_open_mode(mode);
+}
+
+//! The method sets maximum file size.
+BOOST_LOG_API void text_file_backend::set_rotation_size(uintmax_t size)
+{
+ m_pImpl->m_FileRotationSize = size;
+}
+
+//! The method sets the maximum time interval between file rotations.
+BOOST_LOG_API void text_file_backend::set_time_based_rotation(time_based_rotation_predicate const& predicate)
+{
+ m_pImpl->m_TimeBasedRotation = predicate;
+}
+
+//! Sets the flag to automatically flush buffers of all attached streams after each log record
+BOOST_LOG_API void text_file_backend::auto_flush(bool f)
+{
+ m_pImpl->m_AutoFlush = f;
+}
+
+//! The method writes the message to the sink
+BOOST_LOG_API void text_file_backend::consume(record_view const& rec, string_type const& formatted_message)
+{
+ typedef file_char_traits< string_type::value_type > traits_t;
+ if
+ (
+ (
+ m_pImpl->m_File.is_open() &&
+ (
+ m_pImpl->m_CharactersWritten + formatted_message.size() >= m_pImpl->m_FileRotationSize ||
+ (!m_pImpl->m_TimeBasedRotation.empty() && m_pImpl->m_TimeBasedRotation())
+ )
+ ) ||
+ !m_pImpl->m_File.good()
+ )
+ {
+ rotate_file();
+ }
+
+ if (!m_pImpl->m_File.is_open())
+ {
+ m_pImpl->m_FileName = m_pImpl->m_StorageDir / m_pImpl->m_FileNameGenerator(m_pImpl->m_FileCounter++);
+
+ filesystem::create_directories(m_pImpl->m_FileName.parent_path());
+ m_pImpl->m_File.open(m_pImpl->m_FileName, m_pImpl->m_FileOpenMode);
+ if (!m_pImpl->m_File.is_open())
+ {
+ filesystem_error err(
+ "Failed to open file for writing",
+ m_pImpl->m_FileName,
+ system::error_code(system::errc::io_error, system::generic_category()));
+ BOOST_THROW_EXCEPTION(err);
+ }
+
+ if (!m_pImpl->m_OpenHandler.empty())
+ m_pImpl->m_OpenHandler(m_pImpl->m_File);
+
+ m_pImpl->m_CharactersWritten = static_cast< std::streamoff >(m_pImpl->m_File.tellp());
+ }
+
+ m_pImpl->m_File.write(formatted_message.data(), static_cast< std::streamsize >(formatted_message.size()));
+ m_pImpl->m_File.put(traits_t::newline);
+
+ m_pImpl->m_CharactersWritten += formatted_message.size() + 1;
+
+ if (m_pImpl->m_AutoFlush)
+ m_pImpl->m_File.flush();
+}
+
+//! The method flushes the currently open log file
+BOOST_LOG_API void text_file_backend::flush()
+{
+ if (m_pImpl->m_File.is_open())
+ m_pImpl->m_File.flush();
+}
+
+//! The method sets file name mask
+BOOST_LOG_API void text_file_backend::set_file_name_pattern_internal(filesystem::path const& pattern)
+{
+ typedef file_char_traits< path_char_type > traits_t;
+ filesystem::path p = pattern;
+ if (p.empty())
+ p = traits_t::default_file_name_pattern();
+
+ path_string_type name_pattern = p.filename().string< path_string_type >();
+ m_pImpl->m_FileNamePattern = name_pattern;
+ m_pImpl->m_StorageDir = filesystem::absolute(p.parent_path());
+
+ // Let's try to find the file counter placeholder
+ unsigned int placeholder_count = 0;
+ unsigned int width = 0;
+ bool counter_found = false;
+ path_string_type::size_type counter_pos = 0;
+ path_string_type::const_iterator end = name_pattern.end();
+ path_string_type::const_iterator it = name_pattern.begin();
+
+ do
+ {
+ it = std::find(it, end, traits_t::percent);
+ if (it == end)
+ break;
+ path_string_type::const_iterator placeholder_begin = it++;
+ if (it == end)
+ break;
+ if (*it == traits_t::percent)
+ {
+ // An escaped percent detected
+ ++it;
+ continue;
+ }
+
+ ++placeholder_count;
+
+ if (!counter_found && parse_counter_placeholder(it, end, width))
+ {
+ // We've found the file counter placeholder in the pattern
+ counter_found = true;
+ counter_pos = placeholder_begin - name_pattern.begin();
+ name_pattern.erase(counter_pos, it - placeholder_begin);
+ --placeholder_count;
+ it = name_pattern.begin() + counter_pos;
+ end = name_pattern.end();
+ }
+ }
+ while (it != end);
+
+ // Construct the formatter functor
+ unsigned int choice = (static_cast< unsigned int >(placeholder_count > 0) << 1) |
+ static_cast< unsigned int >(counter_found);
+ switch (choice)
+ {
+ case 1: // Only counter placeholder in the pattern
+ m_pImpl->m_FileNameGenerator =
+ boost::bind(file_counter_formatter(counter_pos, width), name_pattern, _1);
+ break;
+ case 2: // Only date/time placeholders in the pattern
+ m_pImpl->m_FileNameGenerator =
+ boost::bind(date_and_time_formatter(), name_pattern, _1);
+ break;
+ case 3: // Counter and date/time placeholder in the pattern
+ m_pImpl->m_FileNameGenerator = boost::bind(date_and_time_formatter(),
+ boost::bind(file_counter_formatter(counter_pos, width), name_pattern, _1), _1);
+ break;
+ default: // No placeholders detected
+ m_pImpl->m_FileNameGenerator = empty_formatter(name_pattern);
+ break;
+ }
+}
+
+//! The method rotates the file
+BOOST_LOG_API void text_file_backend::rotate_file()
+{
+ if (!m_pImpl->m_CloseHandler.empty())
+ m_pImpl->m_CloseHandler(m_pImpl->m_File);
+ m_pImpl->m_File.close();
+ m_pImpl->m_File.clear();
+ m_pImpl->m_CharactersWritten = 0;
+ if (!!m_pImpl->m_pFileCollector)
+ m_pImpl->m_pFileCollector->store_file(m_pImpl->m_FileName);
+}
+
+//! The method sets the file open mode
+BOOST_LOG_API void text_file_backend::set_open_mode(std::ios_base::openmode mode)
+{
+ mode |= std::ios_base::out;
+ mode &= ~std::ios_base::in;
+ if ((mode & (std::ios_base::trunc | std::ios_base::app)) == 0)
+ mode |= std::ios_base::trunc;
+ m_pImpl->m_FileOpenMode = mode;
+}
+
+//! The method sets file collector
+BOOST_LOG_API void text_file_backend::set_file_collector(shared_ptr< file::collector > const& collector)
+{
+ m_pImpl->m_pFileCollector = collector;
+}
+
+//! The method sets file open handler
+BOOST_LOG_API void text_file_backend::set_open_handler(open_handler_type const& handler)
+{
+ m_pImpl->m_OpenHandler = handler;
+}
+
+//! The method sets file close handler
+BOOST_LOG_API void text_file_backend::set_close_handler(close_handler_type const& handler)
+{
+ m_pImpl->m_CloseHandler = handler;
+}
+
+//! Performs scanning of the target directory for log files
+BOOST_LOG_API uintmax_t text_file_backend::scan_for_files(file::scan_method method, bool update_counter)
+{
+ if (m_pImpl->m_pFileCollector)
+ {
+ unsigned int* counter = update_counter ? &m_pImpl->m_FileCounter : static_cast< unsigned int* >(NULL);
+ return m_pImpl->m_pFileCollector->scan_for_files(method, m_pImpl->m_FileNamePattern, counter);
+ }
+ else
+ {
+ BOOST_LOG_THROW_DESCR(setup_error, "File collector is not set");
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Multifile sink backend implementation
+////////////////////////////////////////////////////////////////////////////////
+//! Sink implementation data
+struct text_multifile_backend::implementation
+{
+ //! File name composer
+ file_name_composer_type m_FileNameComposer;
+ //! Base path for absolute path composition
+ const filesystem::path m_BasePath;
+ //! File stream
+ filesystem::ofstream m_File;
+
+ implementation() :
+ m_BasePath(filesystem::current_path())
+ {
+ }
+
+ //! Makes relative path absolute with respect to the base path
+ filesystem::path make_absolute(filesystem::path const& p)
+ {
+ return filesystem::absolute(p, m_BasePath);
+ }
+};
+
+//! Default constructor
+BOOST_LOG_API text_multifile_backend::text_multifile_backend() : m_pImpl(new implementation())
+{
+}
+
+//! Destructor
+BOOST_LOG_API text_multifile_backend::~text_multifile_backend()
+{
+ delete m_pImpl;
+}
+
+//! The method sets the file name composer
+BOOST_LOG_API void text_multifile_backend::set_file_name_composer_internal(file_name_composer_type const& composer)
+{
+ m_pImpl->m_FileNameComposer = composer;
+}
+
+//! The method writes the message to the sink
+BOOST_LOG_API void text_multifile_backend::consume(record_view const& rec, string_type const& formatted_message)
+{
+ typedef file_char_traits< string_type::value_type > traits_t;
+ if (!m_pImpl->m_FileNameComposer.empty())
+ {
+ filesystem::path file_name = m_pImpl->make_absolute(m_pImpl->m_FileNameComposer(rec));
+ filesystem::create_directories(file_name.parent_path());
+ m_pImpl->m_File.open(file_name, std::ios_base::out | std::ios_base::app);
+ if (m_pImpl->m_File.is_open())
+ {
+ m_pImpl->m_File.write(formatted_message.data(), static_cast< std::streamsize >(formatted_message.size()));
+ m_pImpl->m_File.put(traits_t::newline);
+ m_pImpl->m_File.close();
+ }
+ }
+}
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>

Added: trunk/libs/log/src/text_ostream_backend.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/text_ostream_backend.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,137 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 19.04.2007
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#include <vector>
+#include <algorithm>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+//! Sink implementation
+template< typename CharT >
+struct basic_text_ostream_backend< CharT >::implementation
+{
+ //! Type of the container that holds all aggregated streams
+ typedef std::vector< shared_ptr< stream_type > > ostream_sequence;
+
+ //! Output stream list
+ ostream_sequence m_Streams;
+ //! Auto-flush flag
+ bool m_fAutoFlush;
+
+ implementation() : m_fAutoFlush(false)
+ {
+ }
+};
+
+
+//! Constructor
+template< typename CharT >
+BOOST_LOG_API basic_text_ostream_backend< CharT >::basic_text_ostream_backend() : m_pImpl(new implementation())
+{
+}
+
+//! Destructor (just to make it link from the shared library)
+template< typename CharT >
+BOOST_LOG_API basic_text_ostream_backend< CharT >::~basic_text_ostream_backend()
+{
+ delete m_pImpl;
+}
+
+//! The method adds a new stream to the sink
+template< typename CharT >
+BOOST_LOG_API void basic_text_ostream_backend< CharT >::add_stream(shared_ptr< stream_type > const& strm)
+{
+ typename implementation::ostream_sequence::iterator it =
+ std::find(m_pImpl->m_Streams.begin(), m_pImpl->m_Streams.end(), strm);
+ if (it == m_pImpl->m_Streams.end())
+ {
+ m_pImpl->m_Streams.push_back(strm);
+ }
+}
+
+//! The method removes a stream from the sink
+template< typename CharT >
+BOOST_LOG_API void basic_text_ostream_backend< CharT >::remove_stream(shared_ptr< stream_type > const& strm)
+{
+ typename implementation::ostream_sequence::iterator it =
+ std::find(m_pImpl->m_Streams.begin(), m_pImpl->m_Streams.end(), strm);
+ if (it != m_pImpl->m_Streams.end())
+ m_pImpl->m_Streams.erase(it);
+}
+
+//! Sets the flag to automatically flush buffers after each logged line
+template< typename CharT >
+BOOST_LOG_API void basic_text_ostream_backend< CharT >::auto_flush(bool f)
+{
+ m_pImpl->m_fAutoFlush = f;
+}
+
+//! The method writes the message to the sink
+template< typename CharT >
+BOOST_LOG_API void basic_text_ostream_backend< CharT >::consume(record_view const&, string_type const& message)
+{
+ typename string_type::const_pointer const p = message.data();
+ typename string_type::size_type const s = message.size();
+ typename implementation::ostream_sequence::const_iterator
+ it = m_pImpl->m_Streams.begin(), end = m_pImpl->m_Streams.end();
+ for (; it != end; ++it)
+ {
+ register stream_type* const strm = it->get();
+ if (strm->good())
+ {
+ strm->write(p, static_cast< std::streamsize >(s));
+ strm->put(static_cast< char_type >('\n'));
+
+ if (m_pImpl->m_fAutoFlush)
+ strm->flush();
+ }
+ }
+}
+
+//! The method flushes the associated streams
+template< typename CharT >
+BOOST_LOG_API void basic_text_ostream_backend< CharT >::flush()
+{
+ typename implementation::ostream_sequence::const_iterator
+ it = m_pImpl->m_Streams.begin(), end = m_pImpl->m_Streams.end();
+ for (; it != end; ++it)
+ {
+ register stream_type* const strm = it->get();
+ if (strm->good())
+ strm->flush();
+ }
+}
+
+//! Explicitly instantiate sink backend implementation
+#ifdef BOOST_LOG_USE_CHAR
+template class basic_text_ostream_backend< char >;
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+template class basic_text_ostream_backend< wchar_t >;
+#endif
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>

Added: trunk/libs/log/src/thread_id.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/thread_id.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,264 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 08.1.2012
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#include <boost/log/detail/config.hpp>
+
+#if !defined(BOOST_LOG_NO_THREADS)
+
+#include <new>
+#include <iostream>
+#include <boost/integer.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/io/ios_state.hpp>
+#include <boost/log/detail/thread_id.hpp>
+#if defined(BOOST_LOG_USE_COMPILER_TLS)
+#include <boost/aligned_storage.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#elif defined(BOOST_WINDOWS)
+#include <boost/thread/thread.hpp>
+#include <boost/log/detail/thread_specific.hpp>
+#else
+#include <boost/system/error_code.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/log/utility/once_block.hpp>
+#endif
+#if !defined(BOOST_LOG_USE_COMPILER_TLS)
+#include <boost/log/detail/singleton.hpp>
+#endif
+#include <boost/log/detail/header.hpp>
+
+#if defined(BOOST_WINDOWS)
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "windows_version.hpp"
+#include <windows.h>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+enum { tid_size = sizeof(GetCurrentThreadId()) };
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+ //! The function returns current process identifier
+ inline thread::id get_id_impl()
+ {
+ return thread::id(GetCurrentThreadId());
+ }
+
+} // namespace
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#else // defined(BOOST_WINDOWS)
+
+#include <pthread.h>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+ //! The function returns current thread identifier
+ inline thread::id get_id_impl()
+ {
+ // According to POSIX, pthread_t may not be an integer type:
+ // http://pubs.opengroup.org/onlinepubs/009695399/basedefs/sys/types.h.html
+ // For now we use the hackish cast to get some opaque number that hopefully correlates with system thread identification.
+ union
+ {
+ thread::id::native_type as_uint;
+ pthread_t as_pthread;
+ }
+ caster = {};
+ caster.as_pthread = pthread_self();
+ return thread::id(caster.as_uint);
+ }
+
+} // namespace
+
+enum { tid_size = sizeof(pthread_t) > sizeof(uintmax_t) ? sizeof(uintmax_t) : sizeof(pthread_t) };
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // defined(BOOST_WINDOWS)
+
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+namespace this_thread {
+
+#if defined(BOOST_LOG_USE_COMPILER_TLS)
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+struct id_storage
+{
+ aligned_storage< thread::id, alignment_of< thread::id >::value >::type m_storage;
+ bool m_initialized;
+};
+
+BOOST_LOG_TLS id_storage g_id_storage = {};
+
+} // namespace
+
+//! The function returns current thread identifier
+BOOST_LOG_API thread::id const& get_id()
+{
+ id_storage& s = g_id_storage;
+ if (!s.m_initialized)
+ {
+ new (s.m_storage.address()) thread::id(get_id_impl());
+ s.m_initialized = true;
+ }
+
+ return *static_cast< thread::id const* >(s.m_storage.address());
+}
+
+#elif defined(BOOST_WINDOWS)
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+struct id_storage :
+ lazy_singleton< id_storage >
+{
+ struct deleter
+ {
+ typedef void result_type;
+
+ explicit deleter(thread::id const* p) : m_p(p) {}
+
+ result_type operator() () const
+ {
+ delete m_p;
+ }
+
+ private:
+ thread::id const* m_p;
+ };
+
+ thread_specific< thread::id const* > m_id;
+};
+
+} // namespace
+
+//! The function returns current thread identifier
+BOOST_LOG_API thread::id const& get_id()
+{
+ id_storage& s = id_storage::get();
+ thread::id const* p = s.m_id.get();
+ if (!p)
+ {
+ p = new thread::id(get_id_impl());
+ s.m_id.set(p);
+ boost::this_thread::at_thread_exit(id_storage::deleter(p));
+ }
+
+ return *p;
+}
+
+#else
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+pthread_key_t g_key;
+
+void deleter(void* p)
+{
+ delete static_cast< thread::id* >(p);
+}
+
+} // namespace
+
+//! The function returns current thread identifier
+BOOST_LOG_API thread::id const& get_id()
+{
+ BOOST_LOG_ONCE_BLOCK()
+ {
+ if (int err = pthread_key_create(&g_key, &deleter))
+ {
+ BOOST_THROW_EXCEPTION(system::system_error(err, system::system_category(), "Failed to create a thread-specific storage for thread id"));
+ }
+ }
+
+ thread::id* p = static_cast< thread::id* >(pthread_getspecific(g_key));
+ if (!p)
+ {
+ p = new thread::id(get_id_impl());
+ pthread_setspecific(g_key, p);
+ }
+
+ return *p;
+}
+
+#endif
+
+} // namespace this_thread
+
+template< typename CharT, typename TraitsT >
+std::basic_ostream< CharT, TraitsT >&
+operator<< (std::basic_ostream< CharT, TraitsT >& strm, thread::id const& tid)
+{
+ if (strm.good())
+ {
+ io::ios_flags_saver flags_saver(strm, (strm.flags() & std::ios_base::uppercase) | std::ios_base::hex | std::ios_base::internal | std::ios_base::showbase);
+ io::ios_width_saver width_saver(strm, static_cast< std::streamsize >(tid_size * 2 + 2)); // 2 chars per byte + 2 chars for the leading 0x
+ io::basic_ios_fill_saver< CharT, TraitsT > fill_saver(strm, static_cast< CharT >('0'));
+ strm << static_cast< uint_t< tid_size * 8 >::least >(tid.native_id());
+ }
+
+ return strm;
+}
+
+#if defined(BOOST_LOG_USE_CHAR)
+template BOOST_LOG_API
+std::basic_ostream< char, std::char_traits< char > >&
+operator<< (std::basic_ostream< char, std::char_traits< char > >& strm, thread::id const& tid);
+#endif // defined(BOOST_LOG_USE_CHAR)
+
+#if defined(BOOST_LOG_USE_WCHAR_T)
+template BOOST_LOG_API
+std::basic_ostream< wchar_t, std::char_traits< wchar_t > >&
+operator<< (std::basic_ostream< wchar_t, std::char_traits< wchar_t > >& strm, thread::id const& tid);
+#endif // defined(BOOST_LOG_USE_WCHAR_T)
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // !defined(BOOST_LOG_NO_THREADS)

Added: trunk/libs/log/src/thread_specific.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/thread_specific.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,233 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \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/libs/log/doc/log.html.
+ */
+
+#include <string>
+#include <stdexcept>
+#include <boost/log/exceptions.hpp>
+#include <boost/log/detail/thread_specific.hpp>
+
+#if !defined(BOOST_LOG_NO_THREADS)
+
+#include <boost/thread/tss.hpp> // To hook on Boost.Thread configuration macros
+#include <boost/log/detail/header.hpp>
+
+
+#if defined(BOOST_THREAD_PLATFORM_WIN32)
+
+#include "windows_version.hpp"
+#include <windows.h>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+thread_specific_base::thread_specific_base()
+{
+ m_Key.as_dword = TlsAlloc();
+ if (m_Key.as_dword == TLS_OUT_OF_INDEXES)
+ {
+ BOOST_LOG_THROW_DESCR(system_error, "TLS capacity depleted");
+ }
+ set_content(0);
+}
+
+thread_specific_base::~thread_specific_base()
+{
+ TlsFree(m_Key.as_dword);
+}
+
+void* thread_specific_base::get_content() const
+{
+ return TlsGetValue(m_Key.as_dword);
+}
+
+void thread_specific_base::set_content(void* value) const
+{
+ TlsSetValue(m_Key.as_dword, value);
+}
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
+
+#include <pthread.h>
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+ //! A helper template to disable early name binding
+ template< typename NonDependentT, typename DependentT >
+ struct make_dependent
+ {
+ typedef NonDependentT type;
+ };
+
+ //! Some portability magic to detect where to store the TLS key
+ template<
+ typename StorageT,
+ bool IsStoreableV = sizeof(pthread_key_t) <= sizeof(StorageT)
+ && alignment_of< pthread_key_t >::value <= alignment_of< StorageT >::value,
+ bool IsPointerV = is_pointer< pthread_key_t >::value
+ >
+ struct pthread_key_traits;
+
+ //! Worst case - the key is probably some structure
+ template< typename StorageT, bool IsPointerV >
+ struct pthread_key_traits< StorageT, false, IsPointerV >
+ {
+ typedef typename make_dependent< pthread_key_t, StorageT >::type pthread_key_type;
+
+ static void allocate(StorageT& stg)
+ {
+ pthread_key_type* pkey = new pthread_key_type;
+ if (pthread_key_create(pkey, 0) != 0)
+ {
+ delete pkey;
+ BOOST_LOG_THROW_DESCR(system_error, "TLS capacity depleted");
+ }
+ stg.as_pointer = pkey;
+ }
+
+ static void deallocate(StorageT& stg)
+ {
+ pthread_key_type* pkey = static_cast< pthread_key_type* >(stg.as_pointer);
+ pthread_key_delete(*pkey);
+ delete pkey;
+ }
+
+ static void set_value(StorageT const& stg, void* value)
+ {
+ pthread_setspecific(*static_cast< pthread_key_type* >(stg.as_pointer), value);
+ }
+
+ static void* get_value(StorageT const& stg)
+ {
+ return pthread_getspecific(*static_cast< pthread_key_type* >(stg.as_pointer));
+ }
+ };
+
+ //! The key is a pointer
+ template< typename StorageT >
+ struct pthread_key_traits< StorageT, true, true >
+ {
+ typedef typename make_dependent< pthread_key_t, StorageT >::type pthread_key_type;
+
+ static void allocate(StorageT& stg)
+ {
+ if (pthread_key_create(reinterpret_cast< pthread_key_type* >(&stg.as_pointer), 0) != 0)
+ {
+ BOOST_LOG_THROW_DESCR(system_error, "TLS capacity depleted");
+ }
+ }
+
+ static void deallocate(StorageT& stg)
+ {
+ pthread_key_delete(reinterpret_cast< pthread_key_type >(stg.as_pointer));
+ }
+
+ static void set_value(StorageT const& stg, void* value)
+ {
+ pthread_setspecific(reinterpret_cast< const pthread_key_type >(stg.as_pointer), value);
+ }
+
+ static void* get_value(StorageT const& stg)
+ {
+ return pthread_getspecific(reinterpret_cast< const pthread_key_type >(stg.as_pointer));
+ }
+ };
+
+ //! The most probable case - the key is an integral or a structure that contains one
+ template< typename StorageT >
+ struct pthread_key_traits< StorageT, true, false >
+ {
+ typedef typename make_dependent< pthread_key_t, StorageT >::type pthread_key_type;
+
+ static void allocate(StorageT& stg)
+ {
+ if (pthread_key_create(reinterpret_cast< pthread_key_type* >(&stg.as_dword), 0) != 0)
+ {
+ BOOST_LOG_THROW_DESCR(system_error, "TLS capacity depleted");
+ }
+ }
+
+ static void deallocate(StorageT& stg)
+ {
+ pthread_key_delete(*reinterpret_cast< pthread_key_type* >(&stg.as_dword));
+ }
+
+ static void set_value(StorageT const& stg, void* value)
+ {
+ pthread_setspecific(*reinterpret_cast< pthread_key_type const* >(&stg.as_dword), value);
+ }
+
+ static void* get_value(StorageT const& stg)
+ {
+ return pthread_getspecific(*reinterpret_cast< pthread_key_type const* >(&stg.as_dword));
+ }
+ };
+
+} // namespace
+
+thread_specific_base::thread_specific_base()
+{
+ typedef pthread_key_traits< key_storage > traits_t;
+ traits_t::allocate(m_Key);
+ set_content(0);
+}
+
+thread_specific_base::~thread_specific_base()
+{
+ typedef pthread_key_traits< key_storage > traits_t;
+ traits_t::deallocate(m_Key);
+}
+
+void* thread_specific_base::get_content() const
+{
+ typedef pthread_key_traits< key_storage > traits_t;
+ return traits_t::get_value(m_Key);
+}
+
+void thread_specific_base::set_content(void* value) const
+{
+ typedef pthread_key_traits< key_storage > traits_t;
+ traits_t::set_value(m_Key, value);
+}
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#else
+#error Boost.Log: unsupported threading API
+#endif
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // !defined(BOOST_LOG_NO_THREADS)

Added: trunk/libs/log/src/threadsafe_queue.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/threadsafe_queue.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,213 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \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/libs/log/doc/log.html.
+ *
+ * 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 lock-free version of the mentioned algorithms contain a race condition and therefore
+ * were not included here.
+ */
+
+#include <boost/log/detail/threadsafe_queue.hpp>
+
+#ifndef BOOST_LOG_NO_THREADS
+
+#include <stdlib.h>
+#include <new>
+#include <boost/assert.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/log/detail/spin_mutex.hpp>
+#include <boost/log/detail/locks.hpp>
+#include <boost/log/detail/alignas.hpp>
+
+#if defined(BOOST_HAS_UNISTD_H)
+#include <unistd.h> // _POSIX_VERSION
+#endif
+
+#if defined(BOOST_HAS_STDINT_H)
+#include <stdint.h> // uintptr_t
+#else
+// MSVC defines integer types here
+#include <stddef.h> // uintptr_t
+#endif
+
+#if defined(__APPLE__) || defined(__APPLE_CC__) || defined(macintosh)
+#include <AvailabilityMacros.h>
+#if defined(MAC_OS_X_VERSION_MIN_REQUIRED) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)
+// Mac OS X 10.6 and later have posix_memalign
+#define BOOST_LOG_HAS_POSIX_MEMALIGN 1
+#endif
+#elif (defined(_POSIX_VERSION) && (_POSIX_VERSION >= 200112L)) || (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))
+#define BOOST_LOG_HAS_POSIX_MEMALIGN 1
+#endif
+
+#if defined(BOOST_WINDOWS)
+#include <malloc.h> // _aligned_malloc, _aligned_free
+#endif
+
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! Generic queue implementation with two locks
+class threadsafe_queue_impl_generic :
+ public threadsafe_queue_impl
+{
+private:
+ //! Mutex type to be used
+ typedef spin_mutex mutex_type;
+
+ /*!
+ * A structure that contains a pointer to the node and the associated mutex.
+ * The alignment below allows to eliminate false sharing, it should be not less than CPU cache line size (which is assumed to be 64 bytes in most cases).
+ */
+ struct BOOST_LOG_ALIGNAS(64) pointer
+ {
+ //! Pointer to the either end of the queue
+ node_base* node;
+ //! Lock for access synchronization
+ mutex_type mutex;
+ // 128 bytes padding is chosen to mitigate false sharing for NetBurst CPUs, which load two cache lines in one go.
+ unsigned char padding[128U - (sizeof(node_base*) + sizeof(mutex_type)) % 128U];
+ };
+
+private:
+ //! Pointer to the beginning of the queue
+ pointer m_Head;
+ //! Pointer to the end of the queue
+ pointer m_Tail;
+
+public:
+ explicit threadsafe_queue_impl_generic(node_base* first_node)
+ {
+ set_next(first_node, NULL);
+ m_Head.node = m_Tail.node = first_node;
+ }
+
+ ~threadsafe_queue_impl_generic()
+ {
+ }
+
+ node_base* reset_last_node()
+ {
+ BOOST_ASSERT(m_Head.node == m_Tail.node);
+ node_base* p = m_Head.node;
+ m_Head.node = m_Tail.node = NULL;
+ return p;
+ }
+
+ bool unsafe_empty()
+ {
+ return m_Head.node == m_Tail.node;
+ }
+
+ void push(node_base* p)
+ {
+ set_next(p, NULL);
+ exclusive_lock_guard< mutex_type > _(m_Tail.mutex);
+ set_next(m_Tail.node, p);
+ m_Tail.node = p;
+ }
+
+ bool try_pop(node_base*& node_to_free, node_base*& node_with_value)
+ {
+ exclusive_lock_guard< mutex_type > _(m_Head.mutex);
+ node_base* next = get_next(m_Head.node);
+ if (next)
+ {
+ // We have a node to pop
+ node_to_free = m_Head.node;
+ node_with_value = m_Head.node = next;
+ return true;
+ }
+ else
+ return false;
+ }
+
+private:
+ // Copying and assignment are closed
+ threadsafe_queue_impl_generic(threadsafe_queue_impl_generic const&);
+ threadsafe_queue_impl_generic& operator= (threadsafe_queue_impl_generic const&);
+
+ BOOST_LOG_FORCEINLINE static void set_next(node_base* p, node_base* next)
+ {
+ p->next.data[0] = next;
+ }
+ BOOST_LOG_FORCEINLINE static node_base* get_next(node_base* p)
+ {
+ return static_cast< node_base* >(p->next.data[0]);
+ }
+};
+
+BOOST_LOG_API threadsafe_queue_impl* threadsafe_queue_impl::create(node_base* first_node)
+{
+ return new threadsafe_queue_impl_generic(first_node);
+}
+
+BOOST_LOG_API void* threadsafe_queue_impl::operator new (std::size_t size)
+{
+ void* p = NULL;
+
+#if defined(BOOST_LOG_HAS_POSIX_MEMALIGN)
+ if (posix_memalign(&p, 64, size) || !p)
+ BOOST_THROW_EXCEPTION(std::bad_alloc());
+ return p;
+#elif defined(BOOST_WINDOWS)
+ p = _aligned_malloc(size, 64);
+ if (!p)
+ BOOST_THROW_EXCEPTION(std::bad_alloc());
+#else
+ p = malloc(size + 64);
+ if (!p)
+ BOOST_THROW_EXCEPTION(std::bad_alloc());
+ unsigned char* q = static_cast< unsigned char* >(p) + 64;
+ q = (unsigned char*)((uintptr_t)q & (~(uintptr_t)63));
+ const unsigned char diff = q - static_cast< unsigned char* >(p);
+ p = q;
+ *--q = diff;
+#endif
+
+ return p;
+}
+
+BOOST_LOG_API void threadsafe_queue_impl::operator delete (void* p, std::size_t)
+{
+#if defined(BOOST_LOG_HAS_POSIX_MEMALIGN)
+ free(p);
+#elif defined(BOOST_WINDOWS)
+ _aligned_free(p);
+#else
+ unsigned char* q = static_cast< unsigned char* >(p);
+ const unsigned char diff = *--q;
+ free(static_cast< unsigned char* >(p) - diff);
+#endif
+}
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_NO_THREADS

Added: trunk/libs/log/src/timer.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/timer.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,183 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 02.12.2007
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#include <boost/config.hpp>
+#include <boost/log/attributes/timer.hpp>
+#include <boost/log/attributes/attribute_value_impl.hpp>
+
+#if defined(BOOST_WINDOWS) && !defined(BOOST_LOG_NO_QUERY_PERFORMANCE_COUNTER)
+
+#include "windows_version.hpp"
+#include <boost/limits.hpp>
+#include <boost/assert.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/detail/interlocked.hpp>
+#include <boost/log/detail/locks.hpp>
+#include <boost/log/detail/spin_mutex.hpp>
+#include <windows.h>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace attributes {
+
+//! Factory implementation
+class BOOST_LOG_VISIBLE timer::impl :
+ public attribute::impl
+{
+private:
+#if !defined(BOOST_LOG_NO_THREADS)
+ //! Synchronization mutex type
+ typedef log::aux::spin_mutex mutex_type;
+ //! Synchronization mutex
+ mutex_type m_Mutex;
+#endif
+ //! Frequency factor for calculating duration
+ uint64_t m_FrequencyFactor;
+ //! Last value of the performance counter
+ uint64_t m_LastCounter;
+ //! Elapsed time duration, in microseconds
+ uint64_t m_Duration;
+
+public:
+ //! Constructor
+ impl() : m_Duration(0)
+ {
+ LARGE_INTEGER li;
+ QueryPerformanceFrequency(&li);
+ BOOST_ASSERT(li.QuadPart != 0LL);
+ m_FrequencyFactor = static_cast< uint64_t >(li.QuadPart) / 1000000ULL;
+
+ QueryPerformanceCounter(&li);
+ m_LastCounter = static_cast< uint64_t >(li.QuadPart);
+ }
+
+ //! The method returns the actual attribute value. It must not return NULL.
+ attribute_value get_value()
+ {
+ LARGE_INTEGER li;
+ QueryPerformanceCounter(&li);
+
+ uint64_t duration;
+ {
+ BOOST_LOG_EXPR_IF_MT(log::aux::exclusive_lock_guard< mutex_type > _(m_Mutex);)
+
+ const uint64_t counts = static_cast< uint64_t >(li.QuadPart) - m_LastCounter;
+ m_LastCounter = static_cast< uint64_t >(li.QuadPart);
+ m_Duration += counts / m_FrequencyFactor;
+ duration = m_Duration;
+ }
+
+ // All these dances are needed simply to construct Boost.DateTime duration without truncating the value
+ value_type res;
+ if (duration < static_cast< uint64_t >((std::numeric_limits< value_type::fractional_seconds_type >::max)()))
+ {
+ res = value_type(0, 0, 0, static_cast< value_type::fractional_seconds_type >(
+ duration * (1000000 / value_type::traits_type::ticks_per_second)));
+ }
+ else
+ {
+ uint64_t total_seconds = duration / 1000000ULL;
+ value_type::fractional_seconds_type usec = static_cast< value_type::fractional_seconds_type >(duration % 1000000ULL);
+ if (total_seconds < static_cast< uint64_t >((std::numeric_limits< value_type::sec_type >::max)()))
+ {
+ res = value_type(0, 0, static_cast< value_type::sec_type >(total_seconds), usec);
+ }
+ else
+ {
+ uint64_t total_hours = total_seconds / 3600ULL;
+ value_type::sec_type seconds = static_cast< value_type::sec_type >(total_seconds % 3600ULL);
+ res = value_type(static_cast< value_type::hour_type >(total_hours), 0, seconds, usec);
+ }
+ }
+
+ return attribute_value(new attribute_value_impl< value_type >(res));
+ }
+};
+
+//! Constructor
+timer::timer() : attribute(new impl())
+{
+}
+
+//! Constructor for casting support
+timer::timer(cast_source const& source) : attribute(source.as< impl >())
+{
+}
+
+} // namespace attributes
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#else // defined(BOOST_WINDOWS) && !defined(BOOST_LOG_NO_QUERY_PERFORMANCE_COUNTER)
+
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace attributes {
+
+//! Factory implementation
+class BOOST_LOG_VISIBLE timer::impl :
+ public attribute::impl
+{
+public:
+ //! Time type
+ typedef utc_time_traits::time_type time_type;
+
+private:
+ //! Base time point
+ const time_type m_BaseTimePoint;
+
+public:
+ /*!
+ * Constructor. Starts time counting.
+ */
+ impl() : m_BaseTimePoint(utc_time_traits::get_clock()) {}
+
+ attribute_value get_value()
+ {
+ return attribute_value(new attribute_value_impl< value_type >(
+ utc_time_traits::get_clock() - m_BaseTimePoint));
+ }
+};
+
+//! Constructor
+timer::timer() : attribute(new impl())
+{
+}
+
+//! Constructor for casting support
+timer::timer(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 // defined(BOOST_WINDOWS) && !defined(BOOST_LOG_NO_QUERY_PERFORMANCE_COUNTER)

Added: trunk/libs/log/src/timestamp.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/timestamp.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,315 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \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/libs/log/doc/log.html.
+ */
+
+#include <boost/log/detail/timestamp.hpp>
+
+#if defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#include <boost/log/detail/alignas.hpp>
+#include <boost/detail/interlocked.hpp>
+#include "windows_version.hpp"
+#include <windows.h>
+#if (defined(_MSC_VER) && defined(_M_IX86) && defined(_M_IX86_FP) && _M_IX86_FP >= 2) || (defined(__GNUC__) && defined(__i386__) && defined(__SSE2__))
+#include <emmintrin.h>
+#if defined(_MSC_VER)
+#include <intrin.h>
+#endif
+#endif
+#else
+#include <unistd.h> // for config macros
+#if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
+#include <mach/mach_time.h>
+#include <mach/kern_return.h>
+#include <boost/log/utility/once_block.hpp>
+#endif
+#include <time.h>
+#include <errno.h>
+#include <boost/throw_exception.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/system/system_error.hpp>
+#endif
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+#if defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#if _WIN32_WINNT >= 0x0600
+
+// Directly use API from Vista and later
+BOOST_LOG_API get_tick_count_t get_tick_count = &GetTickCount64;
+
+#else // _WIN32_WINNT >= 0x0600
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+#if defined(_MSC_VER) && !defined(_M_CEE_PURE)
+
+# if defined(_M_IX86)
+# if defined(_M_IX86_FP) && _M_IX86_FP >= 2
+//! Atomically loads and stores the 64-bit value through SSE2 instructions
+BOOST_LOG_FORCEINLINE void move64(const uint64_t* from, uint64_t* to)
+{
+ _mm_storel_epi64(reinterpret_cast< __m128i* >(to), _mm_loadl_epi64(reinterpret_cast< const __m128i* >(from)));
+}
+# else // defined(_M_IX86_FP) && _M_IX86_FP >= 2
+//! Atomically loads and stores the 64-bit value through FPU instructions
+BOOST_LOG_FORCEINLINE void move64(const uint64_t* from, uint64_t* to)
+{
+ __asm
+ {
+ mov eax, from
+ mov edx, to
+ fild qword ptr [eax]
+ fistp qword ptr [edx]
+ };
+}
+# endif // defined(_M_IX86_FP) && _M_IX86_FP >= 2
+# elif defined(_M_AMD64) || defined(_M_IA64)
+//! Atomically loads and stores the 64-bit value
+BOOST_LOG_FORCEINLINE void move64(const uint64_t* from, uint64_t* to)
+{
+ *to = *from;
+}
+# else
+# define BOOST_LOG_GENERIC_MOVE64 1
+# endif
+
+#elif defined(__GNUC__)
+
+# if defined(__i386__)
+# if defined(__SSE2__)
+//! Atomically loads and stores the 64-bit value through SSE2 instructions
+BOOST_LOG_FORCEINLINE void move64(const uint64_t* from, uint64_t* to)
+{
+ _mm_storel_epi64(reinterpret_cast< __m128i* >(to), _mm_loadl_epi64(reinterpret_cast< const __m128i* >(from)));
+}
+# else // defined(__SSE2__)
+//! Atomically loads and stores the 64-bit value through FPU instructions
+BOOST_LOG_FORCEINLINE void move64(const uint64_t* from, uint64_t* to)
+{
+ __asm__ __volatile__
+ (
+ "fildq %1\n\t"
+ "fistpq %0"
+ : "=m" (*to)
+ : "m" (*from)
+ : "memory"
+ );
+}
+# endif // defined(__SSE2__)
+# elif defined(__x86_64__)
+//! Atomically loads and stores the 64-bit value
+BOOST_LOG_FORCEINLINE void move64(const uint64_t* from, uint64_t* to)
+{
+ *to = *from;
+}
+# else
+# define BOOST_LOG_GENERIC_MOVE64 1
+# endif
+
+#else
+
+# define BOOST_LOG_GENERIC_MOVE64 1
+
+#endif
+
+#if defined(BOOST_LOG_GENERIC_MOVE64)
+
+BOOST_LOG_ALIGNAS(16) long g_spin_lock = 0;
+
+//! Atomically loads and stores the 64-bit value
+BOOST_LOG_FORCEINLINE void move64(const uint64_t* from, uint64_t* to)
+{
+ while (BOOST_INTERLOCKED_COMPARE_EXCHANGE(&g_spin_lock, 1, 0) != 0);
+ *to = *from;
+ BOOST_INTERLOCKED_EXCHANGE(&g_spin_lock, 0);
+}
+
+#endif // defined(BOOST_LOG_GENERIC_MOVE64)
+
+BOOST_LOG_ALIGNAS(16) uint64_t g_ticks = 0;
+
+union ticks_caster
+{
+ uint64_t as_uint64;
+ struct
+ {
+ uint32_t ticks;
+ uint32_t counter;
+ }
+ as_components;
+};
+
+//! Artifical implementation of GetTickCount64
+uint64_t __stdcall get_tick_count64()
+{
+ ticks_caster state;
+ move64(&g_ticks, &state.as_uint64);
+
+ uint32_t new_ticks = GetTickCount();
+
+ state.as_components.counter += new_ticks < state.as_components.ticks;
+ state.as_components.ticks = new_ticks;
+
+ move64(&state.as_uint64, &g_ticks);
+ return state.as_uint64;
+}
+
+uint64_t __stdcall get_tick_count_init()
+{
+ HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
+ if (hKernel32)
+ {
+ get_tick_count_t p = (get_tick_count_t)GetProcAddress(hKernel32, "GetTickCount64");
+ if (p)
+ {
+ // Use native API
+ get_tick_count = p;
+ return p();
+ }
+ }
+
+ // No native API available
+ get_tick_count = &get_tick_count64;
+ return get_tick_count64();
+}
+
+} // namespace
+
+BOOST_LOG_API get_tick_count_t get_tick_count = &get_tick_count_init;
+
+#endif // _WIN32_WINNT >= 0x0600
+
+#elif defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0
+
+BOOST_LOG_API int64_t duration::milliseconds() const
+{
+ // Timestamps are always in nanoseconds
+ return m_ticks / 1000000LL;
+}
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+/*!
+ * \c get_timestamp implementation based on POSIX realtime clock.
+ * Note that this implementation is only used as a last resort since
+ * this timer can be manually set and may jump due to DST change.
+ */
+timestamp get_timestamp_realtime_clock()
+{
+ timespec ts;
+ if (clock_gettime(CLOCK_REALTIME, &ts) != 0)
+ {
+ BOOST_THROW_EXCEPTION(boost::system::system_error(
+ errno, boost::system::system_category(), "Failed to acquire current time"));
+ }
+
+ return timestamp(static_cast< uint64_t >(ts.tv_sec) * 1000000000ULL + ts.tv_nsec);
+}
+
+# if defined(_POSIX_MONOTONIC_CLOCK)
+
+//! \c get_timestamp implementation based on POSIX monotonic clock
+timestamp get_timestamp_monotonic_clock()
+{
+ timespec ts;
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
+ {
+ int err = errno;
+ if (err == EINVAL)
+ {
+ // The current platform does not support monotonic timer.
+ // Fall back to realtime clock, which is not exactly what we need
+ // but is better than nothing.
+ get_timestamp = &get_timestamp_realtime_clock;
+ return get_timestamp_realtime_clock();
+ }
+ BOOST_THROW_EXCEPTION(boost::system::system_error(
+ err, boost::system::system_category(), "Failed to acquire current time"));
+ }
+
+ return timestamp(static_cast< uint64_t >(ts.tv_sec) * 1000000000ULL + ts.tv_nsec);
+}
+
+# define BOOST_LOG_DEFAULT_GET_TIMESTAMP get_timestamp_monotonic_clock
+
+# else // if defined(_POSIX_MONOTONIC_CLOCK)
+# define BOOST_LOG_DEFAULT_GET_TIMESTAMP get_timestamp_realtime_clock
+# endif // if defined(_POSIX_MONOTONIC_CLOCK)
+
+} // namespace
+
+// Use POSIX API
+BOOST_LOG_API get_timestamp_t get_timestamp = &BOOST_LOG_DEFAULT_GET_TIMESTAMP;
+
+# undef BOOST_LOG_DEFAULT_GET_TIMESTAMP
+
+#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
+
+BOOST_LOG_API int64_t duration::milliseconds() const
+{
+ static mach_timebase_info_data_t timebase_info = {};
+ BOOST_LOG_ONCE_BLOCK()
+ {
+ kern_return_t err = mach_timebase_info(&timebase_info);
+ if (err != KERN_SUCCESS)
+ {
+ BOOST_THROW_EXCEPTION(boost::system::system_error(
+ err, boost::system::system_category(), "Failed to initialize timebase info"));
+ }
+ }
+
+ // Often the timebase rational equals 1, we can optimize for this case
+ if (timebase_info.numer == timebase_info.denom)
+ {
+ // Timestamps are in nanoseconds
+ return m_ticks / 1000000LL;
+ }
+ else
+ {
+ return (m_ticks * timebase_info.numer) / (1000000LL * timebase_info.denom);
+ }
+}
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+//! \c get_timestamp implementation based on MacOS X absolute time
+timestamp get_timestamp_mach()
+{
+ return timestamp(mach_absolute_time());
+}
+
+} // namespace
+
+// Use MacOS X API
+BOOST_LOG_API get_timestamp_t get_timestamp = &get_timestamp_mach;
+
+#else
+
+# error Boost.Log: Timestamp generation is not supported for your platform
+
+#endif
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>

Added: trunk/libs/log/src/trivial.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/trivial.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,117 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 07.11.2009
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#include <boost/log/detail/config.hpp>
+
+#if defined(BOOST_LOG_USE_CHAR)
+
+#include <string>
+#include <istream>
+#include <boost/log/trivial.hpp>
+#include <boost/log/sources/global_logger_storage.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace trivial {
+
+//! Initialization routine
+BOOST_LOG_API logger::logger_type logger::construct_logger()
+{
+ return logger_type(keywords::severity = info);
+}
+
+//! Returns a reference to the trivial logger instance
+BOOST_LOG_API logger::logger_type& logger::get()
+{
+ return log::sources::aux::logger_singleton< logger >::get();
+}
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+const unsigned int names_count = 6;
+
+template< typename CharT >
+struct severity_level_names
+{
+ static const CharT names[names_count][8];
+};
+
+template< typename CharT >
+const CharT severity_level_names< CharT >::names[names_count][8] =
+{
+ { 't', 'r', 'a', 'c', 'e', 0 },
+ { 'd', 'e', 'b', 'u', 'g', 0 },
+ { 'i', 'n', 'f', 'o', 0 },
+ { 'w', 'a', 'r', 'n', 'i', 'n', 'g', 0 },
+ { 'e', 'r', 'r', 'o', 'r', 0 },
+ { 'f', 'a', 't', 'a', 'l', 0 }
+};
+
+} // namespace
+
+BOOST_LOG_API const char* to_string(severity_level lvl)
+{
+ typedef severity_level_names< char > level_names;
+ if (static_cast< unsigned int >(lvl) < names_count)
+ return level_names::names[static_cast< unsigned int >(lvl)];
+ else
+ return NULL;
+}
+
+template< typename CharT, typename TraitsT >
+BOOST_LOG_API std::basic_istream< CharT, TraitsT >& operator>> (
+ std::basic_istream< CharT, TraitsT >& strm, severity_level& lvl)
+{
+ if (strm.good())
+ {
+ typedef severity_level_names< CharT > level_names;
+ typedef std::basic_string< CharT, TraitsT > string_type;
+ string_type str;
+ strm >> str;
+ for (unsigned int i = 0; i < names_count; ++i)
+ {
+ if (str == level_names::names[i])
+ {
+ lvl = static_cast< severity_level >(i);
+ return strm;
+ }
+ }
+ strm.setstate(std::ios_base::failbit);
+ }
+
+ return strm;
+}
+
+template BOOST_LOG_API std::basic_istream< char, std::char_traits< char > >&
+ operator>> < char, std::char_traits< char > > (
+ std::basic_istream< char, std::char_traits< char > >& strm, severity_level& lvl);
+#ifdef BOOST_LOG_USE_WCHAR_T
+template BOOST_LOG_API std::basic_istream< wchar_t, std::char_traits< wchar_t > >&
+ operator>> < wchar_t, std::char_traits< wchar_t > > (
+ std::basic_istream< wchar_t, std::char_traits< wchar_t > >& strm, severity_level& lvl);
+#endif
+
+} // namespace trivial
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // defined(BOOST_LOG_USE_CHAR)

Added: trunk/libs/log/src/unhandled_exception_count.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/unhandled_exception_count.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,62 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \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/libs/log/doc/log.html.
+ *
+ * The code in this file is based on the implementation by Evgeny Panasyuk:
+ *
+ * https://github.com/panaseleus/stack_unwinding/blob/master/boost/exception/uncaught_exception_count.hpp
+ */
+
+#include <exception>
+#include <boost/log/detail/unhandled_exception_count.hpp>
+#include <boost/log/detail/header.hpp>
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+BOOST_LOG_ANONYMOUS_NAMESPACE {
+
+#if defined(BOOST_LOG_HAS_CXXABI_H)
+// Only GCC 4.7 declares __cxa_get_globals() in cxxabi.h, older compilers do not expose this function but it's there
+extern "C" void* __cxa_get_globals();
+#elif defined(_MSC_VER) && _MSC_VER >= 1400
+#define BOOST_LOG_HAS_GETPTD
+extern "C" void* _getptd();
+#endif
+
+} // namespace
+
+//! Returns the number of currently pending exceptions
+BOOST_LOG_API unsigned int unhandled_exception_count() BOOST_NOEXCEPT
+{
+#if defined(BOOST_LOG_HAS_CXXABI_H)
+ // Tested on {clang 3.2,GCC 3.5.6,GCC 4.1.2,GCC 4.4.6,GCC 4.4.7}x{x32,x64}
+ return *(reinterpret_cast< const unsigned int* >(static_cast< const char* >(__cxa_get_globals()) + sizeof(void*))); // __cxa_eh_globals::uncaughtExceptions, x32 offset - 0x4, x64 - 0x8
+#elif defined(BOOST_LOG_HAS_GETPTD)
+ // MSVC specific. Tested on {MSVC2005SP1,MSVC2008SP1,MSVC2010SP1,MSVC2012}x{x32,x64}.
+ return *(reinterpret_cast< const unsigned int* >(static_cast< const char* >(_getptd()) + (sizeof(void*) == 8 ? 0x100 : 0x90))); // _tiddata::_ProcessingThrow, x32 offset - 0x90, x64 - 0x100
+#else
+ return static_cast< unsigned int >(std::unhandled_exception());
+#endif
+}
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>

Added: trunk/libs/log/src/windows_version.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/src/windows_version.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,52 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 windows_version.hpp
+ * \author Andrey Semashev
+ * \date 07.03.2009
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/libs/log/doc/log.html.
+ */
+
+#ifndef BOOST_LOG_WINDOWS_VERSION_HPP_INCLUDED_
+#define BOOST_LOG_WINDOWS_VERSION_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#if defined(BOOST_LOG_USE_WINNT6_API)
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0600 // _WIN32_WINNT_LONGHORN
+#endif
+
+#else
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0500 // _WIN32_WINNT_WIN2K
+#endif
+
+#endif // BOOST_LOG_USE_WINNT6_API
+
+// This is to make Boost.ASIO happy
+#ifndef __USE_W32_SOCKETS
+#define __USE_W32_SOCKETS
+#endif
+
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#endif // BOOST_LOG_WINDOWS_VERSION_HPP_INCLUDED_

Added: trunk/libs/log/test/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/Jamfile.v2 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,58 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+# The file was adapted from libs/tr2/test/Jamfile.v2 by John Maddock.
+
+import testing ;
+
+project
+ : requirements
+ <include>common
+ <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>intel-win:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>intel-win:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>gcc:<cxxflags>-fno-strict-aliasing # avoids strict aliasing violations in other Boost components
+ <library>/boost/log//boost_log
+ <library>/boost/date_time//boost_date_time
+ <library>/boost/regex//boost_regex
+ <library>/boost/filesystem//boost_filesystem
+ <library>/boost/system//boost_system
+ <library>/boost/test//boost_unit_test_framework
+ <threading>single:<define>BOOST_LOG_NO_THREADS
+ <threading>multi:<library>/boost/thread//boost_thread
+# <link>static
+ ;
+
+# this rule enumerates through all the sources and invokes
+# the run rule for each source, the result is a list of all
+# the run rules, which we can pass on to the test_suite rule:
+rule test_all
+{
+ #ECHO executing test_all rule ;
+ local all_rules = ;
+ for local file_compile in [ glob compile/*.cpp ]
+ {
+ all_rules += [ compile $(file_compile) ] ;
+ }
+ for local file_compile_fail in [ glob compile_fail/*.cpp ]
+ {
+ all_rules += [ compile-fail $(file_compile_fail) ] ;
+ }
+ for local file_run in [ glob run/*.cpp ]
+ {
+ all_rules += [ run $(file_run) ] ;
+ }
+
+ #ECHO $(all_rules) ;
+ return $(all_rules) ;
+}
+
+test-suite log : [ test_all r ] [ build-project ../example ] ;

Added: trunk/libs/log/test/common/attr_comparison.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/common/attr_comparison.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,60 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_comparison.hpp
+ * \author Andrey Semashev
+ * \date 06.08.2010
+ *
+ * \brief This header contains tools for attribute comparison in attribute-related tests.
+ */
+
+#ifndef BOOST_LOG_TESTS_ATTR_COMPARISON_HPP_INCLUDED_
+#define BOOST_LOG_TESTS_ATTR_COMPARISON_HPP_INCLUDED_
+
+#include <ostream>
+#include <boost/log/attributes/attribute.hpp>
+
+class attribute_factory_helper :
+ public boost::log::attribute
+{
+ typedef boost::log::attribute base_type;
+
+public:
+ attribute_factory_helper(base_type const& that) : base_type(that)
+ {
+ }
+
+ impl* get_impl() const
+ {
+ return base_type::get_impl();
+ }
+};
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+inline bool operator== (attribute const& left, attribute const& right)
+{
+ return attribute_factory_helper(left).get_impl() == attribute_factory_helper(right).get_impl();
+}
+inline bool operator!= (attribute const& left, attribute const& right)
+{
+ return attribute_factory_helper(left).get_impl() != attribute_factory_helper(right).get_impl();
+}
+
+inline std::ostream& operator<< (std::ostream& strm, attribute const& val)
+{
+ strm << attribute_factory_helper(val).get_impl();
+ return strm;
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_TESTS_ATTR_COMPARISON_HPP_INCLUDED_

Added: trunk/libs/log/test/common/char_definitions.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/common/char_definitions.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,116 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 char_definitions.hpp
+ * \author Andrey Semashev
+ * \date 24.01.2009
+ *
+ * \brief This header contains common type definitions for character type dependent tests.
+ */
+
+#ifndef BOOST_LOG_TESTS_CHAR_DEFINITIONS_HPP_INCLUDED_
+#define BOOST_LOG_TESTS_CHAR_DEFINITIONS_HPP_INCLUDED_
+
+#include <string>
+#include <iostream>
+#include <boost/mpl/vector.hpp>
+
+namespace mpl = boost::mpl;
+
+typedef mpl::vector<
+#ifdef BOOST_LOG_USE_CHAR
+ char
+#endif
+#if defined(BOOST_LOG_USE_CHAR) && defined(BOOST_LOG_USE_WCHAR_T)
+ ,
+#endif
+#ifdef BOOST_LOG_USE_WCHAR_T
+ wchar_t
+#endif
+>::type char_types;
+
+template< typename >
+struct test_data;
+
+
+#ifdef BOOST_LOG_USE_CHAR
+
+template< >
+struct test_data< char >
+{
+ static const char* abc() { return "abc"; }
+ static const char* ABC() { return "ABC"; }
+ static const char* some_test_string() { return "some test string"; }
+ static const char* zero_to_five() { return "012345"; }
+ static const char* def() { return "def"; }
+ static const char* aaa() { return "aaa"; }
+ static const char* abcd() { return "abcd"; }
+ static const char* zz() { return "zz"; }
+ static const char* abcdefg0123456789() { return "abcdefg0123456789"; }
+
+ static const char* attr1() { return "attr1"; }
+ static const char* attr2() { return "attr2"; }
+ static const char* attr3() { return "attr3"; }
+ static const char* attr4() { return "attr4"; }
+
+ static const char* int_format1() { return "%08d"; }
+ static const char* fp_format1() { return "%06.3f"; }
+};
+
+//! The function compares two strings and prints them if they are not equal
+inline bool equal_strings(std::string const& left, std::string const& right)
+{
+ if (left != right)
+ {
+ std::cout << "Left: \"" << left << "\"\nRight: \"" << right << "\"" << std::endl;
+ return false;
+ }
+ else
+ return true;
+}
+
+#endif // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+
+template< >
+struct test_data< wchar_t >
+{
+ static const wchar_t* abc() { return L"abc"; }
+ static const wchar_t* ABC() { return L"ABC"; }
+ static const wchar_t* some_test_string() { return L"some test string"; }
+ static const wchar_t* zero_to_five() { return L"012345"; }
+ static const wchar_t* def() { return L"def"; }
+ static const wchar_t* aaa() { return L"aaa"; }
+ static const wchar_t* abcd() { return L"abcd"; }
+ static const wchar_t* zz() { return L"zz"; }
+ static const wchar_t* abcdefg0123456789() { return L"abcdefg0123456789"; }
+
+ static const char* attr1() { return "attr1"; }
+ static const char* attr2() { return "attr2"; }
+ static const char* attr3() { return "attr3"; }
+ static const char* attr4() { return "attr4"; }
+
+ static const wchar_t* int_format1() { return L"%08d"; }
+ static const wchar_t* fp_format1() { return L"%06.3f"; }
+};
+
+//! The function compares two strings and prints them if they are not equal
+inline bool equal_strings(std::wstring const& left, std::wstring const& right)
+{
+ if (left != right)
+ {
+ std::wcout << L"Left: \"" << left << L"\"\nRight: \"" << right << L"\"" << std::endl;
+ return false;
+ }
+ else
+ return true;
+}
+
+#endif // BOOST_LOG_USE_WCHAR_T
+
+#endif // BOOST_LOG_TESTS_CHAR_DEFINITIONS_HPP_INCLUDED_

Added: trunk/libs/log/test/common/make_record.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/common/make_record.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,32 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 make_record.hpp
+ * \author Andrey Semashev
+ * \date 18.03.2009
+ *
+ * \brief This header contains a helper function make_record that creates a log record with the specified attributes.
+ */
+
+#ifndef BOOST_LOG_TESTS_MAKE_RECORD_HPP_INCLUDED_
+#define BOOST_LOG_TESTS_MAKE_RECORD_HPP_INCLUDED_
+
+#include <boost/move/utility.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/attributes/attribute_set.hpp>
+
+inline boost::log::record make_record(boost::log::attribute_set const& src_attrs)
+{
+ return boost::log::core::get()->open_record(src_attrs);
+}
+
+inline boost::log::record_view make_record_view(boost::log::attribute_set const& src_attrs)
+{
+ return make_record(src_attrs).lock();
+}
+
+#endif // BOOST_LOG_TESTS_MAKE_RECORD_HPP_INCLUDED_

Added: trunk/libs/log/test/common/test_sink.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/common/test_sink.hpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,92 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 test_sink.hpp
+ * \author Andrey Semashev
+ * \date 18.03.2009
+ *
+ * \brief This header contains a test sink frontend that is used through various tests.
+ */
+
+#ifndef BOOST_LOG_TESTS_TEST_SINK_HPP_INCLUDED_
+#define BOOST_LOG_TESTS_TEST_SINK_HPP_INCLUDED_
+
+#include <cstddef>
+#include <map>
+#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/sinks/sink.hpp>
+#include <boost/log/expressions/filter.hpp>
+
+//! A sink implementation for testing purpose
+struct test_sink :
+ public boost::log::sinks::sink
+{
+public:
+ typedef boost::log::attribute_value_set attribute_values;
+ typedef boost::log::record_view record_type;
+ typedef boost::log::filter filter_type;
+ typedef attribute_values::key_type key_type;
+
+ struct key_type_order
+ {
+ typedef bool result_type;
+
+ result_type operator() (key_type const& left, key_type const& right) const
+ {
+ return left.id() < right.id();
+ }
+ };
+
+ typedef std::map< key_type, std::size_t, key_type_order > attr_counters_map;
+
+public:
+ filter_type m_Filter;
+ attr_counters_map m_Consumed;
+ std::size_t m_RecordCounter;
+
+public:
+ test_sink() : boost::log::sinks::sink(false), m_RecordCounter(0) {}
+
+ void set_filter(filter_type const& f)
+ {
+ m_Filter = f;
+ }
+
+ void reset_filter()
+ {
+ m_Filter.reset();
+ }
+
+ bool will_consume(attribute_values const& attributes)
+ {
+ return m_Filter(attributes);
+ }
+
+ void consume(record_type const& record)
+ {
+ ++m_RecordCounter;
+ attribute_values::const_iterator
+ it = record.attribute_values().begin(),
+ end = record.attribute_values().end();
+ for (; it != end; ++it)
+ ++m_Consumed[it->first];
+ }
+
+ void flush()
+ {
+ }
+
+ void clear()
+ {
+ m_RecordCounter = 0;
+ m_Consumed.clear();
+ }
+};
+
+#endif // BOOST_LOG_TESTS_TEST_SINK_HPP_INCLUDED_

Added: trunk/libs/log/test/compile/current_function_support.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/compile/current_function_support.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,37 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_function_support.cpp
+ * \author Andrey Semashev
+ * \date 26.09.2010
+ *
+ * \brief This test checks that the BOOST_CURRENT_FUNCTION macro has semantics
+ * compatible with Boost.Log on the current platform.
+ *
+ * The point of this test is to determine whether the macro unfolds into a string literal
+ * rather than a pointer to a string. This is critical because BOOST_LOG_WFUNCTION
+ * relies on this fact - it determines the length of the literal by applying sizeof to it.
+ */
+
+#define BOOST_TEST_MODULE current_function_support
+
+#include <boost/current_function.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_array.hpp>
+
+template< typename T >
+void check(T& param)
+{
+ BOOST_STATIC_ASSERT(boost::is_array< T >::value);
+}
+
+int main(int, char*[])
+{
+ check(BOOST_CURRENT_FUNCTION);
+
+ return 0;
+}

Added: trunk/libs/log/test/compile/src_logger_assignable.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/compile/src_logger_assignable.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,39 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 src_logger_assignable.cpp
+ * \author Andrey Semashev
+ * \date 16.05.2011
+ *
+ * \brief This header contains a test for logger assignability.
+ */
+
+#include <boost/log/sources/logger.hpp>
+#include <boost/log/sources/severity_logger.hpp>
+#include <boost/log/sources/channel_logger.hpp>
+#include <boost/log/sources/severity_channel_logger.hpp>
+
+template< typename LoggerT >
+void test()
+{
+ LoggerT lg1, lg2;
+
+ // Loggers must be assignable. The assignment operator must be taken
+ // from the composite_logger class and not auto-generated (in which
+ // case it will fail to compile because assignment in basic_logger is private).
+ lg1 = lg2;
+}
+
+int main(int, char*[])
+{
+ test< boost::log::sources::logger >();
+ test< boost::log::sources::severity_logger< > >();
+ test< boost::log::sources::channel_logger< > >();
+ test< boost::log::sources::severity_channel_logger< > >();
+
+ return 0;
+}

Added: trunk/libs/log/test/compile/util_explicit_operator_bool.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/compile/util_explicit_operator_bool.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,43 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 util_explicit_operator_bool.cpp
+ * \author Andrey Semashev
+ * \date 17.07.2010
+ *
+ * \brief This test checks that explicit operator bool can be used in
+ * the valid contexts.
+ */
+
+#define BOOST_TEST_MODULE util_explicit_operator_bool
+
+#include <boost/log/utility/explicit_operator_bool.hpp>
+
+namespace {
+
+ // A test object that has the operator of explicit conversion to bool
+ struct checkable
+ {
+ BOOST_LOG_EXPLICIT_OPERATOR_BOOL()
+ bool operator! () const
+ {
+ return false;
+ }
+ };
+
+} // namespace
+
+int main(int, char*[])
+{
+ checkable val;
+ if (val)
+ {
+ return 1;
+ }
+
+ return 0;
+}

Added: trunk/libs/log/test/compile/util_unique_identifier.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/compile/util_unique_identifier.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,27 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 util_unique_identifier.cpp
+ * \author Andrey Semashev
+ * \date 24.01.2009
+ *
+ * \brief This header contains tests for the unique identifier name generator.
+ */
+
+#include <boost/log/utility/unique_identifier_name.hpp>
+
+int main(int, char*[])
+{
+ // Names with the same prefixes may coexist in different lines
+ int BOOST_LOG_UNIQUE_IDENTIFIER_NAME(var) = 0;
+ int BOOST_LOG_UNIQUE_IDENTIFIER_NAME(var) = 0;
+
+ // Names with different prefixes may coexist on the same line
+ int BOOST_LOG_UNIQUE_IDENTIFIER_NAME(var1) = 0; int BOOST_LOG_UNIQUE_IDENTIFIER_NAME(var2) = 0;
+
+ return 0;
+}

Added: trunk/libs/log/test/compile_fail/attr_functor_void_return.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/compile_fail/attr_functor_void_return.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,42 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_functor_void_return.cpp
+ * \author Andrey Semashev
+ * \date 25.01.2009
+ *
+ * \brief This test checks that it is not possible to create a functor attribute
+ * with a void-returning functor.
+ */
+
+#define BOOST_TEST_MODULE attr_functor_void_return
+
+#include <boost/utility/result_of.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/attributes/function.hpp>
+
+namespace logging = boost::log;
+namespace attrs = logging::attributes;
+
+namespace {
+
+ // A test function that returns an attribute value
+ void get_attr_value();
+
+} // namespace
+
+int main(int, char*[])
+{
+ logging::attribute attr1 =
+#ifndef BOOST_NO_RESULT_OF
+ attrs::make_function(&get_attr_value);
+#else
+ attrs::make_function< void >(&get_attr_value);
+#endif
+
+ return 0;
+}

Added: trunk/libs/log/test/compile_fail/util_explicit_operator_bool_conv_int.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/compile_fail/util_explicit_operator_bool_conv_int.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 util_explicit_operator_bool_conv_int.cpp
+ * \author Andrey Semashev
+ * \date 17.07.2010
+ *
+ * \brief This test checks that explicit operator bool cannot be used in
+ * an unintended context.
+ */
+
+#define BOOST_TEST_MODULE util_explicit_operator_bool_conv_int
+
+#include <boost/log/utility/explicit_operator_bool.hpp>
+
+namespace {
+
+ // A test object that has the operator of explicit conversion to bool
+ struct checkable
+ {
+ BOOST_LOG_EXPLICIT_OPERATOR_BOOL()
+ bool operator! () const
+ {
+ return false;
+ }
+ };
+
+} // namespace
+
+int main(int, char*[])
+{
+ checkable val;
+ int n = val;
+
+ return 0;
+}

Added: trunk/libs/log/test/compile_fail/util_explicit_operator_bool_conv_pvoid.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/compile_fail/util_explicit_operator_bool_conv_pvoid.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 util_explicit_operator_bool_conv_pvoid.cpp
+ * \author Andrey Semashev
+ * \date 17.07.2010
+ *
+ * \brief This test checks that explicit operator bool cannot be used in
+ * an unintended context.
+ */
+
+#define BOOST_TEST_MODULE util_explicit_operator_bool_conv_pvoid
+
+#include <boost/log/utility/explicit_operator_bool.hpp>
+
+namespace {
+
+ // A test object that has the operator of explicit conversion to bool
+ struct checkable
+ {
+ BOOST_LOG_EXPLICIT_OPERATOR_BOOL()
+ bool operator! () const
+ {
+ return false;
+ }
+ };
+
+} // namespace
+
+int main(int, char*[])
+{
+ checkable val;
+ void* p = val;
+
+ return 0;
+}

Added: trunk/libs/log/test/compile_fail/util_explicit_operator_bool_delete.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/compile_fail/util_explicit_operator_bool_delete.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 util_explicit_operator_bool_delete.cpp
+ * \author Andrey Semashev
+ * \date 17.07.2010
+ *
+ * \brief This test checks that explicit operator bool cannot be used in
+ * an unintended context.
+ */
+
+#define BOOST_TEST_MODULE util_explicit_operator_bool_delete
+
+#include <boost/log/utility/explicit_operator_bool.hpp>
+
+namespace {
+
+ // A test object that has the operator of explicit conversion to bool
+ struct checkable
+ {
+ BOOST_LOG_EXPLICIT_OPERATOR_BOOL()
+ bool operator! () const
+ {
+ return false;
+ }
+ };
+
+} // namespace
+
+int main(int, char*[])
+{
+ checkable val;
+ delete val;
+
+ return 0;
+}

Added: trunk/libs/log/test/compile_fail/util_explicit_operator_bool_shift.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/compile_fail/util_explicit_operator_bool_shift.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 util_explicit_operator_bool_shift.cpp
+ * \author Andrey Semashev
+ * \date 17.07.2010
+ *
+ * \brief This test checks that explicit operator bool cannot be used in
+ * an unintended context.
+ */
+
+#define BOOST_TEST_MODULE util_explicit_operator_bool_shift
+
+#include <boost/log/utility/explicit_operator_bool.hpp>
+
+namespace {
+
+ // A test object that has the operator of explicit conversion to bool
+ struct checkable
+ {
+ BOOST_LOG_EXPLICIT_OPERATOR_BOOL()
+ bool operator! () const
+ {
+ return false;
+ }
+ };
+
+} // namespace
+
+int main(int, char*[])
+{
+ checkable val;
+ val << 2;
+
+ return 0;
+}

Added: trunk/libs/log/test/performance/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/performance/Jamfile.v2 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,11 @@
+#
+# Copyright Andrey Semashev 2007 - 2013.
+# 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)
+#
+
+exe record_emission
+ : record_emission.cpp ../../build//boost_log
+ ;
+

Added: trunk/libs/log/test/performance/record_emission.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/performance/record_emission.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,129 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_emission.cpp
+ * \author Andrey Semashev
+ * \date 22.03.2009
+ *
+ * \brief This code measures performance of log record emission
+ */
+
+// #define BOOST_LOG_USE_CHAR
+// #define BOOST_ALL_DYN_LINK 1
+// #define BOOST_LOG_DYN_LINK 1
+#define BOOST_NO_DYN_LINK 1
+
+#include <iomanip>
+#include <iostream>
+#include <boost/ref.hpp>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/date_time/microsec_time_clock.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/barrier.hpp>
+
+#include <boost/log/core.hpp>
+#include <boost/log/common.hpp>
+#include <boost/log/attributes.hpp>
+#include <boost/log/sinks.hpp>
+#include <boost/log/sinks/basic_sink_backend.hpp>
+
+#include <boost/log/expressions.hpp>
+
+#include <boost/log/attributes/scoped_attribute.hpp>
+
+enum config
+{
+ RECORD_COUNT = 50000000,
+ THREAD_COUNT = 3,
+ SINK_COUNT = 3
+};
+
+namespace logging = boost::log;
+namespace expr = boost::log::expressions;
+namespace sinks = boost::log::sinks;
+namespace attrs = boost::log::attributes;
+namespace src = boost::log::sources;
+namespace keywords = boost::log::keywords;
+
+enum severity_level
+{
+ normal,
+ warning,
+ error
+};
+
+BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", severity_level)
+
+namespace {
+
+ //! A fake sink backend that receives log records
+ class fake_backend :
+ public sinks::basic_sink_backend< sinks::concurrent_feeding >
+ {
+ public:
+ void consume(logging::record const& rec)
+ {
+ }
+ };
+
+} // namespace
+
+void test(unsigned int record_count, boost::barrier& bar)
+{
+ BOOST_LOG_SCOPED_THREAD_TAG("ThreadID", boost::this_thread::get_id());
+ bar.wait();
+
+ src::severity_logger< severity_level > slg;
+ for (unsigned int i = 0; i < record_count; ++i)
+ {
+ BOOST_LOG_SEV(slg, warning) << "Test record";
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ std::cout << "Test config: " << THREAD_COUNT << " threads, " << SINK_COUNT << " sinks, " << RECORD_COUNT << " records" << std::endl;
+//__debugbreak();
+// typedef sinks::unlocked_sink< fake_backend > fake_sink;
+// typedef sinks::synchronous_sink< fake_backend > fake_sink;
+ typedef sinks::asynchronous_sink< fake_backend > fake_sink;
+ for (unsigned int i = 0; i < SINK_COUNT; ++i)
+ logging::core::get()->add_sink(boost::make_shared< fake_sink >());
+
+ logging::core::get()->add_global_attribute("LineID", attrs::counter< unsigned int >(1));
+ logging::core::get()->add_global_attribute("TimeStamp", attrs::local_clock());
+ logging::core::get()->add_global_attribute("Scope", attrs::named_scope());
+
+// logging::core::get()->set_filter(severity > normal); // all records pass the filter
+// logging::core::get()->set_filter(severity > error); // all records don't pass the filter
+
+ logging::core::get()->set_filter(severity > error); // all records don't pass the filter
+
+ const unsigned int record_count = RECORD_COUNT / THREAD_COUNT;
+ boost::barrier bar(THREAD_COUNT);
+ boost::thread_group threads;
+
+ for (unsigned int i = 1; i < THREAD_COUNT; ++i)
+ threads.create_thread(boost::bind(&test, record_count, boost::ref(bar)));
+
+ boost::posix_time::ptime start = boost::date_time::microsec_clock< boost::posix_time::ptime >::universal_time(), end;
+ test(record_count, bar);
+ if (THREAD_COUNT > 1)
+ threads.join_all();
+ end = boost::date_time::microsec_clock< boost::posix_time::ptime >::universal_time();
+
+ unsigned long long duration = (end - start).total_microseconds();
+
+ std::cout << "Test duration: " << duration << " us ("
+ << std::fixed << std::setprecision(3) << static_cast< double >(RECORD_COUNT) / (static_cast< double >(duration) / 1000000.0)
+ << " records per second)" << std::endl;
+
+ return 0;
+}

Added: trunk/libs/log/test/run/attr_attribute_set.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/run/attr_attribute_set.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,281 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_attribute_set.cpp
+ * \author Andrey Semashev
+ * \date 24.01.2009
+ *
+ * \brief This header contains tests for the attribute set class.
+ */
+
+#define BOOST_TEST_MODULE attr_attribute_set
+
+#include <list>
+#include <vector>
+#include <string>
+#include <utility>
+#include <iterator>
+#include <boost/test/included/unit_test.hpp>
+#include <boost/log/attributes/constant.hpp>
+#include <boost/log/attributes/attribute_set.hpp>
+#include "char_definitions.hpp"
+#include "attr_comparison.hpp"
+
+namespace logging = boost::log;
+namespace attrs = logging::attributes;
+
+// The test checks construction and assignment
+BOOST_AUTO_TEST_CASE(construction)
+{
+ typedef logging::attribute_set attr_set;
+ typedef test_data< char > data;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+ attrs::constant< std::string > attr3("Hello, world!");
+
+ attr_set set1;
+ BOOST_CHECK(set1.empty());
+ BOOST_CHECK_EQUAL(set1.size(), 0UL);
+
+ attr_set set2 = set1;
+ BOOST_CHECK(set2.empty());
+ BOOST_CHECK_EQUAL(set2.size(), 0UL);
+
+ set2[data::attr1()] = attr1;
+ set2[data::attr2()] = attr2;
+ BOOST_CHECK(set1.empty());
+ BOOST_CHECK_EQUAL(set1.size(), 0UL);
+ BOOST_CHECK(!set2.empty());
+ BOOST_CHECK_EQUAL(set2.size(), 2UL);
+
+ attr_set set3 = set2;
+ BOOST_CHECK(!set3.empty());
+ BOOST_CHECK_EQUAL(set3.size(), 2UL);
+ BOOST_CHECK_EQUAL(set3.count(data::attr1()), 1UL);
+ BOOST_CHECK_EQUAL(set3.count(data::attr2()), 1UL);
+ BOOST_CHECK_EQUAL(set3.count(data::attr3()), 0UL);
+
+ set1[data::attr3()] = attr3;
+ BOOST_CHECK(!set1.empty());
+ BOOST_CHECK_EQUAL(set1.size(), 1UL);
+ BOOST_CHECK_EQUAL(set1.count(data::attr3()), 1UL);
+
+ set2 = set1;
+ BOOST_REQUIRE_EQUAL(set1.size(), set2.size());
+ BOOST_CHECK(std::equal(set1.begin(), set1.end(), set2.begin()));
+}
+
+// The test checks lookup methods
+BOOST_AUTO_TEST_CASE(lookup)
+{
+ typedef logging::attribute_set attr_set;
+ typedef test_data< char > data;
+ typedef std::basic_string< char > string;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+
+ attr_set set1;
+ set1[data::attr1()] = attr1;
+ set1[data::attr2()] = attr2;
+
+ // Traditional find methods
+ attr_set::iterator it = set1.find(data::attr1());
+ BOOST_CHECK(it != set1.end());
+ BOOST_CHECK_EQUAL(it->second, attr1);
+
+ string s1 = data::attr2();
+ it = set1.find(s1);
+ BOOST_CHECK(it != set1.end());
+ BOOST_CHECK_EQUAL(it->second, attr2);
+
+ it = set1.find(data::attr1());
+ BOOST_CHECK(it != set1.end());
+ BOOST_CHECK_EQUAL(it->second, attr1);
+
+ it = set1.find(data::attr3());
+ BOOST_CHECK(it == set1.end());
+
+ // Subscript operator
+ logging::attribute p = set1[data::attr1()];
+ BOOST_CHECK_EQUAL(p, attr1);
+ BOOST_CHECK_EQUAL(set1.size(), 2UL);
+
+ p = set1[s1];
+ BOOST_CHECK_EQUAL(p, attr2);
+ BOOST_CHECK_EQUAL(set1.size(), 2UL);
+
+ p = set1[data::attr1()];
+ BOOST_CHECK_EQUAL(p, attr1);
+ BOOST_CHECK_EQUAL(set1.size(), 2UL);
+
+ p = set1[data::attr3()];
+ BOOST_CHECK(!p);
+ BOOST_CHECK_EQUAL(set1.size(), 2UL);
+
+ // Counting elements
+ BOOST_CHECK_EQUAL(set1.count(data::attr1()), 1UL);
+ BOOST_CHECK_EQUAL(set1.count(s1), 1UL);
+ BOOST_CHECK_EQUAL(set1.count(data::attr1()), 1UL);
+ BOOST_CHECK_EQUAL(set1.count(data::attr3()), 0UL);
+}
+
+// The test checks insertion methods
+BOOST_AUTO_TEST_CASE(insertion)
+{
+ typedef logging::attribute_set attr_set;
+ typedef test_data< char > data;
+ typedef std::basic_string< char > string;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+ attrs::constant< std::string > attr3("Hello, world!");
+
+ attr_set set1;
+
+ // Traditional insert methods
+ std::pair< attr_set::iterator, bool > res = set1.insert(data::attr1(), attr1);
+ BOOST_CHECK(res.second);
+ BOOST_CHECK(res.first != set1.end());
+ BOOST_CHECK(res.first->first == data::attr1());
+ BOOST_CHECK_EQUAL(res.first->second, attr1);
+ BOOST_CHECK(!set1.empty());
+ BOOST_CHECK_EQUAL(set1.size(), 1UL);
+
+ res = set1.insert(std::make_pair(attr_set::key_type(data::attr2()), attr2));
+ BOOST_CHECK(res.second);
+ BOOST_CHECK(res.first != set1.end());
+ BOOST_CHECK(res.first->first == data::attr2());
+ BOOST_CHECK_EQUAL(res.first->second, attr2);
+ BOOST_CHECK(!set1.empty());
+ BOOST_CHECK_EQUAL(set1.size(), 2UL);
+
+ // Insertion attempt of an attribute with the name of an already existing attribute
+ res = set1.insert(std::make_pair(attr_set::key_type(data::attr2()), attr3));
+ BOOST_CHECK(!res.second);
+ BOOST_CHECK(res.first != set1.end());
+ BOOST_CHECK(res.first->first == data::attr2());
+ BOOST_CHECK_EQUAL(res.first->second, attr2);
+ BOOST_CHECK(!set1.empty());
+ BOOST_CHECK_EQUAL(set1.size(), 2UL);
+
+ // Mass insertion
+ typedef attr_set::key_type key_type;
+ std::list< std::pair< key_type, logging::attribute > > elems;
+ elems.push_back(std::make_pair(key_type(data::attr2()), attr2));
+ elems.push_back(std::make_pair(key_type(data::attr1()), attr1));
+ elems.push_back(std::make_pair(key_type(data::attr3()), attr3));
+ // ... with element duplication
+ elems.push_back(std::make_pair(key_type(data::attr1()), attr3));
+
+ attr_set set2;
+ set2.insert(elems.begin(), elems.end());
+ BOOST_CHECK(!set2.empty());
+ BOOST_REQUIRE_EQUAL(set2.size(), 3UL);
+ typedef attr_set::mapped_type mapped_type;
+ BOOST_CHECK_EQUAL(static_cast< mapped_type >(set2[data::attr1()]), attr1);
+ BOOST_CHECK_EQUAL(static_cast< mapped_type >(set2[data::attr2()]), attr2);
+ BOOST_CHECK_EQUAL(static_cast< mapped_type >(set2[data::attr3()]), attr3);
+
+ // The same, but with insertion results collection
+ std::vector< std::pair< attr_set::iterator, bool > > results;
+
+ attr_set set3;
+ set3.insert(elems.begin(), elems.end(), std::back_inserter(results));
+ BOOST_REQUIRE_EQUAL(results.size(), elems.size());
+ BOOST_CHECK(!set3.empty());
+ BOOST_REQUIRE_EQUAL(set3.size(), 3UL);
+ attr_set::iterator it = set3.find(data::attr1());
+ BOOST_REQUIRE(it != set3.end());
+ BOOST_CHECK(it->first == data::attr1());
+ BOOST_CHECK_EQUAL(it->second, attr1);
+ BOOST_CHECK(it == results[1].first);
+ it = set3.find(data::attr2());
+ BOOST_REQUIRE(it != set3.end());
+ BOOST_CHECK(it->first == data::attr2());
+ BOOST_CHECK_EQUAL(it->second, attr2);
+ BOOST_CHECK(it == results[0].first);
+ it = set3.find(data::attr3());
+ BOOST_REQUIRE(it != set3.end());
+ BOOST_CHECK(it->first == data::attr3());
+ BOOST_CHECK_EQUAL(it->second, attr3);
+ BOOST_CHECK(it == results[2].first);
+
+ BOOST_CHECK(results[0].second);
+ BOOST_CHECK(results[1].second);
+ BOOST_CHECK(results[2].second);
+ BOOST_CHECK(!results[3].second);
+
+ // Subscript operator
+ attr_set set4;
+
+ logging::attribute& p1 = (set4[data::attr1()] = attr1);
+ BOOST_CHECK_EQUAL(set4.size(), 1UL);
+ BOOST_CHECK_EQUAL(p1, attr1);
+
+ logging::attribute& p2 = (set4[string(data::attr2())] = attr2);
+ BOOST_CHECK_EQUAL(set4.size(), 2UL);
+ BOOST_CHECK_EQUAL(p2, attr2);
+
+ logging::attribute& p3 = (set4[key_type(data::attr3())] = attr3);
+ BOOST_CHECK_EQUAL(set4.size(), 3UL);
+ BOOST_CHECK_EQUAL(p3, attr3);
+
+ // subscript operator can replace existing elements
+ logging::attribute& p4 = (set4[data::attr3()] = attr1);
+ BOOST_CHECK_EQUAL(set4.size(), 3UL);
+ BOOST_CHECK_EQUAL(p4, attr1);
+}
+
+// The test checks erasure methods
+BOOST_AUTO_TEST_CASE(erasure)
+{
+ typedef logging::attribute_set attr_set;
+ typedef test_data< char > data;
+ typedef std::basic_string< char > string;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+ attrs::constant< std::string > attr3("Hello, world!");
+
+ attr_set set1;
+ set1[data::attr1()] = attr1;
+ set1[data::attr2()] = attr2;
+ set1[data::attr3()] = attr3;
+
+ attr_set set2 = set1;
+ BOOST_REQUIRE_EQUAL(set2.size(), 3UL);
+
+ BOOST_CHECK_EQUAL(set2.erase(data::attr1()), 1UL);
+ BOOST_CHECK_EQUAL(set2.size(), 2UL);
+ BOOST_CHECK_EQUAL(set2.count(data::attr1()), 0UL);
+
+ BOOST_CHECK_EQUAL(set2.erase(data::attr1()), 0UL);
+ BOOST_CHECK_EQUAL(set2.size(), 2UL);
+
+ set2.erase(set2.begin());
+ BOOST_CHECK_EQUAL(set2.size(), 1UL);
+ BOOST_CHECK_EQUAL(set2.count(data::attr2()), 0UL);
+
+ set2 = set1;
+ BOOST_REQUIRE_EQUAL(set2.size(), 3UL);
+
+ attr_set::iterator it = set2.begin();
+ set2.erase(++it, set2.end());
+ BOOST_CHECK_EQUAL(set2.size(), 1UL);
+ BOOST_CHECK_EQUAL(set2.count(data::attr1()), 1UL);
+ BOOST_CHECK_EQUAL(set2.count(data::attr2()), 0UL);
+ BOOST_CHECK_EQUAL(set2.count(data::attr3()), 0UL);
+
+ set2 = set1;
+ BOOST_REQUIRE_EQUAL(set2.size(), 3UL);
+
+ set2.clear();
+ BOOST_CHECK(set2.empty());
+ BOOST_CHECK_EQUAL(set2.size(), 0UL);
+}

Added: trunk/libs/log/test/run/attr_attribute_value_impl.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/run/attr_attribute_value_impl.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,153 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_attribute_value_impl.cpp
+ * \author Andrey Semashev
+ * \date 25.01.2009
+ *
+ * \brief This header contains tests for the basic attribute value class.
+ */
+
+#define BOOST_TEST_MODULE attr_attribute_value_impl
+
+#include <string>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/test/floating_point_comparison.hpp>
+#include <boost/test/included/unit_test.hpp>
+#include <boost/log/attributes/attribute_value.hpp>
+#include <boost/log/attributes/attribute_value_impl.hpp>
+#include <boost/log/attributes/value_extraction.hpp>
+#include <boost/log/attributes/value_visitation.hpp>
+#include <boost/log/utility/type_dispatch/static_type_dispatcher.hpp>
+#include <boost/log/utility/functional/bind_assign.hpp>
+
+namespace logging = boost::log;
+namespace attrs = logging::attributes;
+
+namespace {
+
+ // Type dispatcher for the supported types
+ struct my_dispatcher :
+ public logging::static_type_dispatcher<
+ boost::mpl::vector< int, double, std::string >
+ >
+ {
+ typedef logging::static_type_dispatcher<
+ boost::mpl::vector< int, double, std::string >
+ > base_type;
+
+ enum type_expected
+ {
+ none_expected,
+ int_expected,
+ double_expected,
+ string_expected
+ };
+
+ my_dispatcher() :
+ base_type(*this),
+ m_Expected(none_expected),
+ m_Int(0),
+ m_Double(0.0)
+ {
+ }
+
+ void set_expected()
+ {
+ m_Expected = none_expected;
+ }
+ void set_expected(int value)
+ {
+ m_Expected = int_expected;
+ m_Int = value;
+ }
+ void set_expected(double value)
+ {
+ m_Expected = double_expected;
+ m_Double = value;
+ }
+ void set_expected(std::string const& value)
+ {
+ m_Expected = string_expected;
+ m_String = value;
+ }
+
+ // Implement visitation logic for all supported types
+ void operator() (int const& value) const
+ {
+ BOOST_CHECK_EQUAL(m_Expected, int_expected);
+ BOOST_CHECK_EQUAL(m_Int, value);
+ }
+ void operator() (double const& value) const
+ {
+ BOOST_CHECK_EQUAL(m_Expected, double_expected);
+ BOOST_CHECK_CLOSE(m_Double, value, 0.001);
+ }
+ void operator() (std::string const& value) const
+ {
+ BOOST_CHECK_EQUAL(m_Expected, string_expected);
+ BOOST_CHECK_EQUAL(m_String, value);
+ }
+
+ private:
+ type_expected m_Expected;
+ int m_Int;
+ double m_Double;
+ std::string m_String;
+ };
+
+} // namespace
+
+// The test verifies that type dispatching works
+BOOST_AUTO_TEST_CASE(type_dispatching)
+{
+ my_dispatcher disp;
+ logging::attribute_value p1(attrs::make_attribute_value< int >(10));
+ logging::attribute_value p2(attrs::make_attribute_value< double > (5.5));
+ logging::attribute_value p3(attrs::make_attribute_value< std::string >(std::string("Hello, world!")));
+ logging::attribute_value p4(attrs::make_attribute_value< float >(static_cast< float >(-7.2)));
+
+ disp.set_expected(10);
+ BOOST_CHECK(p1.dispatch(disp));
+ BOOST_CHECK(p1.dispatch(disp)); // check that the contained value doesn't change over time or upon dispatching
+
+ disp.set_expected(5.5);
+ BOOST_CHECK(p2.dispatch(disp));
+
+ disp.set_expected("Hello, world!");
+ BOOST_CHECK(p3.dispatch(disp));
+
+ disp.set_expected();
+ BOOST_CHECK(!p4.dispatch(disp));
+}
+
+// The test verifies that value extracition works
+BOOST_AUTO_TEST_CASE(value_extraction)
+{
+ logging::attribute_value p1(attrs::make_attribute_value< int >(10));
+ logging::attribute_value p2(attrs::make_attribute_value< double >(5.5));
+
+ logging::value_ref< int > val1 = p1.extract< int >();
+ BOOST_CHECK(!!val1);
+ BOOST_CHECK_EQUAL(val1.get(), 10);
+
+ logging::value_ref< double > val2 = p1.extract< double >();
+ BOOST_CHECK(!val2);
+
+ double val3 = 0.0;
+ BOOST_CHECK(p2.visit< double >(logging::bind_assign(val3)));
+ BOOST_CHECK_CLOSE(val3, 5.5, 0.001);
+}
+
+// The test verifies that the detach_from_thread returns a valid pointer
+BOOST_AUTO_TEST_CASE(detaching_from_thread)
+{
+ boost::intrusive_ptr< logging::attribute_value::impl > p1(new attrs::attribute_value_impl< int >(10));
+ boost::intrusive_ptr< logging::attribute_value::impl > p2 = p1->detach_from_thread();
+ BOOST_CHECK(!!p2);
+}

Added: trunk/libs/log/test/run/attr_attribute_value_set.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/run/attr_attribute_value_set.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,224 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_attribute_value_set.cpp
+ * \author Andrey Semashev
+ * \date 24.01.2009
+ *
+ * \brief This header contains tests for the attribute value set.
+ */
+
+#define BOOST_TEST_MODULE attr_attribute_value_set
+
+#include <vector>
+#include <string>
+#include <utility>
+#include <iterator>
+#include <boost/none.hpp>
+#include <boost/optional.hpp>
+#include <boost/config.hpp>
+#include <boost/test/floating_point_comparison.hpp>
+#include <boost/test/included/unit_test.hpp>
+#include <boost/log/attributes/constant.hpp>
+#include <boost/log/attributes/attribute_set.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include <boost/log/attributes/value_visitation.hpp>
+#include <boost/log/utility/type_dispatch/static_type_dispatcher.hpp>
+#include "char_definitions.hpp"
+
+namespace logging = boost::log;
+namespace attrs = logging::attributes;
+
+namespace {
+
+ //! A simple attribute value receiver functional object
+ template< typename T >
+ struct receiver
+ {
+ typedef void result_type;
+ receiver(T& val) : m_Val(val) {}
+ result_type operator() (T const& val) const
+ {
+ m_Val = val;
+ }
+
+ private:
+ T& m_Val;
+ };
+
+ //! The function extracts attribute value
+ template< typename T >
+ inline bool get_attr_value(logging::attribute_value const& val, T& res)
+ {
+ receiver< T > r(res);
+ logging::static_type_dispatcher< T > disp(r);
+ return val.dispatch(disp);
+ }
+
+} // namespace
+
+// The test checks construction and assignment
+BOOST_AUTO_TEST_CASE(construction)
+{
+ typedef logging::attribute_set attr_set;
+ typedef logging::attribute_value_set attr_values;
+ typedef test_data< char > data;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+ attrs::constant< std::string > attr3("Hello, world!");
+ attrs::constant< char > attr4('L');
+
+ {
+ attr_set set1, set2, set3;
+ set1[data::attr1()] = attr1;
+ set1[data::attr2()] = attr2;
+ set1[data::attr3()] = attr3;
+
+ attr_values view1(set1, set2, set3);
+ view1.freeze();
+
+ BOOST_CHECK(!view1.empty());
+ BOOST_CHECK_EQUAL(view1.size(), 3UL);
+ }
+ {
+ attr_set set1, set2, set3;
+ set1[data::attr1()] = attr1;
+ set2[data::attr2()] = attr2;
+ set3[data::attr3()] = attr3;
+
+ attr_values view1(set1, set2, set3);
+ view1.freeze();
+
+ BOOST_CHECK(!view1.empty());
+ BOOST_CHECK_EQUAL(view1.size(), 3UL);
+
+ attr_values view2 = view1;
+ BOOST_CHECK(!view2.empty());
+ BOOST_CHECK_EQUAL(view2.size(), 3UL);
+ }
+
+ // Check that the more prioritized attributes replace the less ones
+ {
+ attrs::constant< int > attr2_2(20);
+ attrs::constant< double > attr4_2(10.3);
+ attrs::constant< float > attr3_3(static_cast< float >(-7.2));
+ attrs::constant< unsigned int > attr4_3(5);
+
+ attr_set set1, set2, set3;
+ set3[data::attr1()] = attr1;
+ set3[data::attr2()] = attr2;
+ set3[data::attr3()] = attr3;
+ set3[data::attr4()] = attr4;
+
+ set2[data::attr2()] = attr2_2;
+ set2[data::attr4()] = attr4_2;
+
+ set1[data::attr3()] = attr3_3;
+ set1[data::attr4()] = attr4_3;
+
+ attr_values view1(set1, set2, set3);
+ view1.freeze();
+
+ BOOST_CHECK(!view1.empty());
+ BOOST_CHECK_EQUAL(view1.size(), 4UL);
+
+ int n = 0;
+ BOOST_CHECK(logging::visit< int >(data::attr1(), view1, receiver< int >(n)));
+ BOOST_CHECK_EQUAL(n, 10);
+
+ BOOST_CHECK(logging::visit< int >(data::attr2(), view1, receiver< int >(n)));
+ BOOST_CHECK_EQUAL(n, 20);
+
+ float f = static_cast< float >(0.0);
+ BOOST_CHECK(logging::visit< float >(data::attr3(), view1, receiver< float >(f)));
+ BOOST_CHECK_CLOSE(f, static_cast< float >(-7.2), static_cast< float >(0.001));
+
+ unsigned int m = 0;
+ BOOST_CHECK(logging::visit< unsigned int >(data::attr4(), view1, receiver< unsigned int >(m)));
+ BOOST_CHECK_EQUAL(m, 5U);
+ }
+}
+
+// The test checks lookup methods
+BOOST_AUTO_TEST_CASE(lookup)
+{
+ typedef logging::attribute_set attr_set;
+ typedef logging::attribute_value_set attr_values;
+ typedef test_data< char > data;
+ typedef std::basic_string< char > string;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+ attrs::constant< std::string > attr3("Hello, world!");
+
+ attr_set set1, set2, set3;
+ set1[data::attr1()] = attr1;
+ set1[data::attr2()] = attr2;
+ set1[data::attr3()] = attr3;
+
+ attr_values view1(set1, set2, set3);
+ view1.freeze();
+
+ // Traditional find methods
+ attr_values::const_iterator it = view1.find(data::attr1());
+ BOOST_CHECK(it != view1.end());
+ BOOST_CHECK(it->first == data::attr1());
+ int val1 = 0;
+ BOOST_CHECK(get_attr_value(it->second, val1));
+ BOOST_CHECK_EQUAL(val1, 10);
+
+ string s1 = data::attr2();
+ it = view1.find(s1);
+ BOOST_CHECK(it != view1.end());
+ BOOST_CHECK(it->first == data::attr2());
+ double val2 = 0;
+ BOOST_CHECK(get_attr_value(it->second, val2));
+ BOOST_CHECK_CLOSE(val2, 5.5, 0.001);
+
+ it = view1.find(data::attr3());
+ BOOST_CHECK(it != view1.end());
+ BOOST_CHECK(it->first == data::attr3());
+ std::string val3;
+ BOOST_CHECK(get_attr_value(it->second, val3));
+ BOOST_CHECK_EQUAL(val3, "Hello, world!");
+
+ // make an additional check that the result is absent if the value type does not match the requested type
+ BOOST_CHECK(!get_attr_value(it->second, val2));
+
+ it = view1.find(data::attr4());
+ BOOST_CHECK(it == view1.end());
+
+ // Subscript operator
+ logging::attribute_value p = view1[data::attr1()];
+ BOOST_CHECK_EQUAL(view1.size(), 3UL);
+ BOOST_CHECK(!!p);
+ BOOST_CHECK(get_attr_value(p, val1));
+ BOOST_CHECK_EQUAL(val1, 10);
+
+ p = view1[s1];
+ BOOST_CHECK_EQUAL(view1.size(), 3UL);
+ BOOST_CHECK(!!p);
+ BOOST_CHECK(get_attr_value(p, val2));
+ BOOST_CHECK_CLOSE(val2, 5.5, 0.001);
+
+ p = view1[data::attr3()];
+ BOOST_CHECK_EQUAL(view1.size(), 3UL);
+ BOOST_CHECK(!!p);
+ BOOST_CHECK(get_attr_value(p, val3));
+ BOOST_CHECK_EQUAL(val3, "Hello, world!");
+
+ p = view1[data::attr4()];
+ BOOST_CHECK(!p);
+ BOOST_CHECK_EQUAL(view1.size(), 3UL);
+
+ // Counting elements
+ BOOST_CHECK_EQUAL(view1.count(data::attr1()), 1UL);
+ BOOST_CHECK_EQUAL(view1.count(s1), 1UL);
+ BOOST_CHECK_EQUAL(view1.count(data::attr3()), 1UL);
+ BOOST_CHECK_EQUAL(view1.count(data::attr4()), 0UL);
+}

Added: trunk/libs/log/test/run/attr_function.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/run/attr_function.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,138 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_function.cpp
+ * \author Andrey Semashev
+ * \date 25.01.2009
+ *
+ * \brief This header contains tests for the function attribute.
+ */
+
+#define BOOST_TEST_MODULE attr_function
+
+#include <string>
+#include <boost/mpl/vector.hpp>
+#include <boost/utility/result_of.hpp>
+#include <boost/test/included/unit_test.hpp>
+#include <boost/log/attributes/function.hpp>
+#include <boost/log/utility/type_dispatch/static_type_dispatcher.hpp>
+
+namespace logging = boost::log;
+namespace attrs = logging::attributes;
+
+namespace {
+
+ // Type dispatcher for the supported types
+ struct my_dispatcher :
+ public logging::static_type_dispatcher<
+ boost::mpl::vector< int, std::string >
+ >
+ {
+ typedef logging::static_type_dispatcher<
+ boost::mpl::vector< int, std::string >
+ > base_type;
+
+ enum type_expected
+ {
+ none_expected,
+ int_expected,
+ string_expected
+ };
+
+ my_dispatcher() : base_type(*this), m_Expected(none_expected), m_Int(0) {}
+
+ void set_expected()
+ {
+ m_Expected = none_expected;
+ }
+ void set_expected(int value)
+ {
+ m_Expected = int_expected;
+ m_Int = value;
+ }
+ void set_expected(std::string const& value)
+ {
+ m_Expected = string_expected;
+ m_String = value;
+ }
+
+ // Implement visitation logic for all supported types
+ void operator() (int const& value) const
+ {
+ BOOST_CHECK_EQUAL(m_Expected, int_expected);
+ BOOST_CHECK_EQUAL(m_Int, value);
+ }
+ void operator() (std::string const& value) const
+ {
+ BOOST_CHECK_EQUAL(m_Expected, string_expected);
+ BOOST_CHECK_EQUAL(m_String, value);
+ }
+
+ private:
+ type_expected m_Expected;
+ int m_Int;
+ std::string m_String;
+ };
+
+ // A test function that returns an attribute value
+ int get_attr_value()
+ {
+ return 10;
+ }
+
+ // A test functional object that returns an attribute value
+ struct attr_value_generator
+ {
+ typedef std::string result_type;
+
+ explicit attr_value_generator(unsigned int& count) : m_CallsCount(count) {}
+ result_type operator() () const
+ {
+ ++m_CallsCount;
+ return "Hello, world!";
+ }
+
+ private:
+ unsigned int& m_CallsCount;
+ };
+
+} // namespace
+
+// The test verifies that the attribute calls the specified functor and returns the value returned by the functor
+BOOST_AUTO_TEST_CASE(calling)
+{
+ unsigned int call_count = 0;
+ my_dispatcher disp;
+
+ logging::attribute attr1 =
+#ifndef BOOST_NO_RESULT_OF
+ attrs::make_function(&get_attr_value);
+#else
+ attrs::make_function< int >(&get_attr_value);
+#endif
+
+ logging::attribute attr2 =
+#ifndef BOOST_NO_RESULT_OF
+ attrs::make_function(attr_value_generator(call_count));
+#else
+ attrs::make_function< std::string >(attr_value_generator(call_count));
+#endif
+
+ logging::attribute_value p1(attr1.get_value());
+ logging::attribute_value p2(attr2.get_value());
+ BOOST_CHECK_EQUAL(call_count, 1);
+ logging::attribute_value p3(attr2.get_value());
+ BOOST_CHECK_EQUAL(call_count, 2);
+
+ disp.set_expected(10);
+ BOOST_CHECK(p1.dispatch(disp));
+ BOOST_CHECK(p1.dispatch(disp)); // check that the contained value doesn't change over time or upon dispatching
+
+ disp.set_expected("Hello, world!");
+ BOOST_CHECK(p2.dispatch(disp));
+ BOOST_CHECK(p3.dispatch(disp));
+}

Added: trunk/libs/log/test/run/attr_named_scope.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/run/attr_named_scope.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,192 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_named_scope.cpp
+ * \author Andrey Semashev
+ * \date 25.01.2009
+ *
+ * \brief This header contains tests for the named scope attribute.
+ */
+
+#define BOOST_TEST_MODULE attr_named_scope
+
+#include <sstream>
+#include <boost/mpl/vector.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/test/included/unit_test.hpp>
+#include <boost/log/attributes/attribute.hpp>
+#include <boost/log/attributes/named_scope.hpp>
+#include <boost/log/attributes/attribute_value.hpp>
+#include <boost/log/attributes/value_extraction.hpp>
+#include <boost/log/utility/string_literal.hpp>
+#include <boost/log/utility/value_ref.hpp>
+#include "char_definitions.hpp"
+
+namespace logging = boost::log;
+namespace attrs = logging::attributes;
+
+namespace {
+
+ template< typename >
+ struct scope_test_data;
+
+ template< >
+ struct scope_test_data< char >
+ {
+ static logging::string_literal scope1() { return logging::str_literal("scope1"); }
+ static logging::string_literal scope2() { return logging::str_literal("scope2"); }
+ static logging::string_literal file() { return logging::str_literal(__FILE__); }
+ };
+
+} // namespace
+
+// The test verifies that the scope macros are defined
+BOOST_AUTO_TEST_CASE(macros)
+{
+#ifdef BOOST_LOG_USE_CHAR
+ BOOST_CHECK(BOOST_IS_DEFINED(BOOST_LOG_NAMED_SCOPE(name)));
+ BOOST_CHECK(BOOST_IS_DEFINED(BOOST_LOG_FUNCTION()));
+#endif // BOOST_LOG_USE_CHAR
+}
+
+// The test checks that scope tracking works correctly
+BOOST_AUTO_TEST_CASE(scope_tracking)
+{
+ typedef attrs::named_scope named_scope;
+ typedef named_scope::sentry sentry;
+ typedef attrs::named_scope_list scopes;
+ typedef attrs::named_scope_entry scope;
+ typedef scope_test_data< char > scope_data;
+
+ named_scope attr;
+
+ // First scope
+ const unsigned int line1 = __LINE__;
+ sentry scope1(scope_data::scope1(), scope_data::file(), line1);
+
+ BOOST_CHECK(!named_scope::get_scopes().empty());
+ BOOST_CHECK_EQUAL(named_scope::get_scopes().size(), 1UL);
+
+ logging::attribute_value val = attr.get_value();
+ BOOST_REQUIRE(!!val);
+
+ logging::value_ref< scopes > sc = val.extract< scopes >();
+ BOOST_REQUIRE(!!sc);
+ BOOST_REQUIRE(!sc->empty());
+ BOOST_CHECK_EQUAL(sc->size(), 1UL);
+
+ scope const& s1 = sc->front();
+ BOOST_CHECK(s1.scope_name == scope_data::scope1());
+ BOOST_CHECK(s1.file_name == scope_data::file());
+ BOOST_CHECK(s1.line == line1);
+
+ // Second scope
+ const unsigned int line2 = __LINE__;
+ scope new_scope(scope_data::scope2(), scope_data::file(), line2);
+ named_scope::push_scope(new_scope);
+
+ BOOST_CHECK(!named_scope::get_scopes().empty());
+ BOOST_CHECK_EQUAL(named_scope::get_scopes().size(), 2UL);
+
+ val = attr.get_value();
+ BOOST_REQUIRE(!!val);
+
+ sc = val.extract< scopes >();
+ BOOST_REQUIRE(!!sc);
+ BOOST_REQUIRE(!sc->empty());
+ BOOST_CHECK_EQUAL(sc->size(), 2UL);
+
+ scopes::const_iterator it = sc->begin();
+ scope const& s2 = *(it++);
+ BOOST_CHECK(s2.scope_name == scope_data::scope1());
+ BOOST_CHECK(s2.file_name == scope_data::file());
+ BOOST_CHECK(s2.line == line1);
+
+ scope const& s3 = *(it++);
+ BOOST_CHECK(s3.scope_name == scope_data::scope2());
+ BOOST_CHECK(s3.file_name == scope_data::file());
+ BOOST_CHECK(s3.line == line2);
+
+ BOOST_CHECK(it == sc->end());
+
+ // Second scope goes out
+ named_scope::pop_scope();
+
+ BOOST_CHECK(!named_scope::get_scopes().empty());
+ BOOST_CHECK_EQUAL(named_scope::get_scopes().size(), 1UL);
+
+ val = attr.get_value();
+ BOOST_REQUIRE(!!val);
+
+ sc = val.extract< scopes >();
+ BOOST_REQUIRE(!!sc);
+ BOOST_REQUIRE(!sc->empty());
+ BOOST_CHECK_EQUAL(sc->size(), 1UL);
+
+ scope const& s4 = sc->back(); // should be the same as front
+ BOOST_CHECK(s4.scope_name == scope_data::scope1());
+ BOOST_CHECK(s4.file_name == scope_data::file());
+ BOOST_CHECK(s4.line == line1);
+}
+
+// The test checks that detaching from thread works correctly
+BOOST_AUTO_TEST_CASE(detaching_from_thread)
+{
+ typedef attrs::named_scope named_scope;
+ typedef named_scope::sentry sentry;
+ typedef attrs::named_scope_list scopes;
+ typedef attrs::named_scope_entry scope;
+ typedef scope_test_data< char > scope_data;
+
+ named_scope attr;
+
+ sentry scope1(scope_data::scope1(), scope_data::file(), __LINE__);
+ logging::attribute_value val1 = attr.get_value();
+ val1.detach_from_thread();
+
+ sentry scope2(scope_data::scope2(), scope_data::file(), __LINE__);
+ logging::attribute_value val2 = attr.get_value();
+ val2.detach_from_thread();
+
+ logging::value_ref< scopes > sc1 = val1.extract< scopes >(), sc2 = val2.extract< scopes >();
+ BOOST_REQUIRE(!!sc1);
+ BOOST_REQUIRE(!!sc2);
+ BOOST_CHECK_EQUAL(sc1->size(), 1UL);
+ BOOST_CHECK_EQUAL(sc2->size(), 2UL);
+}
+
+// The test checks that output streaming is possible
+BOOST_AUTO_TEST_CASE(ostreaming)
+{
+ typedef attrs::named_scope named_scope;
+ typedef named_scope::sentry sentry;
+ typedef scope_test_data< char > scope_data;
+
+ sentry scope1(scope_data::scope1(), scope_data::file(), __LINE__);
+ sentry scope2(scope_data::scope2(), scope_data::file(), __LINE__);
+
+ std::basic_ostringstream< char > strm;
+ strm << named_scope::get_scopes();
+
+ BOOST_CHECK(!strm.str().empty());
+}
+
+// The test checks that the scope list becomes thread-independent after copying
+BOOST_AUTO_TEST_CASE(copying)
+{
+ typedef attrs::named_scope named_scope;
+ typedef named_scope::sentry sentry;
+ typedef attrs::named_scope_list scopes;
+ typedef attrs::named_scope_entry scope;
+ typedef scope_test_data< char > scope_data;
+
+ sentry scope1(scope_data::scope1(), scope_data::file(), __LINE__);
+ scopes sc = named_scope::get_scopes();
+ sentry scope2(scope_data::scope2(), scope_data::file(), __LINE__);
+ BOOST_CHECK_EQUAL(sc.size(), 1UL);
+ BOOST_CHECK_EQUAL(named_scope::get_scopes().size(), 2UL);
+}

Added: trunk/libs/log/test/run/attr_value_visitation.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/run/attr_value_visitation.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,238 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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_value_visitation.cpp
+ * \author Andrey Semashev
+ * \date 21.01.2009
+ *
+ * \brief This header contains tests for the attribute value extraction helpers.
+ */
+
+#define BOOST_TEST_MODULE attr_value_visitation
+
+#include <string>
+#include <boost/mpl/vector.hpp>
+#include <boost/test/included/unit_test.hpp>
+#include <boost/test/floating_point_comparison.hpp>
+#include <boost/log/attributes/value_visitation.hpp>
+#include <boost/log/attributes/constant.hpp>
+#include <boost/log/attributes/attribute_set.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include "char_definitions.hpp"
+
+namespace mpl = boost::mpl;
+namespace logging = boost::log;
+namespace attrs = logging::attributes;
+
+namespace {
+
+ // The receiver functional object that verifies the extracted attribute values
+ struct my_receiver
+ {
+ typedef void result_type;
+
+ enum type_expected
+ {
+ none_expected,
+ int_expected,
+ double_expected,
+ string_expected
+ };
+
+ my_receiver() : m_Expected(none_expected), m_Int(0), m_Double(0.0) {}
+
+ void set_expected()
+ {
+ m_Expected = none_expected;
+ }
+ void set_expected(int value)
+ {
+ m_Expected = int_expected;
+ m_Int = value;
+ }
+ void set_expected(double value)
+ {
+ m_Expected = double_expected;
+ m_Double = value;
+ }
+ void set_expected(std::string const& value)
+ {
+ m_Expected = string_expected;
+ m_String = value;
+ }
+
+ // Implement visitation logic for all supported types
+ void operator() (int const& value)
+ {
+ BOOST_CHECK_EQUAL(m_Expected, int_expected);
+ BOOST_CHECK_EQUAL(m_Int, value);
+ }
+ void operator() (double const& value)
+ {
+ BOOST_CHECK_EQUAL(m_Expected, double_expected);
+ BOOST_CHECK_CLOSE(m_Double, value, 0.001);
+ }
+ void operator() (std::string const& value)
+ {
+ BOOST_CHECK_EQUAL(m_Expected, string_expected);
+ BOOST_CHECK_EQUAL(m_String, value);
+ }
+ void operator() (char value)
+ {
+ // This one should not be called
+ BOOST_ERROR("The unexpected operator() has been called");
+ }
+
+ private:
+ type_expected m_Expected;
+ int m_Int;
+ double m_Double;
+ std::string m_String;
+ };
+
+} // namespace
+
+// The test checks invokers specialized on a single attribute value type
+BOOST_AUTO_TEST_CASE(single_type)
+{
+ typedef logging::attribute_set attr_set;
+ typedef logging::attribute_value_set attr_values;
+ typedef test_data< char > data;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+ attrs::constant< std::string > attr3("Hello, world!");
+
+ attr_set set1, set2, set3;
+ set1[data::attr1()] = attr1;
+ set1[data::attr2()] = attr2;
+
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+
+ my_receiver recv;
+
+ logging::value_visitor_invoker< int > invoker1;
+ logging::value_visitor_invoker< double > invoker2;
+ logging::value_visitor_invoker< std::string > invoker3;
+ logging::value_visitor_invoker< char > invoker4;
+
+ // These two extractors will find their values in the set
+ recv.set_expected(10);
+ BOOST_CHECK(invoker1(data::attr1(), values1, recv));
+
+ recv.set_expected(5.5);
+ BOOST_CHECK(invoker2(data::attr2(), values1, recv));
+
+ // This one will not
+ recv.set_expected();
+ BOOST_CHECK(!invoker3(data::attr3(), values1, recv));
+
+ // But it will find it in this set
+ set1[data::attr3()] = attr3;
+
+ attr_values values2(set1, set2, set3);
+ values2.freeze();
+
+ recv.set_expected("Hello, world!");
+ BOOST_CHECK(invoker3(data::attr3(), values2, recv));
+
+ // This one will find the sought attribute value, but it will have an incorrect type
+ recv.set_expected();
+ BOOST_CHECK(!invoker4(data::attr1(), values1, recv));
+
+ // This one is the same, but there is a value of the requested type in the set
+ BOOST_CHECK(!invoker1(data::attr2(), values1, recv));
+}
+
+
+// The test checks invokers specialized with type lists
+BOOST_AUTO_TEST_CASE(multiple_types)
+{
+ typedef logging::attribute_set attr_set;
+ typedef logging::attribute_value_set attr_values;
+ typedef test_data< char > data;
+ typedef mpl::vector< int, double, std::string, char >::type types;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+ attrs::constant< std::string > attr3("Hello, world!");
+
+ attr_set set1, set2, set3;
+ set1[data::attr1()] = attr1;
+ set1[data::attr2()] = attr2;
+
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+
+ my_receiver recv;
+
+ logging::value_visitor_invoker< types > invoker;
+
+ // These two extractors will find their values in the set
+ recv.set_expected(10);
+ BOOST_CHECK(invoker(data::attr1(), values1, recv));
+
+ recv.set_expected(5.5);
+ BOOST_CHECK(invoker(data::attr2(), values1, recv));
+
+ // This one will not
+ recv.set_expected();
+ BOOST_CHECK(!invoker(data::attr3(), values1, recv));
+
+ // But it will find it in this set
+ set1[data::attr3()] = attr3;
+
+ attr_values values2(set1, set2, set3);
+ values2.freeze();
+
+ recv.set_expected("Hello, world!");
+ BOOST_CHECK(invoker(data::attr3(), values2, recv));
+}
+
+// The test verifies the visit function
+BOOST_AUTO_TEST_CASE(visit_function)
+{
+ typedef logging::attribute_set attr_set;
+ typedef logging::attribute_value_set attr_values;
+ typedef test_data< char > data;
+ typedef mpl::vector< int, double, std::string, char >::type types;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+ attrs::constant< std::string > attr3("Hello, world!");
+
+ attr_set set1, set2, set3;
+ set1[data::attr1()] = attr1;
+ set1[data::attr2()] = attr2;
+
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+
+ my_receiver recv;
+
+ // These two extractors will find their values in the set
+ recv.set_expected(10);
+ BOOST_CHECK(logging::visit< types >(data::attr1(), values1, recv));
+
+ recv.set_expected(5.5);
+ BOOST_CHECK(logging::visit< double >(data::attr2(), values1, recv));
+
+ // These will not
+ recv.set_expected();
+ BOOST_CHECK(!logging::visit< types >(data::attr3(), values1, recv));
+ BOOST_CHECK(!logging::visit< char >(data::attr1(), values1, recv));
+
+ // But it will find it in this set
+ set1[data::attr3()] = attr3;
+
+ attr_values values2(set1, set2, set3);
+ values2.freeze();
+
+ recv.set_expected("Hello, world!");
+ BOOST_CHECK(logging::visit< std::string >(data::attr3(), values2, recv));
+}

Added: trunk/libs/log/test/run/core.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/run/core.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,246 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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.cpp
+ * \author Andrey Semashev
+ * \date 08.02.2009
+ *
+ * \brief This header contains tests for the logging core.
+ */
+
+#define BOOST_TEST_MODULE core
+
+#include <cstddef>
+#include <map>
+#include <string>
+#include <boost/shared_ptr.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/test/included/unit_test.hpp>
+#include <boost/log/core/core.hpp>
+#include <boost/log/attributes/constant.hpp>
+#include <boost/log/attributes/attribute_set.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sinks/sink.hpp>
+#include <boost/log/core/record.hpp>
+#ifndef BOOST_LOG_NO_THREADS
+#include <boost/thread/thread.hpp>
+#endif // BOOST_LOG_NO_THREADS
+#include "char_definitions.hpp"
+#include "test_sink.hpp"
+
+namespace logging = boost::log;
+namespace attrs = logging::attributes;
+namespace sinks = logging::sinks;
+namespace expr = logging::expressions;
+
+// The test checks that message filtering works
+BOOST_AUTO_TEST_CASE(filtering)
+{
+ typedef logging::attribute_set attr_set;
+ typedef logging::core core;
+ typedef logging::record record_type;
+ typedef std::basic_string< char > string;
+ typedef test_data< char > data;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+
+ attr_set set1;
+ set1[data::attr1()] = attr1;
+ set1[data::attr2()] = attr2;
+
+ boost::shared_ptr< core > pCore = core::get();
+ boost::shared_ptr< test_sink > pSink(new test_sink());
+ pCore->add_sink(pSink);
+
+ // No filtering at all
+ {
+ record_type rec = pCore->open_record(set1);
+ BOOST_REQUIRE(rec);
+ pCore->push_record(boost::move(rec));
+ BOOST_CHECK_EQUAL(pSink->m_RecordCounter, 1UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr1()], 1UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr2()], 1UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr3()], 0UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr4()], 0UL);
+ pSink->clear();
+ }
+
+ // Core-level filtering
+ {
+ pCore->set_filter(expr::has_attr(data::attr3()));
+ record_type rec = pCore->open_record(set1);
+ BOOST_CHECK(!rec);
+ BOOST_CHECK_EQUAL(pSink->m_RecordCounter, 0UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr1()], 0UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr2()], 0UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr3()], 0UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr4()], 0UL);
+ pSink->clear();
+ }
+ {
+ pCore->set_filter(expr::has_attr(data::attr2()));
+ record_type rec = pCore->open_record(set1);
+ BOOST_REQUIRE(rec);
+ pCore->push_record(boost::move(rec));
+ BOOST_CHECK_EQUAL(pSink->m_RecordCounter, 1UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr1()], 1UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr2()], 1UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr3()], 0UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr4()], 0UL);
+ pSink->clear();
+ }
+
+ // Sink-level filtering
+ {
+ pCore->reset_filter();
+ pSink->set_filter(expr::has_attr(data::attr2()));
+ record_type rec = pCore->open_record(set1);
+ BOOST_REQUIRE(rec);
+ pCore->push_record(boost::move(rec));
+ BOOST_CHECK_EQUAL(pSink->m_RecordCounter, 1UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr1()], 1UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr2()], 1UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr3()], 0UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr4()], 0UL);
+ pSink->clear();
+ }
+ {
+ pSink->set_filter(expr::has_attr(data::attr3()));
+ record_type rec = pCore->open_record(set1);
+ BOOST_CHECK(!rec);
+ BOOST_CHECK_EQUAL(pSink->m_RecordCounter, 0UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr1()], 0UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr2()], 0UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr3()], 0UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr4()], 0UL);
+ pSink->clear();
+ pSink->reset_filter();
+ }
+ // Only one sink of the two accepts the record
+ {
+ pSink->set_filter(expr::has_attr(data::attr2()));
+
+ boost::shared_ptr< test_sink > pSink2(new test_sink());
+ pCore->add_sink(pSink2);
+ pSink2->set_filter(expr::has_attr(data::attr3()));
+
+ record_type rec = pCore->open_record(set1);
+ BOOST_REQUIRE(rec);
+ pCore->push_record(boost::move(rec));
+
+ BOOST_CHECK_EQUAL(pSink->m_RecordCounter, 1UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr1()], 1UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr2()], 1UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr3()], 0UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr4()], 0UL);
+ pSink->clear();
+
+ BOOST_CHECK_EQUAL(pSink2->m_RecordCounter, 0UL);
+ BOOST_CHECK_EQUAL(pSink2->m_Consumed[data::attr1()], 0UL);
+ BOOST_CHECK_EQUAL(pSink2->m_Consumed[data::attr2()], 0UL);
+ BOOST_CHECK_EQUAL(pSink2->m_Consumed[data::attr3()], 0UL);
+ BOOST_CHECK_EQUAL(pSink2->m_Consumed[data::attr4()], 0UL);
+ pCore->remove_sink(pSink2);
+ }
+
+ pCore->remove_sink(pSink);
+ pCore->reset_filter();
+}
+
+#ifndef BOOST_LOG_NO_THREADS
+namespace {
+
+ //! A test routine that runs in a separate thread
+ void thread_attributes_test()
+ {
+ typedef test_data< char > data;
+ typedef logging::core core;
+ typedef logging::record record_type;
+ typedef std::basic_string< char > string;
+ typedef logging::attribute_set attr_set;
+ attrs::constant< short > attr4(255);
+
+ boost::shared_ptr< core > pCore = core::get();
+ pCore->add_thread_attribute(data::attr4(), attr4);
+
+ attr_set set1;
+ record_type rec = pCore->open_record(set1);
+ BOOST_CHECK(rec);
+ if (rec)
+ pCore->push_record(boost::move(rec));
+ }
+
+} // namespace
+#endif // BOOST_LOG_NO_THREADS
+
+// The test checks that global and thread-specific attributes work
+BOOST_AUTO_TEST_CASE(attributes)
+{
+ typedef logging::attribute_set attr_set;
+ typedef logging::core core;
+ typedef logging::record record_type;
+ typedef std::basic_string< char > string;
+ typedef test_data< char > data;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+ attrs::constant< std::string > attr3("Hello, world!");
+
+ attr_set set1;
+ set1[data::attr1()] = attr1;
+
+ boost::shared_ptr< core > pCore = core::get();
+ boost::shared_ptr< test_sink > pSink(new test_sink());
+ pCore->add_sink(pSink);
+
+ attr_set::iterator itGlobal = pCore->add_global_attribute(data::attr2(), attr2).first;
+ attr_set::iterator itThread = pCore->add_thread_attribute(data::attr3(), attr3).first;
+
+ {
+ attr_set glob = pCore->get_global_attributes();
+ BOOST_CHECK_EQUAL(glob.size(), 1UL);
+ BOOST_CHECK_EQUAL(glob.count(data::attr2()), 1UL);
+
+ attr_set thr = pCore->get_thread_attributes();
+ BOOST_CHECK_EQUAL(thr.size(), 1UL);
+ BOOST_CHECK_EQUAL(thr.count(data::attr3()), 1UL);
+ }
+ {
+ record_type rec = pCore->open_record(set1);
+ BOOST_REQUIRE(rec);
+ pCore->push_record(boost::move(rec));
+ BOOST_CHECK_EQUAL(pSink->m_RecordCounter, 1UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr1()], 1UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr2()], 1UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr3()], 1UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr4()], 0UL);
+ pSink->clear();
+ }
+#ifndef BOOST_LOG_NO_THREADS
+ {
+ boost::thread th(&thread_attributes_test);
+ th.join();
+ BOOST_CHECK_EQUAL(pSink->m_RecordCounter, 1UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr1()], 0UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr2()], 1UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr3()], 0UL);
+ BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr4()], 1UL);
+ pSink->clear();
+
+ // Thread-specific attributes must not interfere
+ attr_set thr = pCore->get_thread_attributes();
+ BOOST_CHECK_EQUAL(thr.size(), 1UL);
+ BOOST_CHECK_EQUAL(thr.count(data::attr3()), 1UL);
+ }
+#endif // BOOST_LOG_NO_THREADS
+
+ pCore->remove_global_attribute(itGlobal);
+ pCore->remove_thread_attribute(itThread);
+ pCore->remove_sink(pSink);
+}

Added: trunk/libs/log/test/run/filt_attr.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/run/filt_attr.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,403 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 filt_attr.cpp
+ * \author Andrey Semashev
+ * \date 31.01.2009
+ *
+ * \brief This header contains tests for the \c attr filter.
+ */
+
+#define BOOST_TEST_MODULE filt_attr
+
+#include <memory>
+#include <string>
+#include <algorithm>
+#include <boost/regex.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/phoenix/bind.hpp>
+#include <boost/test/included/unit_test.hpp>
+#include <boost/log/attributes/constant.hpp>
+#include <boost/log/attributes/attribute_set.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include <boost/log/utility/type_dispatch/standard_types.hpp>
+#include <boost/log/support/regex.hpp>
+#include <boost/log/expressions.hpp>
+#include "char_definitions.hpp"
+
+namespace phoenix = boost::phoenix;
+
+namespace logging = boost::log;
+namespace attrs = logging::attributes;
+namespace expr = logging::expressions;
+
+// The test checks that general conditions work
+BOOST_AUTO_TEST_CASE(general_conditions)
+{
+ typedef logging::attribute_set attr_set;
+ typedef logging::attribute_value_set attr_values;
+ typedef logging::filter filter;
+ typedef test_data< char > data;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+ attrs::constant< std::string > attr3("Hello, world!");
+
+ attr_set set1, set2, set3;
+ set1[data::attr1()] = attr1;
+ set1[data::attr2()] = attr2;
+ set1[data::attr3()] = attr3;
+
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+
+ filter f = expr::attr< int >(data::attr1()) == 10;
+ BOOST_CHECK(f(values1));
+
+ f = expr::attr< int >(data::attr1()) < 0;
+ BOOST_CHECK(!f(values1));
+
+ f = expr::attr< float >(data::attr1()).or_throw() > 0;
+ BOOST_CHECK_THROW(f(values1), logging::runtime_error);
+ f = expr::attr< float >(data::attr1()) > 0;
+ BOOST_CHECK(!f(values1));
+
+ f = expr::attr< int >(data::attr4()).or_throw() >= 1;
+ BOOST_CHECK_THROW(f(values1), logging::runtime_error);
+ f = expr::attr< int >(data::attr4()) >= 1;
+ BOOST_CHECK(!f(values1));
+
+ f = expr::attr< int >(data::attr4()) < 1;
+ BOOST_CHECK(!f(values1));
+
+ f = expr::attr< logging::numeric_types >(data::attr2()) > 5;
+ BOOST_CHECK(f(values1));
+
+ f = expr::attr< std::string >(data::attr3()) == "Hello, world!";
+ BOOST_CHECK(f(values1));
+
+ f = expr::attr< std::string >(data::attr3()) > "AAA";
+ BOOST_CHECK(f(values1));
+}
+
+// The test checks that is_in_range condition works
+BOOST_AUTO_TEST_CASE(in_range_check)
+{
+ typedef logging::attribute_set attr_set;
+ typedef logging::attribute_value_set attr_values;
+ typedef logging::filter filter;
+ typedef test_data< char > data;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+ attrs::constant< std::string > attr3("Hello, world!");
+
+ attr_set set1, set2, set3;
+ set1[data::attr1()] = attr1;
+ set1[data::attr2()] = attr2;
+ set1[data::attr3()] = attr3;
+
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+
+ filter f = expr::is_in_range(expr::attr< int >(data::attr1()), 5, 20);
+ BOOST_CHECK(f(values1));
+
+ f = expr::is_in_range(expr::attr< int >(data::attr1()), 5, 10);
+ BOOST_CHECK(!f(values1));
+
+ f = expr::is_in_range(expr::attr< int >(data::attr1()), 10, 20);
+ BOOST_CHECK(f(values1));
+
+ f = expr::is_in_range(expr::attr< logging::numeric_types >(data::attr2()), 5, 6);
+ BOOST_CHECK(f(values1));
+
+ f = expr::is_in_range(expr::attr< std::string >(data::attr3()), "AAA", "zzz");
+ BOOST_CHECK(f(values1));
+
+ // Check that strings are saved into the filter by value
+ char buf1[128];
+ char buf2[128];
+ std::strcpy(buf1, "AAA");
+ std::strcpy(buf2, "zzz");
+ f = expr::is_in_range(expr::attr< std::string >(data::attr3()), buf1, buf2);
+ std::fill_n(buf1, sizeof(buf1), static_cast< char >(0));
+ std::fill_n(buf2, sizeof(buf2), static_cast< char >(0));
+ BOOST_CHECK(f(values1));
+
+ std::strcpy(buf1, "AAA");
+ std::strcpy(buf2, "zzz");
+ f = expr::is_in_range(expr::attr< std::string >(data::attr3()),
+ static_cast< const char* >(buf1), static_cast< const char* >(buf2));
+ std::fill_n(buf1, sizeof(buf1), static_cast< char >(0));
+ std::fill_n(buf2, sizeof(buf2), static_cast< char >(0));
+ BOOST_CHECK(f(values1));
+}
+
+namespace {
+
+ struct predicate
+ {
+ typedef bool result_type;
+
+ explicit predicate(unsigned int& present_counter, bool& result) :
+ m_PresentCounter(present_counter),
+ m_Result(result)
+ {
+ }
+
+ template< typename T, typename TagT >
+ result_type operator() (logging::value_ref< T, TagT > const& val) const
+ {
+ m_PresentCounter += !val.empty();
+ return m_Result;
+ }
+
+ private:
+ unsigned int& m_PresentCounter;
+ bool& m_Result;
+ };
+
+} // namespace
+
+// The test checks that phoenix::bind interaction works
+BOOST_AUTO_TEST_CASE(bind_support_check)
+{
+ typedef logging::attribute_set attr_set;
+ typedef logging::attribute_value_set attr_values;
+ typedef logging::filter filter;
+ typedef test_data< char > data;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+ attrs::constant< std::string > attr3("Hello, world!");
+
+ attr_set set1, set2, set3;
+ set1[data::attr1()] = attr1;
+ set1[data::attr2()] = attr2;
+ set1[data::attr3()] = attr3;
+
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+
+ unsigned int present_counter = 0;
+ bool predicate_result = false;
+
+ filter f = phoenix::bind(predicate(present_counter, predicate_result), expr::attr< int >(data::attr1()));
+ BOOST_CHECK_EQUAL(f(values1), predicate_result);
+ BOOST_CHECK_EQUAL(present_counter, 1U);
+
+ predicate_result = true;
+ BOOST_CHECK_EQUAL(f(values1), predicate_result);
+ BOOST_CHECK_EQUAL(present_counter, 2U);
+
+ f = phoenix::bind(predicate(present_counter, predicate_result), expr::attr< logging::numeric_types >(data::attr2()));
+ BOOST_CHECK_EQUAL(f(values1), predicate_result);
+ BOOST_CHECK_EQUAL(present_counter, 3U);
+
+ f = phoenix::bind(predicate(present_counter, predicate_result), expr::attr< int >(data::attr2()).or_throw());
+ BOOST_CHECK_THROW(f(values1), logging::runtime_error);
+ f = phoenix::bind(predicate(present_counter, predicate_result), expr::attr< int >(data::attr2()));
+ BOOST_CHECK_EQUAL(f(values1), true);
+ BOOST_CHECK_EQUAL(present_counter, 3U);
+
+ f = phoenix::bind(predicate(present_counter, predicate_result), expr::attr< int >(data::attr4()).or_throw());
+ BOOST_CHECK_THROW(f(values1), logging::runtime_error);
+ f = phoenix::bind(predicate(present_counter, predicate_result), expr::attr< int >(data::attr4()));
+ BOOST_CHECK_EQUAL(f(values1), true);
+ BOOST_CHECK_EQUAL(present_counter, 3U);
+}
+
+// The test checks that begins_with condition works
+BOOST_AUTO_TEST_CASE(begins_with_check)
+{
+ typedef logging::attribute_set attr_set;
+ typedef logging::attribute_value_set attr_values;
+ typedef logging::filter filter;
+ typedef test_data< char > data;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+ attrs::constant< std::string > attr3("Hello, world!");
+
+ attr_set set1, set2, set3;
+ set1[data::attr1()] = attr1;
+ set1[data::attr2()] = attr2;
+ set1[data::attr3()] = attr3;
+
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+
+ filter f = expr::begins_with(expr::attr< std::string >(data::attr3()), "Hello");
+ BOOST_CHECK(f(values1));
+
+ f = expr::begins_with(expr::attr< std::string >(data::attr3()), "hello");
+ BOOST_CHECK(!f(values1));
+
+ f = expr::begins_with(expr::attr< std::string >(data::attr3()).or_throw(), "Bye");
+ BOOST_CHECK(!f(values1));
+
+ f = expr::begins_with(expr::attr< std::string >(data::attr3()).or_throw(), "world!");
+ BOOST_CHECK(!f(values1));
+
+ f = expr::begins_with(expr::attr< std::string >(data::attr2()), "Hello");
+ BOOST_CHECK(!f(values1));
+
+ f = expr::begins_with(expr::attr< std::string >(data::attr4()), "Hello");
+ BOOST_CHECK(!f(values1));
+}
+
+// The test checks that ends_with condition works
+BOOST_AUTO_TEST_CASE(ends_with_check)
+{
+ typedef logging::attribute_set attr_set;
+ typedef logging::attribute_value_set attr_values;
+ typedef logging::filter filter;
+ typedef test_data< char > data;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+ attrs::constant< std::string > attr3("Hello, world!");
+
+ attr_set set1, set2, set3;
+ set1[data::attr1()] = attr1;
+ set1[data::attr2()] = attr2;
+ set1[data::attr3()] = attr3;
+
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+
+ filter f = expr::ends_with(expr::attr< std::string >(data::attr3()), "world!");
+ BOOST_CHECK(f(values1));
+
+ f = expr::ends_with(expr::attr< std::string >(data::attr3()), "World!");
+ BOOST_CHECK(!f(values1));
+
+ f = expr::ends_with(expr::attr< std::string >(data::attr3()).or_throw(), "Bye");
+ BOOST_CHECK(!f(values1));
+
+ f = expr::ends_with(expr::attr< std::string >(data::attr3()).or_throw(), "Hello");
+ BOOST_CHECK(!f(values1));
+
+ f = expr::ends_with(expr::attr< std::string >(data::attr2()), "world!");
+ BOOST_CHECK(!f(values1));
+
+ f = expr::ends_with(expr::attr< std::string >(data::attr4()), "world!");
+ BOOST_CHECK(!f(values1));
+}
+
+// The test checks that contains condition works
+BOOST_AUTO_TEST_CASE(contains_check)
+{
+ typedef logging::attribute_set attr_set;
+ typedef logging::attribute_value_set attr_values;
+ typedef logging::filter filter;
+ typedef test_data< char > data;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+ attrs::constant< std::string > attr3("Hello, world!");
+
+ attr_set set1, set2, set3;
+ set1[data::attr1()] = attr1;
+ set1[data::attr2()] = attr2;
+ set1[data::attr3()] = attr3;
+
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+
+ filter f = expr::contains(expr::attr< std::string >(data::attr3()), "Hello");
+ BOOST_CHECK(f(values1));
+
+ f = expr::contains(expr::attr< std::string >(data::attr3()), "hello");
+ BOOST_CHECK(!f(values1));
+
+ f = expr::contains(expr::attr< std::string >(data::attr3()).or_throw(), "o, w");
+ BOOST_CHECK(f(values1));
+
+ f = expr::contains(expr::attr< std::string >(data::attr3()).or_throw(), "world!");
+ BOOST_CHECK(f(values1));
+
+ f = expr::contains(expr::attr< std::string >(data::attr2()), "Hello");
+ BOOST_CHECK(!f(values1));
+
+ f = expr::contains(expr::attr< std::string >(data::attr4()), "Hello");
+ BOOST_CHECK(!f(values1));
+}
+
+// The test checks that matches condition works
+BOOST_AUTO_TEST_CASE(matches_check)
+{
+ typedef logging::attribute_set attr_set;
+ typedef logging::attribute_value_set attr_values;
+ typedef logging::filter filter;
+ typedef test_data< char > data;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+ attrs::constant< std::string > attr3("Hello, world!");
+
+ attr_set set1, set2, set3;
+ set1[data::attr1()] = attr1;
+ set1[data::attr2()] = attr2;
+ set1[data::attr3()] = attr3;
+
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+
+ boost::regex rex("hello");
+ filter f = expr::matches(expr::attr< std::string >(data::attr3()), rex);
+ BOOST_CHECK(!f(values1));
+
+ rex = ".*world.*";
+ f = expr::matches(expr::attr< std::string >(data::attr3()).or_throw(), rex);
+ BOOST_CHECK(f(values1));
+
+ rex = ".*";
+ f = expr::matches(expr::attr< std::string >(data::attr2()), rex);
+ BOOST_CHECK(!f(values1));
+
+ f = expr::matches(expr::attr< std::string >(data::attr4()), rex);
+ BOOST_CHECK(!f(values1));
+}
+
+// The test checks that the filter composition works
+BOOST_AUTO_TEST_CASE(composition_check)
+{
+ typedef logging::attribute_set attr_set;
+ typedef logging::attribute_value_set attr_values;
+ typedef logging::filter filter;
+ typedef test_data< char > data;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+ attrs::constant< std::string > attr3("Hello, world!");
+
+ attr_set set1, set2, set3;
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+ set1[data::attr2()] = attr2;
+ attr_values values2(set1, set2, set3);
+ values2.freeze();
+ set1[data::attr3()] = attr3;
+ set1[data::attr1()] = attr1;
+ attr_values values3(set1, set2, set3);
+ values3.freeze();
+
+ filter f =
+ expr::attr< int >(data::attr1()) <= 10 ||
+ expr::is_in_range(expr::attr< double >(data::attr2()), 2.2, 7.7);
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(f(values2));
+ BOOST_CHECK(f(values3));
+
+ f = expr::attr< int >(data::attr1()) == 10 &&
+ expr::begins_with(expr::attr< std::string >(data::attr3()), "Hello");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(!f(values2));
+ BOOST_CHECK(f(values3));
+}

Added: trunk/libs/log/test/run/filt_has_attr.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/run/filt_has_attr.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,102 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 filt_has_attr.cpp
+ * \author Andrey Semashev
+ * \date 31.01.2009
+ *
+ * \brief This header contains tests for the \c has_attr filter.
+ */
+
+#define BOOST_TEST_MODULE filt_has_attr
+
+#include <string>
+#include <boost/mpl/vector.hpp>
+#include <boost/test/included/unit_test.hpp>
+#include <boost/log/attributes/constant.hpp>
+#include <boost/log/attributes/attribute_set.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include <boost/log/expressions.hpp>
+#include "char_definitions.hpp"
+
+namespace logging = boost::log;
+namespace attrs = logging::attributes;
+namespace expr = logging::expressions;
+
+// The test checks that the filter detects the attribute value presence
+BOOST_AUTO_TEST_CASE(presence_check)
+{
+ typedef logging::attribute_set attr_set;
+ typedef logging::attribute_value_set attr_values;
+ typedef logging::filter filter;
+ typedef test_data< char > data;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+ attrs::constant< std::string > attr3("Hello, world!");
+
+ attr_set set1, set2, set3;
+ set1[data::attr1()] = attr1;
+ set1[data::attr2()] = attr2;
+ set1[data::attr3()] = attr3;
+
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+
+ filter f = expr::has_attr(data::attr1());
+ BOOST_CHECK(f(values1));
+
+ f = expr::has_attr(data::attr4());
+ BOOST_CHECK(!f(values1));
+
+ f = expr::has_attr< double >(data::attr2());
+ BOOST_CHECK(f(values1));
+
+ f = expr::has_attr< double >(data::attr3());
+ BOOST_CHECK(!f(values1));
+
+ typedef mpl::vector< unsigned int, char, std::string >::type value_types;
+ f = expr::has_attr< value_types >(data::attr3());
+ BOOST_CHECK(f(values1));
+
+ f = expr::has_attr< value_types >(data::attr1());
+ BOOST_CHECK(!f(values1));
+}
+
+// The test checks that the filter composition works
+BOOST_AUTO_TEST_CASE(composition_check)
+{
+ typedef logging::attribute_set attr_set;
+ typedef logging::attribute_value_set attr_values;
+ typedef logging::filter filter;
+ typedef test_data< char > data;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+ attrs::constant< std::string > attr3("Hello, world!");
+
+ attr_set set1, set2, set3;
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+ set1[data::attr2()] = attr2;
+ attr_values values2(set1, set2, set3);
+ values2.freeze();
+ set1[data::attr3()] = attr3;
+ set1[data::attr1()] = attr1;
+ attr_values values3(set1, set2, set3);
+ values3.freeze();
+
+ filter f = expr::has_attr(data::attr1()) || expr::has_attr< double >(data::attr2());
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(f(values2));
+ BOOST_CHECK(f(values3));
+
+ f = expr::has_attr(data::attr1()) && expr::has_attr< double >(data::attr2());
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(!f(values2));
+ BOOST_CHECK(f(values3));
+}

Added: trunk/libs/log/test/run/form_attr.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/run/form_attr.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,123 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 form_attr.cpp
+ * \author Andrey Semashev
+ * \date 01.02.2009
+ *
+ * \brief This header contains tests for the \c attr formatter.
+ */
+
+#define BOOST_TEST_MODULE form_attr
+
+#include <memory>
+#include <string>
+#include <iomanip>
+#include <ostream>
+#include <algorithm>
+#include <boost/test/included/unit_test.hpp>
+#include <boost/log/attributes/constant.hpp>
+#include <boost/log/attributes/attribute_set.hpp>
+#include <boost/log/utility/type_dispatch/standard_types.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/core/record.hpp>
+#include "char_definitions.hpp"
+#include "make_record.hpp"
+
+namespace logging = boost::log;
+namespace attrs = logging::attributes;
+namespace expr = logging::expressions;
+
+namespace {
+
+ class my_class
+ {
+ int m_Data;
+
+ public:
+ explicit my_class(int data) : m_Data(data) {}
+
+ template< typename CharT, typename TraitsT >
+ friend std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, my_class const& obj)
+ {
+ strm << "[data: " << obj.m_Data << "]";
+ return strm;
+ }
+ };
+
+} // namespace
+
+// The test checks that default formatting work
+BOOST_AUTO_TEST_CASE_TEMPLATE(default_formatting, CharT, char_types)
+{
+ typedef logging::record_view record_view;
+ typedef logging::attribute_set attr_set;
+ typedef std::basic_string< CharT > string;
+ typedef logging::basic_formatting_ostream< CharT > osstream;
+ typedef logging::basic_formatter< CharT > formatter;
+ typedef test_data< CharT > data;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+ attrs::constant< my_class > attr3(my_class(77));
+
+ attr_set set1;
+ set1[data::attr1()] = attr1;
+ set1[data::attr2()] = attr2;
+ set1[data::attr3()] = attr3;
+
+ record_view rec = make_record_view(set1);
+
+ // Check for various modes of attribute value type specification
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream << expr::attr< int >(data::attr1()) << expr::attr< double >(data::attr2());
+ f(rec, strm1);
+ strm2 << 10 << 5.5;
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream << expr::attr< logging::numeric_types >(data::attr1()) << expr::attr< logging::numeric_types >(data::attr2());
+ f(rec, strm1);
+ strm2 << 10 << 5.5;
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+ // Check that custom types as attribute values are also supported
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream << expr::attr< my_class >(data::attr3());
+ f(rec, strm1);
+ strm2 << my_class(77);
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+ // Check how missing attribute values are handled
+ {
+ string str1;
+ osstream strm1(str1);
+ formatter f = expr::stream
+ << expr::attr< int >(data::attr1())
+ << expr::attr< int >(data::attr4()).or_throw()
+ << expr::attr< double >(data::attr2());
+ BOOST_CHECK_THROW(f(rec, strm1), logging::runtime_error);
+ }
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream
+ << expr::attr< int >(data::attr1())
+ << expr::attr< int >(data::attr4())
+ << expr::attr< double >(data::attr2());
+ f(rec, strm1);
+ strm2 << 10 << 5.5;
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+}

Added: trunk/libs/log/test/run/form_date_time.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/run/form_date_time.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,212 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 form_date_time.cpp
+ * \author Andrey Semashev
+ * \date 07.02.2009
+ *
+ * \brief This header contains tests for the date and time formatters.
+ */
+
+#define BOOST_TEST_MODULE form_date_time
+
+#include <memory>
+#include <locale>
+#include <string>
+#include <iomanip>
+#include <ostream>
+#include <algorithm>
+#include <boost/date_time.hpp>
+#include <boost/test/included/unit_test.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/attributes/constant.hpp>
+#include <boost/log/attributes/attribute_set.hpp>
+#include <boost/log/utility/string_literal.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/core/record.hpp>
+#include <boost/log/support/date_time.hpp>
+#include "char_definitions.hpp"
+#include "make_record.hpp"
+
+namespace logging = boost::log;
+namespace attrs = logging::attributes;
+namespace expr = logging::expressions;
+namespace keywords = logging::keywords;
+
+typedef boost::posix_time::ptime ptime;
+typedef boost::gregorian::date gdate;
+typedef ptime::time_duration_type duration;
+
+namespace {
+
+ template< typename CharT >
+ struct date_time_formats;
+
+#ifdef BOOST_LOG_USE_CHAR
+ template< >
+ struct date_time_formats< char >
+ {
+ typedef logging::basic_string_literal< char > string_literal_type;
+
+ static string_literal_type default_date_format() { return logging::str_literal("%Y-%b-%d"); }
+ static string_literal_type default_time_format() { return logging::str_literal("%H:%M:%S.%f"); }
+ static string_literal_type default_date_time_format() { return logging::str_literal("%Y-%b-%d %H:%M:%S.%f"); }
+ static string_literal_type default_time_duration_format() { return logging::str_literal("%-%H:%M:%S.%f"); }
+
+ static string_literal_type date_format() { return logging::str_literal("%d/%m/%Y"); }
+ static string_literal_type time_format() { return logging::str_literal("%H.%M.%S"); }
+ static string_literal_type date_time_format() { return logging::str_literal("%d/%m/%Y %H.%M.%S"); }
+ static string_literal_type time_duration_format() { return logging::str_literal("%+%H.%M.%S.%f"); }
+ };
+#endif // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+ template< >
+ struct date_time_formats< wchar_t >
+ {
+ typedef logging::basic_string_literal< wchar_t > string_literal_type;
+
+ static string_literal_type default_date_format() { return logging::str_literal(L"%Y-%b-%d"); }
+ static string_literal_type default_time_format() { return logging::str_literal(L"%H:%M:%S.%f"); }
+ static string_literal_type default_date_time_format() { return logging::str_literal(L"%Y-%b-%d %H:%M:%S.%f"); }
+ static string_literal_type default_time_duration_format() { return logging::str_literal(L"%-%H:%M:%S.%f"); }
+
+ static string_literal_type date_format() { return logging::str_literal(L"%d/%m/%Y"); }
+ static string_literal_type time_format() { return logging::str_literal(L"%H.%M.%S"); }
+ static string_literal_type date_time_format() { return logging::str_literal(L"%d/%m/%Y %H.%M.%S"); }
+ static string_literal_type time_duration_format() { return logging::str_literal(L"%+%H.%M.%S.%f"); }
+ };
+#endif // BOOST_LOG_USE_WCHAR_T
+
+} // namespace
+
+// The test checks that date_time formatting work
+BOOST_AUTO_TEST_CASE_TEMPLATE(date_time, CharT, char_types)
+{
+ typedef logging::attribute_set attr_set;
+ typedef std::basic_string< CharT > string;
+ typedef logging::basic_formatting_ostream< CharT > osstream;
+ typedef logging::record_view record_view;
+ typedef logging::basic_formatter< CharT > formatter;
+ typedef test_data< CharT > data;
+ typedef date_time_formats< CharT > formats;
+ typedef boost::date_time::time_facet< ptime, CharT > facet;
+
+ ptime t1(gdate(2009, 2, 7), ptime::time_duration_type(14, 40, 15));
+ attrs::constant< ptime > attr1(t1);
+
+ attr_set set1;
+ set1[data::attr1()] = attr1;
+
+ record_view rec = make_record_view(set1);
+
+ // Check for various formats specification
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream << expr::format_date_time< ptime >(data::attr1(), formats::default_date_time_format().c_str());
+ f(rec, strm1);
+ strm2.imbue(std::locale(strm2.getloc(), new facet(formats::default_date_time_format().c_str())));
+ strm2 << t1;
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream << expr::format_date_time< ptime >(data::attr1(), formats::date_time_format().c_str());
+ f(rec, strm1);
+ strm2.imbue(std::locale(strm2.getloc(), new facet(formats::date_time_format().c_str())));
+ strm2 << t1;
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+}
+
+// The test checks that date formatting work
+BOOST_AUTO_TEST_CASE_TEMPLATE(date, CharT, char_types)
+{
+ typedef logging::attribute_set attr_set;
+ typedef std::basic_string< CharT > string;
+ typedef logging::basic_formatting_ostream< CharT > osstream;
+ typedef logging::record_view record_view;
+ typedef logging::basic_formatter< CharT > formatter;
+ typedef test_data< CharT > data;
+ typedef date_time_formats< CharT > formats;
+ typedef boost::date_time::date_facet< gdate, CharT > facet;
+
+ gdate d1(2009, 2, 7);
+ attrs::constant< gdate > attr1(d1);
+
+ attr_set set1;
+ set1[data::attr1()] = attr1;
+
+ record_view rec = make_record_view(set1);
+
+ // Check for various formats specification
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream << expr::format_date_time< gdate >(data::attr1(), formats::default_date_format().c_str());
+ f(rec, strm1);
+ strm2.imbue(std::locale(strm2.getloc(), new facet(formats::default_date_format().c_str())));
+ strm2 << d1;
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream << expr::format_date_time< gdate >(data::attr1(), formats::date_format().c_str());
+ f(rec, strm1);
+ strm2.imbue(std::locale(strm2.getloc(), new facet(formats::date_format().c_str())));
+ strm2 << d1;
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+}
+
+// The test checks that time_duration formatting work
+BOOST_AUTO_TEST_CASE_TEMPLATE(time_duration, CharT, char_types)
+{
+ typedef logging::attribute_set attr_set;
+ typedef std::basic_string< CharT > string;
+ typedef logging::basic_formatting_ostream< CharT > osstream;
+ typedef logging::record_view record_view;
+ typedef logging::basic_formatter< CharT > formatter;
+ typedef test_data< CharT > data;
+ typedef date_time_formats< CharT > formats;
+ typedef boost::date_time::time_facet< ptime, CharT > facet;
+
+ duration t1(14, 40, 15);
+ attrs::constant< duration > attr1(t1);
+
+ attr_set set1;
+ set1[data::attr1()] = attr1;
+
+ record_view rec = make_record_view(set1);
+
+ // Check for various formats specification
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream << expr::format_date_time< duration >(data::attr1(), formats::default_time_duration_format().c_str());
+ f(rec, strm1);
+ facet* fac = new facet();
+ fac->time_duration_format(formats::default_time_duration_format().c_str());
+ strm2.imbue(std::locale(strm2.getloc(), fac));
+ strm2 << t1;
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream << expr::format_date_time< duration >(data::attr1(), formats::time_duration_format().c_str());
+ f(rec, strm1);
+ facet* fac = new facet();
+ fac->time_duration_format(formats::time_duration_format().c_str());
+ strm2.imbue(std::locale(strm2.getloc(), fac));
+ strm2 << t1;
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+}

Added: trunk/libs/log/test/run/form_format.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/run/form_format.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,83 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 form_format.cpp
+ * \author Andrey Semashev
+ * \date 07.02.2009
+ *
+ * \brief This header contains tests for the Boost.Format-style formatting.
+ */
+
+#define BOOST_TEST_MODULE form_format
+
+#include <string>
+#include <boost/test/included/unit_test.hpp>
+#include <boost/log/attributes/constant.hpp>
+#include <boost/log/attributes/attribute_set.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/core/record.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include "char_definitions.hpp"
+#include "make_record.hpp"
+
+namespace logging = boost::log;
+namespace attrs = logging::attributes;
+namespace expr = logging::expressions;
+
+namespace {
+
+ template< typename >
+ struct format_test_data;
+
+#ifdef BOOST_LOG_USE_CHAR
+ template< >
+ struct format_test_data< char > :
+ public test_data< char >
+ {
+ static const char* format1() { return "%1%, %2%"; }
+ };
+#endif // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+ template< >
+ struct format_test_data< wchar_t > :
+ public test_data< wchar_t >
+ {
+ static const wchar_t* format1() { return L"%1%, %2%"; }
+ };
+#endif // BOOST_LOG_USE_WCHAR_T
+
+} // namespace
+
+// The test checks that Boost.Format formatting works
+BOOST_AUTO_TEST_CASE_TEMPLATE(formatting, CharT, char_types)
+{
+ typedef logging::attribute_set attr_set;
+ typedef std::basic_string< CharT > string;
+ typedef logging::basic_formatting_ostream< CharT > osstream;
+ typedef logging::record_view record_view;
+ typedef logging::basic_formatter< CharT > formatter;
+ typedef format_test_data< CharT > data;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+
+ attr_set set1;
+ set1[data::attr1()] = attr1;
+ set1[data::attr2()] = attr2;
+
+ record_view rec = make_record_view(set1);
+
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::format(data::format1()) % expr::attr< int >(data::attr1()) % expr::attr< double >(data::attr2());
+ f(rec, strm1);
+ strm2 << 10 << ", " << 5.5;
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+}

Added: trunk/libs/log/test/run/form_if.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/run/form_if.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,107 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 form_if.cpp
+ * \author Andrey Semashev
+ * \date 05.02.2009
+ *
+ * \brief This header contains tests for the \c if_ formatter.
+ */
+
+#define BOOST_TEST_MODULE form_if
+
+#include <string>
+#include <ostream>
+#include <boost/test/included/unit_test.hpp>
+#include <boost/log/attributes/constant.hpp>
+#include <boost/log/attributes/attribute_set.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/core/record.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include "char_definitions.hpp"
+#include "make_record.hpp"
+
+namespace logging = boost::log;
+namespace attrs = logging::attributes;
+namespace expr = logging::expressions;
+
+// The test checks that conditional formatting work
+BOOST_AUTO_TEST_CASE_TEMPLATE(conditional_formatting, CharT, char_types)
+{
+ typedef logging::attribute_set attr_set;
+ typedef std::basic_string< CharT > string;
+ typedef logging::basic_formatting_ostream< CharT > osstream;
+ typedef logging::record_view record_view;
+ typedef logging::basic_formatter< CharT > formatter;
+ typedef test_data< CharT > data;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+
+ attr_set set1;
+ set1[data::attr1()] = attr1;
+ set1[data::attr2()] = attr2;
+
+ record_view rec = make_record_view(set1);
+
+ // Check for various modes of attribute value type specification
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream <<
+ expr::if_(expr::has_attr< int >(data::attr1()))
+ [
+ expr::stream << expr::attr< int >(data::attr1())
+ ];
+ f(rec, strm1);
+ strm2 << 10;
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+ {
+ string str1;
+ osstream strm1(str1);
+ formatter f = expr::stream <<
+ expr::if_(expr::has_attr< int >(data::attr2()))
+ [
+ expr::stream << expr::attr< int >(data::attr2())
+ ];
+ f(rec, strm1);
+ BOOST_CHECK(equal_strings(strm1.str(), string()));
+ }
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream <<
+ expr::if_(expr::has_attr< int >(data::attr1()))
+ [
+ expr::stream << expr::attr< int >(data::attr1())
+ ]
+ .else_
+ [
+ expr::stream << expr::attr< double >(data::attr2())
+ ];
+ f(rec, strm1);
+ strm2 << 10;
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream <<
+ expr::if_(expr::has_attr< int >(data::attr2()))
+ [
+ expr::stream << expr::attr< int >(data::attr1())
+ ]
+ .else_
+ [
+ expr::stream << expr::attr< double >(data::attr2())
+ ];
+ f(rec, strm1);
+ strm2 << 5.5;
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+}

Added: trunk/libs/log/test/run/form_message.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/run/form_message.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,84 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 form_message.cpp
+ * \author Andrey Semashev
+ * \date 01.02.2009
+ *
+ * \brief This header contains tests for the \c message formatter.
+ */
+
+#define BOOST_TEST_MODULE form_message
+
+#include <string>
+#include <boost/test/included/unit_test.hpp>
+#include <boost/log/attributes/constant.hpp>
+#include <boost/log/attributes/attribute_set.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/core/record.hpp>
+#include "char_definitions.hpp"
+#include "make_record.hpp"
+
+namespace logging = boost::log;
+namespace attrs = logging::attributes;
+namespace expr = logging::expressions;
+
+namespace {
+
+ template< typename CharT >
+ struct message_test_data;
+
+#ifdef BOOST_LOG_USE_CHAR
+ template< >
+ struct message_test_data< char > :
+ public test_data< char >
+ {
+ static expr::smessage_type message() { return expr::smessage; }
+ };
+#endif // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+ template< >
+ struct message_test_data< wchar_t > :
+ public test_data< wchar_t >
+ {
+ static expr::wmessage_type message() { return expr::wmessage; }
+ };
+#endif // BOOST_LOG_USE_WCHAR_T
+
+} // namespace
+
+// The test checks that message formatting work
+BOOST_AUTO_TEST_CASE_TEMPLATE(message_formatting, CharT, char_types)
+{
+ typedef logging::attribute_set attr_set;
+ typedef std::basic_string< CharT > string;
+ typedef logging::basic_formatting_ostream< CharT > osstream;
+ typedef logging::record_view record_view;
+ typedef logging::basic_formatter< CharT > formatter;
+ typedef message_test_data< CharT > data;
+
+ attrs::constant< int > attr1(10);
+ attrs::constant< double > attr2(5.5);
+
+ attr_set set1;
+ set1[data::attr1()] = attr1;
+ set1[data::attr2()] = attr2;
+ set1[data::message().get_name()] = attrs::constant< string >(data::some_test_string());
+
+ record_view rec = make_record_view(set1);
+
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream << data::message();
+ f(rec, strm1);
+ strm2 << data::some_test_string();
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+}

Added: trunk/libs/log/test/run/form_named_scope.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/run/form_named_scope.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,199 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 form_named_scope.cpp
+ * \author Andrey Semashev
+ * \date 07.02.2009
+ *
+ * \brief This header contains tests for the \c named_scope formatter.
+ */
+
+#define BOOST_TEST_MODULE form_named_scope
+
+#include <string>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/test/included/unit_test.hpp>
+#include <boost/log/attributes/constant.hpp>
+#include <boost/log/attributes/attribute_set.hpp>
+#include <boost/log/attributes/named_scope.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/utility/string_literal.hpp>
+#include <boost/log/core/record.hpp>
+#include "char_definitions.hpp"
+#include "make_record.hpp"
+
+namespace logging = boost::log;
+namespace attrs = logging::attributes;
+namespace expr = logging::expressions;
+namespace keywords = logging::keywords;
+
+namespace {
+
+ template< typename CharT >
+ struct named_scope_test_data;
+
+#ifdef BOOST_LOG_USE_CHAR
+ template< >
+ struct named_scope_test_data< char > :
+ public test_data< char >
+ {
+ static logging::string_literal default_format() { return logging::str_literal("%n"); }
+ static logging::string_literal full_format() { return logging::str_literal("%n (%f:%l)"); }
+ static logging::string_literal delimiter1() { return logging::str_literal("|"); }
+
+ static logging::string_literal scope1() { return logging::str_literal("scope1"); }
+ static logging::string_literal scope2() { return logging::str_literal("scope2"); }
+ static logging::string_literal file() { return logging::str_literal(__FILE__); }
+ };
+#endif // BOOST_LOG_USE_CHAR
+
+#ifdef BOOST_LOG_USE_WCHAR_T
+ template< >
+ struct named_scope_test_data< wchar_t > :
+ public test_data< wchar_t >
+ {
+ static logging::wstring_literal default_format() { return logging::str_literal(L"%n"); }
+ static logging::wstring_literal full_format() { return logging::str_literal(L"%n (%f:%l)"); }
+ static logging::wstring_literal delimiter1() { return logging::str_literal(L"|"); }
+
+ static logging::string_literal scope1() { return logging::str_literal("scope1"); }
+ static logging::string_literal scope2() { return logging::str_literal("scope2"); }
+ static logging::string_literal file() { return logging::str_literal(__FILE__); }
+ };
+#endif // BOOST_LOG_USE_WCHAR_T
+
+} // namespace
+
+// The test checks that named scopes stack formatting works
+BOOST_AUTO_TEST_CASE_TEMPLATE(scopes_formatting, CharT, char_types)
+{
+ typedef attrs::named_scope named_scope;
+ typedef named_scope::sentry sentry;
+ typedef attrs::named_scope_list scopes;
+ typedef attrs::named_scope_entry scope;
+
+ typedef logging::attribute_set attr_set;
+ typedef std::basic_string< CharT > string;
+ typedef logging::basic_formatting_ostream< CharT > osstream;
+ typedef logging::record_view record_view;
+ typedef logging::basic_formatter< CharT > formatter;
+ typedef named_scope_test_data< CharT > data;
+
+ named_scope attr;
+
+ // First scope
+ const unsigned int line1 = __LINE__;
+ sentry scope1(data::scope1(), data::file(), line1);
+ const unsigned int line2 = __LINE__;
+ sentry scope2(data::scope2(), data::file(), line2);
+
+ attr_set set1;
+ set1[data::attr1()] = attr;
+
+ record_view rec = make_record_view(set1);
+
+ // Default format
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream << expr::format_named_scope(data::attr1(),
+ keywords::format = data::default_format().c_str());
+ f(rec, strm1);
+ strm2 << data::scope1() << "->" << data::scope2();
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+ // Full format
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream << expr::format_named_scope(data::attr1(),
+ keywords::format = data::full_format().c_str());
+ f(rec, strm1);
+ strm2 << data::scope1() << " (" << data::file() << ":" << line1 << ")->"
+ << data::scope2() << " (" << data::file() << ":" << line2 << ")";
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+ // Different delimiter
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream << expr::format_named_scope(data::attr1(),
+ keywords::format = data::default_format().c_str(),
+ keywords::delimiter = data::delimiter1().c_str());
+ f(rec, strm1);
+ strm2 << data::scope1() << "|" << data::scope2();
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+ // Different direction
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream << expr::format_named_scope(data::attr1(),
+ keywords::format = data::default_format().c_str(),
+ keywords::iteration = expr::reverse);
+ f(rec, strm1);
+ strm2 << data::scope2() << "<-" << data::scope1();
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream << expr::format_named_scope(data::attr1(),
+ keywords::format = data::default_format().c_str(),
+ keywords::delimiter = data::delimiter1().c_str(),
+ keywords::iteration = expr::reverse);
+ f(rec, strm1);
+ strm2 << data::scope2() << "|" << data::scope1();
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+ // Limiting the number of scopes
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream << expr::format_named_scope(data::attr1(),
+ keywords::format = data::default_format().c_str(),
+ keywords::depth = 1);
+ f(rec, strm1);
+ strm2 << "...->" << data::scope2();
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream << expr::format_named_scope(data::attr1(),
+ keywords::format = data::default_format().c_str(),
+ keywords::depth = 1,
+ keywords::iteration = expr::reverse);
+ f(rec, strm1);
+ strm2 << data::scope2() << "<-...";
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream << expr::format_named_scope(data::attr1(),
+ keywords::format = data::default_format().c_str(),
+ keywords::delimiter = data::delimiter1().c_str(),
+ keywords::depth = 1);
+ f(rec, strm1);
+ strm2 << "...|" << data::scope2();
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+ {
+ string str1, str2;
+ osstream strm1(str1), strm2(str2);
+ formatter f = expr::stream << expr::format_named_scope(data::attr1(),
+ keywords::format = data::default_format().c_str(),
+ keywords::delimiter = data::delimiter1().c_str(),
+ keywords::depth = 1,
+ keywords::iteration = expr::reverse);
+ f(rec, strm1);
+ strm2 << data::scope2() << "|...";
+ BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
+ }
+}

Added: trunk/libs/log/test/run/util_dynamic_type_dispatcher.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/run/util_dynamic_type_dispatcher.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,138 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 util_dynamic_type_dispatcher.cpp
+ * \author Andrey Semashev
+ * \date 09.01.2009
+ *
+ * \brief This header contains tests for the dynamic type dispatcher.
+ */
+
+#define BOOST_TEST_MODULE util_dynamic_type_dispatcher
+
+#include <string>
+#include <boost/bind.hpp>
+#include <boost/test/floating_point_comparison.hpp>
+#include <boost/test/included/unit_test.hpp>
+#include <boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp>
+
+namespace logging = boost::log;
+
+namespace {
+
+ // A simple attribute value
+ template< typename T >
+ struct my_value
+ {
+ T m_Value;
+
+ explicit my_value(T const& value) : m_Value(value) {}
+
+ // The function passes the contained type into the dispatcher
+ bool dispatch(logging::type_dispatcher& dispatcher)
+ {
+ logging::type_dispatcher::callback< T > callback = dispatcher.get_callback< T >();
+ if (callback)
+ {
+ callback(m_Value);
+ return true;
+ }
+ else
+ return false;
+ }
+ };
+
+ struct my_visitor
+ {
+ enum type_expected
+ {
+ none_expected,
+ int_expected,
+ double_expected,
+ string_expected
+ };
+
+ my_visitor() : m_Expected(none_expected), m_Int(0), m_Double(0.0) {}
+
+ void set_expected()
+ {
+ m_Expected = none_expected;
+ }
+ void set_expected(int value)
+ {
+ m_Expected = int_expected;
+ m_Int = value;
+ }
+ void set_expected(double value)
+ {
+ m_Expected = double_expected;
+ m_Double = value;
+ }
+ void set_expected(std::string const& value)
+ {
+ m_Expected = string_expected;
+ m_String = value;
+ }
+
+ // Implement visitation logic for all supported types
+ void on_int(int const& value)
+ {
+ BOOST_CHECK_EQUAL(m_Expected, int_expected);
+ BOOST_CHECK_EQUAL(m_Int, value);
+ }
+ void on_double(double const& value)
+ {
+ BOOST_CHECK_EQUAL(m_Expected, double_expected);
+ BOOST_CHECK_CLOSE(m_Double, value, 0.001);
+ }
+ void on_string(std::string const& value)
+ {
+ BOOST_CHECK_EQUAL(m_Expected, string_expected);
+ BOOST_CHECK_EQUAL(m_String, value);
+ }
+
+ private:
+ type_expected m_Expected;
+ int m_Int;
+ double m_Double;
+ std::string m_String;
+ };
+
+} // namespace
+
+// The test checks that general functionality works
+BOOST_AUTO_TEST_CASE(type_dispatch)
+{
+ my_visitor vis;
+ logging::dynamic_type_dispatcher disp;
+
+ // Register type visitors
+ disp.register_type< int >(boost::bind(&my_visitor::on_int, &vis, _1));
+ disp.register_type< double >(boost::bind(&my_visitor::on_double, &vis, _1));
+
+ BOOST_CHECK(disp.registered_types_count() == 2);
+
+ // Right now strings are not supported by the dispatcher
+ my_value< std::string > val1("Hello world!");
+ BOOST_CHECK(!val1.dispatch(disp));
+
+ // And now they are
+ disp.register_type< std::string >(boost::bind(&my_visitor::on_string, &vis, _1));
+ BOOST_CHECK(disp.registered_types_count() == 3);
+
+ vis.set_expected(val1.m_Value);
+ BOOST_CHECK(val1.dispatch(disp));
+
+ my_value< double > val2(1.2);
+ vis.set_expected(val2.m_Value);
+ BOOST_CHECK(val2.dispatch(disp));
+
+ // This one is not supported
+ my_value< float > val3(static_cast< float >(-4.3));
+ vis.set_expected();
+ BOOST_CHECK(!val3.dispatch(disp));
+}

Added: trunk/libs/log/test/run/util_exception_handler.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/run/util_exception_handler.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,361 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 util_exception_handler.cpp
+ * \author Andrey Semashev
+ * \date 13.07.2009
+ *
+ * \brief This header contains tests for the exception handler functional objects.
+ */
+
+#define BOOST_TEST_MODULE util_exception_handler
+
+#include <memory>
+#include <string>
+#include <typeinfo>
+#include <stdexcept>
+#include <boost/mpl/vector.hpp>
+#include <boost/test/included/unit_test.hpp>
+#include <boost/log/utility/exception_handler.hpp>
+
+namespace logging = boost::log;
+
+namespace {
+
+ struct my_handler1
+ {
+ typedef void result_type;
+
+ std::type_info const*& m_pExceptionType;
+
+ my_handler1(std::type_info const*& p) : m_pExceptionType(p) {}
+
+ void operator() (std::exception&) const
+ {
+ m_pExceptionType = &typeid(std::exception);
+ }
+ void operator() (std::runtime_error&) const
+ {
+ m_pExceptionType = &typeid(std::runtime_error);
+ }
+ };
+
+ struct my_handler2
+ {
+ typedef void result_type;
+ typedef boost::mpl::vector< std::runtime_error, std::exception >::type exception_types;
+
+ std::type_info const*& m_pExceptionType;
+
+ explicit my_handler2(std::type_info const*& p) : m_pExceptionType(p) {}
+
+ void operator() (std::exception&) const
+ {
+ m_pExceptionType = &typeid(std::exception);
+ }
+ void operator() (std::runtime_error&) const
+ {
+ m_pExceptionType = &typeid(std::runtime_error);
+ }
+ };
+
+ struct my_handler1_nothrow
+ {
+ typedef void result_type;
+
+ std::type_info const*& m_pExceptionType;
+
+ my_handler1_nothrow(std::type_info const*& p) : m_pExceptionType(p) {}
+
+ void operator() (std::exception&) const
+ {
+ m_pExceptionType = &typeid(std::exception);
+ }
+ void operator() (std::runtime_error&) const
+ {
+ m_pExceptionType = &typeid(std::runtime_error);
+ }
+ void operator() () const
+ {
+ m_pExceptionType = &typeid(void);
+ }
+ };
+
+ struct my_handler2_nothrow
+ {
+ typedef void result_type;
+ typedef boost::mpl::vector< std::runtime_error, std::exception >::type exception_types;
+
+ std::type_info const*& m_pExceptionType;
+
+ explicit my_handler2_nothrow(std::type_info const*& p) : m_pExceptionType(p) {}
+
+ void operator() (std::exception&) const
+ {
+ m_pExceptionType = &typeid(std::exception);
+ }
+ void operator() (std::runtime_error&) const
+ {
+ m_pExceptionType = &typeid(std::runtime_error);
+ }
+ void operator() () const
+ {
+ m_pExceptionType = &typeid(void);
+ }
+ };
+
+ struct my_exception {};
+
+ struct my_function0
+ {
+ struct impl_base
+ {
+ virtual ~impl_base() {}
+ virtual void invoke() = 0;
+ };
+
+ template< typename T >
+ struct impl : public impl_base
+ {
+ T m_Fun;
+
+ explicit impl(T const& fun) : m_Fun(fun) {}
+ void invoke() { m_Fun(); }
+ };
+
+ private:
+ std::auto_ptr< impl_base > m_pImpl;
+
+ public:
+ template< typename T >
+ my_function0& operator= (T const& fun)
+ {
+ m_pImpl.reset(new impl< T >(fun));
+ return *this;
+ }
+
+ void operator() () const
+ {
+ m_pImpl->invoke();
+ }
+ };
+
+} // namespace
+
+// Tests for handler with explicit exception types specification
+BOOST_AUTO_TEST_CASE(explicit_exception_types)
+{
+ std::type_info const* pExceptionType = 0;
+ my_function0 handler;
+ handler = logging::make_exception_handler<
+ std::runtime_error,
+ std::exception
+ >(my_handler1(pExceptionType));
+
+ try
+ {
+ throw std::runtime_error("error");
+ }
+ catch (...)
+ {
+ handler();
+ }
+ BOOST_REQUIRE(pExceptionType != 0);
+ BOOST_CHECK(*pExceptionType == typeid(std::runtime_error));
+ pExceptionType = 0;
+
+ try
+ {
+ throw std::logic_error("error");
+ }
+ catch (...)
+ {
+ handler();
+ }
+ BOOST_REQUIRE(pExceptionType != 0);
+ BOOST_CHECK(*pExceptionType == typeid(std::exception));
+ pExceptionType = 0;
+
+ try
+ {
+ throw my_exception();
+ }
+ catch (...)
+ {
+ BOOST_CHECK_THROW(handler(), my_exception);
+ }
+ BOOST_REQUIRE(pExceptionType == 0);
+
+ // Verify that exception types are checked in the specified order
+ handler = logging::make_exception_handler<
+ std::exception,
+ std::runtime_error
+ >(my_handler1(pExceptionType));
+
+ try
+ {
+ throw std::runtime_error("error");
+ }
+ catch (...)
+ {
+ handler();
+ }
+ BOOST_REQUIRE(pExceptionType != 0);
+ BOOST_CHECK(*pExceptionType == typeid(std::exception));
+ pExceptionType = 0;
+}
+
+// Tests for handler with explicit exception types specification (no-throw version)
+BOOST_AUTO_TEST_CASE(explicit_exception_types_nothrow)
+{
+ std::type_info const* pExceptionType = 0;
+ my_function0 handler;
+ handler = logging::make_exception_handler<
+ std::runtime_error,
+ std::exception
+ >(my_handler1_nothrow(pExceptionType), std::nothrow);
+
+ try
+ {
+ throw std::runtime_error("error");
+ }
+ catch (...)
+ {
+ handler();
+ }
+ BOOST_REQUIRE(pExceptionType != 0);
+ BOOST_CHECK(*pExceptionType == typeid(std::runtime_error));
+ pExceptionType = 0;
+
+ try
+ {
+ throw std::logic_error("error");
+ }
+ catch (...)
+ {
+ handler();
+ }
+ BOOST_REQUIRE(pExceptionType != 0);
+ BOOST_CHECK(*pExceptionType == typeid(std::exception));
+ pExceptionType = 0;
+
+ try
+ {
+ throw my_exception();
+ }
+ catch (...)
+ {
+ BOOST_CHECK_NO_THROW(handler());
+ }
+ BOOST_REQUIRE(pExceptionType != 0);
+ BOOST_CHECK(*pExceptionType == typeid(void));
+ pExceptionType = 0;
+
+ // Verify that exception types are checked in the specified order
+ handler = logging::make_exception_handler<
+ std::exception,
+ std::runtime_error
+ >(my_handler1_nothrow(pExceptionType), std::nothrow);
+
+ try
+ {
+ throw std::runtime_error("error");
+ }
+ catch (...)
+ {
+ handler();
+ }
+ BOOST_REQUIRE(pExceptionType != 0);
+ BOOST_CHECK(*pExceptionType == typeid(std::exception));
+ pExceptionType = 0;
+}
+
+// Tests for handler with self-contained exception types
+BOOST_AUTO_TEST_CASE(self_contained_exception_types)
+{
+ std::type_info const* pExceptionType = 0;
+ my_function0 handler;
+ handler = logging::make_exception_handler(my_handler2(pExceptionType));
+
+ try
+ {
+ throw std::runtime_error("error");
+ }
+ catch (...)
+ {
+ handler();
+ }
+ BOOST_REQUIRE(pExceptionType != 0);
+ BOOST_CHECK(*pExceptionType == typeid(std::runtime_error));
+ pExceptionType = 0;
+
+ try
+ {
+ throw std::logic_error("error");
+ }
+ catch (...)
+ {
+ handler();
+ }
+ BOOST_REQUIRE(pExceptionType != 0);
+ BOOST_CHECK(*pExceptionType == typeid(std::exception));
+ pExceptionType = 0;
+
+ try
+ {
+ throw my_exception();
+ }
+ catch (...)
+ {
+ BOOST_CHECK_THROW(handler(), my_exception);
+ }
+ BOOST_REQUIRE(pExceptionType == 0);
+}
+
+// Tests for handler with self-contained exception types (no-throw version)
+BOOST_AUTO_TEST_CASE(self_contained_exception_types_nothrow)
+{
+ std::type_info const* pExceptionType = 0;
+ my_function0 handler;
+ handler = logging::make_exception_handler(my_handler2_nothrow(pExceptionType), std::nothrow);
+
+ try
+ {
+ throw std::runtime_error("error");
+ }
+ catch (...)
+ {
+ handler();
+ }
+ BOOST_REQUIRE(pExceptionType != 0);
+ BOOST_CHECK(*pExceptionType == typeid(std::runtime_error));
+ pExceptionType = 0;
+
+ try
+ {
+ throw std::logic_error("error");
+ }
+ catch (...)
+ {
+ handler();
+ }
+ BOOST_REQUIRE(pExceptionType != 0);
+ BOOST_CHECK(*pExceptionType == typeid(std::exception));
+ pExceptionType = 0;
+
+ try
+ {
+ throw my_exception();
+ }
+ catch (...)
+ {
+ BOOST_CHECK_NO_THROW(handler());
+ }
+ BOOST_REQUIRE(pExceptionType != 0);
+ BOOST_CHECK(*pExceptionType == typeid(void));
+ pExceptionType = 0;
+}

Added: trunk/libs/log/test/run/util_once_block.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/run/util_once_block.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,193 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 util_once_block.cpp
+ * \author Andrey Semashev
+ * \date 24.06.2010
+ *
+ * \brief This header contains tests for once-blocks implementation.
+ *
+ * The test was adopted from test_once.cpp test of Boost.Thread.
+ */
+
+#define BOOST_TEST_MODULE util_once_block
+
+#include <boost/log/utility/once_block.hpp>
+
+#if !defined(BOOST_LOG_NO_THREADS)
+
+#include <boost/test/included/unit_test.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/locks.hpp>
+
+namespace logging = boost::log;
+
+enum config
+{
+ THREAD_COUNT = 20,
+ LOOP_COUNT = 100
+};
+
+boost::mutex m;
+typedef boost::lock_guard< boost::mutex > scoped_lock;
+
+logging::once_block_flag flag = BOOST_LOG_ONCE_BLOCK_INIT;
+int var_to_init_once_flag = 0;
+
+void initialize_variable()
+{
+ // ensure that if multiple threads get in here, they are serialized, so we can see the effect
+ scoped_lock lock(m);
+ ++var_to_init_once_flag;
+}
+
+
+void once_block_flag_thread()
+{
+ int my_once_value = 0;
+ for (unsigned i = 0; i < LOOP_COUNT; ++i)
+ {
+ BOOST_LOG_ONCE_BLOCK_FLAG(flag)
+ {
+ initialize_variable();
+ }
+
+ my_once_value = var_to_init_once_flag;
+ if (my_once_value != 1)
+ {
+ break;
+ }
+ }
+ scoped_lock lock(m);
+ BOOST_CHECK_EQUAL(my_once_value, 1);
+}
+
+// The test checks if the BOOST_LOG_ONCE_BLOCK_FLAG macro works
+BOOST_AUTO_TEST_CASE(once_block_flag)
+{
+ boost::thread_group group;
+
+ try
+ {
+ for (unsigned i = 0; i < THREAD_COUNT; ++i)
+ {
+ group.create_thread(&once_block_flag_thread);
+ }
+ group.join_all();
+ }
+ catch (...)
+ {
+ group.interrupt_all();
+ group.join_all();
+ throw;
+ }
+
+ BOOST_CHECK_EQUAL(var_to_init_once_flag, 1);
+}
+
+int var_to_init_once = 0;
+
+void once_block_thread()
+{
+ int my_once_value = 0;
+ for (unsigned i = 0; i < LOOP_COUNT; ++i)
+ {
+ BOOST_LOG_ONCE_BLOCK()
+ {
+ scoped_lock lock(m);
+ ++var_to_init_once;
+ }
+
+ my_once_value = var_to_init_once;
+ if (my_once_value != 1)
+ {
+ break;
+ }
+ }
+
+ scoped_lock lock(m);
+ BOOST_CHECK_EQUAL(my_once_value, 1);
+}
+
+// The test checks if the BOOST_LOG_ONCE_BLOCK macro works
+BOOST_AUTO_TEST_CASE(once_block)
+{
+ boost::thread_group group;
+
+ try
+ {
+ for (unsigned i = 0; i < THREAD_COUNT; ++i)
+ {
+ group.create_thread(&once_block_thread);
+ }
+ group.join_all();
+ }
+ catch(...)
+ {
+ group.interrupt_all();
+ group.join_all();
+ throw;
+ }
+
+ BOOST_CHECK_EQUAL(var_to_init_once, 1);
+}
+
+
+struct my_exception
+{
+};
+
+unsigned pass_counter = 0;
+unsigned exception_counter = 0;
+
+void once_block_with_exception_thread()
+{
+ try
+ {
+ BOOST_LOG_ONCE_BLOCK()
+ {
+ scoped_lock lock(m);
+ ++pass_counter;
+ if (pass_counter < 3)
+ {
+ throw my_exception();
+ }
+ }
+ }
+ catch (my_exception&)
+ {
+ scoped_lock lock(m);
+ ++exception_counter;
+ }
+}
+
+// The test verifies that the once_block flag is not set if an exception is thrown from the once-block
+BOOST_AUTO_TEST_CASE(once_block_retried_on_exception)
+{
+ boost::thread_group group;
+
+ try
+ {
+ for (unsigned i = 0; i < THREAD_COUNT; ++i)
+ {
+ group.create_thread(&once_block_with_exception_thread);
+ }
+ group.join_all();
+ }
+ catch(...)
+ {
+ group.interrupt_all();
+ group.join_all();
+ throw;
+ }
+
+ BOOST_CHECK_EQUAL(pass_counter, 3u);
+ BOOST_CHECK_EQUAL(exception_counter, 2u);
+}
+
+#endif // BOOST_LOG_NO_THREADS

Added: trunk/libs/log/test/run/util_static_type_dispatcher.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/run/util_static_type_dispatcher.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,147 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 util_static_type_dispatcher.cpp
+ * \author Andrey Semashev
+ * \date 09.01.2009
+ *
+ * \brief This header contains tests for the static type dispatcher.
+ */
+
+#define BOOST_TEST_MODULE util_static_type_dispatcher
+
+#include <string>
+#include <typeinfo>
+#include <boost/mpl/vector.hpp>
+#include <boost/test/floating_point_comparison.hpp>
+#include <boost/test/included/unit_test.hpp>
+#include <boost/log/utility/type_dispatch/static_type_dispatcher.hpp>
+
+namespace logging = boost::log;
+
+namespace {
+
+ // A simple attribute value
+ template< typename T >
+ struct my_value
+ {
+ T m_Value;
+
+ explicit my_value(T const& value) : m_Value(value) {}
+
+ // The function passes the contained type into the dispatcher
+ bool dispatch(logging::type_dispatcher& dispatcher)
+ {
+ logging::type_dispatcher::callback< T > callback = dispatcher.get_callback< T >();
+ if (callback)
+ {
+ callback(m_Value);
+ return true;
+ }
+ else
+ return false;
+ }
+ };
+
+ // The function tests general functionality of the type dispatcher
+ template< typename DispatcherT >
+ void test_general_functionality(DispatcherT& disp)
+ {
+ // These two attributes are supported by the dispatcher
+ my_value< std::string > val1("Hello world!");
+ disp.set_expected(val1.m_Value);
+ BOOST_CHECK(val1.dispatch(disp));
+
+ my_value< double > val2(1.2);
+ disp.set_expected(val2.m_Value);
+ BOOST_CHECK(val2.dispatch(disp));
+
+ // This one is not
+ my_value< float > val3(static_cast< float >(-4.3));
+ disp.set_expected();
+ BOOST_CHECK(!val3.dispatch(disp));
+ }
+
+
+ // Type dispatcher for the supported types
+ struct my_dispatcher :
+ public logging::static_type_dispatcher<
+ boost::mpl::vector< int, double, std::string >
+ >
+ {
+ typedef logging::static_type_dispatcher<
+ boost::mpl::vector< int, double, std::string >
+ > base_type;
+
+ enum type_expected
+ {
+ none_expected,
+ int_expected,
+ double_expected,
+ string_expected
+ };
+
+ my_dispatcher() :
+ base_type(*this),
+ m_Expected(none_expected),
+ m_Int(0),
+ m_Double(0.0)
+ {
+ }
+
+ void set_expected()
+ {
+ m_Expected = none_expected;
+ }
+ void set_expected(int value)
+ {
+ m_Expected = int_expected;
+ m_Int = value;
+ }
+ void set_expected(double value)
+ {
+ m_Expected = double_expected;
+ m_Double = value;
+ }
+ void set_expected(std::string const& value)
+ {
+ m_Expected = string_expected;
+ m_String = value;
+ }
+
+ // Implement visitation logic for all supported types
+ void operator() (int const& value) const
+ {
+ BOOST_CHECK_EQUAL(m_Expected, int_expected);
+ BOOST_CHECK_EQUAL(m_Int, value);
+ }
+ void operator() (double const& value) const
+ {
+ BOOST_CHECK_EQUAL(m_Expected, double_expected);
+ BOOST_CHECK_CLOSE(m_Double, value, 0.001);
+ }
+ void operator() (std::string const& value) const
+ {
+ BOOST_CHECK_EQUAL(m_Expected, string_expected);
+ BOOST_CHECK_EQUAL(m_String, value);
+ }
+
+ private:
+ type_expected m_Expected;
+ int m_Int;
+ double m_Double;
+ std::string m_String;
+ };
+
+} // namespace
+
+// The test checks that general functionality works
+BOOST_AUTO_TEST_CASE(type_dispatch)
+{
+ my_dispatcher disp;
+ test_general_functionality(disp);
+}

Added: trunk/libs/log/test/run/util_string_literal.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/run/util_string_literal.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,218 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 util_string_literal.cpp
+ * \author Andrey Semashev
+ * \date 09.01.2009
+ *
+ * \brief This header contains tests for the string literals wrapper.
+ */
+
+#define BOOST_TEST_MODULE util_string_literal
+
+#include <cwchar>
+#include <set>
+#include <memory>
+#include <string>
+#include <algorithm>
+#include <boost/test/included/unit_test.hpp>
+#include <boost/log/utility/string_literal.hpp>
+
+namespace logging = boost::log;
+
+// Construction tests
+BOOST_AUTO_TEST_CASE(string_literal_ctors)
+{
+ // Default construction
+ {
+ logging::string_literal lit;
+ BOOST_CHECK(lit.empty());
+ BOOST_CHECK_EQUAL(lit.size(), 0UL);
+ BOOST_CHECK(lit.c_str() != NULL);
+ }
+
+ // Construction from a literal
+ {
+ logging::string_literal lit = "abcd";
+ BOOST_CHECK(!lit.empty());
+ BOOST_CHECK_EQUAL(lit.size(), 4UL);
+ BOOST_CHECK(strcmp(lit.c_str(), "abcd") == 0);
+ }
+
+ // Copying
+ {
+ logging::wstring_literal lit1 = L"Hello";
+ logging::wstring_literal lit2 = lit1;
+ BOOST_CHECK(wcscmp(lit2.c_str(), L"Hello") == 0);
+ BOOST_CHECK(wcscmp(lit1.c_str(), lit2.c_str()) == 0);
+ }
+
+ // Generator functions
+ {
+ logging::string_literal lit1 = logging::str_literal("Wow!");
+ BOOST_CHECK(strcmp(lit1.c_str(), "Wow!") == 0);
+
+ logging::wstring_literal lit2 = logging::str_literal(L"Wow!");
+ BOOST_CHECK(wcscmp(lit2.c_str(), L"Wow!") == 0);
+ }
+}
+
+// Assignment tests
+BOOST_AUTO_TEST_CASE(string_literal_assignment)
+{
+ // operator=
+ {
+ logging::string_literal lit;
+ BOOST_CHECK(lit.empty());
+
+ lit = "Hello";
+ BOOST_CHECK(strcmp(lit.c_str(), "Hello") == 0);
+
+ logging::string_literal empty_lit;
+ lit = empty_lit;
+ BOOST_CHECK(lit.empty());
+
+ logging::string_literal filled_lit = "Some string";
+ lit = filled_lit;
+ BOOST_CHECK(strcmp(lit.c_str(), filled_lit.c_str()) == 0);
+ }
+
+ // assign
+ {
+ logging::string_literal lit;
+ BOOST_CHECK(lit.empty());
+
+ lit.assign("Hello");
+ BOOST_CHECK(strcmp(lit.c_str(), "Hello") == 0);
+
+ logging::string_literal empty_lit;
+ lit.assign(empty_lit);
+ BOOST_CHECK(lit.empty());
+
+ logging::string_literal filled_lit = "Some string";
+ lit.assign(filled_lit);
+ BOOST_CHECK(strcmp(lit.c_str(), filled_lit.c_str()) == 0);
+ }
+}
+
+// Comparison tests
+BOOST_AUTO_TEST_CASE(string_literal_comparison)
+{
+ logging::string_literal lit;
+ BOOST_CHECK(lit == "");
+
+ lit = "abcdefg";
+ BOOST_CHECK(lit == "abcdefg");
+ BOOST_CHECK(lit != "xyz");
+ BOOST_CHECK(lit != "aBcDeFg");
+
+ logging::string_literal lit2 = "Yo!";
+ BOOST_CHECK(lit != lit2);
+ lit2 = "abcdefg";
+ BOOST_CHECK(lit == lit2);
+
+ BOOST_CHECK(lit.compare(lit2) == 0);
+ BOOST_CHECK(lit.compare("aaaaa") > 0);
+ BOOST_CHECK(lit.compare("zzzzzzzz") < 0);
+ BOOST_CHECK(lit.compare("zbcdefg") < 0);
+
+ BOOST_CHECK(lit.compare(2, 3, "cde") == 0);
+ BOOST_CHECK(lit.compare(2, 3, "cdefgh", 3) == 0);
+
+ // Check ordering
+ std::set< logging::string_literal > lit_set;
+ lit_set.insert(logging::str_literal("abc"));
+ lit_set.insert(logging::str_literal("def"));
+ lit_set.insert(logging::str_literal("aaa"));
+ lit_set.insert(logging::str_literal("abcd"));
+ lit_set.insert(logging::str_literal("zz"));
+
+ std::set< std::string > str_set;
+ str_set.insert(logging::str_literal("abc").str());
+ str_set.insert(logging::str_literal("def").str());
+ str_set.insert(logging::str_literal("aaa").str());
+ str_set.insert(logging::str_literal("abcd").str());
+ str_set.insert(logging::str_literal("zz").str());
+
+ BOOST_CHECK_EQUAL_COLLECTIONS(lit_set.begin(), lit_set.end(), str_set.begin(), str_set.end());
+}
+
+// Iteration tests
+BOOST_AUTO_TEST_CASE(string_literal_iteration)
+{
+ std::string str;
+ logging::string_literal lit = "abcdefg";
+
+ std::copy(lit.begin(), lit.end(), std::back_inserter(str));
+ BOOST_CHECK(str == "abcdefg");
+
+ str.clear();
+ std::copy(lit.rbegin(), lit.rend(), std::back_inserter(str));
+ BOOST_CHECK(str == "gfedcba");
+}
+
+// Subscript tests
+BOOST_AUTO_TEST_CASE(string_literal_indexing)
+{
+ logging::string_literal lit = "abcdefg";
+
+ BOOST_CHECK_EQUAL(lit[2], 'c');
+ BOOST_CHECK_EQUAL(lit.at(3), 'd');
+
+ BOOST_CHECK_THROW(lit.at(100), std::exception);
+}
+
+// Clearing tests
+BOOST_AUTO_TEST_CASE(string_literal_clear)
+{
+ logging::string_literal lit = "yo-ho-ho";
+ BOOST_CHECK(!lit.empty());
+
+ lit.clear();
+ BOOST_CHECK(lit.empty());
+ BOOST_CHECK_EQUAL(lit, "");
+}
+
+// Swapping tests
+BOOST_AUTO_TEST_CASE(string_literal_swap)
+{
+ logging::string_literal lit1 = "yo-ho-ho";
+ logging::string_literal lit2 = "hello";
+
+ lit1.swap(lit2);
+ BOOST_CHECK_EQUAL(lit1, "hello");
+ BOOST_CHECK_EQUAL(lit2, "yo-ho-ho");
+
+ swap(lit1, lit2);
+ BOOST_CHECK_EQUAL(lit2, "hello");
+ BOOST_CHECK_EQUAL(lit1, "yo-ho-ho");
+}
+
+// STL strings acquision tests
+BOOST_AUTO_TEST_CASE(string_literal_str)
+{
+ logging::string_literal lit = "yo-ho-ho";
+ std::string str = lit.str();
+ BOOST_CHECK_EQUAL(str, "yo-ho-ho");
+ BOOST_CHECK_EQUAL(lit, str);
+}
+
+// Substring extraction tests
+BOOST_AUTO_TEST_CASE(string_literal_copy)
+{
+ logging::string_literal lit = "yo-ho-ho";
+ char t[32] = { 0 };
+
+ BOOST_CHECK_EQUAL(lit.copy(t, 2), 2UL);
+ BOOST_CHECK(strcmp(t, "yo") == 0);
+
+ BOOST_CHECK_EQUAL(lit.copy(t, 4, 2), 4UL);
+ BOOST_CHECK(strcmp(t, "-ho-") == 0);
+
+ BOOST_CHECK_EQUAL(lit.copy(t, 100), 8UL);
+ BOOST_CHECK(strcmp(t, "yo-ho-ho") == 0);
+}

Added: trunk/libs/log/test/run/util_type_info_wrapper.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/run/util_type_info_wrapper.cpp 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -0,0 +1,97 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 util_type_info_wrapper.cpp
+ * \author Andrey Semashev
+ * \date 18.01.2009
+ *
+ * \brief This header contains tests for the type_info wrapper.
+ */
+
+#define BOOST_TEST_MODULE util_type_info_wrapper
+
+#include <string>
+#include <typeinfo>
+#include <algorithm>
+#include <boost/test/included/unit_test.hpp>
+#include <boost/log/utility/type_info_wrapper.hpp>
+
+namespace logging = boost::log;
+
+namespace {
+
+ struct my_struct1 {};
+ struct my_struct2 {};
+
+} // namespace
+
+// Tests for constructors and assignment
+BOOST_AUTO_TEST_CASE(constructors)
+{
+ logging::type_info_wrapper info1;
+ BOOST_CHECK(!info1);
+
+ logging::type_info_wrapper info2 = typeid(my_struct1);
+ BOOST_CHECK(info2);
+
+ logging::type_info_wrapper info3 = info2;
+ BOOST_CHECK(info3);
+
+ logging::type_info_wrapper info4 = info1;
+ BOOST_CHECK(!info4);
+
+ info3 = info4;
+ BOOST_CHECK(!info3);
+}
+
+// Tests for swapping
+BOOST_AUTO_TEST_CASE(swapping)
+{
+ logging::type_info_wrapper info1 = typeid(my_struct1);
+ logging::type_info_wrapper info2 = typeid(my_struct2);
+
+ BOOST_CHECK(info1 == typeid(my_struct1));
+ BOOST_CHECK(info2 == typeid(my_struct2));
+
+ using std::swap;
+ swap(info1, info2);
+ BOOST_CHECK(info1 == typeid(my_struct2));
+ BOOST_CHECK(info2 == typeid(my_struct1));
+
+ info1.swap(info2);
+ BOOST_CHECK(info1 == typeid(my_struct1));
+ BOOST_CHECK(info2 == typeid(my_struct2));
+}
+
+// Tests for comparison and ordering
+BOOST_AUTO_TEST_CASE(comparison)
+{
+ logging::type_info_wrapper info1 = typeid(my_struct1);
+ logging::type_info_wrapper info2 = typeid(my_struct2);
+
+ const bool ordering = typeid(my_struct1).before(typeid(my_struct2)) != 0;
+ BOOST_CHECK((info1 < info2) == ordering);
+
+ logging::type_info_wrapper empty1, empty2;
+ BOOST_CHECK(empty1 != info1);
+ BOOST_CHECK(empty1 != info2);
+ BOOST_CHECK(empty1 == empty2);
+}
+
+// Tests for pretty_name
+BOOST_AUTO_TEST_CASE(pretty_name)
+{
+ // We don't check for the prety_name result contents.
+ // Simply verify that the function exists and returns a non-empty string.
+ logging::type_info_wrapper info = typeid(my_struct1);
+ std::string str = info.pretty_name();
+ BOOST_CHECK(!str.empty());
+
+ logging::type_info_wrapper empty;
+ str = info.pretty_name();
+ BOOST_CHECK(!str.empty());
+}

Modified: trunk/libs/maintainers.txt
==============================================================================
--- trunk/libs/maintainers.txt (original)
+++ trunk/libs/maintainers.txt 2013-04-13 08:30:25 EDT (Sat, 13 Apr 2013)
@@ -60,8 +60,9 @@
 lexical_cast Antony Polukhin <antoshkka -at- gmail.com>
 local_function Lorenzo Caminiti <lorcaminiti -at- gmail.com>
 locale Artyom Beilis <artyomtnk -at- yahoo.com>
-logic Douglas Gregor <dgregor -at- cs.indiana.edu>
 lockfree Tim Blechmann <tim -at- klingt.org>
+log Andrey Semashev <andrey.semashev -at- gmail.com>
+logic Douglas Gregor <dgregor -at- cs.indiana.edu>
 math Hubert Holin <Hubert.Holin -at- meteo.fr>, John Maddock <john -at- johnmaddock.co.uk>
 move Ion Gaztanaga <igaztanaga -at- gmail.com>
 mpl Aleksey Gurtovoy <agurtovoy -at- meta-comm.com>


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk