mirror of
https://github.com/boostorg/beast.git
synced 2025-08-02 22:34:32 +02:00
Reduce template instantiations
This commit is contained in:
@@ -44,6 +44,7 @@ class read_op
|
|||||||
Stream& s_;
|
Stream& s_;
|
||||||
DynamicBuffer& b_;
|
DynamicBuffer& b_;
|
||||||
Condition cond_;
|
Condition cond_;
|
||||||
|
error_code ec_;
|
||||||
std::size_t total_ = 0;
|
std::size_t total_ = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -72,13 +73,14 @@ public:
|
|||||||
std::size_t bytes_transferred,
|
std::size_t bytes_transferred,
|
||||||
bool cont = true)
|
bool cont = true)
|
||||||
{
|
{
|
||||||
|
ec_ = ec;
|
||||||
std::size_t max_size;
|
std::size_t max_size;
|
||||||
std::size_t max_prepare;
|
std::size_t max_prepare;
|
||||||
BOOST_ASIO_CORO_REENTER(*this)
|
BOOST_ASIO_CORO_REENTER(*this)
|
||||||
{
|
{
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
max_size = cond_(ec, total_, b_);
|
max_size = cond_(ec_, total_, b_);
|
||||||
max_prepare = std::min<std::size_t>(
|
max_prepare = std::min<std::size_t>(
|
||||||
std::max<std::size_t>(
|
std::max<std::size_t>(
|
||||||
512, b_.capacity() - b_.size()),
|
512, b_.capacity() - b_.size()),
|
||||||
@@ -92,115 +94,21 @@ public:
|
|||||||
b_.commit(bytes_transferred);
|
b_.commit(bytes_transferred);
|
||||||
total_ += 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
|
struct run_read_op
|
||||||
{
|
{
|
||||||
template<
|
template<
|
||||||
@@ -235,54 +143,6 @@ struct run_read_op
|
|||||||
std::forward<Condition>(c));
|
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;
|
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<
|
template<
|
||||||
class AsyncReadStream,
|
class AsyncReadStream,
|
||||||
class DynamicBuffer,
|
class DynamicBuffer,
|
||||||
|
@@ -17,7 +17,6 @@
|
|||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/core/empty_value.hpp>
|
#include <boost/core/empty_value.hpp>
|
||||||
#include <boost/core/exchange.hpp>
|
#include <boost/core/exchange.hpp>
|
||||||
#include <memory>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace boost {
|
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>
|
template<class Handler, class Allocator>
|
||||||
void
|
void
|
||||||
saved_handler::
|
saved_handler::
|
||||||
@@ -169,27 +145,6 @@ emplace(Handler&& handler)
|
|||||||
net::get_associated_allocator(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
|
} // beast
|
||||||
} // boost
|
} // boost
|
||||||
|
|
||||||
|
66
include/boost/beast/core/impl/saved_handler.ipp
Normal file
66
include/boost/beast/core/impl/saved_handler.ipp
Normal 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
|
@@ -120,5 +120,8 @@ public:
|
|||||||
} // boost
|
} // boost
|
||||||
|
|
||||||
#include <boost/beast/core/impl/saved_handler.hpp>
|
#include <boost/beast/core/impl/saved_handler.hpp>
|
||||||
|
#ifdef BOOST_BEAST_HEADER_ONLY
|
||||||
|
#include <boost/beast/core/impl/saved_handler.ipp>
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -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_posix.ipp>
|
||||||
#include <boost/beast/core/impl/file_stdio.ipp>
|
#include <boost/beast/core/impl/file_stdio.ipp>
|
||||||
#include <boost/beast/core/impl/file_win32.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/core/impl/static_buffer.ipp>
|
||||||
|
|
||||||
#include <boost/beast/http/impl/error.ipp>
|
#include <boost/beast/http/impl/error.ipp>
|
||||||
|
@@ -2727,7 +2727,7 @@ private:
|
|||||||
|
|
||||||
@see stream::secure_prng
|
@see stream::secure_prng
|
||||||
*/
|
*/
|
||||||
BOOST_BEAST_DECL
|
inline
|
||||||
void
|
void
|
||||||
seed_prng(std::seed_seq& ss)
|
seed_prng(std::seed_seq& ss)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user