|
1358 | 1358 | \end{codeblock}
|
1359 | 1359 | \begin{note}
|
1360 | 1360 | 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} |
1362 | 1362 | to give scheduler authors a way to customize both
|
1363 | 1363 | how to transition onto (\tcode{continues_on}) and off of (\tcode{schedule_from})
|
1364 | 1364 | a given execution context.
|
|
1961 | 1961 |
|
1962 | 1962 | \rSec2[exec.awaitable]{Awaitable helpers}
|
1963 | 1963 |
|
| 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 | + |
1964 | 2074 | \rSec1[exec.util]{Sender/receiver utilities}
|
1965 | 2075 |
|
1966 | 2076 | \rSec1[exec.ctx]{Execution contexts}
|
|
0 commit comments