Skip to content

Commit

Permalink
P3325R5 A Utility for Creating Execution Environments
Browse files Browse the repository at this point in the history
  • Loading branch information
jensmaurer authored and tkoeppe committed Dec 17, 2024
1 parent ef8c8ca commit d58b6b1
Showing 1 changed file with 168 additions and 20 deletions.
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

0 comments on commit d58b6b1

Please sign in to comment.