Replace detail/work_guard.hpp with net::executor_work_guard

In newer versions of Asio, `executor_work_guard<>` can be used even when
`ASIO_NO_TS_EXECUTORS` is defined.
This commit is contained in:
Mohammad Nejati
2025-04-27 10:04:53 +00:00
committed by Mohammad Nejati
parent 78478557f6
commit 19c38c308a
11 changed files with 25 additions and 173 deletions

View File

@@ -19,6 +19,7 @@ def main(ctx):
linux_cxx("GCC Valgrind", "g++", packages="g++-14 libssl-dev valgrind", image="cppalliance/droneubuntu2404:1", buildtype="boost_v1", buildscript="drone", environment={ "VARIANT": "beast_valgrind", "TOOLSET": "gcc", "COMPILER": "g++", "CXXSTD": "11" }, globalenv=globalenv), linux_cxx("GCC Valgrind", "g++", packages="g++-14 libssl-dev valgrind", image="cppalliance/droneubuntu2404:1", buildtype="boost_v1", buildscript="drone", environment={ "VARIANT": "beast_valgrind", "TOOLSET": "gcc", "COMPILER": "g++", "CXXSTD": "11" }, globalenv=globalenv),
linux_cxx("Default g++", "g++", packages="mlocate", image="cppalliance/droneubuntu1604:1", buildtype="boost_v1", buildscript="drone", environment={ "VARIANT": "release", "TOOLSET": "gcc", "COMPILER": "g++", "CXXSTD": "11" }, globalenv=globalenv), linux_cxx("Default g++", "g++", packages="mlocate", image="cppalliance/droneubuntu1604:1", buildtype="boost_v1", buildscript="drone", environment={ "VARIANT": "release", "TOOLSET": "gcc", "COMPILER": "g++", "CXXSTD": "11" }, globalenv=globalenv),
linux_cxx("GCC 8, C++17, libstdc++, release", "g++-8", packages="g++-8 mlocate", image="cppalliance/droneubuntu1604:1", buildtype="boost_v1", buildscript="drone", environment={ "VARIANT": "release", "TOOLSET": "gcc", "COMPILER": "g++-8", "CXXSTD" : "17" }, globalenv=globalenv), linux_cxx("GCC 8, C++17, libstdc++, release", "g++-8", packages="g++-8 mlocate", image="cppalliance/droneubuntu1604:1", buildtype="boost_v1", buildscript="drone", environment={ "VARIANT": "release", "TOOLSET": "gcc", "COMPILER": "g++-8", "CXXSTD" : "17" }, globalenv=globalenv),
linux_cxx("GCC 14, -DBOOST_ASIO_NO_TS_EXECUTORS", "g++-14", packages="g++-14", image="cppalliance/droneubuntu2404:1", buildtype="boost_v1", buildscript="drone", environment={ "VARIANT": "release", "TOOLSET": "gcc", "COMPILER": "g++-14", "CXXSTD" : "20" , "CXX_FLAGS": "<cxxflags>-DBOOST_ASIO_NO_TS_EXECUTORS"}, globalenv=globalenv),
linux_cxx("Clang 18, UBasan", "clang++-18", packages="clang-18 libssl-dev", image="cppalliance/droneubuntu2404:1", buildtype="boost_v1", buildscript="drone", environment={"VARIANT": "beast_ubasan", "TOOLSET": "clang", "COMPILER": "clang++-18", "CXXSTD": "17", "UBSAN_OPTIONS": 'print_stacktrace=1', "DRONE_BEFORE_INSTALL": "UBasan" }, globalenv=globalenv, privileged=True), linux_cxx("Clang 18, UBasan", "clang++-18", packages="clang-18 libssl-dev", image="cppalliance/droneubuntu2404:1", buildtype="boost_v1", buildscript="drone", environment={"VARIANT": "beast_ubasan", "TOOLSET": "clang", "COMPILER": "clang++-18", "CXXSTD": "17", "UBSAN_OPTIONS": 'print_stacktrace=1', "DRONE_BEFORE_INSTALL": "UBasan" }, globalenv=globalenv, privileged=True),
linux_cxx("docs", "", packages="docbook docbook-xml docbook-xsl xsltproc libsaxonhe-java default-jre-headless flex libfl-dev bison unzip rsync mlocate", image="cppalliance/droneubuntu1804:1", buildtype="docs", buildscript="drone", environment={"COMMENT": "docs"}, globalenv=globalenv), linux_cxx("docs", "", packages="docbook docbook-xml docbook-xsl xsltproc libsaxonhe-java default-jre-headless flex libfl-dev bison unzip rsync mlocate", image="cppalliance/droneubuntu1804:1", buildtype="docs", buildscript="drone", environment={"COMMENT": "docs"}, globalenv=globalenv),
linux_cxx("GCC 14, UBasan", "g++-14", packages="g++-14", buildtype="boost", buildscript="drone", image="cppalliance/droneubuntu2404:1", environment={'COMMENT': 'ubsan', 'B2_VARIANT': 'debug', 'B2_TOOLSET': 'gcc-14', 'B2_CXXSTD': '14,17,20,23', 'B2_UBSAN': '1', 'B2_DEFINES': 'BOOST_NO_STRESS_TEST=1', 'B2_LINKFLAGS': '-fuse-ld=gold'}, globalenv=globalenv, privileged=True), linux_cxx("GCC 14, UBasan", "g++-14", packages="g++-14", buildtype="boost", buildscript="drone", image="cppalliance/droneubuntu2404:1", environment={'COMMENT': 'ubsan', 'B2_VARIANT': 'debug', 'B2_TOOLSET': 'gcc-14', 'B2_CXXSTD': '14,17,20,23', 'B2_UBSAN': '1', 'B2_DEFINES': 'BOOST_NO_STRESS_TEST=1', 'B2_LINKFLAGS': '-fuse-ld=gold'}, globalenv=globalenv, privileged=True),

