Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

P3325R5 A Utility for Creating Execution Environments #7469

Merged
merged 1 commit into from
Dec 17, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 168 additions & 20 deletions source/exec.tex
Original file line number Diff line number Diff line change
Expand Up @@ -465,13 +465,20 @@
template<class CPO>
constexpr get_completion_scheduler_t<CPO> @\libglobal{get_completion_scheduler}@{};

struct @\libglobal{empty_env}@ {};
struct @\libglobal{get_env_t}@ { @\unspec@ };
inline constexpr get_env_t @\libglobal{get_env}@{};

template<class T>
using @\libglobal{env_of_t}@ = decltype(get_env(declval<T>()));

// \ref{exec.prop}, class template \tcode{prop}
template<class QueryTag, class ValueType>
struct prop;

// \ref{exec.env}, class template \tcode{env}
template<@\exposconcept{queryable}@... Envs>
struct env;

// \ref{exec.domain.default}, execution domains
struct default_domain;

Expand Down Expand Up @@ -513,7 +520,7 @@
template<class Sndr>
concept @\libconcept{sender}@ = @\seebelow@;

template<class Sndr, class Env = empty_env>
template<class Sndr, class Env = env<>>
concept @\libconcept{sender_in}@ = @\seebelow@;

template<class Sndr, class Rcvr>
Expand All @@ -526,7 +533,7 @@
struct get_completion_signatures_t;
inline constexpr get_completion_signatures_t get_completion_signatures {};

template<class Sndr, class Env = empty_env>
template<class Sndr, class Env = env<>>
requires @\libconcept{sender_in}@<Sndr, Env>
using completion_signatures_of_t = @\exposid{call-result-t}@<get_completion_signatures_t, Sndr, Env>;

Expand All @@ -536,18 +543,18 @@
template<class... Ts>
using @\exposidnc{variant-or-empty}@ = @\seebelownc@; // \expos

template<class Sndr, class Env = empty_env,
template<class Sndr, class Env = env<>,
template<class...> class Tuple = @\exposid{decayed-tuple}@,
template<class...> class Variant = @\exposid{variant-or-empty}@>
requires @\libconcept{sender_in}@<Sndr, Env>
using value_types_of_t = @\seebelow@;

template<class Sndr, class Env = empty_env,
template<class Sndr, class Env = env<>,
template<class...> class Variant = @\exposid{variant-or-empty}@>
requires @\libconcept{sender_in}@<Sndr, Env>
using error_types_of_t = @\seebelow@;

template<class Sndr, class Env = empty_env>
template<class Sndr, class Env = env<>>
requires @\libconcept{sender_in}@<Sndr, Env>
constexpr bool sends_stopped = @\seebelow@;

Expand Down Expand Up @@ -661,7 +668,7 @@

template<
@\libconcept{sender}@ Sndr,
class Env = empty_env,
class Env = env<>,
@\exposconcept{valid-completion-signatures}@ AdditionalSignatures = completion_signatures<>,
template<class...> class SetValue = @\seebelow@,
template<class> class SetError = @\seebelow@,
Expand Down Expand Up @@ -833,7 +840,7 @@
The type of the expression above satisfies
\exposconcept{queryable}\iref{exec.queryable}.
\item
Otherwise, \tcode{empty_env\{\}}.
Otherwise, \tcode{env<>\{\}}.
\end{itemize}

\pnum
Expand Down Expand Up @@ -1785,7 +1792,7 @@
if constexpr (sizeof...(child) == 1)
return (@\exposid{FWD-ENV}@(get_env(child)), ...);
else
return empty_env();
return env<>();
}
\end{codeblock}

Expand Down Expand Up @@ -1929,7 +1936,7 @@
template<class Sndr>
concept @\defexposconcept{enable-sender}@ = // \expos
@\exposconcept{is-sender}@<Sndr> ||
@\exposconcept{is-awaitable}@<Sndr, @\exposid{env-promise}@<empty_env>>; // \ref{exec.awaitable}
@\exposconcept{is-awaitable}@<Sndr, @\exposid{env-promise}@<env<>>>; // \ref{exec.awaitable}

