static_buffer improvements:

* Revise documentation
* Specify exception safety
* Mark more functions noexcept
This commit is contained in:
Vinnie Falco
2018-12-08 11:51:47 -08:00
parent 4fec064ad8
commit 3e695d588a
4 changed files with 151 additions and 97 deletions

View File

@ -2,6 +2,7 @@ Version 198:
* flat_buffer improvements
* multi_buffer improvements
* static_buffer improvements
API Changes:

View File

@ -0,0 +1,90 @@
//
// Copyright (c) 2018 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/beast
//
#ifndef BOOST_BEAST_DETAIL_BUFFERS_PAIR_HPP
#define BOOST_BEAST_DETAIL_BUFFERS_PAIR_HPP
#include <boost/asio/buffer.hpp>
#include <boost/assert.hpp>
#include <type_traits>
namespace boost {
namespace beast {
namespace detail {
template<bool IsMutable>
class buffers_pair
{
template<bool IsMutable_>
friend class buffers_pair;
public:
// VFALCO: This type is public otherwise
// asio::buffers_iterator won't compile.
using value_type = typename
std::conditional<IsMutable,
net::mutable_buffer,
net::const_buffer>::type;
using const_iterator = value_type const*;
buffers_pair() = default;
buffers_pair(buffers_pair const&) = default;
buffers_pair& operator=(buffers_pair const&) = default;
template<
bool IsMutable_ = IsMutable,
class = typename
std::enable_if<! IsMutable_>::type>
buffers_pair(
buffers_pair<true> const& other) noexcept
: b_{other.b_[0], other.b_[1]}
{
}
template<
bool IsMutable_ = IsMutable,
class = typename
std::enable_if<! IsMutable_>::type>
buffers_pair& operator=(
buffers_pair<true> const& other) noexcept
{
b_ = {other.b_[0], other.b_[1]};
return *this;
}
value_type&
operator[](int i) noexcept
{
BOOST_ASSERT(i >= 0 && i < 2);
return b_[i];
}
const_iterator
begin() const noexcept
{
return &b_[0];
}
const_iterator
end() const noexcept
{
if(b_[1].size() > 0)
return &b_[2];
return &b_[1];
}
private:
value_type b_[2];
};
} // detail
} // beast
} // boost
#endif

View File

