Use async_initiate

This commit is contained in:
Vinnie Falco
2019-02-20 20:25:01 -08:00
parent e2d3f741b8
commit d08cc82e15
26 changed files with 1216 additions and 590 deletions

View File

@ -4,6 +4,7 @@ Version 217:
* RatePolicy documentation
* Pass strand to async_accept
* Fix file_body_win32
* Use async_initiate
--------------------------------------------------------------------------------

View File

@ -179,9 +179,6 @@ endif()
include_directories (.)
# VFALCO FIXME Need this for recent asio changes
#add_definitions (-DBOOST_BEAST_NO_FILE_BODY_WIN32=1)
if (OPENSSL_FOUND)
include_directories (${OPENSSL_INCLUDE_DIR})
endif()

View File

@ -47,7 +47,7 @@
[link beast.ref.boost__beast__unlimited_rate_policy `unlimited`],
or a user-defined
[link beast.concepts.RatePolicy ['RatePolicy]]!
* [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html [P1322R0]]
* [[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html P1322R0]]
Put the strand on the socket itself, no more `bind_executor` at call sites!
* Base classes
[link beast.ref.boost__beast__async_op_base `async_op_base`] and

View File

@ -68,7 +68,7 @@ namespace http {
template<class NextLayer>
class icy_stream
{
template<class, class> class read_op;
struct ops;
NextLayer stream_;
bool detect_ = true;

View File

@ -118,8 +118,11 @@ public:
} // detail
template<class NextLayer>
template<class MutableBufferSequence, class Handler>
class icy_stream<NextLayer>::read_op
struct icy_stream<NextLayer>::ops
{
template<class Buffers, class Handler>
class read_op
: public beast::stable_async_op_base<Handler,
beast::executor_type<icy_stream>>
, public net::coroutine
@ -127,15 +130,21 @@ class icy_stream<NextLayer>::read_op
// VFALCO We need a stable reference to `b`
// to pass to asio's read functions.
//
// VFALCO Why did I do all this rigamarole?
// we only need 6 or 8 bytes at most,
// this should all just be tucked
// away into the icy_stream. We can
// simulate a dynamic buffer adaptor
// with one or two simple ints.
struct data
{
icy_stream& s;
buffers_adaptor<MutableBufferSequence> b;
buffers_adaptor<Buffers> b;
bool match = false;
data(
icy_stream& s_,
MutableBufferSequence const& b_)
Buffers const& b_)
: s(s_)
, b(b_)
{
@ -149,7 +158,7 @@ public:
read_op(
Handler_&& h,
icy_stream& s,
MutableBufferSequence const& b)
Buffers const& b)
: stable_async_op_base<Handler,
beast::executor_type<icy_stream>>(
std::forward<Handler_>(h), s.get_executor())
@ -165,7 +174,7 @@ public:
{
using iterator = net::buffers_iterator<
typename beast::dynamic_buffer_ref_wrapper<
buffers_adaptor<MutableBufferSequence>>::const_buffers_type>;
buffers_adaptor<Buffers>>::const_buffers_type>;
BOOST_ASIO_CORO_REENTER(*this)
{
if(d_.b.max_size() == 0)
@ -272,7 +281,7 @@ public:
}
{
buffers_suffix<beast::detail::buffers_ref<
MutableBufferSequence>> dest(
Buffers>> dest(
boost::in_place_init, d_.b.value());
dest.consume(5);
detail::buffer_shift(
@ -289,6 +298,33 @@ public:
}
};
struct run_read_op
{
template<class ReadHandler, class Buffers>
void
operator()(
ReadHandler&& h,
icy_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 the handler.
static_assert(
beast::detail::is_invocable<ReadHandler,
void(error_code, std::size_t)>::value,
"ReadHandler type requirements not met");
read_op<
Buffers,
typename std::decay<ReadHandler>::type>(
std::forward<ReadHandler>(h), s, b);
}
};
};
//------------------------------------------------------------------------------
template<class NextLayer>
@ -449,14 +485,13 @@ async_read_some(
static_assert(net::is_mutable_buffer_sequence<
MutableBufferSequence >::value,
"MutableBufferSequence type requirements not met");
BOOST_BEAST_HANDLER_INIT(
ReadHandler, void(error_code, std::size_t));
read_op<
MutableBufferSequence,
BOOST_ASIO_HANDLER_TYPE(
ReadHandler, void(error_code, std::size_t))>(
std::move(init.completion_handler), *this, buffers);
return init.result.get();
return net::async_initiate<
ReadHandler,
void(error_code, std::size_t)>(
typename ops::run_read_op{},
handler,
*this,
buffers);
}
template<class NextLayer>

View File

@ -31,20 +31,23 @@ class stream::read_op : public stream::read_op_base
class lambda
{
Handler h_;
state& s_;
Buffers b_;
Handler h_;
net::executor_work_guard<ex2_type> wg2_;
public:
lambda(lambda&&) = default;
lambda(lambda const&) = default;
template<class DeducedHandler>
lambda(state& s, Buffers const& b, DeducedHandler&& h)
: s_(s)
template<class Handler_>
lambda(
Handler_&& h,
state& s,
Buffers const& b)
: h_(std::forward<Handler_>(h))
, s_(s)
, b_(b)
, h_(std::forward<DeducedHandler>(h))
, wg2_(net::get_associated_executor(
h_, s_.ioc.get_executor()))
{
@ -88,9 +91,11 @@ class stream::read_op : public stream::read_op_base
public:
template<class Handler_>
read_op(state& s,
Buffers const& b, Handler_&& h)
: fn_(s, b, std::forward<Handler_>(h))
read_op(
Handler_&& h,
state& s,
Buffers const& b)
: fn_(std::forward<Handler_>(h), s, b)
, wg1_(s.ioc.get_executor())
{
}
@ -107,6 +112,172 @@ public:
}
};
struct stream::run_read_op
{
template<
class ReadHandler,
class MutableBufferSequence>
void
operator()(
ReadHandler&& h,
std::shared_ptr<state> in_,
MutableBufferSequence const& buffers)
{
// 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");
++in_->nread;
std::unique_lock<std::mutex> lock(in_->m);
if(in_->op != nullptr)
throw std::logic_error(
"in_->op != nullptr");
// test failure
error_code ec;
if(in_->fc && in_->fc->fail(ec))
{
net::post(
in_->ioc.get_executor(),
beast::bind_front_handler(
std::move(h),
ec, std::size_t{0}));
return;
}
// A request to read 0 bytes from a stream is a no-op.
if(buffer_size(buffers) == 0)
{
lock.unlock();
net::post(
in_->ioc.get_executor(),
beast::bind_front_handler(
std::move(h),
ec, std::size_t{0}));
return;
}
// deliver bytes before eof
if(buffer_size(in_->b.data()) > 0)
{
auto n = net::buffer_copy(
buffers, in_->b.data(), in_->read_max);
in_->b.consume(n);
lock.unlock();
net::post(
in_->ioc.get_executor(),
beast::bind_front_handler(
std::move(h),
ec, n));
return;
}
// deliver error
if(in_->code != status::ok)
{
lock.unlock();
ec = net::error::eof;
net::post(
in_->ioc.get_executor(),
beast::bind_front_handler(
std::move(h),
ec, std::size_t{0}));
return;
}
// complete when bytes available or closed
in_->op.reset(
new read_op<
ReadHandler,
MutableBufferSequence>(
std::move(h), *in_, buffers));
}
};
struct stream::run_write_op
{
template<
class WriteHandler,
class ConstBufferSequence>
void
operator()(
WriteHandler&& h,
std::shared_ptr<state> in_,
std::weak_ptr<state> out_,
ConstBufferSequence const& buffers)
{
// 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<WriteHandler,
void(error_code, std::size_t)>::value,
"WriteHandler type requirements not met");
++in_->nwrite;
// test failure
error_code ec;
if(in_->fc && in_->fc->fail(ec))
{
net::post(
in_->ioc.get_executor(),
beast::bind_front_handler(
std::move(h),
ec,
std::size_t{0}));
return;
}
// A request to read 0 bytes from a stream is a no-op.
if(buffer_size(buffers) == 0)
{
net::post(
in_->ioc.get_executor(),
beast::bind_front_handler(
std::move(h),
ec, std::size_t{0}));
return;
}
// connection closed
auto out = out_.lock();
if(! out)
{
net::post(
in_->ioc.get_executor(),
beast::bind_front_handler(
std::move(h),
net::error::connection_reset,
std::size_t{0}));
return;
}
// copy buffers
auto n = std::min<std::size_t>(
buffer_size(buffers), in_->write_max);
{
std::lock_guard<std::mutex> lock(out->m);
n = net::buffer_copy(out->b.prepare(n), buffers);
out->b.commit(n);
out->notify_read();
}
net::post(
in_->ioc.get_executor(),
beast::bind_front_handler(
std::move(h),
error_code{},
n));
}
};
//------------------------------------------------------------------------------
stream::
@ -376,74 +547,13 @@ async_read_some(
MutableBufferSequence>::value,
"MutableBufferSequence type requirements not met");
BOOST_BEAST_HANDLER_INIT(
ReadHandler, void(error_code, std::size_t));
++in_->nread;
std::unique_lock<std::mutex> lock(in_->m);
if(in_->op != nullptr)
throw std::logic_error(
"in_->op != nullptr");
// test failure
error_code ec;
if(in_->fc && in_->fc->fail(ec))
{
net::post(
in_->ioc.get_executor(),
beast::bind_front_handler(
std::move(init.completion_handler),
ec, std::size_t{0}));
return init.result.get();
}
// A request to read 0 bytes from a stream is a no-op.
if(buffer_size(buffers) == 0)
{
lock.unlock();
net::post(
in_->ioc.get_executor(),
beast::bind_front_handler(
std::move(init.completion_handler),
ec, std::size_t{0}));
return init.result.get();
}
// deliver bytes before eof
if(buffer_size(in_->b.data()) > 0)
{
auto n = net::buffer_copy(
buffers, in_->b.data(), in_->read_max);
in_->b.consume(n);
lock.unlock();
net::post(
in_->ioc.get_executor(),
beast::bind_front_handler(
std::move(init.completion_handler),
ec, n));
return init.result.get();
}
// deliver error
if(in_->code != status::ok)
{
lock.unlock();
ec = net::error::eof;
net::post(
in_->ioc.get_executor(),
beast::bind_front_handler(
std::move(init.completion_handler),
ec, std::size_t{0}));
return init.result.get();
}
// complete when bytes available or closed
in_->op.reset(new read_op<BOOST_ASIO_HANDLER_TYPE(
ReadHandler, void(error_code, std::size_t)),
MutableBufferSequence>{*in_, buffers,
std::move(init.completion_handler)});
return init.result.get();
return net::async_initiate<
ReadHandler,
void(error_code, std::size_t)>(
run_read_op{},
handler,
in_,
buffers);
}
template<class ConstBufferSequence>
@ -509,70 +619,22 @@ template<class ConstBufferSequence, class WriteHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(
WriteHandler, void(error_code, std::size_t))
stream::
async_write_some(ConstBufferSequence const& buffers,
async_write_some(
ConstBufferSequence const& buffers,
WriteHandler&& handler)
{
static_assert(net::is_const_buffer_sequence<
ConstBufferSequence>::value,
"ConstBufferSequence type requirements not met");
BOOST_BEAST_HANDLER_INIT(
WriteHandler, void(error_code, std::size_t));
++in_->nwrite;
// test failure
error_code ec;
if(in_->fc && in_->fc->fail(ec))
{
net::post(
in_->ioc.get_executor(),
beast::bind_front_handler(
std::move(init.completion_handler),
ec,
std::size_t{0}));
return init.result.get();
}
// A request to read 0 bytes from a stream is a no-op.
if(buffer_size(buffers) == 0)
{
net::post(
in_->ioc.get_executor(),
beast::bind_front_handler(
std::move(init.completion_handler),
ec, std::size_t{0}));
return init.result.get();
}
// connection closed
auto out = out_.lock();
if(! out)
{
net::post(
in_->ioc.get_executor(),
beast::bind_front_handler(
std::move(init.completion_handler),
net::error::connection_reset,
std::size_t{0}));
return init.result.get();
}
// copy buffers
auto n = std::min<std::size_t>(
buffer_size(buffers), in_->write_max);
{
std::lock_guard<std::mutex> lock(out->m);
n = net::buffer_copy(out->b.prepare(n), buffers);
out->b.commit(n);
out->notify_read();
}
net::post(
in_->ioc.get_executor(),
beast::bind_front_handler(
std::move(init.completion_handler),
error_code{}, n));
return init.result.get();
return net::async_initiate<
WriteHandler,
void(error_code, std::size_t)>(
run_write_op{},
handler,
in_,
out_,
buffers);
}
void

View File

@ -105,6 +105,9 @@ class stream
template<class Handler, class Buffers>
class read_op;
struct run_read_op;
struct run_write_op;
enum class status
{
ok,

View File

@ -95,8 +95,7 @@ class buffered_read_stream
net::is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer type requirements not met");
template<class Buffers, class Handler>
class read_some_op;
struct ops;
DynamicBuffer buffer_;
std::size_t capacity_ = 0;

View File

@ -26,6 +26,9 @@ static std::size_t constexpr default_max_stack_buffer = 16384;
//------------------------------------------------------------------------------
struct dynamic_read_ops
{
// read into a dynamic buffer until the
// condition is met or an error occurs
template<
@ -46,19 +49,19 @@ class read_op
public:
read_op(read_op&&) = default;
template<class Handler_>
template<class Handler_, class Condition_>
read_op(
Handler_&& h,
Stream& s,
DynamicBuffer& b,
Condition cond,
Handler_&& h)
Condition_&& cond)
: async_op_base<Handler,
beast::executor_type<Stream>>(
std::forward<Handler_>(h),
s.get_executor())
, s_(s)
, b_(b)
, cond_(cond)
, cond_(std::forward<Condition_>(cond))
{
(*this)({}, 0, false);
}
@ -100,16 +103,16 @@ public:
// EXPERIMENTAL
// optimized non-blocking read algorithm
template<
class Protocol,
class Protocol, class Executor,
class DynamicBuffer,
class Condition,
class Handler>
class read_non_blocking_op
: public net::coroutine
, public async_op_base<Handler,
beast::executor_type<net::basic_stream_socket<Protocol>>>
, public async_op_base<Handler, Executor>
{
net::basic_stream_socket<Protocol>& s_;
net::basic_stream_socket<
Protocol, Executor>& s_;
DynamicBuffer& b_;
Condition cond_;
std::size_t limit_;
@ -119,18 +122,18 @@ public:
read_non_blocking_op(read_non_blocking_op&&) = default;
read_non_blocking_op(read_non_blocking_op const&) = delete;
template<class Handler_>
template<class Handler_, class Condition_>
read_non_blocking_op(
net::basic_stream_socket<Protocol>& s,
Handler_&& h,
net::basic_stream_socket<
Protocol, Executor>& s,
DynamicBuffer& b,
Condition cond,
Handler_&& h)
: async_op_base<Handler, beast::executor_type<
net::basic_stream_socket<Protocol>>>(
s.get_executor(), std::forward<Handler_>(h))
Condition cond)
: async_op_base<Handler, Executor>(
s.get_executor(), std::forward<Handler_>(h))
, s_(s)
, b_(b)
, cond_(cond)
, cond_(std::forward<Condition_>(cond))
{
(*this)({}, false);
}
@ -198,92 +201,91 @@ public:
#endif
//------------------------------------------------------------------------------
template<
class AsyncReadStream,
class DynamicBuffer,
class CompletionCondition,
class ReadHandler,
class>
BOOST_ASIO_INITFN_RESULT_TYPE(
ReadHandler, void(error_code, std::size_t))
async_read(
AsyncReadStream& stream,
DynamicBuffer& buffer,
CompletionCondition cond,
ReadHandler&& handler)
struct run_read_op
{
static_assert(is_async_read_stream<AsyncReadStream>::value,
"AsyncReadStream type requirements not met");
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");
BOOST_BEAST_HANDLER_INIT(
ReadHandler, void(error_code, std::size_t));
detail::read_op<
AsyncReadStream,
DynamicBuffer,
CompletionCondition,
BOOST_ASIO_HANDLER_TYPE(
ReadHandler, void(error_code, std::size_t))>(
stream, buffer, std::move(cond),
std::move(init.completion_handler));
return init.result.get();
}
template<
class AsyncReadStream,
class DynamicBuffer,
class Condition,
class ReadHandler>
void
operator()(
ReadHandler&& h,
AsyncReadStream& s,
DynamicBuffer& b,
Condition&& c)
{
// If you get an error on the following line it means
// that your handler does not meet the documented type
// requirements for the handler.
#ifdef BOOST_BEAST_ENABLE_NON_BLOCKING
template<
class Protocol,
class DynamicBuffer,
class CompletionCondition,
class ReadHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(
ReadHandler, void(error_code, std::size_t))
async_read(
net::basic_stream_socket<Protocol>& socket,
DynamicBuffer& buffer,
CompletionCondition cond,
ReadHandler&& handler)
{
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");
BOOST_BEAST_HANDLER_INIT(
ReadHandler, void(error_code, std::size_t));
if(socket.non_blocking())
{
detail::read_non_blocking_op<
Protocol,
static_assert(
beast::detail::is_invocable<ReadHandler,
void(error_code, std::size_t)>::value,
"ReadHandler type requirements not met");
read_op<
AsyncReadStream,
DynamicBuffer,
CompletionCondition,
BOOST_ASIO_HANDLER_TYPE(
ReadHandler, void(error_code, std::size_t))>(
socket, buffer, std::move(cond),
std::move(init.completion_handler));
typename std::decay<Condition>::type,
typename std::decay<ReadHandler>::type>(
std::forward<ReadHandler>(h),
s,
b,
std::forward<Condition>(c));
}
else
#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)
{
detail::read_op<
decltype(socket),
DynamicBuffer,
CompletionCondition,
BOOST_ASIO_HANDLER_TYPE(
ReadHandler, void(error_code, std::size_t))>(
socket, buffer, std::move(cond),
std::move(init.completion_handler));
// 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));
}
}
return init.result.get();
}
#endif
};
};
//------------------------------------------------------------------------------
@ -444,6 +446,39 @@ read(
}
#endif
template<
class AsyncReadStream,
class DynamicBuffer,
class CompletionCondition,
class ReadHandler,
class>
BOOST_ASIO_INITFN_RESULT_TYPE(
ReadHandler, void(error_code, std::size_t))
async_read(
AsyncReadStream& stream,
DynamicBuffer& buffer,
CompletionCondition&& cond,
ReadHandler&& handler)
{
static_assert(is_async_read_stream<AsyncReadStream>::value,
"AsyncReadStream type requirements not met");
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");
return net::async_initiate<
ReadHandler,
void(error_code, std::size_t)>(
typename dynamic_read_ops::run_read_op{},
handler,
stream,
buffer,
std::forward<CompletionCondition>(cond));
}
} // detail
} // beast
} // boost

