Reduce template instantiations

This commit is contained in:
Vinnie Falco
2019-02-22 20:08:20 -08:00
parent 46eb006757
commit d4dddec1c0
6 changed files with 84 additions and 284 deletions

View File

@@ -44,6 +44,7 @@ class read_op
Stream& s_;
DynamicBuffer& b_;
Condition cond_;
error_code ec_;
std::size_t total_ = 0;
public:
@@ -72,13 +73,14 @@ public:
std::size_t bytes_transferred,
bool cont = true)
{
ec_ = ec;
std::size_t max_size;
std::size_t max_prepare;
BOOST_ASIO_CORO_REENTER(*this)
{
for(;;)
{
max_size = cond_(ec, total_, b_);
max_size = cond_(ec_, total_, b_);
max_prepare = std::min<std::size_t>(
std::max<std::size_t>(
512, b_.capacity() - b_.size()),
@@ -92,115 +94,21 @@ public:
b_.commit(bytes_transferred);
total_ += bytes_transferred;
}
this->invoke(cont, ec, total_);
if(! cont)
{
// run this handler "as-if" using net::post
// to reduce template instantiations
BOOST_ASIO_CORO_YIELD
s_.async_read_some(
b_.prepare(0), std::move(*this));
}
this->invoke_now(ec_, total_);
}
}
};
//------------------------------------------------------------------------------
#ifdef BOOST_BEAST_ENABLE_NON_BLOCKING
// EXPERIMENTAL
// optimized non-blocking read algorithm
template<
class Protocol, class Executor,
class DynamicBuffer,
class Condition,
class Handler>
class read_non_blocking_op
: public net::coroutine
, public async_op_base<Handler, Executor>
{
net::basic_stream_socket<
Protocol, Executor>& s_;
DynamicBuffer& b_;
Condition cond_;
std::size_t limit_;
std::size_t total_ = 0;
public:
read_non_blocking_op(read_non_blocking_op&&) = default;
read_non_blocking_op(read_non_blocking_op const&) = delete;
template<class Handler_, class Condition_>
read_non_blocking_op(
Handler_&& h,
net::basic_stream_socket<
Protocol, Executor>& s,
DynamicBuffer& b,
Condition cond)
: async_op_base<Handler, Executor>(
s.get_executor(), std::forward<Handler_>(h))
, s_(s)
, b_(b)
, cond_(std::forward<Condition_>(cond))
{
(*this)({}, false);
}
void
operator()(error_code ec, bool cont = true)
{
std::size_t n;
std::size_t bytes_transferred;
BOOST_ASIO_CORO_REENTER(*this)
{
limit_ = cond_(ec, total_, b_);
for(;;)
{
n = detail::min<std::size_t>(
limit_, b_.max_size() - b_.size());
if(n == 0)
break;
BOOST_ASIO_CORO_YIELD
s_.async_wait(
net::socket_base::wait_read, std::move(*this));
if(b_.size() <= default_max_stack_buffer)
{
flat_static_buffer<
default_max_stack_buffer> sb;
bytes_transferred = net::buffer_copy(
sb.prepare(b_.size()), b_.data());
sb.commit(bytes_transferred);
b_.consume(bytes_transferred);
//detail::shrink_to_fit(b_);
n = detail::min<std::size_t>(
limit_,
sb.capacity() - sb.size(),
b_.max_size() - sb.size());
BOOST_ASSERT(n > 0);
bytes_transferred =
s_.read_some(sb.prepare(n), ec);
sb.commit(bytes_transferred);
total_ += bytes_transferred;
limit_ = cond_(ec, total_, sb);
b_.commit(net::buffer_copy(
b_.prepare(sb.size()), sb.data()));
}
else
{
n = detail::min<std::size_t>(
limit_,
s_.available(),
b_.max_size() - b_.size(),
std::max<std::size_t>(
512, b_.capacity() - b_.size()));
BOOST_ASSERT(n > 0);
bytes_transferred = s_.read_some(
b_.prepare(n), ec);
b_.commit(bytes_transferred);
total_ += bytes_transferred;
limit_ = cond_(ec, total_, b_);
}
}
this->invoke(cont, ec, total_);
}
}
};
#endif
struct run_read_op
{
template<
@@ -235,54 +143,6 @@ struct run_read_op
std::forward<Condition>(c));
}
#if BOOST_BEAST_ENABLE_NON_BLOCKING
template<
class Protocol, class Executor,
class DynamicBuffer,
class Condition,
class ReadHandler>
void
operator()(
net::basic_stream_socket<Protocol, Executor>& s,
DynamicBuffer& b,
Condition&& c,
ReadHandler&& h)
{
// If you get an error on the following line it means
// that your handler does not meet the documented type
// requirements for the handler.
static_assert(
beast::detail::is_invocable<ReadHandler,
void(error_code, std::size_t)>::value,
"ReadHandler type requirements not met");
if(s.non_blocking())
{
read_non_blocking_op<
Protocol, Executor,
DynamicBuffer,
typename std::decay<Condition>::type,
typename std::decay<ReadHandler>::type>(
std::forward<ReadHandler>(h),
s,
b,
std::forward<Condition>(c));
}
else
{
read_op<
net::basic_stream_socket<Protocol, Executor>,
DynamicBuffer,
typename std::decay<Condition>::type,
typename std::decay<ReadHandler>::type>(
std::forward<ReadHandler>(h),
s,
b,
std::forward<Condition>(c));
}
}
#endif
};
};
@@ -360,92 +220,6 @@ read(
return total;
}
#ifdef BOOST_BEAST_ENABLE_NON_BLOCKING
template<
class Protocol,
class DynamicBuffer,
class CompletionCondition>
std::size_t
read(
net::basic_stream_socket<Protocol>& socket,
DynamicBuffer& buffer,
CompletionCondition cond,
error_code& ec)
{
static_assert(
net::is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer type requirements not met");
static_assert(
detail::is_invocable<CompletionCondition,
void(error_code&, std::size_t, DynamicBuffer&)>::value,
"CompletionCondition type requirements not met");
ec = {};
std::size_t n;
std::size_t limit;
std::size_t total = 0;
std::size_t bytes_transferred;
limit = cond(ec, total, buffer);
for(;;)
{
n = detail::min<std::size_t>(
limit, buffer.max_size() - buffer.size());
if(n == 0)
break;
socket.non_blocking(false);
socket.wait(net::socket_base::wait_read, ec);
socket.non_blocking(true);
if(ec)
{
limit = cond(ec, total, buffer);
}
else if(buffer.size() <= default_max_stack_buffer)
{
flat_static_buffer<
default_max_stack_buffer> sb;
bytes_transferred = net::buffer_copy(
sb.prepare(buffer.size()), buffer.data());
sb.commit(bytes_transferred);
buffer.consume(bytes_transferred);
//detail::shrink_to_fit(buffer);
n = detail::min<std::size_t>(
limit,
sb.capacity() - sb.size(),
buffer.max_size() - sb.size());
BOOST_ASSERT(n > 0);
bytes_transferred =
socket.read_some(sb.prepare(n), ec);
if(ec != net::error::would_block)
{
sb.commit(bytes_transferred);
total += bytes_transferred;
limit = cond(ec, total, sb);
}
buffer.commit(net::buffer_copy(
buffer.prepare(sb.size()), sb.data()));
}
else
{
n = detail::min<std::size_t>(
limit,
socket.available(),
buffer.max_size() - buffer.size(),
std::max<std::size_t>(
512, buffer.capacity() - buffer.size()));
BOOST_ASSERT(n > 0);
bytes_transferred = socket.read_some(
buffer.prepare(n), ec);
if(ec != net::error::would_block)
{
buffer.commit(bytes_transferred);
total += bytes_transferred;
limit = cond(ec, total, buffer);
}
}
}
return total;
}
#endif
template<
class AsyncReadStream,
class DynamicBuffer,

View File

@@ -17,7 +17,6 @@
#include <boost/assert.hpp>
#include <boost/core/empty_value.hpp>
#include <boost/core/exchange.hpp>
#include <memory>
#include <utility>
namespace boost {
@@ -95,29 +94,6 @@ public:
//------------------------------------------------------------------------------
saved_handler::
~saved_handler()
{
if(p_)
p_->destroy();
}
saved_handler::
saved_handler(saved_handler&& other) noexcept
: p_(boost::exchange(other.p_, nullptr))
{
}
saved_handler&
saved_handler::
operator=(saved_handler&& other) noexcept
{
// Can't delete a handler before invoking
BOOST_ASSERT(! has_value());
p_ = boost::exchange(other.p_, nullptr);
return *this;
}
template<class Handler, class Allocator>
void
saved_handler::
@@ -169,27 +145,6 @@ emplace(Handler&& handler)
net::get_associated_allocator(handler));
}
void
saved_handler::
invoke()
{
// Can't invoke without a value
BOOST_ASSERT(has_value());
boost::exchange(
p_, nullptr)->invoke();
}
bool
saved_handler::
maybe_invoke()
{
if(! p_)
return false;
boost::exchange(
p_, nullptr)->invoke();
return true;
}
} // beast
} // boost

