Boost
C++ Libraries
...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Submits a function to be run on a specified target executor, and passes the result to a completion handler.
template< typename Function, typename Executor, typename CompletionToken = default_completion_token_t<Executor>> auto dispatch( Function && function, const Executor & ex, CompletionToken && token = default_completion_token_t< Executor >(), constraint_t< !is_void< result_of_t< decay_t< Function >()> >::value > = 0, constraint_t<(execution::is_executor< Executor >::value &&can_require< Executor, execution::blocking_t::never_t >::value)||is_executor< Executor >::value > = 0);
This function submits a function object for execution using the specified
executor. The function object may be called from the current thread prior
to returning from dispatch(). Otherwise, it is queued for execution.
After the submitted function completes, the completion handler is dispatched
along with the function's result, to run on its associated executor.
A nullary function to be executed on the target executor.
The target executor.
The completion token that will be used to produce a completion handler. The function signature of the completion handler must be:
void handler(decay_t<result_of_t<decay_t<Function>()>>);
This function returns async_initiate<CompletionToken, void()>(Init{ex}, token),
where Init is a function
object type defined as:
class Init { public: using executor_type = Executor; explicit Init(const Executor& ex) : ex_(ex) {} executor_type get_executor() const noexcept { return ex_; } template <typename CompletionHandler> void operator()(CompletionHandler&& completion_handler, Function&& function) const; private: Executor ex_; // exposition only };
The function call operator of Init:
Obtains the handler's associated executor object ex1
of type Ex1 by performing
auto ex1 = get_associated_executor(completion_handler, ex);
Obtains the handler's associated allocator object alloc
by performing
auto alloc = get_associated_allocator(completion_handler);
If execution::is_executor<Ex1>::value is true, constructs a function
object wrapper f with
a member executor_
that is initialised with prefer(ex1, execution::outstanding_work.tracked), a member function_
that is a decay-copy of function,
a member handler_ that
is a decay-copy of completion_handler,
and a function call operator that performs:
auto result = std::move(function_)(); auto a = get_associated_allocator(handler_); prefer(executor_, execution::allocator(a)).execute( std::bind(std::move(handler_), std::move(result)));
If execution::is_executor<Ex1>::value is false, constructs a function
object wrapper f with
a member work_ that
is initialised with make_work_guard(ex1), a member function_
that is a decay-copy of function,
a member handler_ that
is a decay-copy of completion_handler,
and a function call operator that performs:
auto result = std::move(function_)(); auto a = get_associated_allocator(handler_); work_.get_executor().dispatch( std::bind(std::move(handler_), std::move(result)), a); work_.reset();
If execution::is_executor<Executor>::value is true, performs
prefer( require(ex, execution::blocking.never), execution::relationship.fork, execution::allocator(alloc) ).execute(std::move(f));
If execution::is_executor<Executor>::value is false, performs
ex.dispatch(std::move(f), alloc);
If the function object throws an exception, that exception is allowed to
propagate to the target executor. The behaviour in this case is dependent
on the executor. For example, io_context will allow the exception
to propagate to the caller that runs the io_context,
whereas thread_pool will call std::terminate.
void(decay_t<result_of_t<decay_t<Function>()>>)