View File

@ -235,7 +235,7 @@ BOOST_ASIO_INITFN_RESULT_TYPE(
async_read(
AsyncReadStream& stream,
DynamicBuffer& buffer,
CompletionCondition completion_condition,
CompletionCondition&& completion_condition,
ReadHandler&& handler);
} // detail

View File

@ -124,20 +124,6 @@ struct is_contiguous_container<T, E, void_t<
>::type>>: std::true_type
{};
//------------------------------------------------------------------------------
/* If this static assert goes off, it means that the completion
handler you provided to an asynchronous initiating function did
not have the right signature. Check the parameter types for your
completion handler and make sure they match the list of types
expected by the initiating function,
*/
#define BOOST_BEAST_HANDLER_INIT(type, sig) \
static_assert(::boost::beast::detail::is_invocable< \
BOOST_ASIO_HANDLER_TYPE(type, sig), sig>::value, \
"CompletionHandler type requirements not met"); \
::boost::beast::net::async_completion<type, sig> init{handler}
} // detail
} // beast
} // boost

View File

@ -90,13 +90,13 @@ class flat_stream
: private detail::flat_stream_base
#endif
{
template<class> class write_op;
NextLayer stream_;
flat_buffer buffer_;
BOOST_STATIC_ASSERT(has_get_executor<NextLayer>::value);
struct ops;
template<class ConstBufferSequence>
std::size_t
stack_write_some(

View File

@ -539,16 +539,17 @@ struct run_read_op
operator()(
ReadHandler&& h,
basic_stream& s,
Buffers const& b
)
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 ReadHandler.
// requirements for the handler.
static_assert(
detail::is_invocable<ReadHandler,
void(error_code, std::size_t)>::value,
"ReadHandler type requirements not met");
transfer_op<
true,
Buffers,
@ -568,11 +569,13 @@ struct run_write_op
{
// If you get an error on the following line it means
// that your handler does not meet the documented type
// requirements for a WriteHandler.
// requirements for the handler.
static_assert(
detail::is_invocable<WriteHandler,
void(error_code, std::size_t)>::value,
"WriteHandler type requirements not met");
transfer_op<
false,
Buffers,
@ -592,11 +595,13 @@ struct run_connect_op
{
// If you get an error on the following line it means
// that your handler does not meet the documented type
// requirements for a ConnectHandler.
// requirements for the handler.
static_assert(
detail::is_invocable<ConnectHandler,
void(error_code)>::value,
"ConnectHandler type requirements not met");
connect_op<typename std::decay<ConnectHandler>::type>(
std::forward<ConnectHandler>(h), s, ep);
}
@ -617,11 +622,13 @@ struct run_connect_range_op
{
// If you get an error on the following line it means
// that your handler does not meet the documented type
// requirements for a RangeConnectHandler.
// requirements for the handler.
static_assert(
detail::is_invocable<RangeConnectHandler,
void(error_code, typename Protocol::endpoint)>::value,
"RangeConnectHandler type requirements not met");
connect_op<typename std::decay<RangeConnectHandler>::type>(
std::forward<RangeConnectHandler>(h), s, eps, cond);
}
@ -642,11 +649,13 @@ struct run_connect_iter_op
{
// If you get an error on the following line it means
// that your handler does not meet the documented type
// requirements for a IteratorConnectHandler.
// requirements for the handler.
static_assert(
detail::is_invocable<IteratorConnectHandler,
void(error_code, Iterator)>::value,
"IteratorConnectHandler type requirements not met");
connect_op<typename std::decay<IteratorConnectHandler>::type>(
std::forward<IteratorConnectHandler>(h), s, begin, end, cond);
}

View File

@ -22,23 +22,26 @@
namespace boost {
namespace beast {
template<class Stream, class DynamicBuffer>
struct buffered_read_stream<Stream, DynamicBuffer>::ops
{
template<class MutableBufferSequence, class Handler>
class buffered_read_stream<
Stream, DynamicBuffer>::read_some_op
: public async_op_base<
Handler, beast::executor_type<buffered_read_stream>>
class read_op
: public async_op_base<Handler,
beast::executor_type<buffered_read_stream>>
{
buffered_read_stream& s_;
MutableBufferSequence b_;
int step_ = 0;
public:
read_some_op(read_some_op&&) = default;
read_some_op(read_some_op const&) = delete;
read_op(read_op&&) = default;
read_op(read_op const&) = delete;
template<class Handler_>
read_some_op(
read_op(
Handler_&& h,
buffered_read_stream& s,
MutableBufferSequence const& b)
@ -56,6 +59,7 @@ public:
error_code ec,
std::size_t bytes_transferred)
{
// VFALCO TODO Rewrite this using reenter/yield
switch(step_)
{
case 0:
@ -99,6 +103,35 @@ public:
}
};
struct run_read_op
{
template<class ReadHandler, class Buffers>
void
operator()(
ReadHandler&& h,
buffered_read_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 the handler.
static_assert(
beast::detail::is_invocable<ReadHandler,
void(error_code, std::size_t)>::value,
"ReadHandler type requirements not met");
read_op<
Buffers,
typename std::decay<ReadHandler>::type>(
std::forward<ReadHandler>(h),
s,
b);
}
};
};
//------------------------------------------------------------------------------
template<class Stream, class DynamicBuffer>
@ -198,12 +231,13 @@ async_read_some(
if(buffer_.size() == 0 && capacity_ == 0)
return next_layer_.async_read_some(buffers,
std::forward<ReadHandler>(handler));
BOOST_BEAST_HANDLER_INIT(
ReadHandler, void(error_code, std::size_t));
read_some_op<MutableBufferSequence, BOOST_ASIO_HANDLER_TYPE(
ReadHandler, void(error_code, std::size_t))>(
std::move(init.completion_handler), *this, buffers);
return init.result.get();
return net::async_initiate<
ReadHandler,
void(error_code, std::size_t)>(
typename ops::run_read_op{},
handler,
*this,
buffers);
}
} // beast

View File

@ -23,8 +23,11 @@ namespace boost {
namespace beast {
template<class NextLayer>
struct flat_stream<NextLayer>::ops
{
template<class Handler>
class flat_stream<NextLayer>::write_op
class write_op
: public async_op_base<Handler,
beast::executor_type<flat_stream>>
, public net::coroutine
@ -34,9 +37,9 @@ public:
class ConstBufferSequence,
class Handler_>
write_op(
Handler_&& h,
flat_stream<NextLayer>& s,
ConstBufferSequence const& b,
Handler_&& h)
ConstBufferSequence const& b)
: async_op_base<Handler,
beast::executor_type<flat_stream>>(
std::forward<Handler_>(h),
@ -72,6 +75,34 @@ public:
}
};
struct run_write_op
{
template<class WriteHandler, class Buffers>
void
operator()(
WriteHandler&& h,
flat_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 the handler.
static_assert(
beast::detail::is_invocable<WriteHandler,
void(error_code, std::size_t)>::value,
"WriteHandler type requirements not met");
write_op<
typename std::decay<WriteHandler>::type>(
std::forward<WriteHandler>(h),
s,
b);
}
};
};
//------------------------------------------------------------------------------
template<class NextLayer>
@ -212,12 +243,13 @@ async_write_some(
static_assert(net::is_const_buffer_sequence<
ConstBufferSequence>::value,
"ConstBufferSequence type requirements not met");
BOOST_BEAST_HANDLER_INIT(
WriteHandler, void(error_code, std::size_t));
write_op<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)>(
typename ops::run_write_op{},
handler,
*this,
buffers);
}
template<class NextLayer>

View File

@ -32,7 +32,7 @@ namespace beast {
namespace http {
namespace detail {
template<class, class, class, bool, class>
template<class, class, bool, class, class>
class write_some_win32_op;
} // detail
@ -52,7 +52,7 @@ struct basic_file_body<file_win32>
friend class reader;
friend struct basic_file_body<file_win32>;
template<class, class, class, bool, class>
template<class, class, bool, class, class>
friend class detail::write_some_win32_op;
template<
class Protocol, class Executor,
@ -102,7 +102,7 @@ struct basic_file_body<file_win32>
class writer
{
template<class, class, class, bool, class>
template<class, class, bool, class, class>
friend class detail::write_some_win32_op;
template<
class Protocol, class Executor,
@ -328,7 +328,8 @@ public:
template<
class Protocol, class Executor,
class Handler, bool isRequest, class Fields>
bool isRequest, class Fields,
class Handler>
class write_some_win32_op
: public beast::async_op_base<Handler, Executor>
{
@ -433,6 +434,39 @@ public:
}
};
struct run_write_some_win32_op
{
template<
class Protocol, class Executor,
bool isRequest, class Fields,
class WriteHandler>
void
operator()(
WriteHandler&& h,
net::basic_stream_socket<
Protocol, Executor>& s,
serializer<isRequest,
basic_file_body<file_win32>, Fields>& sr)
{
// 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<WriteHandler,
void(error_code, std::size_t)>::value,
"WriteHandler type requirements not met");
write_some_win32_op<
Protocol, Executor,
isRequest, Fields,
typename std::decay<WriteHandler>::type>(
std::forward<WriteHandler>(h),
s,
sr);
}
};
#endif
} // detail
@ -520,17 +554,14 @@ async_write_some(
serializer<isRequest,
basic_file_body<file_win32>, Fields>& sr,
WriteHandler&& handler)
{
BOOST_BEAST_HANDLER_INIT(
WriteHandler, void(error_code, std::size_t));
detail::write_some_win32_op<
Protocol, Executor,
BOOST_ASIO_HANDLER_TYPE(WriteHandler,
void(error_code, std::size_t)),
isRequest, Fields>{
std::move(init.completion_handler), sock, sr}();
return init.result.get();
{
return net::async_initiate<
WriteHandler,
void(error_code, std::size_t)>(
detail::run_write_some_win32_op{},
handler,
sock,
sr);
}
#endif

View File

@ -179,10 +179,10 @@ class read_msg_op
public:
template<class Handler_>
read_msg_op(
Handler_&& h,
Stream& s,
DynamicBuffer& b,
message_type& m,
Handler_&& h)
message_type& m)
: stable_async_op_base<
Handler, beast::executor_type<Stream>>(
std::forward<Handler_>(h), s.get_executor())
@ -203,6 +203,42 @@ public:
}
};
struct run_read_msg_op
{
template<
class ReadHandler,
class AsyncReadStream,
class DynamicBuffer,
bool isRequest, class Body, class Allocator>
void
operator()(
ReadHandler&& h,
AsyncReadStream& s,
DynamicBuffer& b,
message<isRequest, Body,
basic_fields<Allocator>>& m)
{
// 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");
read_msg_op<
AsyncReadStream,
DynamicBuffer,
isRequest, Body, Allocator,
typename std::decay<ReadHandler>::type>(
std::forward<ReadHandler>(h),
s,
b,
m);
}
};
} // detail
//------------------------------------------------------------------------------
@ -266,19 +302,12 @@ async_read_some(
basic_parser<isRequest, Derived>& parser,
ReadHandler&& handler)
{
static_assert(
is_async_read_stream<AsyncReadStream>::value,
"AsyncReadStream type requirements not met");
static_assert(
net::is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer type requirements not met");
BOOST_BEAST_HANDLER_INIT(
ReadHandler, void(error_code, std::size_t));
beast::detail::async_read(stream, buffer,
return beast::detail::async_read(
stream,
buffer,
detail::read_some_condition<
isRequest, Derived>{parser}, std::move(
init.completion_handler));
return init.result.get();
isRequest, Derived>{parser},
std::forward<ReadHandler>(handler));
}
//------------------------------------------------------------------------------
@ -343,20 +372,13 @@ async_read_header(
basic_parser<isRequest, Derived>& parser,
ReadHandler&& handler)
{
static_assert(
is_async_read_stream<AsyncReadStream>::value,
"AsyncReadStream type requirements not met");
static_assert(
net::is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer type requirements not met");
BOOST_BEAST_HANDLER_INIT(
ReadHandler, void(error_code, std::size_t));
parser.eager(false);
beast::detail::async_read(stream, buffer,
return beast::detail::async_read(
stream,
buffer,
detail::read_header_condition<
isRequest, Derived>{parser}, std::move(
init.completion_handler));
return init.result.get();
isRequest, Derived>{parser},
std::forward<ReadHandler>(handler));
}
//------------------------------------------------------------------------------
@ -427,14 +449,13 @@ async_read(
static_assert(
net::is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer type requirements not met");
BOOST_BEAST_HANDLER_INIT(
ReadHandler, void(error_code, std::size_t));
parser.eager(true);
beast::detail::async_read(stream, buffer,
return beast::detail::async_read(
stream,
buffer,
detail::read_all_condition<
isRequest, Derived>{parser}, std::move(
init.completion_handler));
return init.result.get();
isRequest, Derived>{parser},
std::forward<ReadHandler>(handler));
}
//------------------------------------------------------------------------------
@ -521,17 +542,14 @@ async_read(
"Body type requirements not met");
static_assert(is_body_reader<Body>::value,
"BodyReader type requirements not met");
BOOST_BEAST_HANDLER_INIT(
ReadHandler, void(error_code, std::size_t));
detail::read_msg_op<
AsyncReadStream,
DynamicBuffer,
isRequest, Body, Allocator,
BOOST_ASIO_HANDLER_TYPE(
ReadHandler, void(error_code, std::size_t))>(
stream, buffer, msg, std::move(
init.completion_handler));
return init.result.get();
return net::async_initiate<
ReadHandler,
void(error_code, std::size_t)>(
detail::run_read_msg_op{},
handler,
stream,
buffer,
msg);
}
} // http

View File

@ -30,7 +30,8 @@ namespace http {
namespace detail {
template<
class Stream, class Handler,
class Handler,
class Stream,
bool isRequest, class Body, class Fields>
class write_some_op
: public beast::async_op_base<
@ -150,7 +151,9 @@ struct serializer_is_done
//------------------------------------------------------------------------------
template<
class Stream, class Handler, class Predicate,
class Handler,
class Stream,
class Predicate,
bool isRequest, class Body, class Fields>
class write_op
: public beast::async_op_base<
@ -211,7 +214,8 @@ public:
//------------------------------------------------------------------------------
template<
class Stream, class Handler,
class Handler,
class Stream,
bool isRequest, class Body, class Fields>
class write_msg_op
: public beast::stable_async_op_base<
@ -225,8 +229,8 @@ public:
class Handler_,
class... Args>
write_msg_op(
Stream& s,
Handler_&& h,
Stream& s,
Args&&... args)
: stable_async_op_base<
Handler, beast::executor_type<Stream>>(
@ -253,6 +257,138 @@ public:
}
};
struct run_write_some_op
{
template<
class WriteHandler,
class Stream,
bool isRequest, class Body, class Fields>
void
operator()(
WriteHandler&& h,
Stream& s,
serializer<isRequest, Body, Fields>& sr)
{
// 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<WriteHandler,
void(error_code, std::size_t)>::value,
"WriteHandler type requirements not met");
write_some_op<
typename std::decay<WriteHandler>::type,
Stream,
isRequest, Body, Fields>(
std::forward<WriteHandler>(h),
s,
sr);
}
};
struct run_write_op
{
template<
class WriteHandler,
class Stream,
class Predicate,
bool isRequest, class Body, class Fields>
void
operator()(
WriteHandler&& h,
Stream& s,
Predicate const&,
serializer<isRequest, Body, Fields>& sr)
{
// 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<WriteHandler,
void(error_code, std::size_t)>::value,
"WriteHandler type requirements not met");
write_op<
typename std::decay<WriteHandler>::type,
Stream,
Predicate,
isRequest, Body, Fields>(
std::forward<WriteHandler>(h),
s,
sr);
}
};
struct run_write_msg_op
{
template<
class WriteHandler,
class Stream,
bool isRequest, class Body, class Fields,
class... Args>
void
operator()(
WriteHandler&& h,
Stream& s,
message<isRequest, Body, Fields>& m,
std::false_type,
Args&&... args)
{
// 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<WriteHandler,
void(error_code, std::size_t)>::value,
"WriteHandler type requirements not met");
write_msg_op<
typename std::decay<WriteHandler>::type,
Stream,
isRequest, Body, Fields>(
std::forward<WriteHandler>(h),
s,
m,
std::forward<Args>(args)...);
}
template<
class WriteHandler,
class Stream,
bool isRequest, class Body, class Fields,
class... Args>
void
operator()(
WriteHandler&& h,
Stream& s,
message<isRequest, Body, Fields> const& m,
std::true_type,
Args&&... args)
{
// 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<WriteHandler,
void(error_code, std::size_t)>::value,
"WriteHandler type requirements not met");
write_msg_op<
typename std::decay<WriteHandler>::type,
Stream,
isRequest, Body, Fields>(
std::forward<WriteHandler>(h),
s,
m,
std::forward<Args>(args)...);
}
};
//------------------------------------------------------------------------------
template<class Stream>
@ -341,15 +477,13 @@ async_write_some_impl(
serializer<isRequest, Body, Fields>& sr,
WriteHandler&& handler)
{
BOOST_BEAST_HANDLER_INIT(
WriteHandler, void(error_code, std::size_t));
detail::write_some_op<
AsyncWriteStream,
BOOST_ASIO_HANDLER_TYPE(WriteHandler,
void(error_code, std::size_t)),
isRequest, Body, Fields>(
std::move(init.completion_handler), stream, sr);
return init.result.get();
return net::async_initiate<
WriteHandler,
void(error_code, std::size_t)>(
run_write_some_op{},
handler,
stream,
sr);
}
} // detail
@ -498,16 +632,14 @@ async_write_header(
static_assert(is_body_writer<Body>::value,
"BodyWriter type requirements not met");
sr.split(true);
BOOST_BEAST_HANDLER_INIT(
WriteHandler, void(error_code, std::size_t));
detail::write_op<
AsyncWriteStream,
BOOST_ASIO_HANDLER_TYPE(WriteHandler,
void(error_code, std::size_t)),
detail::serializer_is_header_done,
isRequest, Body, Fields>{
std::move(init.completion_handler), stream, sr};
return init.result.get();
return net::async_initiate<
WriteHandler,
void(error_code, std::size_t)>(
detail::run_write_op{},
handler,
stream,
detail::serializer_is_header_done{},
sr);
}
//------------------------------------------------------------------------------
@ -574,16 +706,14 @@ async_write(
static_assert(is_body_writer<Body>::value,
"BodyWriter type requirements not met");
sr.split(false);
BOOST_BEAST_HANDLER_INIT(
WriteHandler, void(error_code, std::size_t));
detail::write_op<
AsyncWriteStream,
BOOST_ASIO_HANDLER_TYPE(WriteHandler,
void(error_code, std::size_t)),
detail::serializer_is_done,
isRequest, Body, Fields>{
std::move(init.completion_handler), stream, sr};
return init.result.get();
return net::async_initiate<
WriteHandler,
void(error_code, std::size_t)>(
detail::run_write_op{},
handler,
stream,
detail::serializer_is_done{},
sr);
}
//------------------------------------------------------------------------------
@ -698,15 +828,14 @@ async_write(
"Body type requirements not met");
static_assert(is_body_writer<Body>::value,
"BodyWriter type requirements not met");
BOOST_BEAST_HANDLER_INIT(
WriteHandler, void(error_code, std::size_t));
detail::write_msg_op<
AsyncWriteStream,
BOOST_ASIO_HANDLER_TYPE(WriteHandler,
void(error_code, std::size_t)),
isRequest, Body, Fields>(stream,
std::move(init.completion_handler), msg);
return init.result.get();
return net::async_initiate<
WriteHandler,
void(error_code, std::size_t)>(
detail::run_write_msg_op{},
handler,
stream,
msg,
std::false_type{});
}
template<
@ -729,15 +858,14 @@ async_write(
"Body type requirements not met");
static_assert(is_body_writer<Body>::value,
"BodyWriter type requirements not met");
BOOST_BEAST_HANDLER_INIT(
WriteHandler, void(error_code, std::size_t));
detail::write_msg_op<
AsyncWriteStream,
BOOST_ASIO_HANDLER_TYPE(WriteHandler,
void(error_code, std::size_t)),
isRequest, Body, Fields>(stream,
std::move(init.completion_handler), msg);
return init.result.get();
return net::async_initiate<
WriteHandler,
void(error_code, std::size_t)>(
detail::run_write_msg_op{},
handler,
stream,
msg,
std::true_type{});
}
//------------------------------------------------------------------------------

