Created
June 24, 2020 19:31
-
-
Save vinniefalco/3359ffa2bccccc95e9eab67d79577a61 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** A shared buffer sequence of length 1. | |
This is a reference counted, copyable handle to a constant | |
buffer sequence of length one. It is used for broadcasting. | |
The originating buffers are copied upon construction. | |
*/ | |
class message | |
{ | |
struct impl | |
{ | |
net::const_buffer cb; | |
std::atomic<std::size_t> count; | |
explicit | |
impl(std::size_t n) | |
: cb(this + 1, n) | |
, count(1) | |
{ | |
} | |
}; | |
impl* p_ = nullptr; | |
using allocator = std::allocator<impl>; | |
template<class Buffers> | |
impl* | |
construct( | |
Buffers const& buffers) | |
{ | |
allocator a; | |
auto const n = | |
net::buffer_size(buffers); | |
auto const p = ::new(a.allocate( | |
(2 * sizeof(impl) + n - 1) / | |
sizeof(impl))) impl(n); | |
net::buffer_copy( | |
net::mutable_buffer( | |
p + 1, n), | |
buffers); | |
return p; | |
} | |
public: | |
using value_type = net::const_buffer; | |
using iterator = value_type const*; | |
// Construct a null message | |
message() = default; | |
// immutable | |
message& | |
operator=( | |
message const&) = delete; | |
~message() | |
{ | |
if(p_ && --p_->count == 0) | |
{ | |
allocator a; | |
a.deallocate(p_, | |
(2 * sizeof(impl) + | |
p_->cb.size() - 1) / | |
sizeof(impl)); | |
} | |
} | |
/** Construct a message from a buffer sequence | |
This function allocates a flat copy of the input | |
buffer sequence. | |
*/ | |
template< | |
class ConstBufferSequence | |
#ifndef BOOST_BEAST_DOXYGEN | |
,class = typename std::enable_if< | |
net::is_const_buffer_sequence< | |
ConstBufferSequence>::value>::type | |
#endif | |
> | |
message( | |
ConstBufferSequence const& buffers) | |
: p_(construct(buffers)) | |
{ | |
} | |
message(message&& other) noexcept | |
{ | |
p_ = other.p_; | |
other.p_ = nullptr; | |
} | |
message(message const& other) noexcept | |
: p_(other.p_) | |
{ | |
if(p_) | |
++p_->count; | |
} | |
iterator | |
begin() const noexcept | |
{ | |
return &p_->cb; | |
} | |
iterator | |
end() const noexcept | |
{ | |
return begin() + 1; | |
} | |
friend | |
void | |
swap( | |
message& lhs, | |
message& rhs) noexcept | |
{ | |
std::swap( | |
lhs.p_, rhs.p_); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment