Submits a completion token or function object for execution.
template< typename Executor, typename NullaryToken = DEFAULT> DEDUCED defer( const Executor & ex, NullaryToken && token = DEFAULT, typename constraint< execution::is_executor< Executor >::value||is_executor< Executor >::value >::type = 0);
This function submits an object for execution using the specified executor.
The function object is queued for execution, and is never called from the
current thread prior to returning from defer()
.
The use of defer()
,
rather than post
,
indicates the caller's preference that the executor defer the queueing
of the function object. This may allow the executor to optimise queueing
for cases when the function object represents a continuation of the current
call context.
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();
This function returns async_initiate<NullaryToken, 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) 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(handler, ex);
Obtains the handler's associated allocator object alloc
by performing
auto alloc = get_associated_allocator(handler);
If execution::is_executor<Ex1>::value
is true, constructs a function
object f
with a member
executor_
that is initialised
with prefer(ex1, execution::outstanding_work.tracked)
,
a member handler_
that
is a decay-copy of completion_handler
,
and a function call operator that performs:
auto a = get_associated_allocator(handler_); execution::execute( prefer(executor_, execution::blocking.possibly, execution::allocator(a)), std::move(handler_));
If execution::is_executor<Ex1>::value
is false, constructs a function
object f
with a member
work_
that is initialised
with make_work_guard(ex1)
, a member handler_
that is a decay-copy of completion_handler
,
and a function call operator that performs:
auto a = get_associated_allocator(handler_); work_.get_executor().dispatch(std::move(handler_), a); work_.reset();
If execution::is_executor<Ex>::value
is true, performs
execution::execute( prefer( require(ex, execution::blocking.never), execution::relationship.continuation, execution::allocator(alloc)), std::move(f));
If execution::is_executor<Ex>::value
is false, performs
ex.defer(std::move(f), alloc);
void()