diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 9eba5b2..392c2ad 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -19,9 +19,8 @@ local here = [ modules.binding $(__name__) ] ; project.push-current [ project.current ] ; project.load [ path.join [ path.make $(here:D) ] ../config/message-compiler ] ; -project.pop-current ; -project.push-current [ project.current ] ; project.load [ path.join [ path.make $(here:D) ] ../config/x86-ext ] ; +project.load [ path.join [ path.make $(here:D) ] ../config/visibility ] ; project.pop-current ; # Windows libs @@ -66,7 +65,7 @@ rule select-log-api ( properties * ) # We have to verify if message compiler is available if ! ( BOOST_LOG_WITHOUT_EVENT_LOG in $(properties) || BOOST_LOG_WITHOUT_EVENT_LOG=1 in $(properties) ) { - local has_mc = [ configure.builds /boost/message-compiler//test-availability : $(properties) : message-compiler ] ; + local has_mc = [ configure.builds /boost/log/message-compiler//test-availability : $(properties) : message-compiler ] ; if $(has_mc) { result = winnt ; @@ -113,12 +112,27 @@ rule select-regex-backend ( properties * ) return $(result) ; } +rule check-visibility ( properties * ) +{ + local result = ; + + local has_visibility = [ configure.builds /boost/log/visibility//visibility : $(properties) : compiler-supports-visibility ] ; + if $(has_visibility) + { + result = "-fvisibility=hidden" ; + } + + return $(result) ; +} + project boost/log : source-location ../src : requirements @select-log-api @check-instruction-set @select-regex-backend + @check-visibility + BOOST_SPIRIT_USE_PHOENIX_V3=1 BOOST_THREAD_DONT_USE_CHRONO=1 # Don't introduce false dependency on Boost.Chrono @@ -136,6 +150,7 @@ project boost/log msvc:/wd4503 # decorated name length exceeded, name was truncated msvc:/wd4456 # declaration of 'A' hides previous local declaration msvc:/wd4459 # declaration of 'A' hides global declaration + msvc:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS which are used by Fusion # Disable Intel warnings: # warning #177: function "X" was declared but never referenced @@ -243,7 +258,7 @@ rule ssse3-targets-cond ( properties * ) if x86 in [ log-architecture.deduce-architecture $(properties) ] { - local has_ssse3 = [ configure.builds /boost/x86-extensions//ssse3 : $(properties) : compiler-supports-ssse3 ] ; + local has_ssse3 = [ configure.builds /boost/log/x86-extensions//ssse3 : $(properties) : compiler-supports-ssse3 ] ; if $(has_ssse3) { result = ; @@ -305,7 +320,7 @@ rule avx2-targets-cond ( properties * ) if x86 in [ log-architecture.deduce-architecture $(properties) ] { - local has_ssse3 = [ configure.builds /boost/x86-extensions//avx2 : $(properties) : compiler-supports-avx2 ] ; + local has_ssse3 = [ configure.builds /boost/log/x86-extensions//avx2 : $(properties) : compiler-supports-avx2 ] ; if $(has_ssse3) { result = ; diff --git a/config/message-compiler/Jamfile.jam b/config/message-compiler/Jamfile.jam index ece98ed..5000c27 100644 --- a/config/message-compiler/Jamfile.jam +++ b/config/message-compiler/Jamfile.jam @@ -1,5 +1,5 @@ # -# Copyright Andrey Semashev 2007 - 2014. +# Copyright Andrey Semashev 2007 - 2015. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) @@ -8,7 +8,7 @@ import project ; using mc ; -project /boost/message-compiler +project /boost/log/message-compiler : source-location ../../src : requirements off diff --git a/config/visibility/Jamfile.jam b/config/visibility/Jamfile.jam new file mode 100644 index 0000000..4cef480 --- /dev/null +++ b/config/visibility/Jamfile.jam @@ -0,0 +1,22 @@ +# +# Copyright Andrey Semashev 2007 - 2015. +# Distributed under the 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 project ; + +project /boost/log/visibility + : source-location . + : requirements + off + ; + +obj visibility : visibility.cpp + : + "-fvisibility=hidden" + # Some compilers may not support visibility but just ignore the option with a warning + all + on + ; diff --git a/config/visibility/visibility.cpp b/config/visibility/visibility.cpp new file mode 100644 index 0000000..30f1a64 --- /dev/null +++ b/config/visibility/visibility.cpp @@ -0,0 +1,16 @@ +/* + * Copyright Andrey Semashev 2007 - 2015. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ + +// Guess what, MSVC doesn't ever fail on unknown options, even with /WX. Hence this additional check. +#if !defined(__GNUC__) +#error Visibility option is only supported by gcc and compatible compilers +#endif + +int main(int, char*[]) +{ + return 0; +} diff --git a/config/x86-ext/Jamfile.jam b/config/x86-ext/Jamfile.jam index 75d9467..976fbab 100644 --- a/config/x86-ext/Jamfile.jam +++ b/config/x86-ext/Jamfile.jam @@ -1,5 +1,5 @@ # -# Copyright Andrey Semashev 2007 - 2014. +# Copyright Andrey Semashev 2007 - 2015. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) @@ -7,7 +7,7 @@ import project ; -project /boost/x86-extensions +project /boost/log/x86-extensions : source-location . : requirements off diff --git a/doc/changelog.qbk b/doc/changelog.qbk index 942cc2e..0359443 100644 --- a/doc/changelog.qbk +++ b/doc/changelog.qbk @@ -9,6 +9,24 @@ [section:changelog Changelog] +[heading 2.6, Boost 1.59] + +[*General changes:] + +* On systems with [@https://gcc.gnu.org/wiki/Visibility symbol visibility] support (e.g. Linux) the library is now built with all internal symbols hidden. API symbols still have default visibility, so this shouldn't affect linking with the library. +* *Breaking change:* The library has been ported to __boost_type_index__ for its underlying type info management tool. This improved library compatibility with hidden symbol visibility mode on some compilers. This affected the following public interfaces: + * `invalid_type` exceptions thrown by the library now have `typeindex::type_index` attached as the description of the offending type. The type was previously identified by `type_info_wrapper`. + * __boost_exception__ `type_info_info` error information now contains `typeindex::type_index` instead of `type_info_wrapper`. This is the error info that can be used to obtain the type info from `invalid_type` exceptions. + * `attribute_value::get_type()` now returns `typeindex::type_index` instead of `type_info_wrapper`. If the `attribute_value` object is empty, the returned `type_index` is default-constructed (i.e. refers to the `void` type). User-defined attribute value implementations should be similatly changed (the `attribute_value::impl::get_type()` virtual method now also returns `typeindex::type_index`). +* `type_info_wrapper` component has been deprecated and will be removed in future releases. __boost_type_index__ is recommended as a replacement. +* Removed the previously deprecated headers: `boost/log/utility/intrusive_ref_counter.hpp`, `boost/log/utility/explicit_operator_bool.hpp`, `boost/log/utility/empty_deleter.hpp`. +* Added support for building the library for OpenBSD. ([ticket 11446]) +* Improved internal implementation of the event synchronization primitive used for asynchronous logging. The updated implementation relies on __boost_atomic__ for atomic operations which provides better portability. On Linux the implementation uses futexes directly. ([ticket 11398]) + +[*Bug fixes:] + +* Fixed incorrect behavior of `attribute_value_set::insert()` and `attribute_value_set` constructor in some cases. The inserted elements could have made some previously inserted elements not findable. The constructor from `attribute_set`s could leave some of the attribute values acquired from attributes not findable. ([ticket 11190]) + [heading 2.5, Boost 1.58] [*Bug fixes:] diff --git a/doc/log.qbk b/doc/log.qbk index 1a9b8d6..4ccbec6 100644 --- a/doc/log.qbk +++ b/doc/log.qbk @@ -17,6 +17,7 @@ [/ Links to external resources /] [def __boost_config__ [@http://www.boost.org/doc/libs/release/libs/config/doc/html/index.html Boost.Config]] +[def __boost_atomic__ [@http://www.boost.org/doc/libs/release/doc/html/atomic.html Boost.Atomic]] [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]] @@ -46,6 +47,7 @@ [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_type_index__ [@http://www.boost.org/doc/libs/release/doc/html/boost_typeindex.html Boost.TypeIndex]] [def __boost_utility__ [@http://www.boost.org/doc/libs/release/libs/utility/utility.htm Boost.Utility]] [def __boost_quickbook__ [@http://www.boost.org/doc/libs/release/doc/html/quickbook.html Boost.Quickbook]] @@ -245,6 +247,8 @@ The library provides the `BOOST_LOG_USE_COMPILER_TLS` configuration macro that a * 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. +Note that the `BOOST_LOG_USE_COMPILER_TLS` macro only controls use of TLS in Boost.Log but not in other libraries used by Boost.Log. For example, __boost_asio__ uses compiler-supplied TLS by default. In order to build Boost.Log binaries completely free from use of compiler-supplied TLS, this feature has to be disabled in those other libraries as well (in case of __boost_asio__ this can be achieved by defining `BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION` when building and using Boost). + [endsect] [endsect] diff --git a/doc/utilities.qbk b/doc/utilities.qbk index 52fb750..3dae3b2 100644 --- a/doc/utilities.qbk +++ b/doc/utilities.qbk @@ -23,6 +23,8 @@ String literals support interface similar to STL strings, except for string modi [section:type_info_wrapper Type information wrapper] +[note This component is deprecated and will be removed in future releases. __boost_type_index__ is recommended as a replacement.] + #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. diff --git a/example/advanced_usage/Jamfile.v2 b/example/advanced_usage/Jamfile.v2 index 528181c..03ea037 100644 --- a/example/advanced_usage/Jamfile.v2 +++ b/example/advanced_usage/Jamfile.v2 @@ -16,6 +16,7 @@ project msvc:/wd4503 # decorated name length exceeded, name was truncated msvc:/wd4456 # declaration of 'A' hides previous local declaration msvc:/wd4459 # declaration of 'A' hides global declaration + msvc:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS which are used by Fusion intel-win:_SCL_SECURE_NO_WARNINGS intel-win:_SCL_SECURE_NO_DEPRECATE intel-win:_CRT_SECURE_NO_WARNINGS diff --git a/example/async_log/Jamfile.v2 b/example/async_log/Jamfile.v2 index bf77369..7af11ff 100644 --- a/example/async_log/Jamfile.v2 +++ b/example/async_log/Jamfile.v2 @@ -16,6 +16,7 @@ project msvc:/wd4503 # decorated name length exceeded, name was truncated msvc:/wd4456 # declaration of 'A' hides previous local declaration msvc:/wd4459 # declaration of 'A' hides global declaration + msvc:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS which are used by Fusion intel-win:_SCL_SECURE_NO_WARNINGS intel-win:_SCL_SECURE_NO_DEPRECATE intel-win:_CRT_SECURE_NO_WARNINGS diff --git a/example/basic_usage/Jamfile.v2 b/example/basic_usage/Jamfile.v2 index 6d01742..b46fd3e 100644 --- a/example/basic_usage/Jamfile.v2 +++ b/example/basic_usage/Jamfile.v2 @@ -16,6 +16,7 @@ project msvc:/wd4503 # decorated name length exceeded, name was truncated msvc:/wd4456 # declaration of 'A' hides previous local declaration msvc:/wd4459 # declaration of 'A' hides global declaration + msvc:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS which are used by Fusion intel-win:_SCL_SECURE_NO_WARNINGS intel-win:_SCL_SECURE_NO_DEPRECATE intel-win:_CRT_SECURE_NO_WARNINGS diff --git a/example/bounded_async_log/Jamfile.v2 b/example/bounded_async_log/Jamfile.v2 index d13a3c6..be5887e 100644 --- a/example/bounded_async_log/Jamfile.v2 +++ b/example/bounded_async_log/Jamfile.v2 @@ -16,6 +16,7 @@ project msvc:/wd4503 # decorated name length exceeded, name was truncated msvc:/wd4456 # declaration of 'A' hides previous local declaration msvc:/wd4459 # declaration of 'A' hides global declaration + msvc:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS which are used by Fusion intel-win:_SCL_SECURE_NO_WARNINGS intel-win:_SCL_SECURE_NO_DEPRECATE intel-win:_CRT_SECURE_NO_WARNINGS diff --git a/example/doc/Jamfile.v2 b/example/doc/Jamfile.v2 index 567577b..894332e 100644 --- a/example/doc/Jamfile.v2 +++ b/example/doc/Jamfile.v2 @@ -19,6 +19,7 @@ project msvc:/wd4503 # decorated name length exceeded, name was truncated msvc:/wd4456 # declaration of 'A' hides previous local declaration msvc:/wd4459 # declaration of 'A' hides global declaration + msvc:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS which are used by Fusion intel-win:_SCL_SECURE_NO_WARNINGS intel-win:_SCL_SECURE_NO_DEPRECATE intel-win:_CRT_SECURE_NO_WARNINGS diff --git a/example/event_log/Jamfile.v2 b/example/event_log/Jamfile.v2 index b62a8d6..7c89c49 100644 --- a/example/event_log/Jamfile.v2 +++ b/example/event_log/Jamfile.v2 @@ -18,6 +18,7 @@ project msvc:/wd4503 # decorated name length exceeded, name was truncated msvc:/wd4456 # declaration of 'A' hides previous local declaration msvc:/wd4459 # declaration of 'A' hides global declaration + msvc:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS which are used by Fusion intel-win:_SCL_SECURE_NO_WARNINGS intel-win:_SCL_SECURE_NO_DEPRECATE intel-win:_CRT_SECURE_NO_WARNINGS diff --git a/example/keywords/Jamfile.v2 b/example/keywords/Jamfile.v2 index aadf4f5..1e4a40c 100644 --- a/example/keywords/Jamfile.v2 +++ b/example/keywords/Jamfile.v2 @@ -16,6 +16,7 @@ project msvc:/wd4503 # decorated name length exceeded, name was truncated msvc:/wd4456 # declaration of 'A' hides previous local declaration msvc:/wd4459 # declaration of 'A' hides global declaration + msvc:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS which are used by Fusion intel-win:_SCL_SECURE_NO_WARNINGS intel-win:_SCL_SECURE_NO_DEPRECATE intel-win:_CRT_SECURE_NO_WARNINGS diff --git a/example/multiple_files/Jamfile.v2 b/example/multiple_files/Jamfile.v2 index 31c3e4f..29566c3 100644 --- a/example/multiple_files/Jamfile.v2 +++ b/example/multiple_files/Jamfile.v2 @@ -16,6 +16,7 @@ project msvc:/wd4503 # decorated name length exceeded, name was truncated msvc:/wd4456 # declaration of 'A' hides previous local declaration msvc:/wd4459 # declaration of 'A' hides global declaration + msvc:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS which are used by Fusion intel-win:_SCL_SECURE_NO_WARNINGS intel-win:_SCL_SECURE_NO_DEPRECATE intel-win:_CRT_SECURE_NO_WARNINGS diff --git a/example/multiple_threads/Jamfile.v2 b/example/multiple_threads/Jamfile.v2 index bc98bc9..66dc00f 100644 --- a/example/multiple_threads/Jamfile.v2 +++ b/example/multiple_threads/Jamfile.v2 @@ -16,6 +16,7 @@ project msvc:/wd4503 # decorated name length exceeded, name was truncated msvc:/wd4456 # declaration of 'A' hides previous local declaration msvc:/wd4459 # declaration of 'A' hides global declaration + msvc:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS which are used by Fusion intel-win:_SCL_SECURE_NO_WARNINGS intel-win:_SCL_SECURE_NO_DEPRECATE intel-win:_CRT_SECURE_NO_WARNINGS diff --git a/example/native_syslog/Jamfile.v2 b/example/native_syslog/Jamfile.v2 index 393f403..f2a2c2b 100644 --- a/example/native_syslog/Jamfile.v2 +++ b/example/native_syslog/Jamfile.v2 @@ -17,6 +17,7 @@ project msvc:/wd4503 # decorated name length exceeded, name was truncated msvc:/wd4456 # declaration of 'A' hides previous local declaration msvc:/wd4459 # declaration of 'A' hides global declaration + msvc:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS which are used by Fusion intel-win:_SCL_SECURE_NO_WARNINGS intel-win:_SCL_SECURE_NO_DEPRECATE intel-win:_CRT_SECURE_NO_WARNINGS diff --git a/example/rotating_file/Jamfile.v2 b/example/rotating_file/Jamfile.v2 index 2a4d9f9..a9b4748 100644 --- a/example/rotating_file/Jamfile.v2 +++ b/example/rotating_file/Jamfile.v2 @@ -16,6 +16,7 @@ project msvc:/wd4503 # decorated name length exceeded, name was truncated msvc:/wd4456 # declaration of 'A' hides previous local declaration msvc:/wd4459 # declaration of 'A' hides global declaration + msvc:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS which are used by Fusion intel-win:_SCL_SECURE_NO_WARNINGS intel-win:_SCL_SECURE_NO_DEPRECATE intel-win:_CRT_SECURE_NO_WARNINGS diff --git a/example/settings_file/Jamfile.v2 b/example/settings_file/Jamfile.v2 index 72595aa..d5ce605 100644 --- a/example/settings_file/Jamfile.v2 +++ b/example/settings_file/Jamfile.v2 @@ -16,6 +16,7 @@ project msvc:/wd4503 # decorated name length exceeded, name was truncated msvc:/wd4456 # declaration of 'A' hides previous local declaration msvc:/wd4459 # declaration of 'A' hides global declaration + msvc:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS which are used by Fusion intel-win:_SCL_SECURE_NO_WARNINGS intel-win:_SCL_SECURE_NO_DEPRECATE intel-win:_CRT_SECURE_NO_WARNINGS diff --git a/example/settings_file_formatter_factory/Jamfile.v2 b/example/settings_file_formatter_factory/Jamfile.v2 index 83bd4d2..6098f8a 100644 --- a/example/settings_file_formatter_factory/Jamfile.v2 +++ b/example/settings_file_formatter_factory/Jamfile.v2 @@ -16,6 +16,7 @@ project msvc:/wd4503 # decorated name length exceeded, name was truncated msvc:/wd4456 # declaration of 'A' hides previous local declaration msvc:/wd4459 # declaration of 'A' hides global declaration + msvc:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS which are used by Fusion intel-win:_SCL_SECURE_NO_WARNINGS intel-win:_SCL_SECURE_NO_DEPRECATE intel-win:_CRT_SECURE_NO_WARNINGS diff --git a/example/syslog/Jamfile.v2 b/example/syslog/Jamfile.v2 index 14d24c9..8e81bf4 100644 --- a/example/syslog/Jamfile.v2 +++ b/example/syslog/Jamfile.v2 @@ -17,6 +17,7 @@ project msvc:/wd4503 # decorated name length exceeded, name was truncated msvc:/wd4456 # declaration of 'A' hides previous local declaration msvc:/wd4459 # declaration of 'A' hides global declaration + msvc:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS which are used by Fusion intel-win:_SCL_SECURE_NO_WARNINGS intel-win:_SCL_SECURE_NO_DEPRECATE intel-win:_CRT_SECURE_NO_WARNINGS diff --git a/example/trivial/Jamfile.v2 b/example/trivial/Jamfile.v2 index 2d3ffa0..7ea90e1 100644 --- a/example/trivial/Jamfile.v2 +++ b/example/trivial/Jamfile.v2 @@ -16,6 +16,7 @@ project msvc:/wd4503 # decorated name length exceeded, name was truncated msvc:/wd4456 # declaration of 'A' hides previous local declaration msvc:/wd4459 # declaration of 'A' hides global declaration + msvc:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS which are used by Fusion intel-win:_SCL_SECURE_NO_WARNINGS intel-win:_SCL_SECURE_NO_DEPRECATE intel-win:_CRT_SECURE_NO_WARNINGS diff --git a/example/wide_char/Jamfile.v2 b/example/wide_char/Jamfile.v2 index 4fb28ad..2d45644 100644 --- a/example/wide_char/Jamfile.v2 +++ b/example/wide_char/Jamfile.v2 @@ -16,6 +16,7 @@ project msvc:/wd4503 # decorated name length exceeded, name was truncated msvc:/wd4456 # declaration of 'A' hides previous local declaration msvc:/wd4459 # declaration of 'A' hides global declaration + msvc:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS which are used by Fusion intel-win:_SCL_SECURE_NO_WARNINGS intel-win:_SCL_SECURE_NO_DEPRECATE intel-win:_CRT_SECURE_NO_WARNINGS diff --git a/include/boost/log/attributes/attribute_value.hpp b/include/boost/log/attributes/attribute_value.hpp index 95014c1..7cc11bf 100644 --- a/include/boost/log/attributes/attribute_value.hpp +++ b/include/boost/log/attributes/attribute_value.hpp @@ -15,11 +15,11 @@ #ifndef BOOST_LOG_ATTRIBUTE_VALUE_HPP_INCLUDED_ #define BOOST_LOG_ATTRIBUTE_VALUE_HPP_INCLUDED_ +#include #include #include #include #include -#include #include #include #include @@ -103,7 +103,7 @@ public: /*! * \return The attribute value type */ - virtual type_info_wrapper get_type() const { return type_info_wrapper(); } + virtual typeindex::type_index get_type() const { return typeindex::type_index(); } }; private: @@ -166,12 +166,12 @@ public: * 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 + typeindex::type_index get_type() const { if (m_pImpl.get()) return m_pImpl->get_type(); else - return type_info_wrapper(); + return typeindex::type_index(); } /*! diff --git a/include/boost/log/attributes/attribute_value_impl.hpp b/include/boost/log/attributes/attribute_value_impl.hpp index 99bf022..50ba812 100644 --- a/include/boost/log/attributes/attribute_value_impl.hpp +++ b/include/boost/log/attributes/attribute_value_impl.hpp @@ -15,6 +15,7 @@ #ifndef BOOST_LOG_ATTRIBUTES_ATTRIBUTE_VALUE_IMPL_HPP_INCLUDED_ #define BOOST_LOG_ATTRIBUTES_ATTRIBUTE_VALUE_IMPL_HPP_INCLUDED_ +#include #include #include #include @@ -87,7 +88,7 @@ public: /*! * \return The attribute value type */ - type_info_wrapper get_type() const { return type_info_wrapper(typeid(value_type)); } + typeindex::type_index get_type() const { return typeindex::type_id< value_type >(); } /*! * \return Reference to the contained value. diff --git a/include/boost/log/attributes/current_thread_id.hpp b/include/boost/log/attributes/current_thread_id.hpp index 0861a37..23573e3 100644 --- a/include/boost/log/attributes/current_thread_id.hpp +++ b/include/boost/log/attributes/current_thread_id.hpp @@ -79,7 +79,7 @@ protected: return new detached_value(boost::log::aux::this_thread::get_id()); } - type_info_wrapper get_type() const { return type_info_wrapper(typeid(value_type)); } + typeindex::type_index get_type() const { return typeindex::type_id< value_type >(); } }; public: diff --git a/include/boost/log/attributes/fallback_policy.hpp b/include/boost/log/attributes/fallback_policy.hpp index 549b81d..cde3e94 100644 --- a/include/boost/log/attributes/fallback_policy.hpp +++ b/include/boost/log/attributes/fallback_policy.hpp @@ -15,11 +15,11 @@ #ifndef BOOST_LOG_ATTRIBUTES_FALLBACK_POLICY_HPP_INCLUDED_ #define BOOST_LOG_ATTRIBUTES_FALLBACK_POLICY_HPP_INCLUDED_ +#include #include #include #include #include -#include #include #include @@ -59,7 +59,7 @@ struct fallback_to_none /*! * 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&) + static void on_invalid_type(typeindex::type_index const&) { } @@ -99,7 +99,7 @@ struct fallback_to_throw /*! * 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) + static void on_invalid_type(typeindex::type_index const& t) { BOOST_LOG_THROW_DESCR_PARAMS(invalid_type, "Attribute value has incompatible type", (t)); } @@ -161,7 +161,7 @@ struct fallback_to_default /*! * 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&) + static void on_invalid_type(typeindex::type_index const&) { } diff --git a/include/boost/log/core/record_view.hpp b/include/boost/log/core/record_view.hpp index 613f93d..6fa7a63 100644 --- a/include/boost/log/core/record_view.hpp +++ b/include/boost/log/core/record_view.hpp @@ -88,8 +88,8 @@ private: BOOST_DELETED_FUNCTION(public_data(public_data const&)) BOOST_DELETED_FUNCTION(public_data& operator= (public_data const&)) - friend void intrusive_ptr_add_ref(const public_data* p) { ++p->m_ref_counter; } - friend void intrusive_ptr_release(const public_data* p) { if (--p->m_ref_counter == 0) public_data::destroy(p); } + friend void intrusive_ptr_add_ref(const public_data* p) BOOST_NOEXCEPT { ++p->m_ref_counter; } + friend void intrusive_ptr_release(const public_data* p) BOOST_NOEXCEPT { if (--p->m_ref_counter == 0) public_data::destroy(p); } }; private: diff --git a/include/boost/log/detail/event.hpp b/include/boost/log/detail/event.hpp index 4bb4982..0168e17 100644 --- a/include/boost/log/detail/event.hpp +++ b/include/boost/log/detail/event.hpp @@ -22,12 +22,15 @@ #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 -# include -# define BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE -# endif +# include +# if (defined(linux) || defined(__linux) || defined(__linux__)) && BOOST_ATOMIC_INT_LOCK_FREE == 2 +# include +# define BOOST_LOG_EVENT_USE_FUTEX +# elif defined(_POSIX_SEMAPHORES) && (_POSIX_SEMAPHORES + 0) > 0 && BOOST_ATOMIC_FLAG_LOCK_FREE == 2 +# include +# include +# include +# define BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE # endif #elif defined(BOOST_THREAD_PLATFORM_WIN32) # include @@ -48,12 +51,37 @@ BOOST_LOG_OPEN_NAMESPACE namespace aux { -#if defined(BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE) +#if defined(BOOST_LOG_EVENT_USE_FUTEX) + +class futex_based_event +{ +private: + boost::atomic< int > m_state; + +public: + //! Default constructor + BOOST_LOG_API futex_based_event(); + //! Destructor + BOOST_LOG_API ~futex_based_event(); + + //! Waits for the object to become signalled + BOOST_LOG_API void wait(); + //! Sets the object to a signalled state + BOOST_LOG_API void set_signalled(); + + // Copying prohibited + BOOST_DELETED_FUNCTION(futex_based_event(futex_based_event const&)) + BOOST_DELETED_FUNCTION(futex_based_event& operator= (futex_based_event const&)) +}; + +typedef futex_based_event event; + +#elif defined(BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE) class sem_based_event { private: - boost::uint32_t m_state; + boost::atomic_flag m_state; sem_t m_semaphore; public: diff --git a/include/boost/log/detail/visible_type.hpp b/include/boost/log/detail/is_ostream.hpp similarity index 54% rename from include/boost/log/detail/visible_type.hpp rename to include/boost/log/detail/is_ostream.hpp index 79f4007..2131bae 100644 --- a/include/boost/log/detail/visible_type.hpp +++ b/include/boost/log/detail/is_ostream.hpp @@ -5,19 +5,23 @@ * http://www.boost.org/LICENSE_1_0.txt) */ /*! - * \file visible_type.hpp + * \file is_ostream.hpp * \author Andrey Semashev - * \date 08.03.2007 + * \date 05.07.2015 * * \brief This header is the Boost.Log library implementation, see the library documentation * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. In this file * internal configuration macros are defined. */ -#ifndef BOOST_LOG_DETAIL_VISIBLE_TYPE_HPP_INCLUDED_ -#define BOOST_LOG_DETAIL_VISIBLE_TYPE_HPP_INCLUDED_ +#ifndef BOOST_LOG_DETAIL_IS_OSTREAM_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_IS_OSTREAM_HPP_INCLUDED_ +#include +#include +#include #include +#include #include #ifdef BOOST_HAS_PRAGMA_ONCE @@ -30,11 +34,16 @@ BOOST_LOG_OPEN_NAMESPACE namespace aux { -//! The wrapper type whose type_info is always visible template< typename T > -struct BOOST_SYMBOL_VISIBLE visible_type +struct is_ostream { - typedef T wrapped_type; + static BOOST_CONSTEXPR_OR_CONST bool value = is_base_of< std::ios_base, T >::value && has_left_shift< T, int >::value; +}; + +template< typename CharT, typename TraitsT, typename AllocatorT > +struct is_ostream< basic_formatting_ostream< CharT, TraitsT, AllocatorT > > +{ + static BOOST_CONSTEXPR_OR_CONST bool value = true; }; } // namespace aux @@ -45,4 +54,4 @@ BOOST_LOG_CLOSE_NAMESPACE // namespace log #include -#endif // BOOST_LOG_DETAIL_VISIBLE_TYPE_HPP_INCLUDED_ +#endif // BOOST_LOG_DETAIL_IS_OSTREAM_HPP_INCLUDED_ diff --git a/include/boost/log/exceptions.hpp b/include/boost/log/exceptions.hpp index f5bcbc4..8f305fa 100644 --- a/include/boost/log/exceptions.hpp +++ b/include/boost/log/exceptions.hpp @@ -18,10 +18,10 @@ #include #include #include +#include #include #include #include -#include #include #ifdef BOOST_HAS_PRAGMA_ONCE @@ -130,8 +130,8 @@ public: 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); + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, typeindex::type_index const& type); + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, attribute_name const& name, typeindex::type_index const& type); #endif }; diff --git a/include/boost/log/sources/global_logger_storage.hpp b/include/boost/log/sources/global_logger_storage.hpp index ffbc431..a98e5e6 100644 --- a/include/boost/log/sources/global_logger_storage.hpp +++ b/include/boost/log/sources/global_logger_storage.hpp @@ -15,14 +15,13 @@ #ifndef BOOST_LOG_SOURCES_GLOBAL_LOGGER_STORAGE_HPP_INCLUDED_ #define BOOST_LOG_SOURCES_GLOBAL_LOGGER_STORAGE_HPP_INCLUDED_ -#include #include +#include #include #include #include #include #include -#include #include #ifdef BOOST_HAS_PRAGMA_ONCE @@ -41,17 +40,19 @@ namespace aux { struct BOOST_LOG_NO_VTABLE BOOST_SYMBOL_VISIBLE logger_holder_base { //! The source file name where the logger was registered - const char* m_RegistrationFile; + const char* const m_RegistrationFile; //! The line number where the logger was registered - unsigned int m_RegistrationLine; + const unsigned int m_RegistrationLine; + //! Stored logger type + const typeindex::type_index m_LoggerType; - logger_holder_base(const char* file, unsigned int line) : + logger_holder_base(const char* file, unsigned int line, typeindex::type_index logger_type) BOOST_NOEXCEPT : m_RegistrationFile(file), - m_RegistrationLine(line) + m_RegistrationLine(line), + m_LoggerType(logger_type) { } virtual ~logger_holder_base() {} - virtual std::type_info const& logger_type() const = 0; }; //! The actual logger holder class @@ -63,11 +64,10 @@ struct BOOST_SYMBOL_VISIBLE logger_holder : LoggerT m_Logger; logger_holder(const char* file, unsigned int line, LoggerT const& logger) : - logger_holder_base(file, line), + logger_holder_base(file, line, typeindex::type_id< LoggerT >()), m_Logger(logger) { } - std::type_info const& logger_type() const { return typeid(LoggerT); } }; //! The class implements a global repository of tagged loggers @@ -76,7 +76,7 @@ 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); + BOOST_LOG_API static shared_ptr< logger_holder_base > get_or_init(typeindex::type_index key, initializer_t initializer); // Non-constructible, non-copyable, non-assignable BOOST_DELETED_FUNCTION(global_storage()) @@ -86,8 +86,8 @@ struct global_storage //! 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, + typeindex::type_index tag_type, + typeindex::type_index logger_type, logger_holder_base const& registered); //! The class implements a logger singleton @@ -116,18 +116,24 @@ struct logger_singleton : 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) + const typeindex::type_index tag_type_index = typeindex::type_id< TagT >(); + shared_ptr< logger_holder_base > holder = global_storage::get_or_init(tag_type_index, &logger_singleton::construct_logger); + const typeindex::type_index logger_type_index = typeindex::type_id< logger_type >(); + if (holder->m_LoggerType == logger_type_index) + { + // Note: dynamic_cast may fail here if logger_type is not visible (for example, with Clang on Linux, if the original logger + // instance was initialized in a different DSO than where it's being queried). logger_holder default visibility doesn't + // help since it is inhibited by the template parameter visibility. + instance = boost::static_pointer_cast< logger_holder< logger_type > >(holder); + } + else { // 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); + throw_odr_violation(tag_type_index, logger_type_index, *holder); } } diff --git a/include/boost/log/support/exception.hpp b/include/boost/log/support/exception.hpp index e880115..f6d9be2 100644 --- a/include/boost/log/support/exception.hpp +++ b/include/boost/log/support/exception.hpp @@ -15,11 +15,11 @@ #ifndef BOOST_LOG_SUPPORT_EXCEPTION_HPP_INCLUDED_ #define BOOST_LOG_SUPPORT_EXCEPTION_HPP_INCLUDED_ +#include #include #include #include #include -#include #include #ifdef BOOST_HAS_PRAGMA_ONCE @@ -38,7 +38,7 @@ typedef error_info< struct attribute_name_info_tag, attribute_name > attribute_n /*! * Type info exception information */ -typedef error_info< struct type_info_info_tag, type_info_wrapper > type_info_info; +typedef error_info< struct type_info_info_tag, typeindex::type_index > type_info_info; /*! * Parse position exception information diff --git a/include/boost/log/utility/empty_deleter.hpp b/include/boost/log/utility/empty_deleter.hpp deleted file mode 100644 index 09bf29c..0000000 --- a/include/boost/log/utility/empty_deleter.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright Andrey Semashev 2007 - 2015. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -/*! - * \file empty_deleter.hpp - * \author Andrey Semashev - * \date 22.04.2007 - * - * This header is deprecated, use boost/utility/empty_deleter.hpp instead. The header is left for - * backward compatibility and will be removed in future versions. - */ - -#ifndef BOOST_LOG_UTILITY_EMPTY_DELETER_HPP_INCLUDED_ -#define BOOST_LOG_UTILITY_EMPTY_DELETER_HPP_INCLUDED_ - -#include -#include - -#ifdef BOOST_HAS_PRAGMA_ONCE -#pragma once -#endif - -#if defined(__GNUC__) -#pragma message "Boost.Log: This header is deprecated, use boost/core/null_deleter.hpp instead." -#elif defined(_MSC_VER) -#pragma message("Boost.Log: This header is deprecated, use boost/core/null_deleter.hpp instead.") -#endif - -namespace boost { - -BOOST_LOG_OPEN_NAMESPACE - -typedef boost::null_deleter empty_deleter; - -BOOST_LOG_CLOSE_NAMESPACE // namespace log - -} // namespace boost - -#endif // BOOST_LOG_UTILITY_EMPTY_DELETER_HPP_INCLUDED_ diff --git a/include/boost/log/utility/explicit_operator_bool.hpp b/include/boost/log/utility/explicit_operator_bool.hpp deleted file mode 100644 index d30aff6..0000000 --- a/include/boost/log/utility/explicit_operator_bool.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright Andrey Semashev 2007 - 2015. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -/*! - * \file explicit_operator_bool.hpp - * \author Andrey Semashev - * \date 08.03.2009 - * - * This header is deprecated, use boost/utility/explicit_operator_bool.hpp instead. The header is left for - * backward compatibility and will be removed in future versions. - */ - -#ifndef BOOST_LOG_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_ -#define BOOST_LOG_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_ - -#include -#include - -#ifdef BOOST_HAS_PRAGMA_ONCE -#pragma once -#endif - -#if defined(__GNUC__) -#pragma message "Boost.Log: This header is deprecated, use boost/utility/explicit_operator_bool.hpp instead." -#elif defined(_MSC_VER) -#pragma message("Boost.Log: This header is deprecated, use boost/utility/explicit_operator_bool.hpp instead.") -#endif - -/*! - * \brief The macro defines an explicit operator of conversion to \c bool - * - * The macro should be used inside the definition of a class that has to - * support the conversion. The class should also implement operator!, - * in terms of which the conversion operator will be implemented. - */ -#define BOOST_LOG_EXPLICIT_OPERATOR_BOOL()\ - BOOST_EXPLICIT_OPERATOR_BOOL() - -#endif // BOOST_LOG_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_ diff --git a/include/boost/log/utility/formatting_ostream.hpp b/include/boost/log/utility/formatting_ostream.hpp index 88b85f8..5c7d96d 100644 --- a/include/boost/log/utility/formatting_ostream.hpp +++ b/include/boost/log/utility/formatting_ostream.hpp @@ -54,6 +54,11 @@ template< typename R > struct enable_if_char_type< char32_t, R > { typedef R type; }; #endif +template< typename StreamT, typename R > +struct enable_if_formatting_ostream {}; +template< typename CharT, typename TraitsT, typename AllocatorT, typename R > +struct enable_if_formatting_ostream< basic_formatting_ostream< CharT, TraitsT, AllocatorT >, R > { typedef R type; }; + } // namespace aux /*! @@ -768,17 +773,19 @@ void basic_formatting_ostream< CharT, TraitsT, AllocatorT >::aligned_write(const } } -template< typename CharT, typename TraitsT, typename AllocatorT, typename T > -inline basic_formatting_ostream< CharT, TraitsT, AllocatorT >& -operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >& strm, T const& value) +// Implementation note: these operators below should be the least attractive for the compiler +// so that user's overloads are chosen, when present. We use function template partial ordering for this purpose. +template< typename StreamT, typename T > +inline typename boost::log::aux::enable_if_formatting_ostream< StreamT, StreamT& >::type +operator<< (StreamT& strm, T const& value) { strm.stream() << value; return strm; } -template< typename CharT, typename TraitsT, typename AllocatorT, typename T > -inline basic_formatting_ostream< CharT, TraitsT, AllocatorT >& -operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >& strm, T& value) +template< typename StreamT, typename T > +inline typename boost::log::aux::enable_if_formatting_ostream< StreamT, StreamT& >::type +operator<< (StreamT& strm, T& value) { strm.stream() << value; return strm; @@ -786,19 +793,19 @@ operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >& strm, T& val #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) -template< typename CharT, typename TraitsT, typename AllocatorT, typename T > -inline basic_formatting_ostream< CharT, TraitsT, AllocatorT >& -operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >&& strm, T const& value) +template< typename StreamT, typename T > +inline typename boost::log::aux::enable_if_formatting_ostream< StreamT, StreamT& >::type +operator<< (StreamT&& strm, T const& value) { - static_cast< basic_formatting_ostream< CharT, TraitsT, AllocatorT >& >(strm) << value; + strm.stream() << value; return strm; } -template< typename CharT, typename TraitsT, typename AllocatorT, typename T > -inline basic_formatting_ostream< CharT, TraitsT, AllocatorT >& -operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >&& strm, T& value) +template< typename StreamT, typename T > +inline typename boost::log::aux::enable_if_formatting_ostream< StreamT, StreamT& >::type +operator<< (StreamT&& strm, T& value) { - static_cast< basic_formatting_ostream< CharT, TraitsT, AllocatorT >& >(strm) << value; + strm.stream() << value; return strm; } diff --git a/include/boost/log/utility/intrusive_ref_counter.hpp b/include/boost/log/utility/intrusive_ref_counter.hpp deleted file mode 100644 index 87f8ccc..0000000 --- a/include/boost/log/utility/intrusive_ref_counter.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright Andrey Semashev 2007 - 2015. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -/*! - * \file intrusive_ref_counter.hpp - * \author Andrey Semashev - * \date 12.03.2009 - * - * This header is deprecated, use boost/smart_ptr/intrusive_ref_counter.hpp instead. The header is left for - * backward compatibility and will be removed in future versions. - */ - -#ifndef BOOST_LOG_UTILITY_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_ -#define BOOST_LOG_UTILITY_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_ - -#include -#include -#include -#include - -#ifdef BOOST_HAS_PRAGMA_ONCE -#pragma once -#endif - -#if defined(__GNUC__) -#pragma message "Boost.Log: This header is deprecated, use boost/smart_ptr/intrusive_ref_counter.hpp instead." -#elif defined(_MSC_VER) -#pragma message("Boost.Log: This header is deprecated, use boost/smart_ptr/intrusive_ref_counter.hpp instead.") -#endif - -namespace boost { - -BOOST_LOG_OPEN_NAMESPACE - -namespace aux { - -struct legacy_intrusive_ref_counter_root -{ - virtual ~legacy_intrusive_ref_counter_root() {} -}; - -} // namespace aux - -typedef boost::intrusive_ref_counter< aux::legacy_intrusive_ref_counter_root > intrusive_ref_counter; - -BOOST_LOG_CLOSE_NAMESPACE // namespace log - -} // namespace boost - -#include - -#endif // BOOST_LOG_UTILITY_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_ diff --git a/include/boost/log/utility/manipulators/to_log.hpp b/include/boost/log/utility/manipulators/to_log.hpp index 20ea2c2..9186616 100644 --- a/include/boost/log/utility/manipulators/to_log.hpp +++ b/include/boost/log/utility/manipulators/to_log.hpp @@ -16,8 +16,9 @@ #define BOOST_LOG_UTILITY_MANIPULATORS_TO_LOG_HPP_INCLUDED_ #include -#include +#include #include +#include #include #include @@ -46,34 +47,27 @@ private: 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) {} + explicit to_log_manip(value_type const& value) BOOST_NOEXCEPT : m_value(value) {} + to_log_manip(to_log_manip const& that) BOOST_NOEXCEPT : m_value(that.m_value) {} - value_type const& get() const { return m_value; } + value_type const& get() const BOOST_NOEXCEPT { 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) +template< typename StreamT, typename T, typename TagT > +inline typename enable_if_c< log::aux::is_ostream< StreamT >::value, StreamT& >::type operator<< (StreamT& 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) +inline to_log_manip< T > to_log(T const& value) BOOST_NOEXCEPT { return to_log_manip< T >(value); } template< typename TagT, typename T > -inline to_log_manip< T, TagT > to_log(T const& value) +inline to_log_manip< T, TagT > to_log(T const& value) BOOST_NOEXCEPT { return to_log_manip< T, TagT >(value); } diff --git a/include/boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp b/include/boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp index 63c7bc1..d01228a 100644 --- a/include/boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp +++ b/include/boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp @@ -19,11 +19,10 @@ #include #include #include +#include #include #include #include -#include -#include #include #include @@ -78,7 +77,7 @@ private: #endif // BOOST_LOG_DOXYGEN_PASS //! The dispatching map - typedef std::map< type_info_wrapper, shared_ptr< callback_base > > dispatching_map; + typedef std::map< typeindex::type_index, shared_ptr< callback_base > > dispatching_map; dispatching_map m_DispatchingMap; public: @@ -118,7 +117,7 @@ public: 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 >)); + typeindex::type_index wrapper(typeindex::type_id< T >()); m_DispatchingMap[wrapper].swap(p); } @@ -132,11 +131,10 @@ public: private: #ifndef BOOST_LOG_DOXYGEN_PASS - static callback_base get_callback(type_dispatcher* p, std::type_info const& type) + static callback_base get_callback(type_dispatcher* p, typeindex::type_index 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); + dispatching_map::iterator it = self->m_DispatchingMap.find(type); if (it != self->m_DispatchingMap.end()) return *it->second; else diff --git a/include/boost/log/utility/type_dispatch/static_type_dispatcher.hpp b/include/boost/log/utility/type_dispatch/static_type_dispatcher.hpp index a5743e2..bae420f 100644 --- a/include/boost/log/utility/type_dispatch/static_type_dispatcher.hpp +++ b/include/boost/log/utility/type_dispatch/static_type_dispatcher.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -30,9 +31,7 @@ #include #include #include -#include #include -#include #include #include @@ -50,7 +49,7 @@ namespace aux { struct dispatching_map_order { typedef bool result_type; - typedef std::pair< type_info_wrapper, void* > first_argument_type, second_argument_type; + typedef std::pair< typeindex::type_index, 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); @@ -62,15 +61,15 @@ template< typename VisitorT > struct dispatching_map_initializer { template< typename IteratorT > - static BOOST_FORCEINLINE void init(IteratorT*, IteratorT*, std::pair< type_info_wrapper, void* >*) + static BOOST_FORCEINLINE void init(IteratorT*, IteratorT*, std::pair< typeindex::type_index, void* >*) { } template< typename BeginIteratorT, typename EndIteratorT > - static BOOST_FORCEINLINE void init(BeginIteratorT*, EndIteratorT* end, std::pair< type_info_wrapper, void* >* p) + static BOOST_FORCEINLINE void init(BeginIteratorT*, EndIteratorT* end, std::pair< typeindex::type_index, void* >* p) { typedef typename mpl::deref< BeginIteratorT >::type type; - do_init(static_cast< visible_type< type >* >(0), p); + do_init(static_cast< type* >(0), p); typedef typename mpl::next< BeginIteratorT >::type next_iterator_type; init(static_cast< next_iterator_type* >(0), end, p + 1); @@ -78,9 +77,9 @@ struct dispatching_map_initializer private: template< typename T > - static BOOST_FORCEINLINE void do_init(visible_type< T >*, std::pair< type_info_wrapper, void* >* p) + static BOOST_FORCEINLINE void do_init(T*, std::pair< typeindex::type_index, void* >* p) { - p->first = typeid(visible_type< T >); + p->first = typeindex::type_id< 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"); @@ -101,7 +100,7 @@ class type_sequence_dispatcher_base : { private: //! Dispatching map element type - typedef std::pair< type_info_wrapper, void* > dispatching_map_element_type; + typedef std::pair< typeindex::type_index, void* > dispatching_map_element_type; private: //! Dispatching map @@ -123,21 +122,20 @@ protected: private: //! The get_callback method implementation - static callback_base get_callback(type_dispatcher* p, std::type_info const& type) + static callback_base get_callback(type_dispatcher* p, typeindex::type_index type) { type_sequence_dispatcher_base* const self = static_cast< type_sequence_dispatcher_base* >(p); - type_info_wrapper wrapper(type); const dispatching_map_element_type* begin = self->m_dispatching_map_begin; const dispatching_map_element_type* end = begin + self->m_dispatching_map_size; const dispatching_map_element_type* it = std::lower_bound ( begin, end, - dispatching_map_element_type(wrapper, (void*)0), + dispatching_map_element_type(type, (void*)0), dispatching_map_order() ); - if (it != end && it->first == wrapper) + if (it != end && it->first == type) return callback_base(self->m_visitor, it->second); else return callback_base(); @@ -160,7 +158,7 @@ public: private: //! The dispatching map typedef array< - std::pair< type_info_wrapper, void* >, + std::pair< typeindex::type_index, void* >, mpl::size< supported_types >::value > dispatching_map; @@ -210,13 +208,13 @@ class single_type_dispatcher_base : { private: //! The type to match against - std::type_info const& m_type; + typeindex::type_index m_type; //! A callback for the supported type callback_base m_callback; protected: //! Initializing constructor - single_type_dispatcher_base(std::type_info const& type, callback_base const& callback) BOOST_NOEXCEPT : + single_type_dispatcher_base(typeindex::type_index type, callback_base const& callback) BOOST_NOEXCEPT : type_dispatcher(&single_type_dispatcher_base::get_callback), m_type(type), m_callback(callback) @@ -225,7 +223,7 @@ protected: private: //! The get_callback method implementation - static callback_base get_callback(type_dispatcher* p, std::type_info const& type) + static callback_base get_callback(type_dispatcher* p, typeindex::type_index type) { single_type_dispatcher_base* const self = static_cast< single_type_dispatcher_base* >(p); if (type == self->m_type) @@ -248,7 +246,7 @@ public: //! Constructor template< typename VisitorT > explicit single_type_dispatcher(VisitorT& visitor) BOOST_NOEXCEPT : - single_type_dispatcher_base(typeid(visible_type< T >), callback_base((void*)boost::addressof(visitor), &callback_base::trampoline< VisitorT, T >)) + single_type_dispatcher_base(typeindex::type_id< T >(), callback_base((void*)boost::addressof(visitor), &callback_base::trampoline< VisitorT, T >)) { } diff --git a/include/boost/log/utility/type_dispatch/type_dispatcher.hpp b/include/boost/log/utility/type_dispatch/type_dispatcher.hpp index 9ca52cd..c526511 100644 --- a/include/boost/log/utility/type_dispatch/type_dispatcher.hpp +++ b/include/boost/log/utility/type_dispatch/type_dispatcher.hpp @@ -15,10 +15,9 @@ #ifndef BOOST_LOG_TYPE_DISPATCHER_HPP_INCLUDED_ #define BOOST_LOG_TYPE_DISPATCHER_HPP_INCLUDED_ -#include +#include #include #include -#include #include #include @@ -148,7 +147,7 @@ public: protected: //! Pointer to the callback acquisition method - typedef callback_base (*get_callback_impl_type)(type_dispatcher*, std::type_info const&); + typedef callback_base (*get_callback_impl_type)(type_dispatcher*, typeindex::type_index); private: //! Pointer to the callback acquisition method @@ -176,7 +175,7 @@ public: template< typename T > callback< T > get_callback() { - return callback< T >((this->m_get_callback_impl)(this, typeid(boost::log::aux::visible_type< T >))); + return callback< T >((this->m_get_callback_impl)(this, typeindex::type_id< T >())); } }; diff --git a/include/boost/log/utility/type_info_wrapper.hpp b/include/boost/log/utility/type_info_wrapper.hpp index 9b1dc53..81cd3ae 100644 --- a/include/boost/log/utility/type_info_wrapper.hpp +++ b/include/boost/log/utility/type_info_wrapper.hpp @@ -26,6 +26,12 @@ #pragma once #endif +#if defined(__GNUC__) +#pragma message "Boost.Log: This header is deprecated, use Boost.TypeIndex instead." +#elif defined(_MSC_VER) +#pragma message("Boost.Log: This header is deprecated, use Boost.TypeIndex instead.") +#endif + namespace boost { BOOST_LOG_OPEN_NAMESPACE diff --git a/src/attribute_value_set.cpp b/src/attribute_value_set.cpp index 9453567..918109a 100644 --- a/src/attribute_value_set.cpp +++ b/src/attribute_value_set.cpp @@ -119,8 +119,6 @@ private: //! 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 @@ -141,7 +139,6 @@ private: m_pSourceAttributes(source_attrs), m_pThreadAttributes(thread_attrs), m_pGlobalAttributes(global_attrs), - m_pStorage(storage), m_pEnd(storage), m_pEOS(eos) { diff --git a/src/core.cpp b/src/core.cpp index 5eb18af..a3f9019 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -20,11 +20,14 @@ #include #include #include +#include #include #include #include #include #include +#include +#include #include #include #include @@ -38,6 +41,7 @@ #include #include #include +#include #endif #include "default_sink.hpp" #include "stateless_allocator.hpp" @@ -48,6 +52,29 @@ namespace boost { BOOST_LOG_OPEN_NAMESPACE +namespace aux { + +BOOST_LOG_ANONYMOUS_NAMESPACE { + +//! Sequence shuffling algorithm. Very similar to std::random_shuffle, used for forward portability with compilers that removed it from STL. +template< typename Iterator, typename RandomNumberGenerator > +void random_shuffle(Iterator begin, Iterator end, RandomNumberGenerator& rng) +{ + Iterator it = begin; + ++it; + while (it != end) + { + Iterator where = begin + rng() % (it - begin + 1u); + if (where != it) + boost::swap(*where, *it); + ++it; + } +} + +} // namespace + +} // namespace aux + //! Private record data information, with core-specific structures struct record_view::private_data : public public_data @@ -209,6 +236,23 @@ public: { //! Thread-specific attribute set attribute_set m_thread_attributes; + //! Random number generator for shuffling + random::taus88 m_rng; + + thread_data() : m_rng(get_random_seed()) + { + } + + private: + //! Creates a seed for RNG + static uint32_t get_random_seed() + { + uint32_t seed = static_cast< uint32_t >(posix_time::microsec_clock::universal_time().time_of_day().ticks()); +#if !defined(BOOST_LOG_NO_THREADS) + seed += static_cast< uint32_t >(log::aux::this_thread::get_id().native_id()); +#endif + return seed; + } }; public: @@ -643,7 +687,8 @@ BOOST_LOG_API void core::push_record_move(record& rec) // If all sinks are busy then block on any if (!shuffled) { - std::random_shuffle(begin, end); + implementation::thread_data* tsd = m_impl->get_thread_data(); + log::aux::random_shuffle(begin, end, tsd->m_rng); shuffled = true; } diff --git a/src/event.cpp b/src/event.cpp index ce2a9bb..0c41d40 100644 --- a/src/event.cpp +++ b/src/event.cpp @@ -24,16 +24,32 @@ #include #include -#if defined(BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE) +#if defined(BOOST_LOG_EVENT_USE_FUTEX) -#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) +#include +#include +#include +#include +#include + +#if defined(FUTEX_WAIT_PRIVATE) +#define BOOST_LOG_FUTEX_WAIT FUTEX_WAIT_PRIVATE #else -#error Boost.Log internal error: BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE must only be defined when atomic ops are available +#define BOOST_LOG_FUTEX_WAIT FUTEX_WAIT #endif + +#if defined(FUTEX_WAKE_PRIVATE) +#define BOOST_LOG_FUTEX_WAKE FUTEX_WAKE_PRIVATE +#else +#define BOOST_LOG_FUTEX_WAKE FUTEX_WAKE +#endif + +#elif defined(BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE) + #include #include +#include +#include #elif defined(BOOST_LOG_EVENT_USE_WINAPI) @@ -55,10 +71,66 @@ BOOST_LOG_OPEN_NAMESPACE namespace aux { -#if defined(BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE) +#if defined(BOOST_LOG_EVENT_USE_FUTEX) //! Default constructor -BOOST_LOG_API sem_based_event::sem_based_event() : m_state(0U) +BOOST_LOG_API futex_based_event::futex_based_event() : m_state(0) +{ +} + +//! Destructor +BOOST_LOG_API futex_based_event::~futex_based_event() +{ +} + +//! Waits for the object to become signalled +BOOST_LOG_API void futex_based_event::wait() +{ + if (m_state.exchange(0, boost::memory_order_acq_rel) == 0) + { + while (true) + { + if (::syscall(SYS_futex, &m_state.storage(), BOOST_LOG_FUTEX_WAIT, 0, NULL, NULL, 0) == 0) + { + // Another thread has set the event while sleeping + break; + } + + const int err = errno; + if (err == EWOULDBLOCK) + { + // Another thread has set the event before sleeping + break; + } + else if (err != EINTR) + { + BOOST_THROW_EXCEPTION(system::system_error( + err, system::system_category(), "Failed to block on the futex")); + } + } + + m_state.store(0, boost::memory_order_relaxed); + } +} + +//! Sets the object to a signalled state +BOOST_LOG_API void futex_based_event::set_signalled() +{ + if (m_state.exchange(1, boost::memory_order_release) == 0) + { + if (BOOST_UNLIKELY(::syscall(SYS_futex, &m_state.storage(), BOOST_LOG_FUTEX_WAKE, 1, NULL, NULL, 0) < 0)) + { + const int err = errno; + BOOST_THROW_EXCEPTION(system::system_error( + err, system::system_category(), "Failed to wake threads blocked on the futex")); + } + } +} + +#elif defined(BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE) + +//! Default constructor +BOOST_LOG_API sem_based_event::sem_based_event() : m_state() { if (sem_init(&m_semaphore, 0, 0) != 0) { @@ -77,6 +149,7 @@ BOOST_LOG_API sem_based_event::~sem_based_event() //! Waits for the object to become signalled BOOST_LOG_API void sem_based_event::wait() { + boost::atomic_thread_fence(boost::memory_order_acq_rel); while (true) { if (sem_wait(&m_semaphore) != 0) @@ -91,18 +164,17 @@ BOOST_LOG_API void sem_based_event::wait() else break; } - BOOST_LOG_EVENT_RESET(m_state); + m_state.clear(boost::memory_order_relaxed); } //! 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 (!m_state.test_and_set(boost::memory_order_release)) { if (sem_post(&m_semaphore) != 0) { const int err = errno; - BOOST_LOG_EVENT_RESET(m_state); BOOST_THROW_EXCEPTION(system::system_error( err, system::system_category(), "Failed to wake the blocked thread")); } diff --git a/src/exceptions.cpp b/src/exceptions.cpp index db1ee3f..0adcef4 100644 --- a/src/exceptions.cpp +++ b/src/exceptions.cpp @@ -129,7 +129,7 @@ void invalid_type::throw_(const char* file, std::size_t line, std::string const& ); } -void invalid_type::throw_(const char* file, std::size_t line, std::string const& descr, type_info_wrapper const& type) +void invalid_type::throw_(const char* file, std::size_t line, std::string const& descr, typeindex::type_index const& type) { boost::throw_exception(boost::enable_error_info(invalid_type(descr)) << boost::throw_file(file) @@ -138,7 +138,7 @@ void invalid_type::throw_(const char* file, std::size_t line, std::string const& ); } -void invalid_type::throw_(const char* file, std::size_t line, std::string const& descr, attribute_name const& name, type_info_wrapper const& type) +void invalid_type::throw_(const char* file, std::size_t line, std::string const& descr, attribute_name const& name, typeindex::type_index const& type) { boost::throw_exception(boost::enable_error_info(invalid_type(descr)) << boost::throw_file(file) diff --git a/src/global_logger_storage.cpp b/src/global_logger_storage.cpp index cb8e6a6..1cd026a 100644 --- a/src/global_logger_storage.cpp +++ b/src/global_logger_storage.cpp @@ -16,10 +16,10 @@ #include #include #include +#include #include #include #include -#include #include #if !defined(BOOST_LOG_NO_THREADS) #include @@ -42,7 +42,7 @@ 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; + typedef std::map< typeindex::type_index, shared_ptr< logger_holder_base > > loggers_map_t; #if !defined(BOOST_LOG_NO_THREADS) //! Synchronization primitive @@ -55,14 +55,13 @@ struct loggers_repository : } // 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) +BOOST_LOG_API shared_ptr< logger_holder_base > global_storage::get_or_init(typeindex::type_index 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); + loggers_map_t::iterator it = repo.m_Loggers.find(key); if (it != repo.m_Loggers.end()) { // There is an instance @@ -72,15 +71,15 @@ BOOST_LOG_API shared_ptr< logger_holder_base > global_storage::get_or_init(std:: { // We have to create a logger instance shared_ptr< logger_holder_base > inst = initializer(); - repo.m_Loggers[wrapped_key] = inst; + repo.m_Loggers[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, + typeindex::type_index tag_type, + typeindex::type_index logger_type, logger_holder_base const& registered) { char buf[std::numeric_limits< unsigned int >::digits10 + 3]; @@ -88,11 +87,11 @@ BOOST_LOG_API BOOST_LOG_NORETURN void throw_odr_violation( buf[0] = '\0'; std::string str = std::string("Could not initialize global logger with tag \"") + - type_info_wrapper(tag_type).pretty_name() + + tag_type.pretty_name() + "\" and type \"" + - type_info_wrapper(logger_type).pretty_name() + + logger_type.pretty_name() + "\". A logger of type \"" + - type_info_wrapper(registered.logger_type()).pretty_name() + + registered.m_LoggerType.pretty_name() + "\" with the same tag has already been registered at " + registered.m_RegistrationFile + ":" + buf + "."; diff --git a/src/named_scope.cpp b/src/named_scope.cpp index f86c1e2..0e8f95b 100644 --- a/src/named_scope.cpp +++ b/src/named_scope.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -105,7 +106,7 @@ BOOST_LOG_ANONYMOUS_NAMESPACE { /*! * \return The attribute value type */ - type_info_wrapper get_type() const { return type_info_wrapper(typeid(scope_stack)); } + typeindex::type_index get_type() const { return typeindex::type_id< 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. diff --git a/src/timestamp.cpp b/src/timestamp.cpp index 6c252df..bfd07df 100644 --- a/src/timestamp.cpp +++ b/src/timestamp.cpp @@ -203,7 +203,7 @@ 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) /* POSIX timers supported */ \ - || defined(__GNU__) /* GNU Hurd does not support POSIX timers fully but does provide clock_gettime() */ + || defined(__GNU__) || defined(__OpenBSD__) /* GNU Hurd and OpenBSD don't support POSIX timers fully but do provide clock_gettime() */ BOOST_LOG_API int64_t duration::milliseconds() const { diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 91dd1b5..8294fcd 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -28,6 +28,7 @@ project msvc:/wd4503 # decorated name length exceeded, name was truncated msvc:/wd4456 # declaration of 'A' hides previous local declaration msvc:/wd4459 # declaration of 'A' hides global declaration + msvc:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS which are used by Fusion # Disable Intel warnings: # warning #177: function "X" was declared but never referenced diff --git a/test/performance/record_emission.cpp b/test/performance/record_emission.cpp index 296f9af..d07851e 100644 --- a/test/performance/record_emission.cpp +++ b/test/performance/record_emission.cpp @@ -41,7 +41,7 @@ enum config { RECORD_COUNT = 50000000, - THREAD_COUNT = 3, + THREAD_COUNT = 8, SINK_COUNT = 3 }; @@ -104,7 +104,7 @@ int main(int argc, char* argv[]) // 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 +// 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); diff --git a/test/run/form_to_log_manip.cpp b/test/run/form_to_log_manip.cpp new file mode 100644 index 0000000..a7f83d3 --- /dev/null +++ b/test/run/form_to_log_manip.cpp @@ -0,0 +1,98 @@ +/* + * Copyright Andrey Semashev 2007 - 2015. + * Distributed under the Boost 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_to_log_manip.cpp + * \author Andrey Semashev + * \date 05.07.2015 + * + * \brief This header contains tests for support for the \c to_log_manip customization point. + */ + +#define BOOST_TEST_MODULE form_to_log_manip + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "char_definitions.hpp" +#include "make_record.hpp" + +namespace logging = boost::log; +namespace attrs = logging::attributes; +namespace expr = logging::expressions; + +namespace { + +struct my_class +{ + int m_Data; + + explicit my_class(int data) : m_Data(data) {} +}; + +} // namespace + +BOOST_LOG_ATTRIBUTE_KEYWORD(a_my_class, "MyClass", my_class) +BOOST_LOG_ATTRIBUTE_KEYWORD(a_string, "String", std::string) + +namespace { + +template< typename CharT, typename TraitsT, typename AllocatorT > +inline logging::basic_formatting_ostream< CharT, TraitsT, AllocatorT >& +operator<< (logging::basic_formatting_ostream< CharT, TraitsT, AllocatorT >& strm, logging::to_log_manip< my_class, tag::a_my_class > const& obj) +{ + strm << "a_my_class: [data: " << obj.get().m_Data << "]"; + return strm; +} + +} // namespace + +namespace std { + +template< typename CharT, typename TraitsT, typename AllocatorT > +inline logging::basic_formatting_ostream< CharT, TraitsT, AllocatorT >& +operator<< (logging::basic_formatting_ostream< CharT, TraitsT, AllocatorT >& strm, logging::to_log_manip< std::string, tag::a_string > const& obj) +{ + strm << "a_string: [" << obj.get() << "]"; + return strm; +} + +} // namespace std + +BOOST_AUTO_TEST_CASE_TEMPLATE(operator_overrides, 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; + + attrs::constant< my_class > attr1(my_class(77)); + attrs::constant< std::string > attr2("Hello"); + + attr_set set1; + set1[a_my_class.get_name()] = attr1; + set1[a_string.get_name()] = attr2; + + record_view rec = make_record_view(set1); + + // Check that out custom operators are called + { + string str1, str2; + osstream strm1(str1), strm2(str2); + formatter f = expr::stream << a_my_class << ", " << a_string; + f(rec, strm1); + strm2 << "a_my_class: [data: " << 77 << "], a_string: [" << "Hello" << "]"; + BOOST_CHECK(equal_strings(strm1.str(), strm2.str())); + } +} diff --git a/test/run/util_manip_to_log.cpp b/test/run/util_manip_to_log.cpp new file mode 100644 index 0000000..3937d54 --- /dev/null +++ b/test/run/util_manip_to_log.cpp @@ -0,0 +1,134 @@ +/* + * Copyright Andrey Semashev 2007 - 2015. + * Distributed under the Boost 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_manip_to_log.cpp + * \author Andrey Semashev + * \date 05.07.2015 + * + * \brief This header contains tests for the \c to_log stream manipulator. + */ + +#define BOOST_TEST_MODULE util_manip_to_log + +#include +#include +#include +#include +#include +#include +#include "char_definitions.hpp" + +namespace logging = boost::log; + +namespace tag { + +struct a_my_class; + +} // namespace tag + +namespace { + +struct my_class +{ + int m_Data; + + explicit my_class(int data) : m_Data(data) {} +}; + +template< typename CharT, typename TraitsT > +inline std::basic_ostream< CharT, TraitsT >& +operator<< (std::basic_ostream< CharT, TraitsT >& strm, my_class const& obj) +{ + strm << "my_class: [data: " << obj.m_Data << "]"; + return strm; +} + +template< typename StreamT > +inline StreamT& +operator<< (StreamT& strm, logging::to_log_manip< my_class > const& obj) +{ + strm << "to_log(my_class: [data: " << obj.get().m_Data << "])"; + return strm; +} + +template< typename StreamT > +inline StreamT& +operator<< (StreamT& strm, logging::to_log_manip< my_class, tag::a_my_class > const& obj) +{ + strm << "to_log(my_class: [data: " << obj.get().m_Data << "])"; + return strm; +} + +template< typename CharT, typename StreamT > +struct tests +{ + typedef CharT char_type; + typedef StreamT stream_type; + typedef std::basic_string< char_type > string; + typedef std::basic_ostringstream< char_type > std_stream; + + //! The test verifies that the default behavior of the manipulator is equivalent to the standard operator<< + static void default_operator() + { + string str; + stream_type strm1(str); + strm1 << logging::to_log(10); + + std_stream strm2; + strm2 << 10; + BOOST_CHECK(equal_strings(strm1.str(), strm2.str())); + } + + //! The test verifies that operator overrides work + static void operator_overrides() + { + { + string str; + stream_type strm1(str); + strm1 << my_class(10); + + std_stream strm2; + strm2 << "my_class: [data: " << 10 << "]"; + BOOST_CHECK(equal_strings(strm1.str(), strm2.str())); + } + { + string str; + stream_type strm1(str); + strm1 << logging::to_log(my_class(10)); + + std_stream strm2; + strm2 << "to_log(my_class: [data: " << 10 << "])"; + BOOST_CHECK(equal_strings(strm1.str(), strm2.str())); + } + { + string str; + stream_type strm1(str); + strm1 << logging::to_log< tag::a_my_class >(my_class(10)); + + std_stream strm2; + strm2 << "to_log(my_class: [data: " << 10 << "])"; + BOOST_CHECK(equal_strings(strm1.str(), strm2.str())); + } + } +}; + +} // namespace + + +//! The test verifies that the default behavior of the manipulator is equivalent to the standard operator<< +BOOST_AUTO_TEST_CASE_TEMPLATE(default_operator, CharT, char_types) +{ + tests< CharT, std::basic_ostringstream< CharT > >::default_operator(); + tests< CharT, logging::basic_formatting_ostream< CharT > >::default_operator(); +} + +//! The test verifies that operator overrides work +BOOST_AUTO_TEST_CASE_TEMPLATE(operator_overrides, CharT, char_types) +{ + tests< CharT, std::basic_ostringstream< CharT > >::operator_overrides(); + tests< CharT, logging::basic_formatting_ostream< CharT > >::operator_overrides(); +}