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

View File

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

View File

@@ -302,6 +302,21 @@ public:
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
{
testBufferSequence();
@@ -309,6 +324,7 @@ public:
testEmpty();
testGccWarning1();
testGccWarning2();
testSingleBuffer();
}
};