From 7ab1b14758228a5a05e6a588fe31e3d844218102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Hunold?= Date: Fri, 20 Feb 2015 18:24:50 +0100 Subject: [PATCH 01/27] Lift architecture detection --- build/log-architecture.jam | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/log-architecture.jam b/build/log-architecture.jam index 84da489..785dda0 100644 --- a/build/log-architecture.jam +++ b/build/log-architecture.jam @@ -20,7 +20,7 @@ feature.feature log-address-model : : free ; feature.feature log-instruction-set : : free ; project.push-current [ project.current ] ; -project.load [ path.join [ path.make $(here:D) ] ../../context/config ] ; +project.load [ path.join [ path.make $(here:D) ] ../../config/checks/architecture ] ; project.pop-current ; rule deduce-address-model ( properties * ) From 71b12228f178ebf019bad6fbb3395d2d2db978ee Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Tue, 10 Mar 2015 02:09:31 +0300 Subject: [PATCH 02/27] Disabled warning C4003 on MSVC 8 (VS2005). The warning was caused by Boost.PP macros used in Boost.Fusion and as reported by Boost.PP maintainer cannot be worked around locally in the macro definition. --- build/Jamfile.v2 | 1 + example/advanced_usage/Jamfile.v2 | 1 + example/async_log/Jamfile.v2 | 1 + example/basic_usage/Jamfile.v2 | 1 + example/bounded_async_log/Jamfile.v2 | 1 + example/doc/Jamfile.v2 | 1 + example/event_log/Jamfile.v2 | 1 + example/keywords/Jamfile.v2 | 1 + example/multiple_files/Jamfile.v2 | 1 + example/multiple_threads/Jamfile.v2 | 1 + example/native_syslog/Jamfile.v2 | 1 + example/rotating_file/Jamfile.v2 | 1 + example/settings_file/Jamfile.v2 | 1 + example/settings_file_formatter_factory/Jamfile.v2 | 1 + example/syslog/Jamfile.v2 | 1 + example/trivial/Jamfile.v2 | 1 + example/wide_char/Jamfile.v2 | 1 + test/Jamfile.v2 | 1 + 18 files changed, 18 insertions(+) diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 9eba5b2..242c598 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -136,6 +136,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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic are used by Fusion # Disable Intel warnings: # warning #177: function "X" was declared but never referenced diff --git a/example/advanced_usage/Jamfile.v2 b/example/advanced_usage/Jamfile.v2 index 528181c..6520de8 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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic 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..221aaeb 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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic 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..6652fc1 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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic 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..d1d257b 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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic 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..567dc3e 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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic 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..221f36e 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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic 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..2d30f29 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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic 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..fe22988 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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic 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..b6f0e7f 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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic 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..cddf097 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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic 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..c91fb1c 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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic 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..2ba99dc 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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic 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..e8f0fc4 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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic 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..7fea6ad 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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic 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..9677ee5 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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic 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..a1b4354 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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic 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/test/Jamfile.v2 b/test/Jamfile.v2 index 91dd1b5..3c03c45 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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic are used by Fusion # Disable Intel warnings: # warning #177: function "X" was declared but never referenced From 30ff0390ce4d3063d035735ed7b9463277b59697 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 15 Mar 2015 15:00:53 +0300 Subject: [PATCH 03/27] Fixed #11106. In some cases inserted attribute set elements could invalidate the existing elements preventing them from being found. --- doc/changelog.qbk | 1 + src/attribute_set_impl.hpp | 12 ++--- test/run/attr_attribute_set_ticket11106.cpp | 51 +++++++++++++++++++++ 3 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 test/run/attr_attribute_set_ticket11106.cpp diff --git a/doc/changelog.qbk b/doc/changelog.qbk index 02c85aa..a650198 100644 --- a/doc/changelog.qbk +++ b/doc/changelog.qbk @@ -17,6 +17,7 @@ * Fixed process id formatting. Process ids could have misplaced filler zeros. ([ticket 10926]) * Fixed build failure on GNU Hurd. * Fixed incorrect behavior of [link log.detailed.sink_backends.text_file text file sink backend] in case if free space on the file system gets exhausted. The sink will no longer create lots of empty files in attempt to recover. ([ticket 11016]) +* Fixed incorrect behavior of `attribute_set::insert()` in some cases. The inserted elements could have made some previously inserted elements not findable. ([ticket 11106]) [heading 2.4, Boost 1.57] diff --git a/src/attribute_set_impl.hpp b/src/attribute_set_impl.hpp index bbea5c5..0391519 100644 --- a/src/attribute_set_impl.hpp +++ b/src/attribute_set_impl.hpp @@ -283,12 +283,6 @@ public: b.first = b.last = n; it = m_Nodes.end(); } - else if (p == b.first) - { - // The new element should become the first element of the bucket - it = m_Nodes.iterator_to(*p); - b.first = n; - } else if (p == b.last && key.id() > p->m_Value.first.id()) { // The new element should become the last element of the bucket @@ -296,6 +290,12 @@ public: ++it; b.last = n; } + else if (p == b.first) + { + // The new element should become the first element of the bucket + it = m_Nodes.iterator_to(*p); + b.first = n; + } else { // The new element should be within the bucket diff --git a/test/run/attr_attribute_set_ticket11106.cpp b/test/run/attr_attribute_set_ticket11106.cpp new file mode 100644 index 0000000..142307d --- /dev/null +++ b/test/run/attr_attribute_set_ticket11106.cpp @@ -0,0 +1,51 @@ +/* + * 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 attr_attribute_set_ticket11106.cpp + * \author Andrey Semashev + * \date 15.03.2015 + * + * \brief This header contains a test for the fix for https://svn.boost.org/trac/boost/ticket/11106. + */ + +#define BOOST_TEST_MODULE attr_attribute_set_ticket11106 + +#include +#include +#include +#include +#include +#include + +// The test checks that insertion does not invalidate existing elements in the container +BOOST_AUTO_TEST_CASE(ticket11106) +{ + boost::log::attribute_set set; + + unsigned int i = 0; + while (i < 100) + { + std::ostringstream strm; + strm << "Attr" << i; + boost::log::attribute_name name = strm.str(); + + std::pair< boost::log::attribute_set::iterator, bool > res = set.insert(name, boost::log::attributes::make_constant(5)); + ++i; + + BOOST_CHECK(res.second); // check that insertion succeeded + BOOST_CHECK(set.find(res.first->first) != set.end()); // check that lookup works + + // Now check that all previously inserted elements are still findable + unsigned int j = 0; + for (boost::log::attribute_set::const_iterator it = set.begin(), end = set.end(); it != end; ++it, ++j) + { + boost::log::attribute_name key = it->first; + BOOST_CHECK(set.find(key) != set.end()); + } + BOOST_CHECK_EQUAL(j, i); + } +} From 89474f4a8097d419493ebe8915db363e668fef5c Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Wed, 25 Mar 2015 00:32:36 +0300 Subject: [PATCH 04/27] Define ASIO config macros before using it. Use hidden visibility by default. Boost.ASIO should not use compiler-based TLS unless it is allowed by the user of Boost.Log, otherwise the Boost.Log config option has no practical effect. As a result, it becomes more probable that Boost.ASIO will be compiled with different config macros in Boost.Log and user's code. As a partial solution use hidden visibility when building Boost.Log shared libs and ensure it uses its local copy of Boost.ASIO. Added a config test to detect support for visibility command line option. Also adjusted project names of other config tests to avoid possible name clashes with other libraries and Boost.Build infrastructure. MSVC warning 4003 is now silenced on all compiler versions as apparently not only MSVC 8 is affected. --- config/visibility/Jamfile.jam | 19 +++++++++++++++ config/visibility/visibility.cpp | 11 +++++++++ src/asio_config.hpp | 41 ++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 config/visibility/Jamfile.jam create mode 100644 config/visibility/visibility.cpp create mode 100644 src/asio_config.hpp diff --git a/config/visibility/Jamfile.jam b/config/visibility/Jamfile.jam new file mode 100644 index 0000000..5d388bc --- /dev/null +++ b/config/visibility/Jamfile.jam @@ -0,0 +1,19 @@ +# +# 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" + ; diff --git a/config/visibility/visibility.cpp b/config/visibility/visibility.cpp new file mode 100644 index 0000000..446e977 --- /dev/null +++ b/config/visibility/visibility.cpp @@ -0,0 +1,11 @@ +/* + * 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) + */ + +int main(int, char*[]) +{ + return 0; +} diff --git a/src/asio_config.hpp b/src/asio_config.hpp new file mode 100644 index 0000000..45fa736 --- /dev/null +++ b/src/asio_config.hpp @@ -0,0 +1,41 @@ +/* + * 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 asio_config.hpp + * \author Andrey Semashev + * \date 24.03.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. + */ + +#ifndef BOOST_LOG_ASIO_CONFIG_HPP_INCLUDED_ +#define BOOST_LOG_ASIO_CONFIG_HPP_INCLUDED_ + +#include + +#if !defined(BOOST_LOG_NO_ASIO) + +#if defined(BOOST_LOG_DLL) +// Make sure we have our local copy of Boost.ASIO with our configuration. This is to avoid possible ABI clashes with user's code, +// if it's compiled with other macros defined. For shared library build we also limit symbol visibility, where possible (see build/Jamfile.v2). +// Alas, for static library build there is no such protection, so user's config has to match the one of Boost.Log. +#undef BOOST_ASIO_SEPARATE_COMPILATION +#undef BOOST_ASIO_DYN_LINK +#define BOOST_ASIO_HEADER_ONLY 1 +#endif + +// Unless explicitly enabled, disable compiler-based TLS in Boost.ASIO. First, this ensures that the built Boost.Log binaries +// actually don't use compiler-based TLS unless allowed. Second, this is a temporary workaround for dynamic linking issue with +// Clang on Android described here: https://tracker.crystax.net/issues/912 (linked binaries refer to the missing __tls_get_addr symbol). +#if !defined(BOOST_LOG_USE_COMPILER_TLS) && !defined(BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION) +#define BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION +#endif + +#endif // !defined(BOOST_LOG_NO_ASIO) + +#endif // BOOST_LOG_ASIO_CONFIG_HPP_INCLUDED_ From 18df30ed33e7b1ed81067f79589b1bc96313544a Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Wed, 25 Mar 2015 00:48:52 +0300 Subject: [PATCH 05/27] Followup for the previous commit. --- build/Jamfile.v2 | 26 ++++++++++++++----- config/message-compiler/Jamfile.jam | 4 +-- config/x86-ext/Jamfile.jam | 4 +-- example/advanced_usage/Jamfile.v2 | 2 +- example/async_log/Jamfile.v2 | 2 +- example/basic_usage/Jamfile.v2 | 2 +- example/bounded_async_log/Jamfile.v2 | 2 +- example/doc/Jamfile.v2 | 2 +- example/event_log/Jamfile.v2 | 2 +- example/keywords/Jamfile.v2 | 2 +- example/multiple_files/Jamfile.v2 | 2 +- example/multiple_threads/Jamfile.v2 | 2 +- example/native_syslog/Jamfile.v2 | 2 +- example/rotating_file/Jamfile.v2 | 2 +- example/settings_file/Jamfile.v2 | 2 +- .../Jamfile.v2 | 2 +- example/syslog/Jamfile.v2 | 2 +- example/trivial/Jamfile.v2 | 2 +- example/wide_char/Jamfile.v2 | 2 +- src/init_from_settings.cpp | 1 + src/syslog_backend.cpp | 1 + test/Jamfile.v2 | 2 +- 22 files changed, 43 insertions(+), 27 deletions(-) diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 242c598..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,7 +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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic are used by Fusion + 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 @@ -244,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 = ; @@ -306,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/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/example/advanced_usage/Jamfile.v2 b/example/advanced_usage/Jamfile.v2 index 6520de8..03ea037 100644 --- a/example/advanced_usage/Jamfile.v2 +++ b/example/advanced_usage/Jamfile.v2 @@ -16,7 +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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic are used by Fusion + 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 221aaeb..7af11ff 100644 --- a/example/async_log/Jamfile.v2 +++ b/example/async_log/Jamfile.v2 @@ -16,7 +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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic are used by Fusion + 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 6652fc1..b46fd3e 100644 --- a/example/basic_usage/Jamfile.v2 +++ b/example/basic_usage/Jamfile.v2 @@ -16,7 +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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic are used by Fusion + 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 d1d257b..be5887e 100644 --- a/example/bounded_async_log/Jamfile.v2 +++ b/example/bounded_async_log/Jamfile.v2 @@ -16,7 +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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic are used by Fusion + 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 567dc3e..894332e 100644 --- a/example/doc/Jamfile.v2 +++ b/example/doc/Jamfile.v2 @@ -19,7 +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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic are used by Fusion + 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 221f36e..7c89c49 100644 --- a/example/event_log/Jamfile.v2 +++ b/example/event_log/Jamfile.v2 @@ -18,7 +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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic are used by Fusion + 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 2d30f29..1e4a40c 100644 --- a/example/keywords/Jamfile.v2 +++ b/example/keywords/Jamfile.v2 @@ -16,7 +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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic are used by Fusion + 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 fe22988..29566c3 100644 --- a/example/multiple_files/Jamfile.v2 +++ b/example/multiple_files/Jamfile.v2 @@ -16,7 +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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic are used by Fusion + 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 b6f0e7f..66dc00f 100644 --- a/example/multiple_threads/Jamfile.v2 +++ b/example/multiple_threads/Jamfile.v2 @@ -16,7 +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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic are used by Fusion + 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 cddf097..f2a2c2b 100644 --- a/example/native_syslog/Jamfile.v2 +++ b/example/native_syslog/Jamfile.v2 @@ -17,7 +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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic are used by Fusion + 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 c91fb1c..a9b4748 100644 --- a/example/rotating_file/Jamfile.v2 +++ b/example/rotating_file/Jamfile.v2 @@ -16,7 +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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic are used by Fusion + 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 2ba99dc..d5ce605 100644 --- a/example/settings_file/Jamfile.v2 +++ b/example/settings_file/Jamfile.v2 @@ -16,7 +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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic are used by Fusion + 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 e8f0fc4..6098f8a 100644 --- a/example/settings_file_formatter_factory/Jamfile.v2 +++ b/example/settings_file_formatter_factory/Jamfile.v2 @@ -16,7 +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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic are used by Fusion + 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 7fea6ad..8e81bf4 100644 --- a/example/syslog/Jamfile.v2 +++ b/example/syslog/Jamfile.v2 @@ -17,7 +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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic are used by Fusion + 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 9677ee5..7ea90e1 100644 --- a/example/trivial/Jamfile.v2 +++ b/example/trivial/Jamfile.v2 @@ -16,7 +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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic are used by Fusion + 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 a1b4354..2d45644 100644 --- a/example/wide_char/Jamfile.v2 +++ b/example/wide_char/Jamfile.v2 @@ -16,7 +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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic are used by Fusion + 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/src/init_from_settings.cpp b/src/init_from_settings.cpp index fdd5457..4b8dfbc 100644 --- a/src/init_from_settings.cpp +++ b/src/init_from_settings.cpp @@ -62,6 +62,7 @@ #include #include #if !defined(BOOST_LOG_NO_ASIO) +#include "asio_config.hpp" #include #endif #if !defined(BOOST_LOG_NO_THREADS) diff --git a/src/syslog_backend.cpp b/src/syslog_backend.cpp index a866a1e..78aaedc 100644 --- a/src/syslog_backend.cpp +++ b/src/syslog_backend.cpp @@ -27,6 +27,7 @@ #include #include #if !defined(BOOST_LOG_NO_ASIO) +#include "asio_config.hpp" #include #include #include diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 3c03c45..8294fcd 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -28,7 +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-8:/wd4003 # not enough actual parameters for macro 'X' - caused by BOOST_PP_IS_EMPTY and BOOST_PP_IS_BEGIN_PARENS whic are used by Fusion + 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 From 54759c689055a6ea37c8a690ec108c7e8588a06a Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Wed, 25 Mar 2015 01:39:20 +0300 Subject: [PATCH 06/27] Added a workaround for MSVC not failing the check for visibility support. --- config/visibility/Jamfile.jam | 3 +++ config/visibility/visibility.cpp | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/config/visibility/Jamfile.jam b/config/visibility/Jamfile.jam index 5d388bc..4cef480 100644 --- a/config/visibility/Jamfile.jam +++ b/config/visibility/Jamfile.jam @@ -16,4 +16,7 @@ project /boost/log/visibility 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 index 446e977..30f1a64 100644 --- a/config/visibility/visibility.cpp +++ b/config/visibility/visibility.cpp @@ -5,6 +5,11 @@ * 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; From f74a7df2df0947da7927782424924d605f11c349 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 28 Mar 2015 19:04:31 +0300 Subject: [PATCH 07/27] Fixed #11148. Fixed incorrect behavior of `attribute_value_set::size()` if a large number of attribute values are inserted into the set. --- doc/changelog.qbk | 1 + .../log/attributes/attribute_value_set.hpp | 2 +- src/attribute_value_set.cpp | 6 ++--- test/run/attr_attribute_value_set.cpp | 22 +++++++++++++++++++ 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/doc/changelog.qbk b/doc/changelog.qbk index a650198..942cc2e 100644 --- a/doc/changelog.qbk +++ b/doc/changelog.qbk @@ -18,6 +18,7 @@ * Fixed build failure on GNU Hurd. * Fixed incorrect behavior of [link log.detailed.sink_backends.text_file text file sink backend] in case if free space on the file system gets exhausted. The sink will no longer create lots of empty files in attempt to recover. ([ticket 11016]) * Fixed incorrect behavior of `attribute_set::insert()` in some cases. The inserted elements could have made some previously inserted elements not findable. ([ticket 11106]) +* Fixed incorrect behavior of `attribute_value_set::size()` if a large number of attribute values are inserted into the set. ([ticket 11148]) [heading 2.4, Boost 1.57] diff --git a/include/boost/log/attributes/attribute_value_set.hpp b/include/boost/log/attributes/attribute_value_set.hpp index f61da06..7aca478 100644 --- a/include/boost/log/attributes/attribute_value_set.hpp +++ b/include/boost/log/attributes/attribute_value_set.hpp @@ -330,7 +330,7 @@ public: */ BOOST_LOG_API size_type size() const; /*! - * \return true if there are no elements in the container, false otherwise. + * \return \c true if there are no elements in the container, \c false otherwise. */ bool empty() const { return (this->size() == 0); } diff --git a/src/attribute_value_set.cpp b/src/attribute_value_set.cpp index 4846b26..9c9886e 100644 --- a/src/attribute_value_set.cpp +++ b/src/attribute_value_set.cpp @@ -79,7 +79,7 @@ private: typedef intrusive::list< node, intrusive::value_traits< value_traits >, - intrusive::constant_time_size< false > + intrusive::constant_time_size< true > > node_list; //! A hash table bucket @@ -100,7 +100,7 @@ private: struct disposer { typedef void result_type; - void operator() (node* p) const + void operator() (node* p) const BOOST_NOEXCEPT { if (!p->m_DynamicallyAllocated) p->~node(); @@ -259,7 +259,7 @@ public: size_type size() { freeze(); - return (m_pEnd - m_pStorage); + return m_Nodes.size(); } //! Looks for the element with an equivalent key diff --git a/test/run/attr_attribute_value_set.cpp b/test/run/attr_attribute_value_set.cpp index a57a3a6..15fdeec 100644 --- a/test/run/attr_attribute_value_set.cpp +++ b/test/run/attr_attribute_value_set.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -220,3 +221,24 @@ BOOST_AUTO_TEST_CASE(lookup) BOOST_CHECK_EQUAL(view1.count(data::attr3()), 1UL); BOOST_CHECK_EQUAL(view1.count(data::attr4()), 0UL); } + +// The test checks size method +BOOST_AUTO_TEST_CASE(size) +{ + typedef logging::attribute_value_set attr_values; + attrs::constant< int > attr1(10); + + attr_values view; + view.freeze(); + + unsigned int i = 0; + for (; i < 100; ++i) + { + std::ostringstream strm; + strm << "Attr" << i; + + view.insert(attr_values::key_type(strm.str()), attr1.get_value()); + } + + BOOST_CHECK_EQUAL(view.size(), i); +} From 2e7eb45f485da31dba5a896c3d134c4bb6383643 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 28 Mar 2015 20:12:19 +0300 Subject: [PATCH 08/27] Removed unused data member. --- src/attribute_value_set.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/attribute_value_set.cpp b/src/attribute_value_set.cpp index 9c9886e..6210394 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) { From f1337c6fbc5699b95eec5964bb187c9008b4d133 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 28 Mar 2015 21:20:55 +0300 Subject: [PATCH 09/27] Ported library to Boost.TypeIndex. This solves symbol visibility problems with Clang on Linux when the library is built with -fvisibility=hidden. --- doc/changelog.qbk | 10 +++++ doc/log.qbk | 1 + .../boost/log/attributes/attribute_value.hpp | 8 ++-- .../log/attributes/attribute_value_impl.hpp | 3 +- .../log/attributes/current_thread_id.hpp | 2 +- .../boost/log/attributes/fallback_policy.hpp | 8 ++-- include/boost/log/exceptions.hpp | 6 +-- .../log/sources/global_logger_storage.hpp | 42 +++++++++++-------- include/boost/log/support/exception.hpp | 4 +- .../type_dispatch/dynamic_type_dispatcher.hpp | 12 +++--- .../type_dispatch/static_type_dispatcher.hpp | 34 +++++++-------- .../utility/type_dispatch/type_dispatcher.hpp | 7 ++-- src/exceptions.cpp | 4 +- src/global_logger_storage.cpp | 21 +++++----- src/named_scope.cpp | 3 +- 15 files changed, 89 insertions(+), 76 deletions(-) diff --git a/doc/changelog.qbk b/doc/changelog.qbk index 942cc2e..9e039e1 100644 --- a/doc/changelog.qbk +++ b/doc/changelog.qbk @@ -9,6 +9,16 @@ [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 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`). + [heading 2.5, Boost 1.58] [*Bug fixes:] diff --git a/doc/log.qbk b/doc/log.qbk index 1a9b8d6..be4da18 100644 --- a/doc/log.qbk +++ b/doc/log.qbk @@ -46,6 +46,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]] 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/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/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/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. From 7f9dfd579e81fc1099492ee2160766c81472a1ba Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 28 Mar 2015 21:28:49 +0300 Subject: [PATCH 10/27] Deprecated type_info_wrapper. --- doc/changelog.qbk | 1 + doc/utilities.qbk | 2 ++ include/boost/log/utility/type_info_wrapper.hpp | 6 ++++++ 3 files changed, 9 insertions(+) diff --git a/doc/changelog.qbk b/doc/changelog.qbk index 9e039e1..d297ef9 100644 --- a/doc/changelog.qbk +++ b/doc/changelog.qbk @@ -18,6 +18,7 @@ * `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. [heading 2.5, Boost 1.58] diff --git a/doc/utilities.qbk b/doc/utilities.qbk index 0f2a38a..f94123e 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/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 From d14a7e1256f5f809dedc2411831a235591031ef9 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 28 Mar 2015 21:34:11 +0300 Subject: [PATCH 11/27] Removed the previously deprecated headers: , , . --- doc/changelog.qbk | 1 + include/boost/log/utility/empty_deleter.hpp | 42 -------------- .../log/utility/explicit_operator_bool.hpp | 42 -------------- .../log/utility/intrusive_ref_counter.hpp | 55 ------------------- 4 files changed, 1 insertion(+), 139 deletions(-) delete mode 100644 include/boost/log/utility/empty_deleter.hpp delete mode 100644 include/boost/log/utility/explicit_operator_bool.hpp delete mode 100644 include/boost/log/utility/intrusive_ref_counter.hpp diff --git a/doc/changelog.qbk b/doc/changelog.qbk index d297ef9..a946000 100644 --- a/doc/changelog.qbk +++ b/doc/changelog.qbk @@ -19,6 +19,7 @@ * __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`. [heading 2.5, Boost 1.58] 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/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_ From a9738b1249021fe1aae5c28160a07ad4d8f81e99 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 28 Mar 2015 21:48:43 +0300 Subject: [PATCH 12/27] Added a release note about Boost.ASIO TLS config enforcement. --- doc/changelog.qbk | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/changelog.qbk b/doc/changelog.qbk index a946000..0982713 100644 --- a/doc/changelog.qbk +++ b/doc/changelog.qbk @@ -13,6 +13,7 @@ [*General changes:] +* The library now enforces compiler-based TLS configuration of __boost_asio__ according to Boost.Log configuration. Unless compiler-based TLS is enabled by defining `BOOST_LOG_USE_COMPILER_TLS` at Boost.Log compilation stage, compiler-based TLS in __boost_asio__ is disabled by defining `BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION`. On some systems this may cause ODR violation issues, if user's code uses __boost_asio__ with a different configuration (by default compiler-based TLS is enabled in __boost_asio__). It is *strongly advised* to align Boost.Log and __boost_asio__ configuration (either enable or disable compiler-based TLS for both libraries). * 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 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`. From 2e906dbe46f91b9f8dbf919c2643b7b68f3eab6b Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 28 Mar 2015 21:54:35 +0300 Subject: [PATCH 13/27] Imroved release notes. --- doc/changelog.qbk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/changelog.qbk b/doc/changelog.qbk index 0982713..3c47c44 100644 --- a/doc/changelog.qbk +++ b/doc/changelog.qbk @@ -15,7 +15,7 @@ * The library now enforces compiler-based TLS configuration of __boost_asio__ according to Boost.Log configuration. Unless compiler-based TLS is enabled by defining `BOOST_LOG_USE_COMPILER_TLS` at Boost.Log compilation stage, compiler-based TLS in __boost_asio__ is disabled by defining `BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION`. On some systems this may cause ODR violation issues, if user's code uses __boost_asio__ with a different configuration (by default compiler-based TLS is enabled in __boost_asio__). It is *strongly advised* to align Boost.Log and __boost_asio__ configuration (either enable or disable compiler-based TLS for both libraries). * 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 affected the following public interfaces: +* *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`). From a86343abfab7c4371fd0dbc3b04b8460b7aefe04 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 28 Mar 2015 22:03:24 +0300 Subject: [PATCH 14/27] Removed unused header. --- include/boost/log/detail/visible_type.hpp | 48 ----------------------- 1 file changed, 48 deletions(-) delete mode 100644 include/boost/log/detail/visible_type.hpp diff --git a/include/boost/log/detail/visible_type.hpp b/include/boost/log/detail/visible_type.hpp deleted file mode 100644 index 79f4007..0000000 --- a/include/boost/log/detail/visible_type.hpp +++ /dev/null @@ -1,48 +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 visible_type.hpp - * \author Andrey Semashev - * \date 08.03.2007 - * - * \brief This header is the Boost.Log library implementation, see the library documentation - * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. In this file - * internal configuration macros are defined. - */ - -#ifndef BOOST_LOG_DETAIL_VISIBLE_TYPE_HPP_INCLUDED_ -#define BOOST_LOG_DETAIL_VISIBLE_TYPE_HPP_INCLUDED_ - -#include -#include - -#ifdef BOOST_HAS_PRAGMA_ONCE -#pragma once -#endif - -namespace boost { - -BOOST_LOG_OPEN_NAMESPACE - -namespace aux { - -//! The wrapper type whose type_info is always visible -template< typename T > -struct BOOST_SYMBOL_VISIBLE visible_type -{ - typedef T wrapped_type; -}; - -} // namespace aux - -BOOST_LOG_CLOSE_NAMESPACE // namespace log - -} // namespace boost - -#include - -#endif // BOOST_LOG_DETAIL_VISIBLE_TYPE_HPP_INCLUDED_ From 34e68c7b5a7d885db51f877ba35c13927553d2ac Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 29 Mar 2015 20:12:58 +0300 Subject: [PATCH 15/27] Ported from std::random_shuffle and std::rand to Boost.Random and custom random_shuffle implementation. --- include/boost/log/core/record_view.hpp | 4 +-- src/core.cpp | 47 +++++++++++++++++++++++++- test/performance/record_emission.cpp | 4 +-- 3 files changed, 50 insertions(+), 5 deletions(-) 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/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/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); From 7cbcf861e593a68519d59e3a33be2cef64220252 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 4 Apr 2015 16:01:16 +0300 Subject: [PATCH 16/27] Improved docs. --- doc/extension.qbk | 6 ++--- doc/utilities.qbk | 22 +++++++++++++++---- .../extension_filter_parser_custom_rel.cpp | 8 +++---- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/doc/extension.qbk b/doc/extension.qbk index 4f15ee4..9a252fe 100644 --- a/doc/extension.qbk +++ b/doc/extension.qbk @@ -312,9 +312,9 @@ the `on_equality_relation` method will be called with `name` argument being "Coo 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: +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_rectangle" 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)}"] +[pre %Coordinates% is\_in\_rectangle "{(10, 10) - (20, 20)}"] First, let's define our rectangle class: @@ -324,7 +324,7 @@ As it was said, the rectangle is described by two points - the top left and the [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]. +The `on_custom_relation` method is called with the relation name (the "is\_in\_rectangle" 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_rectangle` 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] diff --git a/doc/utilities.qbk b/doc/utilities.qbk index f94123e..3dae3b2 100644 --- a/doc/utilities.qbk +++ b/doc/utilities.qbk @@ -429,13 +429,27 @@ Below are some examples of filters: [[`%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`. +The formatter string syntax is even simpler and pretty much resembles __boost_format__ format string syntax. The string is interpreted as a template which can contain attribute names enclosed with percent signs ("%"). The corresponding attribute values will replace these placeholders when the formatter is applied. The placeholder "%Message%" will be replaced with the log record text. For instance, the following formatter string: + +[teletype] + + [%TimeStamp%] *%Severity%* %Message% + +[c++] + +will make log records look like this: + +[teletype] + + [2008-07-05 13:44:23] *0* Hello world + +[c++] [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. +It must be noted 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. It is also possible to override formatting rules of the known types, including support for additional formatting parameters in the string template. 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.] +[note The parsed formatters and filters are generally less optimal than the equivalent ones written in code with [link log.detailed.expressions template expressions]. 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, when performance matters, it is advised to avoid parsed filters and formatters.] [endsect] @@ -465,7 +479,7 @@ So basically, settings container is a layered associative container, with string ] ] -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". +Sink settings are divided into separate subsections within the common top-level section "Sinks" - one subsection for each sink. The subsection names 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 container. Support for this syntax will be removed in future releases.] diff --git a/example/doc/extension_filter_parser_custom_rel.cpp b/example/doc/extension_filter_parser_custom_rel.cpp index 4db3a47..0498a00 100644 --- a/example/doc/extension_filter_parser_custom_rel.cpp +++ b/example/doc/extension_filter_parser_custom_rel.cpp @@ -120,7 +120,7 @@ std::basic_istream< CharT, TraitsT >& operator>> (std::basic_istream< CharT, Tra //[ 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) +bool is_in_rectangle(logging::value_ref< point > const& p, rectangle const& r) { if (p) { @@ -152,9 +152,9 @@ public: logging::filter on_custom_relation(logging::attribute_name const& name, string_type const& rel, string_type const& arg) { - if (rel == "is_in_rect") + if (rel == "is_in_rectangle") { - return boost::phoenix::bind(&is_in_rect, expr::attr< point >(name), boost::lexical_cast< rectangle >(arg)); + return boost::phoenix::bind(&is_in_rectangle, expr::attr< point >(name), boost::lexical_cast< rectangle >(arg)); } throw std::runtime_error("Unsupported filter relation: " + rel); } @@ -176,7 +176,7 @@ void init_logging() logging::add_console_log ( std::clog, - keywords::filter = "%Coordinates% is_in_rect \"{(0, 0) - (20, 20)}\"", + keywords::filter = "%Coordinates% is_in_rectangle \"{(0, 0) - (20, 20)}\"", keywords::format = "%TimeStamp% %Coordinates% %Message%" ); From 04e24c7a02434dc6350eae3e0dd35ae39f9f4e84 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 4 Apr 2015 16:08:13 +0300 Subject: [PATCH 17/27] Corrected a copyright date. --- doc/gen_references.xsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/gen_references.xsl b/doc/gen_references.xsl index d06ccb5..8e097b1 100644 --- a/doc/gen_references.xsl +++ b/doc/gen_references.xsl @@ -13,7 +13,7 @@ [/ - 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) From d720a11e3b0590f26bc669a733aec46b9229df7c Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 25 Apr 2015 22:49:01 +0300 Subject: [PATCH 18/27] Fixed #11190. Constructing attribute value set from attribute sets or inserting elements could invalidate elements that were in the container. --- src/attribute_value_set.cpp | 16 ++--- .../attr_attribute_value_set_ticket11190.cpp | 60 +++++++++++++++++++ 2 files changed, 68 insertions(+), 8 deletions(-) create mode 100644 test/run/attr_attribute_value_set_ticket11190.cpp diff --git a/src/attribute_value_set.cpp b/src/attribute_value_set.cpp index 6210394..918109a 100644 --- a/src/attribute_value_set.cpp +++ b/src/attribute_value_set.cpp @@ -94,7 +94,7 @@ private: }; //! A list of buckets - typedef boost::array< bucket, 1U << BOOST_LOG_HASH_TABLE_SIZE_LOG > buckets; + typedef boost::array< bucket, 1u << BOOST_LOG_HASH_TABLE_SIZE_LOG > buckets; //! Element disposer struct disposer @@ -317,7 +317,7 @@ private: //! The function returns a bucket for the specified element bucket& get_bucket(id_type id) { - return m_Buckets[id & (buckets::static_size - 1)]; + return m_Buckets[id & (buckets::static_size - 1u)]; } //! Attempts to find an element with the specified key in the bucket @@ -395,12 +395,6 @@ private: b.first = b.last = p; it = m_Nodes.end(); } - else if (where == b.first) - { - // The new element should become the first element of the bucket - it = m_Nodes.iterator_to(*where); - b.first = p; - } else if (where == b.last && key.id() > where->m_Value.first.id()) { // The new element should become the last element of the bucket @@ -408,6 +402,12 @@ private: ++it; b.last = p; } + else if (where == b.first) + { + // The new element should become the first element of the bucket + it = m_Nodes.iterator_to(*where); + b.first = p; + } else { // The new element should be within the bucket diff --git a/test/run/attr_attribute_value_set_ticket11190.cpp b/test/run/attr_attribute_value_set_ticket11190.cpp new file mode 100644 index 0000000..d5a0388 --- /dev/null +++ b/test/run/attr_attribute_value_set_ticket11190.cpp @@ -0,0 +1,60 @@ +/* + * 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 attr_attribute_value_set_ticket11190.cpp + * \author Andrey Semashev + * \date 25.04.2015 + * + * \brief This header contains a test for the fix for https://svn.boost.org/trac/boost/ticket/11190. + */ + +#define BOOST_TEST_MODULE attr_attribute_value_set_ticket11190 + +#include +#include +#include +#include +#include +#include +#include + +// The test checks that insertion does not invalidate existing elements in the container +BOOST_AUTO_TEST_CASE(ticket11190) +{ + boost::log::attribute_set set, dummy; + + unsigned int i = 0; + while (i < 100) + { + std::ostringstream strm; + strm << "Attr" << i; + boost::log::attribute_name name = strm.str(); + + std::pair< boost::log::attribute_set::iterator, bool > res = set.insert(name, boost::log::attributes::make_constant(5)); + ++i; + + BOOST_CHECK(res.second); // check that insertion succeeded + // check that lookup works + boost::log::attribute_set::iterator find_result = set.find(name); + BOOST_CHECK(find_result != set.end()); + BOOST_CHECK(find_result == res.first); + } + + boost::log::attribute_value_set vset(set, dummy, dummy); + BOOST_CHECK_EQUAL(vset.size(), set.size()); + + // Check that all inserted elements are findable + unsigned int j = 0; + for (boost::log::attribute_value_set::const_iterator it = vset.begin(), end = vset.end(); it != end; ++it, ++j) + { + boost::log::attribute_name key = it->first; + BOOST_CHECK(vset.find(key) != vset.end()); + } + + // Check that vset.size() is valid + BOOST_CHECK_EQUAL(j, i); +} From 83026646a2e301659061fbd3a95bb028a187f11f Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 25 Apr 2015 22:55:13 +0300 Subject: [PATCH 19/27] Updated changelog. --- doc/changelog.qbk | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/changelog.qbk b/doc/changelog.qbk index 3c47c44..cb44baf 100644 --- a/doc/changelog.qbk +++ b/doc/changelog.qbk @@ -22,6 +22,10 @@ * `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`. +[*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:] From bdf86442e5437ffc70b0a738916f715b0e1270c6 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Mon, 1 Jun 2015 00:10:57 +0300 Subject: [PATCH 20/27] Fixed operator<< for lvalue strings where character conversion is needed. --- .../boost/log/utility/formatting_ostream.hpp | 67 +++++++- test/run/util_formatting_ostream.cpp | 151 ++++++++++++++++-- 2 files changed, 205 insertions(+), 13 deletions(-) diff --git a/include/boost/log/utility/formatting_ostream.hpp b/include/boost/log/utility/formatting_ostream.hpp index 13f367f..88b85f8 100644 --- a/include/boost/log/utility/formatting_ostream.hpp +++ b/include/boost/log/utility/formatting_ostream.hpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -26,7 +27,6 @@ #include #include #include -#include #include #ifdef BOOST_HAS_PRAGMA_ONCE @@ -530,6 +530,71 @@ public: return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size())); } + template< typename OtherCharT, typename OtherTraitsT, typename OtherAllocatorT > + friend typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type + operator<< (basic_formatting_ostream& strm, std::basic_string< OtherCharT, OtherTraitsT, OtherAllocatorT >& str) + { + return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size())); + } + + template< typename OtherCharT, typename OtherTraitsT > + friend typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type + operator<< (basic_formatting_ostream& strm, basic_string_literal< OtherCharT, OtherTraitsT >& str) + { + return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size())); + } + + template< typename OtherCharT, typename OtherTraitsT > + friend typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type + operator<< (basic_formatting_ostream& strm, basic_string_ref< OtherCharT, OtherTraitsT >& str) + { + return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size())); + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template< typename OtherCharT, typename OtherTraitsT, typename OtherAllocatorT > + friend typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type + operator<< (basic_formatting_ostream&& strm, std::basic_string< OtherCharT, OtherTraitsT, OtherAllocatorT > const& str) + { + return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size())); + } + + template< typename OtherCharT, typename OtherTraitsT > + friend typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type + operator<< (basic_formatting_ostream&& strm, basic_string_literal< OtherCharT, OtherTraitsT > const& str) + { + return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size())); + } + + template< typename OtherCharT, typename OtherTraitsT > + friend typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type + operator<< (basic_formatting_ostream&& strm, basic_string_ref< OtherCharT, OtherTraitsT > const& str) + { + return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size())); + } + + template< typename OtherCharT, typename OtherTraitsT, typename OtherAllocatorT > + friend typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type + operator<< (basic_formatting_ostream&& strm, std::basic_string< OtherCharT, OtherTraitsT, OtherAllocatorT >& str) + { + return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size())); + } + + template< typename OtherCharT, typename OtherTraitsT > + friend typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type + operator<< (basic_formatting_ostream&& strm, basic_string_literal< OtherCharT, OtherTraitsT >& str) + { + return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size())); + } + + template< typename OtherCharT, typename OtherTraitsT > + friend typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type + operator<< (basic_formatting_ostream&& strm, basic_string_ref< OtherCharT, OtherTraitsT >& str) + { + return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size())); + } +#endif + private: void init_stream() { diff --git a/test/run/util_formatting_ostream.cpp b/test/run/util_formatting_ostream.cpp index 59cc6c9..dcd1fa5 100644 --- a/test/run/util_formatting_ostream.cpp +++ b/test/run/util_formatting_ostream.cpp @@ -18,7 +18,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -121,6 +123,20 @@ struct test_impl BOOST_CHECK(equal_strings(strm_fmt.str(), strm_correct.str())); } } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template< typename StringT > + static void rvalue_stream() + { + string_type str_fmt; + formatting_ostream_type(str_fmt) << strings::abc() << std::setw(8) << (StringT)strings::abcd() << strings::ABC() << std::flush; + + ostream_type strm_correct; + strm_correct << strings::abc() << std::setw(8) << (StringT)strings::abcd() << strings::ABC(); + + BOOST_CHECK(equal_strings(str_fmt, strm_correct.str())); + } +#endif }; } // namespace @@ -152,6 +168,67 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(alignment, CharT, char_types) test::BOOST_NESTED_TEMPLATE alignment< boost::basic_string_ref< CharT > >(); } +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +// Test support for rvalue stream objects +BOOST_AUTO_TEST_CASE_TEMPLATE(rvalue_stream, CharT, char_types) +{ + typedef test_impl< CharT > test; + test::BOOST_NESTED_TEMPLATE rvalue_stream< const CharT* >(); + test::BOOST_NESTED_TEMPLATE rvalue_stream< typename test::string_type >(); + test::BOOST_NESTED_TEMPLATE rvalue_stream< boost::basic_string_ref< CharT > >(); +} +#endif + +namespace my_namespace { + +class A {}; +template< typename CharT, typename TraitsT > +inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, A const&) +{ + strm << "A"; + return strm; +} + +class B {}; +template< typename CharT, typename TraitsT > +inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, B&) +{ + strm << "B"; + return strm; +} + +class C {}; +template< typename CharT, typename TraitsT > +inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, C const&) +{ + strm << "C"; + return strm; +} + +} // namespace my_namespace + +// Test operator forwarding +BOOST_AUTO_TEST_CASE_TEMPLATE(operator_forwarding, CharT, char_types) +{ + typedef CharT char_type; + typedef std::basic_string< char_type > string_type; + typedef std::basic_ostringstream< char_type > ostream_type; + typedef logging::basic_formatting_ostream< char_type > formatting_ostream_type; + + string_type str_fmt; + formatting_ostream_type strm_fmt(str_fmt); + + const my_namespace::A a; // const lvalue + my_namespace::B b; // lvalue + strm_fmt << a << b << my_namespace::C(); // rvalue + strm_fmt.flush(); + + ostream_type strm_correct; + strm_correct << a << b << my_namespace::C(); + + BOOST_CHECK(equal_strings(strm_fmt.str(), strm_correct.str())); +} + #if defined(BOOST_LOG_USE_CHAR) && defined(BOOST_LOG_USE_WCHAR_T) namespace { @@ -172,13 +249,38 @@ void test_narrowing_code_conversion() { std::locale loc(std::locale::classic(), new utf8_codecvt_facet()); - std::string str_fmt; - logging::formatting_ostream strm_fmt(str_fmt); - strm_fmt.imbue(loc); - strm_fmt << (StringT)wide_chars; - strm_fmt.flush(); + // Test rvalues + { + std::string str_fmt; + logging::formatting_ostream strm_fmt(str_fmt); + strm_fmt.imbue(loc); + strm_fmt << (StringT)wide_chars; + strm_fmt.flush(); - BOOST_CHECK(equal_strings(str_fmt, std::string(narrow_chars))); + BOOST_CHECK(equal_strings(str_fmt, std::string(narrow_chars))); + } + // Test lvalues + { + std::string str_fmt; + logging::formatting_ostream strm_fmt(str_fmt); + strm_fmt.imbue(loc); + StringT wstr = StringT(wide_chars); + strm_fmt << wstr; + strm_fmt.flush(); + + BOOST_CHECK(equal_strings(str_fmt, std::string(narrow_chars))); + } + // Test const lvalues + { + std::string str_fmt; + logging::formatting_ostream strm_fmt(str_fmt); + strm_fmt.imbue(loc); + const StringT wstr = StringT(wide_chars); + strm_fmt << wstr; + strm_fmt.flush(); + + BOOST_CHECK(equal_strings(str_fmt, std::string(narrow_chars))); + } } template< typename StringT > @@ -186,13 +288,38 @@ void test_widening_code_conversion() { std::locale loc(std::locale::classic(), new utf8_codecvt_facet()); - std::wstring str_fmt; - logging::wformatting_ostream strm_fmt(str_fmt); - strm_fmt.imbue(loc); - strm_fmt << (StringT)narrow_chars; - strm_fmt.flush(); + // Test rvalues + { + std::wstring str_fmt; + logging::wformatting_ostream strm_fmt(str_fmt); + strm_fmt.imbue(loc); + strm_fmt << (StringT)narrow_chars; + strm_fmt.flush(); - BOOST_CHECK(equal_strings(str_fmt, std::wstring(wide_chars))); + BOOST_CHECK(equal_strings(str_fmt, std::wstring(wide_chars))); + } + // Test lvalues + { + std::wstring str_fmt; + logging::wformatting_ostream strm_fmt(str_fmt); + strm_fmt.imbue(loc); + StringT str = StringT(narrow_chars); + strm_fmt << str; + strm_fmt.flush(); + + BOOST_CHECK(equal_strings(str_fmt, std::wstring(wide_chars))); + } + // Test const lvalues + { + std::wstring str_fmt; + logging::wformatting_ostream strm_fmt(str_fmt); + strm_fmt.imbue(loc); + const StringT str = StringT(narrow_chars); + strm_fmt << str; + strm_fmt.flush(); + + BOOST_CHECK(equal_strings(str_fmt, std::wstring(wide_chars))); + } } } // namespace From b2a3106a2170f0862b2eb4c97386444376c5dcfa Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Mon, 1 Jun 2015 16:00:08 +0300 Subject: [PATCH 21/27] Trying to work around compilation failure with clang. --- test/run/util_formatting_ostream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/run/util_formatting_ostream.cpp b/test/run/util_formatting_ostream.cpp index dcd1fa5..394a37b 100644 --- a/test/run/util_formatting_ostream.cpp +++ b/test/run/util_formatting_ostream.cpp @@ -218,7 +218,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(operator_forwarding, CharT, char_types) string_type str_fmt; formatting_ostream_type strm_fmt(str_fmt); - const my_namespace::A a; // const lvalue + const my_namespace::A a = my_namespace::A(); // const lvalue my_namespace::B b; // lvalue strm_fmt << a << b << my_namespace::C(); // rvalue strm_fmt.flush(); From 3d5d5e31d09a776374c2d38371ab93e554704bb7 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 5 Jul 2015 16:25:22 +0300 Subject: [PATCH 22/27] Added tests for the to_log manipulator. Made generic operator<< for the formatting stream less attractive for the compiler. --- include/boost/log/detail/is_ostream.hpp | 57 ++++++++ .../boost/log/utility/formatting_ostream.hpp | 35 +++-- .../boost/log/utility/manipulators/to_log.hpp | 24 ++-- test/run/form_to_log_manip.cpp | 99 +++++++++++++ test/run/util_manip_to_log.cpp | 134 ++++++++++++++++++ 5 files changed, 320 insertions(+), 29 deletions(-) create mode 100644 include/boost/log/detail/is_ostream.hpp create mode 100644 test/run/form_to_log_manip.cpp create mode 100644 test/run/util_manip_to_log.cpp diff --git a/include/boost/log/detail/is_ostream.hpp b/include/boost/log/detail/is_ostream.hpp new file mode 100644 index 0000000..2131bae --- /dev/null +++ b/include/boost/log/detail/is_ostream.hpp @@ -0,0 +1,57 @@ +/* + * 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 is_ostream.hpp + * \author Andrey Semashev + * \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_IS_OSTREAM_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_IS_OSTREAM_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +template< typename T > +struct is_ostream +{ + 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 + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include + +#endif // BOOST_LOG_DETAIL_IS_OSTREAM_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/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/test/run/form_to_log_manip.cpp b/test/run/form_to_log_manip.cpp new file mode 100644 index 0000000..727c757 --- /dev/null +++ b/test/run/form_to_log_manip.cpp @@ -0,0 +1,99 @@ +/* + * 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; + typedef test_data< CharT > data; + + 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(); +} From 7dea4539d6a3f08511416ef975a5ba8b0e5863f0 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 5 Jul 2015 18:52:29 +0300 Subject: [PATCH 23/27] Reverted the TLS config enforcement for Boost.ASIO. Partially reverts 89474f4a8097d419493ebe8915db363e668fef5c and a9738b1249021fe1aae5c28160a07ad4d8f81e99. During the discussion on the ML, there was opinion that Boost.Log should not influence other libraries' configuration. This can cause ODR violations and cause surprises to the users. The long term solution will be removal of Boost.ASIO and re-implementing network abstraction layer. For now users are required to configure each library separately. This requirement has been documented. --- doc/changelog.qbk | 1 - doc/log.qbk | 2 ++ src/asio_config.hpp | 41 -------------------------------------- src/init_from_settings.cpp | 1 - src/syslog_backend.cpp | 1 - 5 files changed, 2 insertions(+), 44 deletions(-) delete mode 100644 src/asio_config.hpp diff --git a/doc/changelog.qbk b/doc/changelog.qbk index cb44baf..dbedb7e 100644 --- a/doc/changelog.qbk +++ b/doc/changelog.qbk @@ -13,7 +13,6 @@ [*General changes:] -* The library now enforces compiler-based TLS configuration of __boost_asio__ according to Boost.Log configuration. Unless compiler-based TLS is enabled by defining `BOOST_LOG_USE_COMPILER_TLS` at Boost.Log compilation stage, compiler-based TLS in __boost_asio__ is disabled by defining `BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION`. On some systems this may cause ODR violation issues, if user's code uses __boost_asio__ with a different configuration (by default compiler-based TLS is enabled in __boost_asio__). It is *strongly advised* to align Boost.Log and __boost_asio__ configuration (either enable or disable compiler-based TLS for both libraries). * 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`. diff --git a/doc/log.qbk b/doc/log.qbk index be4da18..4cd8da1 100644 --- a/doc/log.qbk +++ b/doc/log.qbk @@ -246,6 +246,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/src/asio_config.hpp b/src/asio_config.hpp deleted file mode 100644 index 45fa736..0000000 --- a/src/asio_config.hpp +++ /dev/null @@ -1,41 +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 asio_config.hpp - * \author Andrey Semashev - * \date 24.03.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. - */ - -#ifndef BOOST_LOG_ASIO_CONFIG_HPP_INCLUDED_ -#define BOOST_LOG_ASIO_CONFIG_HPP_INCLUDED_ - -#include - -#if !defined(BOOST_LOG_NO_ASIO) - -#if defined(BOOST_LOG_DLL) -// Make sure we have our local copy of Boost.ASIO with our configuration. This is to avoid possible ABI clashes with user's code, -// if it's compiled with other macros defined. For shared library build we also limit symbol visibility, where possible (see build/Jamfile.v2). -// Alas, for static library build there is no such protection, so user's config has to match the one of Boost.Log. -#undef BOOST_ASIO_SEPARATE_COMPILATION -#undef BOOST_ASIO_DYN_LINK -#define BOOST_ASIO_HEADER_ONLY 1 -#endif - -// Unless explicitly enabled, disable compiler-based TLS in Boost.ASIO. First, this ensures that the built Boost.Log binaries -// actually don't use compiler-based TLS unless allowed. Second, this is a temporary workaround for dynamic linking issue with -// Clang on Android described here: https://tracker.crystax.net/issues/912 (linked binaries refer to the missing __tls_get_addr symbol). -#if !defined(BOOST_LOG_USE_COMPILER_TLS) && !defined(BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION) -#define BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION -#endif - -#endif // !defined(BOOST_LOG_NO_ASIO) - -#endif // BOOST_LOG_ASIO_CONFIG_HPP_INCLUDED_ diff --git a/src/init_from_settings.cpp b/src/init_from_settings.cpp index 4b8dfbc..fdd5457 100644 --- a/src/init_from_settings.cpp +++ b/src/init_from_settings.cpp @@ -62,7 +62,6 @@ #include #include #if !defined(BOOST_LOG_NO_ASIO) -#include "asio_config.hpp" #include #endif #if !defined(BOOST_LOG_NO_THREADS) diff --git a/src/syslog_backend.cpp b/src/syslog_backend.cpp index 78aaedc..a866a1e 100644 --- a/src/syslog_backend.cpp +++ b/src/syslog_backend.cpp @@ -27,7 +27,6 @@ #include #include #if !defined(BOOST_LOG_NO_ASIO) -#include "asio_config.hpp" #include #include #include From c98b1f459add14d5ce3e9e63e2469064601d7f71 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 5 Jul 2015 19:06:18 +0300 Subject: [PATCH 24/27] Fixes #11446. Add support for OpenBSD (clock_gettime). --- doc/changelog.qbk | 1 + src/timestamp.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/changelog.qbk b/doc/changelog.qbk index dbedb7e..466130b 100644 --- a/doc/changelog.qbk +++ b/doc/changelog.qbk @@ -20,6 +20,7 @@ * `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]) [*Bug fixes:] 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 { From 30e7f036316d20285f8cecea36ca6a8ac0190125 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 5 Jul 2015 22:00:03 +0300 Subject: [PATCH 25/27] Fixes #11398. Improved the event synchronization primitive. The updated implementation relies on Boost.Atomic for atomic operations which provides better portability. On Linux the implementation uses futexes directly, which should improve performance slightly. The event implementation choice should be more stable across different compiler versions because of these changes. --- doc/changelog.qbk | 1 + doc/log.qbk | 1 + include/boost/log/detail/event.hpp | 44 +++++++++++--- src/event.cpp | 95 ++++++++++++++++++++++++++---- 4 files changed, 123 insertions(+), 18 deletions(-) diff --git a/doc/changelog.qbk b/doc/changelog.qbk index 466130b..0359443 100644 --- a/doc/changelog.qbk +++ b/doc/changelog.qbk @@ -21,6 +21,7 @@ * `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:] diff --git a/doc/log.qbk b/doc/log.qbk index 4cd8da1..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]] 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/src/event.cpp b/src/event.cpp index ce2a9bb..bba7321 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,69 @@ 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 != EINTR) + { + if (err == EWOULDBLOCK) + { + // Another thread has set the event before sleeping + break; + } + else + { + 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 +152,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 +167,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")); } From 2c26ec929ae62d74089360038e3dc77f2f98faf2 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 5 Jul 2015 22:18:15 +0300 Subject: [PATCH 26/27] Minor code simplification. --- src/event.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/event.cpp b/src/event.cpp index bba7321..0c41d40 100644 --- a/src/event.cpp +++ b/src/event.cpp @@ -97,18 +97,15 @@ BOOST_LOG_API void futex_based_event::wait() } const int err = errno; - if (err != EINTR) + if (err == EWOULDBLOCK) { - if (err == EWOULDBLOCK) - { - // Another thread has set the event before sleeping - break; - } - else - { - BOOST_THROW_EXCEPTION(system::system_error( - err, system::system_category(), "Failed to block on the futex")); - } + // 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")); } } From 12fb58fd54b4d9357caf83474d0f2d740bd47778 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Mon, 6 Jul 2015 11:59:58 +0300 Subject: [PATCH 27/27] Removed unused typedef. --- test/run/form_to_log_manip.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/run/form_to_log_manip.cpp b/test/run/form_to_log_manip.cpp index 727c757..a7f83d3 100644 --- a/test/run/form_to_log_manip.cpp +++ b/test/run/form_to_log_manip.cpp @@ -76,7 +76,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(operator_overrides, CharT, char_types) 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< my_class > attr1(my_class(77)); attrs::constant< std::string > attr2("Hello");