diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c8aa58d..981a9b6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Version 217: * RatePolicy documentation * Pass strand to async_accept * Fix file_body_win32 +* Use async_initiate -------------------------------------------------------------------------------- diff --git a/CMakeLists.txt b/CMakeLists.txt index 32c7062c..5caa2e32 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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() diff --git a/doc/qbk/release_notes.qbk b/doc/qbk/release_notes.qbk index 4645342c..a651713d 100644 --- a/doc/qbk/release_notes.qbk +++ b/doc/qbk/release_notes.qbk @@ -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 diff --git a/include/boost/beast/_experimental/http/icy_stream.hpp b/include/boost/beast/_experimental/http/icy_stream.hpp index 983a6a8b..7f2a4b0f 100644 --- a/include/boost/beast/_experimental/http/icy_stream.hpp +++ b/include/boost/beast/_experimental/http/icy_stream.hpp @@ -68,7 +68,7 @@ namespace http { template class icy_stream { - template class read_op; + struct ops; NextLayer stream_; bool detect_ = true; diff --git a/include/boost/beast/_experimental/http/impl/icy_stream.hpp b/include/boost/beast/_experimental/http/impl/icy_stream.hpp index 7e72dcf7..97327ff0 100644 --- a/include/boost/beast/_experimental/http/impl/icy_stream.hpp +++ b/include/boost/beast/_experimental/http/impl/icy_stream.hpp @@ -118,8 +118,11 @@ public: } // detail template -template -class icy_stream::read_op +struct icy_stream::ops +{ + +template +class read_op : public beast::stable_async_op_base> , public net::coroutine @@ -127,15 +130,21 @@ class icy_stream::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 b; + buffers_adaptor 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>( std::forward(h), s.get_executor()) @@ -165,7 +174,7 @@ public: { using iterator = net::buffers_iterator< typename beast::dynamic_buffer_ref_wrapper< - buffers_adaptor>::const_buffers_type>; + buffers_adaptor>::const_buffers_type>; BOOST_ASIO_CORO_REENTER(*this) { if(d_.b.max_size() == 0) @@ -272,7 +281,7 @@ public: } { buffers_suffix> 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 + 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::value, + "ReadHandler type requirements not met"); + + read_op< + Buffers, + typename std::decay::type>( + std::forward(h), s, b); + } +}; + +}; + //------------------------------------------------------------------------------ template @@ -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 diff --git a/include/boost/beast/_experimental/test/impl/stream.hpp b/include/boost/beast/_experimental/test/impl/stream.hpp index c31f101f..4c1cd67a 100644 --- a/include/boost/beast/_experimental/test/impl/stream.hpp +++ b/include/boost/beast/_experimental/test/impl/stream.hpp @@ -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 wg2_; public: lambda(lambda&&) = default; lambda(lambda const&) = default; - template - lambda(state& s, Buffers const& b, DeducedHandler&& h) - : s_(s) + template + lambda( + Handler_&& h, + state& s, + Buffers const& b) + : h_(std::forward(h)) + , s_(s) , b_(b) - , h_(std::forward(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 - read_op(state& s, - Buffers const& b, Handler_&& h) - : fn_(s, b, std::forward(h)) + read_op( + Handler_&& h, + state& s, + Buffers const& b) + : fn_(std::forward(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 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::value, + "ReadHandler type requirements not met"); + + ++in_->nread; + + std::unique_lock 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 in_, + std::weak_ptr 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::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( + buffer_size(buffers), in_->write_max); + { + std::lock_guard 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 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{*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 @@ -509,70 +619,22 @@ template 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( - buffer_size(buffers), in_->write_max); - { - std::lock_guard 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 diff --git a/include/boost/beast/_experimental/test/stream.hpp b/include/boost/beast/_experimental/test/stream.hpp index 6c29ab76..5b4dc1ce 100644 --- a/include/boost/beast/_experimental/test/stream.hpp +++ b/include/boost/beast/_experimental/test/stream.hpp @@ -105,6 +105,9 @@ class stream template class read_op; + struct run_read_op; + struct run_write_op; + enum class status { ok, diff --git a/include/boost/beast/core/buffered_read_stream.hpp b/include/boost/beast/core/buffered_read_stream.hpp index 4c3dfed4..2ff88236 100644 --- a/include/boost/beast/core/buffered_read_stream.hpp +++ b/include/boost/beast/core/buffered_read_stream.hpp @@ -95,8 +95,7 @@ class buffered_read_stream net::is_dynamic_buffer::value, "DynamicBuffer type requirements not met"); - template - class read_some_op; + struct ops; DynamicBuffer buffer_; std::size_t capacity_ = 0; diff --git a/include/boost/beast/core/detail/impl/read.hpp b/include/boost/beast/core/detail/impl/read.hpp index 84121034..682735b3 100644 --- a/include/boost/beast/core/detail/impl/read.hpp +++ b/include/boost/beast/core/detail/impl/read.hpp @@ -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 + template read_op( + Handler_&& h, Stream& s, DynamicBuffer& b, - Condition cond, - Handler_&& h) + Condition_&& cond) : async_op_base>( std::forward(h), s.get_executor()) , s_(s) , b_(b) - , cond_(cond) + , cond_(std::forward(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>> + , public async_op_base { - net::basic_stream_socket& 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 + template read_non_blocking_op( - net::basic_stream_socket& s, + Handler_&& h, + net::basic_stream_socket< + Protocol, Executor>& s, DynamicBuffer& b, - Condition cond, - Handler_&& h) - : async_op_base>>( - s.get_executor(), std::forward(h)) + Condition cond) + : async_op_base( + s.get_executor(), std::forward(h)) , s_(s) , b_(b) - , cond_(cond) + , cond_(std::forward(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::value, - "AsyncReadStream type requirements not met"); - static_assert( - net::is_dynamic_buffer::value, - "DynamicBuffer type requirements not met"); - static_assert( - detail::is_invocable::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& socket, - DynamicBuffer& buffer, - CompletionCondition cond, - ReadHandler&& handler) -{ - static_assert( - net::is_dynamic_buffer::value, - "DynamicBuffer type requirements not met"); - static_assert( - detail::is_invocable::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::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::type, + typename std::decay::type>( + std::forward(h), + s, + b, + std::forward(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& 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::value, + "ReadHandler type requirements not met"); + + if(s.non_blocking()) + { + read_non_blocking_op< + Protocol, Executor, + DynamicBuffer, + typename std::decay::type, + typename std::decay::type>( + std::forward(h), + s, + b, + std::forward(c)); + } + else + { + read_op< + net::basic_stream_socket, + DynamicBuffer, + typename std::decay::type, + typename std::decay::type>( + std::forward(h), + s, + b, + std::forward(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::value, + "AsyncReadStream type requirements not met"); + static_assert( + net::is_dynamic_buffer::value, + "DynamicBuffer type requirements not met"); + static_assert( + detail::is_invocable::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(cond)); +} + } // detail } // beast } // boost diff --git a/include/boost/beast/core/detail/read.hpp b/include/boost/beast/core/detail/read.hpp index 614988a6..6fc5642b 100644 --- a/include/boost/beast/core/detail/read.hpp +++ b/include/boost/beast/core/detail/read.hpp @@ -235,7 +235,7 @@ BOOST_ASIO_INITFN_RESULT_TYPE( async_read( AsyncReadStream& stream, DynamicBuffer& buffer, - CompletionCondition completion_condition, + CompletionCondition&& completion_condition, ReadHandler&& handler); } // detail diff --git a/include/boost/beast/core/detail/type_traits.hpp b/include/boost/beast/core/detail/type_traits.hpp index f57458d7..cbc5f918 100644 --- a/include/boost/beast/core/detail/type_traits.hpp +++ b/include/boost/beast/core/detail/type_traits.hpp @@ -124,20 +124,6 @@ struct is_contiguous_container::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 init{handler} - } // detail } // beast } // boost diff --git a/include/boost/beast/core/flat_stream.hpp b/include/boost/beast/core/flat_stream.hpp index d294ef16..45b33628 100644 --- a/include/boost/beast/core/flat_stream.hpp +++ b/include/boost/beast/core/flat_stream.hpp @@ -90,13 +90,13 @@ class flat_stream : private detail::flat_stream_base #endif { - template class write_op; - NextLayer stream_; flat_buffer buffer_; BOOST_STATIC_ASSERT(has_get_executor::value); + struct ops; + template std::size_t stack_write_some( diff --git a/include/boost/beast/core/impl/basic_stream.hpp b/include/boost/beast/core/impl/basic_stream.hpp index 18699e7a..d9974577 100644 --- a/include/boost/beast/core/impl/basic_stream.hpp +++ b/include/boost/beast/core/impl/basic_stream.hpp @@ -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::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::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::value, "ConnectHandler type requirements not met"); + connect_op::type>( std::forward(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::value, "RangeConnectHandler type requirements not met"); + connect_op::type>( std::forward(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::value, "IteratorConnectHandler type requirements not met"); + connect_op::type>( std::forward(h), s, begin, end, cond); } diff --git a/include/boost/beast/core/impl/buffered_read_stream.hpp b/include/boost/beast/core/impl/buffered_read_stream.hpp index 805ce9c0..223cfd3b 100644 --- a/include/boost/beast/core/impl/buffered_read_stream.hpp +++ b/include/boost/beast/core/impl/buffered_read_stream.hpp @@ -22,23 +22,26 @@ namespace boost { namespace beast { + template +struct buffered_read_stream::ops +{ + template -class buffered_read_stream< - Stream, DynamicBuffer>::read_some_op - : public async_op_base< - Handler, beast::executor_type> +class read_op + : public async_op_base> { 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 - 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 + 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::value, + "ReadHandler type requirements not met"); + + read_op< + Buffers, + typename std::decay::type>( + std::forward(h), + s, + b); + } +}; + +}; + //------------------------------------------------------------------------------ template @@ -198,12 +231,13 @@ async_read_some( if(buffer_.size() == 0 && capacity_ == 0) return next_layer_.async_read_some(buffers, std::forward(handler)); - BOOST_BEAST_HANDLER_INIT( - ReadHandler, void(error_code, std::size_t)); - read_some_op( - 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 diff --git a/include/boost/beast/core/impl/flat_stream.hpp b/include/boost/beast/core/impl/flat_stream.hpp index 734b199c..092833d3 100644 --- a/include/boost/beast/core/impl/flat_stream.hpp +++ b/include/boost/beast/core/impl/flat_stream.hpp @@ -23,8 +23,11 @@ namespace boost { namespace beast { template +struct flat_stream::ops +{ + template -class flat_stream::write_op +class write_op : public async_op_base> , public net::coroutine @@ -34,9 +37,9 @@ public: class ConstBufferSequence, class Handler_> write_op( + Handler_&& h, flat_stream& s, - ConstBufferSequence const& b, - Handler_&& h) + ConstBufferSequence const& b) : async_op_base>( std::forward(h), @@ -72,6 +75,34 @@ public: } }; +struct run_write_op +{ + template + 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::value, + "WriteHandler type requirements not met"); + + write_op< + typename std::decay::type>( + std::forward(h), + s, + b); + } +}; + +}; + //------------------------------------------------------------------------------ template @@ -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( - *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 diff --git a/include/boost/beast/http/impl/file_body_win32.ipp b/include/boost/beast/http/impl/file_body_win32.ipp index dff028d3..01f8e5a6 100644 --- a/include/boost/beast/http/impl/file_body_win32.ipp +++ b/include/boost/beast/http/impl/file_body_win32.ipp @@ -32,7 +32,7 @@ namespace beast { namespace http { namespace detail { -template +template class write_some_win32_op; } // detail @@ -52,7 +52,7 @@ struct basic_file_body friend class reader; friend struct basic_file_body; - template + template friend class detail::write_some_win32_op; template< class Protocol, class Executor, @@ -102,7 +102,7 @@ struct basic_file_body class writer { - template + template 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 { @@ -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, 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::value, + "WriteHandler type requirements not met"); + + write_some_win32_op< + Protocol, Executor, + isRequest, Fields, + typename std::decay::type>( + std::forward(h), + s, + sr); + } +}; + #endif } // detail @@ -520,17 +554,14 @@ async_write_some( serializer, 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 diff --git a/include/boost/beast/http/impl/read.ipp b/include/boost/beast/http/impl/read.ipp index 3cc9c0bf..135ab4a7 100644 --- a/include/boost/beast/http/impl/read.ipp +++ b/include/boost/beast/http/impl/read.ipp @@ -179,10 +179,10 @@ class read_msg_op public: template 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>( std::forward(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>& 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::value, + "ReadHandler type requirements not met"); + + read_msg_op< + AsyncReadStream, + DynamicBuffer, + isRequest, Body, Allocator, + typename std::decay::type>( + std::forward(h), + s, + b, + m); + } +}; + } // detail //------------------------------------------------------------------------------ @@ -266,19 +302,12 @@ async_read_some( basic_parser& parser, ReadHandler&& handler) { - static_assert( - is_async_read_stream::value, - "AsyncReadStream type requirements not met"); - static_assert( - net::is_dynamic_buffer::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(handler)); } //------------------------------------------------------------------------------ @@ -343,20 +372,13 @@ async_read_header( basic_parser& parser, ReadHandler&& handler) { - static_assert( - is_async_read_stream::value, - "AsyncReadStream type requirements not met"); - static_assert( - net::is_dynamic_buffer::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(handler)); } //------------------------------------------------------------------------------ @@ -427,14 +449,13 @@ async_read( static_assert( net::is_dynamic_buffer::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(handler)); } //------------------------------------------------------------------------------ @@ -521,17 +542,14 @@ async_read( "Body type requirements not met"); static_assert(is_body_reader::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 diff --git a/include/boost/beast/http/impl/write.ipp b/include/boost/beast/http/impl/write.ipp index 15318f4e..b3628198 100644 --- a/include/boost/beast/http/impl/write.ipp +++ b/include/boost/beast/http/impl/write.ipp @@ -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>( @@ -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& 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::value, + "WriteHandler type requirements not met"); + + write_some_op< + typename std::decay::type, + Stream, + isRequest, Body, Fields>( + std::forward(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& 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::value, + "WriteHandler type requirements not met"); + + write_op< + typename std::decay::type, + Stream, + Predicate, + isRequest, Body, Fields>( + std::forward(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& 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::value, + "WriteHandler type requirements not met"); + + write_msg_op< + typename std::decay::type, + Stream, + isRequest, Body, Fields>( + std::forward(h), + s, + m, + std::forward(args)...); + } + + template< + class WriteHandler, + class Stream, + bool isRequest, class Body, class Fields, + class... Args> + void + operator()( + WriteHandler&& h, + Stream& s, + message 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::value, + "WriteHandler type requirements not met"); + + write_msg_op< + typename std::decay::type, + Stream, + isRequest, Body, Fields>( + std::forward(h), + s, + m, + std::forward(args)...); + } +}; + //------------------------------------------------------------------------------ template @@ -341,15 +477,13 @@ async_write_some_impl( serializer& 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::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::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::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::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{}); } //------------------------------------------------------------------------------ diff --git a/include/boost/beast/websocket/impl/accept.hpp b/include/boost/beast/websocket/impl/accept.hpp index 88fe2c77..992ee191 100644 --- a/include/boost/beast/websocket/impl/accept.hpp +++ b/include/boost/beast/websocket/impl/accept.hpp @@ -241,7 +241,7 @@ public: // read and respond to an upgrade request // template -template +template class stream::accept_op : public beast::stable_async_op_base< Handler, beast::executor_type> @@ -256,8 +256,8 @@ public: accept_op( Handler_&& h, boost::shared_ptr const& sp, - Buffers const& buffers, - Decorator const& decorator) + Decorator const& decorator, + Buffers const& buffers) : stable_async_op_base>( std::forward(h), @@ -325,6 +325,74 @@ public: } }; +template +struct stream:: + run_response_op +{ + template< + class AcceptHandler, + class Body, class Allocator, + class Decorator> + void + operator()( + AcceptHandler&& h, + boost::shared_ptr const& sp, + http::request> 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::value, + "AcceptHandler type requirements not met"); + + response_op< + typename std::decay::type>( + std::forward(h), + sp, + m, + d); + } +}; + +template +struct stream:: + run_accept_op +{ + template< + class AcceptHandler, + class Decorator, + class Buffers> + void + operator()( + AcceptHandler&& h, + boost::shared_ptr 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::value, + "AcceptHandler type requirements not met"); + + accept_op< + typename std::decay::type, + Decorator>( + std::forward(h), + sp, + d, + b); + } +}; + //------------------------------------------------------------------------------ template @@ -488,17 +556,15 @@ async_accept( { static_assert(is_async_stream::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 @@ -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 @@ -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 @@ -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 @@ -608,15 +670,15 @@ async_accept( { static_assert(is_async_stream::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 @@ -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); } //------------------------------------------------------------------------------ diff --git a/include/boost/beast/websocket/impl/close.hpp b/include/boost/beast/websocket/impl/close.hpp index 884007d7..360e095b 100644 --- a/include/boost/beast/websocket/impl/close.hpp +++ b/include/boost/beast/websocket/impl/close.hpp @@ -230,6 +230,34 @@ public: } }; +template +struct stream:: + run_close_op +{ + template + void + operator()( + CloseHandler&& h, + boost::shared_ptr 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::value, + "CloseHandler type requirements not met"); + + close_op< + typename std::decay::type>( + std::forward(h), + sp, + cr); + } +}; + //------------------------------------------------------------------------------ template @@ -360,12 +388,13 @@ async_close(close_reason const& cr, CloseHandler&& handler) { static_assert(is_async_stream::value, "AsyncStream type requirements not met"); - BOOST_BEAST_HANDLER_INIT( - CloseHandler, void(error_code)); - close_op( - 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 diff --git a/include/boost/beast/websocket/impl/handshake.hpp b/include/boost/beast/websocket/impl/handshake.hpp index a0d294e8..8074f4fb 100644 --- a/include/boost/beast/websocket/impl/handshake.hpp +++ b/include/boost/beast/websocket/impl/handshake.hpp @@ -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 +struct stream:: + run_handshake_op +{ + template + void operator()( + HandshakeHandler&& h, + boost::shared_ptr 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::value, + "HandshakeHandler type requirements not met"); + + handshake_op< + typename std::decay::type>( + std::forward(h), + sp, + r, + host, target, + d); + } +}; + //------------------------------------------------------------------------------ template @@ -241,14 +273,15 @@ async_handshake(string_view host, { static_assert(is_async_stream::value, "AsyncStream type requirements not met"); - BOOST_BEAST_HANDLER_INIT( - HandshakeHandler, void(error_code)); - handshake_op( - 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 @@ -263,14 +296,15 @@ async_handshake(response_type& res, { static_assert(is_async_stream::value, "AsyncStream type requirements not met"); - BOOST_BEAST_HANDLER_INIT( - HandshakeHandler, void(error_code)); - handshake_op( - 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 @@ -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( - 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 @@ -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( - 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 diff --git a/include/boost/beast/websocket/impl/ping.hpp b/include/boost/beast/websocket/impl/ping.hpp index 2e5b7223..6645cfdd 100644 --- a/include/boost/beast/websocket/impl/ping.hpp +++ b/include/boost/beast/websocket/impl/ping.hpp @@ -200,6 +200,36 @@ public: } }; +template +struct stream:: + run_ping_op +{ + template + void + operator()( + WriteHandler&& h, + boost::shared_ptr 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::value, + "WriteHandler type requirements not met"); + + ping_op< + typename std::decay::type>( + std::forward(h), + sp, + op, + p); + } +}; + //------------------------------------------------------------------------------ template @@ -263,13 +293,14 @@ async_ping(ping_data const& payload, WriteHandler&& handler) { static_assert(is_async_stream::value, "AsyncStream type requirements not met"); - BOOST_BEAST_HANDLER_INIT( - WriteHandler, void(error_code)); - ping_op( - 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 @@ -281,13 +312,14 @@ async_pong(ping_data const& payload, WriteHandler&& handler) { static_assert(is_async_stream::value, "AsyncStream type requirements not met"); - BOOST_BEAST_HANDLER_INIT( - WriteHandler, void(error_code)); - ping_op( - 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 diff --git a/include/boost/beast/websocket/impl/read.hpp b/include/boost/beast/websocket/impl/read.hpp index 2f13f221..fdc997ac 100644 --- a/include/boost/beast/websocket/impl/read.hpp +++ b/include/boost/beast/websocket/impl/read.hpp @@ -43,9 +43,7 @@ namespace websocket { Also reads and handles control frames. */ template -template< - class MutableBufferSequence, - class Handler> +template class stream::read_some_op : public beast::async_op_base< Handler, beast::executor_type> @@ -613,9 +611,7 @@ public: //------------------------------------------------------------------------------ template -template< - class DynamicBuffer, - class Handler> +template class stream::read_op : public beast::async_op_base< Handler, beast::executor_type> @@ -674,7 +670,7 @@ public: // VFALCO TODO use boost::beast::bind_continuation BOOST_ASIO_CORO_YIELD - read_some_op( + read_some_op( std::move(*this), sp, *mb); b_.commit(bytes_transferred); bytes_written_ += bytes_transferred; @@ -689,6 +685,72 @@ public: } }; +template +struct stream:: + run_read_some_op +{ + template< + class ReadHandler, + class MutableBufferSequence> + void + operator()( + ReadHandler&& h, + boost::shared_ptr 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::value, + "ReadHandler type requirements not met"); + + read_some_op< + typename std::decay::type, + MutableBufferSequence>( + std::forward(h), + sp, + b); + } +}; + +template +struct stream:: + run_read_op +{ + template< + class ReadHandler, + class DynamicBuffer> + void + operator()( + ReadHandler&& h, + boost::shared_ptr 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::value, + "ReadHandler type requirements not met"); + + read_op< + typename std::decay::type, + DynamicBuffer>( + std::forward(h), + sp, + b, + limit, + some); + } +}; + //------------------------------------------------------------------------------ template @@ -743,13 +805,15 @@ async_read(DynamicBuffer& buffer, ReadHandler&& handler) static_assert( net::is_dynamic_buffer::value, "DynamicBuffer type requirements not met"); - BOOST_BEAST_HANDLER_INIT( - ReadHandler, void(error_code, std::size_t)); - read_op( - 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::value, "DynamicBuffer type requirements not met"); - BOOST_BEAST_HANDLER_INIT( - ReadHandler, void(error_code, std::size_t)); - read_op( - 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( - 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 diff --git a/include/boost/beast/websocket/impl/write.hpp b/include/boost/beast/websocket/impl/write.hpp index 19a65258..44e7b93a 100644 --- a/include/boost/beast/websocket/impl/write.hpp +++ b/include/boost/beast/websocket/impl/write.hpp @@ -37,7 +37,7 @@ namespace beast { namespace websocket { template -template +template class stream::write_some_op : public beast::async_op_base< Handler, beast::executor_type> @@ -430,6 +430,39 @@ operator()( } } +template +struct stream:: + run_write_some_op +{ + template< + class WriteHandler, + class ConstBufferSequence> + void + operator()( + WriteHandler&& h, + boost::shared_ptr 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::value, + "WriteHandler type requirements not met"); + + write_some_op< + typename std::decay::type, + ConstBufferSequence>( + std::forward(h), + sp, + fin, + b); + } +}; + //------------------------------------------------------------------------------ template @@ -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( - 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( - 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 diff --git a/include/boost/beast/websocket/stream.hpp b/include/boost/beast/websocket/stream.hpp index bdcfc29f..25a1c54e 100644 --- a/include/boost/beast/websocket/stream.hpp +++ b/include/boost/beast/websocket/stream.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -127,6 +128,16 @@ class stream : private stream_base #endif { + struct impl_type; + + boost::shared_ptr impl_; + + using time_point = typename + std::chrono::steady_clock::time_point; + + using control_cb_type = + std::function; + 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; - - struct impl_type; - - boost::shared_ptr 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::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; /** Destructor @@ -2636,6 +2638,17 @@ private: template class write_some_op; template 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&) {} diff --git a/test/beast/core/buffered_read_stream.cpp b/test/beast/core/buffered_read_stream.cpp index 13d447a4..c48c8c41 100644 --- a/test/beast/core/buffered_read_stream.cpp +++ b/test/beast/core/buffered_read_stream.cpp @@ -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(); } };