View File

@ -241,7 +241,7 @@ public:
// read and respond to an upgrade request
//
template<class NextLayer, bool deflateSupported>
template<class Decorator, class Handler>
template<class Handler, class Decorator>
class stream<NextLayer, deflateSupported>::accept_op
: public beast::stable_async_op_base<
Handler, beast::executor_type<stream>>
@ -256,8 +256,8 @@ public:
accept_op(
Handler_&& h,
boost::shared_ptr<impl_type> const& sp,
Buffers const& buffers,
Decorator const& decorator)
Decorator const& decorator,
Buffers const& buffers)
: stable_async_op_base<Handler,
beast::executor_type<stream>>(
std::forward<Handler_>(h),
@ -325,6 +325,74 @@ public:
}
};
template<class NextLayer, bool deflateSupported>
struct stream<NextLayer, deflateSupported>::
run_response_op
{
template<
class AcceptHandler,
class Body, class Allocator,
class Decorator>
void
operator()(
AcceptHandler&& h,
boost::shared_ptr<impl_type> const& sp,
http::request<Body,
http::basic_fields<Allocator>> const& m,
Decorator const& d)
{
// 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<AcceptHandler,
void(error_code)>::value,
"AcceptHandler type requirements not met");
response_op<
typename std::decay<AcceptHandler>::type>(
std::forward<AcceptHandler>(h),
sp,
m,
d);
}
};
template<class NextLayer, bool deflateSupported>
struct stream<NextLayer, deflateSupported>::
run_accept_op
{
template<
class AcceptHandler,
class Decorator,
class Buffers>
void
operator()(
AcceptHandler&& h,
boost::shared_ptr<impl_type> const& sp,
Decorator const& d,
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 the handler.
static_assert(
beast::detail::is_invocable<AcceptHandler,
void(error_code)>::value,
"AcceptHandler type requirements not met");
accept_op<
typename std::decay<AcceptHandler>::type,
Decorator>(
std::forward<AcceptHandler>(h),
sp,
d,
b);
}
};
//------------------------------------------------------------------------------
template<class NextLayer, bool deflateSupported>
@ -488,17 +556,15 @@ async_accept(
{
static_assert(is_async_stream<next_layer_type>::value,
"AsyncStream type requirements not met");
BOOST_BEAST_HANDLER_INIT(
AcceptHandler, void(error_code));
impl_->reset();
accept_op<
decltype(&default_decorate_res),
BOOST_ASIO_HANDLER_TYPE(
AcceptHandler, void(error_code))>(
std::move(init.completion_handler),
impl_, net::const_buffer{},
&default_decorate_res);;
return init.result.get();
return net::async_initiate<
AcceptHandler,
void(error_code)>(
run_accept_op{},
handler,
impl_,
&default_decorate_res,
net::const_buffer{});
}
template<class NextLayer, bool deflateSupported>
@ -517,17 +583,15 @@ async_accept_ex(
static_assert(detail::is_response_decorator<
ResponseDecorator>::value,
"ResponseDecorator requirements not met");
BOOST_BEAST_HANDLER_INIT(
AcceptHandler, void(error_code));
impl_->reset();
accept_op<
ResponseDecorator,
BOOST_ASIO_HANDLER_TYPE(
AcceptHandler, void(error_code))>(
std::move(init.completion_handler),
impl_, net::const_buffer{},
decorator);
return init.result.get();
return net::async_initiate<
AcceptHandler,
void(error_code)>(
run_accept_op{},
handler,
impl_,
decorator,
net::const_buffer{});
}
template<class NextLayer, bool deflateSupported>
@ -548,16 +612,15 @@ async_accept(
static_assert(net::is_const_buffer_sequence<
ConstBufferSequence>::value,
"ConstBufferSequence type requirements not met");
BOOST_BEAST_HANDLER_INIT(
AcceptHandler, void(error_code));
impl_->reset();
accept_op<
decltype(&default_decorate_res),
BOOST_ASIO_HANDLER_TYPE(
AcceptHandler, void(error_code))>(
std::move(init.completion_handler),
impl_, buffers, &default_decorate_res);
return init.result.get();
return net::async_initiate<
AcceptHandler,
void(error_code)>(
run_accept_op{},
handler,
impl_,
&default_decorate_res,
buffers);
}
template<class NextLayer, bool deflateSupported>
@ -583,16 +646,15 @@ async_accept_ex(
static_assert(detail::is_response_decorator<
ResponseDecorator>::value,
"ResponseDecorator requirements not met");
BOOST_BEAST_HANDLER_INIT(
AcceptHandler, void(error_code));
impl_->reset();
accept_op<
ResponseDecorator,
BOOST_ASIO_HANDLER_TYPE(
AcceptHandler, void(error_code))>(
std::move(init.completion_handler),
impl_, buffers, decorator);
return init.result.get();
return net::async_initiate<
AcceptHandler,
void(error_code)>(
run_accept_op{},
handler,
impl_,
decorator,
buffers);
}
template<class NextLayer, bool deflateSupported>
@ -608,15 +670,15 @@ async_accept(
{
static_assert(is_async_stream<next_layer_type>::value,
"AsyncStream type requirements not met");
BOOST_BEAST_HANDLER_INIT(
AcceptHandler, void(error_code));
impl_->reset();
response_op<
BOOST_ASIO_HANDLER_TYPE(
AcceptHandler, void(error_code))>(
std::move(init.completion_handler),
impl_, req, &default_decorate_res);
return init.result.get();
return net::async_initiate<
AcceptHandler,
void(error_code)>(
run_response_op{},
handler,
impl_,
req,
&default_decorate_res);
}
template<class NextLayer, bool deflateSupported>
@ -637,15 +699,15 @@ async_accept_ex(
static_assert(detail::is_response_decorator<
ResponseDecorator>::value,
"ResponseDecorator requirements not met");
BOOST_BEAST_HANDLER_INIT(
AcceptHandler, void(error_code));
impl_->reset();
response_op<
BOOST_ASIO_HANDLER_TYPE(
AcceptHandler, void(error_code))>(
std::move(init.completion_handler),
impl_, req, decorator);
return init.result.get();
return net::async_initiate<
AcceptHandler,
void(error_code)>(
run_response_op{},
handler,
impl_,
req,
decorator);
}
//------------------------------------------------------------------------------

View File

@ -230,6 +230,34 @@ public:
}
};
template<class NextLayer, bool deflateSupported>
struct stream<NextLayer, deflateSupported>::
run_close_op
{
template<class CloseHandler>
void
operator()(
CloseHandler&& h,
boost::shared_ptr<impl_type> const& sp,
close_reason const& cr)
{
// 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<CloseHandler,
void(error_code)>::value,
"CloseHandler type requirements not met");
close_op<
typename std::decay<CloseHandler>::type>(
std::forward<CloseHandler>(h),
sp,
cr);
}
};
//------------------------------------------------------------------------------
template<class NextLayer, bool deflateSupported>
@ -360,12 +388,13 @@ async_close(close_reason const& cr, CloseHandler&& handler)
{
static_assert(is_async_stream<next_layer_type>::value,
"AsyncStream type requirements not met");
BOOST_BEAST_HANDLER_INIT(
CloseHandler, void(error_code));
close_op<BOOST_ASIO_HANDLER_TYPE(
CloseHandler, void(error_code))>(
std::move(init.completion_handler), impl_, cr);
return init.result.get();
return net::async_initiate<
CloseHandler,
void(error_code)>(
run_close_op{},
handler,
impl_,
cr);
}
} // websocket

