Skip to content

Commit 8ca7ca1

Browse files
committed
P3325R5 A Utility for Creating Execution Environments
1 parent 219b959 commit 8ca7ca1

File tree

1 file changed

+168
-20
lines changed

1 file changed

+168
-20
lines changed

source/exec.tex

Lines changed: 168 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -466,13 +466,20 @@
466466
template<class CPO>
467467
constexpr get_completion_scheduler_t<CPO> @\libglobal{get_completion_scheduler}@{};
468468

469-
struct @\libglobal{empty_env}@ {};
470469
struct @\libglobal{get_env_t}@ { @\unspec@ };
471470
inline constexpr get_env_t @\libglobal{get_env}@{};
472471

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

475+
// \ref{exec.prop}, class template \tcode{prop}
476+
template<class QueryTag, class ValueType>
477+
struct prop;
478+
479+
// \ref{exec.env}, class template \tcode{env}
480+
template<@\exposconcept{queryable}@... Envs>
481+
struct env;
482+
476483
// \ref{exec.domain.default}, execution domains
477484
struct default_domain;
478485

@@ -514,7 +521,7 @@
514521
template<class Sndr>
515522
concept @\libconcept{sender}@ = @\seebelow@;
516523

517-
template<class Sndr, class Env = empty_env>
524+
template<class Sndr, class Env = env<>>
518525
concept @\libconcept{sender_in}@ = @\seebelow@;
519526

520527
template<class Sndr, class Rcvr>
@@ -527,7 +534,7 @@
527534
struct get_completion_signatures_t;
528535
inline constexpr get_completion_signatures_t get_completion_signatures {};
529536

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

@@ -537,18 +544,18 @@
537544
template<class... Ts>
538545
using @\exposidnc{variant-or-empty}@ = @\seebelownc@; // \expos
539546

540-
template<class Sndr, class Env = empty_env,
547+
template<class Sndr, class Env = env<>,
541548
template<class...> class Tuple = @\exposid{decayed-tuple}@,
542549
template<class...> class Variant = @\exposid{variant-or-empty}@>
543550
requires @\libconcept{sender_in}@<Sndr, Env>
544551
using value_types_of_t = @\seebelow@;
545552

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

551-
template<class Sndr, class Env = empty_env>
558+
template<class Sndr, class Env = env<>>
552559
requires @\libconcept{sender_in}@<Sndr, Env>
553560
constexpr bool sends_stopped = @\seebelow@;
554561

@@ -662,7 +669,7 @@
662669

663670
template<
664671
@\libconcept{sender}@ Sndr,
665-
class Env = empty_env,
672+
class Env = env<>,
666673
@\exposconcept{valid-completion-signatures}@ AdditionalSignatures = completion_signatures<>,
667674
template<class...> class SetValue = @\seebelow@,
668675
template<class> class SetError = @\seebelow@,
@@ -834,7 +841,7 @@
834841
The type of the expression above satisfies
835842
\exposconcept{queryable}\iref{exec.queryable}.
836843
\item
837-
Otherwise, \tcode{empty_env\{\}}.
844+
Otherwise, \tcode{env<>\{\}}.
838845
\end{itemize}
839846

840847
\pnum
@@ -1782,7 +1789,7 @@
17821789
if constexpr (sizeof...(child) == 1)
17831790
return (@\exposid{FWD-ENV}@(get_env(child)), ...);
17841791
else
1785-
return empty_env();
1792+
return env<>();
17861793
}
17871794
\end{codeblock}
17881795

@@ -1913,7 +1920,7 @@
19131920
template<class Sndr>
19141921
concept @\defexposconcept{enable-sender}@ = // \expos
19151922
@\exposconcept{is-sender}@<Sndr> ||
1916-
@\exposconcept{is-awaitable}@<Sndr, @\exposid{env-promise}@<empty_env>>; // \ref{exec.awaitable}
1923+
@\exposconcept{is-awaitable}@<Sndr, @\exposid{env-promise}@<env<>>>; // \ref{exec.awaitable}
19171924

19181925
template<class Sndr>
19191926
concept @\deflibconcept{sender}@ =
@@ -1924,7 +1931,7 @@
19241931
@\libconcept{move_constructible}@<remove_cvref_t<Sndr>> &&
19251932
@\libconcept{constructible_from}@<remove_cvref_t<Sndr>, Sndr>;
19261933

1927-
template<class Sndr, class Env = empty_env>
1934+
template<class Sndr, class Env = env<>>
19281935
concept @\deflibconcept{sender_in}@ =
19291936
@\libconcept{sender}@<Sndr> &&
19301937
@\exposconcept{queryable}@<Env> &&
@@ -1982,7 +1989,7 @@
19821989
value_types_of_t<Sndr, Env, @\exposid{value-signature}@, type_identity_t>);
19831990

