From 6dffed6538e500b3291851daf5a26d7c84bce3a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sun, 29 Jun 2025 18:03:20 +0200 Subject: [PATCH 1/6] applied the changes for P3552r3 I have applied some [I think editorial] changes compared to P3552r3: - added with_error and change_coroutine_scheduler declarations to the synopsis before task; they are in the detailed description but not in the synopsis (possibly they should only be in the synopsis) as there is no further description) - inconsistent default template arguments for the ctor in the class declaration (allocator and the later description (allocator); the wording consistently uses allocator - added "of the" to a sentence about the type of a completion datum: "... defines the type *of the* value completion datum" - the use of the template parameter of the nested type state is Rcvr which has two problems: 1. the ctor also uses the name Rcvr for its template parameter 2. the class stores an object of type R which is the receiver named rcvr the most logic fix is to use Rcvr consistently for the state and change the name for the ctor's parameter: 1. change the ctor template parameter type to use R 2. change the member to use Rcvr 3. change the type R used for the own-env-t to be "...get_env(declval())..." --- source/exceptions.tex | 5 +- source/exec.tex | 776 ++++++++++++++++++++++++++++++++++++++++++ source/support.tex | 1 + 3 files changed, 781 insertions(+), 1 deletion(-) diff --git a/source/exceptions.tex b/source/exceptions.tex index 79684e4c51..de858e4445 100644 --- a/source/exceptions.tex +++ b/source/exceptions.tex @@ -1126,7 +1126,10 @@ when \tcode{unhandled_stopped} is called on a \tcode{with_awaitable_senders} object\iref{exec.with.awaitable.senders} whose continuation is not a handle to a coroutine -whose promise type has an \tcode{unhandled_stopped} member function. +whose promise type has an \tcode{unhandled_stopped} member function, or + +\item% +when an exception is thrown from a coroutine \tcode{std::execution::task}\iref{exec.task} which doesn’t support a \tcode{std::execution::set_error_t(std::execption_ptr)} completion. \end{itemize} diff --git a/source/exec.tex b/source/exec.tex index 8fa3c30a24..e95ff1a88d 100644 --- a/source/exec.tex +++ b/source/exec.tex @@ -708,6 +708,24 @@ // \ref{exec.with.awaitable.senders} template<@\exposconcept{class-type}@ Promise> struct with_awaitable_senders; + + // \ref{exec.affine.on} + struct @\libglobal{affine_on_t}@ { @\unspec@ }; + inline constexpr affine_on_t @\libglobal{affine_on}@{}; + + // \ref{exec.inline.scheduler} + class @\libglobal{inline_scheduler}@; + + // \ref{exec.task.scheduler} + class @\libglobal{task_scheduler}@; + + // \ref{exec.task} + template + struct @\libglobal{with_error}@; + template <@\libconcept{scheduler}@ Sch> + struct @\libglobal{change_coroutine_scheduler}@; + template + class @\libglobal{task}@; } \end{codeblock} @@ -5672,3 +5690,761 @@ return as_awaitable(std::forward(value), static_cast(*this)); \end{codeblock} \end{itemdescr} + +\rSec2[exec.affine.on]{\tcode{execution::affine_on}} + +\pnum \tcode{affine_on} adapts a sender into one that completes on +the specified scheduler. If the algorithm determines that the adapted +sender already completes on the correct scheduler it can avoid any +scheduling operation. + +\pnum The name \tcode{affine_on} denotes a pipeable sender adaptor +object. For subexpressions \tcode{sch} and \tcode{sndr}, if +\tcode{decltype((sch))} does not satisfy \libconcept{scheduler}, or +\tcode{decltype((sndr))} does not satisfy \libconcept{sender}, +\tcode{affine_on(sndr, sch)} is ill-formed. + +\pnum Otherwise, the expression \tcode{affine_on(sndr, sch)} is +expression-equivalent to: +\begin{codeblock} +transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@(affine_on, sch, sndr)) +\end{codeblock} +except that \tcode{sndr} is evalutated only once. + +\pnum +The exposition-only class template \exposid{impls-for}\iref{exec.snd.general} +is specialized for \tcode{affine_on_t} as follows: + +\begin{codeblock} +namespace std::execution { + template <> + struct @\exposid{impls-for}@: @\exposid{default-impls}@ { + static constexpr auto @\exposid{get-attrs}@ = + [](const auto& data, const auto& child) noexcept -> decltype(auto) { + return @\exposid{JOIN-ENV}@(@\exposid{SCHED-ATTRS}@(data), @\exposid{FWD-ENV}@(get_env(child))); + }; + }; +} +\end{codeblock} + +\pnum Let \tcode{out_sndr} be a subexpression denoting a sender +returned from \tcode{affine_on(sndr, sch)} or one equal to such, +and let \tcode{OutSndr} be the type \tcode{decltype((out_sndr))}. +Let \tcode{out_rcvr} be a subexpression denoting a receiver that +has an environment of type \tcode{Env} such that \tcode{sender_in} +is \tcode{true}. Let \tcode{op} be an lvalue referring to +the operation state that results from connecting \tcode{out_sndr} +to \tcode{out_rcvr}. Calling \tcode{start(op)} will start \tcode{sndr} +on the current execution agent and execute completion operations +on \tcode{out_rcvr} on an execution agent of the execution resource +associated with \tcode{sch}. If the current execution resource is +the same as the execution resource associated with \tcode{sch}, the +completion operation on \tcode{out_rcvr} may be called before +\tcode{start(op)} completes. If scheduling onto \tcode{sch} fails, +an error completion on \tcode{out_rcvr} shall be executed on an +unspecified execution agent. + +\rSec2[exec.inline.scheduler]{\tcode{execution::inline_scheduler}} + +\begin{codeblock} +namespace std::execution { + class @\libglobal{inline_scheduler}@ { + class @\exposidnc{inline-sender}@; // \expos + template <@\libconcept{receiver}@ R> + class @\exposidnc{inline-state}@; // \expos + + public: + using scheduler_concept = scheduler_t; + + constexpr @\exposid{inline-sender}@ schedule() noexcept { return {}; } + constexpr bool operator== (const inline_scheduler&) const noexcept = default; + }; +} +\end{codeblock} + +\pnum \tcode{inline_scheduler} is a class that models +\libconcept{scheduler}\iref{exec.sched}. All objects of type +\tcode{inline_scheduler} are equal. + +\pnum \exposid{inline-sender} is an exposition-only type that satisfies +\libconcept{sender}. The type +\tcode{completion_signatures_of_t<\exposid{inline-sender}>} +is \tcode{completion_signatures}. + +\pnum Let \tcode{sndr} be an expression of type \exposid{inline-sender}, +let \tcode{rcvr} be an expression such that +\tcode{\libconcept{receiver_of}} is {true} +where \tcode{CS} is \tcode{completion_signatures}, +then: + +\begin{itemize} +\item the expression \tcode{connect(sndr, rcvr)} has +type \tcode{\exposid{inline-state}>} +and is potentially-throwing if and only if +\tcode{((void)sndr, auto(rcvr))} is potentially-throwing, and +\item the expression +\tcode{get_completion_scheduler(get_env(sndr))} has +type \tcode{inline_scheduler} and is potentially-throwing if and +only if \tcode{get_env(sndr)} is potentially-throwing. +\end{itemize} + +\pnum Let \tcode{o} be a non-const lvalue of type +\tcode{\exposid{inline-state}}, and let \tcode{REC(o)} be +a non-const lvalue reference to an object of type \tcode{Rcvr} that +was initialized with the expression \tcode{rcvr} passed to an +invocation of \tcode{connect} that returned \tcode{o}, then: + +\begin{itemize} +\item the object to which \tcode{REC(o)} refers remains valid for +the lifetime of the object to which \tcode{o} refers, and +\item the expression \tcode{start(o)} is equivalent to +\tcode{set_value(std::move(REC(o)))}. +\end{itemize} + +\rSec2[exec.task.scheduler]{\tcode{execution::task_scheduler}} + +\begin{codeblock} +namespace std::execution { + class task_scheduler { + class @\exposidnc{sender}@; // \expos + template <@\libconcept{receiver}@ R> + class @\exposidnc{state}@; // \expos + + public: + using scheduler_concept = scheduler_t; + + template > + requires (!same_as>) + && scheduler + explicit task_scheduler(Sch&& sch, Allocator alloc = {}); + + @\exposid{sender}@ schedule(); + + friend bool operator== (const task_scheduler& lhs, const task_scheduler& rhs) + noexcept; + template + requires (!same_as) + && scheduler + friend bool operator== (const task_scheduler& lhs, const Sch& rhs) noexcept; + + private: + shared_ptr @\exposidnc{sch_}@; // \expos + }; +} +\end{codeblock} + +\pnum \tcode{task_scheduler} is a class that models +\libconcept{scheduler}\iref{exec.sched}. Given on object \tcode{s} +of type \tcode{task_scheduler}, let \tcode{SCHED(s)} be the object +owned by \tcode{s.\exposid{sch_}}. + +\begin{itemdecl} +template > + requires(!same_as>) && scheduler +explicit task_scheduler(Sch&& sch, Allocator alloc = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum \effects: Initialize \exposid{sch_} with +\tcode{allocate_shared>(alloc, +std::forward(sch))}. + +\pnum \recommended Implementations should avoid the use of dynamically +allocated memory for small scheduler objects. + +\pnum \remarks Any allocations performed by construction of +\exposid{sender} or \exposid{state} objects resulting from calls +on \tcode{*this} are performed using a copy of \tcode{alloc}. +\end{itemdescr} + +\begin{itemdecl} +@\exposid{sender}@ schedule(); +\end{itemdecl} + +\begin{itemdescr} +\pnum \effects Returns an object of type \exposid{sender} containing +a sender initialized with \tcode{schedule(SCHED(*this))}. +\end{itemdescr} + +\begin{itemdecl} +bool operator== (const task_scheduler& lhs, const task_scheduler& rhs) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum \effects Equivalent to: \tcode{return lhs == SCHED(rhs);} +\end{itemdescr} + +\begin{itemdecl} +template + requires (!same_as) + && scheduler +bool operator== (const task_scheduler& lhs, const Sch& rhs) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum \returns \tcode{false} if type of \tcode{SCHED(lhs)} is not +\tcode{Sch}, otherwise \tcode{SCHED(lhs) == rhs;} +\end{itemdescr} + +\begin{codeblock} +class task_scheduler::@\exposid{sender}@ { // \expos +public: + using sender_concept = sender_t; + + template <@\libconcept{receiver}@ Rcvr> + @\exposid{state}@ connect(Rcvr&& rcvr); +}; +\end{codeblock} + +\pnum \exposid{sender} is an exposition-only class that models +\libconcept{sender}\iref{exec.snd} and for which +\tcode{completion_signatures_of_t<\exposid{sender}>} denotes: + +\begin{codeblock} +completion_signatures< + set_value_t(), + set_error_t(error_code), + set_error_t(exception_ptr), + set_stopped_t()> +\end{codeblock} + +\pnum Let \tcode{sch} be an object of type \tcode{task_scheduler} +and let \tcode{sndr} be an object of type \exposid{sender} obtained +from \tcode{schedule(sch)}. Then +\tcode{get_completion_scheduler(get_env(sndr)) == sch} +is \tcode{true}. The object \tcode{SENDER(sndr)} is the sender +object contained by \tcode{sndr} or an object move constructed from +it. + +\begin{itemdecl} +template<@\libconcept{receiver}@ Rcvr> +@\exposid{state}@ connect(Rcvr&& rcvr); +\end{itemdecl} + +\pnum \effects Let \tcode{r} be an object of a type that models +\libconcept{receiver} and whose completion handlers result in +invoking the corresponding completion handlers of \tcode{rcvr} or +copy thereof. Returns an object of type \tcode{\exposid{state}} +containing an operation state object initialized with +\tcode{connect(SENDER(*this), std::move(r))}. + +\begin{codeblock} +template +class task_scheduler::@\exposid{state}@ { // \expos +public: + using operation_state_concept = operation_state_t; + + void start() & noexcept; +}; +\end{codeblock} + +\pnum \exposid{state} is an exposition-only class template whose +specializations model \libconcept{operation_state}\iref{exec.opstate}. + +\begin{itemdecl} +void start() & noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum \effects Equivalent to \tcode{start(st)} where \tcode{st} is +the operation state object contained by \tcode{*this}. +\end{itemdescr} + +\rSec2[exec.task]{\tcode{execution::task}} + +\rSec3[task.overview]{\tcode{task} Overview} + +\pnum The \tcode{task} class template represents a sender that can +be used as the return type of coroutines. The first template parameter +\tcode{T} defines the type of the value completion datum +\iref{exec.async.ops} if \tcode{T} is not \tcode{void}. Otherwise, +there are no value completion datums. Inside coroutines returning +\tcode{task} the operand of \tcode{co_return} (if any) becomes +the argument of \tcode{set_value}. The second template parameter +\tcode{Environment} is used to customize the behavior of \tcode{task}. + +\rSec3[task.class]{Class template \tcode{task}} + +\begin{codeblock} +namespace std::execution { + template + class task { + // \ref{task.state} + template + class @\exposidnc{state}@; // \expos + + public: + using sender_concept = sender_t; + using completion_signatures = @\seebelow@; + using allocator_type = @\seebelow@; + using scheduler_type = @\seebelow@; + using stop_source_type = @\seebelow@; + using stop_token_type = decltype(declval().get_token()); + using error_types = @\seebelow@; + + // \ref{task.promise} + class promise_type; + + task(task&&) noexcept; + ~task(); + + template + @\exposid{state}@ connect(Rcvr&& rcvr); + + private: + coroutine_handle @\exposidnc{handle}@; // \expos + }; +} +\end{codeblock} + +\pnum \tcode{task} models \libconcept{sender}\iref{exec.snd} +if \tcode{T} is \tcode{void}, a reference type, or an \cv{}-unqualified +non-array object type and \tcode{E} is a class type. Otherwise a program +that instantiates the definition of \tcode{task} is ill-formed. + +\pnum The nested types of \tcode{task} template specializations +are determined based on the \tcode{Environment} parameter: + +\begin{itemize} +\item \tcode{allocator_type} is \tcode{Environment::allocator_type} +if that qualified-id is valid and denotes a type, \tcode{allocator} +otherwise. +\item \tcode{scheduler_type} is \tcode{Environment::scheduler_type} +if that qualified-id is valid and denotes a type, \tcode{task_scheduler} +otherwise. +\item \tcode{stop_source_type} is \tcode{Environment::stop_source_type} +if that qualified-id is valid and denotes a type, +\tcode{inplace_stop_source} otherwise. +\item \tcode{error_types} is \tcode{Environment::error_types} if +that qualified-id is valid and denotes a type, +\tcode{completion_signatures} otherwise. +\end{itemize} + +\pnum A program is ill-formed if \tcode{error_types} is not a +specialization of \tcode{completion_signatures} or +\tcode{ErrorSigs} contains an element which is not of the form +\tcode{set_error_t(E)} for some type \tcode{E}. + +\pnum The type alias \tcode{completion_signatures} is a specialization +of \tcode{execution::completion_signatures} with the template +arguments (in unspecified order): + +\begin{itemize} +\item \tcode{set_value_t()} if \tcode{T} is \tcode{void}, and +\tcode{set_value_t(T)} otherwise; +\item template arguments of the specialization of +\tcode{execution::completion_signatures} denoted by \tcode{error_types}; +and +\item \tcode{set_stopped_t()}. +\end{itemize} + +\pnum \tcode{allocator_type} shall meet the \libconcept{Cpp17Allocator} +requirements. + +\rSec3[task.members]{\tcode{task} Members} + +\begin{itemdecl} +task(task&& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum \effects Initializes \exposid{handle} with +\tcode{exchange(other.\exposid{handle}, \{\})}. +\end{itemdescr} + +\begin{itemdecl} +~task(); +\end{itemdecl} + +\begin{itemdescr} +\pnum \effects Equivalent to: + +\begin{codeblock} +if (@\exposid{handle}@) + @\exposid{handle}@.destroy(); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +template <@\libconcept{receiver}@ R> +@\exposid{state}@ connect(R&& recv); +\end{itemdecl} + +\begin{itemdescr} +\pnum \expects \tcode{bool(\exposid{handle})} is \tcode{true}. + +\pnum \effects Equivalent to: \tcode{return +\exposid{state}(exchange(\exposid{handle}, \{\}), +std::forward(recv));} +\end{itemdescr} + +\rSec3[task.state]{\tcode{Class template \tcode{task::state}}} + +\begin{codeblock} +namespace std::execution { + template + template + class task::@\exposid{state}@ { // \expos + public: + using operation_state_concept = operation_state_t; + + template + @\exposid{state}@(coroutine_handle h, R&& rr); + ~@\exposid{state}@(); + void start() & noexcept; + +private: + using @\exposidnc{own-env-t}@ = @\seebelow@; // \expos + coroutine_handle @\exposidnc{handle}@; // \expos + remove_cvref_t @\exposidnc{rcvr}@; // \expos + @\exposid{own-env-t}@ @\exposidnc{own-env}@; // \expos + Environment @\exposidnc{environment}@; // \expos + }; +} +\end{codeblock} + +\begin{itemdescr} +\pnum The type \exposid{own-env-t} is \tcode{Environment::template +env_type()))>} if that qualified-id is +valid and denotes a type, \tcode{env<>} otherwise. +\end{itemdescr} + +\begin{itemdecl} +template +@\exposid{state}@(coroutine_handle h, R&& rr); +\end{itemdecl} + +\begin{itemdescr} +\pnum \effects Initializes + +\item \exposid{handle} with \tcode{std::move(h)}; +\item \exposid{rcvr} with \tcode{std::forward(rr)}; +\item \exposid{own-env} + with \tcode{\exposid{own-env-t}(get_env(\exposid{rcvr}))} if that expression + is valid and \tcode{\exposid{own-env-t}()} otherwise. + If neither of these expressions is valid, the program is ill-formed. +\item \exposid{environment} with \tcode{Environment(\exposid{own-env})} if that expression is + valid, otherwise \tcode{Environment(get_env(\exposid{rcvr}))} + if this expression is valid, otherwise \tcode{Environment()}. + If neither of these expressions is valid, the program is ill-formed. +\end{itemdescr} + +\begin{itemdecl} +~@\exposid{state}@(); +\end{itemdecl} + +\begin{itemdescr} +\pnum \effects Equivalent to: + +\begin{codeblock} +if (@\exposid{handle}@) + @\exposid{handle}@.destroy(); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +void start() & noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum \effects Let \tcode{prom} be the object +\tcode{\exposid{handle}.promise()}. Associates +\tcode{STATE(prom)}, \tcode{RCVR(prom)}, +and \tcode{SCHED(prom)} with \tcode{*this} as follows: + +\begin{itemize} +\item \tcode{STATE(prom)} is \tcode{*this}. +\item \tcode{RCVR(prom)} is \tcode{\exposid{rcvr}}. +\item \tcode{SCHED(prom)} is the object initialized +with \tcode{scheduler_type(get_scheduler(get_env(\exposid{rcvr})))} +if that expression is valid and \tcode{scheduler_type()} otherwise. +If neither of these expressions is valid, the program is ill-formed. +\end{itemize} + +Let \tcode{st} be \tcode{get_stop_token(get_env(\exposid{rcvr}))}. +Initializes \tcode{prom.\exposid{token}} and +\tcode{prom.\exposid{source}} such that + +\begin{itemize} +\item \tcode{prom.\exposid{token}.stop_requested()} returns +\tcode{st.stop_requested()}; +\item \tcode{prom.\exposid{token}.stop_possible()} returns +\tcode{st.stop_possible()}; and +\item for types \tcode{Fn} and \tcode{Init} such that both +\tcode{invocable} and \tcode{constructible_from} are +modeled, \tcode{stop_token_type::callback_type} models +\tcode{\exposid{stoppable-callback-for}}. +\end{itemize} + +After that invokes \tcode{\exposid{handle}.resume()}. +\end{itemdescr} + +\rSec3[task.promise]{Class \tcode{task::promise_type}} + +\begin{codeblock} +namespace std::execution { + template + struct with_error { + using type = remove_cvref_t; + type error; + }; + template + with_error(E) -> with_error; + + template <@\libconcept{scheduler}@ Sch> + struct change_coroutine_scheduler { + using type = remove_cvref_t; + type scheduler; + }; + template <@\libconcept{scheduler}@ Sch> + change_coroutine_scheduler(Sch) -> change_coroutine_scheduler; + + template + class task::promise_type { + public: + template + 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 true; + template + void return_value(V&& value); // present only if is_void_v is false; + + template + @\unspec@ yield_value(with_error error); + + template + auto await_transform(A&& a); + template + auto await_transform(change_coroutine_scheduler sch); + + @\unspec@ get_env() const noexcept; + + template + void* operator new(size_t size, Args&&... args); + + void operator delete(void* pointer, size_t size) noexcept; + + private: + using @\exposidnc{error-variant}@ = @\seebelow@; // \expos + + allocator_type @\exposidnc{alloc}@; // \expos + stop_source_type @\exposidnc{source}@; // \expos + stop_token_type @\exposidnc{token}@; // \expos + optional @\exposidnc{result}@; // \expos; present only if is_void_v is false; + @\exposid{error-variant}@ @\exposidnc{errors}@; // \expos + }; +} +\end{codeblock} + +\pnum Let \tcode{prom} be an object of \tcode{promise_type} and let \tcode{tsk} be +the \tcode{task} object created by \tcode{prom.get_return_object()}. The +description below refers to objects \tcode{STATE(prom)}, +\tcode{RCVR(prom)}, and \tcode{SCHED(prom)} associated +with \tcode{tsk} during evalutation of \tcode{task::\exposid{state}::start} +for some receiver \tcode{Rcvr}. + +\pnum \tcode{\exposid{error-variant}} is a \tcode{variant...>}, with duplicate types removed, where \tcode{E...} +are template arguments of the specialization of +\tcode{execution::completion_signatures} denoted by +\tcode{error_types}. + +\begin{itemdecl} +template +promise_type(const Args&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum \mandates The first parameter of type \tcode{allocator_arg_t} (if +any) is not the last parameter. + +\pnum \effects If \tcode{Args} contains an element of type \tcode{allocator_arg_t} +then \tcode{\exposid{alloc}} is initialized with the corresponding next +element of \tcode{args}. Otherwise, \tcode{\exposid{alloc}} is initialized +with \tcode{allocator_type()}. +\end{itemdescr} + +\begin{itemdecl} +task get_return_object() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum \returns A \tcode{task} object whose member \tcode{\exposid{handle}} +is \tcode{coroutine_handle::from_promise(*this)}. +\end{itemdescr} + +\begin{itemdecl} +auto initial_suspend() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum \returns An awaitable object of unspecified type \iref{expr.await} +whose member functions arrange for + +\begin{itemize} +\item the calling coroutine to be suspended, +\item the coroutine to be resumed on an execution agent of the +execution resource associated with \tcode{SCHED(*this)}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +auto final_suspend() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum \returns An awaitable object of unspecified type + \iref{expr.await} whose member functions arrange for the completion + of the asynchronous operation associated with \tcode{STATE(*this)} by invoking: + +\begin{itemize} +\item + \tcode{set_error(std::move(RCVR(*this)), std::move(e))} + if \tcode{\exposid{errors}.index()} is greater than zero and + \tcode{e} is the value held by \tcode{\exposid{errors}}, otherwise +\item + \tcode{set_value(std::move(RCVR(*this)))} if \tcode{is_void} is \tcode{true}, + and otherwise +\item + \tcode{set_value(std::move(RCVR(*this)), *\exposid{result})}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template +auto yield_value(with_error err); +\end{itemdecl} + +\begin{itemdescr} +\pnum \mandates \tcode{std::move(err.error)} is convertible to + exactly one of the \tcode{set_error_t} argument types of \tcode{error_types}. Let \tcode{Cerr} + be that type. + +\pnum \returns An awaitable object of unspecified type + \iref{expr.await} whose member functions arrange for the calling + coroutine to be suspended and then completes + the asynchronous operation associated with \tcode{STATE(*this)} by invoking + \tcode{set_error(std::move(RCVR(*this)), Cerr(std::move(err.error)))}. +\end{itemdescr} + +\begin{itemdecl} +template <@\libconcept{sender}@ Sender> +auto await_transform(Sender&& sndr) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum \returns If \tcode{same_as} is + \tcode{true} returns \tcode{as_awaitable(std::forward (sndr), *this)}; + otherwise returns + \tcode{as_awaitable(affine_on(std::forward(sndr), SCHED(*this)), *this)}. +\end{itemdescr} + +\begin{itemdecl} +template +auto await_transform(change_coroutine_scheduler sch) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum \effects Equivalent to: \tcode{returns +await_transform(just(exchange(SCHED(*this), +scheduler_type (sch.scheduler))), *this);} +\end{itemdescr} + +\begin{itemdecl} +void uncaught_exception(); +\end{itemdecl} + +\begin{itemdescr} +\pnum \effects If the signature \tcode{set_error_t(exception_ptr)} is + not an element of \tcode{error_types}, calls \tcode{terminate()} + \iref{except.terminate}. Otherwise, stores + \tcode{current_exception()} into \tcode{\exposid{errors}}. +\end{itemdescr} + +\begin{itemdecl} +coroutine_handle<> unhandled_stopped(); +\end{itemdecl} + +\begin{itemdescr} +\pnum \effects Completes the asynchronous operation + associated with \tcode{STATE(*this)} by invoking + \tcode{set_stopped(std::move(RCVR(*this)))}. +\end{itemdescr} + +\begin{itemdescr} +\pnum \returns \tcode{noop_coroutine()}. +\end{itemdescr} + +\begin{itemdecl} +@\unspec@ get_env() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum \returns An object \tcode{env} + such that queries are forwarded as follows: + +\begin{itemize} +\item \tcode{env.query(get_scheduler)} returns \tcode{scheduler_type(SCHED(*this))}. +\item \tcode{env.query(get_allocator)} returns \tcode{\exposid{alloc}}. +\item \tcode{env.query(get_stop_token)} returns \tcode{\exposid{token}}. +\item For any other query \tcode{q} and arguments \tcode{a...} a + call to \tcode{env.query(q, a...)} returns + \tcode{STATE(*this).} \tcode{environment.query(q, a...)} if this expression + is well-formed and \tcode{forwarding_query(q)} is well-formed and is \tcode{true}. Otherwise + \tcode{env.query(q, a...)} is ill-formed. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template +void* operator new(size_t size, const Args&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum If there is no parameter with type \tcode{allocator_arg_t} + then let \tcode{alloc} be \tcode{Allocator()}. Let \tcode{arg_next} be the + parameter following the first \tcode{allocator_arg_t} parameter (if + any) and let \tcode{alloc} be \tcode{Allocator(arg_next)}. Then \tcode{PAlloc} + is \tcode{allocator_traits::template rebind_alloc} where + \tcode{U} is an unspecified type whose size and alignment are both + \tcode{__STDCPP_DEFAULT_NEW_ALIGNMENT__}. + +\pnum \mandates + +\begin{itemize} +\item The first parameter of type \tcode{allocator_arg_t} (if any) is not the last parameter. +\item \tcode{Allocator(arg_next)} is a valid expression if there is a parameter + of type \tcode{allocator_arg_t}. +\item \tcode{allocator_traits::pointer} is a pointer type. +\end{itemize} + +\pnum \effects Initializes an allocator \tcode{palloc} of type \tcode{PAlloc} + with \tcode{alloc}. Uses \tcode{palloc} to allocate storage for the smallest + array of \tcode{U} sufficient to provide storage for a coroutine state + of size \tcode{size}, and unspecified additional state necessary to + ensure that \tcode{operator delete} can later deallocate this memory + block with an allocator equal to \tcode{palloc}. + +\pnum \returns A pointer to the allocated storage. +\end{itemdescr} + +\begin{itemdecl} +void operator delete(void* pointer, size_t size) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum \expects \tcode{pointer} was returned from an invocation + of the above overload of \tcode{operator new} with a size argument + equal to \tcode{size}. + +\pnum \effects Deallocates the storage pointed to by \tcode{pointer} + using an allocator equal to that used to allocate it. +\end{itemdescr} diff --git a/source/support.tex b/source/support.tex index 95d674aafb..6baa7f58fb 100644 --- a/source/support.tex +++ b/source/support.tex @@ -825,6 +825,7 @@ #define @\defnlibxname{cpp_lib_string_view}@ 202403L // also in \libheader{string}, \libheader{string_view} #define @\defnlibxname{cpp_lib_submdspan}@ 202411L // freestanding, also in \libheader{mdspan} #define @\defnlibxname{cpp_lib_syncbuf}@ 201803L // also in \libheader{syncstream} +#define @\defnlibxname{cpp_lib_task}@ 202506L // also in \libheader{execution} #define @\defnlibxname{cpp_lib_text_encoding}@ 202306L // also in \libheader{text_encoding} #define @\defnlibxname{cpp_lib_three_way_comparison}@ 201907L // freestanding, also in \libheader{compare} #define @\defnlibxname{cpp_lib_to_address}@ 201711L // freestanding, also in \libheader{memory} From de6b8e0cd033f3cd700af1d1d4b097dea63e88e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sun, 29 Jun 2025 18:34:43 +0200 Subject: [PATCH 2/6] Fixup: actioned CI feedback --- source/exec.tex | 255 +++++++++++++++++++++++++++++------------------- 1 file changed, 155 insertions(+), 100 deletions(-) diff --git a/source/exec.tex b/source/exec.tex index e95ff1a88d..d2d3f10eed 100644 --- a/source/exec.tex +++ b/source/exec.tex @@ -720,11 +720,11 @@ class @\libglobal{task_scheduler}@; // \ref{exec.task} - template + template struct @\libglobal{with_error}@; - template <@\libconcept{scheduler}@ Sch> + template<@\libconcept{scheduler}@ Sch> struct @\libglobal{change_coroutine_scheduler}@; - template + template class @\libglobal{task}@; } \end{codeblock} @@ -5693,18 +5693,21 @@ \rSec2[exec.affine.on]{\tcode{execution::affine_on}} -\pnum \tcode{affine_on} adapts a sender into one that completes on +\pnum +\tcode{affine_on} adapts a sender into one that completes on the specified scheduler. If the algorithm determines that the adapted sender already completes on the correct scheduler it can avoid any scheduling operation. -\pnum The name \tcode{affine_on} denotes a pipeable sender adaptor +\pnum +The name \tcode{affine_on} denotes a pipeable sender adaptor object. For subexpressions \tcode{sch} and \tcode{sndr}, if \tcode{decltype((sch))} does not satisfy \libconcept{scheduler}, or \tcode{decltype((sndr))} does not satisfy \libconcept{sender}, \tcode{affine_on(sndr, sch)} is ill-formed. -\pnum Otherwise, the expression \tcode{affine_on(sndr, sch)} is +\pnum +Otherwise, the expression \tcode{affine_on(sndr, sch)} is expression-equivalent to: \begin{codeblock} transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@(affine_on, sch, sndr)) @@ -5717,7 +5720,7 @@ \begin{codeblock} namespace std::execution { - template <> + template<> struct @\exposid{impls-for}@: @\exposid{default-impls}@ { static constexpr auto @\exposid{get-attrs}@ = [](const auto& data, const auto& child) noexcept -> decltype(auto) { @@ -5727,7 +5730,8 @@ } \end{codeblock} -\pnum Let \tcode{out_sndr} be a subexpression denoting a sender +\pnum +Let \tcode{out_sndr} be a subexpression denoting a sender returned from \tcode{affine_on(sndr, sch)} or one equal to such, and let \tcode{OutSndr} be the type \tcode{decltype((out_sndr))}. Let \tcode{out_rcvr} be a subexpression denoting a receiver that @@ -5750,7 +5754,7 @@ namespace std::execution { class @\libglobal{inline_scheduler}@ { class @\exposidnc{inline-sender}@; // \expos - template <@\libconcept{receiver}@ R> + template<@\libconcept{receiver}@ R> class @\exposidnc{inline-state}@; // \expos public: @@ -5762,16 +5766,19 @@ } \end{codeblock} -\pnum \tcode{inline_scheduler} is a class that models +\pnum +\tcode{inline_scheduler} is a class that models \libconcept{scheduler}\iref{exec.sched}. All objects of type \tcode{inline_scheduler} are equal. -\pnum \exposid{inline-sender} is an exposition-only type that satisfies +\pnum +\exposid{inline-sender} is an exposition-only type that satisfies \libconcept{sender}. The type \tcode{completion_signatures_of_t<\exposid{inline-sender}>} is \tcode{completion_signatures}. -\pnum Let \tcode{sndr} be an expression of type \exposid{inline-sender}, +\pnum +Let \tcode{sndr} be an expression of type \exposid{inline-sender}, let \tcode{rcvr} be an expression such that \tcode{\libconcept{receiver_of}} is {true} where \tcode{CS} is \tcode{completion_signatures}, @@ -5788,7 +5795,8 @@ only if \tcode{get_env(sndr)} is potentially-throwing. \end{itemize} -\pnum Let \tcode{o} be a non-const lvalue of type +\pnum +Let \tcode{o} be a non-const lvalue of type \tcode{\exposid{inline-state}}, and let \tcode{REC(o)} be a non-const lvalue reference to an object of type \tcode{Rcvr} that was initialized with the expression \tcode{rcvr} passed to an @@ -5807,13 +5815,13 @@ namespace std::execution { class task_scheduler { class @\exposidnc{sender}@; // \expos - template <@\libconcept{receiver}@ R> + template<@\libconcept{receiver}@ R> class @\exposidnc{state}@; // \expos public: using scheduler_concept = scheduler_t; - template > + template> requires (!same_as>) && scheduler explicit task_scheduler(Sch&& sch, Allocator alloc = {}); @@ -5822,7 +5830,7 @@ friend bool operator== (const task_scheduler& lhs, const task_scheduler& rhs) noexcept; - template + template requires (!same_as) && scheduler friend bool operator== (const task_scheduler& lhs, const Sch& rhs) noexcept; @@ -5833,26 +5841,30 @@ } \end{codeblock} -\pnum \tcode{task_scheduler} is a class that models +\pnum +\tcode{task_scheduler} is a class that models \libconcept{scheduler}\iref{exec.sched}. Given on object \tcode{s} of type \tcode{task_scheduler}, let \tcode{SCHED(s)} be the object owned by \tcode{s.\exposid{sch_}}. \begin{itemdecl} -template > +template> requires(!same_as>) && scheduler explicit task_scheduler(Sch&& sch, Allocator alloc = {}); \end{itemdecl} \begin{itemdescr} -\pnum \effects: Initialize \exposid{sch_} with +\pnum +\effects: Initialize \exposid{sch_} with \tcode{allocate_shared>(alloc, std::forward(sch))}. -\pnum \recommended Implementations should avoid the use of dynamically +\pnum +\recommended Implementations should avoid the use of dynamically allocated memory for small scheduler objects. -\pnum \remarks Any allocations performed by construction of +\pnum +\remarks Any allocations performed by construction of \exposid{sender} or \exposid{state} objects resulting from calls on \tcode{*this} are performed using a copy of \tcode{alloc}. \end{itemdescr} @@ -5862,7 +5874,8 @@ \end{itemdecl} \begin{itemdescr} -\pnum \effects Returns an object of type \exposid{sender} containing +\pnum +\effects Returns an object of type \exposid{sender} containing a sender initialized with \tcode{schedule(SCHED(*this))}. \end{itemdescr} @@ -5871,18 +5884,20 @@ \end{itemdecl} \begin{itemdescr} -\pnum \effects Equivalent to: \tcode{return lhs == SCHED(rhs);} +\pnum +\effects Equivalent to: \tcode{return lhs == SCHED(rhs);} \end{itemdescr} \begin{itemdecl} -template +template requires (!same_as) && scheduler bool operator== (const task_scheduler& lhs, const Sch& rhs) noexcept; \end{itemdecl} \begin{itemdescr} -\pnum \returns \tcode{false} if type of \tcode{SCHED(lhs)} is not +\pnum +\returns \tcode{false} if type of \tcode{SCHED(lhs)} is not \tcode{Sch}, otherwise \tcode{SCHED(lhs) == rhs;} \end{itemdescr} @@ -5891,12 +5906,13 @@ public: using sender_concept = sender_t; - template <@\libconcept{receiver}@ Rcvr> + template<@\libconcept{receiver}@ Rcvr> @\exposid{state}@ connect(Rcvr&& rcvr); }; \end{codeblock} -\pnum \exposid{sender} is an exposition-only class that models +\pnum +\exposid{sender} is an exposition-only class that models \libconcept{sender}\iref{exec.snd} and for which \tcode{completion_signatures_of_t<\exposid{sender}>} denotes: @@ -5908,7 +5924,8 @@ set_stopped_t()> \end{codeblock} -\pnum Let \tcode{sch} be an object of type \tcode{task_scheduler} +\pnum +Let \tcode{sch} be an object of type \tcode{task_scheduler} and let \tcode{sndr} be an object of type \exposid{sender} obtained from \tcode{schedule(sch)}. Then \tcode{get_completion_scheduler(get_env(sndr)) == sch} @@ -5921,7 +5938,8 @@ @\exposid{state}@ connect(Rcvr&& rcvr); \end{itemdecl} -\pnum \effects Let \tcode{r} be an object of a type that models +\pnum +\effects Let \tcode{r} be an object of a type that models \libconcept{receiver} and whose completion handlers result in invoking the corresponding completion handlers of \tcode{rcvr} or copy thereof. Returns an object of type \tcode{\exposid{state}} @@ -5929,7 +5947,7 @@ \tcode{connect(SENDER(*this), std::move(r))}. \begin{codeblock} -template +template class task_scheduler::@\exposid{state}@ { // \expos public: using operation_state_concept = operation_state_t; @@ -5938,7 +5956,8 @@ }; \end{codeblock} -\pnum \exposid{state} is an exposition-only class template whose +\pnum +\exposid{state} is an exposition-only class template whose specializations model \libconcept{operation_state}\iref{exec.opstate}. \begin{itemdecl} @@ -5946,7 +5965,8 @@ \end{itemdecl} \begin{itemdescr} -\pnum \effects Equivalent to \tcode{start(st)} where \tcode{st} is +\pnum +\effects Equivalent to \tcode{start(st)} where \tcode{st} is the operation state object contained by \tcode{*this}. \end{itemdescr} @@ -5954,7 +5974,8 @@ \rSec3[task.overview]{\tcode{task} Overview} -\pnum The \tcode{task} class template represents a sender that can +\pnum +The \tcode{task} class template represents a sender that can be used as the return type of coroutines. The first template parameter \tcode{T} defines the type of the value completion datum \iref{exec.async.ops} if \tcode{T} is not \tcode{void}. Otherwise, @@ -5967,10 +5988,10 @@ \begin{codeblock} namespace std::execution { - template + template class task { // \ref{task.state} - template + template class @\exposidnc{state}@; // \expos public: @@ -5988,7 +6009,7 @@ task(task&&) noexcept; ~task(); - template + template @\exposid{state}@ connect(Rcvr&& rcvr); private: @@ -5997,12 +6018,14 @@ } \end{codeblock} -\pnum \tcode{task} models \libconcept{sender}\iref{exec.snd} +\pnum +\tcode{task} models \libconcept{sender}\iref{exec.snd} if \tcode{T} is \tcode{void}, a reference type, or an \cv{}-unqualified non-array object type and \tcode{E} is a class type. Otherwise a program that instantiates the definition of \tcode{task} is ill-formed. -\pnum The nested types of \tcode{task} template specializations +\pnum +The nested types of \tcode{task} template specializations are determined based on the \tcode{Environment} parameter: \begin{itemize} @@ -6020,12 +6043,14 @@ \tcode{completion_signatures} otherwise. \end{itemize} -\pnum A program is ill-formed if \tcode{error_types} is not a +\pnum + A program is ill-formed if \tcode{error_types} is not a specialization of \tcode{completion_signatures} or \tcode{ErrorSigs} contains an element which is not of the form \tcode{set_error_t(E)} for some type \tcode{E}. -\pnum The type alias \tcode{completion_signatures} is a specialization +\pnum +The type alias \tcode{completion_signatures} is a specialization of \tcode{execution::completion_signatures} with the template arguments (in unspecified order): @@ -6038,7 +6063,8 @@ \item \tcode{set_stopped_t()}. \end{itemize} -\pnum \tcode{allocator_type} shall meet the \libconcept{Cpp17Allocator} +\pnum +\tcode{allocator_type} shall meet the \libconcept{Cpp17Allocator} requirements. \rSec3[task.members]{\tcode{task} Members} @@ -6048,7 +6074,8 @@ \end{itemdecl} \begin{itemdescr} -\pnum \effects Initializes \exposid{handle} with +\pnum +\effects Initializes \exposid{handle} with \tcode{exchange(other.\exposid{handle}, \{\})}. \end{itemdescr} @@ -6057,7 +6084,8 @@ \end{itemdecl} \begin{itemdescr} -\pnum \effects Equivalent to: +\pnum +\effects Equivalent to: \begin{codeblock} if (@\exposid{handle}@) @@ -6066,14 +6094,16 @@ \end{itemdescr} \begin{itemdecl} -template <@\libconcept{receiver}@ R> +template<@\libconcept{receiver}@ R> @\exposid{state}@ connect(R&& recv); \end{itemdecl} \begin{itemdescr} -\pnum \expects \tcode{bool(\exposid{handle})} is \tcode{true}. +\pnum +\expects \tcode{bool(\exposid{handle})} is \tcode{true}. -\pnum \effects Equivalent to: \tcode{return +\pnum +\effects Equivalent to: \tcode{return \exposid{state}(exchange(\exposid{handle}, \{\}), std::forward(recv));} \end{itemdescr} @@ -6082,13 +6112,13 @@ \begin{codeblock} namespace std::execution { - template - template + template + template class task::@\exposid{state}@ { // \expos public: using operation_state_concept = operation_state_t; - template + template @\exposid{state}@(coroutine_handle h, R&& rr); ~@\exposid{state}@(); void start() & noexcept; @@ -6104,18 +6134,20 @@ \end{codeblock} \begin{itemdescr} -\pnum The type \exposid{own-env-t} is \tcode{Environment::template +\pnum +The type \exposid{own-env-t} is \tcode{Environment::template env_type()))>} if that qualified-id is valid and denotes a type, \tcode{env<>} otherwise. \end{itemdescr} \begin{itemdecl} -template +template @\exposid{state}@(coroutine_handle h, R&& rr); \end{itemdecl} \begin{itemdescr} -\pnum \effects Initializes +\pnum +\effects Initializes \item \exposid{handle} with \tcode{std::move(h)}; \item \exposid{rcvr} with \tcode{std::forward(rr)}; @@ -6134,7 +6166,8 @@ \end{itemdecl} \begin{itemdescr} -\pnum \effects Equivalent to: +\pnum +\effects Equivalent to: \begin{codeblock} if (@\exposid{handle}@) @@ -6147,14 +6180,15 @@ \end{itemdecl} \begin{itemdescr} -\pnum \effects Let \tcode{prom} be the object +\pnum +\effects Let \tcode{prom} be the object \tcode{\exposid{handle}.promise()}. Associates \tcode{STATE(prom)}, \tcode{RCVR(prom)}, and \tcode{SCHED(prom)} with \tcode{*this} as follows: \begin{itemize} \item \tcode{STATE(prom)} is \tcode{*this}. -\item \tcode{RCVR(prom)} is \tcode{\exposid{rcvr}}. +\item \tcode{RCVR(prom)} is \exposid{rcvr}. \item \tcode{SCHED(prom)} is the object initialized with \tcode{scheduler_type(get_scheduler(get_env(\exposid{rcvr})))} if that expression is valid and \tcode{scheduler_type()} otherwise. @@ -6183,26 +6217,26 @@ \begin{codeblock} namespace std::execution { - template + template struct with_error { using type = remove_cvref_t; type error; }; - template + template with_error(E) -> with_error; - template <@\libconcept{scheduler}@ Sch> + template<@\libconcept{scheduler}@ Sch> struct change_coroutine_scheduler { using type = remove_cvref_t; type scheduler; }; - template <@\libconcept{scheduler}@ Sch> + template<@\libconcept{scheduler}@ Sch> change_coroutine_scheduler(Sch) -> change_coroutine_scheduler; - template + template class task::promise_type { public: - template + template promise_type(const Args&... args); task get_return_object() noexcept; @@ -6213,21 +6247,21 @@ void uncaught_exception(); coroutine_handle<> unhandled_stopped(); - void return_void(); // present only if is_void_v is true; - template - void return_value(V&& value); // present only if is_void_v is false; + void return_void(); // present only if is_void_v is true; + template + void return_value(V&& value); // present only if is_void_v is false; - template + template @\unspec@ yield_value(with_error error); - template + template auto await_transform(A&& a); - template + template auto await_transform(change_coroutine_scheduler sch); @\unspec@ get_env() const noexcept; - template + template void* operator new(size_t size, Args&&... args); void operator delete(void* pointer, size_t size) noexcept; @@ -6244,31 +6278,35 @@ } \end{codeblock} -\pnum Let \tcode{prom} be an object of \tcode{promise_type} and let \tcode{tsk} be +\pnum +Let \tcode{prom} be an object of \tcode{promise_type} and let \tcode{tsk} be the \tcode{task} object created by \tcode{prom.get_return_object()}. The description below refers to objects \tcode{STATE(prom)}, \tcode{RCVR(prom)}, and \tcode{SCHED(prom)} associated with \tcode{tsk} during evalutation of \tcode{task::\exposid{state}::start} for some receiver \tcode{Rcvr}. -\pnum \tcode{\exposid{error-variant}} is a \tcode{variant...>}, with duplicate types removed, where \tcode{E...} are template arguments of the specialization of \tcode{execution::completion_signatures} denoted by \tcode{error_types}. \begin{itemdecl} -template +template promise_type(const Args&... args); \end{itemdecl} \begin{itemdescr} -\pnum \mandates The first parameter of type \tcode{allocator_arg_t} (if +\pnum +\mandates The first parameter of type \tcode{allocator_arg_t} (if any) is not the last parameter. -\pnum \effects If \tcode{Args} contains an element of type \tcode{allocator_arg_t} -then \tcode{\exposid{alloc}} is initialized with the corresponding next -element of \tcode{args}. Otherwise, \tcode{\exposid{alloc}} is initialized +\pnum +\effects If \tcode{Args} contains an element of type \tcode{allocator_arg_t} +then \exposid{alloc} is initialized with the corresponding next +element of \tcode{args}. Otherwise, \exposid{alloc} is initialized with \tcode{allocator_type()}. \end{itemdescr} @@ -6277,7 +6315,8 @@ \end{itemdecl} \begin{itemdescr} -\pnum \returns A \tcode{task} object whose member \tcode{\exposid{handle}} +\pnum +\returns A \tcode{task} object whose member \exposid{handle} is \tcode{coroutine_handle::from_promise(*this)}. \end{itemdescr} @@ -6286,7 +6325,8 @@ \end{itemdecl} \begin{itemdescr} -\pnum \returns An awaitable object of unspecified type \iref{expr.await} +\pnum +\returns An awaitable object of unspecified type \iref{expr.await} whose member functions arrange for \begin{itemize} @@ -6301,7 +6341,8 @@ \end{itemdecl} \begin{itemdescr} -\pnum \returns An awaitable object of unspecified type +\pnum +\returns An awaitable object of unspecified type \iref{expr.await} whose member functions arrange for the completion of the asynchronous operation associated with \tcode{STATE(*this)} by invoking: @@ -6309,7 +6350,7 @@ \item \tcode{set_error(std::move(RCVR(*this)), std::move(e))} if \tcode{\exposid{errors}.index()} is greater than zero and - \tcode{e} is the value held by \tcode{\exposid{errors}}, otherwise + \tcode{e} is the value held by \exposid{errors}, otherwise \item \tcode{set_value(std::move(RCVR(*this)))} if \tcode{is_void} is \tcode{true}, and otherwise @@ -6319,16 +6360,18 @@ \end{itemdescr} \begin{itemdecl} -template +template auto yield_value(with_error err); \end{itemdecl} \begin{itemdescr} -\pnum \mandates \tcode{std::move(err.error)} is convertible to +\pnum +\mandates \tcode{std::move(err.error)} is convertible to exactly one of the \tcode{set_error_t} argument types of \tcode{error_types}. Let \tcode{Cerr} be that type. -\pnum \returns An awaitable object of unspecified type +\pnum +\returns An awaitable object of unspecified type \iref{expr.await} whose member functions arrange for the calling coroutine to be suspended and then completes the asynchronous operation associated with \tcode{STATE(*this)} by invoking @@ -6336,24 +6379,26 @@ \end{itemdescr} \begin{itemdecl} -template <@\libconcept{sender}@ Sender> +template<@\libconcept{sender}@ Sender> auto await_transform(Sender&& sndr) noexcept; \end{itemdecl} \begin{itemdescr} -\pnum \returns If \tcode{same_as} is +\pnum +\returns If \tcode{same_as} is \tcode{true} returns \tcode{as_awaitable(std::forward (sndr), *this)}; otherwise returns \tcode{as_awaitable(affine_on(std::forward(sndr), SCHED(*this)), *this)}. \end{itemdescr} \begin{itemdecl} -template +template auto await_transform(change_coroutine_scheduler sch) noexcept; \end{itemdecl} \begin{itemdescr} -\pnum \effects Equivalent to: \tcode{returns +\pnum +\effects Equivalent to: \tcode{returns await_transform(just(exchange(SCHED(*this), scheduler_type (sch.scheduler))), *this);} \end{itemdescr} @@ -6363,10 +6408,11 @@ \end{itemdecl} \begin{itemdescr} -\pnum \effects If the signature \tcode{set_error_t(exception_ptr)} is +\pnum +\effects If the signature \tcode{set_error_t(exception_ptr)} is not an element of \tcode{error_types}, calls \tcode{terminate()} \iref{except.terminate}. Otherwise, stores - \tcode{current_exception()} into \tcode{\exposid{errors}}. + \tcode{current_exception()} into \exposid{errors}. \end{itemdescr} \begin{itemdecl} @@ -6374,13 +6420,15 @@ \end{itemdecl} \begin{itemdescr} -\pnum \effects Completes the asynchronous operation +\pnum +\effects Completes the asynchronous operation associated with \tcode{STATE(*this)} by invoking \tcode{set_stopped(std::move(RCVR(*this)))}. \end{itemdescr} \begin{itemdescr} -\pnum \returns \tcode{noop_coroutine()}. +\pnum +\returns \tcode{noop_coroutine()}. \end{itemdescr} \begin{itemdecl} @@ -6388,13 +6436,14 @@ \end{itemdecl} \begin{itemdescr} -\pnum \returns An object \tcode{env} +\pnum +\returns An object \tcode{env} such that queries are forwarded as follows: \begin{itemize} \item \tcode{env.query(get_scheduler)} returns \tcode{scheduler_type(SCHED(*this))}. -\item \tcode{env.query(get_allocator)} returns \tcode{\exposid{alloc}}. -\item \tcode{env.query(get_stop_token)} returns \tcode{\exposid{token}}. +\item \tcode{env.query(get_allocator)} returns \exposid{alloc}. +\item \tcode{env.query(get_stop_token)} returns \exposid{token}. \item For any other query \tcode{q} and arguments \tcode{a...} a call to \tcode{env.query(q, a...)} returns \tcode{STATE(*this).} \tcode{environment.query(q, a...)} if this expression @@ -6404,12 +6453,13 @@ \end{itemdescr} \begin{itemdecl} -template +template void* operator new(size_t size, const Args&... args); \end{itemdecl} \begin{itemdescr} -\pnum If there is no parameter with type \tcode{allocator_arg_t} +\pnum +If there is no parameter with type \tcode{allocator_arg_t} then let \tcode{alloc} be \tcode{Allocator()}. Let \tcode{arg_next} be the parameter following the first \tcode{allocator_arg_t} parameter (if any) and let \tcode{alloc} be \tcode{Allocator(arg_next)}. Then \tcode{PAlloc} @@ -6417,7 +6467,8 @@ \tcode{U} is an unspecified type whose size and alignment are both \tcode{__STDCPP_DEFAULT_NEW_ALIGNMENT__}. -\pnum \mandates +\pnum +\mandates \begin{itemize} \item The first parameter of type \tcode{allocator_arg_t} (if any) is not the last parameter. @@ -6426,14 +6477,16 @@ \item \tcode{allocator_traits::pointer} is a pointer type. \end{itemize} -\pnum \effects Initializes an allocator \tcode{palloc} of type \tcode{PAlloc} +\pnum +\effects Initializes an allocator \tcode{palloc} of type \tcode{PAlloc} with \tcode{alloc}. Uses \tcode{palloc} to allocate storage for the smallest array of \tcode{U} sufficient to provide storage for a coroutine state of size \tcode{size}, and unspecified additional state necessary to ensure that \tcode{operator delete} can later deallocate this memory block with an allocator equal to \tcode{palloc}. -\pnum \returns A pointer to the allocated storage. +\pnum +\returns A pointer to the allocated storage. \end{itemdescr} \begin{itemdecl} @@ -6441,10 +6494,12 @@ \end{itemdecl} \begin{itemdescr} -\pnum \expects \tcode{pointer} was returned from an invocation +\pnum +\expects \tcode{pointer} was returned from an invocation of the above overload of \tcode{operator new} with a size argument equal to \tcode{size}. -\pnum \effects Deallocates the storage pointed to by \tcode{pointer} +\pnum +\effects Deallocates the storage pointed to by \tcode{pointer} using an allocator equal to that used to allocate it. \end{itemdescr} From 1587aa47c0ddfc7b51a68a672987dcb8f2001109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sun, 29 Jun 2025 20:03:09 +0200 Subject: [PATCH 3/6] Fixup: address more issues reported by the CI --- source/exceptions.tex | 2 +- source/exec.tex | 177 ++++++++++++++++++++++++------------------ 2 files changed, 101 insertions(+), 78 deletions(-) diff --git a/source/exceptions.tex b/source/exceptions.tex index de858e4445..c036557223 100644 --- a/source/exceptions.tex +++ b/source/exceptions.tex @@ -1129,7 +1129,7 @@ whose promise type has an \tcode{unhandled_stopped} member function, or \item% -when an exception is thrown from a coroutine \tcode{std::execution::task}\iref{exec.task} which doesn’t support a \tcode{std::execution::set_error_t(std::execption_ptr)} completion. +when an exception is thrown from a coroutine \tcode{std::execution::task}\iref{exec.task} which doesn't support a \tcode{std::execution::set_error_t(std::execption_ptr)} completion. \end{itemize} diff --git a/source/exec.tex b/source/exec.tex index d2d3f10eed..22ad3b97e3 100644 --- a/source/exec.tex +++ b/source/exec.tex @@ -5855,7 +5855,8 @@ \begin{itemdescr} \pnum -\effects: Initialize \exposid{sch_} with +\effects +Initialize \exposid{sch_} with \tcode{allocate_shared>(alloc, std::forward(sch))}. @@ -5864,9 +5865,10 @@ allocated memory for small scheduler objects. \pnum -\remarks Any allocations performed by construction of -\exposid{sender} or \exposid{state} objects resulting from calls -on \tcode{*this} are performed using a copy of \tcode{alloc}. +\remarks +Any allocations performed by construction of \exposid{sender} or +\exposid{state} objects resulting from calls on \tcode{*this} are +performed using a copy of \tcode{alloc}. \end{itemdescr} \begin{itemdecl} @@ -5875,8 +5877,9 @@ \begin{itemdescr} \pnum -\effects Returns an object of type \exposid{sender} containing -a sender initialized with \tcode{schedule(SCHED(*this))}. +\effects +Returns an object of type \exposid{sender} containing a sender +initialized with \tcode{schedule(SCHED(*this))}. \end{itemdescr} \begin{itemdecl} @@ -5885,7 +5888,8 @@ \begin{itemdescr} \pnum -\effects Equivalent to: \tcode{return lhs == SCHED(rhs);} +\effects +Equivalent to: \tcode{return lhs == SCHED(rhs);} \end{itemdescr} \begin{itemdecl} @@ -5897,8 +5901,9 @@ \begin{itemdescr} \pnum -\returns \tcode{false} if type of \tcode{SCHED(lhs)} is not -\tcode{Sch}, otherwise \tcode{SCHED(lhs) == rhs;} +\returns +\tcode{false} if type of \tcode{SCHED(lhs)} is not \tcode{Sch}, +otherwise \tcode{SCHED(lhs) == rhs;} \end{itemdescr} \begin{codeblock} @@ -5939,12 +5944,13 @@ \end{itemdecl} \pnum -\effects Let \tcode{r} be an object of a type that models -\libconcept{receiver} and whose completion handlers result in -invoking the corresponding completion handlers of \tcode{rcvr} or -copy thereof. Returns an object of type \tcode{\exposid{state}} -containing an operation state object initialized with -\tcode{connect(SENDER(*this), std::move(r))}. +\effects +Let \tcode{r} be an object of a type that models \libconcept{receiver} +and whose completion handlers result in invoking the corresponding +completion handlers of \tcode{rcvr} or copy thereof. Returns an +object of type \tcode{\exposid{state}} containing an operation +state object initialized with \tcode{connect(SENDER(*this), +std::move(r))}. \begin{codeblock} template @@ -5966,8 +5972,9 @@ \begin{itemdescr} \pnum -\effects Equivalent to \tcode{start(st)} where \tcode{st} is -the operation state object contained by \tcode{*this}. +\effects +Equivalent to \tcode{start(st)} where \tcode{st} is the operation +state object contained by \tcode{*this}. \end{itemdescr} \rSec2[exec.task]{\tcode{execution::task}} @@ -6075,8 +6082,9 @@ \begin{itemdescr} \pnum -\effects Initializes \exposid{handle} with -\tcode{exchange(other.\exposid{handle}, \{\})}. +\effects +Initializes \exposid{handle} with \tcode{exchange(other.\exposid{handle}, +\{\})}. \end{itemdescr} \begin{itemdecl} @@ -6085,7 +6093,8 @@ \begin{itemdescr} \pnum -\effects Equivalent to: +\effects +Equivalent to: \begin{codeblock} if (@\exposid{handle}@) @@ -6100,12 +6109,13 @@ \begin{itemdescr} \pnum -\expects \tcode{bool(\exposid{handle})} is \tcode{true}. +\expects +\tcode{bool(\exposid{handle})} is \tcode{true}. \pnum -\effects Equivalent to: \tcode{return -\exposid{state}(exchange(\exposid{handle}, \{\}), -std::forward(recv));} +\effects +Equivalent to: \tcode{return \exposid{state}(exchange(\exposid{handle}, +\{\}), std::forward(recv));} \end{itemdescr} \rSec3[task.state]{\tcode{Class template \tcode{task::state}}} @@ -6147,7 +6157,8 @@ \begin{itemdescr} \pnum -\effects Initializes +\effects +Initializes \item \exposid{handle} with \tcode{std::move(h)}; \item \exposid{rcvr} with \tcode{std::forward(rr)}; @@ -6167,7 +6178,8 @@ \begin{itemdescr} \pnum -\effects Equivalent to: +\effects +Equivalent to: \begin{codeblock} if (@\exposid{handle}@) @@ -6181,10 +6193,10 @@ \begin{itemdescr} \pnum -\effects Let \tcode{prom} be the object -\tcode{\exposid{handle}.promise()}. Associates -\tcode{STATE(prom)}, \tcode{RCVR(prom)}, -and \tcode{SCHED(prom)} with \tcode{*this} as follows: +\effects +Let \tcode{prom} be the object \tcode{\exposid{handle}.promise()}. +Associates \tcode{STATE(prom)}, \tcode{RCVR(prom)}, and \tcode{SCHED(prom)} +with \tcode{*this} as follows: \begin{itemize} \item \tcode{STATE(prom)} is \tcode{*this}. @@ -6300,11 +6312,13 @@ \begin{itemdescr} \pnum -\mandates The first parameter of type \tcode{allocator_arg_t} (if -any) is not the last parameter. +\mandates +The first parameter of type \tcode{allocator_arg_t} (if any) is not +the last parameter. \pnum -\effects If \tcode{Args} contains an element of type \tcode{allocator_arg_t} +\effects +If \tcode{Args} contains an element of type \tcode{allocator_arg_t} then \exposid{alloc} is initialized with the corresponding next element of \tcode{args}. Otherwise, \exposid{alloc} is initialized with \tcode{allocator_type()}. @@ -6316,8 +6330,9 @@ \begin{itemdescr} \pnum -\returns A \tcode{task} object whose member \exposid{handle} -is \tcode{coroutine_handle::from_promise(*this)}. +\returns +A \tcode{task} object whose member \exposid{handle} is +\tcode{coroutine_handle::from_promise(*this)}. \end{itemdescr} \begin{itemdecl} @@ -6326,8 +6341,9 @@ \begin{itemdescr} \pnum -\returns An awaitable object of unspecified type \iref{expr.await} -whose member functions arrange for +\returns +An awaitable object of unspecified type \iref{expr.await} whose +member functions arrange for \begin{itemize} \item the calling coroutine to be suspended, @@ -6342,9 +6358,10 @@ \begin{itemdescr} \pnum -\returns An awaitable object of unspecified type - \iref{expr.await} whose member functions arrange for the completion - of the asynchronous operation associated with \tcode{STATE(*this)} by invoking: +\returns +An awaitable object of unspecified type \iref{expr.await} whose +member functions arrange for the completion of the asynchronous +operation associated with \tcode{STATE(*this)} by invoking: \begin{itemize} \item @@ -6366,16 +6383,18 @@ \begin{itemdescr} \pnum -\mandates \tcode{std::move(err.error)} is convertible to - exactly one of the \tcode{set_error_t} argument types of \tcode{error_types}. Let \tcode{Cerr} - be that type. +\mandates +\tcode{std::move(err.error)} is convertible to exactly one of the +\tcode{set_error_t} argument types of \tcode{error_types}. Let +\tcode{Cerr} be that type. \pnum -\returns An awaitable object of unspecified type - \iref{expr.await} whose member functions arrange for the calling - coroutine to be suspended and then completes - the asynchronous operation associated with \tcode{STATE(*this)} by invoking - \tcode{set_error(std::move(RCVR(*this)), Cerr(std::move(err.error)))}. +\returns +An awaitable object of unspecified type \iref{expr.await} whose +member functions arrange for the calling coroutine to be suspended +and then completes the asynchronous operation associated with +\tcode{STATE(*this)} by invoking \tcode{set_error(std::move(RCVR(*this)), +Cerr(std::move(err.error)))}. \end{itemdescr} \begin{itemdecl} @@ -6385,10 +6404,11 @@ \begin{itemdescr} \pnum -\returns If \tcode{same_as} is - \tcode{true} returns \tcode{as_awaitable(std::forward (sndr), *this)}; - otherwise returns - \tcode{as_awaitable(affine_on(std::forward(sndr), SCHED(*this)), *this)}. +\returns +If \tcode{same_as} is \tcode{true} +returns \tcode{as_awaitable(std::forward (sndr), *this)}; +otherwise returns \tcode{as_awaitable(affine_on(std::forward(sndr), +SCHED(*this)), *this)}. \end{itemdescr} \begin{itemdecl} @@ -6398,8 +6418,8 @@ \begin{itemdescr} \pnum -\effects Equivalent to: \tcode{returns -await_transform(just(exchange(SCHED(*this), +\effects +Equivalent to: \tcode{returns await_transform(just(exchange(SCHED(*this), scheduler_type (sch.scheduler))), *this);} \end{itemdescr} @@ -6409,10 +6429,10 @@ \begin{itemdescr} \pnum -\effects If the signature \tcode{set_error_t(exception_ptr)} is - not an element of \tcode{error_types}, calls \tcode{terminate()} - \iref{except.terminate}. Otherwise, stores - \tcode{current_exception()} into \exposid{errors}. +\effects +If the signature \tcode{set_error_t(exception_ptr)} is not an element +of \tcode{error_types}, calls \tcode{terminate()} \iref{except.terminate}. +Otherwise, stores \tcode{current_exception()} into \exposid{errors}. \end{itemdescr} \begin{itemdecl} @@ -6421,14 +6441,15 @@ \begin{itemdescr} \pnum -\effects Completes the asynchronous operation - associated with \tcode{STATE(*this)} by invoking - \tcode{set_stopped(std::move(RCVR(*this)))}. +\effects +Completes the asynchronous operation associated with \tcode{STATE(*this)} +by invoking \tcode{set_stopped(std::move(RCVR(*this)))}. \end{itemdescr} \begin{itemdescr} \pnum -\returns \tcode{noop_coroutine()}. +\returns +\tcode{noop_coroutine()}. \end{itemdescr} \begin{itemdecl} @@ -6437,8 +6458,8 @@ \begin{itemdescr} \pnum -\returns An object \tcode{env} - such that queries are forwarded as follows: +\returns +An object \tcode{env} such that queries are forwarded as follows: \begin{itemize} \item \tcode{env.query(get_scheduler)} returns \tcode{scheduler_type(SCHED(*this))}. @@ -6478,15 +6499,16 @@ \end{itemize} \pnum -\effects Initializes an allocator \tcode{palloc} of type \tcode{PAlloc} - with \tcode{alloc}. Uses \tcode{palloc} to allocate storage for the smallest - array of \tcode{U} sufficient to provide storage for a coroutine state - of size \tcode{size}, and unspecified additional state necessary to - ensure that \tcode{operator delete} can later deallocate this memory - block with an allocator equal to \tcode{palloc}. - +\effects +Initializes an allocator \tcode{palloc} of type \tcode{PAlloc} with +\tcode{alloc}. Uses \tcode{palloc} to allocate storage for the +smallest array of \tcode{U} sufficient to provide storage for a +coroutine state of size \tcode{size}, and unspecified additional +state necessary to ensure that \tcode{operator delete} can later +deallocate this memory block with an allocator equal to \tcode{palloc}. \pnum -\returns A pointer to the allocated storage. +\returns +A pointer to the allocated storage. \end{itemdescr} \begin{itemdecl} @@ -6495,11 +6517,12 @@ \begin{itemdescr} \pnum -\expects \tcode{pointer} was returned from an invocation - of the above overload of \tcode{operator new} with a size argument - equal to \tcode{size}. +\expects +\tcode{pointer} was returned from an invocation of the above overload +of \tcode{operator new} with a size argument equal to \tcode{size}. \pnum -\effects Deallocates the storage pointed to by \tcode{pointer} - using an allocator equal to that used to allocate it. +\effects +Deallocates the storage pointed to by \tcode{pointer} using an +allocator equal to that used to allocate it. \end{itemdescr} From 308523f1b42bcf05cc6a359860de65ef315fab0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sun, 29 Jun 2025 23:19:17 +0100 Subject: [PATCH 4/6] Fixup: addressed more CI feedback --- source/exec.tex | 76 ++++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/source/exec.tex b/source/exec.tex index 22ad3b97e3..9f795dd5a6 100644 --- a/source/exec.tex +++ b/source/exec.tex @@ -5791,8 +5791,8 @@ \tcode{((void)sndr, auto(rcvr))} is potentially-throwing, and \item the expression \tcode{get_completion_scheduler(get_env(sndr))} has -type \tcode{inline_scheduler} and is potentially-throwing if and -only if \tcode{get_env(sndr)} is potentially-throwing. +type\linebreak\tcode{inline_scheduler} and is potentially-throwing % avoid Overfull +if and only if \tcode{get_env(sndr)} is potentially-throwing. \end{itemize} \pnum @@ -5822,8 +5822,8 @@ using scheduler_concept = scheduler_t; template> - requires (!same_as>) - && scheduler + requires (!@\libconcept{same_as}@>) + && @\libconcept{scheduler}@ explicit task_scheduler(Sch&& sch, Allocator alloc = {}); @\exposid{sender}@ schedule(); @@ -5831,8 +5831,8 @@ friend bool operator== (const task_scheduler& lhs, const task_scheduler& rhs) noexcept; template - requires (!same_as) - && scheduler + requires (!@\libconcept{same_as}@) + && @\libconcept{scheduler}@ friend bool operator== (const task_scheduler& lhs, const Sch& rhs) noexcept; private: @@ -5849,7 +5849,7 @@ \begin{itemdecl} template> - requires(!same_as>) && scheduler + requires(!@\libconcept{same_as}@>) && @\libconcept{scheduler}@ explicit task_scheduler(Sch&& sch, Allocator alloc = {}); \end{itemdecl} @@ -5857,7 +5857,7 @@ \pnum \effects Initialize \exposid{sch_} with -\tcode{allocate_shared>(alloc, +\tcode{allocate_shared>(alloc, \linebreak % avoid Overfull std::forward(sch))}. \pnum @@ -5879,7 +5879,7 @@ \pnum \effects Returns an object of type \exposid{sender} containing a sender -initialized with \tcode{schedule(SCHED(*this))}. +initialized with\linebreak \tcode{schedule(SCHED(*this))}. % avoid Overfull \end{itemdescr} \begin{itemdecl} @@ -5894,8 +5894,8 @@ \begin{itemdecl} template - requires (!same_as) - && scheduler + requires (!@\libconcept{same_as}@) + && @\libconcept{scheduler}@ bool operator== (const task_scheduler& lhs, const Sch& rhs) noexcept; \end{itemdecl} @@ -5953,7 +5953,7 @@ std::move(r))}. \begin{codeblock} -template +template<@\libconcept{receiver}@ R> class task_scheduler::@\exposid{state}@ { // \expos public: using operation_state_concept = operation_state_t; @@ -5998,7 +5998,7 @@ template class task { // \ref{task.state} - template + template<@\libconcept{receiver}@ Rcvr> class @\exposidnc{state}@; // \expos public: @@ -6016,7 +6016,7 @@ task(task&&) noexcept; ~task(); - template + template<@\libconcept{receiver}@ Rcvr> @\exposid{state}@ connect(Rcvr&& rcvr); private: @@ -6046,7 +6046,7 @@ if that qualified-id is valid and denotes a type, \tcode{inplace_stop_source} otherwise. \item \tcode{error_types} is \tcode{Environment::error_types} if -that qualified-id is valid and denotes a type, +that qualified-id is valid and denotes a type, \linebreak % avoid Overfull \tcode{completion_signatures} otherwise. \end{itemize} @@ -6123,7 +6123,7 @@ \begin{codeblock} namespace std::execution { template - template + template<@\libconcept{receiver}@ Rcvr> class task::@\exposid{state}@ { // \expos public: using operation_state_concept = operation_state_t; @@ -6146,8 +6146,8 @@ \begin{itemdescr} \pnum The type \exposid{own-env-t} is \tcode{Environment::template -env_type()))>} if that qualified-id is -valid and denotes a type, \tcode{env<>} otherwise. +env_type()))>} if that % avoid Overfull +qualified-id is valid and denotes a type, \tcode{env<>} otherwise. \end{itemdescr} \begin{itemdecl} @@ -6212,14 +6212,19 @@ \tcode{prom.\exposid{source}} such that \begin{itemize} -\item \tcode{prom.\exposid{token}.stop_requested()} returns +\item +\tcode{prom.\exposid{token}.stop_requested()} returns \tcode{st.stop_requested()}; -\item \tcode{prom.\exposid{token}.stop_possible()} returns +\item +\tcode{prom.\exposid{token}.stop_possible()} returns \tcode{st.stop_possible()}; and -\item for types \tcode{Fn} and \tcode{Init} such that both -\tcode{invocable} and \tcode{constructible_from} are -modeled, \tcode{stop_token_type::callback_type} models -\tcode{\exposid{stoppable-callback-for}}. +\item +for types \tcode{Fn} and \tcode{Init} such that both +\tcode{\libconcept{invocable}} and +\tcode{\libconcept{constructible_from}} are modeled, +\tcode{stop_token_type::callback_type} models +\tcode{\exposid{stoppable-callback-for}}. \end{itemize} After that invokes \tcode{\exposid{handle}.resume()}. @@ -6332,7 +6337,7 @@ \pnum \returns A \tcode{task} object whose member \exposid{handle} is -\tcode{coroutine_handle::from_promise(*this)}. +\tcode{coroutine_handle::\linebreak from_promise(*this)}. % avoid Overfull \end{itemdescr} \begin{itemdecl} @@ -6406,8 +6411,9 @@ \pnum \returns If \tcode{same_as} is \tcode{true} -returns \tcode{as_awaitable(std::forward (sndr), *this)}; -otherwise returns \tcode{as_awaitable(affine_on(std::forward(sndr), +returns \tcode{as_awaitable(\linebreak std::forward (sndr), % avoid Overfull +*this)}; otherwise returns +\tcode{as_awaitable(affine_on(\linebreak std::forward(sndr), % avoid Overfull SCHED(*this)), *this)}. \end{itemdescr} @@ -6420,7 +6426,7 @@ \pnum \effects Equivalent to: \tcode{returns await_transform(just(exchange(SCHED(*this), -scheduler_type (sch.scheduler))), *this);} +\linebreak scheduler_type(sch.scheduler))), *this);} % avoid Overfull \end{itemdescr} \begin{itemdecl} @@ -6480,13 +6486,13 @@ \begin{itemdescr} \pnum -If there is no parameter with type \tcode{allocator_arg_t} - then let \tcode{alloc} be \tcode{Allocator()}. Let \tcode{arg_next} be the - parameter following the first \tcode{allocator_arg_t} parameter (if - any) and let \tcode{alloc} be \tcode{Allocator(arg_next)}. Then \tcode{PAlloc} - is \tcode{allocator_traits::template rebind_alloc} where - \tcode{U} is an unspecified type whose size and alignment are both - \tcode{__STDCPP_DEFAULT_NEW_ALIGNMENT__}. +If there is no parameter with type \tcode{allocator_arg_t} then let +\tcode{alloc} be \tcode{Allocator()}. Let \tcode{arg_next} be the +parameter following the first \tcode{allocator_arg_t} parameter (if +any) and let \tcode{alloc} be \tcode{Allocator(arg_next)}. Then +\tcode{PAlloc} is \tcode{allocator_traits::template +rebind_alloc\linebreak} where \tcode{U} is an unspecified type % avoid Overfull +whose size and alignment are both \tcode{__STDCPP_DEFAULT_NEW_ALIGNMENT__}. \pnum \mandates From 123ff25f8253532e7c6dd0ff789fd0c590fe871d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sun, 29 Jun 2025 23:31:17 +0100 Subject: [PATCH 5/6] Fixup: address more CI feedback The CI objected to use of \exposid{sender} => renamed sender to ts-sender. This change should be editorial but is more invovled --- source/exec.tex | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/source/exec.tex b/source/exec.tex index 9f795dd5a6..5c317565d3 100644 --- a/source/exec.tex +++ b/source/exec.tex @@ -5814,7 +5814,7 @@ \begin{codeblock} namespace std::execution { class task_scheduler { - class @\exposidnc{sender}@; // \expos + class @\exposidnc{ts-sender}@; // \expos template<@\libconcept{receiver}@ R> class @\exposidnc{state}@; // \expos @@ -5826,7 +5826,7 @@ && @\libconcept{scheduler}@ explicit task_scheduler(Sch&& sch, Allocator alloc = {}); - @\exposid{sender}@ schedule(); + @\exposid{ts-sender}@ schedule(); friend bool operator== (const task_scheduler& lhs, const task_scheduler& rhs) noexcept; @@ -5866,19 +5866,19 @@ \pnum \remarks -Any allocations performed by construction of \exposid{sender} or +Any allocations performed by construction of \exposid{ts-sender} or \exposid{state} objects resulting from calls on \tcode{*this} are performed using a copy of \tcode{alloc}. \end{itemdescr} \begin{itemdecl} -@\exposid{sender}@ schedule(); +@\exposid{ts-sender}@ schedule(); \end{itemdecl} \begin{itemdescr} \pnum \effects -Returns an object of type \exposid{sender} containing a sender +Returns an object of type \exposid{ts-sender} containing a sender initialized with\linebreak \tcode{schedule(SCHED(*this))}. % avoid Overfull \end{itemdescr} @@ -5907,7 +5907,7 @@ \end{itemdescr} \begin{codeblock} -class task_scheduler::@\exposid{sender}@ { // \expos +class task_scheduler::@\exposid{ts-sender}@ { // \expos public: using sender_concept = sender_t; @@ -5917,9 +5917,9 @@ \end{codeblock} \pnum -\exposid{sender} is an exposition-only class that models +\exposid{ts-sender} is an exposition-only class that models \libconcept{sender}\iref{exec.snd} and for which -\tcode{completion_signatures_of_t<\exposid{sender}>} denotes: +\tcode{completion_signatures_of_t<\exposid{ts-sender}>} denotes: \begin{codeblock} completion_signatures< @@ -5931,7 +5931,7 @@ \pnum Let \tcode{sch} be an object of type \tcode{task_scheduler} -and let \tcode{sndr} be an object of type \exposid{sender} obtained +and let \tcode{sndr} be an object of type \exposid{ts-sender} obtained from \tcode{schedule(sch)}. Then \tcode{get_completion_scheduler(get_env(sndr)) == sch} is \tcode{true}. The object \tcode{SENDER(sndr)} is the sender From af0f16f190fc899000e8fb787e642e94980b0fbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sun, 29 Jun 2025 23:49:52 +0100 Subject: [PATCH 6/6] Fixup: addressed more CI feedback (on referencing Cpp17Allocator) --- source/exec.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/exec.tex b/source/exec.tex index 5c317565d3..d05a6ca414 100644 --- a/source/exec.tex +++ b/source/exec.tex @@ -6071,8 +6071,8 @@ \end{itemize} \pnum -\tcode{allocator_type} shall meet the \libconcept{Cpp17Allocator} -requirements. +\tcode{allocator_type} shall meet the \oldconcept{Allocator} +requirements\iref{allocator.requirements.general}. \rSec3[task.members]{\tcode{task} Members}