View File

@ -74,6 +74,7 @@ public:
d_.req = sp->build_request(
key_, host, target, decorator);
sp->reset(); // VFALCO I don't like this
(*this)({}, 0, false);
}
void
@ -157,6 +158,37 @@ public:
}
};
template<class NextLayer, bool deflateSupported>
struct stream<NextLayer, deflateSupported>::
run_handshake_op
{
template<class HandshakeHandler, class Decorator>
void operator()(
HandshakeHandler&& h,
boost::shared_ptr<impl_type> const& sp,
response_type* r,
string_view host, string_view target,
Decorator const& d)
{
// 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<HandshakeHandler,
void(error_code)>::value,
"HandshakeHandler type requirements not met");
handshake_op<
typename std::decay<HandshakeHandler>::type>(
std::forward<HandshakeHandler>(h),
sp,
r,
host, target,
d);
}
};
//------------------------------------------------------------------------------
template<class NextLayer, bool deflateSupported>
@ -241,14 +273,15 @@ async_handshake(string_view host,
{
static_assert(is_async_stream<next_layer_type>::value,
"AsyncStream type requirements not met");
BOOST_BEAST_HANDLER_INIT(
HandshakeHandler, void(error_code));
handshake_op<BOOST_ASIO_HANDLER_TYPE(
HandshakeHandler, void(error_code))>(
std::move(init.completion_handler),
impl_, nullptr, host, target,
&default_decorate_req)();
return init.result.get();
return net::async_initiate<
HandshakeHandler,
void(error_code)>(
run_handshake_op{},
handler,
impl_,
nullptr,
host, target,
&default_decorate_req);
}
template<class NextLayer, bool deflateSupported>
@ -263,14 +296,15 @@ async_handshake(response_type& res,
{
static_assert(is_async_stream<next_layer_type>::value,
"AsyncStream type requirements not met");
BOOST_BEAST_HANDLER_INIT(
HandshakeHandler, void(error_code));
handshake_op<BOOST_ASIO_HANDLER_TYPE(
HandshakeHandler, void(error_code))>(
std::move(init.completion_handler),
impl_, &res, host, target,
&default_decorate_req)();
return init.result.get();
return net::async_initiate<
HandshakeHandler,
void(error_code)>(
run_handshake_op{},
handler,
impl_,
&res,
host, target,
&default_decorate_req);
}
template<class NextLayer, bool deflateSupported>
@ -442,14 +476,15 @@ async_handshake_ex(string_view host,
static_assert(detail::is_request_decorator<
RequestDecorator>::value,
"RequestDecorator requirements not met");
BOOST_BEAST_HANDLER_INIT(
HandshakeHandler, void(error_code));
handshake_op<BOOST_ASIO_HANDLER_TYPE(
HandshakeHandler, void(error_code))>(
std::move(init.completion_handler),
impl_, nullptr, host, target,
decorator)();
return init.result.get();
return net::async_initiate<
HandshakeHandler,
void(error_code)>(
run_handshake_op{},
handler,
impl_,
nullptr,
host, target,
decorator);
}
template<class NextLayer, bool deflateSupported>
@ -472,19 +507,17 @@ async_handshake_ex(response_type& res,
static_assert(detail::is_request_decorator<
RequestDecorator>::value,
"RequestDecorator requirements not met");
BOOST_BEAST_HANDLER_INIT(
HandshakeHandler, void(error_code));
handshake_op<BOOST_ASIO_HANDLER_TYPE(
HandshakeHandler, void(error_code))>(
std::move(init.completion_handler),
impl_, &res, host, target,
decorator)();
return init.result.get();
return net::async_initiate<
HandshakeHandler,
void(error_code)>(
run_handshake_op{},
handler,
impl_,
&res,
host, target,
decorator);
}
} // websocket
} // beast
} // boost