19841991
template<class Sndr, class... Values>
1985-
concept @\defexposconcept{sender-of}@ = @\exposconcept{sender-in-of}@<Sndr, empty_env, Values...>;
1992+
concept @\defexposconcept{sender-of}@ = @\exposconcept{sender-in-of}@<Sndr, env<>, Values...>;
19861993
}
19871994
\end{codeblock}
19881995

@@ -2665,7 +2672,7 @@
26652672
\tcode{\exposid{FWD-ENV}(get_env(sndr))}\iref{exec.fwd.env}.
26662673
\item
26672674
A parent sender with more than one child sender has
2668-
an associated attributes object equal to \tcode{empty_env\{\}}.
2675+
an associated attributes object equal to \tcode{env<>\{\}}.
26692676
\item
26702677
When a parent sender is connected to a receiver \tcode{rcvr},
26712678
any receiver used to connect a child sender has
@@ -3387,7 +3394,7 @@
33873394
\item
33883395
\tcode{\exposid{MAKE-ENV}(get_domain, get_domain(get_env(sndr)))}
33893396
\item
3390-
\tcode{(void(sndr), empty_env\{\})}
3397+
\tcode{(void(sndr), env<>\{\})}
33913398
\end{itemize}
33923399

33933400
\pnum
@@ -4088,7 +4095,7 @@
40884095
\begin{codeblock}
40894096
[](auto&&, auto&&... child) noexcept {
40904097
if constexpr (@\libconcept{same_as}@<CD, default_domain>) {
4091-
return empty_env();
4098+
return env<>();
40924099
} else {
40934100
return @\exposid{MAKE-ENV}@(get_domain, CD());
40944101
}
@@ -4816,23 +4823,21 @@
48164823
template<@\exposconcept{completion-signature}@... Fns>
48174824
struct completion_signatures {};
48184825

4819-
template<class Sndr,
4820-
class Env = empty_env,
4826+
template<class Sndr, class Env = env<>,
48214827
template<class...> class Tuple = @\exposid{decayed-tuple}@,
48224828
template<class...> class Variant = @\exposid{variant-or-empty}@>
48234829
requires @\libconcept{sender_in}@<Sndr, Env>
48244830
using value_types_of_t =
48254831
@\exposid{gather-signatures}@<set_value_t, completion_signatures_of_t<Sndr, Env>, Tuple, Variant>;
48264832

4827-
template<class Sndr,
4828-
class Env = empty_env,
4833+
template<class Sndr, class Env = env<>,
48294834
template<class...> class Variant = @\exposid{variant-or-empty}@>
48304835
requires @\libconcept{sender_in}@<Sndr, Env>
48314836
using error_types_of_t =
48324837
@\exposid{gather-signatures}@<set_error_t, completion_signatures_of_t<Sndr, Env>,
48334838
type_identity_t, Variant>;
48344839

4835-
template<class Sndr, class Env = empty_env>
4840+
template<class Sndr, class Env = env<>>
48364841
requires @\libconcept{sender_in}@<Sndr, Env>
48374842
constexpr bool sends_stopped =
48384843
!@\libconcept{same_as}@<@\exposid{type-list}@<>,
@@ -4941,6 +4946,149 @@
49414946
of all the \tcode{completion_signatures} specializations in the set
49424947
\tcode{AdditionalSignatures}, \tcode{Vs...}, \tcode{Es...}, \tcode{Ss}.
49434948

4949+
\rSec1[exec.envs]{Queryable uilities}
4950+
4951+
\rSec2[exec.prop]{Class template \tcode{prop}}
4952+
4953+
\begin{codeblock}
4954+
namespace std::execution {
4955+
template<class QueryTag, class ValueType>
4956+
struct @\libglobal{prop}@ {
4957+
QueryTag @\exposid{query_}@; // \expos
4958+
ValueType @\exposid{value_}@; // \expos
4959+
4960+
constexpr const ValueType& query(QueryTag) const noexcept {
4961+
return @\exposid{value_}@;
4962+
}
4963+
};
4964+
4965+
template<class QueryTag, class ValueType>
4966+
prop(QueryTag, ValueType) -> prop<QueryTag, unwrap_reference_t<ValueType>>;
4967+
}
4968+
\end{codeblock}
4969+
4970+
\pnum
4971+
Class template \tcode{prop} is for building a queryable object
4972+
from a query object and a value.
4973+
4974+
\pnum
4975+
\mandates
4976+
\tcode{\exposconcept{callable}<QueryTag, \exposid{prop-like}<ValueType>>}
4977+
is modeled,
4978+
where \exposid{prop-like} is the following exposition-only class template:
4979+
\begin{codeblock}
4980+
template<class ValueType>
4981+
struct @\exposid{prop-like}@ { // \expos
4982+
const ValueType& query(auto) const noexcept;
4983+
};
4984+
\end{codeblock}
4985+
4986+
\pnum
4987+
\begin{example}
4988+
\begin{codeblock}
4989+
template<sender Sndr>
4990+
sender auto parameterize_work(Sndr sndr) {
4991+
// Make an environment such that \tcode{get_allocator(env)} returns a reference to a copy of \tcode{my_alloc\{\}}.
4992+
auto e = prop(get_allocator, my_alloc{});
4993+
4994+
// Parameterize the input sender so that it will use our custom execution environment.
4995+
return write_env(sndr, e);
4996+
}
4997+
\end{codeblock}
4998+
\end{example}
4999+
5000+
\pnum
5001+
Specializations of \tcode{prop} are not assignable.
5002+
5003+
\rSec2[exec.env]{Class template \tcode{env}}
5004+
5005+
\begin{codeblock}
5006+
namespace std::execution {
5007+
template<@\exposconcept{queryable}@... Envs>
5008+
struct @\libglobal{env}@ {
5009+
Envs@$_0$@ @$\exposid{envs}_0$@; // \expos
5010+
Envs@$_1$@ @$\exposid{envs}_1$@; // \expos
5011+
@\vdots@
5012+
Envs@$_{n-1}$@ @$\exposid{envs}_{n-1}$@; // \expos
5013+
5014+
template<class QueryTag>
5015+
constexpr decltype(auto) query(QueryTag q) const noexcept(@\seebelow@);
5016+
};
5017+
5018+
template<class... Envs>
5019+
env(Envs...) -> env<unwrap_reference_t<Envs>...>;
5020+
}
5021+
\end{codeblock}
5022+
5023+
\pnum
5024+
The class template \tcode{env} is used to construct a queryable object
5025+
from several queryable objects.
5026+
Query invocations on the resulting object are resolved
5027+
by attempting to query each subobject in lexical order.
5028+
5029+
\pnum
5030+
Specializations of \tcode{env} are not assignable.
5031+
5032+
\pnum
5033+
It is unspecified
5034+
whether \tcode{env} supports initialization
5035+
using a parenthesized \grammarterm{expression-list}\iref{dcl.init},
5036+
unless the \grammarterm{expression-list} consist of
5037+
a single element of type (possibly const) \tcode{env}.
5038+
5039+
\pnum
5040+
\begin{example}
5041+
\begin{codeblock}
5042+
template<sender Sndr>
5043+
sender auto parameterize_work(Sndr sndr) {
5044+
// Make an environment such that:
5045+
// \tcode{get_allocator(env)} returns a reference to a copy of \tcode{my_alloc\{\}}
5046+
// \tcode{get_scheduler(env)} returns a reference to a copy of \tcode{my_sched\{\}}
5047+
auto e = env{prop(get_allocator, my_alloc{}),
5048+
prop(get_scheduler, my_sched{})};
5049+
5050+
// Parameterize the input sender so that it will use our custom execution environment.
5051+
return write_env(sndr, e);
5052+
}
5053+
\end{codeblock}
5054+
\end{example}
5055+
5056+
\indexlibrarymember{query}{env}%
5057+
\begin{itemdecl}
5058+
template<class QueryTag>
5059+
constexpr decltype(auto) query(QueryTag q) const noexcept(@\seebelow@);
5060+
\end{itemdecl}
5061+
5062+
\begin{itemdescr}
5063+
\pnum
5064+
Let \exposconcept{has-query} be the following exposition-only concept:
5065+
\begin{codeblock}
5066+
template<class Env, class QueryTag>
5067+
concept @\defexposconcept{has-query}@ = // \expos
5068+
requires (const Env& env) {
5069+
env.query(QueryTag());
5070+
};
5071+
\end{codeblock}
5072+
5073+
\pnum
5074+
Let \exposid{fe} be the first element of
5075+
$\exposid{envs}_0$, $\exposid{envs}_1$, $\dotsc$, $\exposid{envs}_{n-1}$
5076+
such that the expression \tcode{\exposid{fe}.query(q)} is well-formed.
5077+
5078+
\pnum
5079+
\constraints
5080+
\tcode{(\exposconcept{has-query}<Envs, QueryTag> || ...)} is \tcode{true}.
5081+
5082+
\pnum
5083+
\effects
5084+
Equivalent to: \tcode{return \exposid{fe}.query(q);}
5085+
5086+
\pnum
5087+
\remarks
5088+
The expression in the \tcode{noexcept} clause is equivalent
5089+
to \tcode{noexcept(\exposid{fe}.query(q))}.
5090+
\end{itemdescr}
5091+
49445092
\rSec1[exec.ctx]{Execution contexts}
49455093

49465094
\rSec2[exec.run.loop]{\tcode{execution::run_loop}}

0 commit comments

Comments
 (0)