View File

@@ -2,4 +2,4 @@
include(${CMAKE_CURRENT_LIST_DIR}/common.cmake) include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)
# Compiler options. # Compiler options.
add_compile_options(-Wall -Wextra -Wpedantic -Wno-unused-parameter) add_compile_options(-Wall -Wextra -Wpedantic)

View File

@@ -362,8 +362,7 @@ net::awaitable<void, executor_type>
run_websocket_session( run_websocket_session(
Stream& stream, Stream& stream,
beast::flat_buffer& buffer, beast::flat_buffer& buffer,
http::request<http::string_body> req, http::request<http::string_body> req)
beast::string_view doc_root)
{ {
auto cs = co_await net::this_coro::cancellation_state; auto cs = co_await net::this_coro::cancellation_state;
auto ws = websocket::stream<Stream&>{ stream }; auto ws = websocket::stream<Stream&>{ stream };
@@ -438,7 +437,7 @@ run_session(
beast::get_lowest_layer(stream).expires_never(); beast::get_lowest_layer(stream).expires_never();
co_await run_websocket_session( co_await run_websocket_session(
stream, buffer, parser.release(), doc_root); stream, buffer, parser.release());
co_return; co_return;
} }
@@ -581,7 +580,9 @@ handle_signals(task_group& task_group)
} }
else // SIGTERM else // SIGTERM
{ {
executor.get_inner_executor().context().stop(); net::query(
executor.get_inner_executor(),
net::execution::context).stop();
} }
} }

View File

