Files
cppdraft_translate/cppdraft/exec/task.md
2025-10-25 03:02:53 +03:00

22 KiB
Raw Blame History

[exec.task]

33 Execution control library [exec]

33.13 Coroutine utilities [exec.coro.util]

33.13.6 execution::task [exec.task]

33.13.6.1 task overview [task.overview]

1

#

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 {// [task.state]template<receiver Rcvr>class state; // exposition onlypublic: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; // [task.promise]class promise_type;

task(task&&) noexcept; ~task(); template<receiver Rcvr>state connect(Rcvr&& rcvr); private: coroutine_handle<promise_type> handle; // exposition only};}

1

#

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.

2

#

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

  • (2.1)

    allocator_type is Environment::allocator_type if that qualified-id is valid and denotes a type,allocator otherwise.

  • (2.2)

    scheduler_type is Environment::scheduler_type if that qualified-id is valid and denotes a type,task_scheduler otherwise.

  • (2.3)

    stop_source_type is Environment::stop_source_type if that qualified-id is valid and denotes a type,inplace_stop_source otherwise.

  • (2.4)

    error_types is Environment::error_types if that qualified-id is valid and denotes a type,completion_signatures<set_error_t(exception_ptr)> otherwise.

3

#

A program is ill-formed if error_types is not a specialization of completion_signatures<ErrorSigs...> orErrorSigs contains an element which is not of the formset_error_t(E) for some type E.

4

#

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

set_value_t() if T is void, and set_value_t(T) otherwise;

template arguments of the specialization ofexecution::completion_signatures denoted by error_types; and

set_stopped_t().

5

#

allocator_type shall meet the Cpp17Allocator requirements.

33.13.6.3 task members [task.members]

🔗

task(task&& other) noexcept;

1

#

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

🔗

~task();

2

#

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

🔗

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

3

#

Preconditions: bool(handle) is true.

4

#

Effects: Equivalent to:return state(exchange(handle, {}), std::forward(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 { // exposition onlypublic:using operation_state_concept = operation_state_t; templatestate(coroutine_handle<promise_type> h, R&& rr); ~state(); void start() & noexcept; private:using own-env-t = see below; // exposition only coroutine_handle<promise_type> handle; // exposition only remove_cvref_t rcvr; // exposition only**own-env-t own-env; // exposition only Environment environment; // exposition only};}

1

#

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

🔗

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

2

#

Effects: Initializes

  • (2.1)

    handle with std::move(h);

  • (2.2)

    rcvr with std::forward(rr);

  • (2.3)

    own-env with own-env-t(get_env(rcvr)) if that expression is valid and own-env-t() otherwise. If neither of these expressions is valid, the program is ill-formed.

  • (2.4)

    environment withEnvironment(own-env) if that expression is valid, otherwise Environment(get_env(rcvr)) if this expression is valid, otherwise Environment(). If neither of these expressions is valid, the program is ill-formed.

🔗

~state();

3

#

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

🔗

void start() & noexcept;

4

#

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

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

  • (4.1)

    STATE(prom) is *this.

  • (4.2)

    RCVR(prom) is rcvr.

  • (4.3)

    SCHED(prom) is the object initialized with scheduler_type(get_scheduler(get_env(rcvr))) if that expression is valid and scheduler_type() otherwise. If neither of these expressions is valid, the program is ill-formed.

Let st be get_stop_token(get_env(rcvr)).

Initializes prom.token andprom.source such that

prom.token.stop_requested() returnsst.stop_requested();

prom.token.stop_possible() returnsst.stop_possible(); and

for types Fn and Init such that bothinvocable andconstructible_from<Fn, Init> are modeled,stop_token_type::callback_type modelsstoppable-callback-for<Fn, stop_token_type, Init>.

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(); // present only if is_void_v is truetemplatevoid return_value(V&& value); // present only if is_void_v is falsetemplateunspecified yield_value(with_error error); templateauto await_transform(A&& a); templateauto await_transform(change_coroutine_scheduler 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; // exposition only allocator_type alloc; // exposition only stop_source_type source; // exposition only stop_token_type token; // exposition only optional result; // exposition only; present only if is_void_v is falseerror-variant errors; // exposition only};}

1

#

Let prom be an object of promise_type and 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::start for some receiver Rcvr.

2

#

error-variant is a variant<monostate, remove_cvref_t...>, 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);

3

#

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

4

#

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

Otherwise, alloc is initialized with allocator_type().

🔗

task get_return_object() noexcept;

5

#

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

🔗

auto initial_suspend() noexcept;

6

#

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

the calling coroutine to be suspended,

the coroutine to be resumed on an execution agent of the execution resource associated with SCHED(*this).

🔗

auto final_suspend() noexcept;

7

#

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:

set_error(std::move(RCVR(*this)), std::move(e)) if errors.index() is greater than zero ande is the value held by errors, otherwise

set_value(std::move(RCVR(*this))) if is_void is true, and otherwise

set_value(std::move(RCVR(*this)), *result).

🔗

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

8

#

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

Let Cerr be that type.

9

#

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 withSTATE(*this) by invoking set_error(std::move(RCVR(*this)),Cerr(std::move(err.error))).

🔗

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

10

#

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

🔗

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

11

#

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

🔗

void uncaught_exception();

12

#

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();

13

#

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

14

#

Returns: noop_coroutine().

🔗

unspecified get_env() const noexcept;

15

#

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

  • (15.1)

    env.query(get_scheduler) returns scheduler_type(SCHED(*this)).

  • (15.2)

    env.query(get_allocator) returns alloc.

  • (15.3)

    env.query(get_stop_token) returns token.

  • (15.4)

    For any other query q and arguments a... a call to env.query(q, a...) returnsSTATE(*this). environment.query(q, a...) if this expression is well-formed and forwarding_query(q) is well-formed and is true. Otherwise env.query(q, a...) is ill-formed.

🔗

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

16

#

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>::template rebind_alloc, where U is an unspecified type whose size and alignment are both STDCPP_DEFAULT_NEW_ALIGNMENT.

17

#

Mandates:

  • (17.1)

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

  • (17.2)

    allocator_type(arg_next) is a valid expression if there is a parameter of type allocator_arg_t.

  • (17.3)

    allocator_traits::pointer is a pointer type.

18

#

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.

19

#

Returns: A pointer to the allocated storage.

🔗

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

20

#

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

21

#

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