Skip to content

Commit 86dba29

Browse files
committed
fixup: add 34.9.3
1 parent 3c3dda1 commit 86dba29

File tree

1 file changed

+111
-1
lines changed

1 file changed

+111
-1
lines changed

source/exec.tex

Lines changed: 111 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1358,7 +1358,7 @@
13581358
\end{codeblock}
13591359
\begin{note}
13601360
The \tcode{continues_on} algorithm works
1361-
in tandem with \tcode{schedule_from}\iref{[exec.schedule.from}
1361+
in tandem with \tcode{schedule_from}\iref{exec.schedule.from}
13621362
to give scheduler authors a way to customize both
13631363
how to transition onto (\tcode{continues_on}) and off of (\tcode{schedule_from})
13641364
a given execution context.
@@ -1961,6 +1961,116 @@
19611961

19621962
\rSec2[exec.awaitable]{Awaitable helpers}
19631963

1964+
\pnum
1965+
The sender concepts recognize awaitables as senders.
1966+
For \ref{exec}, an \defn{awaitable} is an expression
1967+
that would be well-formed as the operand of a \tcode{co_await} expression
1968+
within a given context.
1969+
1970+
\pnum
1971+
For a subexpression \tcode{c},
1972+
let \tcode{\exposid{GET-AWAITER}(c, p)} be expression-equivalent to
1973+
the series of transformations and conversions applied to \tcode{c}
1974+
as the operand of an \grammarterm{await-expression} in a coroutine,
1975+
resulting in lvalue \tcode{e} as described by \ref{expr.await},
1976+
where \tcode{p} is an lvalue referring to the coroutine's promise,
1977+
which has type \tcode{Promise}.
1978+
\begin{note}
1979+
This includes the invocation of
1980+
the promise type's \tcode{await_transform} member if any,
1981+
the invocation of the \tcode{operator co_await}
1982+
picked by overload resolution if any, and
1983+
any necessary implicit conversions and materializations.
1984+
\end{note}
1985+
1986+
\pnum
1987+
Let \exposconcept{is-awaitable} be the following exposition-only concept:
1988+
\begin{codeblock}
1989+
namespace std {
1990+
template<class T>
1991+
concept @\exposconcept{await-suspend-result}@ = @\seebelow@; // \expos
1992+
1993+
template<class A, class Promise>
1994+
concept @\defexposconcept{is-awaiter}@ = // \expos
1995+
requires (A& a, coroutine_handle<Promise> h) {
1996+
a.await_ready() ? 1 : 0;
1997+
{ a.await_suspend(h) } -> @\exposconcept{await-suspend-result}@;
1998+
a.await_resume();
1999+
};
2000+
2001+
template<class C, class Promise>
2002+
concept @\defexposconcept{is-awaitable}@ = // \expos
2003+
requires (C (*fc)() noexcept, Promise& p) {
2004+
{ @\exposid{GET-AWAITER}@(fc(), p) } -> @\exposconcept{is-awaiter}@<Promise>;
2005+
};
2006+
}
2007+
\end{codeblock}
2008+
2009+
\tcode{\defexposconcept{await-suspend-result}<T>} is \tcode{true}
2010+
if and only if one of the following is \tcode{true}:
2011+
\begin{itemize}
2012+
\item \tcode{T} is \tcode{void}, or
2013+
\item \tcode{T} is \tcode{bool}, or
2014+
\item \tcode{T} is a specialization of \tcode{coroutine_handle}.
2015+
\end{itemize}
2016+
2017+
\pnum
2018+
For a subexpression \tcode{c}
2019+
such that \tcode{decltype((c))} is type \tcode{C}, and
2020+
an lvalue \tcode{p} of type \tcode{Promise},
2021+
\tcode{\exposid{await-result-type}<C, Promise>} denotes
2022+
the type \tcode{decltype(\exposid{GET-AWAITER}(c, p).await_resume())}.
2023+
2024+
\pnum
2025+
Let \exposid{with-await-transform} be the exposition-only class template:
2026+
\begin{codeblock}
2027+
namespace std::execution {
2028+
template<class T, class Promise>
2029+
concept @\defexposconcept{has-as-awaitable}@ = // \expos
2030+
requires (T&& t, Promise& p) {
2031+
{ std::forward<T>(t).as_awaitable(p) } -> @\exposconcept{is-awaitable}@<Promise&>;
2032+
};
2033+
2034+
template<class Derived>
2035+
struct @\exposid{with-await-transform}@ { // \expos
2036+
template<class T>
2037+
T&& await_transform(T&& value) noexcept {
2038+
return std::forward<T>(value);
2039+
}
2040+
2041+
template<@\exposconcept{has-as-awaitable}@<Derived> T>
2042+
decltype(auto) await_transform(T&& value)
2043+
noexcept(noexcept(std::forward<T>(value).as_awaitable(declval<Derived&>()))) {
2044+
return std::forward<T>(value).as_awaitable(static_cast<Derived&>(*this));
2045+
}
2046+
};
2047+
}
2048+
\end{codeblock}
2049+
2050+
\pnum
2051+
Let \exposid{env-promise} be the exposition-only class template:
2052+
\begin{codeblock}
2053+
namespace std::execution {
2054+
template<class Env>
2055+
struct @\exposid{env-promise}@ : @\exposid{with-await-transform}@<@\exposid{env-promise}@<Env>> { // \expos
2056+
@\unspec@ get_return_object() noexcept;
2057+
@\unspec@ initial_suspend() noexcept;
2058+
@\unspec@ final_suspend() noexcept;
2059+
void unhandled_exception() noexcept;
2060+
void return_void() noexcept;
2061+
coroutine_handle<> unhandled_stopped() noexcept;
2062+
2063+
const Env& get_env() const noexcept;
2064+
};
2065+
}
2066+
\end{codeblock}
2067+
\begin{note}
2068+
of \exposid{env-promise} are used only for the purpose of type computation;
2069+
its members need not be defined.
2070+
\end{note}
2071+
2072+
2073+
19642074
\rSec1[exec.util]{Sender/receiver utilities}
19652075

19662076
\rSec1[exec.ctx]{Execution contexts}

0 commit comments

Comments
 (0)