View File

@ -200,6 +200,36 @@ public:
}
};
template<class NextLayer, bool deflateSupported>
struct stream<NextLayer, deflateSupported>::
run_ping_op
{
template<class WriteHandler>
void
operator()(
WriteHandler&& h,
boost::shared_ptr<impl_type> const& sp,
detail::opcode op,
ping_data const& p)
{
// 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<WriteHandler,
void(error_code)>::value,
"WriteHandler type requirements not met");
ping_op<
typename std::decay<WriteHandler>::type>(
std::forward<WriteHandler>(h),
sp,
op,
p);
}
};
//------------------------------------------------------------------------------
template<class NextLayer, bool deflateSupported>
@ -263,13 +293,14 @@ async_ping(ping_data const& payload, WriteHandler&& handler)
{
static_assert(is_async_stream<next_layer_type>::value,
"AsyncStream type requirements not met");
BOOST_BEAST_HANDLER_INIT(
WriteHandler, void(error_code));
ping_op<BOOST_ASIO_HANDLER_TYPE(
WriteHandler, void(error_code))>(
std::move(init.completion_handler), impl_,
detail::opcode::ping, payload);
return init.result.get();
return net::async_initiate<
WriteHandler,
void(error_code)>(
run_ping_op{},
handler,
impl_,
detail::opcode::ping,
payload);
}
template<class NextLayer, bool deflateSupported>
@ -281,13 +312,14 @@ async_pong(ping_data const& payload, WriteHandler&& handler)
{
static_assert(is_async_stream<next_layer_type>::value,
"AsyncStream type requirements not met");
BOOST_BEAST_HANDLER_INIT(
WriteHandler, void(error_code));
ping_op<BOOST_ASIO_HANDLER_TYPE(
WriteHandler, void(error_code))>(
std::move(init.completion_handler), impl_,
detail::opcode::pong, payload);
return init.result.get();
return net::async_initiate<
WriteHandler,
void(error_code)>(
run_ping_op{},
handler,
impl_,
detail::opcode::pong,
payload);
}
} // websocket