View File

@@ -0,0 +1,66 @@
//
// Copyright (c) 2016-2019 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_CORE_IMPL_SAVED_HANDLER_IPP
#define BOOST_BEAST_CORE_IMPL_SAVED_HANDLER_IPP
#include <boost/beast/core/saved_handler.hpp>
#include <boost/core/exchange.hpp>
namespace boost {
namespace beast {
saved_handler::
~saved_handler()
{
if(p_)
p_->destroy();
}
saved_handler::
saved_handler(saved_handler&& other) noexcept
: p_(boost::exchange(other.p_, nullptr))
{
}
saved_handler&
saved_handler::
operator=(saved_handler&& other) noexcept
{
// Can't delete a handler before invoking
BOOST_ASSERT(! has_value());
p_ = boost::exchange(other.p_, nullptr);
return *this;
}
void
saved_handler::
invoke()
{
// Can't invoke without a value
BOOST_ASSERT(has_value());
boost::exchange(
p_, nullptr)->invoke();
}
bool
saved_handler::
maybe_invoke()
{
if(! p_)
return false;
boost::exchange(
p_, nullptr)->invoke();
return true;
}
} // beast
} // boost
#endif

View File

@@ -120,5 +120,8 @@ public:
} // boost
#include <boost/beast/core/impl/saved_handler.hpp>
#ifdef BOOST_BEAST_HEADER_ONLY
#include <boost/beast/core/impl/saved_handler.ipp>
#endif
#endif

View File

@@ -34,6 +34,8 @@ the program, with the macro BOOST_BEAST_SPLIT_COMPILATION defined.
#include <boost/beast/core/impl/file_posix.ipp>
#include <boost/beast/core/impl/file_stdio.ipp>
#include <boost/beast/core/impl/file_win32.ipp>
#include <boost/beast/core/impl/flat_static_buffer.ipp>
#include <boost/beast/core/impl/saved_handler.ipp>
#include <boost/beast/core/impl/static_buffer.ipp>
#include <boost/beast/http/impl/error.ipp>

View File

@@ -2727,7 +2727,7 @@ private:
@see stream::secure_prng
*/
BOOST_BEAST_DECL
inline
void
seed_prng(std::seed_seq& ss)
{