template<class Sndr>
concept @\deflibconcept{sender}@ =
Expand All @@ -1940,7 +1947,7 @@
@\libconcept{move_constructible}@<remove_cvref_t<Sndr>> &&
@\libconcept{constructible_from}@<remove_cvref_t<Sndr>, Sndr>;

template<class Sndr, class Env = empty_env>
template<class Sndr, class Env = env<>>
concept @\deflibconcept{sender_in}@ =
@\libconcept{sender}@<Sndr> &&
@\exposconcept{queryable}@<Env> &&
Expand Down Expand Up @@ -1998,7 +2005,7 @@
value_types_of_t<Sndr, Env, @\exposid{value-signature}@, type_identity_t>);

template<class Sndr, class... Values>
concept @\defexposconcept{sender-of}@ = @\exposconcept{sender-in-of}@<Sndr, empty_env, Values...>;
concept @\defexposconcept{sender-of}@ = @\exposconcept{sender-in-of}@<Sndr, env<>, Values...>;
}
\end{codeblock}

Expand Down Expand Up @@ -2680,7 +2687,7 @@
\tcode{\exposid{FWD-ENV}(get_env(sndr))}\iref{exec.fwd.env}.
\item
A parent sender with more than one child sender has
an associated attributes object equal to \tcode{empty_env\{\}}.
an associated attributes object equal to \tcode{env<>\{\}}.
\item
When a parent sender is connected to a receiver \tcode{rcvr},
any receiver used to connect a child sender has
Expand Down Expand Up @@ -3401,7 +3408,7 @@
\item
\tcode{\exposid{MAKE-ENV}(get_domain, get_domain(get_env(sndr)))}
\item
\tcode{(void(sndr), empty_env\{\})}
\tcode{(void(sndr), env<>\{\})}
\end{itemize}

