summaryrefslogtreecommitdiff
path: root/boost/log
diff options
context:
space:
mode:
Diffstat (limited to 'boost/log')
-rw-r--r--boost/log/attributes/attribute_value_impl.hpp2
-rw-r--r--boost/log/attributes/constant.hpp2
-rw-r--r--boost/log/attributes/mutable_constant.hpp2
-rw-r--r--boost/log/attributes/scoped_attribute.hpp4
-rw-r--r--boost/log/attributes/value_extraction.hpp6
-rw-r--r--boost/log/core/record.hpp6
-rw-r--r--boost/log/core/record_view.hpp16
-rw-r--r--boost/log/detail/adaptive_mutex.hpp19
-rw-r--r--boost/log/detail/attachable_sstream_buf.hpp236
-rw-r--r--boost/log/detail/c_str.hpp55
-rw-r--r--boost/log/detail/code_conversion.hpp83
-rw-r--r--boost/log/detail/config.hpp18
-rw-r--r--boost/log/detail/decomposed_time.hpp39
-rw-r--r--boost/log/detail/enqueued_record.hpp2
-rw-r--r--boost/log/detail/format.hpp58
-rw-r--r--boost/log/detail/light_function.hpp16
-rw-r--r--boost/log/detail/light_function_pp.hpp12
-rw-r--r--boost/log/detail/locks.hpp31
-rw-r--r--boost/log/detail/parameter_tools.hpp43
-rw-r--r--boost/log/detail/pause.hpp61
-rw-r--r--boost/log/detail/sfinae_tools.hpp44
-rw-r--r--boost/log/detail/sink_init_helpers.hpp10
-rw-r--r--boost/log/detail/snprintf.hpp29
-rw-r--r--boost/log/detail/tagged_integer.hpp24
-rw-r--r--boost/log/detail/threadsafe_queue.hpp2
-rw-r--r--boost/log/exceptions.hpp102
-rw-r--r--boost/log/expressions/attr.hpp2
-rw-r--r--boost/log/expressions/filter.hpp12
-rw-r--r--boost/log/expressions/formatter.hpp10
-rw-r--r--boost/log/expressions/formatters.hpp1
-rw-r--r--boost/log/expressions/formatters/char_decorator.hpp20
-rw-r--r--boost/log/expressions/formatters/date_time.hpp8
-rw-r--r--boost/log/expressions/formatters/format.hpp2
-rw-r--r--boost/log/expressions/formatters/if.hpp4
-rw-r--r--boost/log/expressions/formatters/max_size_decorator.hpp561
-rw-r--r--boost/log/expressions/formatters/named_scope.hpp8
-rw-r--r--boost/log/expressions/formatters/wrap_formatter.hpp10
-rw-r--r--boost/log/expressions/predicates/channel_severity_filter.hpp2
-rw-r--r--boost/log/keywords/block_size.hpp40
-rw-r--r--boost/log/keywords/capacity.hpp40
-rw-r--r--boost/log/keywords/name.hpp40
-rw-r--r--boost/log/keywords/overflow_policy.hpp40
-rw-r--r--boost/log/keywords/permissions.hpp40
-rw-r--r--boost/log/sinks.hpp1
-rw-r--r--boost/log/sinks/async_frontend.hpp50
-rw-r--r--boost/log/sinks/attribute_mapping.hpp2
-rw-r--r--boost/log/sinks/basic_sink_frontend.hpp41
-rw-r--r--boost/log/sinks/sync_frontend.hpp25
-rw-r--r--boost/log/sinks/text_ipc_message_queue_backend.hpp172
-rw-r--r--boost/log/sinks/text_multifile_backend.hpp3
-rw-r--r--boost/log/sinks/unlocked_frontend.hpp25
-rw-r--r--boost/log/sources/basic_logger.hpp4
-rw-r--r--boost/log/sources/channel_feature.hpp2
-rw-r--r--boost/log/sources/exception_handler_feature.hpp2
-rw-r--r--boost/log/sources/global_logger_storage.hpp19
-rw-r--r--boost/log/sources/record_ostream.hpp4
-rw-r--r--boost/log/sources/severity_feature.hpp2
-rw-r--r--boost/log/support/date_time.hpp2
-rw-r--r--boost/log/support/exception.hpp12
-rw-r--r--boost/log/support/spirit_classic.hpp2
-rw-r--r--boost/log/support/spirit_qi.hpp4
-rw-r--r--boost/log/utility/exception_handler.hpp10
-rw-r--r--boost/log/utility/formatting_ostream.hpp49
-rw-r--r--boost/log/utility/ipc/object_name.hpp271
-rw-r--r--boost/log/utility/ipc/reliable_message_queue.hpp776
-rw-r--r--boost/log/utility/manipulators/dump.hpp4
-rw-r--r--boost/log/utility/open_mode.hpp46
-rw-r--r--boost/log/utility/permissions.hpp213
-rw-r--r--boost/log/utility/record_ordering.hpp6
-rw-r--r--boost/log/utility/setup/filter_parser.hpp6
-rw-r--r--boost/log/utility/setup/formatter_parser.hpp6
-rw-r--r--boost/log/utility/setup/from_settings.hpp10
-rw-r--r--boost/log/utility/setup/settings.hpp4
-rw-r--r--boost/log/utility/strictest_lock.hpp5
-rw-r--r--boost/log/utility/string_literal.hpp192
-rw-r--r--boost/log/utility/type_dispatch/static_type_dispatcher.hpp2
-rw-r--r--boost/log/utility/value_ref.hpp96
77 files changed, 3440 insertions, 390 deletions
diff --git a/boost/log/attributes/attribute_value_impl.hpp b/boost/log/attributes/attribute_value_impl.hpp
index b21091e58b..e18015bec3 100644
--- a/boost/log/attributes/attribute_value_impl.hpp
+++ b/boost/log/attributes/attribute_value_impl.hpp
@@ -17,7 +17,7 @@
#include <boost/type_index.hpp>
#include <boost/move/core.hpp>
-#include <boost/move/utility.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/attributes/attribute_value.hpp>
diff --git a/boost/log/attributes/constant.hpp b/boost/log/attributes/constant.hpp
index 1e9a036176..f10b0a7e5b 100644
--- a/boost/log/attributes/constant.hpp
+++ b/boost/log/attributes/constant.hpp
@@ -16,7 +16,7 @@
#define BOOST_LOG_ATTRIBUTES_CONSTANT_HPP_INCLUDED_
#include <boost/move/core.hpp>
-#include <boost/move/utility.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/embedded_string_type.hpp>
diff --git a/boost/log/attributes/mutable_constant.hpp b/boost/log/attributes/mutable_constant.hpp
index 52356b45de..6ff76ddc2c 100644
--- a/boost/log/attributes/mutable_constant.hpp
+++ b/boost/log/attributes/mutable_constant.hpp
@@ -19,7 +19,7 @@
#include <boost/smart_ptr/intrusive_ptr.hpp>
#include <boost/mpl/if.hpp>
#include <boost/move/core.hpp>
-#include <boost/move/utility.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/type_traits/is_void.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/locks.hpp>
diff --git a/boost/log/attributes/scoped_attribute.hpp b/boost/log/attributes/scoped_attribute.hpp
index bd0e52da7f..88dd218e4c 100644
--- a/boost/log/attributes/scoped_attribute.hpp
+++ b/boost/log/attributes/scoped_attribute.hpp
@@ -17,8 +17,8 @@
#include <utility>
#include <boost/move/core.hpp>
-#include <boost/move/utility.hpp>
-#include <boost/utility/addressof.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/core/addressof.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/core/core.hpp>
#include <boost/log/sources/basic_logger.hpp>
diff --git a/boost/log/attributes/value_extraction.hpp b/boost/log/attributes/value_extraction.hpp
index 7ec3f1d174..87fd1495e3 100644
--- a/boost/log/attributes/value_extraction.hpp
+++ b/boost/log/attributes/value_extraction.hpp
@@ -25,7 +25,7 @@
#include <boost/mpl/contains.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/type_traits/is_same.hpp>
-#include <boost/utility/enable_if.hpp>
+#include <boost/core/enable_if.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/exceptions.hpp>
#include <boost/log/core/record.hpp>
@@ -137,14 +137,14 @@ private:
//! The function unwraps \c value_ref, if possible
template< typename T, typename TagT >
-BOOST_FORCEINLINE typename enable_if< mpl::is_sequence< T >, value_ref< T, TagT > >::type
+BOOST_FORCEINLINE typename boost::enable_if_c< mpl::is_sequence< T >::value, value_ref< T, TagT > >::type
unwrap_value_ref(value_ref< T, TagT > const& r)
{
return r;
}
template< typename T, typename TagT >
-BOOST_FORCEINLINE typename disable_if< mpl::is_sequence< T >, T const& >::type
+BOOST_FORCEINLINE typename boost::disable_if_c< mpl::is_sequence< T >::value, T const& >::type
unwrap_value_ref(value_ref< T, TagT > const& r)
{
return r.get();
diff --git a/boost/log/core/record.hpp b/boost/log/core/record.hpp
index b58177c58a..b666214c61 100644
--- a/boost/log/core/record.hpp
+++ b/boost/log/core/record.hpp
@@ -55,6 +55,10 @@ private:
//! A pointer to the log record implementation
public_data* m_impl;
+private:
+ // A private constructor, accessible from core
+ BOOST_CONSTEXPR explicit record(public_data* impl) BOOST_NOEXCEPT : m_impl(impl) {}
+
#endif // BOOST_LOG_DOXYGEN_PASS
public:
@@ -63,7 +67,7 @@ public:
*
* \post <tt>!*this == true</tt>
*/
- record() : m_impl(NULL) {}
+ BOOST_CONSTEXPR record() BOOST_NOEXCEPT : m_impl(NULL) {}
/*!
* Move constructor. Source record contents unspecified after the operation.
diff --git a/boost/log/core/record_view.hpp b/boost/log/core/record_view.hpp
index 6fa7a63f98..515627aebd 100644
--- a/boost/log/core/record_view.hpp
+++ b/boost/log/core/record_view.hpp
@@ -17,6 +17,7 @@
#include <boost/smart_ptr/intrusive_ptr.hpp>
#include <boost/move/core.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/utility/explicit_operator_bool.hpp>
#include <boost/log/attributes/attribute_value_set.hpp>
@@ -72,10 +73,10 @@ private:
//! Attribute values view
attribute_value_set m_attribute_values;
- //! Constructor from the attribute sets
- explicit public_data(BOOST_RV_REF(attribute_value_set) values) :
+ //! Constructor from the attribute value set
+ explicit public_data(BOOST_RV_REF(attribute_value_set) values) BOOST_NOEXCEPT :
m_ref_counter(1),
- m_attribute_values(values)
+ m_attribute_values(boost::move(values))
{
}
@@ -98,7 +99,7 @@ private:
private:
// A private constructor, accessible from record
- explicit record_view(public_data* impl) : m_impl(impl, false) {}
+ explicit record_view(public_data* impl) BOOST_NOEXCEPT : m_impl(impl, false) {}
#endif // BOOST_LOG_DOXYGEN_PASS
@@ -108,7 +109,12 @@ public:
*
* \post <tt>!*this == true</tt>
*/
- BOOST_DEFAULTED_FUNCTION(record_view(), {})
+ BOOST_CONSTEXPR record_view() BOOST_NOEXCEPT
+#if !defined(BOOST_LOG_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS)
+ = default;
+#else
+ {}
+#endif
/*!
* Copy constructor
diff --git a/boost/log/detail/adaptive_mutex.hpp b/boost/log/detail/adaptive_mutex.hpp
index 25e7559e17..f9830effde 100644
--- a/boost/log/detail/adaptive_mutex.hpp
+++ b/boost/log/detail/adaptive_mutex.hpp
@@ -37,19 +37,11 @@
#if defined(BOOST_LOG_ADAPTIVE_MUTEX_USE_WINAPI)
+#include <boost/log/detail/pause.hpp>
#include <boost/detail/interlocked.hpp>
#include <boost/detail/winapi/thread.hpp>
#if defined(__INTEL_COMPILER) || defined(_MSC_VER)
-# if defined(_M_IX86)
-# define BOOST_LOG_PAUSE_OP __asm { pause }
-# elif defined(_M_AMD64)
-extern "C" void _mm_pause(void);
-# if defined(BOOST_MSVC)
-# pragma intrinsic(_mm_pause)
-# endif
-# define BOOST_LOG_PAUSE_OP _mm_pause()
-# endif
# if defined(__INTEL_COMPILER)
# define BOOST_LOG_COMPILER_BARRIER __memory_barrier()
# else
@@ -60,7 +52,6 @@ extern "C" void _ReadWriteBarrier(void);
# define BOOST_LOG_COMPILER_BARRIER _ReadWriteBarrier()
# endif
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
-# define BOOST_LOG_PAUSE_OP __asm__ __volatile__("pause;")
# define BOOST_LOG_COMPILER_BARRIER __asm__ __volatile__("" : : : "memory")
#endif
@@ -94,17 +85,17 @@ public:
void lock()
{
-#if defined(BOOST_LOG_PAUSE_OP)
+#if defined(BOOST_LOG_AUX_PAUSE)
unsigned int pause_count = initial_pause;
#endif
while (!try_lock())
{
-#if defined(BOOST_LOG_PAUSE_OP)
+#if defined(BOOST_LOG_AUX_PAUSE)
if (pause_count < max_pause)
{
for (unsigned int i = 0; i < pause_count; ++i)
{
- BOOST_LOG_PAUSE_OP;
+ BOOST_LOG_AUX_PAUSE;
}
pause_count += pause_count;
}
@@ -136,7 +127,7 @@ public:
BOOST_DELETED_FUNCTION(adaptive_mutex& operator= (adaptive_mutex const&))
};
-#undef BOOST_LOG_PAUSE_OP
+#undef BOOST_LOG_AUX_PAUSE
#undef BOOST_LOG_COMPILER_BARRIER
} // namespace aux
diff --git a/boost/log/detail/attachable_sstream_buf.hpp b/boost/log/detail/attachable_sstream_buf.hpp
index ae536a4316..3608bb1083 100644
--- a/boost/log/detail/attachable_sstream_buf.hpp
+++ b/boost/log/detail/attachable_sstream_buf.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright Andrey Semashev 2007 - 2015.
+ * Copyright Andrey Semashev 2007 - 2016.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
@@ -16,11 +16,14 @@
#ifndef BOOST_LOG_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_
#define BOOST_LOG_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_
+#include <cstddef>
#include <memory>
+#include <locale>
#include <string>
#include <streambuf>
#include <boost/assert.hpp>
-#include <boost/utility/addressof.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/locale/utf.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/header.hpp>
@@ -58,66 +61,196 @@ public:
typedef typename base_type::traits_type traits_type;
//! String type
typedef std::basic_string< char_type, traits_type, AllocatorT > string_type;
+ //! Size type
+ typedef typename string_type::size_type size_type;
//! Int type
typedef typename base_type::int_type int_type;
+ struct storage_state
+ {
+ //! A reference to the string that will be filled
+ string_type* storage;
+ //! Max size of the storage, in characters
+ size_type max_size;
+ //! Indicates that storage overflow happened
+ bool overflow;
+
+ BOOST_CONSTEXPR storage_state() BOOST_NOEXCEPT : storage(NULL), max_size(0u), overflow(false)
+ {
+ }
+ };
+
private:
- //! A reference to the string that will be filled
- string_type* m_Storage;
+ //! Buffer storage state
+ storage_state m_storage_state;
//! A buffer used to temporarily store output
- char_type m_Buffer[buffer_size];
+ char_type m_buffer[buffer_size];
public:
//! Constructor
- explicit basic_ostringstreambuf() : m_Storage(0)
+ basic_ostringstreambuf() BOOST_NOEXCEPT
{
- base_type::setp(m_Buffer, m_Buffer + (sizeof(m_Buffer) / sizeof(*m_Buffer)));
+ base_type::setp(m_buffer, m_buffer + (sizeof(m_buffer) / sizeof(*m_buffer)));
}
//! Constructor
- explicit basic_ostringstreambuf(string_type& storage) : m_Storage(boost::addressof(storage))
+ explicit basic_ostringstreambuf(string_type& storage) BOOST_NOEXCEPT
{
- base_type::setp(m_Buffer, m_Buffer + (sizeof(m_Buffer) / sizeof(*m_Buffer)));
+ base_type::setp(m_buffer, m_buffer + (sizeof(m_buffer) / sizeof(*m_buffer)));
+ attach(storage);
}
- //! Clears the buffer to the initial state
- void clear()
- {
- char_type* pBase = this->pbase();
- char_type* pPtr = this->pptr();
- if (pBase != pPtr)
- this->pbump(static_cast< int >(pBase - pPtr));
- }
+ storage_state const& get_storage_state() const BOOST_NOEXCEPT { return m_storage_state; }
+ void set_storage_state(storage_state const& st) BOOST_NOEXCEPT { m_storage_state = st; }
//! Detaches the buffer from the string
void detach()
{
- if (m_Storage)
+ if (m_storage_state.storage)
{
this_type::sync();
- m_Storage = 0;
+ m_storage_state.storage = NULL;
+ m_storage_state.max_size = 0u;
+ m_storage_state.overflow = false;
}
}
//! Attaches the buffer to another string
void attach(string_type& storage)
{
+ attach(storage, storage.max_size());
+ }
+
+ //! Attaches the buffer to another string
+ void attach(string_type& storage, size_type max_size)
+ {
detach();
- m_Storage = boost::addressof(storage);
+ m_storage_state.storage = &storage;
+ this->max_size(max_size);
}
//! Returns a pointer to the attached string
- string_type* storage() const { return m_Storage; }
+ string_type* storage() const BOOST_NOEXCEPT { return m_storage_state.storage; }
+
+ //! Returns the maximum size of the storage
+ size_type max_size() const BOOST_NOEXCEPT { return m_storage_state.max_size; }
+ //! Sets the maximum size of the storage
+ void max_size(size_type size)
+ {
+ if (m_storage_state.storage)
+ {
+ const size_type storage_max_size = m_storage_state.storage->max_size();
+ size = size > storage_max_size ? storage_max_size : size;
+ }
+
+ m_storage_state.max_size = size;
+ ensure_max_size();
+ }
+ //! Makes sure the storage does not exceed the max size limit. Should be called after the storage is modified externally.
+ void ensure_max_size()
+ {
+ if (m_storage_state.storage && m_storage_state.storage->size() > m_storage_state.max_size)
+ {
+ const size_type len = length_until_boundary(m_storage_state.storage->c_str(), m_storage_state.storage->size(), m_storage_state.max_size);
+ m_storage_state.storage->resize(len);
+ m_storage_state.overflow = true;
+ }
+ }
+
+ //! Returns true if the max size limit has been exceeded
+ bool storage_overflow() const BOOST_NOEXCEPT { return m_storage_state.overflow; }
+ //! Sets the overflow flag
+ void storage_overflow(bool f) BOOST_NOEXCEPT { m_storage_state.overflow = f; }
+
+ //! Returns the size left in the storage
+ size_type size_left() const BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT(m_storage_state.storage != NULL);
+
+ const size_type size = m_storage_state.storage->size();
+ return size < m_storage_state.max_size ? m_storage_state.max_size - size : static_cast< size_type >(0u);
+ }
+
+ //! Appends a string to the storage and returns the number of written characters
+ size_type append(const char_type* s, size_type n)
+ {
+ if (!m_storage_state.overflow)
+ {
+ BOOST_ASSERT(m_storage_state.storage != NULL);
+
+ size_type left = size_left();
+ BOOST_LOG_ASSUME(left <= m_storage_state.storage->max_size());
+ if (BOOST_LIKELY(n <= left))
+ {
+ m_storage_state.storage->append(s, n);
+ return n;
+ }
+ else
+ {
+ // We have to find out where the last character that fits before the limit ends
+ left = length_until_boundary(s, n, left);
+ m_storage_state.storage->append(s, left);
+ m_storage_state.overflow = true;
+ return left;
+ }
+ }
+ return 0u;
+ }
+
+ //! Appends the specified number of characters to the storage and returns the number of written characters
+ size_type append(size_type n, char_type c)
+ {
+ if (!m_storage_state.overflow)
+ {
+ BOOST_ASSERT(m_storage_state.storage != NULL);
+
+ const size_type left = size_left();
+ BOOST_LOG_ASSUME(left <= m_storage_state.storage->max_size());
+ if (BOOST_LIKELY(n <= left))
+ {
+ m_storage_state.storage->append(n, c);
+ return n;
+ }
+ else
+ {
+ m_storage_state.storage->append(left, c);
+ m_storage_state.overflow = true;
+ return left;
+ }
+ }
+ return 0u;
+ }
+
+ //! Appends a character to the storage and returns the number of written characters
+ size_type push_back(char_type c)
+ {
+ if (!m_storage_state.overflow)
+ {
+ BOOST_ASSERT(m_storage_state.storage != NULL);
+
+ BOOST_LOG_ASSUME(m_storage_state.max_size <= m_storage_state.storage->max_size());
+ if (BOOST_LIKELY(m_storage_state.storage->size() < m_storage_state.max_size))
+ {
+ m_storage_state.storage->push_back(c);
+ return 1u;
+ }
+ else
+ {
+ m_storage_state.overflow = true;
+ return 0u;
+ }
+ }
+ return 0u;
+ }
protected:
//! Puts all buffered data to the string
int sync()
{
- BOOST_ASSERT(m_Storage != 0);
char_type* pBase = this->pbase();
char_type* pPtr = this->pptr();
if (pBase != pPtr)
{
- m_Storage->append(pBase, pPtr);
+ this->append(pBase, static_cast< size_type >(pPtr - pBase));
this->pbump(static_cast< int >(pBase - pPtr));
}
return 0;
@@ -125,11 +258,10 @@ protected:
//! Puts an unbuffered character to the string
int_type overflow(int_type c)
{
- BOOST_ASSERT(m_Storage != 0);
- basic_ostringstreambuf::sync();
+ this_type::sync();
if (!traits_type::eq_int_type(c, traits_type::eof()))
{
- m_Storage->push_back(traits_type::to_char_type(c));
+ this->push_back(traits_type::to_char_type(c));
return c;
}
else
@@ -138,21 +270,47 @@ protected:
//! Puts a character sequence to the string
std::streamsize xsputn(const char_type* s, std::streamsize n)
{
- BOOST_ASSERT(m_Storage != 0);
- basic_ostringstreambuf::sync();
- typedef typename string_type::size_type string_size_type;
- const string_size_type max_storage_left =
- m_Storage->max_size() - m_Storage->size();
- if (static_cast< string_size_type >(n) < max_storage_left)
- {
- m_Storage->append(s, static_cast< string_size_type >(n));
- return n;
- }
- else
+ this_type::sync();
+ return static_cast< std::streamsize >(this->append(s, static_cast< size_type >(n)));
+ }
+
+ //! Finds the string length so that it includes only complete characters, and does not exceed \a max_size
+ size_type length_until_boundary(const char_type* s, size_type n, size_type max_size) const
+ {
+ return length_until_boundary(s, n, max_size, mpl::bool_< sizeof(char_type) == 1u >());;
+ }
+
+ //! Finds the string length so that it includes only complete characters, and does not exceed \a max_size
+ size_type length_until_boundary(const char_type* s, size_type n, size_type max_size, mpl::true_) const
+ {
+ std::locale loc = this->getloc();
+ std::codecvt< wchar_t, char, std::mbstate_t > const& fac = std::use_facet< std::codecvt< wchar_t, char, std::mbstate_t > >(loc);
+ std::mbstate_t mbs = std::mbstate_t();
+ return static_cast< size_type >(fac.length(mbs, s, s + max_size, ~static_cast< std::size_t >(0u)));
+ }
+
+ //! Finds the string length so that it includes only complete characters, and does not exceed \a max_size
+ static size_type length_until_boundary(const char_type* s, size_type n, size_type max_size, mpl::false_)
+ {
+ // Note: Although it's not required to be true for wchar_t, here we assume that the string has Unicode encoding.
+ // Compilers use some version of Unicode for wchar_t on all tested platforms, and std::locale doesn't offer a way
+ // to find the character boundary for character types other than char anyway.
+ typedef boost::locale::utf::utf_traits< CharT > utf_traits;
+
+ size_type pos = max_size;
+ while (pos > 0u)
{
- m_Storage->append(s, max_storage_left);
- return static_cast< std::streamsize >(max_storage_left);
+ --pos;
+ if (utf_traits::is_lead(s[pos]))
+ {
+ const char_type* p = s + pos;
+ boost::locale::utf::code_point cp = utf_traits::decode(p, s + n);
+ if (boost::locale::utf::is_valid_codepoint(cp) && p <= (s + max_size))
+ return static_cast< size_type >(p - s);
+ }
}
+
+ return 0u;
}
//! Copy constructor (closed)
diff --git a/boost/log/detail/c_str.hpp b/boost/log/detail/c_str.hpp
new file mode 100644
index 0000000000..049d1c389e
--- /dev/null
+++ b/boost/log/detail/c_str.hpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright Andrey Semashev 2016.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file c_str.hpp
+ * \author Andrey Semashev
+ * \date 23.02.2016
+ *
+ * This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_C_STR_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_C_STR_HPP_INCLUDED_
+
+#include <string>
+#include <boost/core/enable_if.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/is_character_type.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+template< typename T >
+inline typename boost::enable_if_c< is_character_type< T >::value, const T* >::type c_str(const T* str) BOOST_NOEXCEPT
+{
+ return str;
+}
+
+template< typename T, typename TraitsT, typename AllocatorT >
+inline typename boost::enable_if_c< is_character_type< T >::value, const T* >::type c_str(std::basic_string< T, TraitsT, AllocatorT > const& str) BOOST_NOEXCEPT
+{
+ return str.c_str();
+}
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_C_STR_HPP_INCLUDED_
diff --git a/boost/log/detail/code_conversion.hpp b/boost/log/detail/code_conversion.hpp
index 86cdfd8800..b39970d022 100644
--- a/boost/log/detail/code_conversion.hpp
+++ b/boost/log/detail/code_conversion.hpp
@@ -38,64 +38,99 @@ namespace aux {
// type. These conversions are used in sinks, e.g. to convert multibyte strings to wide-character filesystem paths.
//! The function converts one string to the character type of another
-BOOST_LOG_API void code_convert_impl(const wchar_t* str1, std::size_t len, std::string& str2, std::locale const& loc = std::locale());
+BOOST_LOG_API bool code_convert_impl(const wchar_t* str1, std::size_t len, std::string& str2, std::size_t max_size, std::locale const& loc = std::locale());
//! The function converts one string to the character type of another
-BOOST_LOG_API void code_convert_impl(const char* str1, std::size_t len, std::wstring& str2, std::locale const& loc = std::locale());
+BOOST_LOG_API bool code_convert_impl(const char* str1, std::size_t len, std::wstring& str2, std::size_t max_size, std::locale const& loc = std::locale());
#if !defined(BOOST_LOG_NO_CXX11_CODECVT_FACETS)
#if !defined(BOOST_NO_CXX11_CHAR16_T)
//! The function converts one string to the character type of another
-BOOST_LOG_API void code_convert_impl(const char16_t* str1, std::size_t len, std::string& str2, std::locale const& loc = std::locale());
+BOOST_LOG_API bool code_convert_impl(const char16_t* str1, std::size_t len, std::string& str2, std::size_t max_size, std::locale const& loc = std::locale());
//! The function converts one string to the character type of another
-BOOST_LOG_API void code_convert_impl(const char* str1, std::size_t len, std::u16string& str2, std::locale const& loc = std::locale());
+BOOST_LOG_API bool code_convert_impl(const char* str1, std::size_t len, std::u16string& str2, std::size_t max_size, std::locale const& loc = std::locale());
//! The function converts one string to the character type of another
-BOOST_LOG_API void code_convert_impl(const char16_t* str1, std::size_t len, std::wstring& str2, std::locale const& loc = std::locale());
+BOOST_LOG_API bool code_convert_impl(const char16_t* str1, std::size_t len, std::wstring& str2, std::size_t max_size, std::locale const& loc = std::locale());
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T)
//! The function converts one string to the character type of another
-BOOST_LOG_API void code_convert_impl(const char32_t* str1, std::size_t len, std::string& str2, std::locale const& loc = std::locale());
+BOOST_LOG_API bool code_convert_impl(const char32_t* str1, std::size_t len, std::string& str2, std::size_t max_size, std::locale const& loc = std::locale());
//! The function converts one string to the character type of another
-BOOST_LOG_API void code_convert_impl(const char* str1, std::size_t len, std::u32string& str2, std::locale const& loc = std::locale());
+BOOST_LOG_API bool code_convert_impl(const char* str1, std::size_t len, std::u32string& str2, std::size_t max_size, std::locale const& loc = std::locale());
//! The function converts one string to the character type of another
-BOOST_LOG_API void code_convert_impl(const char32_t* str1, std::size_t len, std::wstring& str2, std::locale const& loc = std::locale());
+BOOST_LOG_API bool code_convert_impl(const char32_t* str1, std::size_t len, std::wstring& str2, std::size_t max_size, std::locale const& loc = std::locale());
#endif
#if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_CHAR32_T)
//! The function converts one string to the character type of another
-BOOST_LOG_API void code_convert_impl(const char16_t* str1, std::size_t len, std::u32string& str2, std::locale const& loc = std::locale());
+BOOST_LOG_API bool code_convert_impl(const char16_t* str1, std::size_t len, std::u32string& str2, std::size_t max_size, std::locale const& loc = std::locale());
//! The function converts one string to the character type of another
-BOOST_LOG_API void code_convert_impl(const char32_t* str1, std::size_t len, std::u16string& str2, std::locale const& loc = std::locale());
+BOOST_LOG_API bool code_convert_impl(const char32_t* str1, std::size_t len, std::u16string& str2, std::size_t max_size, std::locale const& loc = std::locale());
#endif
#endif // !defined(BOOST_LOG_NO_CXX11_CODECVT_FACETS)
//! The function converts one string to the character type of another
+template< typename SourceCharT, typename TargetCharT, typename TargetTraitsT, typename TargetAllocatorT >
+inline typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) == sizeof(TargetCharT), bool >::type
+code_convert(const SourceCharT* str1, std::size_t len, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::size_t max_size, std::locale const& = std::locale())
+{
+ std::size_t size_left = str2.size() < max_size ? max_size - str2.size() : static_cast< std::size_t >(0u);
+ const bool overflow = len > size_left;
+ str2.append(reinterpret_cast< const TargetCharT* >(str1), overflow ? size_left : len);
+ return !overflow;
+}
+
+//! The function converts one string to the character type of another
template< typename SourceCharT, typename SourceTraitsT, typename SourceAllocatorT, typename TargetCharT, typename TargetTraitsT, typename TargetAllocatorT >
-inline typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) == sizeof(TargetCharT) >::type
-code_convert(std::basic_string< SourceCharT, SourceTraitsT, SourceAllocatorT > const& str1, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& = std::locale())
+inline typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) == sizeof(TargetCharT), bool >::type
+code_convert(std::basic_string< SourceCharT, SourceTraitsT, SourceAllocatorT > const& str1, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::size_t max_size, std::locale const& loc = std::locale())
+{
+ return aux::code_convert(str1.data(), str1.size(), str2, max_size, loc);
+}
+
+//! The function converts one string to the character type of another
+template< typename SourceCharT, typename SourceTraitsT, typename SourceAllocatorT, typename TargetCharT, typename TargetTraitsT, typename TargetAllocatorT >
+inline typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) == sizeof(TargetCharT), bool >::type
+code_convert(std::basic_string< SourceCharT, SourceTraitsT, SourceAllocatorT > const& str1, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& loc = std::locale())
{
- str2.append(reinterpret_cast< const TargetCharT* >(str1.c_str()), str1.size());
+ return aux::code_convert(str1.data(), str1.size(), str2, str2.max_size(), loc);
}
//! The function converts one string to the character type of another
template< typename SourceCharT, typename TargetCharT, typename TargetTraitsT, typename TargetAllocatorT >
-inline typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) == sizeof(TargetCharT) >::type
-code_convert(const SourceCharT* str1, std::size_t len, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& = std::locale())
+inline typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) == sizeof(TargetCharT), bool >::type
+code_convert(const SourceCharT* str1, std::size_t len, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& loc = std::locale())
{
- str2.append(reinterpret_cast< const TargetCharT* >(str1), len);
+ return aux::code_convert(str1, len, str2, str2.max_size(), loc);
}
//! The function converts one string to the character type of another
template< typename SourceCharT, typename SourceTraitsT, typename SourceAllocatorT, typename TargetCharT, typename TargetTraitsT, typename TargetAllocatorT >
-inline typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) != sizeof(TargetCharT) >::type
+inline typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) != sizeof(TargetCharT), bool >::type
code_convert(std::basic_string< SourceCharT, SourceTraitsT, SourceAllocatorT > const& str1, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& loc = std::locale())
{
- aux::code_convert_impl(str1.c_str(), str1.size(), str2, loc);
+ return aux::code_convert_impl(str1.c_str(), str1.size(), str2, str2.max_size(), loc);
}
//! The function converts one string to the character type of another
template< typename SourceCharT, typename TargetCharT, typename TargetTraitsT, typename TargetAllocatorT >
-inline typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) != sizeof(TargetCharT) >::type
+inline typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) != sizeof(TargetCharT), bool >::type
code_convert(const SourceCharT* str1, std::size_t len, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& loc = std::locale())
{
- aux::code_convert_impl(str1, len, str2, loc);
+ return aux::code_convert_impl(str1, len, str2, str2.max_size(), loc);
+}
+
+//! The function converts one string to the character type of another
+template< typename SourceCharT, typename SourceTraitsT, typename SourceAllocatorT, typename TargetCharT, typename TargetTraitsT, typename TargetAllocatorT >
+inline typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) != sizeof(TargetCharT), bool >::type
+code_convert(std::basic_string< SourceCharT, SourceTraitsT, SourceAllocatorT > const& str1, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::size_t max_size, std::locale const& loc = std::locale())
+{
+ return aux::code_convert_impl(str1.c_str(), str1.size(), str2, max_size, loc);
+}
+
+//! The function converts one string to the character type of another
+template< typename SourceCharT, typename TargetCharT, typename TargetTraitsT, typename TargetAllocatorT >
+inline typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) != sizeof(TargetCharT), bool >::type
+code_convert(const SourceCharT* str1, std::size_t len, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::size_t max_size, std::locale const& loc = std::locale())
+{
+ return aux::code_convert_impl(str1, len, str2, max_size, loc);
}
//! The function converts the passed string to the narrow-character encoding
@@ -114,8 +149,8 @@ inline std::string const& to_narrow(std::string const& str, std::locale const&)
inline std::string to_narrow(std::wstring const& str, std::locale const& loc = std::locale())
{
std::string res;
- aux::code_convert_impl(str.c_str(), str.size(), res, loc);
-#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ aux::code_convert_impl(str.c_str(), str.size(), res, res.max_size(), loc);
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_HAS_NRVO)
return static_cast< std::string&& >(res);
#else
return res;
@@ -138,8 +173,8 @@ inline std::wstring const& to_wide(std::wstring const& str, std::locale const&)
inline std::wstring to_wide(std::string const& str, std::locale const& loc = std::locale())
{
std::wstring res;
- aux::code_convert_impl(str.c_str(), str.size(), res, loc);
-#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ aux::code_convert_impl(str.c_str(), str.size(), res, res.max_size(), loc);
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_HAS_NRVO)
return static_cast< std::wstring&& >(res);
#else
return res;
diff --git a/boost/log/detail/config.hpp b/boost/log/detail/config.hpp
index ce9aeb2dc1..7265d2b6e4 100644
--- a/boost/log/detail/config.hpp
+++ b/boost/log/detail/config.hpp
@@ -134,6 +134,16 @@
#define BOOST_LOG_NO_CXX11_ARG_PACKS_TO_NON_VARIADIC_ARGS_EXPANSION
#endif
+#if defined(BOOST_NO_CXX11_CONSTEXPR) || (defined(BOOST_GCC) && ((BOOST_GCC+0) / 100) <= 406)
+// GCC 4.6 does not support in-class brace initializers for static constexpr array members
+#define BOOST_LOG_NO_CXX11_CONSTEXPR_DATA_MEMBER_BRACE_INITIALIZERS
+#endif
+
+#if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || (defined(BOOST_GCC) && ((BOOST_GCC+0) / 100) <= 406)
+// GCC 4.6 cannot handle a defaulted function with noexcept specifier
+#define BOOST_LOG_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
+#endif
+
#if defined(_MSC_VER)
# define BOOST_LOG_NO_VTABLE __declspec(novtable)
#elif defined(__GNUC__)
@@ -168,6 +178,14 @@
# define BOOST_LOG_UNREACHABLE_RETURN(r) BOOST_LOG_UNREACHABLE()
#endif
+// The macro efficiently returns a local lvalue from a function.
+// It employs NRVO, if supported by compiler, or uses a move constructor otherwise.
+#if defined(BOOST_HAS_NRVO)
+#define BOOST_LOG_NRVO_RESULT(x) x
+#else
+#define BOOST_LOG_NRVO_RESULT(x) boost::move(x)
+#endif
+
// Some compilers support a special attribute that shows that a function won't return
#if defined(__GNUC__) || (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x590)
// GCC and Sun Studio 12 support attribute syntax
diff --git a/boost/log/detail/decomposed_time.hpp b/boost/log/detail/decomposed_time.hpp
index 6008d6a798..0328106edc 100644
--- a/boost/log/detail/decomposed_time.hpp
+++ b/boost/log/detail/decomposed_time.hpp
@@ -25,6 +25,7 @@
#include <boost/range/iterator_range_core.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/date_time_format_parser.hpp>
+#include <boost/log/detail/attachable_sstream_buf.hpp>
#include <boost/log/utility/formatting_ostream.hpp>
#include <boost/log/detail/header.hpp>
@@ -108,7 +109,7 @@ struct decomposed_time_wrapper :
};
template< typename CharT >
-BOOST_LOG_API void put_integer(std::basic_string< CharT >& str, uint32_t value, unsigned int width, CharT fill_char);
+BOOST_LOG_API void put_integer(boost::log::aux::basic_ostringstreambuf< CharT >& strbuf, uint32_t value, unsigned int width, CharT fill_char);
template< typename T, typename CharT >
class date_time_formatter
@@ -130,14 +131,12 @@ public:
{
date_time_formatter const& self;
stream_type& strm;
- string_type& str;
value_type const& value;
unsigned int literal_index, literal_pos;
context(date_time_formatter const& self_, stream_type& strm_, value_type const& value_) :
self(self_),
strm(strm_),
- str(*strm_.rdbuf()->storage()),
value(value_),
literal_index(0),
literal_pos(0)
@@ -166,12 +165,12 @@ public:
m_literal_chars(that.m_literal_chars)
{
}
- date_time_formatter(BOOST_RV_REF(date_time_formatter) that)
+ date_time_formatter(BOOST_RV_REF(date_time_formatter) that) BOOST_NOEXCEPT
{
this->swap(static_cast< date_time_formatter& >(that));
}
- date_time_formatter& operator= (date_time_formatter that)
+ date_time_formatter& operator= (date_time_formatter that) BOOST_NOEXCEPT
{
this->swap(that);
return *this;
@@ -200,7 +199,7 @@ public:
m_formatters.push_back(&date_time_formatter_::format_literal);
}
- void swap(date_time_formatter& that)
+ void swap(date_time_formatter& that) BOOST_NOEXCEPT
{
m_formatters.swap(that.m_formatters);
m_literal_lens.swap(that.m_literal_lens);
@@ -220,55 +219,55 @@ public:
static void format_full_year(context& ctx)
{
- (put_integer)(ctx.str, ctx.value.year, 4, static_cast< char_type >('0'));
+ (put_integer)(*ctx.strm.rdbuf(), ctx.value.year, 4, static_cast< char_type >('0'));
}
static void format_short_year(context& ctx)
{
- (put_integer)(ctx.str, ctx.value.year % 100u, 2, static_cast< char_type >('0'));
+ (put_integer)(*ctx.strm.rdbuf(), ctx.value.year % 100u, 2, static_cast< char_type >('0'));
}
static void format_numeric_month(context& ctx)
{
- (put_integer)(ctx.str, ctx.value.month, 2, static_cast< char_type >('0'));
+ (put_integer)(*ctx.strm.rdbuf(), ctx.value.month, 2, static_cast< char_type >('0'));
}
template< char_type FillCharV >
static void format_month_day(context& ctx)
{
- (put_integer)(ctx.str, ctx.value.day, 2, static_cast< char_type >(FillCharV));
+ (put_integer)(*ctx.strm.rdbuf(), ctx.value.day, 2, static_cast< char_type >(FillCharV));
}
static void format_week_day(context& ctx)
{
- (put_integer)(ctx.str, static_cast< decomposed_time const& >(ctx.value).week_day(), 1, static_cast< char_type >('0'));
+ (put_integer)(*ctx.strm.rdbuf(), static_cast< decomposed_time const& >(ctx.value).week_day(), 1, static_cast< char_type >('0'));
}
template< char_type FillCharV >
static void format_hours(context& ctx)
{
- (put_integer)(ctx.str, ctx.value.hours, 2, static_cast< char_type >(FillCharV));
+ (put_integer)(*ctx.strm.rdbuf(), ctx.value.hours, 2, static_cast< char_type >(FillCharV));
}
template< char_type FillCharV >
static void format_hours_12(context& ctx)
{
- (put_integer)(ctx.str, ctx.value.hours % 12u + 1u, 2, static_cast< char_type >(FillCharV));
+ (put_integer)(*ctx.strm.rdbuf(), ctx.value.hours % 12u + 1u, 2, static_cast< char_type >(FillCharV));
}
static void format_minutes(context& ctx)
{
- (put_integer)(ctx.str, ctx.value.minutes, 2, static_cast< char_type >('0'));
+ (put_integer)(*ctx.strm.rdbuf(), ctx.value.minutes, 2, static_cast< char_type >('0'));
}
static void format_seconds(context& ctx)
{
- (put_integer)(ctx.str, ctx.value.seconds, 2, static_cast< char_type >('0'));
+ (put_integer)(*ctx.strm.rdbuf(), ctx.value.seconds, 2, static_cast< char_type >('0'));
}
static void format_fractional_seconds(context& ctx)
{
- (put_integer)(ctx.str, ctx.value.subseconds, decomposed_time::subseconds_digits10, static_cast< char_type >('0'));
+ (put_integer)(*ctx.strm.rdbuf(), ctx.value.subseconds, decomposed_time::subseconds_digits10, static_cast< char_type >('0'));
}
template< bool UpperCaseV >
@@ -277,16 +276,16 @@ public:
static const char_type am[] = { static_cast< char_type >(UpperCaseV ? 'A' : 'a'), static_cast< char_type >(UpperCaseV ? 'M' : 'm'), static_cast< char_type >(0) };
static const char_type pm[] = { static_cast< char_type >(UpperCaseV ? 'P' : 'p'), static_cast< char_type >(UpperCaseV ? 'M' : 'm'), static_cast< char_type >(0) };
- ctx.str.append(((static_cast< decomposed_time const& >(ctx.value).hours > 11) ? pm : am), 2u);
+ ctx.strm.rdbuf()->append(((static_cast< decomposed_time const& >(ctx.value).hours > 11) ? pm : am), 2u);
}
template< bool DisplayPositiveV >
static void format_sign(context& ctx)
{
if (static_cast< decomposed_time const& >(ctx.value).negative)
- ctx.str.push_back('-');
+ ctx.strm.rdbuf()->push_back('-');
else if (DisplayPositiveV)
- ctx.str.push_back('+');
+ ctx.strm.rdbuf()->push_back('+');
}
private:
@@ -296,7 +295,7 @@ private:
++ctx.literal_index;
ctx.literal_pos += len;
const char_type* lit = ctx.self.m_literal_chars.c_str();
- ctx.str.append(lit + pos, len);
+ ctx.strm.rdbuf()->append(lit + pos, len);
}
};
diff --git a/boost/log/detail/enqueued_record.hpp b/boost/log/detail/enqueued_record.hpp
index ef6377799f..f4821363a2 100644
--- a/boost/log/detail/enqueued_record.hpp
+++ b/boost/log/detail/enqueued_record.hpp
@@ -18,7 +18,7 @@
#define BOOST_LOG_DETAIL_ENQUEUED_RECORD_HPP_INCLUDED_
#include <boost/move/core.hpp>
-#include <boost/move/utility.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/timestamp.hpp>
#include <boost/log/core/record_view.hpp>
diff --git a/boost/log/detail/format.hpp b/boost/log/detail/format.hpp
index 89c6a9fb01..449f85edfa 100644
--- a/boost/log/detail/format.hpp
+++ b/boost/log/detail/format.hpp
@@ -21,7 +21,7 @@
#include <iosfwd>
#include <boost/assert.hpp>
#include <boost/move/core.hpp>
-#include <boost/move/utility.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/unhandled_exception_count.hpp>
#include <boost/log/detail/cleanup_scope_guard.hpp>
@@ -188,37 +188,19 @@ public:
}
//! Creates a pump that will receive all format arguments and put the formatted string into the stream
- pump make_pump(stream_type& strm) BOOST_NOEXCEPT
+ pump make_pump(stream_type& strm)
{
+ // Flush the stream beforehand so that the pump can safely switch the stream storage string
+ strm.flush();
return pump(*this, strm);
}
//! Composes the final string from the formatted pieces
- void compose(string_type& str) const
- {
- typename format_description_type::format_element_list::const_iterator it = m_format.format_elements.begin(), end = m_format.format_elements.end();
- for (; it != end; ++it)
- {
- if (it->arg_number >= 0)
- {
- // This is a placeholder
- str.append(m_formatting_params[it->arg_number].target);
- }
- else
- {
- // This is a literal
- const char_type* p = m_format.literal_chars.c_str() + it->literal_start_pos;
- str.append(p, it->literal_len);
- }
- }
- }
-
- //! Composes the final string from the formatted pieces
string_type str() const
{
string_type result;
compose(result);
- return boost::move(result);
+ return BOOST_LOG_NRVO_RESULT(result);
}
private:
@@ -236,6 +218,28 @@ private:
}
}
}
+
+ //! Composes the final string from the formatted pieces
+ template< typename T >
+ void compose(T& str) const
+ {
+ typename format_description_type::format_element_list::const_iterator it = m_format.format_elements.begin(), end = m_format.format_elements.end();
+ for (; it != end; ++it)
+ {
+ if (it->arg_number >= 0)
+ {
+ // This is a placeholder
+ string_type const& target = m_formatting_params[it->arg_number].target;
+ str.append(target.data(), target.size());
+ }
+ else
+ {
+ // This is a literal
+ const char_type* p = m_format.literal_chars.c_str() + it->literal_start_pos;
+ str.append(p, it->literal_len);
+ }
+ }
+ }
};
//! The pump receives arguments and formats them into strings. At destruction the pump composes the final string in the attached stream.
@@ -248,18 +252,18 @@ private:
//! The guard temporarily replaces storage string in the specified stream
struct scoped_storage
{
- scoped_storage(stream_type& strm, string_type& storage) : m_stream(strm), m_storage_backup(*strm.rdbuf()->storage())
+ scoped_storage(stream_type& strm, string_type& storage) : m_stream(strm), m_storage_state_backup(strm.rdbuf()->get_storage_state())
{
strm.attach(storage);
}
~scoped_storage()
{
- m_stream.attach(m_storage_backup);
+ m_stream.rdbuf()->set_storage_state(m_storage_state_backup);
}
private:
stream_type& m_stream;
- string_type& m_storage_backup;
+ typename stream_type::streambuf_type::storage_state m_storage_state_backup;
};
private:
@@ -296,7 +300,7 @@ public:
{
// Compose the final string in the stream buffer
m_stream->flush();
- m_owner->compose(*m_stream->rdbuf()->storage());
+ m_owner->compose(*m_stream->rdbuf());
}
}
}
diff --git a/boost/log/detail/light_function.hpp b/boost/log/detail/light_function.hpp
index d6606e0e67..0835772f66 100644
--- a/boost/log/detail/light_function.hpp
+++ b/boost/log/detail/light_function.hpp
@@ -21,7 +21,7 @@
#include <cstddef>
#include <boost/move/core.hpp>
-#include <boost/move/utility.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/utility/explicit_operator_bool.hpp>
#include <boost/type_traits/remove_cv.hpp>
@@ -33,7 +33,7 @@
#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
#endif
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
-#include <boost/utility/enable_if.hpp>
+#include <boost/log/detail/sfinae_tools.hpp>
#else
#include <boost/type_traits/remove_reference.hpp>
#endif
@@ -194,12 +194,12 @@ public:
}
#else
template< typename FunT >
- light_function(FunT const& fun, typename disable_if_c< is_rv_or_same< FunT, this_type >::value, int >::type = 0) :
+ light_function(FunT const& fun, typename boost::disable_if_c< is_rv_or_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :
m_pImpl(new impl< FunT >(fun))
{
}
template< typename FunT >
- light_function(BOOST_RV_REF(FunT) fun, typename disable_if_c< is_cv_same< FunT, this_type >::value, int >::type = 0) :
+ light_function(BOOST_RV_REF(FunT) fun, typename boost::disable_if_c< is_cv_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :
m_pImpl(new impl< typename remove_cv< FunT >::type >(fun))
{
}
@@ -256,7 +256,7 @@ public:
}
#else
template< typename FunT >
- typename disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type
+ typename boost::disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type
operator= (FunT const& fun)
{
light_function tmp(fun);
@@ -400,12 +400,12 @@ public:
}
#else
template< typename FunT >
- light_function(FunT const& fun, typename disable_if_c< is_rv_or_same< FunT, this_type >::value, int >::type = 0) :
+ light_function(FunT const& fun, typename boost::disable_if_c< is_rv_or_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :
m_pImpl(new impl< FunT >(fun))
{
}
template< typename FunT >
- light_function(BOOST_RV_REF(FunT) fun, typename disable_if_c< is_cv_same< FunT, this_type >::value, int >::type = 0) :
+ light_function(BOOST_RV_REF(FunT) fun, typename boost::disable_if_c< is_cv_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :
m_pImpl(new impl< typename remove_cv< FunT >::type >(fun))
{
}
@@ -462,7 +462,7 @@ public:
}
#else
template< typename FunT >
- typename disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type
+ typename boost::disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type
operator= (FunT const& fun)
{
light_function tmp(fun);
diff --git a/boost/log/detail/light_function_pp.hpp b/boost/log/detail/light_function_pp.hpp
index 92df419a52..9bf5f573fe 100644
--- a/boost/log/detail/light_function_pp.hpp
+++ b/boost/log/detail/light_function_pp.hpp
@@ -119,12 +119,12 @@ public:
}
#else
template< typename FunT >
- light_function(FunT const& fun, typename disable_if_c< is_rv_or_same< FunT, this_type >::value, int >::type = 0) :
+ light_function(FunT const& fun, typename boost::disable_if_c< is_rv_or_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :
m_pImpl(new impl< FunT >(fun))
{
}
template< typename FunT >
- light_function(BOOST_RV_REF(FunT) fun, typename disable_if_c< is_cv_same< FunT, this_type >::value, int >::type = 0) :
+ light_function(BOOST_RV_REF(FunT) fun, typename boost::disable_if_c< is_cv_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :
m_pImpl(new impl< typename remove_cv< FunT >::type >(fun))
{
}
@@ -181,7 +181,7 @@ public:
}
#else
template< typename FunT >
- typename disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type
+ typename boost::disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type
operator= (FunT const& fun)
{
light_function tmp(fun);
@@ -327,12 +327,12 @@ public:
}
#else
template< typename FunT >
- light_function(FunT const& fun, typename disable_if_c< is_rv_or_same< FunT, this_type >::value, int >::type = 0) :
+ light_function(FunT const& fun, typename boost::disable_if_c< is_rv_or_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :
m_pImpl(new impl< FunT >(fun))
{
}
template< typename FunT >
- light_function(BOOST_RV_REF(FunT) fun, typename disable_if_c< is_cv_same< FunT, this_type >::value, int >::type = 0) :
+ light_function(BOOST_RV_REF(FunT) fun, typename boost::disable_if_c< is_cv_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :
m_pImpl(new impl< typename remove_cv< FunT >::type >(fun))
{
}
@@ -389,7 +389,7 @@ public:
}
#else
template< typename FunT >
- typename disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type
+ typename boost::disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type
operator= (FunT const& fun)
{
light_function tmp(fun);
diff --git a/boost/log/detail/locks.hpp b/boost/log/detail/locks.hpp
index 99bc7e17f9..224d8e59bb 100644
--- a/boost/log/detail/locks.hpp
+++ b/boost/log/detail/locks.hpp
@@ -32,6 +32,8 @@ namespace boost {
template< typename >
class lock_guard;
template< typename >
+class shared_lock_guard;
+template< typename >
class shared_lock;
template< typename >
class upgrade_lock;
@@ -92,6 +94,25 @@ struct is_shared_lockable
enum value_t { value = sizeof(check_shared_lockable((MutexT*)NULL)) == sizeof(true_type) };
};
+//! A scope guard that automatically unlocks the mutex on destruction
+template< typename MutexT >
+struct exclusive_auto_unlocker
+{
+ explicit exclusive_auto_unlocker(MutexT& m) BOOST_NOEXCEPT : m_Mutex(m)
+ {
+ }
+ ~exclusive_auto_unlocker()
+ {
+ m_Mutex.unlock();
+ }
+
+ BOOST_DELETED_FUNCTION(exclusive_auto_unlocker(exclusive_auto_unlocker const&))
+ BOOST_DELETED_FUNCTION(exclusive_auto_unlocker& operator= (exclusive_auto_unlocker const&))
+
+protected:
+ MutexT& m_Mutex;
+};
+
//! An analogue to the minimalistic \c lock_guard template. Defined here to avoid including Boost.Thread.
template< typename MutexT >
struct exclusive_lock_guard
@@ -105,9 +126,8 @@ struct exclusive_lock_guard
m_Mutex.unlock();
}
-private:
- exclusive_lock_guard(exclusive_lock_guard const&);
- exclusive_lock_guard& operator= (exclusive_lock_guard const&);
+ BOOST_DELETED_FUNCTION(exclusive_lock_guard(exclusive_lock_guard const&))
+ BOOST_DELETED_FUNCTION(exclusive_lock_guard& operator= (exclusive_lock_guard const&))
private:
MutexT& m_Mutex;
@@ -126,9 +146,8 @@ struct shared_lock_guard
m_Mutex.unlock_shared();
}
-private:
- shared_lock_guard(shared_lock_guard const&);
- shared_lock_guard& operator= (shared_lock_guard const&);
+ BOOST_DELETED_FUNCTION(shared_lock_guard(shared_lock_guard const&))
+ BOOST_DELETED_FUNCTION(shared_lock_guard& operator= (shared_lock_guard const&))
private:
MutexT& m_Mutex;
diff --git a/boost/log/detail/parameter_tools.hpp b/boost/log/detail/parameter_tools.hpp
index 01df40536c..55695e3cde 100644
--- a/boost/log/detail/parameter_tools.hpp
+++ b/boost/log/detail/parameter_tools.hpp
@@ -17,6 +17,8 @@
#define BOOST_LOG_DETAIL_PARAMETER_TOOLS_HPP_INCLUDED_
#include <boost/parameter/keyword.hpp>
+#include <boost/preprocessor/control/if.hpp>
+#include <boost/preprocessor/comparison/equal.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
@@ -24,6 +26,7 @@
#include <boost/preprocessor/arithmetic/dec.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/sfinae_tools.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
@@ -40,23 +43,37 @@
public:\
BOOST_PP_REPEAT_FROM_TO(1, BOOST_LOG_MAX_PARAMETER_ARGS, macro, args)
+#define BOOST_LOG_CTOR_FORWARD_1(n, types)\
+ template< typename T0 >\
+ explicit BOOST_PP_TUPLE_ELEM(2, 0, types)(T0 const& arg0, typename boost::log::aux::enable_if_named_parameters< T0, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :\
+ BOOST_PP_TUPLE_ELEM(2, 1, types)((BOOST_PP_ENUM_PARAMS(n, arg))) {}
-#define BOOST_LOG_CTOR_FORWARD(z, n, types)\
+#define BOOST_LOG_CTOR_FORWARD_N(n, types)\
template< BOOST_PP_ENUM_PARAMS(n, typename T) >\
explicit BOOST_PP_TUPLE_ELEM(2, 0, types)(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg)) :\
BOOST_PP_TUPLE_ELEM(2, 1, types)((BOOST_PP_ENUM_PARAMS(n, arg))) {}
+#define BOOST_LOG_CTOR_FORWARD(z, n, types)\
+ BOOST_PP_IF(BOOST_PP_EQUAL(n, 1), BOOST_LOG_CTOR_FORWARD_1, BOOST_LOG_CTOR_FORWARD_N)(n, types)
+
// The macro expands to a number of templated constructors that aggregate their named arguments
// into an ArgumentsPack and pass it to the base class constructor.
#define BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_FORWARD(class_type, base_type)\
BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(BOOST_LOG_CTOR_FORWARD, (class_type, base_type))
+#define BOOST_LOG_CTOR_CALL_1(n, types)\
+ template< typename T0 >\
+ explicit BOOST_PP_TUPLE_ELEM(2, 0, types)(T0 const& arg0, typename boost::log::aux::enable_if_named_parameters< T0, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy())\
+ { BOOST_PP_TUPLE_ELEM(2, 1, types)((BOOST_PP_ENUM_PARAMS(n, arg))); }
-#define BOOST_LOG_CTOR_CALL(z, n, types)\
+#define BOOST_LOG_CTOR_CALL_N(n, types)\
template< BOOST_PP_ENUM_PARAMS(n, typename T) >\
explicit BOOST_PP_TUPLE_ELEM(2, 0, types)(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg))\
{ BOOST_PP_TUPLE_ELEM(2, 1, types)((BOOST_PP_ENUM_PARAMS(n, arg))); }
+#define BOOST_LOG_CTOR_CALL(z, n, types)\
+ BOOST_PP_IF(BOOST_PP_EQUAL(n, 1), BOOST_LOG_CTOR_CALL_1, BOOST_LOG_CTOR_CALL_N)(n, types)
+
// The macro expands to a number of templated constructors that aggregate their named arguments
// into an ArgumentsPack and pass it to a function call.
#define BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_CALL(class_type, fun)\
@@ -69,6 +86,7 @@ BOOST_LOG_OPEN_NAMESPACE
namespace aux {
// Yeah, not too cute. The empty_arg_list class should really be public.
+// https://svn.boost.org/trac/boost/ticket/7247
typedef boost::parameter::aux::empty_arg_list empty_arg_list;
#if !(defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_LOG_NO_CXX11_ARG_PACKS_TO_NON_VARIADIC_ARGS_EXPANSION))
@@ -103,6 +121,27 @@ struct make_arg_list< ArgT0, BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(BOOST_LOG_MAX_PAR
#endif
+template< typename T, typename R >
+struct enable_if_named_parameters {};
+
+template< typename R >
+struct enable_if_named_parameters< empty_arg_list, R >
+{
+ typedef R type;
+};
+
+template< typename Keyword, typename Arg, typename R >
+struct enable_if_named_parameters< boost::parameter::aux::tagged_argument< Keyword, Arg >, R >
+{
+ typedef R type;
+};
+
+template< typename TaggedArg, typename Next, typename R >
+struct enable_if_named_parameters< boost::parameter::aux::arg_list< TaggedArg, Next >, R >
+{
+ typedef R type;
+};
+
} // namespace aux
BOOST_LOG_CLOSE_NAMESPACE // namespace log
diff --git a/boost/log/detail/pause.hpp b/boost/log/detail/pause.hpp
new file mode 100644
index 0000000000..c1b43498f0
--- /dev/null
+++ b/boost/log/detail/pause.hpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright Andrey Semashev 2016.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file pause.hpp
+ * \author Andrey Semashev
+ * \date 06.01.2016
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_PAUSE_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_PAUSE_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(__INTEL_COMPILER) || defined(_MSC_VER)
+# if defined(_M_IX86)
+# define BOOST_LOG_AUX_PAUSE __asm { pause }
+# elif defined(_M_AMD64)
+extern "C" void _mm_pause(void);
+# if defined(BOOST_MSVC)
+# pragma intrinsic(_mm_pause)
+# endif
+# define BOOST_LOG_AUX_PAUSE _mm_pause()
+# endif
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+# define BOOST_LOG_AUX_PAUSE __asm__ __volatile__("pause;")
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+BOOST_FORCEINLINE void pause() BOOST_NOEXCEPT
+{
+#if defined(BOOST_LOG_AUX_PAUSE)
+ BOOST_LOG_AUX_PAUSE;
+#endif
+}
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_PAUSE_HPP_INCLUDED_
diff --git a/boost/log/detail/sfinae_tools.hpp b/boost/log/detail/sfinae_tools.hpp
new file mode 100644
index 0000000000..e9f2735b25
--- /dev/null
+++ b/boost/log/detail/sfinae_tools.hpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright Andrey Semashev 2016.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file sfinae_tools.hpp
+ * \author Andrey Semashev
+ * \date 23.02.2016
+ *
+ * \brief This header is the Boost.Log library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
+ */
+
+#ifndef BOOST_LOG_DETAIL_SFINAE_TOOLS_HPP_INCLUDED_
+#define BOOST_LOG_DETAIL_SFINAE_TOOLS_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/core/enable_if.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+//! A distinct type that can be used as a fake argument type in constructors filtered by SFINAE
+struct sfinae_dummy {};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DETAIL_SFINAE_TOOLS_HPP_INCLUDED_
diff --git a/boost/log/detail/sink_init_helpers.hpp b/boost/log/detail/sink_init_helpers.hpp
index c94b5630c4..a3bbe0e8a1 100644
--- a/boost/log/detail/sink_init_helpers.hpp
+++ b/boost/log/detail/sink_init_helpers.hpp
@@ -20,7 +20,7 @@
#include <boost/mpl/bool.hpp>
#include <boost/parameter/binding.hpp>
#include <boost/type_traits/is_void.hpp>
-#include <boost/utility/enable_if.hpp>
+#include <boost/core/enable_if.hpp>
#include <boost/phoenix/core/is_actor.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/core/core.hpp>
@@ -54,8 +54,8 @@ inline filter acquire_filter(std::basic_string< CharT, TraitsT, AllocatorT > con
return boost::log::parse_filter(filter);
}
template< typename FilterT >
-inline typename enable_if<
- phoenix::is_actor< FilterT >,
+inline typename boost::enable_if_c<
+ phoenix::is_actor< FilterT >::value,
FilterT const&
>::type acquire_filter(FilterT const& filter)
{
@@ -87,8 +87,8 @@ inline basic_formatter< CharT > acquire_formatter(std::basic_string< CharT, Trai
return boost::log::parse_formatter(formatter);
}
template< typename FormatterT >
-inline typename enable_if<
- phoenix::is_actor< FormatterT >,
+inline typename boost::enable_if_c<
+ phoenix::is_actor< FormatterT >::value,
FormatterT const&
>::type acquire_formatter(FormatterT const& formatter)
{
diff --git a/boost/log/detail/snprintf.hpp b/boost/log/detail/snprintf.hpp
index 7fae834526..14c6a6b1dc 100644
--- a/boost/log/detail/snprintf.hpp
+++ b/boost/log/detail/snprintf.hpp
@@ -35,20 +35,10 @@ BOOST_LOG_OPEN_NAMESPACE
namespace aux {
-#if !defined(_MSC_VER)
+#if defined(_MSC_VER) || (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
-// Standard-conforming compilers already have the correct snprintfs
-using ::snprintf;
-using ::vsnprintf;
-
-# ifdef BOOST_LOG_USE_WCHAR_T
-using ::swprintf;
-using ::vswprintf;
-# endif // BOOST_LOG_USE_WCHAR_T
-
-#else // !defined(_MSC_VER)
-
-// MSVC snprintfs are not conforming but they are good enough for our cases
+// MSVC snprintfs are not conforming but they are good enough for our cases.
+// MinGW32, at least the older versions up until gcc 4.7, also provide the non-conforming interface.
inline int vsnprintf(char* buf, std::size_t size, const char* format, std::va_list args)
{
int n = _vsnprintf(buf, size, format, args);
@@ -93,7 +83,18 @@ inline int swprintf(wchar_t* buf, std::size_t size, const wchar_t* format, ...)
}
# endif // BOOST_LOG_USE_WCHAR_T
-#endif // !defined(_MSC_VER)
+#else
+
+// Standard-conforming compilers already have the correct snprintfs
+using ::snprintf;
+using ::vsnprintf;
+
+# ifdef BOOST_LOG_USE_WCHAR_T
+using ::swprintf;
+using ::vswprintf;
+# endif // BOOST_LOG_USE_WCHAR_T
+
+#endif
} // namespace aux
diff --git a/boost/log/detail/tagged_integer.hpp b/boost/log/detail/tagged_integer.hpp
index f72b9af78d..82c9706863 100644
--- a/boost/log/detail/tagged_integer.hpp
+++ b/boost/log/detail/tagged_integer.hpp
@@ -42,17 +42,17 @@ struct tagged_integer
integer_type value;
//! Conversion operator
- operator integer_type() const { return value; }
+ BOOST_CONSTEXPR operator integer_type() const BOOST_NOEXCEPT { return value; }
// Increment
- tagged_integer& operator++ () { ++value; return *this; }
- tagged_integer operator++ (int) { tagged_integer temp = *this; ++value; return temp; }
+ tagged_integer& operator++ () BOOST_NOEXCEPT { ++value; return *this; }
+ tagged_integer operator++ (int) BOOST_NOEXCEPT { tagged_integer temp = *this; ++value; return temp; }
// Decrement
- tagged_integer& operator-- () { --value; return *this; }
- tagged_integer operator-- (int) { tagged_integer temp = *this; --value; return temp; }
+ tagged_integer& operator-- () BOOST_NOEXCEPT { --value; return *this; }
+ tagged_integer operator-- (int) BOOST_NOEXCEPT { tagged_integer temp = *this; --value; return temp; }
#define BOOST_LOG_TAGGED_INTEGER_OP(op)\
- tagged_integer& operator op (tagged_integer const& that) { value op that.value; return *this; }
+ tagged_integer& operator op (tagged_integer const& that) BOOST_NOEXCEPT { value op that.value; return *this; }
BOOST_LOG_TAGGED_INTEGER_OP(|=)
BOOST_LOG_TAGGED_INTEGER_OP(&=)
@@ -66,13 +66,13 @@ struct tagged_integer
#undef BOOST_LOG_TAGGED_INTEGER_OP
//! Inversion operator
- tagged_integer& operator~ () { ~value; return *this; }
+ tagged_integer& operator~ () BOOST_NOEXCEPT { ~value; return *this; }
// Shift operators
template< typename T >
- tagged_integer& operator<<= (T const& that) { value <<= that; return *this; }
+ tagged_integer& operator<<= (T const& that) BOOST_NOEXCEPT { value <<= that; return *this; }
template< typename T >
- tagged_integer& operator>>= (T const& that) { value >>= that; return *this; }
+ tagged_integer& operator>>= (T const& that) BOOST_NOEXCEPT { value >>= that; return *this; }
private:
// Protection against improper usage
@@ -86,7 +86,7 @@ private:
#define BOOST_LOG_TAGGED_INTEGER_OP(op)\
template< typename IntT, typename TagT >\
inline bool operator op (\
- tagged_integer< IntT, TagT > const& left, tagged_integer< IntT, TagT > const& right)\
+ tagged_integer< IntT, TagT > const& left, tagged_integer< IntT, TagT > const& right) BOOST_NOEXCEPT\
{\
return (left.value op right.value);\
}
@@ -103,7 +103,7 @@ BOOST_LOG_TAGGED_INTEGER_OP(>=)
#define BOOST_LOG_TAGGED_INTEGER_OP(op)\
template< typename IntT, typename TagT >\
inline tagged_integer< IntT, TagT > operator op (\
- tagged_integer< IntT, TagT > const& left, tagged_integer< IntT, TagT > const& right)\
+ tagged_integer< IntT, TagT > const& left, tagged_integer< IntT, TagT > const& right) BOOST_NOEXCEPT\
{\
tagged_integer< IntT, TagT > temp = left;\
temp op##= right;\
@@ -124,7 +124,7 @@ BOOST_LOG_TAGGED_INTEGER_OP(%)
#define BOOST_LOG_TAGGED_INTEGER_OP(op)\
template< typename IntT, typename TagT, typename T >\
inline tagged_integer< IntT, TagT > operator op (\
- tagged_integer< IntT, TagT > const& left, T const& right)\
+ tagged_integer< IntT, TagT > const& left, T const& right) BOOST_NOEXCEPT\
{\
tagged_integer< IntT, TagT > temp = left;\
temp op##= right;\
diff --git a/boost/log/detail/threadsafe_queue.hpp b/boost/log/detail/threadsafe_queue.hpp
index 2ab2172b13..b8b3dbe60a 100644
--- a/boost/log/detail/threadsafe_queue.hpp
+++ b/boost/log/detail/threadsafe_queue.hpp
@@ -29,7 +29,7 @@
#include <cstddef>
#include <boost/aligned_storage.hpp>
#include <boost/move/core.hpp>
-#include <boost/move/utility.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/type_with_alignment.hpp>
#include <boost/log/detail/header.hpp>
diff --git a/boost/log/exceptions.hpp b/boost/log/exceptions.hpp
index 8f305fabeb..32d55d40c5 100644
--- a/boost/log/exceptions.hpp
+++ b/boost/log/exceptions.hpp
@@ -20,6 +20,8 @@
#include <stdexcept>
#include <boost/type_index.hpp>
#include <boost/preprocessor/seq/enum.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/system/system_error.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/attributes/attribute_name.hpp>
#include <boost/log/detail/header.hpp>
@@ -59,6 +61,68 @@ BOOST_LOG_API void attach_attribute_name_info(exception& e, attribute_name const
} // namespace aux
/*!
+ * \brief Base class for memory allocation errors
+ *
+ * Exceptions derived from this class indicate problems with memory allocation.
+ */
+class BOOST_LOG_API bad_alloc :
+ public std::bad_alloc
+{
+private:
+ std::string m_message;
+
+public:
+ /*!
+ * Initializing constructor. Creates an exception with the specified error message.
+ */
+ explicit bad_alloc(const char* descr);
+ /*!
+ * Initializing constructor. Creates an exception with the specified error message.
+ */
+ explicit bad_alloc(std::string const& descr);
+ /*!
+ * Destructor
+ */
+ ~bad_alloc() throw();
+
+ /*!
+ * Error message accessor.
+ */
+ const char* what() const throw();
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, const char* descr);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr);
+#endif
+};
+
+/*!
+ * \brief The exception is used to indicate reaching a storage capacity limit
+ */
+class BOOST_LOG_API capacity_limit_reached :
+ public bad_alloc
+{
+public:
+ /*!
+ * Initializing constructor. Creates an exception with the specified error message.
+ */
+ explicit capacity_limit_reached(const char* descr);
+ /*!
+ * Initializing constructor. Creates an exception with the specified error message.
+ */
+ explicit capacity_limit_reached(std::string const& descr);
+ /*!
+ * Destructor
+ */
+ ~capacity_limit_reached() throw();
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, const char* descr);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr);
+#endif
+};
+
+/*!
* \brief Base class for runtime exceptions from the logging library
*
* Exceptions derived from this class indicate a problem that may not directly
@@ -68,7 +132,7 @@ BOOST_LOG_API void attach_attribute_name_info(exception& e, attribute_name const
class BOOST_LOG_API runtime_error :
public std::runtime_error
{
-protected:
+public:
/*!
* Initializing constructor. Creates an exception with the specified error message.
*/
@@ -101,7 +165,9 @@ public:
#ifndef BOOST_LOG_DOXYGEN_PASS
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, const char* descr);
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, const char* descr, attribute_name const& name);
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, attribute_name const& name);
#endif
};
@@ -128,9 +194,13 @@ public:
#ifndef BOOST_LOG_DOXYGEN_PASS
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, const char* descr);
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, const char* descr, attribute_name const& name);
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, const char* descr, typeindex::type_index 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, const char* descr, attribute_name const& name, 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
};
@@ -157,6 +227,7 @@ public:
#ifndef BOOST_LOG_DOXYGEN_PASS
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, const char* descr);
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr);
#endif
};
@@ -183,8 +254,11 @@ public:
#ifndef BOOST_LOG_DOXYGEN_PASS
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, const char* descr);
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, const char* descr, std::size_t content_line);
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, std::size_t content_line);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, const char* descr, attribute_name const& name);
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, attribute_name const& name);
#endif
};
@@ -211,6 +285,7 @@ public:
#ifndef BOOST_LOG_DOXYGEN_PASS
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, const char* descr);
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr);
#endif
};
@@ -219,25 +294,23 @@ public:
* \brief Exception class that is used to indicate underlying OS API errors
*/
class BOOST_LOG_API system_error :
- public runtime_error
+ public boost::system::system_error
{
public:
/*!
- * Default constructor. Creates an exception with the default error message.
- */
- system_error();
- /*!
* Initializing constructor. Creates an exception with the specified error message.
*/
- explicit system_error(std::string const& descr);
+ system_error(boost::system::error_code code, std::string const& descr);
/*!
* Destructor
*/
~system_error() throw();
#ifndef BOOST_LOG_DOXYGEN_PASS
- static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line);
- static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, const char* descr, int system_error_code);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, int system_error_code);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, const char* descr, boost::system::error_code code);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, boost::system::error_code code);
#endif
};
@@ -250,7 +323,7 @@ public:
class BOOST_LOG_API logic_error :
public std::logic_error
{
-protected:
+public:
/*!
* Initializing constructor. Creates an exception with the specified error message.
*/
@@ -259,6 +332,11 @@ protected:
* Destructor
*/
~logic_error() throw();
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, const char* descr);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr);
+#endif
};
/*!
@@ -283,6 +361,7 @@ public:
#ifndef BOOST_LOG_DOXYGEN_PASS
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, const char* descr);
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr);
#endif
};
@@ -309,6 +388,7 @@ public:
#ifndef BOOST_LOG_DOXYGEN_PASS
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, const char* descr);
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr);
#endif
};
@@ -335,6 +415,7 @@ public:
#ifndef BOOST_LOG_DOXYGEN_PASS
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, const char* descr);
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr);
#endif
};
@@ -361,6 +442,7 @@ public:
#ifndef BOOST_LOG_DOXYGEN_PASS
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line);
+ static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, const char* descr);
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr);
#endif
};
diff --git a/boost/log/expressions/attr.hpp b/boost/log/expressions/attr.hpp
index aca0447cff..60540e7d77 100644
--- a/boost/log/expressions/attr.hpp
+++ b/boost/log/expressions/attr.hpp
@@ -56,8 +56,10 @@ private:
typedef attribute_terminal< T, FallbackPolicyT, TagT > this_type;
public:
+#ifndef BOOST_LOG_DOXYGEN_PASS
//! Internal typedef for type categorization
typedef void _is_boost_log_terminal;
+#endif
//! Attribute tag type
typedef TagT tag_type;
diff --git a/boost/log/expressions/filter.hpp b/boost/log/expressions/filter.hpp
index ae43abe150..1e53f5c3bd 100644
--- a/boost/log/expressions/filter.hpp
+++ b/boost/log/expressions/filter.hpp
@@ -16,11 +16,11 @@
#define BOOST_LOG_EXPRESSIONS_FILTER_HPP_INCLUDED_
#include <boost/move/core.hpp>
-#include <boost/move/utility.hpp>
+#include <boost/move/utility_core.hpp>
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
-#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_cv.hpp>
+#include <boost/log/detail/sfinae_tools.hpp>
#endif
#include <boost/log/detail/config.hpp>
#include <boost/log/attributes/attribute_value_set.hpp>
@@ -89,13 +89,13 @@ public:
filter(FunT&& fun) : m_Filter(boost::forward< FunT >(fun))
{
}
-#elif !defined(BOOST_MSVC) || BOOST_MSVC > 1400
+#elif !defined(BOOST_MSVC) || BOOST_MSVC >= 1600
template< typename FunT >
- filter(FunT const& fun, typename disable_if_c< move_detail::is_rv< FunT >::value, int >::type = 0) : m_Filter(fun)
+ filter(FunT const& fun, typename boost::disable_if_c< move_detail::is_rv< FunT >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) : m_Filter(fun)
{
}
#else
- // MSVC 8 blows up in unexpected ways if we use SFINAE to disable constructor instantiation
+ // MSVC 9 and older blows up in unexpected ways if we use SFINAE to disable constructor instantiation
template< typename FunT >
filter(FunT const& fun) : m_Filter(fun)
{
@@ -137,7 +137,7 @@ public:
filter& operator= (FunT const& fun)
#else
template< typename FunT >
- typename disable_if< is_same< typename remove_cv< FunT >::type, filter >, filter& >::type
+ typename boost::disable_if_c< is_same< typename remove_cv< FunT >::type, filter >::value, filter& >::type
operator= (FunT const& fun)
#endif
{
diff --git a/boost/log/expressions/formatter.hpp b/boost/log/expressions/formatter.hpp
index bdbabb504e..bc80dfa250 100644
--- a/boost/log/expressions/formatter.hpp
+++ b/boost/log/expressions/formatter.hpp
@@ -19,11 +19,11 @@
#include <ostream>
#include <boost/ref.hpp>
#include <boost/move/core.hpp>
-#include <boost/move/utility.hpp>
+#include <boost/move/utility_core.hpp>
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
-#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_cv.hpp>
+#include <boost/log/detail/sfinae_tools.hpp>
#endif
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/light_function.hpp>
@@ -376,11 +376,11 @@ public:
}
#elif !defined(BOOST_MSVC) || BOOST_MSVC >= 1600
template< typename FunT >
- basic_formatter(FunT const& fun, typename disable_if_c< move_detail::is_rv< FunT >::value, int >::type = 0) : m_Formatter(fun)
+ basic_formatter(FunT const& fun, typename boost::disable_if_c< move_detail::is_rv< FunT >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) : m_Formatter(fun)
{
}
#else
- // MSVC 9 blows up in unexpected ways if we use SFINAE to disable constructor instantiation
+ // MSVC 9 and older blows up in unexpected ways if we use SFINAE to disable constructor instantiation
template< typename FunT >
basic_formatter(FunT const& fun) : m_Formatter(fun)
{
@@ -426,7 +426,7 @@ public:
}
#else
template< typename FunT >
- typename disable_if< is_same< typename remove_cv< FunT >::type, this_type >, this_type& >::type
+ typename boost::disable_if_c< is_same< typename remove_cv< FunT >::type, this_type >::value, this_type& >::type
operator= (FunT const& fun)
{
this_type(fun).swap(*this);
diff --git a/boost/log/expressions/formatters.hpp b/boost/log/expressions/formatters.hpp
index 1d3f4edd54..f85cb7903b 100644
--- a/boost/log/expressions/formatters.hpp
+++ b/boost/log/expressions/formatters.hpp
@@ -27,6 +27,7 @@
#include <boost/log/expressions/formatters/xml_decorator.hpp>
#include <boost/log/expressions/formatters/csv_decorator.hpp>
#include <boost/log/expressions/formatters/c_decorator.hpp>
+#include <boost/log/expressions/formatters/max_size_decorator.hpp>
#include <boost/log/expressions/formatters/if.hpp>
#include <boost/log/expressions/formatters/wrap_formatter.hpp>
diff --git a/boost/log/expressions/formatters/char_decorator.hpp b/boost/log/expressions/formatters/char_decorator.hpp
index e3188810ff..229e72ae89 100644
--- a/boost/log/expressions/formatters/char_decorator.hpp
+++ b/boost/log/expressions/formatters/char_decorator.hpp
@@ -27,9 +27,8 @@
#include <boost/range/const_iterator.hpp>
#include <boost/range/value_type.hpp>
#include <boost/move/core.hpp>
-#include <boost/move/utility.hpp>
-#include <boost/core/enable_if.hpp>
-#include <boost/utility/addressof.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/core/addressof.hpp>
#include <boost/phoenix/core/actor.hpp>
#include <boost/phoenix/core/meta_grammar.hpp>
#include <boost/phoenix/core/terminal_fwd.hpp>
@@ -43,6 +42,7 @@
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/custom_terminal_spec.hpp>
#include <boost/log/detail/deduce_char_type.hpp>
+#include <boost/log/detail/sfinae_tools.hpp>
#include <boost/log/utility/formatting_ostream.hpp>
#include <boost/log/detail/header.hpp>
@@ -113,7 +113,7 @@ public:
explicit pattern_replacer(RangeT const& decorations
#ifndef BOOST_LOG_DOXYGEN_PASS
// This is needed for a workaround against an MSVC-10 and older bug in constructor overload resolution
- , typename boost::enable_if_has_type< typename range_const_iterator< RangeT >::type, int >::type = 0
+ , typename boost::enable_if_has_type< typename range_const_iterator< RangeT >::type, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()
#endif
)
{
@@ -235,8 +235,10 @@ private:
typedef char_decorator_output_terminal< LeftT, SubactorT, ImplT > this_type;
public:
+#ifndef BOOST_LOG_DOXYGEN_PASS
//! Internal typedef for type categorization
typedef void _is_boost_log_terminal;
+#endif
//! Implementation type
typedef ImplT impl_type;
@@ -300,12 +302,12 @@ public:
typename string_type::size_type const start_pos = strm.rdbuf()->storage()->size();
// Invoke the adopted formatter
- typedef typename result< this_type(ContextT const&) >::type result_type;
phoenix::eval(m_subactor, ctx);
// Flush the buffered characters and apply decorations
strm.flush();
m_impl(*strm.rdbuf()->storage(), start_pos);
+ strm.rdbuf()->ensure_max_size();
return strm;
}
@@ -323,12 +325,12 @@ public:
typename string_type::size_type const start_pos = strm.rdbuf()->storage()->size();
// Invoke the adopted formatter
- typedef typename result< const this_type(ContextT const&) >::type result_type;
phoenix::eval(m_subactor, ctx);
// Flush the buffered characters and apply decorations
strm.flush();
m_impl(*strm.rdbuf()->storage(), start_pos);
+ strm.rdbuf()->ensure_max_size();
return strm;
}
@@ -357,8 +359,10 @@ private:
typedef char_decorator_terminal< SubactorT, ImplT > this_type;
public:
+#ifndef BOOST_LOG_DOXYGEN_PASS
//! Internal typedef for type categorization
typedef void _is_boost_log_terminal;
+#endif
//! Implementation type
typedef ImplT impl_type;
@@ -439,7 +443,7 @@ public:
strm.flush();
m_impl(*strm.rdbuf()->storage());
- return boost::move(str);
+ return BOOST_LOG_NRVO_RESULT(str);
}
/*!
@@ -471,7 +475,7 @@ public:
strm.flush();
m_impl(*strm.rdbuf()->storage());
- return boost::move(str);
+ return BOOST_LOG_NRVO_RESULT(str);
}
BOOST_DELETED_FUNCTION(char_decorator_terminal())
diff --git a/boost/log/expressions/formatters/date_time.hpp b/boost/log/expressions/formatters/date_time.hpp
index 45091fc206..b8de0b4cb7 100644
--- a/boost/log/expressions/formatters/date_time.hpp
+++ b/boost/log/expressions/formatters/date_time.hpp
@@ -17,7 +17,7 @@
#include <string>
#include <boost/move/core.hpp>
-#include <boost/move/utility.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/phoenix/core/actor.hpp>
#include <boost/phoenix/core/terminal_fwd.hpp>
#include <boost/phoenix/core/is_nullary.hpp>
@@ -54,8 +54,10 @@ template< typename T, typename FallbackPolicyT, typename CharT >
class format_date_time_terminal
{
public:
+#ifndef BOOST_LOG_DOXYGEN_PASS
//! Internal typedef for type categorization
typedef void _is_boost_log_terminal;
+#endif
//! Attribute value type
typedef T value_type;
@@ -126,7 +128,7 @@ public:
stream_type strm(str);
m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< formatter_function_type&, stream_type& >(m_formatter, strm));
strm.flush();
- return boost::move(str);
+ return BOOST_LOG_NRVO_RESULT(str);
}
//! Invokation operator
@@ -137,7 +139,7 @@ public:
stream_type strm(str);
m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< formatter_function_type const&, stream_type& >(m_formatter, strm));
strm.flush();
- return boost::move(str);
+ return BOOST_LOG_NRVO_RESULT(str);
}
BOOST_DELETED_FUNCTION(format_date_time_terminal())
diff --git a/boost/log/expressions/formatters/format.hpp b/boost/log/expressions/formatters/format.hpp
index ceccae942e..d312d8e36d 100644
--- a/boost/log/expressions/formatters/format.hpp
+++ b/boost/log/expressions/formatters/format.hpp
@@ -44,8 +44,10 @@ template< typename CharT >
class format_terminal
{
public:
+#ifndef BOOST_LOG_DOXYGEN_PASS
//! Internal typedef for type categorization
typedef void _is_boost_log_terminal;
+#endif
//! Character type
typedef CharT char_type;
diff --git a/boost/log/expressions/formatters/if.hpp b/boost/log/expressions/formatters/if.hpp
index 360622f843..3e1e1abc5a 100644
--- a/boost/log/expressions/formatters/if.hpp
+++ b/boost/log/expressions/formatters/if.hpp
@@ -48,8 +48,10 @@ private:
typedef if_output_terminal this_type;
public:
+#ifndef BOOST_LOG_DOXYGEN_PASS
//! Internal typedef for type categorization
typedef void _is_boost_log_terminal;
+#endif
//! Result type definition
template< typename >
@@ -113,8 +115,10 @@ private:
typedef if_else_output_terminal this_type;
public:
+#ifndef BOOST_LOG_DOXYGEN_PASS
//! Internal typedef for type categorization
typedef void _is_boost_log_terminal;
+#endif
//! Result type definition
template< typename >
diff --git a/boost/log/expressions/formatters/max_size_decorator.hpp b/boost/log/expressions/formatters/max_size_decorator.hpp
new file mode 100644
index 0000000000..0ab44d6fa4
--- /dev/null
+++ b/boost/log/expressions/formatters/max_size_decorator.hpp
@@ -0,0 +1,561 @@
+/*
+ * Copyright Andrey Semashev 2016.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file formatters/max_size_decorator.hpp
+ * \author Andrey Semashev
+ * \date 06.07.2016
+ *
+ * The header contains implementation of a string length limiting decorator.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_MAX_SIZE_DECORATOR_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_FORMATTERS_MAX_SIZE_DECORATOR_HPP_INCLUDED_
+
+#include <cstddef>
+#include <string>
+#include <boost/assert.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/core/addressof.hpp>
+#include <boost/phoenix/core/actor.hpp>
+#include <boost/phoenix/core/meta_grammar.hpp>
+#include <boost/phoenix/core/terminal_fwd.hpp>
+#include <boost/phoenix/core/is_nullary.hpp>
+#include <boost/phoenix/core/environment.hpp>
+#include <boost/phoenix/support/vector.hpp>
+#include <boost/fusion/sequence/intrinsic/at_c.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/custom_terminal_spec.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+namespace aux {
+
+//! String size limiting decorator stream output terminal
+template< typename LeftT, typename SubactorT, typename CharT >
+class max_size_decorator_output_terminal
+{
+private:
+ //! Self type
+ typedef max_size_decorator_output_terminal< LeftT, SubactorT, CharT > this_type;
+
+public:
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ //! Internal typedef for type categorization
+ typedef void _is_boost_log_terminal;
+#endif
+
+ //! Character type
+ typedef CharT char_type;
+ //! String type
+ typedef std::basic_string< char_type > string_type;
+ //! String size type
+ typedef std::size_t size_type;
+ //! Adopted actor type
+ typedef SubactorT subactor_type;
+
+ //! Result type definition
+ template< typename >
+ struct result;
+
+ template< typename ThisT, typename ContextT >
+ struct result< ThisT(ContextT) >
+ {
+ typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type;
+ typedef typename phoenix::evaluator::impl<
+ typename LeftT::proto_base_expr&,
+ context_type,
+ phoenix::unused
+ >::result_type type;
+ };
+
+private:
+ //! Left argument actor
+ LeftT m_left;
+ //! Adopted formatter actor
+ subactor_type m_subactor;
+ //! Max size of the formatted string produced by the adopted formatter
+ size_type m_max_size;
+ //! Overflow marker
+ string_type m_overflow_marker;
+
+public:
+ /*!
+ * Initializing constructor. Creates decorator of the \a fmt formatter with the specified \a decorations.
+ */
+ max_size_decorator_output_terminal(LeftT const& left, subactor_type const& sub, size_type max_size, string_type const& overflow_marker = string_type()) :
+ m_left(left), m_subactor(sub), m_max_size(max_size), m_overflow_marker(overflow_marker)
+ {
+ BOOST_ASSERT(overflow_marker.size() <= max_size);
+ }
+ /*!
+ * Copy constructor
+ */
+ max_size_decorator_output_terminal(max_size_decorator_output_terminal const& that) :
+ m_left(that.m_left), m_subactor(that.m_subactor), m_max_size(that.m_max_size), m_overflow_marker(that.m_overflow_marker)
+ {
+ }
+
+ /*!
+ * Invokation operator
+ */
+ template< typename ContextT >
+ typename result< this_type(ContextT const&) >::type operator() (ContextT const& ctx)
+ {
+ // Flush the stream and keep the current write position in the target string
+ typedef typename result< this_type(ContextT const&) >::type result_type;
+ result_type strm = phoenix::eval(m_left, ctx);
+ strm.flush();
+
+ if (!strm.rdbuf()->storage_overflow())
+ {
+ const size_type old_max_size = strm.rdbuf()->max_size();
+ const size_type start_pos = strm.rdbuf()->storage()->size(), max_size_left = strm.rdbuf()->storage()->max_size() - start_pos;
+ strm.rdbuf()->max_size(start_pos + (m_max_size <= max_size_left ? m_max_size : max_size_left));
+
+ try
+ {
+ // Invoke the adopted formatter
+ phoenix::eval(m_subactor, ctx);
+
+ // Flush the buffered characters and apply decorations
+ strm.flush();
+
+ if (strm.rdbuf()->storage_overflow())
+ {
+ if (!m_overflow_marker.empty())
+ {
+ // Free up space for the overflow marker
+ strm.rdbuf()->max_size(strm.rdbuf()->max_size() - m_overflow_marker.size());
+
+ // Append the marker
+ strm.rdbuf()->max_size(strm.rdbuf()->storage()->max_size());
+ strm.rdbuf()->storage_overflow(false);
+ strm.rdbuf()->append(m_overflow_marker.data(), m_overflow_marker.size());
+ }
+ else
+ {
+ strm.rdbuf()->storage_overflow(false);
+ }
+ }
+
+ // Restore the original size limit
+ strm.rdbuf()->max_size(old_max_size);
+ }
+ catch (...)
+ {
+ strm.rdbuf()->storage_overflow(false);
+ strm.rdbuf()->max_size(old_max_size);
+ throw;
+ }
+ }
+
+ return strm;
+ }
+
+ /*!
+ * Invokation operator
+ */
+ template< typename ContextT >
+ typename result< const this_type(ContextT const&) >::type operator() (ContextT const& ctx) const
+ {
+ // Flush the stream and keep the current write position in the target string
+ typedef typename result< const this_type(ContextT const&) >::type result_type;
+ result_type strm = phoenix::eval(m_left, ctx);
+ strm.flush();
+
+ if (!strm.rdbuf()->storage_overflow())
+ {
+ const size_type old_max_size = strm.rdbuf()->max_size();
+ const size_type start_pos = strm.rdbuf()->storage()->size(), max_size_left = strm.rdbuf()->storage()->max_size() - start_pos;
+ strm.rdbuf()->max_size(start_pos + (m_max_size <= max_size_left ? m_max_size : max_size_left));
+
+ try
+ {
+ // Invoke the adopted formatter
+ phoenix::eval(m_subactor, ctx);
+
+ // Flush the buffered characters and apply decorations
+ strm.flush();
+
+ if (strm.rdbuf()->storage_overflow())
+ {
+ if (!m_overflow_marker.empty())
+ {
+ // Free up space for the overflow marker
+ strm.rdbuf()->max_size(strm.rdbuf()->max_size() - m_overflow_marker.size());
+
+ // Append the marker
+ strm.rdbuf()->max_size(strm.rdbuf()->storage()->max_size());
+ strm.rdbuf()->storage_overflow(false);
+ strm.rdbuf()->append(m_overflow_marker.data(), m_overflow_marker.size());
+ }
+ else
+ {
+ strm.rdbuf()->storage_overflow(false);
+ }
+ }
+
+ // Restore the original size limit
+ strm.rdbuf()->max_size(old_max_size);
+ }
+ catch (...)
+ {
+ strm.rdbuf()->storage_overflow(false);
+ strm.rdbuf()->max_size(old_max_size);
+ throw;
+ }
+ }
+
+ return strm;
+ }
+
+ BOOST_DELETED_FUNCTION(max_size_decorator_output_terminal())
+};
+
+} // namespace aux
+
+/*!
+ * String size limiting decorator terminal class. This formatter allows to limit the maximum total length
+ * of the strings generated by other formatters.
+ *
+ * The \c max_size_decorator_terminal class aggregates the formatter being decorated, the maximum string length
+ * it can produce and an optional truncation marker string, which will be put at the end of the output if the limit is exceeded. Note that
+ * the marker length is included in the limit and as such must not exceed it.
+ * The \c max_size_decorator_terminal class is a formatter itself, so it can be used to construct
+ * more complex formatters, including nesting decorators.
+ */
+template< typename SubactorT, typename CharT >
+class max_size_decorator_terminal
+{
+private:
+ //! Self type
+ typedef max_size_decorator_terminal< SubactorT, CharT > this_type;
+
+public:
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ //! Internal typedef for type categorization
+ typedef void _is_boost_log_terminal;
+#endif
+
+ //! Character type
+ typedef CharT char_type;
+ //! String type
+ typedef std::basic_string< char_type > string_type;
+ //! String size type
+ typedef std::size_t size_type;
+ //! Stream type
+ typedef basic_formatting_ostream< char_type > stream_type;
+ //! Adopted actor type
+ typedef SubactorT subactor_type;
+
+ //! Result type definition
+ typedef string_type result_type;
+
+private:
+ //! Adopted formatter actor
+ subactor_type m_subactor;
+ //! Max size of the formatted string produced by the adopted formatter
+ size_type m_max_size;
+ //! Overflow marker
+ string_type m_overflow_marker;
+
+public:
+ /*!
+ * Initializing constructor.
+ */
+ max_size_decorator_terminal(subactor_type const& sub, size_type max_size, string_type const& overflow_marker = string_type()) :
+ m_subactor(sub), m_max_size(max_size), m_overflow_marker(overflow_marker)
+ {
+ BOOST_ASSERT(overflow_marker.size() <= max_size);
+ }
+ /*!
+ * Copy constructor
+ */
+ max_size_decorator_terminal(max_size_decorator_terminal const& that) :
+ m_subactor(that.m_subactor), m_max_size(that.m_max_size), m_overflow_marker(that.m_overflow_marker)
+ {
+ }
+
+ /*!
+ * \returns Adopted subactor
+ */
+ subactor_type const& get_subactor() const
+ {
+ return m_subactor;
+ }
+
+ /*!
+ * \returns Max string size limit
+ */
+ size_type get_max_size() const
+ {
+ return m_max_size;
+ }
+
+ /*!
+ * \returns Max string size limit
+ */
+ string_type const& get_overflow_marker() const
+ {
+ return m_overflow_marker;
+ }
+
+ /*!
+ * Invokation operator
+ */
+ template< typename ContextT >
+ result_type operator() (ContextT const& ctx)
+ {
+ string_type str;
+ stream_type strm(str);
+ strm.rdbuf()->max_size(m_max_size);
+
+ // Invoke the adopted formatter
+ typedef phoenix::vector3<
+ subactor_type*,
+ typename fusion::result_of::at_c<
+ typename remove_cv<
+ typename remove_reference<
+ typename phoenix::result_of::env< ContextT const& >::type
+ >::type
+ >::type::args_type,
+ 0
+ >::type,
+ stream_type&
+ > env_type;
+ env_type env = { boost::addressof(m_subactor), fusion::at_c< 0 >(phoenix::env(ctx).args()), strm };
+ phoenix::eval(m_subactor, phoenix::make_context(env, phoenix::actions(ctx)));
+
+ // Flush the buffered characters and see of overflow happened
+ strm.flush();
+
+ if (strm.rdbuf()->storage_overflow() && !m_overflow_marker.empty())
+ {
+ strm.rdbuf()->max_size(strm.rdbuf()->max_size() - m_overflow_marker.size());
+ strm.rdbuf()->max_size(str.max_size());
+ strm.rdbuf()->storage_overflow(false);
+ strm.rdbuf()->append(m_overflow_marker.data(), m_overflow_marker.size());
+ strm.flush();
+ }
+
+ return BOOST_LOG_NRVO_RESULT(str);
+ }
+
+ /*!
+ * Invokation operator
+ */
+ template< typename ContextT >
+ result_type operator() (ContextT const& ctx) const
+ {
+ string_type str;
+ stream_type strm(str);
+ strm.rdbuf()->max_size(m_max_size);
+
+ // Invoke the adopted formatter
+ typedef phoenix::vector3<
+ const subactor_type*,
+ typename fusion::result_of::at_c<
+ typename remove_cv<
+ typename remove_reference<
+ typename phoenix::result_of::env< ContextT const& >::type
+ >::type
+ >::type::args_type,
+ 0
+ >::type,
+ stream_type&
+ > env_type;
+ env_type env = { boost::addressof(m_subactor), fusion::at_c< 0 >(phoenix::env(ctx).args()), strm };
+ phoenix::eval(m_subactor, phoenix::make_context(env, phoenix::actions(ctx)));
+
+ // Flush the buffered characters and see of overflow happened
+ strm.flush();
+
+ if (strm.rdbuf()->storage_overflow())
+ {
+ strm.rdbuf()->max_size(strm.rdbuf()->max_size() - m_overflow_marker.size());
+ strm.rdbuf()->max_size(str.max_size());
+ strm.rdbuf()->storage_overflow(false);
+ strm.rdbuf()->append(m_overflow_marker.data(), m_overflow_marker.size());
+ strm.flush();
+ }
+
+ return BOOST_LOG_NRVO_RESULT(str);
+ }
+
+ BOOST_DELETED_FUNCTION(max_size_decorator_terminal())
+};
+
+/*!
+ * Character decorator actor
+ */
+template< typename SubactorT, typename CharT, template< typename > class ActorT = phoenix::actor >
+class max_size_decorator_actor :
+ public ActorT< max_size_decorator_terminal< SubactorT, CharT > >
+{
+public:
+ //! Base terminal type
+ typedef max_size_decorator_terminal< SubactorT, CharT > terminal_type;
+ //! Character type
+ typedef typename terminal_type::char_type char_type;
+
+ //! Base actor type
+ typedef ActorT< terminal_type > base_type;
+
+public:
+ //! Initializing constructor
+ explicit max_size_decorator_actor(base_type const& act) : base_type(act)
+ {
+ }
+
+ //! Returns reference to the terminal
+ terminal_type const& get_terminal() const
+ {
+ return this->proto_expr_.child0;
+ }
+};
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\
+ template< typename LeftExprT, typename SubactorT, typename CharT, template< typename > class ActorT >\
+ BOOST_FORCEINLINE phoenix::actor< aux::max_size_decorator_output_terminal< phoenix::actor< LeftExprT >, SubactorT, CharT > >\
+ operator<< (phoenix::actor< LeftExprT > left_ref left, max_size_decorator_actor< SubactorT, CharT, ActorT > right_ref right)\
+ {\
+ typedef aux::max_size_decorator_output_terminal< phoenix::actor< LeftExprT >, SubactorT, CharT > terminal_type;\
+ phoenix::actor< terminal_type > actor = {{ terminal_type(left, right.get_terminal().get_subactor(), right.get_terminal().get_max_size(), right.get_terminal().get_overflow_marker()) }};\
+ return actor;\
+ }
+
+#include <boost/log/detail/generate_overloads.hpp>
+
+#undef BOOST_LOG_AUX_OVERLOAD
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+namespace aux {
+
+template< typename CharT >
+class max_size_decorator_gen
+{
+private:
+ typedef CharT char_type;
+ typedef std::basic_string< char_type > string_type;
+ typedef std::size_t size_type;
+
+private:
+ size_type m_max_size;
+ string_type m_overflow_marker;
+
+public:
+ explicit max_size_decorator_gen(size_type max_size, string_type const& overflow_marker = string_type()) :
+ m_max_size(max_size), m_overflow_marker(overflow_marker)
+ {
+ BOOST_ASSERT(overflow_marker.size() <= max_size);
+ }
+
+ template< typename SubactorT >
+ BOOST_FORCEINLINE max_size_decorator_actor< SubactorT, char_type > operator[] (SubactorT const& subactor) const
+ {
+ typedef max_size_decorator_actor< SubactorT, char_type > result_type;
+ typedef typename result_type::terminal_type terminal_type;
+ typename result_type::base_type act = {{ terminal_type(subactor, m_max_size, m_overflow_marker) }};
+ return result_type(act);
+ }
+};
+
+} // namespace aux
+
+/*!
+ * The function returns a decorator generator object. The generator provides <tt>operator[]</tt> that can be used
+ * to construct the actual decorator.
+ *
+ * \param max_size The maximum number of characters (i.e. string element objects) that the decorated formatter can produce.
+ */
+template< typename CharT >
+BOOST_FORCEINLINE aux::max_size_decorator_gen< CharT > max_size_decor(std::size_t max_size)
+{
+ return aux::max_size_decorator_gen< CharT >(max_size);
+}
+
+/*!
+ * The function returns a decorator generator object. The generator provides <tt>operator[]</tt> that can be used
+ * to construct the actual decorator.
+ *
+ * \param max_size The maximum number of characters (i.e. string element objects) that the decorated formatter can produce.
+ * \param overflow_marker The marker string which is appended to the output if the \a max_size limit is exceeded. Must be
+ * a non-null pointer to a zero-terminated string.
+ *
+ * \pre The \a overflow_marker length must not exceed the \a max_size limit.
+ */
+template< typename CharT >
+BOOST_FORCEINLINE aux::max_size_decorator_gen< CharT > max_size_decor(std::size_t max_size, const CharT* overflow_marker)
+{
+ return aux::max_size_decorator_gen< CharT >(max_size, overflow_marker);
+}
+
+/*!
+ * The function returns a decorator generator object. The generator provides <tt>operator[]</tt> that can be used
+ * to construct the actual decorator.
+ *
+ * \param max_size The maximum number of characters (i.e. string element objects) that the decorated formatter can produce.
+ * \param overflow_marker The marker string which is appended to the output if the \a max_size limit is exceeded.
+ *
+ * \pre The \a overflow_marker length must not exceed the \a max_size limit.
+ */
+template< typename CharT >
+BOOST_FORCEINLINE aux::max_size_decorator_gen< CharT > max_size_decor(std::size_t max_size, std::basic_string< CharT > const& overflow_marker)
+{
+ return aux::max_size_decorator_gen< CharT >(max_size, overflow_marker);
+}
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+namespace phoenix {
+
+namespace result_of {
+
+template< typename SubactorT, typename CharT >
+struct is_nullary< custom_terminal< boost::log::expressions::max_size_decorator_terminal< SubactorT, CharT > > > :
+ public mpl::false_
+{
+};
+
+template< typename LeftT, typename SubactorT, typename CharT >
+struct is_nullary< custom_terminal< boost::log::expressions::aux::max_size_decorator_output_terminal< LeftT, SubactorT, CharT > > > :
+ public mpl::false_
+{
+};
+
+} // namespace result_of
+
+} // namespace phoenix
+
+#endif
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_MAX_SIZE_DECORATOR_HPP_INCLUDED_
diff --git a/boost/log/expressions/formatters/named_scope.hpp b/boost/log/expressions/formatters/named_scope.hpp
index cc45dc6e81..ae140b1956 100644
--- a/boost/log/expressions/formatters/named_scope.hpp
+++ b/boost/log/expressions/formatters/named_scope.hpp
@@ -21,7 +21,7 @@
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/move/core.hpp>
-#include <boost/move/utility.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/parameter/binding.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
@@ -257,8 +257,10 @@ template< typename FallbackPolicyT, typename CharT >
class format_named_scope_terminal
{
public:
+#ifndef BOOST_LOG_DOXYGEN_PASS
//! Internal typedef for type categorization
typedef void _is_boost_log_terminal;
+#endif
//! Attribute value type
typedef attributes::named_scope::value_type value_type;
@@ -337,7 +339,7 @@ public:
stream_type strm(str);
m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< formatter_function_type&, stream_type& >(m_formatter, strm));
strm.flush();
- return boost::move(str);
+ return BOOST_LOG_NRVO_RESULT(str);
}
//! Invokation operator
@@ -348,7 +350,7 @@ public:
stream_type strm(str);
m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< formatter_function_type const&, stream_type& >(m_formatter, strm));
strm.flush();
- return boost::move(str);
+ return BOOST_LOG_NRVO_RESULT(str);
}
BOOST_DELETED_FUNCTION(format_named_scope_terminal())
diff --git a/boost/log/expressions/formatters/wrap_formatter.hpp b/boost/log/expressions/formatters/wrap_formatter.hpp
index 612be28d70..29c19c2f80 100644
--- a/boost/log/expressions/formatters/wrap_formatter.hpp
+++ b/boost/log/expressions/formatters/wrap_formatter.hpp
@@ -17,7 +17,7 @@
#include <string>
#include <boost/move/core.hpp>
-#include <boost/move/utility.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/mpl/has_xxx.hpp>
#include <boost/phoenix/core/actor.hpp>
#include <boost/phoenix/core/terminal_fwd.hpp>
@@ -53,8 +53,10 @@ private:
typedef wrapped_formatter_output_terminal< LeftT, FunT > this_type;
public:
+#ifndef BOOST_LOG_DOXYGEN_PASS
//! Internal typedef for type categorization
typedef void _is_boost_log_terminal;
+#endif
//! Wrapped function type
typedef FunT function_type;
@@ -156,8 +158,10 @@ template< typename FunT, typename CharT >
class wrapped_formatter_terminal
{
public:
+#ifndef BOOST_LOG_DOXYGEN_PASS
//! Internal typedef for type categorization
typedef void _is_boost_log_terminal;
+#endif
//! Character type
typedef CharT char_type;
@@ -199,7 +203,7 @@ public:
stream_type strm(str);
m_fun(fusion::at_c< 0 >(phoenix::env(ctx).args()), strm);
strm.flush();
- return boost::move(str);
+ return BOOST_LOG_NRVO_RESULT(str);
}
//! Invokation operator
@@ -210,7 +214,7 @@ public:
stream_type strm(str);
m_fun(fusion::at_c< 0 >(phoenix::env(ctx).args()), strm);
strm.flush();
- return boost::move(str);
+ return BOOST_LOG_NRVO_RESULT(str);
}
};
diff --git a/boost/log/expressions/predicates/channel_severity_filter.hpp b/boost/log/expressions/predicates/channel_severity_filter.hpp
index 079b79233d..c7430a1bd7 100644
--- a/boost/log/expressions/predicates/channel_severity_filter.hpp
+++ b/boost/log/expressions/predicates/channel_severity_filter.hpp
@@ -57,8 +57,10 @@ template<
class channel_severity_filter_terminal
{
public:
+#ifndef BOOST_LOG_DOXYGEN_PASS
//! Internal typedef for type categorization
typedef void _is_boost_log_terminal;
+#endif
//! Function result type
typedef bool result_type;
diff --git a/boost/log/keywords/block_size.hpp b/boost/log/keywords/block_size.hpp
new file mode 100644
index 0000000000..daaa91fc25
--- /dev/null
+++ b/boost/log/keywords/block_size.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2016.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/block_size.hpp
+ * \author Andrey Semashev
+ * \date 23.02.2016
+ *
+ * The header contains the \c block_size keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_BLOCK_SIZE_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_BLOCK_SIZE_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword allows to pass interprocess queue name to the queue constructor
+BOOST_PARAMETER_KEYWORD(tag, block_size)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_BLOCK_SIZE_HPP_INCLUDED_
diff --git a/boost/log/keywords/capacity.hpp b/boost/log/keywords/capacity.hpp
new file mode 100644
index 0000000000..d7b6345ce8
--- /dev/null
+++ b/boost/log/keywords/capacity.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2016.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/capacity.hpp
+ * \author Andrey Semashev
+ * \date 23.02.2016
+ *
+ * The header contains the \c capacity keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_CAPACITY_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_CAPACITY_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword allows to pass interprocess queue capacity to the queue constructor
+BOOST_PARAMETER_KEYWORD(tag, capacity)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_CAPACITY_HPP_INCLUDED_
diff --git a/boost/log/keywords/name.hpp b/boost/log/keywords/name.hpp
new file mode 100644
index 0000000000..d0f93d3d74
--- /dev/null
+++ b/boost/log/keywords/name.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2016.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/name.hpp
+ * \author Andrey Semashev
+ * \date 23.02.2016
+ *
+ * The header contains the \c name keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_NAME_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_NAME_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword allows to pass interprocess queue name to the queue constructor
+BOOST_PARAMETER_KEYWORD(tag, name)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_NAME_HPP_INCLUDED_
diff --git a/boost/log/keywords/overflow_policy.hpp b/boost/log/keywords/overflow_policy.hpp
new file mode 100644
index 0000000000..e66450d824
--- /dev/null
+++ b/boost/log/keywords/overflow_policy.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2016.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/overflow_policy.hpp
+ * \author Andrey Semashev
+ * \date 23.02.2016
+ *
+ * The header contains the \c overflow_policy keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_OVERFLOW_POLICY_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_OVERFLOW_POLICY_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword allows to pass interprocess queue overflow policy to the queue constructor
+BOOST_PARAMETER_KEYWORD(tag, overflow_policy)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_OVERFLOW_POLICY_HPP_INCLUDED_
diff --git a/boost/log/keywords/permissions.hpp b/boost/log/keywords/permissions.hpp
new file mode 100644
index 0000000000..4b2451a0ab
--- /dev/null
+++ b/boost/log/keywords/permissions.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2016.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/permissions.hpp
+ * \author Andrey Semashev
+ * \date 23.02.2016
+ *
+ * The header contains the \c permissions keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_PERMISSIONS_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_PERMISSIONS_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword allows to pass interprocess queue permissions to the queue constructor
+BOOST_PARAMETER_KEYWORD(tag, permissions)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_PERMISSIONS_HPP_INCLUDED_
diff --git a/boost/log/sinks.hpp b/boost/log/sinks.hpp
index 0969b31d3c..d22d1c1d1e 100644
--- a/boost/log/sinks.hpp
+++ b/boost/log/sinks.hpp
@@ -33,6 +33,7 @@
#include <boost/log/sinks/syslog_backend.hpp>
#include <boost/log/sinks/text_file_backend.hpp>
+#include <boost/log/sinks/text_ipc_message_queue_backend.hpp>
#include <boost/log/sinks/text_multifile_backend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#ifdef BOOST_WINDOWS
diff --git a/boost/log/sinks/async_frontend.hpp b/boost/log/sinks/async_frontend.hpp
index c0209bfb2f..ec5371006e 100644
--- a/boost/log/sinks/async_frontend.hpp
+++ b/boost/log/sinks/async_frontend.hpp
@@ -32,6 +32,8 @@
#include <boost/atomic/atomic.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
+#include <boost/preprocessor/control/if.hpp>
+#include <boost/preprocessor/comparison/equal.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/thread.hpp>
@@ -54,7 +56,31 @@ namespace sinks {
#ifndef BOOST_LOG_DOXYGEN_PASS
-#define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL(z, n, types)\
+#define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_1(n, data)\
+ template< typename T0 >\
+ explicit asynchronous_sink(T0 const& arg0, typename boost::log::aux::enable_if_named_parameters< T0, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :\
+ base_type(true),\
+ queue_base_type(arg0),\
+ m_pBackend(boost::make_shared< sink_backend_type >(arg0)),\
+ m_StopRequested(false),\
+ m_FlushRequested(false)\
+ {\
+ if (arg0[keywords::start_thread | true])\
+ start_feeding_thread();\
+ }\
+ template< typename T0 >\
+ explicit asynchronous_sink(shared_ptr< sink_backend_type > const& backend, T0 const& arg0) :\
+ base_type(true),\
+ queue_base_type(arg0),\
+ m_pBackend(backend),\
+ m_StopRequested(false),\
+ m_FlushRequested(false)\
+ {\
+ if (arg0[keywords::start_thread | true])\
+ start_feeding_thread();\
+ }
+
+#define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_N(n, data)\
template< BOOST_PP_ENUM_PARAMS(n, typename T) >\
explicit asynchronous_sink(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg)) :\
base_type(true),\
@@ -78,6 +104,9 @@ namespace sinks {
start_feeding_thread();\
}
+#define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL(z, n, data)\
+ BOOST_PP_IF(BOOST_PP_EQUAL(n, 1), BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_1, BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_N)(n, data)
+
#endif // BOOST_LOG_DOXYGEN_PASS
/*!
@@ -254,8 +283,23 @@ public:
start_feeding_thread();
}
- // Constructors that pass arbitrary parameters to the backend constructor
+ /*!
+ * Constructor that passes arbitrary named parameters to the interprocess sink backend constructor.
+ * Refer to the backend documentation for the list of supported parameters.
+ *
+ * The frontend uses the following named parameters:
+ *
+ * \li start_thread - If \c true, the frontend creates a thread to feed
+ * log records to the backend. Otherwise no thread is
+ * started and it is assumed that the user will call
+ * either \c run or \c feed_records himself.
+ */
+#ifndef BOOST_LOG_DOXYGEN_PASS
BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL, ~)
+#else
+ template< typename... Args >
+ explicit asynchronous_sink(Args&&... args);
+#endif
/*!
* Destructor. Implicitly stops the dedicated feeding thread, if one is running.
@@ -455,6 +499,8 @@ private:
#endif // BOOST_LOG_DOXYGEN_PASS
};
+#undef BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_1
+#undef BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_N
#undef BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL
} // namespace sinks
diff --git a/boost/log/sinks/attribute_mapping.hpp b/boost/log/sinks/attribute_mapping.hpp
index c14f5e7841..24cfe3387e 100644
--- a/boost/log/sinks/attribute_mapping.hpp
+++ b/boost/log/sinks/attribute_mapping.hpp
@@ -83,7 +83,7 @@ namespace aux {
template< typename T >
void operator() (T const& val) const
{
- mapped_type v = { val };
+ mapped_type v = { static_cast< IntT >(val) };
m_Extracted = v;
}
diff --git a/boost/log/sinks/basic_sink_frontend.hpp b/boost/log/sinks/basic_sink_frontend.hpp
index 965451c7a8..3686bc5917 100644
--- a/boost/log/sinks/basic_sink_frontend.hpp
+++ b/boost/log/sinks/basic_sink_frontend.hpp
@@ -17,7 +17,6 @@
#include <boost/mpl/bool.hpp>
#include <boost/log/detail/config.hpp>
-#include <boost/log/detail/cleanup_scope_guard.hpp>
#include <boost/log/detail/code_conversion.hpp>
#include <boost/log/detail/attachable_sstream_buf.hpp>
#include <boost/log/detail/fake_mutex.hpp>
@@ -29,7 +28,6 @@
#if !defined(BOOST_LOG_NO_THREADS)
#include <boost/thread/exceptions.hpp>
#include <boost/thread/tss.hpp>
-#include <boost/thread/locks.hpp>
#include <boost/log/detail/locks.hpp>
#include <boost/log/detail/light_rw_mutex.hpp>
#endif // !defined(BOOST_LOG_NO_THREADS)
@@ -186,13 +184,10 @@ protected:
bool try_feed_record(record_view const& rec, BackendMutexT& backend_mutex, BackendT& backend)
{
#if !defined(BOOST_LOG_NO_THREADS)
- unique_lock< BackendMutexT > lock;
try
{
- unique_lock< BackendMutexT > tmp_lock(backend_mutex, try_to_lock);
- if (!tmp_lock.owns_lock())
+ if (!backend_mutex.try_lock())
return false;
- lock.swap(tmp_lock);
}
catch (thread_interrupted&)
{
@@ -206,6 +201,8 @@ protected:
this->exception_handler()();
return false;
}
+
+ boost::log::aux::exclusive_auto_unlocker< BackendMutexT > unlocker(backend_mutex);
#endif
// No need to lock anything in the feed_record method
boost::log::aux::fake_mutex m;
@@ -280,6 +277,28 @@ protected:
private:
struct formatting_context
{
+ class cleanup_guard
+ {
+ private:
+ formatting_context& m_context;
+
+ public:
+ explicit cleanup_guard(formatting_context& ctx) BOOST_NOEXCEPT : m_context(ctx)
+ {
+ }
+
+ ~cleanup_guard()
+ {
+ m_context.m_FormattedRecord.clear();
+ m_context.m_FormattingStream.rdbuf()->max_size(m_context.m_FormattedRecord.max_size());
+ m_context.m_FormattingStream.rdbuf()->storage_overflow(false);
+ m_context.m_FormattingStream.clear();
+ }
+
+ BOOST_DELETED_FUNCTION(cleanup_guard(cleanup_guard const&))
+ BOOST_DELETED_FUNCTION(cleanup_guard& operator=(cleanup_guard const&))
+ };
+
#if !defined(BOOST_LOG_NO_THREADS)
//! Object version
const unsigned int m_Version;
@@ -431,8 +450,7 @@ protected:
context = &m_Context;
#endif
- boost::log::aux::cleanup_guard< stream_type > cleanup1(context->m_FormattingStream);
- boost::log::aux::cleanup_guard< string_type > cleanup2(context->m_FormattedRecord);
+ typename formatting_context::cleanup_guard cleanup(*context);
try
{
@@ -464,13 +482,10 @@ protected:
bool try_feed_record(record_view const& rec, BackendMutexT& backend_mutex, BackendT& backend)
{
#if !defined(BOOST_LOG_NO_THREADS)
- unique_lock< BackendMutexT > lock;
try
{
- unique_lock< BackendMutexT > tmp_lock(backend_mutex, try_to_lock);
- if (!tmp_lock.owns_lock())
+ if (!backend_mutex.try_lock())
return false;
- lock.swap(tmp_lock);
}
catch (thread_interrupted&)
{
@@ -484,6 +499,8 @@ protected:
this->exception_handler()();
return false;
}
+
+ boost::log::aux::exclusive_auto_unlocker< BackendMutexT > unlocker(backend_mutex);
#endif
// No need to lock anything in the feed_record method
boost::log::aux::fake_mutex m;
diff --git a/boost/log/sinks/sync_frontend.hpp b/boost/log/sinks/sync_frontend.hpp
index 6d3a57f4ee..6a927d0571 100644
--- a/boost/log/sinks/sync_frontend.hpp
+++ b/boost/log/sinks/sync_frontend.hpp
@@ -28,6 +28,8 @@
#include <boost/static_assert.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
+#include <boost/preprocessor/control/if.hpp>
+#include <boost/preprocessor/comparison/equal.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include <boost/log/detail/locking_ptr.hpp>
#include <boost/log/detail/parameter_tools.hpp>
@@ -44,12 +46,21 @@ namespace sinks {
#ifndef BOOST_LOG_DOXYGEN_PASS
-#define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL(z, n, data)\
+#define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_1(n, data)\
+ template< typename T0 >\
+ explicit synchronous_sink(T0 const& arg0, typename boost::log::aux::enable_if_named_parameters< T0, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :\
+ base_type(false),\
+ m_pBackend(boost::make_shared< sink_backend_type >(arg0)) {}
+
+#define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_N(n, data)\
template< BOOST_PP_ENUM_PARAMS(n, typename T) >\
explicit synchronous_sink(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg)) :\
base_type(false),\
m_pBackend(boost::make_shared< sink_backend_type >(BOOST_PP_ENUM_PARAMS(n, arg))) {}
+#define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL(z, n, data)\
+ BOOST_PP_IF(BOOST_PP_EQUAL(n, 1), BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_1, BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_N)(n, data)
+
#endif // BOOST_LOG_DOXYGEN_PASS
/*!
@@ -115,8 +126,16 @@ public:
{
}
- // Constructors that pass arbitrary parameters to the backend constructor
+ /*!
+ * Constructor that passes arbitrary named parameters to the interprocess sink backend constructor.
+ * Refer to the backend documentation for the list of supported parameters.
+ */
+#ifndef BOOST_LOG_DOXYGEN_PASS
BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL, ~)
+#else
+ template< typename... Args >
+ explicit synchronous_sink(Args&&... args);
+#endif
/*!
* Locking accessor to the attached backend
@@ -153,6 +172,8 @@ public:
}
};
+#undef BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_1
+#undef BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_N
#undef BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL
} // namespace sinks
diff --git a/boost/log/sinks/text_ipc_message_queue_backend.hpp b/boost/log/sinks/text_ipc_message_queue_backend.hpp
new file mode 100644
index 0000000000..370ccfb32f
--- /dev/null
+++ b/boost/log/sinks/text_ipc_message_queue_backend.hpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright Lingxi Li 2015.
+ * Copyright Andrey Semashev 2016.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file text_ipc_message_queue_backend.hpp
+ * \author Lingxi Li
+ * \author Andrey Semashev
+ * \date 14.10.2015
+ *
+ * The header contains implementation of a text interprocess message queue sink
+ * backend along with implementation of a supporting interprocess message queue.
+ */
+
+#ifndef BOOST_LOG_SINKS_TEXT_IPC_MESSAGE_QUEUE_BACKEND_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_TEXT_IPC_MESSAGE_QUEUE_BACKEND_HPP_INCLUDED_
+
+#include <limits>
+#include <string>
+#include <boost/cstdint.hpp>
+#include <boost/move/core.hpp>
+#include <boost/preprocessor/control/if.hpp>
+#include <boost/preprocessor/comparison/equal.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/parameter_tools.hpp>
+#include <boost/log/core/record_view.hpp>
+#include <boost/log/sinks/basic_sink_backend.hpp>
+#include <boost/log/sinks/frontend_requirements.hpp>
+#include <boost/log/exceptions.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+#ifndef BOOST_LOG_DOXYGEN_PASS
+
+#define BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL_1(n, data)\
+ template< typename T0 >\
+ explicit text_ipc_message_queue_backend(T0 const& arg0, typename boost::log::aux::enable_if_named_parameters< T0, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :\
+ m_queue(arg0) {}
+
+#define BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL_N(n, data)\
+ template< BOOST_PP_ENUM_PARAMS(n, typename T) >\
+ explicit text_ipc_message_queue_backend(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg)) :\
+ m_queue(BOOST_PP_ENUM_PARAMS(n, arg)) {}
+
+#define BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL(z, n, data)\
+ BOOST_PP_IF(BOOST_PP_EQUAL(n, 1), BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL_1, BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL_N)(n, data)
+
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+/*!
+ * \brief An implementation of a text interprocess message queue sink backend and
+ * a supporting interprocess message queue.
+ *
+ * The sink backend sends formatted log messages to an interprocess message queue
+ * which can be extracted by a viewer process. Methods of this class are not
+ * thread-safe, unless otherwise specified.
+ */
+template< typename QueueT >
+class text_ipc_message_queue_backend :
+ public basic_formatted_sink_backend< char, concurrent_feeding >
+{
+ //! Base type
+ typedef basic_formatted_sink_backend< char, concurrent_feeding > base_type;
+
+public:
+ //! Character type
+ typedef base_type::char_type char_type;
+ //! String type to be used as a message text holder
+ typedef base_type::string_type string_type;
+ //! Interprocess message queue type
+ typedef QueueT queue_type;
+
+private:
+ //! Interprocess queue
+ queue_type m_queue;
+
+public:
+ /*!
+ * Default constructor. The method constructs the backend using the default-constructed
+ * interprocess message queue. The queue may need additional setup in order to be able
+ * to send messages.
+ */
+ text_ipc_message_queue_backend() BOOST_NOEXCEPT
+ {
+ }
+
+ /*!
+ * Initializing constructor. The method constructs the backend using the provided
+ * interprocess message queue. The constructor moves from the provided queue.
+ */
+ explicit text_ipc_message_queue_backend(BOOST_RV_REF(queue_type) queue) BOOST_NOEXCEPT :
+ m_queue(static_cast< BOOST_RV_REF(queue_type) >(queue))
+ {
+ }
+
+ /*!
+ * Constructor that passes arbitrary named parameters to the interprocess queue constructor.
+ * Refer to the queue documentation for the list of supported parameters.
+ */
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL, ~)
+#else
+ template< typename... Args >
+ explicit text_ipc_message_queue_backend(Args&&... args);
+#endif
+
+ /*!
+ * The method returns a reference to the managed \c queue_type object.
+ *
+ * \return A reference to the managed \c queue_type object.
+ */
+ queue_type& message_queue() BOOST_NOEXCEPT { return m_queue; }
+
+ /*!
+ * The method returns a constant reference to the managed \c queue_type object.
+ *
+ * \return A constant reference to the managed \c queue_type object.
+ */
+ queue_type const& message_queue() const BOOST_NOEXCEPT { return m_queue; }
+
+ /*!
+ * Tests whether the object is associated with any message queue. Only when the backend has
+ * an associated message queue, will any message be sent.
+ *
+ * \return \c true if the object is associated with a message queue, and \c false otherwise.
+ */
+ bool is_open() const BOOST_NOEXCEPT { return m_queue.is_open(); }
+
+ /*!
+ * The method writes the message to the backend. Concurrent calls to this method
+ * are allowed. Therefore, the backend may be used with unlocked frontend. <tt>stop_local()</tt>
+ * can be used to have a blocked <tt>consume()</tt> call return and prevent future
+ * calls to <tt>consume()</tt> from blocking.
+ */
+ void consume(record_view const&, string_type const& formatted_message)
+ {
+ if (m_queue.is_open())
+ {
+ typedef typename queue_type::size_type size_type;
+ const string_type::size_type size = formatted_message.size();
+ if (BOOST_UNLIKELY(size > static_cast< string_type::size_type >((std::numeric_limits< size_type >::max)())))
+ BOOST_LOG_THROW_DESCR(limitation_error, "Message too long to send to an interprocess queue");
+ m_queue.send(formatted_message.data(), static_cast< size_type >(size));
+ }
+ }
+};
+
+#undef BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL_1
+#undef BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL_N
+#undef BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SINKS_TEXT_IPC_MESSAGE_QUEUE_BACKEND_HPP_INCLUDED_
diff --git a/boost/log/sinks/text_multifile_backend.hpp b/boost/log/sinks/text_multifile_backend.hpp
index 82c18bf4d9..8e707b990c 100644
--- a/boost/log/sinks/text_multifile_backend.hpp
+++ b/boost/log/sinks/text_multifile_backend.hpp
@@ -113,6 +113,9 @@ namespace file {
/*!
* The function adopts a log record formatter into a file name generator
+ *
+ * \param fmt The formatter function object to adopt
+ * \param loc The locale to use to character code conversion and formatting
*/
template< typename FormatterT >
inline file_name_composer_adapter< FormatterT > as_file_name_composer(
diff --git a/boost/log/sinks/unlocked_frontend.hpp b/boost/log/sinks/unlocked_frontend.hpp
index b7b0d353c4..918efeb6d2 100644
--- a/boost/log/sinks/unlocked_frontend.hpp
+++ b/boost/log/sinks/unlocked_frontend.hpp
@@ -18,6 +18,8 @@
#include <boost/static_assert.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
+#include <boost/preprocessor/control/if.hpp>
+#include <boost/preprocessor/comparison/equal.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/parameter_tools.hpp>
#include <boost/log/detail/fake_mutex.hpp>
@@ -37,12 +39,21 @@ namespace sinks {
#ifndef BOOST_LOG_DOXYGEN_PASS
-#define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL(z, n, types)\
+#define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_1(n, data)\
+ template< typename T0 >\
+ explicit unlocked_sink(T0 const& arg0, typename boost::log::aux::enable_if_named_parameters< T0, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :\
+ base_type(false),\
+ m_pBackend(boost::make_shared< sink_backend_type >(arg0)) {}
+
+#define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_N(n, data)\
template< BOOST_PP_ENUM_PARAMS(n, typename T) >\
explicit unlocked_sink(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg)) :\
base_type(false),\
m_pBackend(boost::make_shared< sink_backend_type >(BOOST_PP_ENUM_PARAMS(n, arg))) {}
+#define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL(z, n, data)\
+ BOOST_PP_IF(BOOST_PP_EQUAL(n, 1), BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_1, BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_N)(n, data)
+
#endif // BOOST_LOG_DOXYGEN_PASS
/*!
@@ -94,8 +105,16 @@ public:
{
}
- // Constructors that pass arbitrary parameters to the backend constructor
+ /*!
+ * Constructor that passes arbitrary named parameters to the interprocess sink backend constructor.
+ * Refer to the backend documentation for the list of supported parameters.
+ */
+#ifndef BOOST_LOG_DOXYGEN_PASS
BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL, ~)
+#else
+ template< typename... Args >
+ explicit unlocked_sink(Args&&... args);
+#endif
/*!
* Locking accessor to the attached backend.
@@ -129,6 +148,8 @@ public:
}
};
+#undef BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_1
+#undef BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_N
#undef BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL
} // namespace sinks
diff --git a/boost/log/sources/basic_logger.hpp b/boost/log/sources/basic_logger.hpp
index bc35acf3a8..58bd6594c5 100644
--- a/boost/log/sources/basic_logger.hpp
+++ b/boost/log/sources/basic_logger.hpp
@@ -21,8 +21,8 @@
#include <ostream>
#include <boost/assert.hpp>
#include <boost/move/core.hpp>
-#include <boost/move/utility.hpp>
-#include <boost/utility/addressof.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/core/addressof.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
#include <boost/preprocessor/facilities/identity.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
diff --git a/boost/log/sources/channel_feature.hpp b/boost/log/sources/channel_feature.hpp
index aa0349010c..d7e88c4aad 100644
--- a/boost/log/sources/channel_feature.hpp
+++ b/boost/log/sources/channel_feature.hpp
@@ -17,7 +17,7 @@
#include <string>
#include <boost/move/core.hpp>
-#include <boost/move/utility.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/locks.hpp>
#include <boost/log/detail/default_attribute_names.hpp>
diff --git a/boost/log/sources/exception_handler_feature.hpp b/boost/log/sources/exception_handler_feature.hpp
index bd77fca528..d29041109d 100644
--- a/boost/log/sources/exception_handler_feature.hpp
+++ b/boost/log/sources/exception_handler_feature.hpp
@@ -17,7 +17,7 @@
#include <boost/mpl/if.hpp>
#include <boost/move/core.hpp>
-#include <boost/move/utility.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/light_function.hpp>
diff --git a/boost/log/sources/global_logger_storage.hpp b/boost/log/sources/global_logger_storage.hpp
index a98e5e63e1..dad41a128c 100644
--- a/boost/log/sources/global_logger_storage.hpp
+++ b/boost/log/sources/global_logger_storage.hpp
@@ -37,7 +37,7 @@ namespace sources {
namespace aux {
//! The base class for logger holders
-struct BOOST_LOG_NO_VTABLE BOOST_SYMBOL_VISIBLE logger_holder_base
+struct logger_holder_base
{
//! The source file name where the logger was registered
const char* const m_RegistrationFile;
@@ -52,12 +52,11 @@ struct BOOST_LOG_NO_VTABLE BOOST_SYMBOL_VISIBLE logger_holder_base
m_LoggerType(logger_type)
{
}
- virtual ~logger_holder_base() {}
};
//! The actual logger holder class
template< typename LoggerT >
-struct BOOST_SYMBOL_VISIBLE logger_holder :
+struct logger_holder :
public logger_holder_base
{
//! The logger instance
@@ -68,6 +67,14 @@ struct BOOST_SYMBOL_VISIBLE logger_holder :
m_Logger(logger)
{
}
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ logger_holder(const char* file, unsigned int line, LoggerT&& logger) :
+ logger_holder_base(file, line, typeindex::type_id< LoggerT >()),
+ m_Logger(static_cast< LoggerT&& >(logger))
+ {
+ }
+#endif
};
//! The class implements a global repository of tagged loggers
@@ -122,8 +129,8 @@ struct logger_singleton :
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 was initialized in a different DSO than where it's being queried). logger_holder visibility doesn't
+ // have effect since it is inhibited by the template parameter visibility.
instance = boost::static_pointer_cast< logger_holder< logger_type > >(holder);
}
else
@@ -133,7 +140,7 @@ struct logger_singleton :
// 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(tag_type_index, logger_type_index, *holder);
+ boost::log::sources::aux::throw_odr_violation(tag_type_index, logger_type_index, *holder);
}
}
diff --git a/boost/log/sources/record_ostream.hpp b/boost/log/sources/record_ostream.hpp
index c1e80593aa..5fac8742b7 100644
--- a/boost/log/sources/record_ostream.hpp
+++ b/boost/log/sources/record_ostream.hpp
@@ -20,8 +20,8 @@
#include <ostream>
#include <boost/assert.hpp>
#include <boost/move/core.hpp>
-#include <boost/move/utility.hpp>
-#include <boost/utility/addressof.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/core/addressof.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/native_typeof.hpp>
#include <boost/log/detail/unhandled_exception_count.hpp>
diff --git a/boost/log/sources/severity_feature.hpp b/boost/log/sources/severity_feature.hpp
index 6ecf95e551..101769bda1 100644
--- a/boost/log/sources/severity_feature.hpp
+++ b/boost/log/sources/severity_feature.hpp
@@ -19,7 +19,7 @@
#include <boost/static_assert.hpp>
#include <boost/smart_ptr/intrusive_ptr.hpp>
#include <boost/move/core.hpp>
-#include <boost/move/utility.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/locks.hpp>
#include <boost/log/detail/default_attribute_names.hpp>
diff --git a/boost/log/support/date_time.hpp b/boost/log/support/date_time.hpp
index e1c9050adb..468f02fa40 100644
--- a/boost/log/support/date_time.hpp
+++ b/boost/log/support/date_time.hpp
@@ -22,7 +22,7 @@
#include <iterator>
#include <boost/cstdint.hpp>
#include <boost/move/core.hpp>
-#include <boost/move/utility.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/date_time/time.hpp>
#include <boost/date_time/date.hpp>
#include <boost/date_time/gregorian/gregorian_types.hpp>
diff --git a/boost/log/support/exception.hpp b/boost/log/support/exception.hpp
index f6d9be20d5..160521d3c9 100644
--- a/boost/log/support/exception.hpp
+++ b/boost/log/support/exception.hpp
@@ -15,6 +15,7 @@
#ifndef BOOST_LOG_SUPPORT_EXCEPTION_HPP_INCLUDED_
#define BOOST_LOG_SUPPORT_EXCEPTION_HPP_INCLUDED_
+#include <string>
#include <boost/type_index.hpp>
#include <boost/exception/info.hpp>
#include <boost/log/detail/config.hpp>
@@ -63,6 +64,17 @@ inline current_scope_info current_scope()
return current_scope_info(attributes::named_scope::get_scopes());
}
+namespace ipc {
+
+class object_name;
+
+/*!
+ * System resource name
+ */
+typedef error_info< struct object_name_tag, object_name > object_name_info;
+
+} // namespace ipc
+
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
diff --git a/boost/log/support/spirit_classic.hpp b/boost/log/support/spirit_classic.hpp
index 36a680ac6f..5f117388d8 100644
--- a/boost/log/support/spirit_classic.hpp
+++ b/boost/log/support/spirit_classic.hpp
@@ -16,7 +16,7 @@
#define BOOST_LOG_SUPPORT_SPIRIT_CLASSIC_HPP_INCLUDED_
#include <boost/mpl/bool.hpp>
-#include <boost/utility/enable_if.hpp>
+#include <boost/core/enable_if.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/utility/functional/matches.hpp>
diff --git a/boost/log/support/spirit_qi.hpp b/boost/log/support/spirit_qi.hpp
index 027552670a..e335d1ae55 100644
--- a/boost/log/support/spirit_qi.hpp
+++ b/boost/log/support/spirit_qi.hpp
@@ -15,7 +15,7 @@
#ifndef BOOST_LOG_SUPPORT_SPIRIT_QI_HPP_INCLUDED_
#define BOOST_LOG_SUPPORT_SPIRIT_QI_HPP_INCLUDED_
-#include <boost/utility/enable_if.hpp>
+#include <boost/core/enable_if.hpp>
#include <boost/spirit/include/qi_parse.hpp>
#include <boost/spirit/include/qi_domain.hpp>
#include <boost/spirit/include/support_unused.hpp>
@@ -40,7 +40,7 @@ struct boost_spirit_qi_expression_tag;
//! The metafunction detects the matching expression kind and returns a tag that is used to specialize \c match_traits
template< typename ExpressionT >
-struct matching_expression_kind< ExpressionT, typename boost::enable_if< spirit::traits::matches< spirit::qi::domain, ExpressionT > >::type >
+struct matching_expression_kind< ExpressionT, typename boost::enable_if_c< spirit::traits::matches< spirit::qi::domain, ExpressionT >::value >::type >
{
typedef boost_spirit_qi_expression_tag type;
};
diff --git a/boost/log/utility/exception_handler.hpp b/boost/log/utility/exception_handler.hpp
index 6b369704d1..9b8551ac0d 100644
--- a/boost/log/utility/exception_handler.hpp
+++ b/boost/log/utility/exception_handler.hpp
@@ -22,10 +22,10 @@
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/has_xxx.hpp>
#include <boost/mpl/vector.hpp>
+#include <boost/core/enable_if.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
-#include <boost/utility/enable_if.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/utility/functional/nop.hpp>
#include <boost/log/detail/header.hpp>
@@ -228,8 +228,8 @@ inline nop make_exception_suppressor()
#ifndef BOOST_LOG_DOXYGEN_PASS
template< typename HandlerT >
-inline typename lazy_enable_if<
- aux::has_exception_types< HandlerT >,
+inline typename boost::lazy_enable_if_c<
+ aux::has_exception_types< HandlerT >::value,
aux::make_self_contained_exception_handler< exception_handler, HandlerT >
>::type make_exception_handler(HandlerT const& handler)
{
@@ -238,8 +238,8 @@ inline typename lazy_enable_if<
}
template< typename HandlerT >
-inline typename lazy_enable_if<
- aux::has_exception_types< HandlerT >,
+inline typename boost::lazy_enable_if_c<
+ aux::has_exception_types< HandlerT >::value,
aux::make_self_contained_exception_handler< nothrow_exception_handler, HandlerT >
>::type make_exception_handler(HandlerT const& handler, std::nothrow_t const&)
{
diff --git a/boost/log/utility/formatting_ostream.hpp b/boost/log/utility/formatting_ostream.hpp
index d3732d36f4..4a79998b1c 100644
--- a/boost/log/utility/formatting_ostream.hpp
+++ b/boost/log/utility/formatting_ostream.hpp
@@ -245,7 +245,7 @@ public:
*/
string_type const& str() const
{
- string_type* storage = m_streambuf.storage();
+ string_type* const storage = m_streambuf.storage();
BOOST_ASSERT(storage != NULL);
m_streambuf.pubsync();
@@ -372,8 +372,12 @@ public:
{
m_stream.flush();
- string_type* storage = m_streambuf.storage();
- aux::code_convert(p, static_cast< std::size_t >(size), *storage, m_stream.getloc());
+ if (!m_streambuf.storage_overflow())
+ {
+ string_type* storage = m_streambuf.storage();
+ if (!aux::code_convert(p, static_cast< std::size_t >(size), *storage, m_streambuf.max_size(), m_stream.getloc()))
+ m_streambuf.storage_overflow(true);
+ }
}
return *this;
@@ -643,9 +647,10 @@ public:
}
#endif
-private:
+protected:
void init_stream()
{
+ m_stream.exceptions(ostream_type::goodbit);
m_stream.clear(m_streambuf.storage() ? ostream_type::goodbit : ostream_type::badbit);
m_stream.flags
(
@@ -658,6 +663,7 @@ private:
m_stream.fill(static_cast< char_type >(' '));
}
+private:
basic_formatting_ostream& formatted_write(const char_type* p, std::streamsize size)
{
sentry guard(*this);
@@ -666,7 +672,7 @@ private:
m_stream.flush();
if (m_stream.width() <= size)
- m_streambuf.storage()->append(p, static_cast< std::size_t >(size));
+ m_streambuf.append(p, static_cast< std::size_t >(size));
else
this->aligned_write(p, size);
@@ -685,7 +691,13 @@ private:
m_stream.flush();
if (m_stream.width() <= size)
- aux::code_convert(p, static_cast< std::size_t >(size), *m_streambuf.storage(), m_stream.getloc());
+ {
+ if (!m_streambuf.storage_overflow())
+ {
+ if (!aux::code_convert(p, static_cast< std::size_t >(size), *m_streambuf.storage(), m_streambuf.max_size(), m_stream.getloc()))
+ m_streambuf.storage_overflow(true);
+ }
+ }
else
this->aligned_write(p, size);
@@ -780,19 +792,18 @@ BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, Allo
template< typename CharT, typename TraitsT, typename AllocatorT >
void basic_formatting_ostream< CharT, TraitsT, AllocatorT >::aligned_write(const char_type* p, std::streamsize size)
{
- string_type* const storage = m_streambuf.storage();
typename string_type::size_type const alignment_size =
static_cast< typename string_type::size_type >(m_stream.width() - size);
const bool align_left = (m_stream.flags() & ostream_type::adjustfield) == ostream_type::left;
if (align_left)
{
- storage->append(p, static_cast< std::size_t >(size));
- storage->append(alignment_size, m_stream.fill());
+ m_streambuf.append(p, static_cast< std::size_t >(size));
+ m_streambuf.append(alignment_size, m_stream.fill());
}
else
{
- storage->append(alignment_size, m_stream.fill());
- storage->append(p, static_cast< std::size_t >(size));
+ m_streambuf.append(alignment_size, m_stream.fill());
+ m_streambuf.append(p, static_cast< std::size_t >(size));
}
}
@@ -806,13 +817,21 @@ void basic_formatting_ostream< CharT, TraitsT, AllocatorT >::aligned_write(const
const bool align_left = (m_stream.flags() & ostream_type::adjustfield) == ostream_type::left;
if (align_left)
{
- aux::code_convert(p, static_cast< std::size_t >(size), *storage, m_stream.getloc());
- storage->append(alignment_size, m_stream.fill());
+ if (!m_streambuf.storage_overflow())
+ {
+ if (!aux::code_convert(p, static_cast< std::size_t >(size), *storage, m_streambuf.max_size(), m_stream.getloc()))
+ m_streambuf.storage_overflow(true);
+ }
+ m_streambuf.append(alignment_size, m_stream.fill());
}
else
{
- storage->append(alignment_size, m_stream.fill());
- aux::code_convert(p, static_cast< std::size_t >(size), *storage, m_stream.getloc());
+ m_streambuf.append(alignment_size, m_stream.fill());
+ if (!m_streambuf.storage_overflow())
+ {
+ if (!aux::code_convert(p, static_cast< std::size_t >(size), *storage, m_streambuf.max_size(), m_stream.getloc()))
+ m_streambuf.storage_overflow(true);
+ }
}
}
diff --git a/boost/log/utility/ipc/object_name.hpp b/boost/log/utility/ipc/object_name.hpp
new file mode 100644
index 0000000000..582ecdcbf3
--- /dev/null
+++ b/boost/log/utility/ipc/object_name.hpp
@@ -0,0 +1,271 @@
+/*
+ * Copyright Andrey Semashev 2016.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file utility/ipc/object_name.hpp
+ * \author Andrey Semashev
+ * \date 05.03.2016
+ *
+ * The header contains declaration of a system object name wrapper.
+ */
+
+#ifndef BOOST_LOG_UTILITY_IPC_OBJECT_NAME_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_IPC_OBJECT_NAME_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <cstddef>
+#include <iosfwd>
+#include <string>
+#include <boost/move/core.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace ipc {
+
+/*!
+ * \brief A system object name class
+ *
+ * In order to identify a system-wide object such as a shared memory segment or a named synchronization primitive the object has to be given a name.
+ * The format of the name is specific to the operating system and the \c object_name class provides an abstraction for names of objects. It also
+ * provides means for scoping, which allows to avoid name clashes between different processes.
+ *
+ * The object name is a UTF-8 encoded string. The portable object name should consist of the following characters:
+ *
+ * <pre>
+ * A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
+ * a b c d e f g h i j k l m n o p q r s t u v w x y z
+ * 0 1 2 3 4 5 6 7 8 9 . _ -
+ * </pre>
+ *
+ * \note The character set corresponds to the POSIX Portable Filename Character Set (http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_278).
+ *
+ * Use of other characters may result in non-portable system-specific behavior.
+ *
+ * The name can have one of the following scopes:
+ *
+ * \li \c global - objects within this scope are visible to any process on the system. In order to use this scope the process may need to have
+ * extended privileges. This scope is not available for Windows Store applications.
+ * \li \c user - objects within this scope can be opened by processes running under the same user as the current process.
+ * \li \c session - objects within this scope are visible to processes within the session of the current process. The definition of a session may vary between
+ * operating systems. On POSIX, a session is typically a group of processes attached to a single virtual terminal device. On Windows a session is
+ * started when a user logs into the system. There is also a separate session for Windows services.
+ * \li \c process_group - objects within this scope are visible to processes within the process group of the current process. Currently, on Windows all processes
+ * running in the current session are considered members of the same process group. This may change in future.
+ *
+ * The scopes are not overlapping. For instance, if an object is created in the global scope, the object cannot be opened with the same name but in user's scope.
+ *
+ * Note that name scoping is not a security feature. On some systems any process on the system has technical capability to open objects within any scope.
+ * The scope is only used to help avoid name clashes between processes using \c object_name to identify objects.
+ */
+class object_name
+{
+public:
+ //! Name scopes
+ enum scope
+ {
+ global, //!< The name has global scope; any process in the system has the potential to open the resource identified by the name
+ user, //!< The name is limited to processes running under the current user
+ session, //!< The name is limited to processes running in the current login session
+ process_group //!< The name is limited to processes running in the current process group
+ };
+
+#if !defined(BOOST_LOG_DOXYGEN_PASS)
+
+ BOOST_COPYABLE_AND_MOVABLE(object_name)
+
+private:
+ std::string m_name;
+
+#endif // !defined(BOOST_LOG_DOXYGEN_PASS)
+
+public:
+ /*!
+ * Default constructor. The method creates an empty object name.
+ *
+ * \post <tt>empty() == true</tt>
+ */
+ object_name() BOOST_NOEXCEPT
+ {
+ }
+
+ /*!
+ * Move constructor.
+ */
+ object_name(BOOST_RV_REF(object_name) that) BOOST_NOEXCEPT
+ {
+ m_name.swap(that.m_name);
+ }
+
+ /*!
+ * Copy constructor.
+ */
+ object_name(object_name const& that) : m_name(that.m_name)
+ {
+ }
+
+ /*!
+ * Constructor from the native string.
+ *
+ * \param str The object name string, must not be \c NULL. The string format is specific to the operating system.
+ */
+ static object_name from_native(const char* str)
+ {
+ object_name name;
+ name.m_name = str;
+ return name;
+ }
+
+ /*!
+ * Constructor from the native string.
+ *
+ * \param str The object name string. The string format is specific to the operating system.
+ */
+ static object_name from_native(std::string const& str)
+ {
+ object_name name;
+ name.m_name = str;
+ return name;
+ }
+
+ /*!
+ * Constructor from the object name
+ * \param ns The scope of the object name
+ * \param str The object name, must not be NULL.
+ */
+ BOOST_LOG_API object_name(scope ns, const char* str);
+
+ /*!
+ * Constructor from the object name
+ * \param ns The scope of the object name
+ * \param str The object name
+ */
+ BOOST_LOG_API object_name(scope ns, std::string const& str);
+
+ /*!
+ * Move assignment
+ */
+ object_name& operator= (BOOST_RV_REF(object_name) that) BOOST_NOEXCEPT
+ {
+ m_name.clear();
+ m_name.swap(that.m_name);
+ return *this;
+ }
+
+ /*!
+ * Copy assignment
+ */
+ object_name& operator= (BOOST_COPY_ASSIGN_REF(object_name) that)
+ {
+ m_name = that.m_name;
+ return *this;
+ }
+
+ /*!
+ * Returns \c true if the object name is empty
+ */
+ bool empty() const BOOST_NOEXCEPT { return m_name.empty(); }
+
+ /*!
+ * Returns length of the name, in bytes
+ */
+ std::size_t size() const BOOST_NOEXCEPT { return m_name.size(); }
+
+ /*!
+ * Returns the name string
+ */
+ const char* c_str() const BOOST_NOEXCEPT { return m_name.c_str(); }
+
+ /*!
+ * Swaps the object name with another object name
+ */
+ void swap(object_name& that) BOOST_NOEXCEPT { m_name.swap(that.m_name); }
+
+ /*!
+ * Swaps two object names
+ */
+ friend void swap(object_name& left, object_name& right) BOOST_NOEXCEPT
+ {
+ left.swap(right);
+ }
+
+ /*!
+ * Returns string representation of the object name
+ */
+ friend std::string to_string(object_name const& name)
+ {
+ return name.m_name;
+ }
+
+ /*!
+ * Equality operator
+ */
+ friend bool operator== (object_name const& left, object_name const& right) BOOST_NOEXCEPT
+ {
+ return left.m_name == right.m_name;
+ }
+ /*!
+ * Inequality operator
+ */
+ friend bool operator!= (object_name const& left, object_name const& right) BOOST_NOEXCEPT
+ {
+ return left.m_name != right.m_name;
+ }
+ /*!
+ * Less operator
+ */
+ friend bool operator< (object_name const& left, object_name const& right) BOOST_NOEXCEPT
+ {
+ return left.m_name < right.m_name;
+ }
+ /*!
+ * Greater operator
+ */
+ friend bool operator> (object_name const& left, object_name const& right) BOOST_NOEXCEPT
+ {
+ return left.m_name > right.m_name;
+ }
+ /*!
+ * Less or equal operator
+ */
+ friend bool operator<= (object_name const& left, object_name const& right) BOOST_NOEXCEPT
+ {
+ return left.m_name <= right.m_name;
+ }
+ /*!
+ * Greater or equal operator
+ */
+ friend bool operator>= (object_name const& left, object_name const& right) BOOST_NOEXCEPT
+ {
+ return left.m_name >= right.m_name;
+ }
+
+ /*!
+ * Stream ouput operator
+ */
+ template< typename CharT, typename TraitsT >
+ friend std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, object_name const& name)
+ {
+ strm << name.c_str();
+ return strm;
+ }
+};
+
+} // namespace ipc
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_IPC_OBJECT_NAME_HPP_INCLUDED_
diff --git a/boost/log/utility/ipc/reliable_message_queue.hpp b/boost/log/utility/ipc/reliable_message_queue.hpp
new file mode 100644
index 0000000000..934d6ab299
--- /dev/null
+++ b/boost/log/utility/ipc/reliable_message_queue.hpp
@@ -0,0 +1,776 @@
+/*
+ * Copyright Lingxi Li 2015.
+ * Copyright Andrey Semashev 2016.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file utility/ipc/reliable_message_queue.hpp
+ * \author Lingxi Li
+ * \author Andrey Semashev
+ * \date 01.01.2016
+ *
+ * The header contains declaration of a reliable interprocess message queue.
+ */
+
+#ifndef BOOST_LOG_UTILITY_IPC_RELIABLE_MESSAGE_QUEUE_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_IPC_RELIABLE_MESSAGE_QUEUE_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <cstddef>
+#include <boost/cstdint.hpp>
+#include <boost/move/core.hpp>
+#include <boost/log/keywords/open_mode.hpp>
+#include <boost/log/keywords/name.hpp>
+#include <boost/log/keywords/capacity.hpp>
+#include <boost/log/keywords/block_size.hpp>
+#include <boost/log/keywords/overflow_policy.hpp>
+#include <boost/log/keywords/permissions.hpp>
+#include <boost/log/utility/open_mode.hpp>
+#include <boost/log/utility/permissions.hpp>
+#include <boost/log/utility/ipc/object_name.hpp>
+#include <boost/log/detail/parameter_tools.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace ipc {
+
+namespace aux {
+
+template< typename T, typename R >
+struct enable_if_byte {};
+template< typename R >
+struct enable_if_byte< char, R > { typedef R type; };
+template< typename R >
+struct enable_if_byte< signed char, R > { typedef R type; };
+template< typename R >
+struct enable_if_byte< unsigned char, R > { typedef R type; };
+
+} // namespace aux
+
+/*!
+ * \brief A reliable interprocess message queue
+ *
+ * The queue implements a reliable one-way channel of passing messages from one or multiple writers to a single reader.
+ * The format of the messages is user-defined and must be consistent across all writers and the reader. The queue does
+ * not enforce any specific format of the messages, other than they should be supplied as a contiguous array of bytes.
+ *
+ * The queue internally uses a process-shared storage identified by an \c object_name (the queue name). Refer to \c object_name
+ * documentation for details on restrictions imposed on object names.
+ *
+ * The queue storage is organized as a fixed number of blocks of a fixed size. The block size must be an integer power of 2 and
+ * is expressed in bytes. Each written message, together with some metadata added by the queue, consumes an integer number
+ * of blocks. Each read message received by the reader releases the blocks allocated for that message. As such the maximum size
+ * of a message is slightly less than block size times capacity of the queue. For efficiency, it is recommended to choose
+ * block size large enough to accommodate most of the messages to be passed through the queue.
+ *
+ * The queue is considered empty when no messages are enqueued (all blocks are free). The queue is considered full at the point
+ * of enqueueing a message when there is not enough free blocks to accommodate the message.
+ *
+ * The queue is reliable in that it will not drop successfully sent messages that are not received by the reader, other than the
+ * case when a non-empty queue is destroyed by the last user. If a message cannot be enqueued by the writer because the queue is
+ * full, the queue can either block the writer or return an error or throw an exception, depending on the policy specified at
+ * the queue creation. The policy is object local, i.e. different writers and the reader can have different overflow policies.
+ *
+ * If the queue is empty and the reader attempts to dequeue a message, it will block until a message is enqueued by a writer.
+ *
+ * A blocked reader or writer can be unblocked by calling \c stop_local. After this method is called, all threads blocked on
+ * this particular object are released and return \c operation_result::aborted. The other instances of the queue (in the current
+ * or other processes) are unaffected. In order to restore the normal functioning of the queue instance after the \c stop_local
+ * call the user has to invoke \c reset_local.
+ *
+ * The queue does not guarantee any particular order of received messages from different writer threads. Messages sent by a
+ * particular writer thread will be received in the order of sending.
+ *
+ * Methods of this class are not thread-safe, unless otherwise specified.
+ */
+class reliable_message_queue
+{
+public:
+ //! Result codes for various operations on the queue
+ enum operation_result
+ {
+ succeeded, //!< The operation has completed successfully
+ no_space, //!< The message could not be sent because the queue is full
+ aborted //!< The operation has been aborted because the queue method <tt>stop_local()</tt> has been called
+ };
+
+ //! Interprocess queue overflow policies
+ enum overflow_policy
+ {
+ //! Block the send operation when the queue is full
+ block_on_overflow,
+ //! Return \c operation_result::no_space when the queue is full
+ fail_on_overflow,
+ //! Throw \c capacity_limit_reached exception when the queue is full
+ throw_on_overflow
+ };
+
+ //! Queue message size type
+ typedef uint32_t size_type;
+
+#if !defined(BOOST_LOG_DOXYGEN_PASS)
+
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(reliable_message_queue)
+
+private:
+ typedef void (*receive_handler)(void* state, const void* data, size_type size);
+
+ struct fixed_buffer_state
+ {
+ uint8_t* data;
+ size_type size;
+ };
+
+ struct implementation;
+ implementation* m_impl;
+
+#endif // !defined(BOOST_LOG_DOXYGEN_PASS)
+
+public:
+ /*!
+ * Default constructor. The method constructs an object that is not associated with any
+ * message queue.
+ *
+ * \post <tt>is_open() == false</tt>
+ */
+ BOOST_CONSTEXPR reliable_message_queue() BOOST_NOEXCEPT : m_impl(NULL)
+ {
+ }
+
+ /*!
+ * Constructor. The method is used to construct an object and create the associated
+ * message queue. The constructed object will be in running state if the message queue is
+ * successfully created.
+ *
+ * \post <tt>is_open() == true</tt>
+ *
+ * \param name Name of the message queue to be associated with.
+ * \param capacity Maximum number of allocation blocks the queue can hold.
+ * \param block_size Size in bytes of allocation block. Must be a power of 2.
+ * \param oflow_policy Queue behavior policy in case of overflow.
+ * \param perms Access permissions for the associated message queue.
+ */
+ reliable_message_queue
+ (
+ open_mode::create_only_tag,
+ object_name const& name,
+ uint32_t capacity,
+ size_type block_size,
+ overflow_policy oflow_policy = block_on_overflow,
+ permissions const& perms = permissions()
+ ) :
+ m_impl(NULL)
+ {
+ this->create(name, capacity, block_size, oflow_policy, perms);
+ }
+
+ /*!
+ * Constructor. The method is used to construct an object and create or open the associated
+ * message queue. The constructed object will be in running state if the message queue is
+ * successfully created or opened. If the message queue that is identified by the name already
+ * exists then the other queue parameters are ignored. The actual queue parameters can be obtained
+ * with accessors from the constructed object.
+ *
+ * \post <tt>is_open() == true</tt>
+ *
+ * \param name Name of the message queue to be associated with.
+ * \param capacity Maximum number of allocation blocks the queue can hold.
+ * \param block_size Size in bytes of allocation block. Must be a power of 2.
+ * \param oflow_policy Queue behavior policy in case of overflow.
+ * \param perms Access permissions for the associated message queue.
+ */
+ reliable_message_queue
+ (
+ open_mode::open_or_create_tag,
+ object_name const& name,
+ uint32_t capacity,
+ size_type block_size,
+ overflow_policy oflow_policy = block_on_overflow,
+ permissions const& perms = permissions()
+ ) :
+ m_impl(NULL)
+ {
+ this->open_or_create(name, capacity, block_size, oflow_policy, perms);
+ }
+
+ /*!
+ * Constructor. The method is used to construct an object and open the existing
+ * message queue. The constructed object will be in running state if the message queue is
+ * successfully opened.
+ *
+ * \post <tt>is_open() == true</tt>
+ *
+ * \param name Name of the message queue to be associated with.
+ * \param oflow_policy Queue behavior policy in case of overflow.
+ * \param perms Access permissions for the associated message queue. The permissions will only be used
+ * if the queue implementation has to create system objects while operating.
+ * This parameter is currently not used on POSIX systems.
+ */
+ reliable_message_queue
+ (
+ open_mode::open_only_tag,
+ object_name const& name,
+ overflow_policy oflow_policy = block_on_overflow,
+ permissions const& perms = permissions()
+ ) :
+ m_impl(NULL)
+ {
+ this->open(name, oflow_policy, perms);
+ }
+
+ /*!
+ * Constructor with named parameters. The method is used to construct an object and create or open
+ * the associated message queue. The constructed object will be in running state if the message queue is
+ * successfully created.
+ *
+ * The following named parameters are accepted:
+ *
+ * * open_mode - One of the open mode tags: \c open_mode::create_only, \c open_mode::open_only or
+ * \c open_mode::open_or_create.
+ * * name - Name of the message queue to be associated with.
+ * * capacity - Maximum number of allocation blocks the queue can hold. Used only if the queue is created.
+ * * block_size - Size in bytes of allocation block. Must be a power of 2. Used only if the queue is created.
+ * * overflow_policy - Queue behavior policy in case of overflow, see \c overflow_policy.
+ * * permissions - Access permissions for the associated message queue.
+ *
+ * \post <tt>is_open() == true</tt>
+ */
+#if !defined(BOOST_LOG_DOXYGEN_PASS)
+ BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_CALL(reliable_message_queue, construct)
+#else
+ template< typename... Args >
+ explicit reliable_message_queue(Args const&... args);
+#endif
+
+ /*!
+ * Destructor. Calls <tt>close()</tt>.
+ */
+ ~reliable_message_queue() BOOST_NOEXCEPT
+ {
+ this->close();
+ }
+
+ /*!
+ * Move constructor. The method move-constructs an object from \c other. After
+ * the call, the constructed object becomes \c other, while \c other is left in
+ * default constructed state.
+ *
+ * \param that The object to be moved.
+ */
+ reliable_message_queue(BOOST_RV_REF(reliable_message_queue) that) BOOST_NOEXCEPT :
+ m_impl(that.m_impl)
+ {
+ that.m_impl = NULL;
+ }
+
+ /*!
+ * Move assignment operator. If the object is associated with a message queue,
+ * <tt>close()</tt> is first called and the precondition to calling <tt>close()</tt>
+ * applies. After the call, the object becomes \a that while \a that is left
+ * in default constructed state.
+ *
+ * \param that The object to be moved.
+ *
+ * \return A reference to the assigned object.
+ */
+ reliable_message_queue& operator= (BOOST_RV_REF(reliable_message_queue) that) BOOST_NOEXCEPT
+ {
+ reliable_message_queue other(static_cast< BOOST_RV_REF(reliable_message_queue) >(that));
+ this->swap(other);
+ return *this;
+ }
+
+ /*!
+ * The method swaps the object with \a that.
+ *
+ * \param that The other object to swap with.
+ */
+ void swap(reliable_message_queue& that) BOOST_NOEXCEPT
+ {
+ implementation* p = m_impl;
+ m_impl = that.m_impl;
+ that.m_impl = p;
+ }
+
+ //! Swaps the two \c reliable_message_queue objects.
+ friend void swap(reliable_message_queue& a, reliable_message_queue& b) BOOST_NOEXCEPT
+ {
+ a.swap(b);
+ }
+
+ /*!
+ * The method creates the message queue to be associated with the object. After the call,
+ * the object will be in running state if a message queue is successfully created.
+ *
+ * \pre <tt>is_open() == false</tt>
+ * \post <tt>is_open() == true</tt>
+ *
+ * \param name Name of the message queue to be associated with.
+ * \param capacity Maximum number of allocation blocks the queue can hold.
+ * \param block_size Size in bytes of allocation block. Must be a power of 2.
+ * \param oflow_policy Queue behavior policy in case of overflow.
+ * \param perms Access permissions for the associated message queue.
+ */
+ BOOST_LOG_API void create
+ (
+ object_name const& name,
+ uint32_t capacity,
+ size_type block_size,
+ overflow_policy oflow_policy = block_on_overflow,
+ permissions const& perms = permissions()
+ );
+
+ /*!
+ * The method creates or opens the message queue to be associated with the object.
+ * After the call, the object will be in running state if a message queue is successfully
+ * created or opened. If the message queue that is identified by the name already exists then
+ * the other queue parameters are ignored. The actual queue parameters can be obtained
+ * with accessors from this object after this method returns.
+ *
+ * \pre <tt>is_open() == false</tt>
+ * \post <tt>is_open() == true</tt>
+ *
+ * \param name Name of the message queue to be associated with.
+ * \param capacity Maximum number of allocation blocks the queue can hold.
+ * \param block_size Size in bytes of allocation block. Must be a power of 2.
+ * \param oflow_policy Queue behavior policy in case of overflow.
+ * \param perms Access permissions for the associated message queue.
+ */
+ BOOST_LOG_API void open_or_create
+ (
+ object_name const& name,
+ uint32_t capacity,
+ size_type block_size,
+ overflow_policy oflow_policy = block_on_overflow,
+ permissions const& perms = permissions()
+ );
+
+ /*!
+ * The method opens the existing message queue to be associated with the object.
+ * After the call, the object will be in running state if a message queue is successfully
+ * opened.
+ *
+ * \pre <tt>is_open() == false</tt>
+ * \post <tt>is_open() == true</tt>
+ *
+ * \param name Name of the message queue to be associated with.
+ * \param oflow_policy Queue behavior policy in case of overflow.
+ * \param perms Access permissions for the associated message queue. The permissions will only be used
+ * if the queue implementation has to create system objects while operating.
+ * This parameter is currently not used on POSIX systems.
+ */
+ BOOST_LOG_API void open
+ (
+ object_name const& name,
+ overflow_policy oflow_policy = block_on_overflow,
+ permissions const& perms = permissions()
+ );
+
+ /*!
+ * Tests whether the object is associated with any message queue.
+ *
+ * \return \c true if the object is associated with a message queue, and \c false otherwise.
+ */
+ bool is_open() const BOOST_NOEXCEPT
+ {
+ return m_impl != NULL;
+ }
+
+ /*!
+ * This method empties the associated message queue. Concurrent calls to this method, <tt>send()</tt>,
+ * <tt>try_send()</tt>, <tt>receive()</tt>, <tt>try_receive()</tt>, and <tt>stop_local()</tt> are allowed.
+ *
+ * \pre <tt>is_open() == true</tt>
+ */
+ BOOST_LOG_API void clear();
+
+ /*!
+ * The method returns the name of the associated message queue.
+ *
+ * \pre <tt>is_open() == true</tt>
+ *
+ * \return Name of the associated message queue
+ */
+ BOOST_LOG_API object_name const& name() const;
+
+ /*!
+ * The method returns the maximum number of allocation blocks the associated message queue
+ * can hold. Note that the returned value may be different from the corresponding
+ * value passed to the constructor or <tt>open_or_create()</tt>, for the message queue may
+ * not have been created by this object.
+ *
+ * \pre <tt>is_open() == true</tt>
+ *
+ * \return Maximum number of allocation blocks the associated message queue can hold.
+ */
+ BOOST_LOG_API uint32_t capacity() const;
+
+ /*!
+ * The method returns the allocation block size, in bytes. Each message in the
+ * associated message queue consumes an integer number of allocation blocks.
+ * Note that the returned value may be different from the corresponding value passed
+ * to the constructor or <tt>open_or_create()</tt>, for the message queue may not
+ * have been created by this object.
+ *
+ * \pre <tt>is_open() == true</tt>
+ *
+ * \return Allocation block size, in bytes.
+ */
+ BOOST_LOG_API size_type block_size() const;
+
+ /*!
+ * The method wakes up all threads that are blocked in calls to <tt>send()</tt> or
+ * <tt>receive()</tt>. Those calls would then return \c false with \c errno \c EINTR.
+ * Note that, the method does not block until the woken-up threads have actually
+ * returned from <tt>send()</tt> or <tt>receive()</tt>. Other means is needed to ensure
+ * that calls to <tt>send()</tt> or <tt>receive()</tt> have returned, e.g., joining the
+ * threads that might be blocking on the calls.
+ *
+ * The method also puts the object in stopped state. When in stopped state, calls to
+ * <tt>send()</tt> or <tt>receive()</tt> will return immediately with return value
+ * \c false and \c errno \c EINTR when they would otherwise block in running state.
+ *
+ * Concurrent calls to this method, <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>,
+ * <tt>try_receive()</tt>, and <tt>clear()</tt> are allowed.
+ *
+ * \pre <tt>is_open() == true</tt>
+ */
+ BOOST_LOG_API void stop_local();
+
+ /*!
+ * The method puts the object in running state where calls to <tt>send()</tt> or
+ * <tt>receive()</tt> may block. This method is not thread-safe.
+ *
+ * \pre <tt>is_open() == true</tt>
+ */
+ BOOST_LOG_API void reset_local();
+
+ /*!
+ * The method disassociates the associated message queue, if any. No other threads
+ * should be using this object before calling this method. The <tt>stop_local()</tt> method
+ * can be used to have any threads currently blocked in <tt>send()</tt> or
+ * <tt>receive()</tt> return, and prevent further calls to them from blocking. Typically,
+ * before calling this method, one would first call <tt>stop_local()</tt> and then join all
+ * threads that might be blocking on <tt>send()</tt> or <tt>receive()</tt> to ensure that
+ * they have returned from the calls. The associated message queue is destroyed if the
+ * object represents the last outstanding reference to it.
+ *
+ * \post <tt>is_open() == false</tt>
+ */
+ void close() BOOST_NOEXCEPT
+ {
+ if (is_open())
+ do_close();
+ }
+
+ /*!
+ * The method sends a message to the associated message queue. When the object is in
+ * running state and the queue has no free space for the message, the method either blocks
+ * or throws an exception, depending on the overflow policy that was specified on the queue
+ * opening/creation. If blocking policy is in effect, the blocking can be interrupted by
+ * calling <tt>stop_local()</tt>, in which case the method returns \c operation_result::aborted.
+ * When the object is already in the stopped state, the method does not block but returns
+ * immediately with return value \c operation_result::aborted.
+ *
+ * It is possible to send an empty message by passing \c 0 to the parameter \c message_size.
+ *
+ * Concurrent calls to <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>, <tt>try_receive()</tt>,
+ * <tt>stop_local()</tt>, and <tt>clear()</tt> are allowed.
+ *
+ * \pre <tt>is_open() == true</tt>
+ *
+ * \param message_data The message data to send. Ignored when \c message_size is \c 0.
+ * \param message_size Size of the message data in bytes. If the size is larger than
+ * the associated message queue capacity, an <tt>std::logic_error</tt> exception is thrown.
+ *
+ * \retval operation_result::succeeded if the operation is successful
+ * \retval operation_result::no_space if \c overflow_policy::fail_on_overflow is in effect and the queue is full
+ * \retval operation_result::aborted if the call was interrupted by <tt>stop_local()</tt>
+ *
+ * <b>Throws:</b> <tt>std::logic_error</tt> in case if the message size exceeds the queue
+ * capacity, <tt>system_error</tt> in case if a native OS method fails.
+ */
+ BOOST_LOG_API operation_result send(void const* message_data, size_type message_size);
+
+ /*!
+ * The method performs an attempt to send a message to the associated message queue.
+ * The method is non-blocking, and always returns immediately.
+ * <tt>boost::system::system_error</tt> is thrown for errors resulting from native
+ * operating system calls. Note that it is possible to send an empty message by passing
+ * \c 0 to the parameter \c message_size. Concurrent calls to <tt>send()</tt>,
+ * <tt>try_send()</tt>, <tt>receive()</tt>, <tt>try_receive()</tt>, <tt>stop_local()</tt>,
+ * and <tt>clear()</tt> are allowed.
+ *
+ * \pre <tt>is_open() == true</tt>
+ *
+ * \param message_data The message data to send. Ignored when \c message_size is \c 0.
+ * \param message_size Size of the message data in bytes. If the size is larger than the
+ * maximum size allowed by the associated message queue, an
+ * <tt>std::logic_error</tt> exception is thrown.
+ *
+ * \return \c true if the message is successfully sent, and \c false otherwise (e.g.,
+ * when the queue is full).
+ *
+ * <b>Throws:</b> <tt>std::logic_error</tt> in case if the message size exceeds the queue
+ * capacity, <tt>system_error</tt> in case if a native OS method fails.
+ */
+ BOOST_LOG_API bool try_send(void const* message_data, size_type message_size);
+
+ /*!
+ * The method takes a message from the associated message queue. When the object is in
+ * running state and the queue is empty, the method blocks. The blocking is interrupted
+ * when <tt>stop_local()</tt> is called, in which case the method returns \c operation_result::aborted.
+ * When the object is already in the stopped state and the queue is empty, the method
+ * does not block but returns immediately with return value \c operation_result::aborted.
+ *
+ * Concurrent calls to <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>,
+ * <tt>try_receive()</tt>, <tt>stop_local()</tt>, and <tt>clear()</tt> are allowed.
+ *
+ * \pre <tt>is_open() == true</tt>
+ *
+ * \param buffer The memory buffer to store the received message in.
+ * \param buffer_size The size of the buffer, in bytes.
+ * \param message_size Receives the size of the received message, in bytes.
+ *
+ * \retval operation_result::succeeded if the operation is successful
+ * \retval operation_result::aborted if the call was interrupted by <tt>stop_local()</tt>
+ */
+ operation_result receive(void* buffer, size_type buffer_size, size_type& message_size)
+ {
+ fixed_buffer_state state = { static_cast< uint8_t* >(buffer), buffer_size };
+ operation_result result = do_receive(&reliable_message_queue::fixed_buffer_receive_handler, &state);
+ message_size = buffer_size - state.size;
+ return result;
+ }
+
+ /*!
+ * The method takes a message from the associated message queue. When the object is in
+ * running state and the queue is empty, the method blocks. The blocking is interrupted
+ * when <tt>stop_local()</tt> is called, in which case the method returns \c operation_result::aborted.
+ * When the object is already in the stopped state and the queue is empty, the method
+ * does not block but returns immediately with return value \c operation_result::aborted.
+ *
+ * Concurrent calls to <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>,
+ * <tt>try_receive()</tt>, <tt>stop_local()</tt>, and <tt>clear()</tt> are allowed.
+ *
+ * \pre <tt>is_open() == true</tt>
+ *
+ * \param buffer The memory buffer to store the received message in.
+ * \param message_size Receives the size of the received message, in bytes.
+ *
+ * \retval operation_result::succeeded if the operation is successful
+ * \retval operation_result::aborted if the call was interrupted by <tt>stop_local()</tt>
+ */
+ template< typename ElementT, size_type SizeV >
+#if !defined(BOOST_LOG_DOXYGEN_PASS)
+ typename aux::enable_if_byte< ElementT, operation_result >::type
+#else
+ operation_result
+#endif
+ receive(ElementT (&buffer)[SizeV], size_type& message_size)
+ {
+ return receive(buffer, SizeV, message_size);
+ }
+
+ /*!
+ * The method takes a message from the associated message queue. When the object is in
+ * running state and the queue is empty, the method blocks. The blocking is interrupted
+ * when <tt>stop_local()</tt> is called, in which case the method returns \c operation_result::aborted.
+ * When the object is already in the stopped state and the queue is empty, the method
+ * does not block but returns immediately with return value \c operation_result::aborted.
+ *
+ * Concurrent calls to <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>,
+ * <tt>try_receive()</tt>, <tt>stop_local()</tt>, and <tt>clear()</tt> are allowed.
+ *
+ * \pre <tt>is_open() == true</tt>
+ *
+ * \param container The container to store the received message in. The container should have
+ * value type of <tt>char</tt>, <tt>signed char</tt> or <tt>unsigned char</tt>
+ * and support inserting elements at the end.
+ *
+ * \retval operation_result::succeeded if the operation is successful
+ * \retval operation_result::aborted if the call was interrupted by <tt>stop_local()</tt>
+ */
+ template< typename ContainerT >
+#if !defined(BOOST_LOG_DOXYGEN_PASS)
+ typename aux::enable_if_byte< typename ContainerT::value_type, operation_result >::type
+#else
+ operation_result
+#endif
+ receive(ContainerT& container)
+ {
+ return do_receive(&reliable_message_queue::container_receive_handler< ContainerT >, &container);
+ }
+
+ /*!
+ * The method performs an attempt to take a message from the associated message queue. The
+ * method is non-blocking, and always returns immediately.
+ *
+ * Concurrent calls to <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>,
+ * <tt>try_receive()</tt>, <tt>stop_local()</tt>, and <tt>clear()</tt> are allowed.
+ *
+ * \pre <tt>is_open() == true</tt>
+ *
+ * \param buffer The memory buffer to store the received message in.
+ * \param buffer_size The size of the buffer, in bytes.
+ * \param message_size Receives the size of the received message, in bytes.
+ *
+ * \return \c true if a message is successfully received, and \c false otherwise (e.g.,
+ * when the queue is empty).
+ */
+ bool try_receive(void* buffer, size_type buffer_size, size_type& message_size)
+ {
+ fixed_buffer_state state = { static_cast< uint8_t* >(buffer), buffer_size };
+ bool result = do_try_receive(&reliable_message_queue::fixed_buffer_receive_handler, &state);
+ message_size = buffer_size - state.size;
+ return result;
+ }
+
+ /*!
+ * The method performs an attempt to take a message from the associated message queue. The
+ * method is non-blocking, and always returns immediately.
+ *
+ * Concurrent calls to <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>,
+ * <tt>try_receive()</tt>, <tt>stop_local()</tt>, and <tt>clear()</tt> are allowed.
+ *
+ * \pre <tt>is_open() == true</tt>
+ *
+ * \param buffer The memory buffer to store the received message in.
+ * \param message_size Receives the size of the received message, in bytes.
+ *
+ * \return \c true if a message is successfully received, and \c false otherwise (e.g.,
+ * when the queue is empty).
+ */
+ template< typename ElementT, size_type SizeV >
+#if !defined(BOOST_LOG_DOXYGEN_PASS)
+ typename aux::enable_if_byte< ElementT, bool >::type
+#else
+ bool
+#endif
+ try_receive(ElementT (&buffer)[SizeV], size_type& message_size)
+ {
+ return try_receive(buffer, SizeV, message_size);
+ }
+
+ /*!
+ * The method performs an attempt to take a message from the associated message queue. The
+ * method is non-blocking, and always returns immediately.
+ *
+ * Concurrent calls to <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>,
+ * <tt>try_receive()</tt>, <tt>stop_local()</tt>, and <tt>clear()</tt> are allowed.
+ *
+ * \pre <tt>is_open() == true</tt>
+ *
+ * \param container The container to store the received message in. The container should have
+ * value type of <tt>char</tt>, <tt>signed char</tt> or <tt>unsigned char</tt>
+ * and support inserting elements at the end.
+ *
+ * \return \c true if a message is successfully received, and \c false otherwise (e.g.,
+ * when the queue is empty).
+ */
+ template< typename ContainerT >
+#if !defined(BOOST_LOG_DOXYGEN_PASS)
+ typename aux::enable_if_byte< typename ContainerT::value_type, bool >::type
+#else
+ bool
+#endif
+ try_receive(ContainerT& container)
+ {
+ return do_try_receive(&reliable_message_queue::container_receive_handler< ContainerT >, &container);
+ }
+
+ /*!
+ * The method frees system-wide resources, associated with the interprocess queue with the supplied name.
+ * The queue referred to by the specified name must not be opened in any process at the point of this call.
+ * After this call succeeds a new queue with the specified name can be created.
+ *
+ * This call can be useful to recover from an earlier process misbehavior (e.g. a crash without properly
+ * closing the message queue). In this case resources allocated for the interprocess queue may remain
+ * allocated after the last process closed the queue, which in turn may prevent creating a new queue with
+ * the same name. By calling this method before creating a queue the application can attempt to ensure
+ * it starts with a clean slate.
+ *
+ * On some platforms resources associated with the queue are automatically reclaimed by the operating system
+ * when the last process using those resources terminates (even if it terminates abnormally). On these
+ * platforms this call may be a no-op. However, portable code should still call this method at appropriate
+ * places to ensure compatibility with other platforms and future library versions, which may change implementation
+ * of the queue.
+ *
+ * \param name Name of the message queue to be removed.
+ */
+ static BOOST_LOG_API void remove(object_name const& name);
+
+#if !defined(BOOST_LOG_DOXYGEN_PASS)
+private:
+ //! Implementation of the constructor with named arguments
+ template< typename ArgsT >
+ void construct(ArgsT const& args)
+ {
+ m_impl = NULL;
+ construct_dispatch(args[keywords::open_mode], args);
+ }
+
+ //! Implementation of the constructor with named arguments
+ template< typename ArgsT >
+ void construct_dispatch(open_mode::create_only_tag, ArgsT const& args)
+ {
+ this->create(args[keywords::name], args[keywords::capacity], args[keywords::block_size], args[keywords::overflow_policy | block_on_overflow], args[keywords::permissions | permissions()]);
+ }
+
+ //! Implementation of the constructor with named arguments
+ template< typename ArgsT >
+ void construct_dispatch(open_mode::open_or_create_tag, ArgsT const& args)
+ {
+ this->open_or_create(args[keywords::name], args[keywords::capacity], args[keywords::block_size], args[keywords::overflow_policy | block_on_overflow], args[keywords::permissions | permissions()]);
+ }
+
+ //! Implementation of the constructor with named arguments
+ template< typename ArgsT >
+ void construct_dispatch(open_mode::open_only_tag, ArgsT const& args)
+ {
+ this->open(args[keywords::name], args[keywords::overflow_policy | block_on_overflow], args[keywords::permissions | permissions()]);
+ }
+
+ //! Closes the message queue, if it's open
+ BOOST_LOG_API void do_close() BOOST_NOEXCEPT;
+
+ //! Receives the message from the queue and calls the handler to place the data in the user's storage
+ BOOST_LOG_API operation_result do_receive(receive_handler handler, void* state);
+ //! Attempts to receives the message from the queue and calls the handler to place the data in the user's storage
+ BOOST_LOG_API bool do_try_receive(receive_handler handler, void* state);
+
+ //! Fixed buffer receive handler
+ static BOOST_LOG_API void fixed_buffer_receive_handler(void* state, const void* data, size_type size);
+ //! Receive handler for a container
+ template< typename ContainerT >
+ static void container_receive_handler(void* state, const void* data, size_type size)
+ {
+ ContainerT* const container = static_cast< ContainerT* >(state);
+ container->insert
+ (
+ container->end(),
+ static_cast< typename ContainerT::value_type const* >(data),
+ static_cast< typename ContainerT::value_type const* >(data) + size
+ );
+ }
+#endif
+};
+
+} // namespace ipc
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_IPC_RELIABLE_MESSAGE_QUEUE_HPP_INCLUDED_
diff --git a/boost/log/utility/manipulators/dump.hpp b/boost/log/utility/manipulators/dump.hpp
index dc1856a47a..3341376f39 100644
--- a/boost/log/utility/manipulators/dump.hpp
+++ b/boost/log/utility/manipulators/dump.hpp
@@ -200,7 +200,7 @@ inline dump_manip dump_elements(T* data, std::size_t count) BOOST_NOEXCEPT
* \brief Creates a stream manipulator that will output contents of a memory region in hexadecimal form
* \param data The pointer to the beginning of the region
* \param size The size of the region, in bytes
- * \params max_size The maximum number of bytes of the region to output
+ * \param max_size The maximum number of bytes of the region to output
* \return The manipulator that is to be put to a stream
*/
template< typename T >
@@ -213,7 +213,7 @@ inline typename aux::enable_dump< T, bounded_dump_manip >::type dump(T* data, st
* \brief Creates a stream manipulator that will dump elements of an array in hexadecimal form
* \param data The pointer to the beginning of the array
* \param count The size of the region, in number of \c T elements
- * \params max_count The maximum number of elements to output
+ * \param max_count The maximum number of elements to output
* \return The manipulator that is to be put to a stream
*/
template< typename T >
diff --git a/boost/log/utility/open_mode.hpp b/boost/log/utility/open_mode.hpp
new file mode 100644
index 0000000000..34a3d8d1aa
--- /dev/null
+++ b/boost/log/utility/open_mode.hpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright Andrey Semashev 2016.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file open_mode.hpp
+ * \author Andrey Semashev
+ * \date 01.01.2016
+ *
+ * The header defines resource opening modes.
+ */
+
+#ifndef BOOST_LOG_UTILITY_OPEN_MODE_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_OPEN_MODE_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace open_mode {
+
+//! Create a new resource; fail if exists already
+struct create_only_tag {} const create_only = create_only_tag();
+//! Opens an existing resource; fail if not exist
+struct open_only_tag {} const open_only = open_only_tag();
+//! Creates a new resource or opens an existing one
+struct open_or_create_tag {} const open_or_create = open_or_create_tag();
+
+} // namespace open_mode
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_OPEN_MODE_HPP_INCLUDED_
diff --git a/boost/log/utility/permissions.hpp b/boost/log/utility/permissions.hpp
new file mode 100644
index 0000000000..e35649a185
--- /dev/null
+++ b/boost/log/utility/permissions.hpp
@@ -0,0 +1,213 @@
+/*
+ * Copyright Lingxi Li 2015.
+ * Copyright Andrey Semashev 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 permissions.hpp
+ * \author Lingxi Li
+ * \author Andrey Semashev
+ * \date 14.10.2015
+ *
+ * The header contains an abstraction wrapper for security permissions.
+ */
+
+#ifndef BOOST_LOG_UTILITY_PERMISSIONS_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_PERMISSIONS_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifdef BOOST_WINDOWS
+extern "C" {
+struct _SECURITY_ATTRIBUTES;
+}
+#endif // BOOST_WINDOWS
+
+namespace boost {
+
+#ifdef BOOST_WINDOWS
+namespace detail {
+namespace winapi {
+struct BOOST_LOG_MAY_ALIAS _SECURITY_ATTRIBUTES;
+}
+}
+#endif
+
+namespace interprocess {
+class permissions;
+} // namespace interprocess
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * \brief Access permissions wrapper.
+ *
+ * On Windows platforms, it represents a pointer to \c SECURITY_ATTRIBUTES. The user is responsible
+ * for allocating and reclaiming resources associated with the pointer, \c permissions instance does
+ * not own them.
+ *
+ * On POSIX platforms, it represents a \c mode_t value.
+ */
+class permissions
+{
+public:
+#if defined(BOOST_LOG_DOXYGEN_PASS)
+ //! The type of security permissions, specific to the operating system
+ typedef implementation_defined native_type;
+#elif defined(BOOST_WINDOWS)
+ typedef ::_SECURITY_ATTRIBUTES* native_type;
+#else
+ // Equivalent to POSIX mode_t
+ typedef unsigned int native_type;
+#endif
+
+#if !defined(BOOST_LOG_DOXYGEN_PASS)
+private:
+ native_type m_perms;
+#endif
+
+public:
+ /*!
+ * Default constructor. The method constructs an object that represents
+ * a null \c SECURITY_ATTRIBUTES pointer on Windows platforms, and a
+ * \c mode_t value \c 0644 on POSIX platforms.
+ */
+ permissions() BOOST_NOEXCEPT
+ {
+ set_default();
+ }
+
+ /*!
+ * Copy constructor.
+ */
+ permissions(permissions const& that) BOOST_NOEXCEPT : m_perms(that.m_perms)
+ {
+ }
+
+ /*!
+ * Copy assignment.
+ */
+ permissions& operator=(permissions const& that) BOOST_NOEXCEPT
+ {
+ m_perms = that.m_perms;
+ return *this;
+ }
+
+ /*!
+ * Initializing constructor.
+ */
+ permissions(native_type perms) BOOST_NOEXCEPT : m_perms(perms)
+ {
+ }
+
+#ifdef BOOST_WINDOWS
+ permissions(boost::detail::winapi::_SECURITY_ATTRIBUTES* perms) BOOST_NOEXCEPT : m_perms(reinterpret_cast< native_type >(perms))
+ {
+ }
+#endif
+
+ /*!
+ * Initializing constructor.
+ */
+ BOOST_LOG_API permissions(boost::interprocess::permissions const& perms) BOOST_NOEXCEPT;
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ /*!
+ * Move constructor.
+ */
+ permissions(permissions&& that) BOOST_NOEXCEPT : m_perms(that.m_perms)
+ {
+ that.set_default();
+ }
+
+ /*!
+ * Move assignment.
+ */
+ permissions& operator=(permissions&& that) BOOST_NOEXCEPT
+ {
+ m_perms = that.m_perms;
+ that.set_default();
+ return *this;
+ }
+#endif
+
+ /*!
+ * Sets permissions from the OS-specific permissions.
+ */
+ void set_native(native_type perms) BOOST_NOEXCEPT
+ {
+ m_perms = perms;
+ }
+
+ /*!
+ * Returns the underlying OS-specific permissions.
+ */
+ native_type get_native() const BOOST_NOEXCEPT
+ {
+ return m_perms;
+ }
+
+ /*!
+ * Sets the default permissions, which are equivalent to \c NULL \c SECURITY_ATTRIBUTES
+ * on Windows and \c 0644 on POSIX platforms.
+ */
+ void set_default() BOOST_NOEXCEPT
+ {
+#if defined(BOOST_WINDOWS)
+ m_perms = 0;
+#else
+ m_perms = 0644;
+#endif
+ }
+
+ /*!
+ * Sets unrestricted permissions, which are equivalent to \c SECURITY_ATTRIBUTES with \c NULL DACL
+ * on Windows and \c 0666 on POSIX platforms.
+ */
+ void set_unrestricted()
+ {
+#if defined(BOOST_WINDOWS)
+ m_perms = get_unrestricted_security_attributes();
+#else
+ m_perms = 0666;
+#endif
+ }
+
+ /*!
+ * The method swaps the object with \a that.
+ *
+ * \param that The other object to swap with.
+ */
+ void swap(permissions& that) BOOST_NOEXCEPT
+ {
+ native_type perms = m_perms;
+ m_perms = that.m_perms;
+ that.m_perms = perms;
+ }
+
+ //! Swaps the two \c permissions objects.
+ friend void swap(permissions& a, permissions& b) BOOST_NOEXCEPT
+ {
+ a.swap(b);
+ }
+
+#if !defined(BOOST_LOG_DOXYGEN_PASS) && defined(BOOST_WINDOWS)
+private:
+ static BOOST_LOG_API native_type get_unrestricted_security_attributes();
+#endif
+};
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_PERMISSIONS_HPP_INCLUDED_
diff --git a/boost/log/utility/record_ordering.hpp b/boost/log/utility/record_ordering.hpp
index f77cd49c43..f9963f62b8 100644
--- a/boost/log/utility/record_ordering.hpp
+++ b/boost/log/utility/record_ordering.hpp
@@ -15,7 +15,7 @@
#ifndef BOOST_LOG_UTILITY_RECORD_ORDERING_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_RECORD_ORDERING_HPP_INCLUDED_
-#include <boost/utility/enable_if.hpp>
+#include <boost/core/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/function_traits.hpp>
@@ -196,10 +196,10 @@ namespace aux {
//! An ordering predicate constructor that uses SFINAE to disable invalid instantiations
template<
typename FunT,
- typename ArityCheckT = typename enable_if_c< aux::arity_of< FunT >::value == 2 >::type,
+ typename ArityCheckT = typename boost::enable_if_c< aux::arity_of< FunT >::value == 2 >::type,
typename Arg1T = typename aux::first_argument_type_of< FunT >::type,
typename Arg2T = typename aux::second_argument_type_of< FunT >::type,
- typename ArgsCheckT = typename enable_if< is_same< Arg1T, Arg2T > >::type
+ typename ArgsCheckT = typename boost::enable_if_c< is_same< Arg1T, Arg2T >::value >::type
>
struct make_attr_ordering_type
{
diff --git a/boost/log/utility/setup/filter_parser.hpp b/boost/log/utility/setup/filter_parser.hpp
index 854ac72caf..f9aa831caf 100644
--- a/boost/log/utility/setup/filter_parser.hpp
+++ b/boost/log/utility/setup/filter_parser.hpp
@@ -21,7 +21,7 @@
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/phoenix/operator/comparison.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
-#include <boost/utility/enable_if.hpp>
+#include <boost/core/enable_if.hpp>
#include <boost/log/detail/setup_config.hpp>
#include <boost/log/detail/code_conversion.hpp>
#include <boost/log/exceptions.hpp>
@@ -242,8 +242,8 @@ BOOST_LOG_SETUP_API void register_filter_factory(
* \param factory The filter factory
*/
template< typename FactoryT >
-inline typename enable_if<
- is_base_and_derived< filter_factory< typename FactoryT::char_type >, FactoryT >
+inline typename boost::enable_if_c<
+ is_base_and_derived< filter_factory< typename FactoryT::char_type >, FactoryT >::value
>::type register_filter_factory(attribute_name const& name, shared_ptr< FactoryT > const& factory)
{
typedef filter_factory< typename FactoryT::char_type > factory_base;
diff --git a/boost/log/utility/setup/formatter_parser.hpp b/boost/log/utility/setup/formatter_parser.hpp
index 8bdc2bca86..250c75c1d2 100644
--- a/boost/log/utility/setup/formatter_parser.hpp
+++ b/boost/log/utility/setup/formatter_parser.hpp
@@ -21,7 +21,7 @@
#include <string>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
-#include <boost/utility/enable_if.hpp>
+#include <boost/core/enable_if.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/log/detail/setup_config.hpp>
#include <boost/log/attributes/attribute_name.hpp>
@@ -136,8 +136,8 @@ BOOST_LOG_SETUP_API void register_formatter_factory(
* \param factory Pointer to the formatter factory
*/
template< typename FactoryT >
-inline typename enable_if<
- is_base_and_derived< formatter_factory< typename FactoryT::char_type >, FactoryT >
+inline typename boost::enable_if_c<
+ is_base_and_derived< formatter_factory< typename FactoryT::char_type >, FactoryT >::value
>::type register_formatter_factory(attribute_name const& attr_name, shared_ptr< FactoryT > const& factory)
{
typedef formatter_factory< typename FactoryT::char_type > factory_base;
diff --git a/boost/log/utility/setup/from_settings.hpp b/boost/log/utility/setup/from_settings.hpp
index 27691bf2da..be1c1bc0b6 100644
--- a/boost/log/utility/setup/from_settings.hpp
+++ b/boost/log/utility/setup/from_settings.hpp
@@ -18,7 +18,7 @@
#include <string>
#include <boost/smart_ptr/shared_ptr.hpp>
-#include <boost/utility/enable_if.hpp>
+#include <boost/core/enable_if.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/log/detail/setup_config.hpp>
#include <boost/log/sinks/sink.hpp>
@@ -126,8 +126,8 @@ inline void register_sink_factory(std::string const& sink_name, shared_ptr< sink
* \param factory Pointer to the custom sink factory. Must not be NULL.
*/
template< typename FactoryT >
-inline typename enable_if<
- is_base_and_derived< sink_factory< typename FactoryT::char_type >, FactoryT >
+inline typename boost::enable_if_c<
+ is_base_and_derived< sink_factory< typename FactoryT::char_type >, FactoryT >::value
>::type register_sink_factory(const char* sink_name, shared_ptr< FactoryT > const& factory)
{
typedef sink_factory< typename FactoryT::char_type > factory_base;
@@ -147,8 +147,8 @@ inline typename enable_if<
* \param factory Pointer to the custom sink factory. Must not be NULL.
*/
template< typename FactoryT >
-inline typename enable_if<
- is_base_and_derived< sink_factory< typename FactoryT::char_type >, FactoryT >
+inline typename boost::enable_if_c<
+ is_base_and_derived< sink_factory< typename FactoryT::char_type >, FactoryT >::value
>::type register_sink_factory(std::string const& sink_name, shared_ptr< FactoryT > const& factory)
{
typedef sink_factory< typename FactoryT::char_type > factory_base;
diff --git a/boost/log/utility/setup/settings.hpp b/boost/log/utility/setup/settings.hpp
index 67b1f2339e..e63fea1200 100644
--- a/boost/log/utility/setup/settings.hpp
+++ b/boost/log/utility/setup/settings.hpp
@@ -28,7 +28,7 @@
#include <boost/log/detail/native_typeof.hpp>
#include <boost/utility/explicit_operator_bool.hpp>
#if !defined(BOOST_LOG_TYPEOF)
-#include <boost/utility/enable_if.hpp>
+#include <boost/core/enable_if.hpp>
#endif
#if defined(BOOST_LOG_TYPEOF) && defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
#include <boost/utility/declval.hpp>
@@ -254,7 +254,7 @@ private:
}
template< typename T >
- typename enable_if< boost::property_tree::detail::is_character< T >, std::basic_string< T > >::type
+ typename boost::enable_if_c< boost::property_tree::detail::is_character< T >::value, std::basic_string< T > >::type
or_default(const T* def_value) const
{
if (m_section.m_ptree)
diff --git a/boost/log/utility/strictest_lock.hpp b/boost/log/utility/strictest_lock.hpp
index 9735961f92..5dd48b4ffb 100644
--- a/boost/log/utility/strictest_lock.hpp
+++ b/boost/log/utility/strictest_lock.hpp
@@ -79,6 +79,11 @@ struct thread_access_mode_of< lock_guard< MutexT > > : mpl::integral_c< lock_acc
};
template< typename MutexT >
+struct thread_access_mode_of< shared_lock_guard< MutexT > > : mpl::integral_c< lock_access_mode, shared_access >
+{
+};
+
+template< typename MutexT >
struct thread_access_mode_of< unique_lock< MutexT > > : mpl::integral_c< lock_access_mode, exclusive_access >
{
};
diff --git a/boost/log/utility/string_literal.hpp b/boost/log/utility/string_literal.hpp
index 0b737000bf..af5bf3640a 100644
--- a/boost/log/utility/string_literal.hpp
+++ b/boost/log/utility/string_literal.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright Andrey Semashev 2007 - 2015.
+ * Copyright Andrey Semashev 2007 - 2016.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
@@ -21,12 +21,11 @@
#include <ios> // std::streamsize
#include <string>
#include <iterator>
-#include <boost/operators.hpp>
#include <boost/throw_exception.hpp>
#include <boost/type_traits/is_same.hpp>
-#include <boost/utility/enable_if.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/utility/string_literal_fwd.hpp>
+#include <boost/log/detail/sfinae_tools.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
@@ -50,16 +49,6 @@ BOOST_LOG_OPEN_NAMESPACE
*/
template< typename CharT, typename TraitsT >
class basic_string_literal
- //! \cond
- : public totally_ordered1< basic_string_literal< CharT, TraitsT >,
- totally_ordered2< basic_string_literal< CharT, TraitsT >, const CharT*,
- totally_ordered2<
- basic_string_literal< CharT, TraitsT >,
- std::basic_string< CharT, TraitsT >
- >
- >
- >
- //! \endcond
{
//! Self type
typedef basic_string_literal< CharT, TraitsT > this_type;
@@ -84,8 +73,12 @@ private:
//! Length
size_type m_Len;
- //! Empty string literal to support clear
+ //! Empty string literal to support \c clear
+#if !defined(BOOST_LOG_NO_CXX11_CONSTEXPR_DATA_MEMBER_BRACE_INITIALIZERS)
+ static constexpr value_type g_EmptyString[1] = { 0 };
+#else
static const value_type g_EmptyString[1];
+#endif
public:
/*!
@@ -93,7 +86,7 @@ public:
*
* \post <tt>empty() == true</tt>
*/
- basic_string_literal() BOOST_NOEXCEPT { clear(); }
+ BOOST_CONSTEXPR basic_string_literal() BOOST_NOEXCEPT : m_pStart(g_EmptyString), m_Len(0) { }
/*!
* Constructor from a string literal
@@ -102,9 +95,9 @@ public:
* \param p A zero-terminated constant sequence of characters
*/
template< typename T, size_type LenV >
- basic_string_literal(T(&p)[LenV]
+ BOOST_CONSTEXPR basic_string_literal(T(&p)[LenV]
//! \cond
- , typename enable_if< is_same< T, const value_type >, int >::type = 0
+ , typename boost::enable_if_c< is_same< T, const value_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()
//! \endcond
) BOOST_NOEXCEPT
: m_pStart(p), m_Len(LenV - 1)
@@ -117,7 +110,7 @@ public:
* \post <tt>*this == that</tt>
* \param that Source literal to copy string from
*/
- basic_string_literal(basic_string_literal const& that) BOOST_NOEXCEPT : m_pStart(that.m_pStart), m_Len(that.m_Len) {}
+ BOOST_CONSTEXPR basic_string_literal(basic_string_literal const& that) BOOST_NOEXCEPT : m_pStart(that.m_pStart), m_Len(that.m_Len) {}
/*!
* Assignment operator
@@ -125,7 +118,7 @@ public:
* \post <tt>*this == that</tt>
* \param that Source literal to copy string from
*/
- this_type& operator= (this_type const& that) BOOST_NOEXCEPT
+ BOOST_CXX14_CONSTEXPR this_type& operator= (this_type const& that) BOOST_NOEXCEPT
{
return assign(that);
}
@@ -136,9 +129,10 @@ public:
* \param p A zero-terminated constant sequence of characters
*/
template< typename T, size_type LenV >
+ BOOST_CXX14_CONSTEXPR
#ifndef BOOST_LOG_DOXYGEN_PASS
- typename enable_if<
- is_same< T, const value_type >,
+ typename boost::enable_if_c<
+ is_same< T, const value_type >::value,
this_type&
>::type
#else
@@ -175,12 +169,43 @@ public:
* \param that Comparand
* \return \c true if the comparand string equals to this string, \c false otherwise
*/
- bool operator== (string_type const& that) const
+ bool operator== (string_type const& that) const BOOST_NOEXCEPT
{
return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) == 0);
}
/*!
+ * Lexicographical comparison (inequality)
+ *
+ * \param that Comparand
+ * \return \c true if the comparand string is not equal to this string, \c false otherwise
+ */
+ bool operator!= (this_type const& that) const BOOST_NOEXCEPT
+ {
+ return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) != 0);
+ }
+ /*!
+ * Lexicographical comparison (inequality)
+ *
+ * \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
+ * \return \c true if the comparand string is not equal to this string, \c false otherwise
+ */
+ bool operator!= (const_pointer str) const BOOST_NOEXCEPT
+ {
+ return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) != 0);
+ }
+ /*!
+ * Lexicographical comparison (inequality)
+ *
+ * \param that Comparand
+ * \return \c true if the comparand string is not equal to this string, \c false otherwise
+ */
+ bool operator!= (string_type const& that) const BOOST_NOEXCEPT
+ {
+ return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) != 0);
+ }
+
+ /*!
* Lexicographical comparison (less ordering)
*
* \param that Comparand
@@ -206,12 +231,43 @@ public:
* \param that Comparand
* \return \c true if this string is less than the comparand, \c false otherwise
*/
- bool operator< (string_type const& that) const
+ bool operator< (string_type const& that) const BOOST_NOEXCEPT
{
return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) < 0);
}
/*!
+ * Lexicographical comparison (less or equal ordering)
+ *
+ * \param that Comparand
+ * \return \c true if this string is less or equal to the comparand, \c false otherwise
+ */
+ bool operator<= (this_type const& that) const BOOST_NOEXCEPT
+ {
+ return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) <= 0);
+ }
+ /*!
+ * Lexicographical comparison (less or equal ordering)
+ *
+ * \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
+ * \return \c true if this string is less or equal to the comparand, \c false otherwise
+ */
+ bool operator<= (const_pointer str) const BOOST_NOEXCEPT
+ {
+ return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) <= 0);
+ }
+ /*!
+ * Lexicographical comparison (less or equal ordering)
+ *
+ * \param that Comparand
+ * \return \c true if this string is less or equal to the comparand, \c false otherwise
+ */
+ bool operator<= (string_type const& that) const BOOST_NOEXCEPT
+ {
+ return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) <= 0);
+ }
+
+ /*!
* Lexicographical comparison (greater ordering)
*
* \param that Comparand
@@ -237,19 +293,50 @@ public:
* \param that Comparand
* \return \c true if this string is greater than the comparand, \c false otherwise
*/
- bool operator> (string_type const& that) const
+ bool operator> (string_type const& that) const BOOST_NOEXCEPT
{
return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) > 0);
}
/*!
+ * Lexicographical comparison (greater or equal ordering)
+ *
+ * \param that Comparand
+ * \return \c true if this string is greater or equal to the comparand, \c false otherwise
+ */
+ bool operator>= (this_type const& that) const BOOST_NOEXCEPT
+ {
+ return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) >= 0);
+ }
+ /*!
+ * Lexicographical comparison (greater or qual ordering)
+ *
+ * \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
+ * \return \c true if this string is greater or equal to the comparand, \c false otherwise
+ */
+ bool operator>= (const_pointer str) const BOOST_NOEXCEPT
+ {
+ return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) >= 0);
+ }
+ /*!
+ * Lexicographical comparison (greater or equal ordering)
+ *
+ * \param that Comparand
+ * \return \c true if this string is greater or equal to the comparand, \c false otherwise
+ */
+ bool operator>= (string_type const& that) const BOOST_NOEXCEPT
+ {
+ return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) >= 0);
+ }
+
+ /*!
* Subscript operator
*
* \pre <tt>i < size()</tt>
* \param i Requested character index
* \return Constant reference to the requested character
*/
- const_reference operator[] (size_type i) const BOOST_NOEXCEPT
+ BOOST_CONSTEXPR const_reference operator[] (size_type i) const BOOST_NOEXCEPT
{
return m_pStart[i];
}
@@ -263,7 +350,7 @@ public:
*/
const_reference at(size_type i) const
{
- if (i >= m_Len)
+ if (BOOST_UNLIKELY(i >= m_Len))
BOOST_THROW_EXCEPTION(std::out_of_range("basic_string_literal::at: the index value is out of range"));
return m_pStart[i];
}
@@ -271,24 +358,24 @@ public:
/*!
* \return Pointer to the beginning of the literal
*/
- const_pointer c_str() const BOOST_NOEXCEPT { return m_pStart; }
+ BOOST_CONSTEXPR const_pointer c_str() const BOOST_NOEXCEPT { return m_pStart; }
/*!
* \return Pointer to the beginning of the literal
*/
- const_pointer data() const BOOST_NOEXCEPT { return m_pStart; }
+ BOOST_CONSTEXPR const_pointer data() const BOOST_NOEXCEPT { return m_pStart; }
/*!
* \return Length of the literal
*/
- size_type size() const BOOST_NOEXCEPT { return m_Len; }
+ BOOST_CONSTEXPR size_type size() const BOOST_NOEXCEPT { return m_Len; }
/*!
* \return Length of the literal
*/
- size_type length() const BOOST_NOEXCEPT { return m_Len; }
+ BOOST_CONSTEXPR size_type length() const BOOST_NOEXCEPT { return m_Len; }
/*!
* \return \c true if the literal is an empty string, \c false otherwise
*/
- bool empty() const BOOST_NOEXCEPT
+ BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT
{
return (m_Len == 0);
}
@@ -296,11 +383,11 @@ public:
/*!
* \return Iterator that points to the first character of the literal
*/
- const_iterator begin() const BOOST_NOEXCEPT { return m_pStart; }
+ BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT { return m_pStart; }
/*!
* \return Iterator that points after the last character of the literal
*/
- const_iterator end() const BOOST_NOEXCEPT { return m_pStart + m_Len; }
+ BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT { return m_pStart + m_Len; }
/*!
* \return Reverse iterator that points to the last character of the literal
*/
@@ -323,7 +410,7 @@ public:
*
* \post <tt>empty() == true</tt>
*/
- void clear() BOOST_NOEXCEPT
+ BOOST_CXX14_CONSTEXPR void clear() BOOST_NOEXCEPT
{
m_pStart = g_EmptyString;
m_Len = 0;
@@ -331,7 +418,7 @@ public:
/*!
* The method swaps two literals
*/
- void swap(this_type& that) BOOST_NOEXCEPT
+ BOOST_CXX14_CONSTEXPR void swap(this_type& that) BOOST_NOEXCEPT
{
const_pointer p = m_pStart;
m_pStart = that.m_pStart;
@@ -348,7 +435,7 @@ public:
* \post <tt>*this == that</tt>
* \param that Source literal to copy string from
*/
- this_type& assign(this_type const& that) BOOST_NOEXCEPT
+ BOOST_CXX14_CONSTEXPR this_type& assign(this_type const& that) BOOST_NOEXCEPT
{
m_pStart = that.m_pStart;
m_Len = that.m_Len;
@@ -361,9 +448,10 @@ public:
* \param p A zero-terminated constant sequence of characters
*/
template< typename T, size_type LenV >
+ BOOST_CXX14_CONSTEXPR
#ifndef BOOST_LOG_DOXYGEN_PASS
- typename enable_if<
- is_same< T, const value_type >,
+ typename boost::enable_if_c<
+ is_same< T, const value_type >::value,
this_type&
>::type
#else
@@ -390,7 +478,7 @@ public:
*/
size_type copy(value_type* str, size_type n, size_type pos = 0) const
{
- if (pos > m_Len)
+ if (BOOST_UNLIKELY(pos > m_Len))
BOOST_THROW_EXCEPTION(std::out_of_range("basic_string_literal::copy: the position is out of range"));
size_type len = m_Len - pos;
@@ -415,7 +503,7 @@ public:
*/
int compare(size_type pos, size_type n, const_pointer str, size_type len) const
{
- if (pos > m_Len)
+ if (BOOST_UNLIKELY(pos > m_Len))
BOOST_THROW_EXCEPTION(std::out_of_range("basic_string_literal::compare: the position is out of range"));
size_type compare_size = m_Len - pos;
@@ -508,9 +596,15 @@ private:
#endif // BOOST_LOG_DOXYGEN_PASS
};
+#if !defined(BOOST_LOG_NO_CXX11_CONSTEXPR_DATA_MEMBER_BRACE_INITIALIZERS)
template< typename CharT, typename TraitsT >
-typename basic_string_literal< CharT, TraitsT >::value_type const
+constexpr typename basic_string_literal< CharT, TraitsT >::value_type
+basic_string_literal< CharT, TraitsT >::g_EmptyString[1];
+#else
+template< typename CharT, typename TraitsT >
+const typename basic_string_literal< CharT, TraitsT >::value_type
basic_string_literal< CharT, TraitsT >::g_EmptyString[1] = { 0 };
+#endif
namespace aux {
@@ -569,7 +663,7 @@ inline std::basic_ostream< CharT, StrmTraitsT >& operator<< (
//! External swap
template< typename CharT, typename TraitsT >
-inline void swap(basic_string_literal< CharT, TraitsT >& left, basic_string_literal< CharT, TraitsT >& right) BOOST_NOEXCEPT
+inline BOOST_CXX14_CONSTEXPR void swap(basic_string_literal< CharT, TraitsT >& left, basic_string_literal< CharT, TraitsT >& right) BOOST_NOEXCEPT
{
left.swap(right);
}
@@ -577,16 +671,16 @@ inline void swap(basic_string_literal< CharT, TraitsT >& left, basic_string_lite
//! Creates a string literal wrapper from a constant string literal
#ifdef BOOST_LOG_USE_CHAR
template< typename T, std::size_t LenV >
-inline
+inline BOOST_CONSTEXPR
#ifndef BOOST_LOG_DOXYGEN_PASS
-typename enable_if<
- is_same< T, const char >,
+typename boost::enable_if_c<
+ is_same< T, const char >::value,
string_literal
>::type
#else
basic_string_literal< T >
#endif // BOOST_LOG_DOXYGEN_PASS
-str_literal(T(&p)[LenV])
+str_literal(T(&p)[LenV]) BOOST_NOEXCEPT
{
return string_literal(p);
}
@@ -596,11 +690,11 @@ str_literal(T(&p)[LenV])
#ifdef BOOST_LOG_USE_WCHAR_T
template< typename T, std::size_t LenV >
-inline typename enable_if<
- is_same< T, const wchar_t >,
+inline BOOST_CONSTEXPR typename boost::enable_if_c<
+ is_same< T, const wchar_t >::value,
wstring_literal
>::type
-str_literal(T(&p)[LenV])
+str_literal(T(&p)[LenV]) BOOST_NOEXCEPT
{
return wstring_literal(p);
}
diff --git a/boost/log/utility/type_dispatch/static_type_dispatcher.hpp b/boost/log/utility/type_dispatch/static_type_dispatcher.hpp
index c580213d66..dcf2cd033d 100644
--- a/boost/log/utility/type_dispatch/static_type_dispatcher.hpp
+++ b/boost/log/utility/type_dispatch/static_type_dispatcher.hpp
@@ -29,7 +29,7 @@
#include <boost/mpl/deref.hpp>
#include <boost/mpl/next.hpp>
#include <boost/mpl/is_sequence.hpp>
-#include <boost/utility/addressof.hpp>
+#include <boost/core/addressof.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/utility/once_block.hpp>
#include <boost/log/utility/type_dispatch/type_dispatcher.hpp>
diff --git a/boost/log/utility/value_ref.hpp b/boost/log/utility/value_ref.hpp
index 438f5db68b..1f9a360785 100644
--- a/boost/log/utility/value_ref.hpp
+++ b/boost/log/utility/value_ref.hpp
@@ -29,15 +29,14 @@
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/contains.hpp>
#include <boost/mpl/index_of.hpp>
-#include <boost/utility/addressof.hpp>
-#include <boost/utility/enable_if.hpp>
+#include <boost/core/explicit_operator_bool.hpp>
+#include <boost/core/addressof.hpp>
#include <boost/optional/optional_fwd.hpp>
-#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_void.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/parameter_tools.hpp>
#include <boost/log/detail/value_ref_visitation.hpp>
-#include <boost/utility/explicit_operator_bool.hpp>
+#include <boost/log/detail/sfinae_tools.hpp>
#include <boost/log/utility/formatting_ostream_fwd.hpp>
#include <boost/log/utility/functional/logical.hpp>
#include <boost/log/utility/functional/bind.hpp>
@@ -78,6 +77,21 @@ private:
result_type m_def_val;
};
+//! Traits for testing type compatibility with the reference wrapper
+struct singular_ref_compatibility_traits
+{
+ template< typename T, typename U >
+ struct is_compatible
+ {
+ BOOST_STATIC_CONSTANT(bool, value = false);
+ };
+ template< typename T >
+ struct is_compatible< T, T >
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+};
+
//! Attribute value reference implementation for a single type case
template< typename T, typename TagT >
class singular_ref
@@ -89,17 +103,8 @@ public:
typedef TagT tag_type;
protected:
- //! The metafunction tests if the type is compatible with the reference wrapper
-#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
- template< typename U >
- using is_compatible = is_same< U, value_type >;
-#else
- template< typename U >
- struct is_compatible :
- public is_same< U, value_type >
- {
- };
-#endif
+ //! Traits for testing type compatibility with the reference wrapper
+ typedef singular_ref_compatibility_traits compatibility_traits;
protected:
//! Pointer to the value
@@ -132,7 +137,7 @@ public:
//! Returns a pointer to the referred value
template< typename U >
- typename enable_if< is_compatible< U >, const U* >::type get_ptr() const BOOST_NOEXCEPT
+ typename boost::enable_if_c< compatibility_traits::is_compatible< value_type, U >::value, const U* >::type get_ptr() const BOOST_NOEXCEPT
{
return m_ptr;
}
@@ -153,7 +158,7 @@ public:
//! Returns a reference to the value
template< typename U >
- typename enable_if< is_compatible< U >, U const& >::type get() const BOOST_NOEXCEPT
+ typename boost::enable_if_c< compatibility_traits::is_compatible< value_type, U >::value, U const& >::type get() const BOOST_NOEXCEPT
{
BOOST_ASSERT(m_ptr != NULL);
return *m_ptr;
@@ -190,7 +195,7 @@ public:
//! Applies a visitor function object to the referred value
template< typename VisitorT >
- typename enable_if< is_void< typename VisitorT::result_type >, bool >::type apply_visitor_optional(VisitorT visitor) const
+ typename boost::enable_if_c< is_void< typename VisitorT::result_type >::value, bool >::type apply_visitor_optional(VisitorT visitor) const
{
if (m_ptr)
{
@@ -203,7 +208,7 @@ public:
//! Applies a visitor function object to the referred value
template< typename VisitorT >
- typename disable_if< is_void< typename VisitorT::result_type >, optional< typename VisitorT::result_type > >::type apply_visitor_optional(VisitorT visitor) const
+ typename boost::disable_if_c< is_void< typename VisitorT::result_type >::value, optional< typename VisitorT::result_type > >::type apply_visitor_optional(VisitorT visitor) const
{
typedef optional< typename VisitorT::result_type > result_type;
if (m_ptr)
@@ -233,6 +238,16 @@ public:
}
};
+//! Traits for testing type compatibility with the reference wrapper
+struct variant_ref_compatibility_traits
+{
+ template< typename T, typename U >
+ struct is_compatible
+ {
+ BOOST_STATIC_CONSTANT(bool, value = (mpl::contains< T, U >::type::value));
+ };
+};
+
//! Attribute value reference implementation for multiple types case
template< typename T, typename TagT >
class variant_ref
@@ -244,17 +259,8 @@ public:
typedef TagT tag_type;
protected:
- //! The metafunction tests if the type is compatible with the reference wrapper
-#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
- template< typename U >
- using is_compatible = mpl::contains< value_type, U >;
-#else
- template< typename U >
- struct is_compatible :
- public mpl::contains< value_type, U >
- {
- };
-#endif
+ //! Traits for testing type compatibility with the reference wrapper
+ typedef variant_ref_compatibility_traits compatibility_traits;
protected:
//! Pointer to the value
@@ -284,7 +290,7 @@ public:
//! Returns a pointer to the referred value
template< typename U >
- typename enable_if< is_compatible< U >, const U* >::type get_ptr() const BOOST_NOEXCEPT
+ typename boost::enable_if_c< compatibility_traits::is_compatible< value_type, U >::value, const U* >::type get_ptr() const BOOST_NOEXCEPT
{
if (m_type_idx == static_cast< unsigned int >(mpl::index_of< value_type, U >::type::value))
return static_cast< const U* >(m_ptr);
@@ -294,7 +300,7 @@ public:
//! Returns a reference to the value
template< typename U >
- typename enable_if< is_compatible< U >, U const& >::type get() const BOOST_NOEXCEPT
+ typename boost::enable_if_c< compatibility_traits::is_compatible< value_type, U >::value, U const& >::type get() const BOOST_NOEXCEPT
{
const U* const p = get_ptr< U >();
BOOST_ASSERT(p != NULL);
@@ -328,7 +334,7 @@ public:
//! Applies a visitor function object to the referred value
template< typename VisitorT >
- typename enable_if< is_void< typename VisitorT::result_type >, bool >::type apply_visitor_optional(VisitorT visitor) const
+ typename boost::enable_if_c< is_void< typename VisitorT::result_type >::value, bool >::type apply_visitor_optional(VisitorT visitor) const
{
if (m_ptr)
{
@@ -341,7 +347,7 @@ public:
//! Applies a visitor function object to the referred value
template< typename VisitorT >
- typename disable_if< is_void< typename VisitorT::result_type >, optional< typename VisitorT::result_type > >::type apply_visitor_optional(VisitorT visitor) const
+ typename boost::disable_if_c< is_void< typename VisitorT::result_type >::value, optional< typename VisitorT::result_type > >::type apply_visitor_optional(VisitorT visitor) const
{
typedef optional< typename VisitorT::result_type > result_type;
if (m_ptr)
@@ -423,6 +429,19 @@ public:
private:
//! Base implementation type
typedef typename aux::value_ref_base< T, TagT >::type base_type;
+ //! Traits for testing type compatibility with the reference wrapper
+ typedef typename base_type::compatibility_traits compatibility_traits;
+
+public:
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ //! Referenced value type
+ typedef typename base_type::value_type value_type;
+#else
+ //! Referenced value type
+ typedef T value_type;
+ //! Tag type
+ typedef TagT tag_type;
+#endif
public:
/*!
@@ -439,7 +458,14 @@ public:
* Initializing constructor. Creates a reference wrapper that refers to the specified value.
*/
template< typename U >
- explicit value_ref(U const& val, typename enable_if< typename base_type::BOOST_NESTED_TEMPLATE is_compatible< U >, int >::type = 0) BOOST_NOEXCEPT :
+ explicit value_ref(U const& val
+#ifndef BOOST_LOG_DOXYGEN_PASS
+// MSVC-8 can't handle SFINAE in this case properly and often wrongly disables this constructor
+#if !defined(_MSC_VER) || (_MSC_VER + 0) >= 1500
+ , typename boost::enable_if_c< compatibility_traits::BOOST_NESTED_TEMPLATE is_compatible< value_type, U >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()
+#endif
+#endif
+ ) BOOST_NOEXCEPT :
base_type(boost::addressof(val))
{
}