diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b1af64e..870048a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 -------------------------------------------------------------------------------- diff --git a/include/boost/beast/core/buffers_cat.hpp b/include/boost/beast/core/buffers_cat.hpp index 532ea32e..0f989210 100644 --- a/include/boost/beast/core/buffers_cat.hpp +++ b/include/boost/beast/core/buffers_cat.hpp @@ -19,7 +19,6 @@ namespace boost { namespace beast { /** A buffer sequence representing a concatenation of buffer sequences. - @see buffers_cat */ template @@ -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 MutableBufferSequence, 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 MutableBufferSequence if each of the passed buffer sequences is also a MutableBufferSequence; otherwise the returned buffer sequence will be a ConstBufferSequence. - @see buffers_cat_view */ #if BOOST_BEAST_DOXYGEN diff --git a/include/boost/beast/core/impl/async_base.hpp b/include/boost/beast/core/impl/async_base.hpp index ec17b1cc..8dc8cb29 100644 --- a/include/boost/beast/core/impl/async_base.hpp +++ b/include/boost/beast/core/impl/async_base.hpp @@ -42,8 +42,9 @@ struct allocate_stable_state final allocate_stable_state>; A a(this->get()); - detail::allocator_traits::destroy(a, this); - detail::allocator_traits::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; struct deleter { allocator_type alloc; - detail::allocate_stable_state< - State, allocator_type>* ptr; + state* ptr; ~deleter() { if(ptr) { A a(alloc); - detail::allocator_traits::deallocate(a, ptr, 1); + a.deallocate(ptr, 1); } } }; A a(base.get_allocator()); - deleter d{base.get_allocator(), nullptr}; - d.ptr = detail::allocator_traits::allocate(a, 1); - detail::allocator_traits::construct(a, d.ptr, - d.alloc, std::forward(args)...); + deleter d{base.get_allocator(), a.allocate(1)}; + ::new(static_cast(d.ptr)) + state(d.alloc, std::forward(args)...); d.ptr->next_ = base.list_; base.list_ = d.ptr; return boost::exchange(d.ptr, nullptr)->value; diff --git a/test/beast/core/buffers_cat.cpp b/test/beast/core/buffers_cat.cpp index 5c894469..b8ed48c9 100644 --- a/test/beast/core/buffers_cat.cpp +++ b/test/beast/core/buffers_cat.cpp @@ -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(); } };