Boost.Asio 提供了对提议的标准执行器的完整实现,如 P0443r13、P1348r0 和 P1393r0 中所述。
正如 Networking TS 模型下的执行器一样,标准执行器表示关于代码应如何、何时以及何地执行的策略。大多数现有代码应继续工作,只需进行少量或无需更改。
io_context::executor_type
、thread_pool::executor_type
、system_executor
和 strand
执行器满足提议的标准执行器的要求。为了兼容性,这些类也满足 Networking TS 执行器模型的要求。
所有 I/O 对象,如 ip::tcp::socket
、异步操作和实用程序,包括 dispatch
、post
、defer
、get_associated_executor
、bind_executor
、make_work_guard
、spawn
、co_spawn
、async_compose
、use_future
等,可以与提议的标准执行器和 Networking TS 执行器互操作。Boost.Asio 的实现会在编译时确定特定执行器满足哪个模型;如果检测到两者,则优先使用提议的标准执行器模型。
可以通过定义 BOOST_ASIO_NO_TS_EXECUTORS
来禁用对现有 Networking TS 执行器模型的支持。
any_io_executor
类型别名是所有 I/O 对象的默认运行时多态执行器。此类型别名指向 execution::any_executor<>
模板,该模板具有一组为与 I/O 一起使用而指定的可支持属性。
这个新名称可能会破坏直接使用旧多态包装器 executor
的现有代码。如果需要向后兼容,可以定义 BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT
,这将更改 any_io_executor
类型别名,使其改为指向 executor
多态包装器。
标准执行器属性将以前对执行器的硬性要求(例如工作计数或区分 post
、dispatch
和 defer
的能力)变为可选功能。在这种放宽条件下,I/O 执行器的最低要求是
executor
概念。execution::context
属性的能力,结果是 execution_context&
或对派生自 execution_context
的类的引用。execute
操作至少具有 execution::blocking.never
语义。以下示例展示了一个最小的 I/O 执行器。假设在其他地方实现了队列提交操作
queue_t queue_create(); template <typename F> void queue_submit(queue_t q, F f);
执行器可以定义如下
struct minimal_io_executor { boost::asio::execution_context* context_; queue_t queue_; bool operator==(const minimal_io_executor& other) const noexcept { return context_ == other.context_ && queue_ == other.queue_; } bool operator!=(const minimal_io_executor& other) const noexcept { return !(*this == other); } boost::asio::execution_context& query( boost::asio::execution::context_t) const noexcept { return *context_; } static constexpr boost::asio::execution::blocking_t::never_t query( boost::asio::execution::blocking_t) noexcept { // This executor always has blocking.never semantics. return boost::asio::execution::blocking.never; } template <class F> void execute(F f) const { queue_submit(queue_, std::move(f)); } };
可以按如下方式创建此执行器
boost::asio::execution_context context; queue_t queue = queue_create(); minimal_io_executor executor{&context, queue};
然后与 I/O 对象一起使用
boost::asio::ip::tcp::acceptor acceptor(executor);
或分配到 any_io_executor
多态包装器中
boost::asio::any_io_executor poly_executor = executor;
较旧的 C++ 标准和编译器需要一些帮助来确定执行器实现是否符合 executor
概念和类型要求。这通过特征的特化来实现。以下代码显示了上面 minimal_io_executor
示例的这些特征的特化
namespace boost { namespace asio { namespace traits { #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) template <typename F> struct execute_member<minimal_io_executor, F> { static constexpr bool is_valid = true; static constexpr bool is_noexcept = true; typedef void result_type; }; #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) template <> struct equality_comparable<minimal_io_executor> { static constexpr bool is_valid = true; static constexpr bool is_noexcept = true; }; #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) template <> struct query_member<minimal_io_executor, boost::asio::execution::context_t> { static constexpr bool is_valid = true; static constexpr bool is_noexcept = true; typedef boost::asio::execution_context& result_type; }; #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) template <typename Property> struct query_static_constexpr_member<minimal_io_executor, Property, typename enable_if< std::is_convertible<Property, boost::asio::execution::blocking_t>::value >::type> { static constexpr bool is_valid = true; static constexpr bool is_noexcept = true; typedef boost::asio::execution::blocking_t::never_t result_type; static constexpr result_type value() noexcept { return result_type(); } }; #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) } // namespace traits } } // namespace boost::asio
Boost.Asio 使用广泛的特征集在较旧的 C++ 标准上实现所有提议的标准执行器功能。这些特征可以在 boost/asio/traits
include 目录中找到。