@@ -17,6 +17,7 @@
#include <boost/asio/append.hpp> #include <boost/asio/append.hpp>
#include <boost/asio/associated_cancellation_slot.hpp> #include <boost/asio/associated_cancellation_slot.hpp>
#include <boost/asio/dispatch.hpp> #include <boost/asio/dispatch.hpp>
#include <boost/asio/executor_work_guard.hpp>
#include <boost/asio/post.hpp> #include <boost/asio/post.hpp>
#include <mutex> #include <mutex>
#include <stdexcept> #include <stdexcept>
@@ -57,13 +58,8 @@ class basic_stream<Executor>::read_op : public detail::stream_read_op_base
Handler h_; Handler h_;
boost::weak_ptr<detail::stream_state> wp_; boost::weak_ptr<detail::stream_state> wp_;
Buffers b_; 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< net::executor_work_guard<
net::associated_executor_t<Handler, net::any_io_executor>> wg2_; net::associated_executor_t<Handler, net::any_io_executor>> wg2_;
#endif // defined(BOOST_ASIO_NO_TS_EXECUTORS)
lambda(lambda&&) = default; lambda(lambda&&) = default;
lambda(lambda const&) = default; lambda(lambda const&) = default;
@@ -75,15 +71,7 @@ class basic_stream<Executor>::read_op : public detail::stream_read_op_base
: h_(std::forward<Handler_>(h)) : h_(std::forward<Handler_>(h))
, wp_(s) , wp_(s)
, b_(b) , b_(b)
#if defined(BOOST_ASIO_NO_TS_EXECUTORS) , wg2_(net::get_associated_executor(h_, s->exec))
, wg2_(net::prefer(
net::get_associated_executor(
h_, s->exec),
net::execution::outstanding_work.tracked))
#else // defined(BOOST_ASIO_NO_TS_EXECUTORS)
, wg2_(net::get_associated_executor(
h_, s->exec))
#endif // defined(BOOST_ASIO_NO_TS_EXECUTORS)
{ {
} }
@@ -131,24 +119,14 @@ class basic_stream<Executor>::read_op : public detail::stream_read_op_base
} }
} }
#if defined(BOOST_ASIO_NO_TS_EXECUTORS)
net::dispatch(wg2_,
net::append(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(), net::dispatch(wg2_.get_executor(),
net::append(std::move(h_), ec, bytes_transferred)); net::append(std::move(h_), ec, bytes_transferred));
wg2_.reset(); wg2_.reset();
#endif // defined(BOOST_ASIO_NO_TS_EXECUTORS)
} }
}; };
lambda fn_; lambda fn_;
#if defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
net::executor_work_guard<net::any_io_executor> wg1_; net::executor_work_guard<net::any_io_executor> wg1_;
#else
net::any_io_executor wg1_;
#endif
public: public:
template<class Handler_> template<class Handler_>
@@ -157,25 +135,15 @@ public:
boost::shared_ptr<detail::stream_state> const& s, boost::shared_ptr<detail::stream_state> const& s,
Buffers const& b) Buffers const& b)
: fn_(std::forward<Handler_>(h), s, b) : fn_(std::forward<Handler_>(h), s, b)
#if defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
, wg1_(s->exec) , wg1_(s->exec)
#else
, wg1_(net::prefer(s->exec,
net::execution::outstanding_work.tracked))
#endif
{ {
} }
void void
operator()(error_code ec) override operator()(error_code ec) override
{ {
#if defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
net::post(wg1_.get_executor(), net::append(std::move(fn_), ec)); net::post(wg1_.get_executor(), net::append(std::move(fn_), ec));
wg1_.reset(); wg1_.reset();
#else
net::post(wg1_, net::append(std::move(fn_), ec));
wg1_ = net::any_io_executor(); // probably unnecessary
#endif
} }
}; };

View File

@@ -19,7 +19,6 @@
#include <boost/asio/async_result.hpp> #include <boost/asio/async_result.hpp>
#include <boost/asio/buffer.hpp> #include <boost/asio/buffer.hpp>
#include <boost/asio/error.hpp> #include <boost/asio/error.hpp>
#include <boost/asio/executor_work_guard.hpp>
#include <boost/asio/any_io_executor.hpp> #include <boost/asio/any_io_executor.hpp>
#include <boost/asio/io_context.hpp> #include <boost/asio/io_context.hpp>
#include <boost/assert.hpp> #include <boost/assert.hpp>

View File

