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("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 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("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),

View File

@@ -2,4 +2,4 @@
include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)
# 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(
Stream& stream,
beast::flat_buffer& buffer,
http::request<http::string_body> req,
beast::string_view doc_root)
http::request<http::string_body> req)
{
auto cs = co_await net::this_coro::cancellation_state;
auto ws = websocket::stream<Stream&>{ stream };
@@ -438,7 +437,7 @@ run_session(
beast::get_lowest_layer(stream).expires_never();
co_await run_websocket_session(
stream, buffer, parser.release(), doc_root);
stream, buffer, parser.release());
co_return;
}
@@ -581,7 +580,9 @@ handle_signals(task_group& task_group)
}
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/associated_cancellation_slot.hpp>
#include <boost/asio/dispatch.hpp>
#include <boost/asio/executor_work_guard.hpp>
#include <boost/asio/post.hpp>
#include <mutex>
#include <stdexcept>
@@ -57,13 +58,8 @@ class basic_stream<Executor>::read_op : public detail::stream_read_op_base
Handler h_;
boost::weak_ptr<detail::stream_state> 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<
net::associated_executor_t<Handler, net::any_io_executor>> wg2_;
#endif // defined(BOOST_ASIO_NO_TS_EXECUTORS)
lambda(lambda&&) = 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))
, wp_(s)
, b_(b)
#if defined(BOOST_ASIO_NO_TS_EXECUTORS)
, 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)
, wg2_(net::get_associated_executor(h_, s->exec))
{
}
@@ -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::append(std::move(h_), ec, bytes_transferred));
wg2_.reset();
#endif // defined(BOOST_ASIO_NO_TS_EXECUTORS)
}
};
lambda fn_;
#if defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
net::executor_work_guard<net::any_io_executor> wg1_;
#else
net::any_io_executor wg1_;
#endif
public:
template<class Handler_>
@@ -157,25 +135,15 @@ public:
boost::shared_ptr<detail::stream_state> const& s,
Buffers const& b)
: fn_(std::forward<Handler_>(h), s, b)
#if defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
, wg1_(s->exec)
#else
, wg1_(net::prefer(s->exec,
net::execution::outstanding_work.tracked))
#endif
{
}
void
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));
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/buffer.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/executor_work_guard.hpp>
#include <boost/asio/any_io_executor.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/assert.hpp>

View File

@@ -14,7 +14,6 @@
#include <boost/beast/core/detail/allocator.hpp>
#include <boost/beast/core/detail/async_base.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/associated_allocator.hpp>
#include <boost/asio/associated_cancellation_slot.hpp>
@@ -22,6 +21,7 @@
#include <boost/asio/associated_immediate_executor.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/dispatch.hpp>
#include <boost/asio/executor_work_guard.hpp>
#include <boost/asio/handler_continuation_hook.hpp>
#include <boost/asio/post.hpp>
#include <boost/core/exchange.hpp>
@@ -186,7 +186,7 @@ class async_base
"Executor type requirements not met");
Handler h_;
detail::select_work_guard_t<Executor1> wg1_;
net::executor_work_guard<Executor1> wg1_;
net::cancellation_type act_{net::cancellation_type::terminal};
public:
/** The type of executor associated with this object.
@@ -202,7 +202,7 @@ public:
typename
net::associated_executor<
Handler,
typename detail::select_work_guard_t<Executor1>::executor_type
typename net::executor_work_guard<Executor1>::executor_type
>::type;
#endif
@@ -260,7 +260,7 @@ public:
Handler_&& handler,
Executor1 const& ex1)
: 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
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
-> decltype(net::get_associated_immediate_executor(
h_, wg1_.get_executor()))
{
return net::get_associated_immediate_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_;
#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::associated_executor_t<Handler>> wg2_;
#endif // defined(BOOST_ASIO_NO_TS_EXECUTORS)
net::cancellation_slot slot_{net::get_associated_cancellation_slot(v_.h)};
public:
template<class Handler_>
impl(alloc_type const& a, Handler_&& h,
saved_handler * owner)
: 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))
#endif // defined(BOOST_ASIO_NO_TS_EXECUTORS)
{
}

View File

@@ -44,7 +44,7 @@ struct ex1_type
{
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); }
net::execution::blocking_t
@@ -52,23 +52,23 @@ struct ex1_type
{ return net::execution::blocking; };
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; }
ex1_type
require(net::execution::blocking_t::possibly_t b) const
require(net::execution::blocking_t::possibly_t) const
{ return *this; }
ex1_type
require(net::execution::blocking_t::never_t b) const
require(net::execution::blocking_t::never_t) const
{ return *this; };
ex1_type
prefer(net::execution::outstanding_work_t::untracked_t w) const
prefer(net::execution::outstanding_work_t::untracked_t) const
{ return *this; };
ex1_type
prefer(net::execution::outstanding_work_t::tracked_t w) const
prefer(net::execution::outstanding_work_t::tracked_t) const
{ return *this; };
template<class F>

View File

@@ -69,6 +69,7 @@ public:
template<class F>
void execute(F&&) const {}
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
void* context() { return nullptr; }
void on_work_started() {}

View File

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