Boost.Asio 提供了提議的標準執行器的完整實作,如 P0443r13、P1348r0 和 P1393r0 中所述。
就像網路 TS 模型下的執行器一樣,標準執行器代表了關於程式碼片段應如何、何時以及何處執行的策略。大多數現有程式碼應繼續運作,且幾乎不需要任何變更。
io_context::executor_type
、thread_pool::executor_type
、system_executor
和 strand
執行器符合提議的標準執行器的要求。為了相容性,這些類別也符合網路 TS 執行器模型的要求。
所有 I/O 物件,例如 ip::tcp::socket
、非同步操作和公用程式,包括 dispatch
、post
、defer
、get_associated_executor
、bind_executor
、make_work_guard
、spawn
、co_spawn
、async_compose
、use_future
等等,可以與提議的標準執行器和網路 TS 執行器互通。Boost.Asio 的實作在編譯時決定特定執行器符合哪個模型;如果同時偵測到兩者,則優先使用提議的標準執行器模型。
可以透過定義 BOOST_ASIO_NO_TS_EXECUTORS
來停用對現有網路 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
包含目錄下找到。