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

View File

@ -11,6 +11,7 @@
#define BOOST_BEAST_STATIC_BUFFER_HPP #define BOOST_BEAST_STATIC_BUFFER_HPP
#include <boost/beast/core/detail/config.hpp> #include <boost/beast/core/detail/config.hpp>
#include <boost/beast/core/detail/buffers_pair.hpp>
#include <boost/asio/buffer.hpp> #include <boost/asio/buffer.hpp>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <algorithm> #include <algorithm>
@ -21,75 +22,7 @@
namespace boost { namespace boost {
namespace beast { namespace beast {
namespace detail { /** A dynamic buffer providing a fixed size, circular buffer.
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 encapsulates memory storage that may be A dynamic buffer encapsulates memory storage that may be
automatically resized as required, where the memory is automatically resized as required, where the memory is
@ -106,8 +39,8 @@ private:
bytes is returned by @ref data when `this` is non-const. bytes is returned by @ref data when `this` is non-const.
@li Buffer sequences representing the readable and writable @li Buffer sequences representing the readable and writable
bytes, returned by @ref data and @ref prepare, will have bytes, returned by @ref data and @ref prepare, may have
length at most one. length up to two.
@li All operations execute in constant time. @li All operations execute in constant time.
@ -140,6 +73,7 @@ public:
@param size The number of valid bytes pointed to by `p`. @param size The number of valid bytes pointed to by `p`.
*/ */
inline
static_buffer_base(void* p, std::size_t size) noexcept; static_buffer_base(void* p, std::size_t size) noexcept;
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@ -181,6 +115,7 @@ public:
} }
/// Returns a constant buffer sequence representing the readable bytes /// Returns a constant buffer sequence representing the readable bytes
inline
const_buffers_type const_buffers_type
data() const noexcept; data() const noexcept;
@ -192,6 +127,7 @@ public:
} }
/// Returns a mutable buffer sequence representing the readable bytes /// Returns a mutable buffer sequence representing the readable bytes
inline
mutable_data_type mutable_data_type
data() noexcept; data() noexcept;
@ -208,7 +144,12 @@ public:
sequence. sequence.
@throws std::length_error if `size() + n` exceeds `max_size()`. @throws std::length_error if `size() + n` exceeds `max_size()`.
@par Exception Safety
Strong guarantee.
*/ */
inline
mutable_buffers_type mutable_buffers_type
prepare(std::size_t n); prepare(std::size_t n);
@ -225,7 +166,12 @@ public:
@param n The number of bytes to append. If this number @param n The number of bytes to append. If this number
is greater than the number of writable bytes, all is greater than the number of writable bytes, all
writable bytes are appended. writable bytes are appended.
@par Exception Safety
No-throw guarantee.
*/ */
inline
void void
commit(std::size_t n) noexcept; commit(std::size_t n) noexcept;
@ -239,7 +185,12 @@ public:
@param n The number of bytes to remove. If this number @param n The number of bytes to remove. If this number
is greater than the number of readable bytes, all is greater than the number of readable bytes, all
readable bytes are removed. readable bytes are removed.
@par Exception Safety
No-throw guarantee.
*/ */
inline
void void
consume(std::size_t n) noexcept; consume(std::size_t n) noexcept;
@ -262,19 +213,39 @@ protected:
@param p A pointer to valid storage of at least `n` bytes. @param p A pointer to valid storage of at least `n` bytes.
@param size The number of valid bytes pointed to by `p`. @param size The number of valid bytes pointed to by `p`.
@par Exception Safety
No-throw guarantee.
*/ */
inline
void void
reset(void* p, std::size_t size) noexcept; 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 A dynamic buffer encapsulates memory storage that may be
never require moving memory. The buffer sequences returned may automatically resized as required, where the memory is
be up to length two. divided into two regions: readable bytes followed by
Ownership of the underlying storage belongs to the derived class. 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. @tparam N The number of bytes in the internal buffer.
@ -291,41 +262,41 @@ class static_buffer : public static_buffer_base
public: public:
/// Constructor /// Constructor
static_buffer(static_buffer const&); static_buffer(static_buffer const&) noexcept;
/// Constructor /// Constructor
static_buffer() static_buffer() noexcept
: static_buffer_base(buf_, N) : static_buffer_base(buf_, N)
{ {
} }
/// Assignment /// Assignment
static_buffer& operator=(static_buffer const&); static_buffer& operator=(static_buffer const&) noexcept;
/// Returns the @ref static_buffer_base portion of this object /// Returns the @ref static_buffer_base portion of this object
static_buffer_base& static_buffer_base&
base() base() noexcept
{ {
return *this; return *this;
} }
/// Returns the @ref static_buffer_base portion of this object /// Returns the @ref static_buffer_base portion of this object
static_buffer_base const& static_buffer_base const&
base() const base() const noexcept
{ {
return *this; return *this;
} }
/// Return the maximum sum of the input and output sequence sizes. /// Return the maximum sum of the input and output sequence sizes.
std::size_t constexpr std::size_t constexpr
max_size() const max_size() const noexcept
{ {
return N; return N;
} }
/// Return the maximum sum of input and output sizes that can be held without an allocation. /// Return the maximum sum of input and output sizes that can be held without an allocation.
std::size_t constexpr std::size_t constexpr
capacity() const capacity() const noexcept
{ {
return N; return N;
} }