summaryrefslogtreecommitdiff
path: root/boost/log/detail
diff options
context:
space:
mode:
Diffstat (limited to 'boost/log/detail')
-rw-r--r--boost/log/detail/allocator_traits.hpp77
-rw-r--r--boost/log/detail/attachable_sstream_buf.hpp10
-rw-r--r--boost/log/detail/config.hpp13
-rw-r--r--boost/log/detail/threadsafe_queue.hpp95
4 files changed, 144 insertions, 51 deletions
diff --git a/boost/log/detail/allocator_traits.hpp b/boost/log/detail/allocator_traits.hpp
new file mode 100644
index 0000000000..3f9501c655
--- /dev/null
+++ b/boost/log/detail/allocator_traits.hpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright Andrey Semashev 2018.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file allocator_traits.hpp
+ * \author Andrey Semashev
+ * \date 03.01.2018
+ *
+ * \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_ALLOCATOR_TRAITS_HPP_INCLUDED_
+#define BOOST_LOG_ALLOCATOR_TRAITS_HPP_INCLUDED_
+
+#include <memory>
+#include <boost/log/detail/config.hpp>
+#if defined(BOOST_NO_CXX11_ALLOCATOR)
+#include <boost/container/allocator_traits.hpp>
+#endif
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace aux {
+
+// A portable name for allocator traits
+#if !defined(BOOST_NO_CXX11_ALLOCATOR)
+using std::allocator_traits;
+#else
+using boost::container::allocator_traits;
+#endif
+
+/*!
+ * \brief A standalone trait to rebind an allocator to another type.
+ *
+ * The important difference from <tt>std::allocator_traits&lt;Alloc&gt;::rebind_alloc&lt;U&gt;</tt> is that this
+ * trait does not require template aliases and thus is compatible with C++03. There is
+ * <tt>boost::container::allocator_traits&lt;Alloc&gt;::portable_rebind_alloc&lt;U&gt;</tt>, but it is not present in <tt>std::allocator_traits</tt>.
+ * It will also attempt to instantiate the allocator type to test if it provides the nested <tt>rebind</tt> template. We don't want
+ * that to happen because it prohibits using <tt>std::allocator&lt;void&gt;</tt> in C++17 and later, which deprecated
+ * this allocator specialization. This standalone trait does not use the nested <tt>rebind</tt> template in this case.
+ */
+template< typename Allocator, typename U >
+struct rebind_alloc
+{
+#if !defined(BOOST_NO_CXX11_ALLOCATOR)
+ typedef typename std::allocator_traits< Allocator >::BOOST_NESTED_TEMPLATE rebind_alloc< U > type;
+#else
+ typedef typename boost::container::allocator_traits< Allocator >::BOOST_NESTED_TEMPLATE portable_rebind_alloc< U >::type type;
+#endif
+};
+
+template< typename U >
+struct rebind_alloc< std::allocator< void >, U >
+{
+ typedef std::allocator< U > type;
+};
+
+} // namespace aux
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_ALLOCATOR_TRAITS_HPP_INCLUDED_
diff --git a/boost/log/detail/attachable_sstream_buf.hpp b/boost/log/detail/attachable_sstream_buf.hpp
index 7bcb3a4307..e196689c80 100644
--- a/boost/log/detail/attachable_sstream_buf.hpp
+++ b/boost/log/detail/attachable_sstream_buf.hpp
@@ -22,7 +22,7 @@
#include <string>
#include <streambuf>
#include <boost/assert.hpp>
-#include <boost/mpl/bool.hpp>
+#include <boost/type_traits/integral_constant.hpp>
#include <boost/locale/utf.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/header.hpp>
@@ -277,11 +277,13 @@ protected:
//! 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 >());
+ BOOST_ASSERT(max_size <= n);
+ return length_until_boundary(s, n, max_size, boost::integral_constant< bool, sizeof(char_type) == 1u >());
}
+private:
//! 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
+ size_type length_until_boundary(const char_type* s, size_type, size_type max_size, boost::true_type) 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);
@@ -290,7 +292,7 @@ protected:
}
//! 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_)
+ static size_type length_until_boundary(const char_type* s, size_type n, size_type max_size, boost::false_type)
{
// 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
diff --git a/boost/log/detail/config.hpp b/boost/log/detail/config.hpp
index 5f43443e42..8db321baad 100644
--- a/boost/log/detail/config.hpp
+++ b/boost/log/detail/config.hpp
@@ -344,11 +344,18 @@ namespace log {
# if !defined(BOOST_NO_CXX11_INLINE_NAMESPACES)
inline namespace BOOST_LOG_VERSION_NAMESPACE {}
-}
# define BOOST_LOG_OPEN_NAMESPACE namespace log { inline namespace BOOST_LOG_VERSION_NAMESPACE {
# define BOOST_LOG_CLOSE_NAMESPACE }}
+# elif defined(BOOST_GCC) && (BOOST_GCC+0) >= 40400
+
+// GCC 7 deprecated strong using directives but allows inline namespaces in C++03 mode since GCC 4.4.
+__extension__ inline namespace BOOST_LOG_VERSION_NAMESPACE {}
+
+# define BOOST_LOG_OPEN_NAMESPACE namespace log { __extension__ inline namespace BOOST_LOG_VERSION_NAMESPACE {
+# define BOOST_LOG_CLOSE_NAMESPACE }}
+
# else
namespace BOOST_LOG_VERSION_NAMESPACE {}
@@ -359,12 +366,12 @@ __attribute__((__strong__))
# endif
;
-}
-
# define BOOST_LOG_OPEN_NAMESPACE namespace log { namespace BOOST_LOG_VERSION_NAMESPACE {
# define BOOST_LOG_CLOSE_NAMESPACE }}
# endif
+} // namespace log
+
#else // !defined(BOOST_LOG_DOXYGEN_PASS)
namespace log {}
diff --git a/boost/log/detail/threadsafe_queue.hpp b/boost/log/detail/threadsafe_queue.hpp
index b8b3dbe60a..b747ed4c5d 100644
--- a/boost/log/detail/threadsafe_queue.hpp
+++ b/boost/log/detail/threadsafe_queue.hpp
@@ -32,6 +32,7 @@
#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/allocator_traits.hpp>
#include <boost/log/detail/header.hpp>
namespace boost {
@@ -69,23 +70,22 @@ struct threadsafe_queue_impl
virtual bool try_pop(node_base*& node_to_free, node_base*& node_with_value) = 0;
};
-//! A helper class to compose some of the types used by the queue
-template< typename T, typename AllocatorT >
-struct threadsafe_queue_types
+//! Thread-safe queue node type
+template< typename T >
+struct threadsafe_queue_node :
+ public threadsafe_queue_impl::node_base
{
- struct node :
- public threadsafe_queue_impl::node_base
- {
- typedef typename aligned_storage< sizeof(T), alignment_of< T >::value >::type storage_type;
- storage_type storage;
+ typedef typename aligned_storage< sizeof(T), alignment_of< T >::value >::type storage_type;
+ storage_type storage;
- node() {}
- explicit node(T const& val) { new (storage.address()) T(val); }
- T& value() { return *static_cast< T* >(storage.address()); }
- void destroy() { static_cast< T* >(storage.address())->~T(); }
- };
+ BOOST_DEFAULTED_FUNCTION(threadsafe_queue_node(), {})
+ explicit threadsafe_queue_node(T const& val) { new (storage.address()) T(val); }
+ T& value() BOOST_NOEXCEPT { return *static_cast< T* >(storage.address()); }
+ void destroy() BOOST_NOEXCEPT { static_cast< T* >(storage.address())->~T(); }
- typedef typename AllocatorT::BOOST_NESTED_TEMPLATE rebind< node >::other allocator_type;
+ // Copying and assignment is prohibited
+ BOOST_DELETED_FUNCTION(threadsafe_queue_node(threadsafe_queue_node const&))
+ BOOST_DELETED_FUNCTION(threadsafe_queue_node& operator= (threadsafe_queue_node const&))
};
/*!
@@ -108,74 +108,77 @@ struct threadsafe_queue_types
*/
template< typename T, typename AllocatorT = std::allocator< void > >
class threadsafe_queue :
- private threadsafe_queue_types< T, AllocatorT >::allocator_type
+ private boost::log::aux::rebind_alloc< AllocatorT, threadsafe_queue_node< T > >::type
{
private:
- typedef typename threadsafe_queue_types< T, AllocatorT >::allocator_type base_type;
- typedef typename threadsafe_queue_types< T, AllocatorT >::node node;
+ typedef threadsafe_queue_node< T > node;
+
+public:
+ typedef typename boost::log::aux::rebind_alloc< AllocatorT, node >::type allocator_type;
+ typedef T value_type;
+ typedef T& reference;
+ typedef T const& const_reference;
+ typedef T* pointer;
+ typedef T const* const_pointer;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::size_t size_type;
+
+private:
+ typedef boost::log::aux::allocator_traits< allocator_type > alloc_traits;
//! A simple scope guard to automate memory reclaiming
struct auto_deallocate;
friend struct auto_deallocate;
struct auto_deallocate
{
- auto_deallocate(base_type* alloc, node* dealloc, node* destr) :
+ auto_deallocate(allocator_type* alloc, node* dealloc, node* destr) BOOST_NOEXCEPT :
m_pAllocator(alloc),
m_pDeallocate(dealloc),
m_pDestroy(destr)
{
}
- ~auto_deallocate()
+ ~auto_deallocate() BOOST_NOEXCEPT
{
- m_pAllocator->deallocate(m_pDeallocate, 1);
+ alloc_traits::destroy(*m_pAllocator, m_pDeallocate);
+ alloc_traits::deallocate(*m_pAllocator, m_pDeallocate, 1);
m_pDestroy->destroy();
}
private:
- base_type* m_pAllocator;
+ allocator_type* m_pAllocator;
node* m_pDeallocate;
node* m_pDestroy;
};
public:
- typedef T value_type;
- typedef T& reference;
- typedef T const& const_reference;
- typedef T* pointer;
- typedef T const* const_pointer;
- typedef std::ptrdiff_t difference_type;
- typedef std::size_t size_type;
- typedef AllocatorT allocator_type;
-
-public:
/*!
* Default constructor, creates an empty queue. Unlike most containers,
* the constructor requires memory allocation.
*
* \throw std::bad_alloc if there is not sufficient memory
*/
- threadsafe_queue(base_type const& alloc = base_type()) :
- base_type(alloc)
+ threadsafe_queue(allocator_type const& alloc = allocator_type()) :
+ allocator_type(alloc)
{
- node* p = base_type::allocate(1);
+ node* p = alloc_traits::allocate(get_allocator(), 1);
if (p)
{
try
{
- new (p) node();
+ alloc_traits::construct(get_allocator(), p);
try
{
m_pImpl = threadsafe_queue_impl::create(p);
}
catch (...)
{
- p->~node();
+ alloc_traits::destroy(get_allocator(), p);
throw;
}
}
catch (...)
{
- base_type::deallocate(p, 1);
+ alloc_traits::deallocate(get_allocator(), p, 1);
throw;
}
}
@@ -185,7 +188,7 @@ public:
/*!
* Destructor
*/
- ~threadsafe_queue()
+ ~threadsafe_queue() BOOST_NOEXCEPT
{
// Clear the queue
if (!unsafe_empty())
@@ -196,8 +199,8 @@ public:
// Remove the last dummy node
node* p = static_cast< node* >(m_pImpl->reset_last_node());
- p->~node();
- base_type::deallocate(p, 1);
+ alloc_traits::destroy(get_allocator(), p);
+ alloc_traits::deallocate(get_allocator(), p, 1);
delete m_pImpl;
}
@@ -213,16 +216,16 @@ public:
*/
void push(const_reference value)
{
- node* p = base_type::allocate(1);
+ node* p = alloc_traits::allocate(get_allocator(), 1);
if (p)
{
try
{
- new (p) node(value);
+ alloc_traits::construct(get_allocator(), p, value);
}
catch (...)
{
- base_type::deallocate(p, 1);
+ alloc_traits::deallocate(get_allocator(), p, 1);
throw;
}
m_pImpl->push(p);
@@ -242,7 +245,7 @@ public:
if (m_pImpl->try_pop(dealloc, destr))
{
node* p = static_cast< node* >(destr);
- auto_deallocate guard(static_cast< base_type* >(this), static_cast< node* >(dealloc), p);
+ auto_deallocate guard(static_cast< allocator_type* >(this), static_cast< node* >(dealloc), p);
value = boost::move(p->value());
return true;
}
@@ -255,6 +258,10 @@ public:
BOOST_DELETED_FUNCTION(threadsafe_queue& operator= (threadsafe_queue const&))
private:
+ //! Returns the allocator instance
+ allocator_type& get_allocator() BOOST_NOEXCEPT { return *static_cast< allocator_type* >(this); }
+
+private:
//! Pointer to the implementation
threadsafe_queue_impl* m_pImpl;
};