diff --git a/include/boost/beast/_experimental/test/impl/stream.hpp b/include/boost/beast/_experimental/test/impl/stream.hpp index 3d58fdb0..f7eac6af 100644 --- a/include/boost/beast/_experimental/test/impl/stream.hpp +++ b/include/boost/beast/_experimental/test/impl/stream.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -74,7 +75,11 @@ class stream::read_op : public stream::read_op_base Handler h_; boost::weak_ptr wp_; Buffers b_; +#if defined(BOOST_ASIO_NO_TS_EXECUTORS) + net::any_io_executor wg2_; +#else // defined(BOOST_ASIO_NO_TS_EXECUTORS) net::executor_work_guard wg2_; +#endif // defined(BOOST_ASIO_NO_TS_EXECUTORS) lambda(lambda&&) = default; lambda(lambda const&) = default; @@ -87,8 +92,15 @@ class stream::read_op : public stream::read_op_base : h_(std::forward(h)) , wp_(s) , b_(b) +#if defined(BOOST_ASIO_NO_TS_EXECUTORS) + , wg2_(net::prefer( + net::get_associated_executor( + h_, s->ioc.get_executor()), + net::execution::outstanding_work.tracked)) +#else // defined(BOOST_ASIO_NO_TS_EXECUTORS) , wg2_(net::get_associated_executor( h_, s->ioc.get_executor())) +#endif // defined(BOOST_ASIO_NO_TS_EXECUTORS) { } @@ -124,15 +136,26 @@ class stream::read_op : public stream::read_op_base } } +#if defined(BOOST_ASIO_NO_TS_EXECUTORS) + net::dispatch(wg2_, + beast::bind_front_handler(std::move(h_), + ec, bytes_transferred)); + wg2_ = net::any_io_executor(); // probably unnecessary +#else // defined(BOOST_ASIO_NO_TS_EXECUTORS) net::dispatch(wg2_.get_executor(), beast::bind_front_handler(std::move(h_), ec, bytes_transferred)); wg2_.reset(); +#endif // defined(BOOST_ASIO_NO_TS_EXECUTORS) } }; lambda fn_; +#if defined(BOOST_ASIO_NO_TS_EXECUTORS) + net::any_io_executor wg1_; +#else // defined(BOOST_ASIO_NO_TS_EXECUTORS) net::executor_work_guard wg1_; +#endif // defined(BOOST_ASIO_NO_TS_EXECUTORS) public: template @@ -141,16 +164,26 @@ public: boost::shared_ptr const& s, Buffers const& b) : fn_(std::forward(h), s, b) +#if defined(BOOST_ASIO_NO_TS_EXECUTORS) + , wg1_(net::prefer(s->ioc.get_executor(), + net::execution::outstanding_work.tracked)) +#else // defined(BOOST_ASIO_NO_TS_EXECUTORS) , wg1_(s->ioc.get_executor()) +#endif // defined(BOOST_ASIO_NO_TS_EXECUTORS) { } void operator()(error_code ec) override { +#if defined(BOOST_ASIO_NO_TS_EXECUTORS) + net::post(wg1_, beast::bind_front_handler(std::move(fn_), ec)); + wg1_ = net::any_io_executor(); // probably unnecessary +#else // defined(BOOST_ASIO_NO_TS_EXECUTORS) net::post(wg1_.get_executor(), beast::bind_front_handler(std::move(fn_), ec)); wg1_.reset(); +#endif // defined(BOOST_ASIO_NO_TS_EXECUTORS) } }; diff --git a/include/boost/beast/_experimental/test/impl/stream.ipp b/include/boost/beast/_experimental/test/impl/stream.ipp index 1570ccaa..ec544ce1 100644 --- a/include/boost/beast/_experimental/test/impl/stream.ipp +++ b/include/boost/beast/_experimental/test/impl/stream.ipp @@ -359,7 +359,11 @@ teardown( stream connect(stream& to) { +#if defined(BOOST_ASIO_NO_TS_EXECUTORS) + stream from{net::query(to.get_executor(), net::execution::context)}; +#else // defined(BOOST_ASIO_NO_TS_EXECUTORS) stream from{to.get_executor().context()}; +#endif // defined(BOOST_ASIO_NO_TS_EXECUTORS) from.connect(to); return from; } diff --git a/include/boost/beast/core/impl/saved_handler.hpp b/include/boost/beast/core/impl/saved_handler.hpp index a2642f59..210befae 100644 --- a/include/boost/beast/core/impl/saved_handler.hpp +++ b/include/boost/beast/core/impl/saved_handler.hpp @@ -63,14 +63,26 @@ class saved_handler::impl final : public base }; ebo_pair v_; +#if defined(BOOST_ASIO_NO_TS_EXECUTORS) + std::decay_t>(), + net::execution::outstanding_work.tracked))> wg2_; +#else // defined(BOOST_ASIO_NO_TS_EXECUTORS) net::executor_work_guard< net::associated_executor_t> wg2_; +#endif // defined(BOOST_ASIO_NO_TS_EXECUTORS) public: template impl(alloc_type const& a, Handler_&& h) : v_(a, std::forward(h)) +#if defined(BOOST_ASIO_NO_TS_EXECUTORS) + , wg2_(net::prefer( + net::get_associated_executor(v_.h), + net::execution::outstanding_work.tracked)) +#else // defined(BOOST_ASIO_NO_TS_EXECUTORS) , wg2_(net::get_associated_executor(v_.h)) +#endif // defined(BOOST_ASIO_NO_TS_EXECUTORS) { } diff --git a/test/beast/core/bind_handler.cpp b/test/beast/core/bind_handler.cpp index a4ac8f1c..20830deb 100644 --- a/test/beast/core/bind_handler.cpp +++ b/test/beast/core/bind_handler.cpp @@ -80,7 +80,18 @@ public: class test_executor { bind_handler_test& s_; - net::io_context::executor_type ex_; + net::any_io_executor ex_; + + // Storing the blocking property as a member is not strictly necessary, + // as we could simply forward the calls + // require(ex_, blocking.possibly) + // and + // require(ex_, blocking.never) + // to the underlying executor, and then + // query(ex_, blocking) + // when required. This forwarding approach is used here for the + // outstanding_work property. + net::execution::blocking_t blocking_; public: test_executor( @@ -91,6 +102,7 @@ public: net::io_context& ioc) : s_(s) , ex_(ioc.get_executor()) + , blocking_(net::execution::blocking.possibly) { } @@ -106,7 +118,67 @@ public: return ex_ != other.ex_; } - net::io_context& + net::execution_context& query(net::execution::context_t c) const noexcept + { + return net::query(ex_, c); + } + + net::execution::blocking_t query(net::execution::blocking_t) const noexcept + { + return blocking_; + } + + net::execution::outstanding_work_t query(net::execution::outstanding_work_t w) const noexcept + { + return net::query(ex_, w); + } + + test_executor require(net::execution::blocking_t::possibly_t b) const + { + test_executor new_ex(*this); + new_ex.blocking_ = b; + return new_ex; + } + + test_executor require(net::execution::blocking_t::never_t b) const + { + test_executor new_ex(*this); + new_ex.blocking_ = b; + return new_ex; + } + + test_executor prefer(net::execution::outstanding_work_t::untracked_t w) const + { + test_executor new_ex(*this); + new_ex.ex_ = net::prefer(ex_, w); + return new_ex; + } + + test_executor prefer(net::execution::outstanding_work_t::tracked_t w) const + { + test_executor new_ex(*this); + new_ex.ex_ = net::prefer(ex_, w); + return new_ex; + } + + template + void execute(F&& f) const + { + if (blocking_ == net::execution::blocking.possibly) + { + s_.on_invoke(); + net::execution::execute(ex_, std::forward(f)); + } + else + { + // shouldn't be called since the enclosing + // networking wrapper only uses dispatch + BEAST_FAIL(); + } + } + +#if !defined(BOOST_ASIO_NO_TS_EXECUTORS) + net::execution_context& context() const noexcept { return ex_.context(); @@ -144,6 +216,7 @@ public: // networking wrapper only uses dispatch BEAST_FAIL(); } +#endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS) }; class test_cb