33 Execution control library [exec] (original) (raw)

33.13 Coroutine utilities [exec.coro.util]

33.13.6 execution​::​task [exec.task]


33.13.6.1 task overview [task.overview]

33.13.6.2 Class template task [task.class]

33.13.6.3 task members [task.members]

33.13.6.4 Class template task​::​state [task.state]

33.13.6.5 Class task​::​promise_type [task.promise]


33.13.6.1 task overview [task.overview]

The task class template represents a sender that can be used as the return type of coroutines.

The first template parameter T defines the type of the value completion datum ([exec.async.ops]) if T is not void.

Otherwise, there are no value completion datums.

Inside coroutines returning task<T, E> the operand ofco_return (if any) becomes the argument of set_value.

The second template parameter Environment is used to customize the behavior of task.

33.13.6.2 Class template task [task.class]

namespace std::execution { template<class T, class Environment> class task { template<receiver Rcvr> class state; public: using sender_concept = sender_t;using completion_signatures = see below;using allocator_type = see below;using scheduler_type = see below;using stop_source_type = see below;using stop_token_type = decltype(declval<stop_source_type>().get_token());using error_types = see below;class promise_type; task(task&&) noexcept;~task();template<receiver Rcvr> state<Rcvr> connect(Rcvr&& rcvr);private: coroutine_handle<promise_type> handle; };}

task<T, E> models sender ([exec.snd]) if T is void, a reference type, or a cv-unqualified non-array object type and E is a class type.

Otherwise a program that instantiates the definition of task<T, E>is ill-formed.

The nested types of task template specializations are determined based on the Environment parameter:

A program is ill-formed if error_types is not a specialization of execution​::​completion_signaturesor if the template arguments of that specialization contain an element which is not of the formset_error_t(E) for some type E.

The type alias completion_signatures is a specialization of execution​::​completion_signatures with the template arguments (in unspecified order):

allocator_type shall meet the _Cpp17Allocator_requirements.

33.13.6.3 task members [task.members]

task(task&& other) noexcept;

Effects: Initializes handle with exchange(other.handle,{}).

Effects: Equivalent to:if (handle) handle.destroy();

