forked from boostorg/beast
Use async_initiate in basic_stream
This commit is contained in:
1 parent
23a7bcc67e
commit
0ad7390e94
5 files changed
+226
-173
No files matched your search
@@ -292,8 +292,12 @@ private:
|
||||
template<class, class, class>
|
||||
friend class basic_stream;
|
||||
|
||||
struct run_async_op;
|
||||
|
||||
struct timeout_handler;
|
||||
|
||||
struct ops;
|
||||
|
||||
#if ! BOOST_BEAST_DOXYGEN
|
||||
// boost::asio::ssl::stream needs these
|
||||
// DEPRECATED
|
||||
|
||||
@@ -135,7 +135,7 @@ struct is_contiguous_container<T, E, void_t<
|
||||
#define BOOST_BEAST_HANDLER_INIT(type, sig) \
|
||||
static_assert(::boost::beast::detail::is_invocable< \
|
||||
BOOST_ASIO_HANDLER_TYPE(type, sig), sig>::value, \
|
||||
"CompletionHandler signature requirements not met"); \
|
||||
"CompletionHandler type requirements not met"); \
|
||||
::boost::beast::net::async_completion<type, sig> init{handler}
|
||||
|
||||
} // detail
|
||||
|
||||
@@ -179,17 +179,157 @@ struct basic_stream<Protocol, Executor, RatePolicy>::
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
The algorithm for implementing the timeout depends
|
||||
on the executor providing ordered execution guarantee.
|
||||
`net::strand` automatically provides this, and we assume
|
||||
that an implicit strand (one thread calling io_context::run)
|
||||
also provides this.
|
||||
*/
|
||||
namespace detail {
|
||||
|
||||
template<
|
||||
class Protocol, class Executor, class RatePolicy,
|
||||
class Handler>
|
||||
class basic_stream_connect_op
|
||||
: public async_op_base<Handler, Executor>
|
||||
{
|
||||
using stream_type = beast::basic_stream<
|
||||
Protocol, Executor, RatePolicy>;
|
||||
|
||||
using timeout_handler =
|
||||
typename stream_type::timeout_handler;
|
||||
|
||||
boost::shared_ptr<typename
|
||||
stream_type::impl_type> impl_;
|
||||
typename stream_type::pending_guard pg0_;
|
||||
typename stream_type::pending_guard pg1_;
|
||||
|
||||
typename stream_type::op_state&
|
||||
state() noexcept
|
||||
{
|
||||
return impl_->write;
|
||||
}
|
||||
|
||||
public:
|
||||
template<class Handler_>
|
||||
basic_stream_connect_op(
|
||||
Handler_&& h,
|
||||
stream_type& s,
|
||||
typename stream_type::endpoint_type ep)
|
||||
: async_op_base<Handler, Executor>(
|
||||
std::forward<Handler_>(h), s.get_executor())
|
||||
, impl_(s.impl_)
|
||||
, pg0_(impl_->read.pending)
|
||||
, pg1_(impl_->write.pending)
|
||||
{
|
||||
if(state().timer.expiry() != stream_base::never())
|
||||
impl_->write.timer.async_wait(
|
||||
net::bind_executor(
|
||||
this->get_executor(),
|
||||
timeout_handler{
|
||||
state(),
|
||||
impl_,
|
||||
state().tick}));
|
||||
|
||||
impl_->socket.async_connect(
|
||||
ep, std::move(*this));
|
||||
// *this is now moved-from
|
||||
}
|
||||
|
||||
template<
|
||||
class Endpoints, class Condition,
|
||||
class Handler_>
|
||||
basic_stream_connect_op(
|
||||
Handler_&& h,
|
||||
stream_type& s,
|
||||
Endpoints const& eps,
|
||||
Condition const& cond)
|
||||
: async_op_base<Handler, Executor>(
|
||||
std::forward<Handler_>(h), s.get_executor())
|
||||
, impl_(s.impl_)
|
||||
, pg0_(impl_->read.pending)
|
||||
, pg1_(impl_->write.pending)
|
||||
{
|
||||
if(state().timer.expiry() != stream_base::never())
|
||||
impl_->write.timer.async_wait(
|
||||
net::bind_executor(
|
||||
this->get_executor(),
|
||||
timeout_handler{
|
||||
state(),
|
||||
impl_,
|
||||
state().tick}));
|
||||
|
||||
net::async_connect(impl_->socket,
|
||||
eps, cond, std::move(*this));
|
||||
// *this is now moved-from
|
||||
}
|
||||
|
||||
template<
|
||||
class Iterator, class Condition,
|
||||
class Handler_>
|
||||
basic_stream_connect_op(
|
||||
Handler_&& h,
|
||||
stream_type& s,
|
||||
Iterator begin, Iterator end,
|
||||
Condition const& cond)
|
||||
: async_op_base<Handler, Executor>(
|
||||
std::forward<Handler_>(h), s.get_executor())
|
||||
, impl_(s.impl_)
|
||||
, pg0_(impl_->read.pending)
|
||||
, pg1_(impl_->write.pending)
|
||||
{
|
||||
if(state().timer.expiry() != stream_base::never())
|
||||
impl_->write.timer.async_wait(
|
||||
net::bind_executor(
|
||||
this->get_executor(),
|
||||
timeout_handler{
|
||||
state(),
|
||||
impl_,
|
||||
state().tick}));
|
||||
|
||||
net::async_connect(impl_->socket,
|
||||
begin, end, cond, std::move(*this));
|
||||
// *this is now moved-from
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
void
|
||||
operator()(error_code ec, Args&&... args)
|
||||
{
|
||||
if(state().timer.expiry() != stream_base::never())
|
||||
{
|
||||
++state().tick;
|
||||
|
||||
// try cancelling timer
|
||||
auto const n =
|
||||
impl_->write.timer.cancel();
|
||||
if(n == 0)
|
||||
{
|
||||
// timeout handler invoked?
|
||||
if(state().timeout)
|
||||
{
|
||||
// yes, socket already closed
|
||||
ec = beast::error::timeout;
|
||||
state().timeout = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(n == 1);
|
||||
BOOST_ASSERT(! state().timeout);
|
||||
}
|
||||
}
|
||||
|
||||
pg0_.reset();
|
||||
pg1_.reset();
|
||||
this->invoke_now(ec, std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class Protocol, class Executor, class RatePolicy>
|
||||
struct basic_stream<Protocol, Executor, RatePolicy>::ops
|
||||
{
|
||||
|
||||
template<bool isRead, class Buffers, class Handler>
|
||||
class basic_stream<Protocol, Executor, RatePolicy>::async_op
|
||||
class async_op
|
||||
: public async_op_base<Handler, Executor>
|
||||
, public boost::asio::coroutine
|
||||
{
|
||||
@@ -279,9 +419,9 @@ class basic_stream<Protocol, Executor, RatePolicy>::async_op
|
||||
public:
|
||||
template<class Handler_>
|
||||
async_op(
|
||||
Handler_&& h,
|
||||
basic_stream& s,
|
||||
Buffers const& b,
|
||||
Handler_&& h)
|
||||
Buffers const& b)
|
||||
: async_op_base<Handler, Executor>(
|
||||
std::forward<Handler_>(h), s.get_executor())
|
||||
, impl_(s.impl_)
|
||||
@@ -390,150 +530,56 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<
|
||||
class Protocol, class Executor, class RatePolicy,
|
||||
class Handler>
|
||||
class basic_stream_connect_op
|
||||
: public async_op_base<Handler, Executor>
|
||||
struct run_read_op
|
||||
{
|
||||
using stream_type = beast::basic_stream<
|
||||
Protocol, Executor, RatePolicy>;
|
||||
|
||||
using timeout_handler =
|
||||
typename stream_type::timeout_handler;
|
||||
|
||||
boost::shared_ptr<typename
|
||||
stream_type::impl_type> impl_;
|
||||
typename stream_type::pending_guard pg0_;
|
||||
typename stream_type::pending_guard pg1_;
|
||||
|
||||
typename stream_type::op_state&
|
||||
state() noexcept
|
||||
{
|
||||
return impl_->write;
|
||||
}
|
||||
|
||||
public:
|
||||
template<class Handler_>
|
||||
basic_stream_connect_op(
|
||||
stream_type& s,
|
||||
typename stream_type::endpoint_type ep,
|
||||
Handler_&& h)
|
||||
: async_op_base<Handler, Executor>(
|
||||
std::forward<Handler_>(h), s.get_executor())
|
||||
, impl_(s.impl_)
|
||||
, pg0_(impl_->read.pending)
|
||||
, pg1_(impl_->write.pending)
|
||||
{
|
||||
if(state().timer.expiry() != stream_base::never())
|
||||
impl_->write.timer.async_wait(
|
||||
net::bind_executor(
|
||||
this->get_executor(),
|
||||
timeout_handler{
|
||||
state(),
|
||||
impl_,
|
||||
state().tick}));
|
||||
|
||||
impl_->socket.async_connect(
|
||||
ep, std::move(*this));
|
||||
// *this is now moved-from
|
||||
}
|
||||
|
||||
template<
|
||||
class Endpoints, class Condition,
|
||||
class Handler_>
|
||||
basic_stream_connect_op(
|
||||
stream_type& s,
|
||||
Endpoints const& eps,
|
||||
Condition const& cond,
|
||||
Handler_&& h)
|
||||
: async_op_base<Handler, Executor>(
|
||||
std::forward<Handler_>(h), s.get_executor())
|
||||
, impl_(s.impl_)
|
||||
, pg0_(impl_->read.pending)
|
||||
, pg1_(impl_->write.pending)
|
||||
{
|
||||
if(state().timer.expiry() != stream_base::never())
|
||||
impl_->write.timer.async_wait(
|
||||
net::bind_executor(
|
||||
this->get_executor(),
|
||||
timeout_handler{
|
||||
state(),
|
||||
impl_,
|
||||
state().tick}));
|
||||
|
||||
net::async_connect(impl_->socket,
|
||||
eps, cond, std::move(*this));
|
||||
// *this is now moved-from
|
||||
}
|
||||
|
||||
template<
|
||||
class Iterator, class Condition,
|
||||
class Handler_>
|
||||
basic_stream_connect_op(
|
||||
stream_type& s,
|
||||
Iterator begin, Iterator end,
|
||||
Condition const& cond,
|
||||
Handler_&& h)
|
||||
: async_op_base<Handler, Executor>(
|
||||
std::forward<Handler_>(h), s.get_executor())
|
||||
, impl_(s.impl_)
|
||||
, pg0_(impl_->read.pending)
|
||||
, pg1_(impl_->write.pending)
|
||||
{
|
||||
if(state().timer.expiry() != stream_base::never())
|
||||
impl_->write.timer.async_wait(
|
||||
net::bind_executor(
|
||||
this->get_executor(),
|
||||
timeout_handler{
|
||||
state(),
|
||||
impl_,
|
||||
state().tick}));
|
||||
|
||||
net::async_connect(impl_->socket,
|
||||
begin, end, cond, std::move(*this));
|
||||
// *this is now moved-from
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
template<class ReadHandler, class Buffers>
|
||||
void
|
||||
operator()(error_code ec, Args&&... args)
|
||||
operator()(
|
||||
ReadHandler&& h,
|
||||
basic_stream& s,
|
||||
Buffers const& b
|
||||
)
|
||||
{
|
||||
if(state().timer.expiry() != stream_base::never())
|
||||
{
|
||||
++state().tick;
|
||||
|
||||
// try cancelling timer
|
||||
auto const n =
|
||||
impl_->write.timer.cancel();
|
||||
if(n == 0)
|
||||
{
|
||||
// timeout handler invoked?
|
||||
if(state().timeout)
|
||||
{
|
||||
// yes, socket already closed
|
||||
ec = beast::error::timeout;
|
||||
state().timeout = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(n == 1);
|
||||
BOOST_ASSERT(! state().timeout);
|
||||
}
|
||||
}
|
||||
|
||||
pg0_.reset();
|
||||
pg1_.reset();
|
||||
this->invoke_now(ec, std::forward<Args>(args)...);
|
||||
// If you get an error on the following line it means
|
||||
// that your handler does not meet the documented type
|
||||
// requirements for a ReadHandler.
|
||||
static_assert(
|
||||
detail::is_invocable<ReadHandler,
|
||||
void(error_code, std::size_t)>::value,
|
||||
"ReadHandler type requirements not met");
|
||||
async_op<
|
||||
true,
|
||||
Buffers,
|
||||
typename std::decay<ReadHandler>::type>(
|
||||
std::forward<ReadHandler>(h), s, b);
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
struct run_write_op
|
||||
{
|
||||
template<class WriteHandler, class Buffers>
|
||||
void
|
||||
operator()(
|
||||
WriteHandler&& h,
|
||||
basic_stream& s,
|
||||
Buffers const& b)
|
||||
{
|
||||
// If you get an error on the following line it means
|
||||
// that your handler does not meet the documented type
|
||||
// requirements for a WriteHandler.
|
||||
static_assert(
|
||||
detail::is_invocable<WriteHandler,
|
||||
void(error_code, std::size_t)>::value,
|
||||
"WriteHandler type requirements not met");
|
||||
async_op<
|
||||
false,
|
||||
Buffers,
|
||||
typename std::decay<WriteHandler>::type>(
|
||||
std::forward<WriteHandler>(h), s, b);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -668,8 +714,9 @@ async_connect(
|
||||
detail::basic_stream_connect_op<
|
||||
Protocol, Executor, RatePolicy,
|
||||
BOOST_ASIO_HANDLER_TYPE(
|
||||
ConnectHandler, void(error_code))>(*this,
|
||||
ep, std::forward<ConnectHandler>(handler));
|
||||
ConnectHandler, void(error_code))>(
|
||||
std::forward<ConnectHandler>(handler),
|
||||
*this, ep);
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
@@ -685,12 +732,13 @@ async_read_some(
|
||||
static_assert(net::is_mutable_buffer_sequence<
|
||||
MutableBufferSequence>::value,
|
||||
"MutableBufferSequence requirements not met");
|
||||
BOOST_BEAST_HANDLER_INIT(
|
||||
ReadHandler, void(error_code, std::size_t));
|
||||
async_op<true, MutableBufferSequence, BOOST_ASIO_HANDLER_TYPE(
|
||||
ReadHandler, void(error_code, std::size_t))>(
|
||||
*this, buffers, std::move(init.completion_handler));
|
||||
return init.result.get();
|
||||
return net::async_initiate<
|
||||
ReadHandler,
|
||||
void(error_code, std::size_t)>(
|
||||
ops::run_read_op{},
|
||||
handler,
|
||||
*this,
|
||||
buffers);
|
||||
}
|
||||
|
||||
template<class Protocol, class Executor, class RatePolicy>
|
||||
@@ -705,12 +753,13 @@ async_write_some(
|
||||
static_assert(net::is_const_buffer_sequence<
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
BOOST_BEAST_HANDLER_INIT(
|
||||
WriteHandler, void(error_code, std::size_t));
|
||||
async_op<false, ConstBufferSequence, BOOST_ASIO_HANDLER_TYPE(
|
||||
WriteHandler, void(error_code, std::size_t))>(
|
||||
*this, buffers, std::move(init.completion_handler));
|
||||
return init.result.get();
|
||||
return net::async_initiate<
|
||||
WriteHandler,
|
||||
void(error_code, std::size_t)>(
|
||||
ops::run_write_op{},
|
||||
handler,
|
||||
*this,
|
||||
buffers);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -733,8 +782,8 @@ async_connect(
|
||||
Protocol, Executor, RatePolicy,
|
||||
BOOST_ASIO_HANDLER_TYPE(RangeConnectHandler,
|
||||
void(error_code, typename Protocol::endpoint))>(
|
||||
stream, endpoints, detail::any_endpoint{},
|
||||
std::move(init.completion_handler));
|
||||
std::move(init.completion_handler), stream,
|
||||
endpoints, detail::any_endpoint{});
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
@@ -758,8 +807,8 @@ async_connect(
|
||||
Protocol, Executor, RatePolicy,
|
||||
BOOST_ASIO_HANDLER_TYPE(RangeConnectHandler,
|
||||
void(error_code, typename Protocol::endpoint))>(
|
||||
stream, endpoints, connect_condition,
|
||||
std::move(init.completion_handler));
|
||||
std::move(init.completion_handler), stream,
|
||||
endpoints, connect_condition);
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
@@ -780,8 +829,8 @@ async_connect(
|
||||
Protocol, Executor, RatePolicy,
|
||||
BOOST_ASIO_HANDLER_TYPE(IteratorConnectHandler,
|
||||
void(error_code, Iterator))>(
|
||||
stream, begin, end, detail::any_endpoint{},
|
||||
std::move(init.completion_handler));
|
||||
std::move(init.completion_handler), stream,
|
||||
begin, end, detail::any_endpoint{});
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
@@ -804,8 +853,8 @@ async_connect(
|
||||
Protocol, Executor, RatePolicy,
|
||||
BOOST_ASIO_HANDLER_TYPE(IteratorConnectHandler,
|
||||
void(error_code, Iterator))>(
|
||||
stream, begin, end, connect_condition,
|
||||
std::move(init.completion_handler));
|
||||
std::move(init.completion_handler), stream,
|
||||
begin, end, connect_condition);
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ struct test_acceptor
|
||||
a.set_option(
|
||||
net::socket_base::reuse_address(true));
|
||||
a.bind(ep);
|
||||
a.listen(0);
|
||||
a.listen(1);
|
||||
ep = a.local_endpoint();
|
||||
a.async_accept(
|
||||
[](error_code, net::ip::tcp::socket)
|
||||
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(beast,websocket,error);
|
||||
BEAST_DEFINE_TESTSUITE(beast,core,error);
|
||||
|
||||
} // beast
|
||||
} // boost
|
||||
Reference in new issue
Block a user