// // detail/work_dispatcher.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2025 Christopher M. Kohlhoff (chris at kohlhoff dot 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) // #ifndef ASIO_DETAIL_WORK_DISPATCHER_HPP #define ASIO_DETAIL_WORK_DISPATCHER_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" #include "asio/detail/bind_handler.hpp" #include "asio/detail/type_traits.hpp" #include "asio/associated_executor.hpp" #include "asio/associated_allocator.hpp" #include "asio/executor_work_guard.hpp" #include "asio/execution/executor.hpp" #include "asio/execution/allocator.hpp" #include "asio/execution/blocking.hpp" #include "asio/execution/outstanding_work.hpp" #include "asio/prefer.hpp" #include "asio/detail/push_options.hpp" namespace asio { namespace detail { struct empty_work_function { void operator()() const noexcept { } }; template struct work_result { typedef decay_t()>> type; }; template using work_result_t = typename work_result::type; template struct is_work_dispatcher_required : true_type { }; template struct is_work_dispatcher_required::asio_associated_executor_is_unspecialised, void >::value >> : false_type { }; template >::value, bool IsClass = is_class::value> class work_dispatcher_function { Function function_; public: template work_dispatcher_function(F&& function) : function_(static_cast(function)) { } work_dispatcher_function(const work_dispatcher_function& other) : function_(other.function_) { } work_dispatcher_function(work_dispatcher_function&& other) : function_(static_cast(other.function_)) { } template auto bind_result(Handler&& handler) -> decltype( asio::detail::move_bind_handler( static_cast(handler), static_cast(function_)())) { return asio::detail::move_bind_handler( static_cast(handler), static_cast(function_)()); } }; template class work_dispatcher_function : Function { public: template work_dispatcher_function(F&& function) : Function(static_cast(function)) { } work_dispatcher_function(const work_dispatcher_function& other) : Function(static_cast(other)) { } work_dispatcher_function(work_dispatcher_function&& other) : Function(static_cast(other)) { } template auto bind_result(Handler&& handler) -> decltype( asio::detail::move_bind_handler( static_cast(handler), static_cast(*static_cast(this))())) { return asio::detail::move_bind_handler( static_cast(handler), static_cast(*static_cast(this))()); } }; template class work_dispatcher_function { Function function_; public: template work_dispatcher_function(F&& function) : function_(static_cast(function)) { } work_dispatcher_function(const work_dispatcher_function& other) : function_(other.function_) { } work_dispatcher_function(work_dispatcher_function&& other) : function_(static_cast(other.function_)) { } template auto bind_result(Handler&& handler) -> decltype(asio::detail::bind_handler( static_cast(handler))) { static_cast(function_)(); return asio::detail::bind_handler( static_cast(handler)); } }; template class work_dispatcher_function : Function { public: template work_dispatcher_function(F&& function) : Function(static_cast(function)) { } work_dispatcher_function(const work_dispatcher_function& other) : Function(static_cast(other)) { } work_dispatcher_function(work_dispatcher_function&& other) : Function(static_cast(other)) { } template auto bind_result(Handler&& handler) -> decltype(asio::detail::bind_handler( static_cast(handler))) { static_cast(*static_cast(this))(); return asio::detail::bind_handler( static_cast(handler)); } }; template class work_dispatcher : work_dispatcher_function { public: template work_dispatcher(F&& function, CompletionHandler&& handler, const Executor& handler_ex) : work_dispatcher_function(static_cast(function)), handler_(static_cast(handler)), executor_(asio::prefer(handler_ex, execution::outstanding_work.tracked)) { } work_dispatcher(const work_dispatcher& other) : work_dispatcher_function(other), handler_(other.handler_), executor_(other.executor_) { } work_dispatcher(work_dispatcher&& other) : work_dispatcher_function( static_cast&&>(other)), handler_(static_cast(other.handler_)), executor_(static_cast(other.executor_)) { } void operator()() { associated_allocator_t alloc((get_associated_allocator)(handler_)); asio::prefer(executor_, execution::allocator(alloc)).execute( this->bind_result(static_cast(handler_))); } private: typedef decay_t< prefer_result_t > work_executor_type; Handler handler_; work_executor_type executor_; }; #if !defined(ASIO_NO_TS_EXECUTORS) template class work_dispatcher::value>> : work_dispatcher_function { public: template work_dispatcher(F&& function, CompletionHandler&& handler, const Executor& handler_ex) : work_dispatcher_function(static_cast(function)), work_(handler_ex), handler_(static_cast(handler)) { } work_dispatcher(const work_dispatcher& other) : work_dispatcher_function(other), work_(other.work_), handler_(other.handler_) { } work_dispatcher(work_dispatcher&& other) : work_dispatcher_function( static_cast&&>(*this)), work_(static_cast&&>(other.work_)), handler_(static_cast(other.handler_)) { } void operator()() { associated_allocator_t alloc((get_associated_allocator)(handler_)); work_.get_executor().dispatch( this->bind_result(static_cast(handler_)), alloc); work_.reset(); } private: executor_work_guard work_; Handler handler_; }; #endif // !defined(ASIO_NO_TS_EXECUTORS) } // namespace detail } // namespace asio #include "asio/detail/pop_options.hpp" #endif // ASIO_DETAIL_WORK_DISPATCHER_HPP