Tune up static_buffer (API Change):

The static buffer is updated:

* reset() is no longer a member. Use b.consume(b.size()) instead.

* Simplified implementaton, uses asio instead of custom types

* Better stream performance: consuming the input makes room
  available in the output. This class is now suitable for
  HTTP reads.

These changes permit the static_buffer wrapper to adapt a user
memory buffer if desired, including a stack based array.
The static_buffer_n class may also be used for this purpose,
it comes with its own storage.
This commit is contained in:
Vinnie Falco
2017-06-07 19:21:33 -07:00
parent 20c59b7e22
commit 53cbeea596
9 changed files with 187 additions and 441 deletions
+32 -32
View File
@@ -16,7 +16,7 @@ namespace beast {
/* Memory is laid out thusly:
p_ ..|.. in_ ..|.. out_ ..|.. last_ ..|.. end_
begin_ ..|.. in_ ..|.. out_ ..|.. last_ ..|.. end_
*/
namespace detail {
@@ -41,13 +41,13 @@ void
basic_flat_buffer<Allocator>::
move_from(basic_flat_buffer& other)
{
p_ = other.p_;
begin_ = other.begin_;
in_ = other.in_;
out_ = other.out_;
last_ = out_;
end_ = other.end_;
max_ = other.max_;
other.p_ = nullptr;
other.begin_ = nullptr;
other.in_ = nullptr;
other.out_ = nullptr;
other.last_ = nullptr;
@@ -65,16 +65,16 @@ copy_from(basic_flat_buffer<
auto const n = other.size();
if(n > 0)
{
p_ = alloc_traits::allocate(
begin_ = alloc_traits::allocate(
this->member(), n);
in_ = p_;
out_ = p_ + n;
in_ = begin_;
out_ = begin_ + n;
last_ = out_;
end_ = out_;
std::memcpy(in_, other.in_, n);
return;
}
p_ = nullptr;
begin_ = nullptr;
in_ = nullptr;
out_ = nullptr;
last_ = nullptr;
@@ -85,9 +85,9 @@ template<class Allocator>
basic_flat_buffer<Allocator>::
~basic_flat_buffer()
{
if(p_)
if(begin_)
alloc_traits::deallocate(
this->member(), p_, dist(p_, end_));
this->member(), begin_, dist(begin_, end_));
}
template<class Allocator>
@@ -160,7 +160,7 @@ basic_flat_buffer(
template<class Allocator>
basic_flat_buffer<Allocator>::
basic_flat_buffer(std::size_t limit)
: p_(nullptr)
: begin_(nullptr)
, in_(nullptr)
, out_(nullptr)
, last_(nullptr)
@@ -176,7 +176,7 @@ basic_flat_buffer(Allocator const& alloc,
std::size_t limit)
: detail::empty_base_optimization<
allocator_type>(alloc)
, p_(nullptr)
, begin_(nullptr)
, in_(nullptr)
, out_(nullptr)
, last_(nullptr)
@@ -204,8 +204,8 @@ prepare(std::size_t n) ->
// after a memmove,
// existing capacity is sufficient
if(len > 0)
std::memmove(p_, in_, len);
in_ = p_;
std::memmove(begin_, in_, len);
in_ = begin_;
out_ = in_ + len;
last_ = out_ + n;
return {out_, n};
@@ -220,19 +220,19 @@ prepare(std::size_t n) ->
detail::next_pow2(len + n), min_size));
auto const p = alloc_traits::allocate(
this->member(), new_size);
if(p_)
if(begin_)
{
BOOST_ASSERT(p);
BOOST_ASSERT(in_);
std::memcpy(p, in_, len);
alloc_traits::deallocate(
this->member(), p_, capacity());
this->member(), begin_, capacity());
}
p_ = p;
in_ = p_;
begin_ = p;
in_ = begin_;
out_ = in_ + len;
last_ = out_ + n;
end_ = p_ + new_size;
end_ = begin_ + new_size;
return {out_, n};
}
@@ -243,8 +243,8 @@ consume(std::size_t n)
{
if(n >= dist(in_, out_))
{
in_ = p_;
out_ = p_;
in_ = begin_;
out_ = begin_;
return;
}
in_ += n;
@@ -266,19 +266,19 @@ reserve(std::size_t n)
auto const p = alloc_traits::allocate(
this->member(), new_size);
auto const len = size();
if(p_)
if(begin_)
{
BOOST_ASSERT(p_);
BOOST_ASSERT(begin_);
BOOST_ASSERT(in_);
std::memcpy(p, in_, len);
alloc_traits::deallocate(
this->member(), p_, capacity());
this->member(), begin_, capacity());
}
p_ = p;
in_ = p_;
out_ = p_ + len;
begin_ = p;
in_ = begin_;
out_ = begin_ + len;
last_ = out_;
end_ = p_ + new_size;
end_ = begin_ + new_size;
}
template<class Allocator>
@@ -292,7 +292,7 @@ shrink_to_fit()
char* p;
if(len > 0)
{
BOOST_ASSERT(p_);
BOOST_ASSERT(begin_);
BOOST_ASSERT(in_);
p = alloc_traits::allocate(
this->member(), len);
@@ -303,10 +303,10 @@ shrink_to_fit()
p = nullptr;
}
alloc_traits::deallocate(
this->member(), p_, dist(p_, end_));
p_ = p;
in_ = p_;
out_ = p_ + len;
this->member(), begin_, dist(begin_, end_));
begin_ = p;
in_ = begin_;
out_ = begin_ + len;
last_ = out_;
end_ = out_;
}
+64 -267
View File
@@ -18,288 +18,85 @@
namespace beast {
class static_buffer::const_buffers_type
{
std::size_t n_;
std::uint8_t const* p_;
/* Memory is laid out thusly:
public:
using value_type = boost::asio::const_buffer;
class const_iterator;
const_buffers_type() = delete;
const_buffers_type(
const_buffers_type const&) = default;
const_buffers_type& operator=(
const_buffers_type const&) = default;
const_iterator
begin() const;
const_iterator
end() const;
private:
friend class static_buffer;
const_buffers_type(
std::uint8_t const* p, std::size_t n)
: n_(n)
, p_(p)
{
}
};
class static_buffer::const_buffers_type::const_iterator
{
std::size_t n_ = 0;
std::uint8_t const* p_ = nullptr;
public:
using value_type = boost::asio::const_buffer;
using pointer = value_type const*;
using reference = value_type;
using difference_type = std::ptrdiff_t;
using iterator_category =
std::bidirectional_iterator_tag;
const_iterator() = default;
const_iterator(const_iterator&& other) = default;
const_iterator(const_iterator const& other) = default;
const_iterator& operator=(const_iterator&& other) = default;
const_iterator& operator=(const_iterator const& other) = default;
bool
operator==(const_iterator const& other) const
{
return p_ == other.p_;
}
bool
operator!=(const_iterator const& other) const
{
return !(*this == other);
}
reference
operator*() const
{
return value_type{p_, n_};
}
pointer
operator->() const = delete;
const_iterator&
operator++()
{
p_ += n_;
return *this;
}
const_iterator
operator++(int)
{
auto temp = *this;
++(*this);
return temp;
}
const_iterator&
operator--()
{
p_ -= n_;
return *this;
}
const_iterator
operator--(int)
{
auto temp = *this;
--(*this);
return temp;
}
private:
friend class const_buffers_type;
const_iterator(
std::uint8_t const* p, std::size_t n)
: n_(n)
, p_(p)
{
}
};
begin_ ..|.. in_ ..|.. out_ ..|.. last_ ..|.. end_
*/
inline
auto
static_buffer::const_buffers_type::begin() const ->
const_iterator
{
return const_iterator{p_, n_};
}
inline
auto
static_buffer::const_buffers_type::end() const ->
const_iterator
{
return const_iterator{p_ + n_, n_};
}
//------------------------------------------------------------------------------
class static_buffer::mutable_buffers_type
{
std::size_t n_;
std::uint8_t* p_;
public:
using value_type = boost::asio::mutable_buffer;
class const_iterator;
mutable_buffers_type() = delete;
mutable_buffers_type(
mutable_buffers_type const&) = default;
mutable_buffers_type& operator=(
mutable_buffers_type const&) = default;
const_iterator
begin() const;
const_iterator
end() const;
private:
friend class static_buffer;
mutable_buffers_type(
std::uint8_t* p, std::size_t n)
: n_(n)
, p_(p)
{
}
};
class static_buffer::mutable_buffers_type::const_iterator
{
std::size_t n_ = 0;
std::uint8_t* p_ = nullptr;
public:
using value_type = boost::asio::mutable_buffer;
using pointer = value_type const*;
using reference = value_type;
using difference_type = std::ptrdiff_t;
using iterator_category =
std::bidirectional_iterator_tag;
const_iterator() = default;
const_iterator(const_iterator&& other) = default;
const_iterator(const_iterator const& other) = default;
const_iterator& operator=(const_iterator&& other) = default;
const_iterator& operator=(const_iterator const& other) = default;
bool
operator==(const_iterator const& other) const
{
return p_ == other.p_;
}
bool
operator!=(const_iterator const& other) const
{
return !(*this == other);
}
reference
operator*() const
{
return value_type{p_, n_};
}
pointer
operator->() const = delete;
const_iterator&
operator++()
{
p_ += n_;
return *this;
}
const_iterator
operator++(int)
{
auto temp = *this;
++(*this);
return temp;
}
const_iterator&
operator--()
{
p_ -= n_;
return *this;
}
const_iterator
operator--(int)
{
auto temp = *this;
--(*this);
return temp;
}
private:
friend class mutable_buffers_type;
const_iterator(std::uint8_t* p, std::size_t n)
: n_(n)
, p_(p)
{
}
};
inline
auto
static_buffer::mutable_buffers_type::begin() const ->
const_iterator
{
return const_iterator{p_, n_};
}
inline
auto
static_buffer::mutable_buffers_type::end() const ->
const_iterator
{
return const_iterator{p_ + n_, n_};
}
//------------------------------------------------------------------------------
inline
auto
static_buffer::data() const ->
static_buffer::
data() const ->
const_buffers_type
{
return const_buffers_type{in_,
static_cast<std::size_t>(out_ - in_)};
return {in_, dist(in_, out_)};
}
inline
auto
static_buffer::prepare(std::size_t n) ->
static_buffer::
prepare(std::size_t n) ->
mutable_buffers_type
{
if(n > static_cast<std::size_t>(end_ - out_))
return prepare_impl(n);
}
inline
void
static_buffer::
reset(void* p, std::size_t n)
{
reset_impl(p, n);
}
template<class>
void
static_buffer::
reset_impl(void* p, std::size_t n)
{
begin_ =
reinterpret_cast<char*>(p);
in_ = begin_;
out_ = begin_;
last_ = begin_;
end_ = begin_ + n;
}
template<class>
auto
static_buffer::
prepare_impl(std::size_t n) ->
mutable_buffers_type
{
if(n <= dist(out_, end_))
{
last_ = out_ + n;
return {out_, n};
}
auto const len = size();
if(n > capacity() - len)
BOOST_THROW_EXCEPTION(std::length_error{
"static_buffer overflow"});
if(len > 0)
std::memmove(begin_, in_, len);
in_ = begin_;
out_ = in_ + len;
last_ = out_ + n;
return mutable_buffers_type{out_, n};
return {out_, n};
}
template<class>
void
static_buffer::
consume_impl(std::size_t n)
{
if(n >= size())
{
in_ = begin_;
out_ = in_;
return;
}
in_ += n;
}
} // beast