template<[receiver](exec.recv.concepts#concept:receiver "33.7.1 Receiver concepts [exec.recv.concepts]") Rcvr> _state_<Rcvr> connect(Rcvr&& recv);

Preconditions: bool(handle) is true.

Effects: Equivalent to:return state<Rcvr>(exchange(handle, {}), std::forward<Rcvr>(recv));

33.13.6.4 Class template task​::​state [task.state]

namespace std::execution { template<class T, class Environment> template<receiver Rcvr> class task<T, Environment>::state { public: using operation_state_concept = operation_state_t;template<class R> state(coroutine_handle<promise_type> h, R&& rr);~state();void start() & noexcept;private: using own-env-t = see below; coroutine_handle<promise_type> handle; remove_cvref_t<Rcvr> rcvr; own-env-t own-env; Environment environment; };}

The type own-env-t is Environment​::​templateenv_type<decltype(get_env(​declval​<Rcvr>(​)))​> if thatqualified-id is valid and denotes a type, env<> otherwise.

template<class R> _state_(coroutine_handle<promise_type> h, R&& rr);

Effects: Initializes

Effects: Equivalent to:if (handle) handle.destroy();

Effects: Let prom be the object handle.promise().

Associates STATE(prom), RCVR(prom), and SCHED(prom)with *this as follows:

Let st be get_stop_token(get_env(rcvr)).

Initializes prom.token and_prom_.source such that

After that invokes handle.resume().

33.13.6.5 Class task​::​promise_type [task.promise]

namespace std::execution { template<class T, class Environment> class task<T, Environment>::promise_type { public: template<class... Args> promise_type(const Args&... args); task get_return_object() noexcept;auto initial_suspend() noexcept;auto final_suspend() noexcept;void uncaught_exception(); coroutine_handle<> unhandled_stopped();void return_void(); template<class V> void return_value(V&& value); template<class E> unspecified yield_value(with_error<E> error);template<class A> auto await_transform(A&& a);template<class Sch> auto await_transform(change_coroutine_scheduler<Sch> sch);unspecified get_env() const noexcept;template<class... Args> void* operator new(size_t size, Args&&... args);void operator delete(void* pointer, size_t size) noexcept;private: using error-variant = see below; allocator_type alloc; stop_source_type source; stop_token_type token; optional<T> result; error-variant errors; };}

Let prom be an object of promise_typeand let tsk be the task object created by prom.get_return_object().

The description below refers to objects STATE(prom),RCVR(prom), and SCHED(prom)associated with tsk_during evaluation of task​::​_state<Rcvr>​::​startfor some receiver Rcvr.

error-variant is a variant<monostate, remove_cvref_t<E>...>, with duplicate types removed, where E...are the parameter types of the template arguments of the specialization ofexecution​::​completion_signatures denoted byerror_types.

template<class... Args> promise_type(const Args&... args);

Mandates: The first parameter of type allocator_arg_t (if any) is not the last parameter.

Effects: If Args contains an element of type allocator_arg_tthen alloc is initialized with the corresponding next element of args.

Otherwise, alloc is initialized with allocator_type().

task get_return_object() noexcept;

Returns: A task object whose member handle iscoroutine_handle<promise_type>​::​​from_promise​(*this).

auto initial_suspend() noexcept;

Returns: An awaitable object of unspecified type ([expr.await]) whose member functions arrange for

auto final_suspend() noexcept;

Returns: An awaitable object of unspecified type ([expr.await]) whose member functions arrange for the completion of the asynchronous operation associated with STATE(*this) by invoking:

template<class Err> auto yield_value(with_error<Err> err);

Mandates: std​::​move(err.error) is convertible to exactly one of theset_error_t argument types of error_types.

Let Cerr be that type.

Returns: An awaitable object of unspecified type ([expr.await]) whose member functions arrange for the calling coroutine to be suspended and then completes the asynchronous operation associated with_STATE_(*this) by invoking set_error(std​::​move(RCVR(*this)),Cerr(std​::​move(err.error))).

template<[sender](exec.snd.concepts#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]") Sender> auto await_transform(Sender&& sndr) noexcept;

Returns: If same_as<inline_scheduler, scheduler_type> is truereturns as_awaitable(​std​::​​forward<Sender>(sndr), *this); otherwise returnsas_awaitable(affine_on(​std​::​​forward<Sender>(sndr), SCHED(*this)), *this).

template<class Sch> auto await_transform(change_coroutine_scheduler<Sch> sch) noexcept;

Effects: Equivalent to:return await_transform(just(exchange(SCHED(*this), scheduler_type(sch.scheduler))), *this);

void uncaught_exception();

Effects: If the signature set_error_t(exception_ptr) is not an element of error_types, calls terminate() ([except.terminate]).

Otherwise, stores current_exception() into errors.

coroutine_handle<> unhandled_stopped();

Effects: Completes the asynchronous operation associated with STATE(*this)by invoking set_stopped(std​::​move(RCVR(*this))).

Returns: noop_coroutine().

_unspecified_ get_env() const noexcept;

Returns: An object env such that queries are forwarded as follows:

template<class... Args> void* operator new(size_t size, const Args&... args);

If there is no parameter with type allocator_arg_t then letalloc be allocator_type().

Otherwise, let arg_next be the parameter following the first allocator_arg_t parameter, and let alloc be allocator_type(arg_next).

Let PAlloc be allocator_traits<allocator_type>​::​templaterebind_alloc<U>, where U is an unspecified type whose size and alignment are both __STDCPP_DEFAULT_NEW_ALIGNMENT__.

Mandates:

Effects: Initializes an allocator palloc of type PAlloc withalloc.

Uses palloc to allocate storage for the smallest array of U sufficient to provide storage for a coroutine state of size size, and unspecified additional state necessary to ensure that operator delete can later deallocate this memory block with an allocator equal to palloc.

Returns: A pointer to the allocated storage.

void operator delete(void* pointer, size_t size) noexcept;

Preconditions: pointer was returned from an invocation of the above overload of operator new with a size argument equal to size.

Effects: Deallocates the storage pointed to by pointer using an allocator equal to that used to allocate it.