@ -21,15 +21,14 @@
namespace boost {
namespace beast {
inline
static_buffer_base::
static_buffer_base(void* p, std::size_t size) noexcept
static_buffer_base(
void* p, std::size_t size) noexcept
: begin_(static_cast<char*>(p))
, capacity_(size)
{
}
inline
auto
static_buffer_base::
data() const noexcept ->
@ -50,7 +49,6 @@ data() const noexcept ->
return result;
}
inline
auto
static_buffer_base::
data() noexcept ->
@ -71,7 +69,6 @@ data() noexcept ->
return result;
}
inline
auto
static_buffer_base::
prepare(std::size_t n) ->
@ -97,7 +94,6 @@ prepare(std::size_t n) ->
return result;
}
inline
void
static_buffer_base::
commit(std::size_t n) noexcept
@ -106,7 +102,6 @@ commit(std::size_t n) noexcept
out_size_ = 0;
}
inline
void
static_buffer_base::
consume(std::size_t n) noexcept
@ -126,7 +121,6 @@ consume(std::size_t n) noexcept
}
}
inline
void
static_buffer_base::
reset(void* p, std::size_t n) noexcept
@ -142,23 +136,21 @@ reset(void* p, std::size_t n) noexcept
template<std::size_t N>
static_buffer<N>::
static_buffer(static_buffer const& other)
static_buffer(static_buffer const& other) noexcept
: static_buffer_base(buf_, N)
{
using net::buffer_copy;
this->commit(buffer_copy(
this->commit(net::buffer_copy(
this->prepare(other.size()), other.data()));
}
template<std::size_t N>
auto
static_buffer<N>::
operator=(static_buffer const& other) ->
operator=(static_buffer const& other) noexcept ->
static_buffer<N>&
{
using net::buffer_copy;
this->consume(this->size());
this->commit(buffer_copy(
this->commit(net::buffer_copy(
this->prepare(other.size()), other.data()));
return *this;
}

View File

@ -11,6 +11,7 @@
#define BOOST_BEAST_STATIC_BUFFER_HPP
#include <boost/beast/core/detail/config.hpp>
#include <boost/beast/core/detail/buffers_pair.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/assert.hpp>
#include <algorithm>
@ -21,75 +22,7 @@
namespace boost {
namespace beast {
namespace detail {
template<bool IsMutable>
class buffers_pair
{
template<bool IsMutable_>
friend class buffers_pair;
public:
// VFALCO: This type is public otherwise
// asio::buffers_iterator won't compile.
using value_type = typename
std::conditional<IsMutable,
net::mutable_buffer,
net::const_buffer>::type;
using const_iterator =
value_type const*;
buffers_pair() = default;
buffers_pair(buffers_pair const&) = default;
buffers_pair& operator=(buffers_pair const&) = default;
template<
bool IsMutable_ = IsMutable,
class = typename std::enable_if<! IsMutable_>::type>
buffers_pair(buffers_pair<true> const& other) noexcept
: b_{other.b_[0], other.b_[1]}
{
}
template<
bool IsMutable_ = IsMutable,
class = typename std::enable_if<! IsMutable_>::type>
buffers_pair& operator=(
buffers_pair<true> const& other) noexcept
{
b_ = {other.b_[0], other.b_[1]};
return *this;
}
value_type&
operator[](int i) noexcept
{
BOOST_ASSERT(i >= 0 && i < 2);
return b_[i];
}
const_iterator
begin() const noexcept
{
return &b_[0];
}
const_iterator
end() const noexcept
{
if(b_[1].size() > 0)
return &b_[2];
else
return &b_[1];
}
private:
value_type b_[2];
};
} // detail
/** A dynamic buffer providing a fixed, circular buffer.
/** A dynamic buffer providing a fixed size, circular buffer.
A dynamic buffer encapsulates memory storage that may be
automatically resized as required, where the memory is
@ -106,8 +39,8 @@ private:
bytes is returned by @ref data when `this` is non-const.
@li Buffer sequences representing the readable and writable
bytes, returned by @ref data and @ref prepare, will have
length at most one.
bytes, returned by @ref data and @ref prepare, may have
length up to two.
@li All operations execute in constant time.
@ -140,6 +73,7 @@ public:
@param size The number of valid bytes pointed to by `p`.
*/
inline
static_buffer_base(void* p, std::size_t size) noexcept;
//--------------------------------------------------------------------------
@ -181,6 +115,7 @@ public:
}
/// Returns a constant buffer sequence representing the readable bytes
inline
const_buffers_type
data() const noexcept;
@ -192,6 +127,7 @@ public:
}
/// Returns a mutable buffer sequence representing the readable bytes
inline
mutable_data_type
data() noexcept;
@ -208,7 +144,12 @@ public:
sequence.
@throws std::length_error if `size() + n` exceeds `max_size()`.
@par Exception Safety
Strong guarantee.
*/
inline
mutable_buffers_type
prepare(std::size_t n);
@ -225,7 +166,12 @@ public:
@param n The number of bytes to append. If this number
is greater than the number of writable bytes, all
writable bytes are appended.
@par Exception Safety
No-throw guarantee.
*/
inline
void
commit(std::size_t n) noexcept;
@ -239,7 +185,12 @@ public:
@param n The number of bytes to remove. If this number
is greater than the number of readable bytes, all
readable bytes are removed.
@par Exception Safety
No-throw guarantee.
*/
inline
void
consume(std::size_t n) noexcept;
@ -262,19 +213,39 @@ protected:
@param p A pointer to valid storage of at least `n` bytes.
@param size The number of valid bytes pointed to by `p`.
@par Exception Safety
No-throw guarantee.
*/
inline
void
reset(void* p, std::size_t size) noexcept;
};
//------------------------------------------------------------------------------
/** A circular @b DynamicBuffer with a fixed size internal buffer.
/** A dynamic buffer providing a fixed size, circular buffer.
This implements a circular dynamic buffer. Calls to @ref prepare
never require moving memory. The buffer sequences returned may
be up to length two.
Ownership of the underlying storage belongs to the derived class.
A dynamic buffer encapsulates memory storage that may be
automatically resized as required, where the memory is
divided into two regions: readable bytes followed by
writable bytes. These memory regions are internal to
the dynamic buffer, but direct access to the elements
is provided to permit them to be efficiently used with
I/O operations.
Objects of this type meet the requirements of @b DynamicBuffer
and have the following additional properties:
@li A mutable buffer sequence representing the readable
bytes is returned by @ref data when `this` is non-const.
@li Buffer sequences representing the readable and writable
bytes, returned by @ref data and @ref prepare, may have
length up to two.
@li All operations execute in constant time.
@tparam N The number of bytes in the internal buffer.
@ -291,41 +262,41 @@ class static_buffer : public static_buffer_base
public:
/// Constructor
static_buffer(static_buffer const&);
static_buffer(static_buffer const&) noexcept;
/// Constructor
static_buffer()
static_buffer() noexcept
: static_buffer_base(buf_, N)
{
}
/// Assignment
static_buffer& operator=(static_buffer const&);
static_buffer& operator=(static_buffer const&) noexcept;
/// Returns the @ref static_buffer_base portion of this object
static_buffer_base&
base()
base() noexcept
{
return *this;
}
/// Returns the @ref static_buffer_base portion of this object
static_buffer_base const&
base() const
base() const noexcept
{
return *this;
}
/// Return the maximum sum of the input and output sequence sizes.
std::size_t constexpr
max_size() const
max_size() const noexcept
{
return N;
}
/// Return the maximum sum of input and output sizes that can be held without an allocation.
std::size_t constexpr
capacity() const
capacity() const noexcept
{
return N;
}