View File

@ -43,9 +43,7 @@ namespace websocket {
Also reads and handles control frames.
*/
template<class NextLayer, bool deflateSupported>
template<
class MutableBufferSequence,
class Handler>
template<class Handler, class MutableBufferSequence>
class stream<NextLayer, deflateSupported>::read_some_op
: public beast::async_op_base<
Handler, beast::executor_type<stream>>
@ -613,9 +611,7 @@ public:
//------------------------------------------------------------------------------
template<class NextLayer, bool deflateSupported>
template<
class DynamicBuffer,
class Handler>
template<class Handler, class DynamicBuffer>
class stream<NextLayer, deflateSupported>::read_op
: public beast::async_op_base<
Handler, beast::executor_type<stream>>
@ -674,7 +670,7 @@ public:
// VFALCO TODO use boost::beast::bind_continuation
BOOST_ASIO_CORO_YIELD
read_some_op<mutable_buffers_type, read_op>(
read_some_op<read_op, mutable_buffers_type>(
std::move(*this), sp, *mb);
b_.commit(bytes_transferred);
bytes_written_ += bytes_transferred;
@ -689,6 +685,72 @@ public:
}
};
template<class NextLayer, bool deflateSupported>
struct stream<NextLayer, deflateSupported>::
run_read_some_op
{
template<
class ReadHandler,
class MutableBufferSequence>
void
operator()(
ReadHandler&& h,
boost::shared_ptr<impl_type> const& sp,
MutableBufferSequence const& b)
{
// 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");
read_some_op<
typename std::decay<ReadHandler>::type,
MutableBufferSequence>(
std::forward<ReadHandler>(h),
sp,
b);
}
};
template<class NextLayer, bool deflateSupported>
struct stream<NextLayer, deflateSupported>::
run_read_op
{
template<
class ReadHandler,
class DynamicBuffer>
void
operator()(
ReadHandler&& h,
boost::shared_ptr<impl_type> const& sp,
DynamicBuffer& b,
std::size_t limit,
bool some)
{
// 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");
read_op<
typename std::decay<ReadHandler>::type,
DynamicBuffer>(
std::forward<ReadHandler>(h),
sp,
b,
limit,
some);
}
};
//------------------------------------------------------------------------------
template<class NextLayer, bool deflateSupported>
@ -743,13 +805,15 @@ async_read(DynamicBuffer& buffer, ReadHandler&& handler)
static_assert(
net::is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer type requirements not met");
BOOST_BEAST_HANDLER_INIT(
ReadHandler, void(error_code, std::size_t));
read_op<DynamicBuffer, BOOST_ASIO_HANDLER_TYPE(
ReadHandler, void(error_code, std::size_t))>(
std::move(init.completion_handler),
impl_, buffer, 0, false);
return init.result.get();
return net::async_initiate<
ReadHandler,
void(error_code, std::size_t)>(
run_read_op{},
handler,
impl_,
buffer,
0,
false);
}
//------------------------------------------------------------------------------
@ -819,13 +883,15 @@ async_read_some(
static_assert(
net::is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer type requirements not met");
BOOST_BEAST_HANDLER_INIT(
ReadHandler, void(error_code, std::size_t));
read_op<DynamicBuffer, BOOST_ASIO_HANDLER_TYPE(
ReadHandler, void(error_code, std::size_t))>(
std::move(init.completion_handler),
impl_, buffer, limit, true);
return init.result.get();
return net::async_initiate<
ReadHandler,
void(error_code, std::size_t)>(
run_read_op{},
handler,
impl_,
buffer,
limit,
true);
}
//------------------------------------------------------------------------------
@ -1200,12 +1266,13 @@ async_read_some(
static_assert(net::is_mutable_buffer_sequence<
MutableBufferSequence>::value,
"MutableBufferSequence type requirements not met");
BOOST_BEAST_HANDLER_INIT(
ReadHandler, void(error_code, std::size_t));
read_some_op<MutableBufferSequence, BOOST_ASIO_HANDLER_TYPE(
ReadHandler, void(error_code, std::size_t))>(
std::move(init.completion_handler), impl_, buffers);
return init.result.get();
return net::async_initiate<
ReadHandler,
void(error_code, std::size_t)>(
run_read_some_op{},
handler,
impl_,
buffers);
}
} // websocket