@@ -14,7 +14,6 @@
#include <boost/beast/core/detail/allocator.hpp> #include <boost/beast/core/detail/allocator.hpp>
#include <boost/beast/core/detail/async_base.hpp> #include <boost/beast/core/detail/async_base.hpp>
#include <boost/beast/core/detail/filtering_cancellation_slot.hpp> #include <boost/beast/core/detail/filtering_cancellation_slot.hpp>
#include <boost/beast/core/detail/work_guard.hpp>
#include <boost/asio/append.hpp> #include <boost/asio/append.hpp>
#include <boost/asio/associated_allocator.hpp> #include <boost/asio/associated_allocator.hpp>
#include <boost/asio/associated_cancellation_slot.hpp> #include <boost/asio/associated_cancellation_slot.hpp>
@@ -22,6 +21,7 @@
#include <boost/asio/associated_immediate_executor.hpp> #include <boost/asio/associated_immediate_executor.hpp>
#include <boost/asio/bind_executor.hpp> #include <boost/asio/bind_executor.hpp>
#include <boost/asio/dispatch.hpp> #include <boost/asio/dispatch.hpp>
#include <boost/asio/executor_work_guard.hpp>
#include <boost/asio/handler_continuation_hook.hpp> #include <boost/asio/handler_continuation_hook.hpp>
#include <boost/asio/post.hpp> #include <boost/asio/post.hpp>
#include <boost/core/exchange.hpp> #include <boost/core/exchange.hpp>
@@ -186,7 +186,7 @@ class async_base
"Executor type requirements not met"); "Executor type requirements not met");
Handler h_; Handler h_;
detail::select_work_guard_t<Executor1> wg1_; net::executor_work_guard<Executor1> wg1_;
net::cancellation_type act_{net::cancellation_type::terminal}; net::cancellation_type act_{net::cancellation_type::terminal};
public: public:
/** The type of executor associated with this object. /** The type of executor associated with this object.
@@ -202,7 +202,7 @@ public:
typename typename
net::associated_executor< net::associated_executor<
Handler, Handler,
typename detail::select_work_guard_t<Executor1>::executor_type typename net::executor_work_guard<Executor1>::executor_type
>::type; >::type;
#endif #endif
@@ -260,7 +260,7 @@ public:
Handler_&& handler, Handler_&& handler,
Executor1 const& ex1) Executor1 const& ex1)
: h_(std::forward<Handler_>(handler)) : h_(std::forward<Handler_>(handler))
, wg1_(detail::make_work_guard(ex1)) , wg1_(ex1)
{ {
} }
@@ -327,10 +327,10 @@ public:
handler, then the object returned from this function will be used handler, then the object returned from this function will be used
as the associated immediate executor of the derived class. as the associated immediate executor of the derived class.
*/ */
auto net::associated_immediate_executor_t<
Handler,
typename net::executor_work_guard<Executor1>::executor_type>
get_immediate_executor() const noexcept get_immediate_executor() const noexcept
-> decltype(net::get_associated_immediate_executor(
h_, wg1_.get_executor()))
{ {
return net::get_associated_immediate_executor( return net::get_associated_immediate_executor(
h_, wg1_.get_executor()); h_, wg1_.get_executor());

View File

@@ -1,102 +0,0 @@
//
// Copyright (c) 2020 Richard Hodges (hodges.r@gmail.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/beast
//
#ifndef BOOST_BEAST_CORE_DETAIL_WORK_GUARD_HPP
#define BOOST_BEAST_CORE_DETAIL_WORK_GUARD_HPP
#include <boost/asio/executor_work_guard.hpp>
#include <boost/asio/execution.hpp>
#include <boost/optional.hpp>
namespace boost {
namespace beast {
namespace detail {
template<class Executor, class Enable = void>
struct select_work_guard;
template<class Executor>
using select_work_guard_t = typename
select_work_guard<Executor>::type;
#if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
template<class Executor>
struct select_work_guard
<
Executor,
typename std::enable_if
<
net::is_executor<Executor>::value
>::type
>
{
using type = net::executor_work_guard<Executor>;
};
#endif
template<class Executor>
struct execution_work_guard
{
using executor_type = typename std::decay<decltype(
net::prefer(std::declval<Executor const&>(),
net::execution::outstanding_work.tracked))>::type;
execution_work_guard(Executor const& exec)
: ex_(net::prefer(exec, net::execution::outstanding_work.tracked))
{
}
executor_type
get_executor() const noexcept
{
BOOST_ASSERT(ex_.has_value());
return *ex_;
}
void reset() noexcept
{
ex_.reset();
}
private:
boost::optional<executor_type> ex_;
};
template<class Executor>
struct select_work_guard
<
Executor,
typename std::enable_if
<
net::execution::is_executor<Executor>::value
#if defined(BOOST_ASIO_NO_TS_EXECUTORS)
|| net::is_executor<Executor>::value
#else
&& !net::is_executor<Executor>::value
#endif
>::type
>
{
using type = execution_work_guard<Executor>;
};
template<class Executor>
select_work_guard_t<Executor>
make_work_guard(Executor const& exec) noexcept
{
return select_work_guard_t<Executor>(exec);
}
}
}
}
#endif // BOOST_BEAST_CORE_DETAIL_WORK_GUARD_HPP

View File

@@ -66,28 +66,15 @@ class saved_handler::impl final : public base
}; };
ebo_pair v_; ebo_pair v_;
#if defined(BOOST_ASIO_NO_TS_EXECUTORS)
typename std::decay<decltype(net::prefer(std::declval<
net::associated_executor_t<Handler>>(),
net::execution::outstanding_work.tracked))>::type
wg2_;
#else // defined(BOOST_ASIO_NO_TS_EXECUTORS)
net::executor_work_guard< net::executor_work_guard<
net::associated_executor_t<Handler>> wg2_; net::associated_executor_t<Handler>> wg2_;
#endif // defined(BOOST_ASIO_NO_TS_EXECUTORS)
net::cancellation_slot slot_{net::get_associated_cancellation_slot(v_.h)}; net::cancellation_slot slot_{net::get_associated_cancellation_slot(v_.h)};
public: public:
template<class Handler_> template<class Handler_>
impl(alloc_type const& a, Handler_&& h, impl(alloc_type const& a, Handler_&& h,
saved_handler * owner) saved_handler * owner)
: base(owner), v_(a, std::forward<Handler_>(h)) : base(owner), v_(a, std::forward<Handler_>(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)) , wg2_(net::get_associated_executor(v_.h))
#endif // defined(BOOST_ASIO_NO_TS_EXECUTORS)
{ {
} }

