allocator_traits::construct is used for user-defined types:

It should only be called when constructing a user-provided type.

Close #1332

Signed-off-by: Damian Jarek <damian.jarek93@gmail.com>
This commit is contained in:
Damian Jarek
2019-05-19 21:14:46 +02:00
parent e5bad9cbc2
commit 9909fada29
4 changed files with 29 additions and 21 deletions

View File

@@ -6,6 +6,7 @@ Version 256:
* Remove redundant template in service_base * Remove redundant template in service_base
* Expand CI matrix using Azure Pipelines * Expand CI matrix using Azure Pipelines
* Make chat websocket javascript client more user friendly * Make chat websocket javascript client more user friendly
* `allocator_traits::construct` is used for user-defined types
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------

View File

@@ -19,7 +19,6 @@ namespace boost {
namespace beast { namespace beast {
/** A buffer sequence representing a concatenation of buffer sequences. /** A buffer sequence representing a concatenation of buffer sequences.
@see buffers_cat @see buffers_cat
*/ */
template<class... Buffers> template<class... Buffers>
@@ -29,7 +28,6 @@ class buffers_cat_view
public: public:
/** The type of buffer returned when dereferencing an iterator. /** The type of buffer returned when dereferencing an iterator.
If every buffer sequence in the view is a <em>MutableBufferSequence</em>, If every buffer sequence in the view is a <em>MutableBufferSequence</em>,
then `value_type` will be `net::mutable_buffer`. then `value_type` will be `net::mutable_buffer`.
Otherwise, `value_type` will be `net::const_buffer`. Otherwise, `value_type` will be `net::const_buffer`.
@@ -50,7 +48,6 @@ public:
buffers_cat_view& operator=(buffers_cat_view const&) = default; buffers_cat_view& operator=(buffers_cat_view const&) = default;
/** Constructor /** Constructor
@param buffers The list of buffer sequences to concatenate. @param buffers The list of buffer sequences to concatenate.
Copies of the arguments will be maintained for the lifetime Copies of the arguments will be maintained for the lifetime
of the concatenated sequence; however, the ownership of the of the concatenated sequence; however, the ownership of the
@@ -63,28 +60,24 @@ public:
const_iterator const_iterator
begin() const; begin() const;
/// Returns an iterator to one past the last buffer in the sequence /// Returns an iterator to one past the last buffer in the sequence
const_iterator const_iterator
end() const; end() const;
}; };
/** Concatenate 2 or more buffer sequences. /** Concatenate 2 or more buffer sequences.
This function returns a constant or mutable buffer sequence which, This function returns a constant or mutable buffer sequence which,
when iterated, efficiently concatenates the input buffer sequences. when iterated, efficiently concatenates the input buffer sequences.
Copies of the arguments passed will be made; however, the returned Copies of the arguments passed will be made; however, the returned
object does not take ownership of the underlying memory. The object does not take ownership of the underlying memory. The
application is still responsible for managing the lifetime of the application is still responsible for managing the lifetime of the
referenced memory. referenced memory.
@param buffers The list of buffer sequences to concatenate. @param buffers The list of buffer sequences to concatenate.
@return A new buffer sequence that represents the concatenation of @return A new buffer sequence that represents the concatenation of
the input buffer sequences. This buffer sequence will be a the input buffer sequences. This buffer sequence will be a
<em>MutableBufferSequence</em> if each of the passed buffer sequences is <em>MutableBufferSequence</em> if each of the passed buffer sequences is
also a <em>MutableBufferSequence</em>; otherwise the returned buffer also a <em>MutableBufferSequence</em>; otherwise the returned buffer
sequence will be a <em>ConstBufferSequence</em>. sequence will be a <em>ConstBufferSequence</em>.
@see buffers_cat_view @see buffers_cat_view
*/ */
#if BOOST_BEAST_DOXYGEN #if BOOST_BEAST_DOXYGEN

View File

@@ -42,8 +42,9 @@ struct allocate_stable_state final
allocate_stable_state>; allocate_stable_state>;
A a(this->get()); A a(this->get());
detail::allocator_traits<A>::destroy(a, this); auto* p = this;
detail::allocator_traits<A>::deallocate(a, this, 1); p->~allocate_stable_state();
a.deallocate(p, 1);
} }
}; };
@@ -118,33 +119,30 @@ allocate_stable(
{ {
using allocator_type = typename stable_async_base< using allocator_type = typename stable_async_base<
Handler, Executor1, Allocator>::allocator_type; Handler, Executor1, Allocator>::allocator_type;
using state = detail::allocate_stable_state<
State, allocator_type>;
using A = typename detail::allocator_traits< using A = typename detail::allocator_traits<
allocator_type>::template rebind_alloc< allocator_type>::template rebind_alloc<state>;
detail::allocate_stable_state<
State, allocator_type>>;
struct deleter struct deleter
{ {
allocator_type alloc; allocator_type alloc;
detail::allocate_stable_state< state* ptr;
State, allocator_type>* ptr;
~deleter() ~deleter()
{ {
if(ptr) if(ptr)
{ {
A a(alloc); A a(alloc);
detail::allocator_traits<A>::deallocate(a, ptr, 1); a.deallocate(ptr, 1);
} }
} }
}; };
A a(base.get_allocator()); A a(base.get_allocator());
deleter d{base.get_allocator(), nullptr}; deleter d{base.get_allocator(), a.allocate(1)};
d.ptr = detail::allocator_traits<A>::allocate(a, 1); ::new(static_cast<void*>(d.ptr))
detail::allocator_traits<A>::construct(a, d.ptr, state(d.alloc, std::forward<Args>(args)...);
d.alloc, std::forward<Args>(args)...);
d.ptr->next_ = base.list_; d.ptr->next_ = base.list_;
base.list_ = d.ptr; base.list_ = d.ptr;
return boost::exchange(d.ptr, nullptr)->value; return boost::exchange(d.ptr, nullptr)->value;

View File

@@ -302,6 +302,21 @@ public:
buffers_cat(buffers_prefix(i, buffers), cb)); buffers_cat(buffers_prefix(i, buffers), cb));
} }
void
testSingleBuffer()
{
char c[1] = {};
auto b = net::const_buffer(c, 1);
auto bs = buffers_cat(net::const_buffer(c, 1));
auto first = net::buffer_sequence_begin(bs);
auto last = net::buffer_sequence_end(bs);
BOOST_ASSERT(first != last);
BEAST_EXPECT(std::distance(first, last) == 1);
net::const_buffer b2(*first);
BEAST_EXPECT(b.data() == b2.data());
BEAST_EXPECT(b.size() == b2.size());
}
void run() override void run() override
{ {
testBufferSequence(); testBufferSequence();
@@ -309,6 +324,7 @@ public:
testEmpty(); testEmpty();
testGccWarning1(); testGccWarning1();
testGccWarning2(); testGccWarning2();
testSingleBuffer();
} }
}; };