\pnum
Expand Down Expand Up @@ -4114,7 +4121,7 @@
\begin{codeblock}
[](auto&&, auto&&... child) noexcept {
if constexpr (@\libconcept{same_as}@<CD, default_domain>) {
return empty_env();
return env<>();
} else {
return @\exposid{MAKE-ENV}@(get_domain, CD());
}
Expand Down Expand Up @@ -4852,23 +4859,21 @@
template<@\exposconcept{completion-signature}@... Fns>
struct completion_signatures {};

template<class Sndr,
class Env = empty_env,
template<class Sndr, class Env = env<>,
template<class...> class Tuple = @\exposid{decayed-tuple}@,
template<class...> class Variant = @\exposid{variant-or-empty}@>
requires @\libconcept{sender_in}@<Sndr, Env>
using value_types_of_t =
@\exposid{gather-signatures}@<set_value_t, completion_signatures_of_t<Sndr, Env>, Tuple, Variant>;

template<class Sndr,
class Env = empty_env,
template<class Sndr, class Env = env<>,
template<class...> class Variant = @\exposid{variant-or-empty}@>
requires @\libconcept{sender_in}@<Sndr, Env>
using error_types_of_t =
@\exposid{gather-signatures}@<set_error_t, completion_signatures_of_t<Sndr, Env>,
type_identity_t, Variant>;

template<class Sndr, class Env = empty_env>
template<class Sndr, class Env = env<>>
requires @\libconcept{sender_in}@<Sndr, Env>
constexpr bool sends_stopped =
!@\libconcept{same_as}@<@\exposid{type-list}@<>,
Expand Down Expand Up @@ -4977,6 +4982,149 @@
of all the \tcode{completion_signatures} specializations in the set
\tcode{AdditionalSignatures}, \tcode{Vs...}, \tcode{Es...}, \tcode{Ss}.

\rSec1[exec.envs]{Queryable uilities}

\rSec2[exec.prop]{Class template \tcode{prop}}

\begin{codeblock}
namespace std::execution {
template<class QueryTag, class ValueType>
struct @\libglobal{prop}@ {
QueryTag @\exposid{query_}@; // \expos
ValueType @\exposid{value_}@; // \expos

constexpr const ValueType& query(QueryTag) const noexcept {
return @\exposid{value_}@;
}
};

template<class QueryTag, class ValueType>
prop(QueryTag, ValueType) -> prop<QueryTag, unwrap_reference_t<ValueType>>;
}
\end{codeblock}

\pnum
Class template \tcode{prop} is for building a queryable object
from a query object and a value.

\pnum
\mandates
\tcode{\exposconcept{callable}<QueryTag, \exposid{prop-like}<ValueType>>}
is modeled,
where \exposid{prop-like} is the following exposition-only class template:
\begin{codeblock}
template<class ValueType>
struct @\exposid{prop-like}@ { // \expos
const ValueType& query(auto) const noexcept;
};
\end{codeblock}

\pnum
\begin{example}
\begin{codeblock}
template<sender Sndr>
sender auto parameterize_work(Sndr sndr) {
// Make an environment such that \tcode{get_allocator(env)} returns a reference to a copy of \tcode{my_alloc\{\}}.
auto e = prop(get_allocator, my_alloc{});

// Parameterize the input sender so that it will use our custom execution environment.
return write_env(sndr, e);
}
\end{codeblock}
\end{example}

\pnum
Specializations of \tcode{prop} are not assignable.

\rSec2[exec.env]{Class template \tcode{env}}

\begin{codeblock}
namespace std::execution {
template<@\exposconcept{queryable}@... Envs>
struct @\libglobal{env}@ {
Envs@$_0$@ @$\exposid{envs}_0$@; // \expos
Envs@$_1$@ @$\exposid{envs}_1$@; // \expos
@\vdots@
Envs@$_{n-1}$@ @$\exposid{envs}_{n-1}$@; // \expos

template<class QueryTag>
constexpr decltype(auto) query(QueryTag q) const noexcept(@\seebelow@);
};

template<class... Envs>
env(Envs...) -> env<unwrap_reference_t<Envs>...>;
}
\end{codeblock}

\pnum
The class template \tcode{env} is used to construct a queryable object
from several queryable objects.
Query invocations on the resulting object are resolved
by attempting to query each subobject in lexical order.

\pnum
Specializations of \tcode{env} are not assignable.

\pnum
It is unspecified
whether \tcode{env} supports initialization
using a parenthesized \grammarterm{expression-list}\iref{dcl.init},
unless the \grammarterm{expression-list} consist of
a single element of type (possibly const) \tcode{env}.

\pnum
\begin{example}
\begin{codeblock}
template<sender Sndr>
sender auto parameterize_work(Sndr sndr) {
// Make an environment such that:
// \tcode{get_allocator(env)} returns a reference to a copy of \tcode{my_alloc\{\}}
// \tcode{get_scheduler(env)} returns a reference to a copy of \tcode{my_sched\{\}}
auto e = env{prop(get_allocator, my_alloc{}),
prop(get_scheduler, my_sched{})};

// Parameterize the input sender so that it will use our custom execution environment.
return write_env(sndr, e);
}
\end{codeblock}
\end{example}

\indexlibrarymember{query}{env}%
\begin{itemdecl}
template<class QueryTag>
constexpr decltype(auto) query(QueryTag q) const noexcept(@\seebelow@);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \exposconcept{has-query} be the following exposition-only concept:
\begin{codeblock}
template<class Env, class QueryTag>
concept @\defexposconcept{has-query}@ = // \expos
requires (const Env& env) {
env.query(QueryTag());
};
\end{codeblock}

\pnum
Let \exposid{fe} be the first element of
$\exposid{envs}_0$, $\exposid{envs}_1$, $\dotsc$, $\exposid{envs}_{n-1}$
such that the expression \tcode{\exposid{fe}.query(q)} is well-formed.

\pnum
\constraints
\tcode{(\exposconcept{has-query}<Envs, QueryTag> || ...)} is \tcode{true}.

\pnum
\effects
Equivalent to: \tcode{return \exposid{fe}.query(q);}

\pnum
\remarks
The expression in the \tcode{noexcept} clause is equivalent
to \tcode{noexcept(\exposid{fe}.query(q))}.
\end{itemdescr}

\rSec1[exec.ctx]{Execution contexts}

\rSec2[exec.run.loop]{\tcode{execution::run_loop}}
Expand Down
Loading