From f35fd5eecfc11055a75d30bb930d6a31d53de06e Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Mon, 16 Sep 2013 18:58:52 +0000 Subject: [PATCH] Merged changes from trunk. [SVN r85713] --- doc/changelog.qbk | 1 + doc/expressions.qbk | 6 +++--- include/boost/log/detail/thread_id.hpp | 2 +- src/core.cpp | 5 +++++ src/default_sink.cpp | 25 +++++++++++++++++++++---- src/thread_id.cpp | 23 ++++++++++++++++++++++- 6 files changed, 53 insertions(+), 9 deletions(-) diff --git a/doc/changelog.qbk b/doc/changelog.qbk index cb1391f..06c886f 100644 --- a/doc/changelog.qbk +++ b/doc/changelog.qbk @@ -23,6 +23,7 @@ * Fixed [link log.detailed.attributes.timer `timer`] attribute generating incorrect time readings on Windows on heavy thread contention when `QueryPerformanceCounter` API was used. * Fixed a bug in the filter parser that prevented using parsed filters with some attributes. For example, parsed filters didn't work with a string-typed attribute value, if the value was compared to a numeric operand. +* Fixed thread id formatting discrepancies between the default sink and formatters. * Closed tickets: [ticket 8815], [ticket 8819], [ticket 8915], [ticket 8917]. [heading 2.1, Boost 1.54] diff --git a/doc/expressions.qbk b/doc/expressions.qbk index e223d2c..be0f03d 100644 --- a/doc/expressions.qbk +++ b/doc/expressions.qbk @@ -388,7 +388,7 @@ Here are a few usage examples: sink->set_formatter ( expr::stream - << expr::named_scope( + << expr::format_named_scope( "Scopes", keywords::format = "%n", keywords::iteration = expr::reverse, @@ -400,7 +400,7 @@ Here are a few usage examples: sink->set_formatter ( expr::stream - << expr::named_scope( + << expr::format_named_scope( "Scopes", keywords::format = "%n", keywords::iteration = expr::forward, @@ -412,7 +412,7 @@ Here are a few usage examples: sink->set_formatter ( expr::stream - << expr::named_scope( + << expr::format_named_scope( "Scopes", keywords::format = "%n", keywords::iteration = expr::reverse, diff --git a/include/boost/log/detail/thread_id.hpp b/include/boost/log/detail/thread_id.hpp index db94f3e..0a073d3 100644 --- a/include/boost/log/detail/thread_id.hpp +++ b/include/boost/log/detail/thread_id.hpp @@ -48,7 +48,7 @@ namespace this_thread { //! The function returns current thread identifier BOOST_LOG_API thread::id const& get_id(); -} // namespace this_process +} // namespace this_thread template< typename CharT, typename TraitsT > BOOST_LOG_API std::basic_ostream< CharT, TraitsT >& diff --git a/src/core.cpp b/src/core.cpp index c4c5cc4..65c989d 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -251,6 +252,10 @@ public: m_default_sink(boost::make_shared< sinks::aux::default_sink >()), m_enabled(true) { + // Workaround for https://svn.boost.org/trac/boost/ticket/8642 + // Initialize global locale in Boost.Filesystem early, so that it is still available while the logging core is destroyed. + // Note that this only helps in the simplest case, when the core is not kept alive by a shared_ptr saved by user. + filesystem::path::codecvt(); } //! Invokes sink-specific filter and adds the sink to the record if the filter passes the log record diff --git a/src/default_sink.cpp b/src/default_sink.cpp index 687dd14..ca19457 100644 --- a/src/default_sink.cpp +++ b/src/default_sink.cpp @@ -31,6 +31,13 @@ namespace boost { BOOST_LOG_OPEN_NAMESPACE +namespace aux { + +// Defined in thread_id.cpp +void format_thread_id(char* buf, std::size_t size, thread::id tid); + +} // namespace aux + namespace sinks { namespace aux { @@ -111,11 +118,16 @@ struct message_printer result_type operator() (std::string const& msg) const { +#if !defined(BOOST_LOG_NO_THREADS) + char thread_id_buf[64]; + boost::log::aux::format_thread_id(thread_id_buf, sizeof(thread_id_buf), boost::log::aux::this_thread::get_id()); +#endif + const decomposed_time_point now = date_time::microsec_clock< decomposed_time_point >::local_time(); std::printf("[%04u-%02u-%02u %02u:%02u:%02u.%06u] " #if !defined(BOOST_LOG_NO_THREADS) - "[0x%08x] " + "[%s] " #endif "%s %s\n", static_cast< unsigned int >(now.date.year), @@ -126,7 +138,7 @@ struct message_printer static_cast< unsigned int >(now.time.seconds), static_cast< unsigned int >(now.time.useconds), #if !defined(BOOST_LOG_NO_THREADS) - static_cast< unsigned int >(boost::log::aux::this_thread::get_id().native_id()), + thread_id_buf, #endif severity_level_to_string(m_level), msg.c_str()); @@ -138,11 +150,16 @@ struct message_printer result_type operator() (std::wstring const& msg) const { +#if !defined(BOOST_LOG_NO_THREADS) + char thread_id_buf[64]; + boost::log::aux::format_thread_id(thread_id_buf, sizeof(thread_id_buf), boost::log::aux::this_thread::get_id()); +#endif + const decomposed_time_point now = date_time::microsec_clock< decomposed_time_point >::local_time(); std::printf("[%04u-%02u-%02u %02u:%02u:%02u.%06u] " #if !defined(BOOST_LOG_NO_THREADS) - "[0x%08x] " + "[%s] " #endif "%s %ls\n", static_cast< unsigned int >(now.date.year), @@ -153,7 +170,7 @@ struct message_printer static_cast< unsigned int >(now.time.seconds), static_cast< unsigned int >(now.time.useconds), #if !defined(BOOST_LOG_NO_THREADS) - static_cast< unsigned int >(boost::log::aux::this_thread::get_id().native_id()), + thread_id_buf, #endif severity_level_to_string(m_level), msg.c_str()); diff --git a/src/thread_id.cpp b/src/thread_id.cpp index baee88e..5052413 100644 --- a/src/thread_id.cpp +++ b/src/thread_id.cpp @@ -226,6 +226,27 @@ BOOST_LOG_API thread::id const& get_id() } // namespace this_thread +// Used in default_sink.cpp +void format_thread_id(char* buf, std::size_t size, thread::id tid) +{ + static const char char_table[] = "0123456789abcdef"; + + // Input buffer is assumed to be always larger than 2 chars + *buf++ = '0'; + *buf++ = 'x'; + + size -= 3; // reserve space for the terminating 0 + thread::id::native_type id = tid.native_id(); + unsigned int i = 0; + const unsigned int n = (size > (tid_size * 2u)) ? static_cast< unsigned int >(tid_size * 2u) : static_cast< unsigned int >(size); + for (unsigned int shift = n * 4u; i < n; ++i, shift -= 4u) + { + buf[i] = char_table[(id >> shift) & 15u]; + } + + buf[i] = '\0'; +} + template< typename CharT, typename TraitsT > std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, thread::id const& tid) @@ -233,8 +254,8 @@ operator<< (std::basic_ostream< CharT, TraitsT >& strm, thread::id const& tid) if (strm.good()) { io::ios_flags_saver flags_saver(strm, (strm.flags() & std::ios_base::uppercase) | std::ios_base::hex | std::ios_base::internal | std::ios_base::showbase); - io::ios_width_saver width_saver(strm, static_cast< std::streamsize >(tid_size * 2 + 2)); // 2 chars per byte + 2 chars for the leading 0x io::basic_ios_fill_saver< CharT, TraitsT > fill_saver(strm, static_cast< CharT >('0')); + strm.width(static_cast< std::streamsize >(tid_size * 2 + 2)); // 2 chars per byte + 2 chars for the leading 0x strm << static_cast< uint_t< tid_size * 8 >::least >(tid.native_id()); }