View File

@ -37,7 +37,7 @@ namespace beast {
namespace websocket {
template<class NextLayer, bool deflateSupported>
template<class Buffers, class Handler>
template<class Handler, class Buffers>
class stream<NextLayer, deflateSupported>::write_some_op
: public beast::async_op_base<
Handler, beast::executor_type<stream>>
@ -430,6 +430,39 @@ operator()(
}
}
template<class NextLayer, bool deflateSupported>
struct stream<NextLayer, deflateSupported>::
run_write_some_op
{
template<
class WriteHandler,
class ConstBufferSequence>
void
operator()(
WriteHandler&& h,
boost::shared_ptr<impl_type> const& sp,
bool fin,
ConstBufferSequence const& b)
{
// 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<WriteHandler,
void(error_code, std::size_t)>::value,
"WriteHandler type requirements not met");
write_some_op<
typename std::decay<WriteHandler>::type,
ConstBufferSequence>(
std::forward<WriteHandler>(h),
sp,
fin,
b);
}
};
//------------------------------------------------------------------------------
template<class NextLayer, bool deflateSupported>
@ -676,12 +709,14 @@ async_write_some(bool fin,
static_assert(net::is_const_buffer_sequence<
ConstBufferSequence>::value,
"ConstBufferSequence type requirements not met");
BOOST_BEAST_HANDLER_INIT(
WriteHandler, void(error_code, std::size_t));
write_some_op<ConstBufferSequence, BOOST_ASIO_HANDLER_TYPE(
WriteHandler, void(error_code, std::size_t))>(
std::move(init.completion_handler), impl_, fin, bs);
return init.result.get();
return net::async_initiate<
WriteHandler,
void(error_code, std::size_t)>(
run_write_some_op{},
handler,
impl_,
fin,
bs);
}
//------------------------------------------------------------------------------
@ -731,12 +766,14 @@ async_write(
static_assert(net::is_const_buffer_sequence<
ConstBufferSequence>::value,
"ConstBufferSequence type requirements not met");
BOOST_BEAST_HANDLER_INIT(
WriteHandler, void(error_code, std::size_t));
write_some_op<ConstBufferSequence, BOOST_ASIO_HANDLER_TYPE(
WriteHandler, void(error_code, std::size_t))>(
std::move(init.completion_handler), impl_, true, bs);
return init.result.get();
return net::async_initiate<
WriteHandler,
void(error_code, std::size_t)>(
run_write_some_op{},
handler,
impl_,
true,
bs);
}
} // websocket