View File

@@ -44,7 +44,7 @@ struct ex1_type
{ {
net::execution_context & net::execution_context &
query(net::execution::context_t c) const noexcept query(net::execution::context_t) const noexcept
{ return *reinterpret_cast<net::execution_context *>(&ex1ctx); } { return *reinterpret_cast<net::execution_context *>(&ex1ctx); }
net::execution::blocking_t net::execution::blocking_t
@@ -52,23 +52,23 @@ struct ex1_type
{ return net::execution::blocking; }; { return net::execution::blocking; };
net::execution::outstanding_work_t net::execution::outstanding_work_t
query(net::execution::outstanding_work_t w) const noexcept query(net::execution::outstanding_work_t) const noexcept
{ return net::execution::outstanding_work; } { return net::execution::outstanding_work; }
ex1_type ex1_type
require(net::execution::blocking_t::possibly_t b) const require(net::execution::blocking_t::possibly_t) const
{ return *this; } { return *this; }
ex1_type ex1_type
require(net::execution::blocking_t::never_t b) const require(net::execution::blocking_t::never_t) const
{ return *this; }; { return *this; };
ex1_type ex1_type
prefer(net::execution::outstanding_work_t::untracked_t w) const prefer(net::execution::outstanding_work_t::untracked_t) const
{ return *this; }; { return *this; };
ex1_type ex1_type
prefer(net::execution::outstanding_work_t::tracked_t w) const prefer(net::execution::outstanding_work_t::tracked_t) const
{ return *this; }; { return *this; };
template<class F> template<class F>

View File

@@ -69,6 +69,7 @@ public:
template<class F> template<class F>
void execute(F&&) const {} void execute(F&&) const {}
simple_executor prefer(net::execution::outstanding_work_t::tracked_t) const { return *this; } simple_executor prefer(net::execution::outstanding_work_t::tracked_t) const { return *this; }
simple_executor require(net::execution::blocking_t::never_t) const { return *this; };
#else #else
void* context() { return nullptr; } void* context() { return nullptr; }
void on_work_started() {} void on_work_started() {}

View File

@@ -41,9 +41,7 @@ protected:
net::io_context ioc_; net::io_context ioc_;
private: private:
beast::detail::select_work_guard_t< net::executor_work_guard<net::io_context::executor_type> work_;
net::io_context::executor_type>
work_;
std::vector<std::thread> threads_; std::vector<std::thread> threads_;
std::mutex m_; std::mutex m_;
std::condition_variable cv_; std::condition_variable cv_;
@@ -56,8 +54,7 @@ public:
explicit explicit
enable_yield_to(std::size_t concurrency = 1) enable_yield_to(std::size_t concurrency = 1)
: work_(beast::detail::make_work_guard( : work_(ioc_.get_executor())
ioc_.get_executor()))
{ {
threads_.reserve(concurrency); threads_.reserve(concurrency);
while(concurrency--) while(concurrency--)