View File

@ -20,6 +20,7 @@
#include <boost/beast/websocket/detail/hybi13.hpp>
#include <boost/beast/websocket/detail/impl_base.hpp>
#include <boost/beast/websocket/detail/pmd_extension.hpp>
#include <boost/beast/core/stream_traits.hpp>
#include <boost/beast/core/string.hpp>
#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/beast/http/detail/type_traits.hpp>
@ -127,6 +128,16 @@ class stream
: private stream_base
#endif
{
struct impl_type;
boost::shared_ptr<impl_type> impl_;
using time_point = typename
std::chrono::steady_clock::time_point;
using control_cb_type =
std::function<void(frame_type, string_view)>;
friend class close_test;
friend class frame_test;
friend class ping_test;
@ -142,16 +153,6 @@ class stream
static std::size_t constexpr max_control_frame_size = 2 + 8 + 4 + 125;
static std::size_t constexpr tcp_frame_size = 1536;
using control_cb_type =
std::function<void(frame_type, string_view)>;
struct impl_type;
boost::shared_ptr<impl_type> impl_;
using time_point = typename
std::chrono::steady_clock::time_point;
static time_point never() noexcept
{
return (time_point::max)();
@ -167,7 +168,8 @@ public:
typename std::remove_reference<NextLayer>::type;
/// The type of the executor associated with the object.
using executor_type = typename next_layer_type::executor_type;
using executor_type =
beast::executor_type<next_layer_type>;
/** Destructor
@ -2636,6 +2638,17 @@ private:
template<class, class> class write_some_op;
template<class, class> class write_op;
struct run_accept_op;
struct run_close_op;
struct run_handshake_op;
struct run_ping_op;
struct run_idle_ping_op;
struct run_read_some_op;
struct run_read_op;
struct run_response_op;
struct run_write_some_op;
struct run_write_op;
static void default_decorate_req(request_type&) {}
static void default_decorate_res(response_type&) {}

View File

@ -211,33 +211,16 @@ public:
}
};
void
testAsioHandlerInvoke()
{
// make sure things compile, also can set a
// breakpoint in asio_handler_invoke to make sure
// it is instantiated.
net::io_context ioc;
net::strand<
net::io_context::executor_type> s(
ioc.get_executor());
test::stream ts{ioc};
buffered_read_stream<
test::stream&, multi_buffer> brs(ts);
brs.async_read_some(net::mutable_buffer{},
net::bind_executor(
s, copyable_handler{}));
}
void run() override
{
testSpecialMembers();
yield_to([&](yield_context yield){
testRead(yield);});
yield_to([&](yield_context yield)
{
testRead(yield);
});
testAsyncLoop();
testAsioHandlerInvoke();
}
};