diff --git a/README.md b/README.md
index 6ff6f784..12b78952 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-->
-[](https://github.com/bemanproject/beman/blob/main/docs/beman_library_maturity_model.md#the-beman-library-maturity-model)[](https://coveralls.io/github/bemanproject/execution?branch=main)[](https://godbolt.org/z/9nfa3rTTK)
+[](https://github.com/bemanproject/beman/blob/main/docs/beman_library_maturity_model.md#the-beman-library-maturity-model)[](https://coveralls.io/github/bemanproject/execution?branch=main)[](https://godbolt.org/z/jeMEWGYbM)
diff --git a/docs/implementation-status.md b/docs/implementation-status.md
new file mode 100644
index 00000000..cc64333e
--- /dev/null
+++ b/docs/implementation-status.md
@@ -0,0 +1,301 @@
+# Implementation Status
+
+Meaning of the status indicators (in order best to worst):
+
+- ❎: reviewed and not applicable (e.g. because a section doesn't provide something which would be reflected in code)
+- ✅: reviewed and OK
+- 🔴: reviewed and found incomplete
+- 🚧: no or incomplete review
+
+The indicators come in groups of threes:
+1. The item is implemented
+2. The item is tested
+3. The item is documented (for a somewhat loose definition of "documented": something is said in the [overview](https://github.com/bemanproject/execution/blob/main/docs/overview.md))
+
+Each section containing subelements reflects the state of the "worst" element.
+
+# 🔴🔴🔴 [exec](https://wg21.link/exec) Execution control library
+## 🚧✅✅ [exec.general](https://wg21.link/exec.general) General
+
+- 🚧❎❎ [MANDATE-NOTHROW(expr)](https://wg21.link/exec.general#5) ⇒ noexcept(expr) is `true`
+- ✅✅✅ [movable-value<T>](https://wg21.link/exec.general#6): [`movable_value.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/movable_value.hpp)
+- ✅✅✅ [MATCHING-SIG<F1, F2>](https://wg21.link/exec.general#7): [`matching_sig.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/matching_sig.hpp)
+- ✅✅✅ [AS-EXCEPT-PTR(error)](https://wg21.link/exec.general#8): [`as_except_ptr.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/as_except_ptr.hpp)
+- 🚧❎❎ [as-const(error)](https://wg21.link/exec.general#9): [std::as_const](https://wg21.link/utility.as.const)(error)
+
+## 🚧✅✅ [exec.queryable](https://wg21.link/exec.queryable) Query and queryables
+### 🚧❎❎ [exec.queryable.general](https://wg21.link/exec.queryable.general) General
+### 🚧✅✅ [exec.queryable.concept](https://wg21.link/exec.queryable.concept) Queryable concept
+
+- 🚧✅✅ [queryable<Q>](https://wg21.link/exec.queryable.concept#1): [`queryable.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/queryable.hpp)
+
+## ❎❎❎ [exec.async.ops](https://wg21.link/exec.async.ops) Asynchronous operations
+## ✅✅🔴 [execution.syn](https://wg21.link/execution.syn) Header `` synopsis
+
+- ✅✅🔴 [is_execution_policy<T>](https://wg21.link/execution.syn): [`execution_policy.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/execution_policy.hpp)
+- ✅✅🔴 [is_execution_policy_v<T>](https://wg21.link/execution.syn): [`execution_policy.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/execution_policy.hpp)
+- ✅✅🔴 [sequenced_policy<T>](https://wg21.link/execution.syn): [`execution_policy.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/execution_policy.hpp)
+- ✅✅🔴 [parallel_policy<T>](https://wg21.link/execution.syn): [`execution_policy.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/execution_policy.hpp)
+- ✅✅🔴 [parallel_unsequenced_policy<T>](https://wg21.link/execution.syn): [`execution_policy.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/execution_policy.hpp)
+- ✅✅🔴 [unsequenced_policy<T>](https://wg21.link/execution.syn): [`execution_policy.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/execution_policy.hpp)
+- ✅✅🔴 [seq](https://wg21.link/execution.syn): [`execution_policy.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/execution_policy.hpp)
+- ✅✅🔴 [par](https://wg21.link/execution.syn): [`execution_policy.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/execution_policy.hpp)
+- ✅✅🔴 [par_unseq](https://wg21.link/execution.syn): [`execution_policy.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/execution_policy.hpp)
+- ✅✅🔴 [unseq](https://wg21.link/execution.syn): [`execution_policy.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/execution_policy.hpp)
+- ✅✅✅ [movable-value<T>](https://wg21.link/exec.general#6): [`movable_value.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/movable_value.hpp)
+- ✅✅✅ [decays-to](https://wg21.link/execution.syn): [`decays_to.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/decays_to.hpp)
+- ✅✅✅ [class-type](https://wg21.link/execution.syn): [`class_type.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/class_type.hpp)
+- ✅✅✅ [queryable<Q>](https://wg21.link/exec.queryable.concept#1): [`queryable.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/queryable.hpp)
+- ✅✅✅ [single-sender-value_type<Sndr, Env...>](https://wg21.link/exec.queryable.concept#1): [`single_sender_value_type.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/single_sender_value_type.hpp)
+- ✅✅✅ [single-sender<Sndr, Env...>](https://wg21.link/exec.queryable.concept#1): [`single_sender.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/single_sender.hpp)
+
+## 🔴🔴🔴 [exec.queries](https://wg21.link/exec.queries) Queries
+### ✅✅✅ [exec.queries.expos](https://wg21.link/exec.queries.expos) Query utilities
+
+- ✅✅✅ [TRY-QUERY(q, tag, a...)](https://wg21.link/exec.queries.expos#2): [`try_query.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/try_query.hpp)
+- ✅✅✅ [HIDE-SCHED(q, tag, a...)](https://wg21.link/exec.queries.expos#3): [`hide_sched.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/hide_sched.hpp)
+
+### ✅✅✅ [exec.fwd.env](https://wg21.link/exec.fwd.env) `forwarding_query`: [`forwarding_query.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/forwarding_query.hpp)
+### ✅✅✅ [exec.get.allocator](https://wg21.link/exec.get.allocator) `get_allocator`: [`get_allocator.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/get_allocator.hpp)
+### ✅✅✅ [exec.get.stop.token](https://wg21.link/exec.get.stop.token) `get_stop_token`: [`get_stop_token.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/get_stop_token.hpp)
+### ✅✅✅ [exec.get.env](https://wg21.link/exec.get.env) `execution::get_env`: [`get_env.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/get_env.hpp)
+### ✅✅✅ [exec.get.domain](https://wg21.link/exec.get.domain) `execution::get_domain`: [`get_domain.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/get_domain.hpp)
+### ✅✅✅ [exec.get.scheduler](https://wg21.link/exec.get.scheduler) `execution::get_scheduler`: [`get_scheduler.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/get_scheduler.hpp)
+### ✅✅✅ [exec.get.start.scheduler](https://wg21.link/exec.get.start.scheduler) `execution::get_start_scheduler`: [`get_start_scheduler.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/get_start_scheduler.hpp)
+### ✅✅✅ [exec.get.delegation.scheduler](https://wg21.link/exec.get.delegation.scheduler) `execution::get_delegation_scheduler`: [`get_delegation_scheduler.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/get_delegation_scheduler.hpp)
+### ✅✅✅ [exec.get.fwd.progress](https://wg21.link/exec.get.fwd.progress) `execution::get_forward_progress_guarantee`
+
+- ✅✅✅ [`forward_progress_guarantee`](https://wg21.link/exec.get.fwd.progress): [`get_forward_progress_guarantee.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/get_forward_progress_guarantee.hpp)
+- ✅✅✅ [`get_forward_progress_guarantee`](https://wg21.link/exec.get.fwd.progress#2): [`get_forward_progress_guarantee.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/get_forward_progress_guarantee.hpp)
+
+### ✅✅✅ [exec.get.compl.sched](https://wg21.link/exec.get.compl.sched) `execution::get_completion_scheduler`: [`get_completion_scheduler.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/get_completion_scheduler.hpp)
+
+- ❎ check [exec.get.compl.sched p6](https://wg21.link/exec.get.compl.sched#6)
+
+### ✅✅🔴 [exec.get.compl.domain](https://wg21.link/exec.get.compl.domain) `execution::get_completion_domain`: [`get_completion_domain.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/get_completion_domain.hpp)
+
+- ❎ check [exec.get.compl.domain p3](https://wg21.link/exec.get.compl.domain#3
+
+### ✅🔴🔴 [exec.get.await.adapt](https://wg21.link/exec.get.await.adapt) `execution::get_await_completion_adaptor`: [`get_await_completion_adaptor.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/get_await_completion_adaptor.hpp)
+## ✅🔴✅ [exec.sched](https://wg21.link/exec.sched) Schedulers
+
+- ✅✅✅ [`scheduler`](https://wg21.link/exec.sched#1): [`scheduler.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/scheduler.hpp)
+- ✅🔴✅ [infallible-scheduler](https://wg21.link/exec.sched#8): [`infallible_scheduler.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/infallible_scheduler.hpp)
+
+## 🔴🔴🔴 [exec.recv](https://wg21.link/exec.recv) Receivers
+### 🔴🔴🔴 [exec.recv.concepts](https://wg21.link/exec.recv.concepts) Receiver concepts
+
+- ✅✅✅ [`receiver`](https://wg21.link/exec.recv.concepts#1): [`receiver.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/receiver.hpp)
+- ✅✅✅ [valid-completion-for](https://wg21.link/exec.recv.concepts#1): [`valid_completion_for.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/valid_completion_for.hpp)
+- ✅✅✅ [has-completion](https://wg21.link/exec.recv.concepts#1): [`has_completions.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/has_completions.hpp)
+- ✅✅✅ [receiver-of](https://wg21.link/exec.recv.concepts#1): [`receiver_of.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/receiver_of.hpp)
+- 🔴🔴🔴 [inlinable_receiver](https://wg21.link/exec.recv.concepts#4)
+
+### ✅✅✅ [exec.set.value](https://wg21.link/exec.set.value) `execution::set_value`: [`set_value.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/set_value.hpp)
+### ✅✅✅ [exec.set.error](https://wg21.link/exec.set.error) `execution::set_error`: [`set_error.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/set_error.hpp)
+### ✅✅✅ [exec.set.stopped](https://wg21.link/exec.set.stopped) `execution::set_stopped`: [`set_stopped.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/set_stopped.hpp)
+## ✅✅✅ [exec.opstate](https://wg21.link/exec.opstate) Operation states
+### ✅✅✅ [exec.opstate.general](https://wg21.link/exec.opstate.general) General: [`operation_state.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/operation_state.hpp)
+### ✅✅✅ [exec.opstate.start](https://wg21.link/exec.opstate.start) `execution::start`: [`start.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/start.hpp)
+## 🔴🔴🔴 [exec.snd](https://wg21.link/exec.snd) Senders
+### ❎❎❎ [exec.snd.general](https://wg21.link/exec.snd.general) General
+### 🔴🔴🔴 [exec.snd.expos](https://wg21.link/exec.snd.expos) Exposition-only entities
+
+- ✅✅✅ [exec.snd.expos p4](https://wg21.link/exec.snd.expos#4) FWD-ENV(env): [`fwd_env.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/fwd_env.hpp)
+- ✅✅✅ [exec.snd.expos p4](https://wg21.link/exec.snd.expos#4) FWD-ENV-T(Env): [`fwd_env.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/fwd_env.hpp)
+- ✅✅✅ [exec.snd.expos p5](https://wg21.link/exec.snd.expos#5) MAKE-ENV(q, v): [`make_env.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/make_env.hpp)
+- ✅✅✅ [exec.snd.expos p6](https://wg21.link/exec.snd.expos#6) JOIN-ENV(ev1, ev2): [`join_env.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/join_env.hpp)
+- ✅🔴✅ [exec.snd.expos p8](https://wg21.link/exec.snd.expos#8) COMMON-DOMAIN(domains...): [`common_domain.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/common_domain.hpp)
+- ✅✅✅ [exec.snd.expos p9](https://wg21.link/exec.snd.expos#9) COMPL-DOMAIN(sndr, ev...): [`compl_domain.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/compl_domain.hpp) 🚨 the name appears to be unused!
+- ✅✅✅ [exec.snd.expos p10](https://wg21.link/exec.snd.expos#10) SCHED-ENV(sch): [`sched_env.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/sched_env.hpp)
+- 🚧🚧🚧 [exec.snd.expos p11](https://wg21.link/exec.snd.expos#11) SET-VALUE(rcvr, expr): [`set_value.hpp](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/set_value.hpp), TRY-EVAL(expr): [`common.hpp](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/common.hpp), TRY-SET-VALUE(rcvr, expr)
+- ✅✅✅ [exec.snd.expos p12](https://wg21.link/exec.snd.expos#12) query-with-default(tag, env, value): [`query_with_default.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/query_with_default.hpp)
+- ✅🔴🔴 [exec.snd.expos p15](https://wg21.link/exec.snd.expos#15) emplace-from{fun}: [`emplace_from.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/emplace_from.hpp)
+- ✅🔴🔴 [exec.snd.expos p12](https://wg21.link/exec.snd.expos#16) on-stop-request{stop_source}: [`on_stop_request.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/on_stop_request.hpp)
+- ✅✅✅ [exec.snd.expos p17](https://wg21.link/exec.snd.expos#17) product-type{members...}: [`product_type.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/product_type.hpp)
+- ✅✅✅ [exec.snd.expos p23](https://wg21.link/exec.snd.expos#23) valid-specialization<T, Args...>: [`valid_specialization.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/valid_specialization.hpp)
+- ✅✅✅ [exec.snd.expos p24](https://wg21.link/exec.snd.expos#24) make-sender(tag, data = empty{}, child...): [`make_sender.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/make_sender.hpp)
+- ✅✅🔴 [exec.snd.expos p27](https://wg21.link/exec.snd.expos#27) state-type<Sndr, Rcvr<: [`state_type.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/state_type.hpp) env-type<Index, Sndr, Rcvr<: [`env_type.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/env_type.hpp) data-type<Sndr<: [`data_type.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/data_type.hpp) child-type<Sndr, I = 0<: [`child_type.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/child_type.hpp) indices-for<Sndr<: [`indices_for.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/indices_for.hpp) basic-state<Sndr<: [`basic_state.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/basic_state.hpp)
+- ✅✅🔴 [exec.snd.expos p29](https://wg21.link/exec.snd.expos#29) basic-receiver<Sndr, Rcvr, Index>: [`basic_receiver.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/basic_receiver.hpp)
+- ✅✅🔴 [exec.snd.expos p30](https://wg21.link/exec.snd.expos#30) connect-all{&op, sndr, indices}: [`connect_all.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/connect_all.hpp)
+- ✅✅🔴 [exec.snd.expos p33](https://wg21.link/exec.snd.expos#33) basic-operation<Sndr, Rcvr>: [`basic_operation.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/basic_operation.hpp)
+- ✅✅🔴 [exec.snd.expos p35](https://wg21.link/exec.snd.expos#35) default-impls: [`default_impls.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/default_impls.hpp) 🚨 verify check-types and impls-for members
+- ✅✅🔴 [exec.snd.expos p43](https://wg21.link/exec.snd.expos#43) basic-sender<Tag, Data, Child...>: [`basic_sender.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/basic_sender.hpp)
+- 🔴🔴🔴 [exec.snd.expos p50](https://wg21.link/exec.snd.expos#50) overload-set<Funs...>
+- 🔴🔴🔴 [exec.snd.expos p51](https://wg21.link/exec.snd.expos#51) not-a-sender
+- 🔴🔴🔴 [exec.snd.expos p52](https://wg21.link/exec.snd.expos#52) not-a-scheduler
+- 🔴🔴🔴 [exec.snd.expos p53](https://wg21.link/exec.snd.expos#53) decay-copyable-result-datums
+- 🔴🔴🔴 [exec.snd.expos p54](https://wg21.link/exec.snd.expos#54) allocator-aware-forward(obj, env)
+- ✅🔴🔴 [exec.snd.expos p56](https://wg21.link/exec.snd.expos#56) call-with-default(fn, value, args...): [`call_with_default.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/call_with_default.hpp)
+- ✅✅🔴 [exec.snd.expos p59](https://wg21.link/exec.snd.expos#59) inline-attrs<T>: [`inline_attrs.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/inline_attrs.hpp)
+
+### 🔴🔴🔴 [exec.snd.concepts](https://wg21.link/exec.snd.concepts) Sender concepts
+
+- ✅🔴🔴 [exec.snd.concepts p1](https://wg21.link/exec.snd.concepts#1) is-constant<Value>: [`is_constant.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/is_constant.hpp)
+- ✅✅🔴 [exec.snd.concepts p1](https://wg21.link/exec.snd.concepts#1) is-sender<Value>: [`is_sender.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/is_sender.hpp)
+- ✅✅🔴 [exec.snd.concepts p1](https://wg21.link/exec.snd.concepts#1) enable-sender<Value>: [`enable_sender.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/enable_sender.hpp)
+- 🔴🔴🔴 [exec.snd.concepts p1](https://wg21.link/exec.snd.concepts#1) is-dependent-sender-helper<Sndr>
+- ✅✅✅ [exec.snd.concepts p1](https://wg21.link/exec.snd.concepts#1) sender<T>: [`sender.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/sender.hpp)
+- ✅✅✅ [exec.snd.concepts p1](https://wg21.link/exec.snd.concepts#1) sender_in<T, Env...>: [`sender_in.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/sender_in.hpp)
+- ✅✅✅ [exec.snd.concepts p1](https://wg21.link/exec.snd.concepts#1) dependent_sender<T, Env...>: [`sender_in.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/sender_in.hpp)
+- ✅✅✅ [exec.snd.concepts p1](https://wg21.link/exec.snd.concepts#1) sender_to<Sndr, Rcvr>: [`sender_to.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/sender_to.hpp)
+- 🔴🔴🔴 [exec.snd.concepts p5](https://wg21.link/exec.snd.concepts#5) value-signature<As...>
+- 🔴🔴🔴 [exec.snd.concepts p5](https://wg21.link/exec.snd.concepts#5) sender-in-of-impl<Sndr, SetValue, Env...>
+- 🔴🔴🔴 [exec.snd.concepts p5](https://wg21.link/exec.snd.concepts#5) sender-in-of<Sndr, Env, Values...>
+- 🔴🔴🔴 [exec.snd.concepts p5](https://wg21.link/exec.snd.concepts#5) sender-of<Sndr, Values...>
+- ✅✅✅ [exec.snd.concepts p6](https://wg21.link/exec.snd.concepts#6) tag_of_t<Sndr>: [`tag_of_t.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/tag_of_t.hpp)
+- ✅✅✅ [exec.snd.concepts p7](https://wg21.link/exec.snd.concepts#7) sender-for<Sndr, tag>: [`sender_for.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/sender_for.hpp)
+- 🔴🔴🔴 [exec.snd.concepts p8](https://wg21.link/exec.snd.concepts#8) SET-VALUE-SIG(T)
+
+### ✅✅🔴 [exec.awaitable](https://wg21.link/exec.awaitable) Awaitable helpers
+
+- ✅✅🔴 [exec.awaitable p2](https://wg21.link/exec.awitable#2) GET-AWAITER(c, p): [`get_awaiter.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/get_awaiter.hpp)
+- ✅✅🔴 [exec.awaitable p3](https://wg21.link/exec.awitable#3) await-suspend-result<T>: [`await_suspend_result.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/await_suspend_result.hpp)
+- ✅✅🔴 [exec.awaitable p3](https://wg21.link/exec.awitable#3) is-awaiter<A, Promise...>: [`await_suspend_result.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/await_suspend_result.hpp)
+- ✅✅🔴 [exec.awaitable p3](https://wg21.link/exec.awitable#3) is-awaitable<C, Promise...>: [`is_awaitable.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/is_awaitable.hpp)
+- ✅✅🔴 [exec.awaitable p5](https://wg21.link/exec.awitable#5) has-as-awaitable<T, Promise>: [`has_as_awaitable.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/has_as_awaitable.hpp)
+- ✅✅🔴 [exec.awaitable p5](https://wg21.link/exec.awitable#5) with-await-transform<Derived>: [`has_as_awaitable.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/has_as_awaitable.hpp)
+- ✅✅🔴 [exec.awaitable p6](https://wg21.link/exec.awitable#6) env-promise<Env>: [`env_promise.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/env_promise.hpp)
+
+### ✅✅🔴 [exec.domain.indeterminate](https://wg21.link/exec.domain.indeterminate) `execution::indeterminate_domain`: [`indeterminate_domain.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/indeterminate_domain.hpp)
+### ✅✅🔴 [exec.domain.default](https://wg21.link/exec.domain.default) `execution::default_domain`: [`default_domain.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/default_domain.hpp)
+### ✅✅🔴 [exec.snd.transform](https://wg21.link/exec.snd.transform) `exuection::transform_sender`: [`transform_sender.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/transform_sender.hpp)
+### ✅✅🔴 [exec.snd.apply](https://wg21.link/exec.snd.apply) `execution::apply_sender`: [`apply_sender.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/apply_sender.hpp)
+### ✅✅✅ [exec.getcomplsigs](https://wg21.link/exec.getcomplsigs) `execution::get_completion_signatures`: [`get_completion_signatures.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/get_completion_signatures.hpp)
+### 🔴🔴🔴 [exec.connect](https://wg21.link/exec.connect) `execution::connect`
+
+- ✅✅✅ [exec.connect p2](https://wg21.link/exec.connect#2) connect(sndr, rcvr): [`connect.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/connect.hpp)
+- ✅✅✅ [exec.connect p3](https://wg21.link/exec.connect#3) connect-awaitable-promise: [`operation_state_task.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/operation_state_task.hpp)
+- ✅✅✅ [exec.connect p4](https://wg21.link/exec.connect#4) operation-state-task: [`operation_state_task.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/operation_state_task.hpp)
+- ✅✅🔴 [exec.connect p5](https://wg21.link/exec.connect#5) await-result-type<DS, Promise>: [`await_result_type.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/await_result_type.hpp)
+- ✅✅🔴 [exec.connect p5](https://wg21.link/exec.connect#5) suspend-complete(fun, as...): [`suspend_complete.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/suspend_complete.hpp)
+- ✅✅🔴 [exec.connect p5](https://wg21.link/exec.connect#5) connect-awaitable(sndr, rcvr): [`connect_awaitable.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/connect_awaitable.hpp)
+
+## ✅✅✅ [exec.factories](https://wg21.link/exec.factories) Sender factories
+### ✅✅✅ [exec.schedule](https://wg21.link/exec.schedule) `execution::schedule`: [`schedule.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/schedule.hpp)
+### ✅✅✅ [exec.just](https://wg21.link/exec.just) `execution::just`, `exuection::just_error`, `execution::just_stopped`: [`just.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/just.hpp)
+### ✅✅✅ [exec.read.env](https://wg21.link/exec.read.env) `execution::read_env`: [`read_env.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/read_env.hpp)
+## ✅🔴🔴 [exec.adapt](https://wg21.link/exec.adapt) Sender adaptors
+### ✅🔴🔴 [exec.adapt.general](https://wg21.link/exec.adapt.general) General
+
+- 🚧 [exec.adapt.general p3.2](https://wg21.link/exec.adapt.general#3.2) verify single child env
+- 🚧 [exec.adapt.general p3.3](https://wg21.link/exec.adapt.general#3.3) verify multi child env
+- 🚧 [exec.adapt.general p3.4](https://wg21.link/exec.adapt.general#3.4) verify child's receiver's env
+- 🚧 [exec.adapt.general p3.5](https://wg21.link/exec.adapt.general#3.5) sender non-dependent
+
+### ✅✅🔴 [exec.adapt.obj](https://wg21.link/exec.adapt.obj) Closure objects
+
+- 🚧 [exec.adapt.obj p1](https://wg21.link/exec.adapt.general#1) verify senders are pipeable
+- 🚧 [exec.adapt.obj p1](https://wg21.link/exec.adapt.general#1) verify pipeable sender adaptor closure objects compose
+
+### ✅✅✅ [exec.write.env](https://wg21.link/exec.write.env) `execution::write_env`: [`write_env.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/write_env.hpp)
+### ✅✅✅ [exec.unstoppable](https://wg21.link/exec.unstoppable) `execution::unstoppable`: [`unstoppable.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/unstoppable.hpp)
+### ✅✅✅ [exec.starts.on](https://wg21.link/exec.starts.on) `execution::starts_on`: [`starts_on.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/starts_on.hpp)
+### ✅✅✅ [exec.continues.on](https://wg21.link/exec.continues.on) `execution::continues_on`: [`continues_one.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/continues_one.hpp)
+### ✅✅✅ [exec.schedule.from](https://wg21.link/exec.schedule.from) `execution::schedule_from`: [`schedule_from.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/schedule_from.hpp)
+### ✅✅✅ [exec.on](https://wg21.link/exec.on) `execution::on`: [`on.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/on.hpp)
+### ✅✅✅ [exec.then](https://wg21.link/exec.then) `execution::then`, `execution::upon_error`, `execution::upon_stopped`: [`then.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/then.hpp)
+
+- 🔴 [exec.then p5](https://wg21.link/exec.then#5) verify check-types
+
+### ✅✅✅ [exec.let](https://wg21.link/exec.let) `execution::let_value`, `execution::let_error`, `execution::let_stopped`: [`let.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/let.hpp)
+
+- 🔴 [exec.let p9](https://wg21.link/exec.let#9) verify check-types
+
+### ✅✅🔴 [exec.bulk](https://wg21.link/exec.bulk) `execution::bulk`, `execution::bulk_chunked`, and `execution::bulk_unchunked`: [`bulk.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/bulk.hpp)
+
+- 🔴 [exec.bulk p6](https://wg21.link/exec.let#6) verify check-types
+- 🔴 [exec.bulk p8](https://wg21.link/exec.let#8) verify check-types
+
+### ✅✅✅ [exec.when.all](https://wg21.link/exec.when.all) `execution::when_all`: [`when_all.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/when_all.hpp)
+
+- 🔴 [exec.adapt.general p3.2](https://wg21.link/exec.adapt.general#3.2) verify single child env
+- 🔴 [exec.when.all p9](https://wg21.link/exec.when.all#9) check use of count-of
+
+### ✅✅✅ [exec.into.variant](https://wg21.link/exec.into.variant) `execution::into_variant`: [`into_variant.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/into_variant.hpp)
+### ✅✅🔴 [exec.stopped.opt](https://wg21.link/exec.stopped.opt) `execution::stopped_as_optional`: [`stopped_as_optional.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/stopped_as_optional.hpp)
+### ✅✅🔴 [exec.stopped.err](https://wg21.link/exec.stopped.err) `execution::stopped_as_error`: [`stopped_as_error.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/stopped_as_error.hpp)
+
+- 🚧 [exec.adapt.general p3.2](https://wg21.link/exec.adapt.general#3.2) verify single child env
+
+### ✅✅🔴 [exec.associate](https://wg21.link/exec.associate) `execution::associate`: [`associate.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/associate.hpp)
+
+- 🚧 [exec.adapt.general p3.2](https://wg21.link/exec.adapt.general#3.2) verify single child env
+
+### ✅✅🔴 [exec.stop.when](https://wg21.link/exec.stop.when) Exposition-only execution::stop_when: [`stop_when.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/stop_when.hpp)
+
+- 🚧 [exec.adapt.general p3.2](https://wg21.link/exec.adapt.general#3.2) verify single child env
+
+### ✅✅✅ [exec.spawn.future](https://wg21.link/exec.spawn.future) `execution::spawn_future`: [`spawn_future.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/spawn_future.hpp)
+
+- 🚧 [exec.adapt.general p3.2](https://wg21.link/exec.adapt.general#3.2) verify single child env
+
+## ✅✅🔴 [exec.consumers](https://wg21.link/exec.consumers) Sender consumers
+### ✅✅🔴 [exec.sync.wait](https://wg21.link/exec.sync.wait) `this_thread::sync_wait`: [`sync_wait.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/sync_wait.hpp)
+### ✅✅✅ [exec.sync.wait.var](https://wg21.link/exec.sync.wait.var) `this_thread::sync_with_variant`: [`sync_wait_with_variant.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/sync_wait_with_variant.hpp)
+### ✅✅🔴 [exec.spawn](https://wg21.link/exec.spawn) `execution::spawn`: [`spawn.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/spawn.hpp)
+## ✅✅🔴 [exec.cmplsig](https://wg21.link/exec.cmplsig) Completion signatures
+
+- ✅✅✅ [exec.cmplsig p4](https://wg21.link/exec.cmplsig#4) completion-signature: [`completion_signature.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/completion_signature.hpp)
+- ✅✅🔴 [exec.cmplsig p5](https://wg21.link/exec.cmplsig#5) indirect-meta-apply: [`indirect_meta_apply.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/indirect_meta_apply.hpp)
+- ✅✅🔴 [exec.cmplsig p5](https://wg21.link/exec.cmplsig#5) always-true: [`gather_signatures.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/gather_signatures.hpp)
+- ❎❎🔴 [exec.cmplsig p6](https://wg21.link/exec.cmplsig#6) META-APPLY: [`gather_signatures.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/gather_signatures.hpp)
+- ✅✅✅ [exec.cmplsig p6](https://wg21.link/exec.cmplsig#6) gather-signatures: [`gather_signatures.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/gather_signatures.hpp)
+- ✅🔴✅ [exec.cmplsig p8](https://wg21.link/exec.cmplsig#8) completion_signatures: [`completion_signatures.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/completion_signatures.hpp)
+- ✅✅✅ [exec.cmplsig p8](https://wg21.link/exec.cmplsig#8) value_types_of_t: [`value_types_of_t.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/value_types_of_t.hpp)
+- ✅✅✅ [exec.cmplsig p8](https://wg21.link/exec.cmplsig#8) error_types_of_t: [`error_types_of_t.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/error_types_of_t.hpp)
+- ✅✅✅ [exec.cmplsig p8](https://wg21.link/exec.cmplsig#8) sends_stopped: [`sends_stopped.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/sends_stopped.hpp)
+
+## ✅✅✅ [exec.envs](https://wg21.link/exec.envs) Queryable utilities
+### ✅✅✅ [exec.prop](https://wg21.link/exec.prop) Class template `prop`: [`prop.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/prop.hpp)
+### ✅✅✅ [exec.env](https://wg21.link/exec.env) Class template `env`: [`env.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/env.hpp)
+## ✅✅✅ [exec.ctx](https://wg21.link/exec.ctx) Execution contexts
+### ✅✅✅ [exec.run.loop](https://wg21.link/exec.run.loop) `execution::run_loop`
+#### ✅✅✅ [exec.run.loop.general](https://wg21.link/exec.run.loop.general) General: [`run_loop.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/run_loop.hpp)
+#### ✅✅❎ [exec.run.loop.types](https://wg21.link/exec.run.loop.types) Associated types
+#### ✅✅❎ [exec.run.loop.ctor](https://wg21.link/exec.run.loop.ctor) Constructor and destructor
+#### ✅✅❎ [exec.run.loop.members](https://wg21.link/exec.run.loop.members) Member functions
+## ✅✅🔴 [exec.coro.util](https://wg21.link/exec.coro.util) Coroutine utilities
+### ✅✅🔴 [exec.as.awaitable](https://wg21.link/exec.as.awaitable) `execution::as_awaitable`
+
+- ✅🔴✅ [exec.as.awaitable p1](https://wg21.link/exec.as.awaitable#1) awaitable-sender: [`awaitable_sender.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/awaitable_sender.hpp)
+- 🔴🔴🔴 [exec.as.awaitable p1](https://wg21.link/exec.as.awaitable#1) has-queryable-await-completion-adaptor: 🚨 this name appears to be is unused
+- ✅🔴✅ [exec.as.awaitable p2](https://wg21.link/exec.as.awaitable#2) sender-awaitable: : [`sender_awaitable.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/sender_awaitable.hpp)
+- ✅✅✅ [exec.as.awaitable p7](https://wg21.link/exec.as.awaitable#7) as_awaitable: : [`as_awaitable.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/as_awaitable.hpp)
+- ✅🔴✅ [exec.as.awaitable p8](https://wg21.link/exec.as.awaitable#8) adapt-for-await-completion: : [`as_awaitable.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/as_awaitable.hpp)
+
+### ✅✅🔴 [exec.with.awaitable.senders](https://wg21.link/exec.with.awaitable.senders) `execution::with_awaitable_senders`: [`with_awaitable_senders.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/with_awaitable_senders.hpp)
+### ✅✅ઑ [exec.affine](https://wg21.link/exec.affine) `execution::affine`: [`affine.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/affine.hpp)
+### ✅✅🔴 [exec.inline.scheduler](https://wg21.link/exec.inline.scheduler) `execution::inline_scheduler`: [`inline_scheduler.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/inline_scheduler.hpp)
+### ✅✅🔴 [exec.task.scheduler](https://wg21.link/exec.task.scheduler) `execution::task_scheduler`: [`task_scheduler.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/task_scheduler.hpp)
+### ✅✅🔴 [exec.task](https://wg21.link/exec.task) `execution::task`
+#### ✅✅🔴 [task.overview](https://wg21.link/task.overview) `task` overview
+#### ✅✅🔴 [task.class](https://wg21.link/task.class) Class template `task`
+#### ✅✅🔴 [task.members](https://wg21.link/task.members) `task` members
+#### ✅✅🔴 [task.state](https://wg21.link/task.state) Class template `task::state`
+#### ✅✅🔴 [task.promise](https://wg21.link/task.promise) Class template `task::promise_type`
+## 🔴🔴🔴 [exec.scope](https://wg21.link/exec.scope) Execution scope utilities
+### ✅🔴🔴 [exec.scope.concepts](https://wg21.link/exec.scope.concepts) Execution scope concepts
+
+- ✅🔴🔴 [exec.scope.concepts p1](https://wg21.link/exec.scope.concepts#1) `scope_association`: [`scope_association.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/scope_association.hpp)
+- ✅✅🔴 [exec.scope.concepts p3](https://wg21.link/exec.scope.concepts#3) `scope_token`: [`scope_token.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/scope_token.hpp)
+
+### 🔴🔴🔴 [exec.counting.scopes](https://wg21.link/exec.counting.scopes) Counting scopes
+#### 🔴🔴🔴 [exec.counting.scopes.general](https://wg21.link/exec.counting.scopes.general) General
+
+- ✅✅🔴 [exec.counting.scopes.general p3](https://wg21.link/exec.counting.scopes.general#3) scope-join-t: [`counting_scope_join.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/counting_scope_join.hpp)
+- ✅🔴🔴 [exec.counting.scopes.general p3](https://wg21.link/exec.counting.scopes.general#3) scope-state-type: [`counting_scope_join.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/counting_scope_base.hpp)
+- 🔴🔴🔴 [exec.counting.scopes.general p5](https://wg21.link/exec.counting.scopes.general#5) association-t
+
+#### ✅✅🔴 [exec.scope.simple.counting](https://wg21.link/exec.scope.simple.counting) Simple Counting Scope
+##### ✅✅🔴 [exec.scope.simple.counting.general](https://wg21.link/exec.scope.simple.counting.general) `simple_counting_scope`: [`simple_counting_scope.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/simple_counting_scope.hpp)
+##### ✅✅🔴 [exec.simple.counting.ctor](https://wg21.link/exec.simple.counting.ctor) Constructor and Destructor
+##### ✅✅🔴 [exec.simple.counting.mem](https://wg21.link/exec.simple.counting.mem) Members
+##### ✅✅🔴 [exec.simple.counting.token](https://wg21.link/exec.simple.counting.token) Token
+#### ✅✅🔴 [exec.scope.counting](https://wg21.link/exec.scope.counting) Counting Scope
+## ✅✅🔴 [exec.par.scheduler](https://wg21.link/exec.par.scheduler) Parallel scheduler: [`parallel_scheduler.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/parallel_scheduler.hpp)
+## ✅✅🔴 [exec.parschedrepl](https://wg21.link/exec.parschedrepl) Namespace `parallel_scheduler_replacement`
+### ❎❎❎ [exec.parschedrepl.general](https://wg21.link/exec.parschedrepl.general) General
+### ✅✅🔴 [exec.parschedrepl.recvproxy](https://wg21.link/exec.parschedrepl.recvproxy) Receiver proxies: [`parallel_scheduler_replacement.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/parallel_scheduler_replacement.hpp)
+### ✅✅🔴 [exec.parschedrepl.query](https://wg21.link/exec.parschedrepl.query) `query_parallel_scheduler_backend`: [`parallel_scheduler_replacement.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/parallel_scheduler_replacement.hpp)
+### ✅✅🔴 [exec.parschedrepl.psb](https://wg21.link/exec.parschedrepl.psb) Class `parallel_scheduler_backend`: [`parallel_scheduler_replacement.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/parallel_scheduler_replacement.hpp)
diff --git a/docs/overview.md b/docs/overview.md
index b6a98020..068ac448 100644
--- a/docs/overview.md
+++ b/docs/overview.md
@@ -173,7 +173,7 @@ Requirements for _Scheduler_:
sender<Sender>
-Senders represent asynchronous work. They may get composed from multiple senders to model a workflow. Senders can’t be run directly. Instead, they are passed to a which connects the sender to a receiver to produce an operation_state which may get started. When using senders to represent work the inner workings shouldn’t matter. They do become relevant when creating sender algorithms.
+Senders represent asynchronous work. They may get composed from multiple senders to model a workflow. Senders can’t be run directly. Instead, they are passed to a sender consumer which connects the sender to a receiver to produce an operation_state which may get started. When using senders to represent work the inner workings shouldn’t matter. They do become relevant when creating sender algorithms.
Requirements for _Sender_:
- The type _Sender_::sender_concept is an alias for `sender_tag` or a type derived thereof or _Sender_ is a suitable _awaitable_.
@@ -229,9 +229,9 @@ static_assert(std::execution::sender);
The concept sender_in<Sender, Env> tests whether _Sender_ is a sender, _Env_ is a destructible type, and std::execution::get_completion_signatures(_sender_, _env_) yields a specialization of std::execution::completion_signatures.
-sender_to<Sender, Receiver>
+sender-to<Sender, Receiver>
-The concept sender_to<Sender, Receiver> tests if std::execution::sender_in<_Sender_, std::execution::env_of_t<_Receiver_>> is true, and if _Receiver_ can receive all completion signals which can be sent by _Sender_, and if _Sender_ can be connected to _Receiver_.
+The concept sender-to<Sender, Receiver> tests if std::execution::sender_in<_Sender_, std::execution::env_of_t<_Receiver_>> is true, and if _Receiver_ can receive all completion signals which can be sent by _Sender_, and if _Sender_ can be connected to _Receiver_.
To determine if _Receiver_ can receive all completion signals from _Sender_ it checks that for each _Signature_ in std::execution::get_completion_signals(_sender_, std::declval<std::execution::env_of_t<_Receiver_>>()) the test std::execution::receiver_of<_Receiver_, _Signature_> yields true. To determine if _Sender_ can be connected to _Receiver_ the concept checks if connect(std::declval<_Sender_>(), std::declval<_Receiver_>) is a valid expression.
@@ -370,7 +370,7 @@ struct alloc_env {
forwarding_query(query) -> bool
-**Default**: `false`
+Default: `false`
The expression forwarding_query(query) is a `constexpr` query used to determine if the query query should be forwarded when wrapping an environment. The expression is required to be a core constant expression if query is a core constant expression.
@@ -378,7 +378,7 @@ The result of the expression is determined as follows:
- The result is the value of the expression
query.query(forwarding_query) if this expression is valid and `noexcept`.
- The result is
true if the type of query is publicly derived from forwarding_query.
- - Otherwise the result is
false.
+ - Otherwise the result is
false.
@@ -403,11 +403,11 @@ struct custom_t: forwarding_query_t {
};
```
-
+
get_env(queryable) -> env
-**Default**: `env<>`
+Default: `env<>`
The expression get_env(queryable) is used to get the environment env associated with queryable. To provide a non-default environment for a queryable a `get_env` member needs to be defined. If queryable doesn’t provide the get_env query an object of type env<> is returned.
The value of the expression is
@@ -437,7 +437,7 @@ Note that the `get_env` member is both `const` and `noexcept`.
get_allocator(env) -> allocator
-**Default**: none
+Default: none
The expression get_allocator(env) returns an allocator for any memory allocations in the respective context. If env doesn’t support this query any attempt to access it will result in a compilation error. The value of the expression get_allocator(env) is the result of as_const(env).query(get_allocator) if
@@ -464,15 +464,32 @@ struct alloc_env {
+get_completion_domain<Tag>(attrs) -> domain
+Default: none
+
+The expression get_completion_domain<Tag>(attrs) yields the completion domain for the completion signal Tag associated with the sender attrs. This query can be used to determine the domain a sender sender completes on for a given completion signal Tag by using get_completion_domain<Tag>(get_env(sender), ev...). The value of the expression is
+
+ - equivalent to
as_const(env).query(get_completion_domain<Tag>, ev...) if
+ Tag is one of the types set_value_t, set_error_t, or set_stopped_t and the expression is valid;
+ - equivalent to
as_const(env).query(get_completion_domain<Tag>) if
+ Tag is one of the types set_value_t, set_error_t, or set_stopped_t and the expression is valid;
+ - equivalent to
get_completion_domain<set_value_t>(get_env(sender), ev...) if Tag is void and the expression is valid;
+ - equivalent to
TRY-QUERY(get_completion_scheduler<Tag>(attrs, env...), get_completion_domain<set_value_t>, ev...) if this expression is well-formed;
+ - equivalent to
default_domain if scheduler<decltype(attrs)> is true and 0u < sizeof...(ev);
+ - ill-formed otherwise.
+
+Otherwise the expression is invalid.
+
+
get_completion_scheduler<Tag>(env) -> scheduler
-**Default**: none
+Default: none
-The expression get_complet_scheduler<Tag>(env) yields the completion scheduler for the completion signal Tag associated with env. This query can be used to determine the scheduler a sender sender completes on for a given completion signal Tag by using get_completion_scheduler<Tag>(get_env(sender)). The value of the expression is equivalent to as_const(env).query(get_completion_scheduler<Tag>) if
+The expression get_completion_scheduler<Tag>(env) yields the completion scheduler for the completion signal Tag associated with env. This query can be used to determine the scheduler a sender sender completes on for a given completion signal Tag by using get_completion_scheduler<Tag>(get_env(sender)). The value of the expression is equivalent to as_const(env).query(get_completion_scheduler<Tag>) if
- Tag is one of the types set_value_t, set_error_t, or set_stopped_t;
+ Tag is one of the types set_value_t, set_error_t, or set_stopped_t;
- this expression is valid;
- this expression is
noexcept;
- - the expression’s type satisfies
scheduler.
+ - the expression’s type satisfies
scheduler.
Otherwise the expression is invalid.
@@ -511,22 +528,23 @@ The expression get_delegation_scheduler(env) yields the sche
- this expression is valid;
- this expression is
noexcept;
- - the expression’s type satisfies
scheduler.
+ - the expression’s type satisfies
scheduler.
Otherwise the expression is invalid.
get_domain(env) -> domain
-The expression get_domain(env) yields the domain associated with env. The value of the expression is equivalent to as_const(env).query(get_domain) if
+The expression get_domain(env) yields the domain associated with env. The value of the expression is equivalent to
- - this expression is valid;
- - this expression is
noexcept.
+ auto(as_const(env).query(get_domain)) if this expression is valid;
+ - otherwise,
get_completion_domain<set_value_t>(get_scheduler(env), HIDE-SCHED(env)) if this expression is valid;
+ default_domain() (except env is evaluated).
Otherwise the expression is invalid.
get_forward_progress_guarantee(scheduler) -> forward_progress_guarantee
-The expression get_forward_progress_guarantee(scheduler) yields the forward progress guarantee of the scheduler’s execution agent. The value of the expression is equivalent to as_const(env).query(get_scheduler) if
+The expression get_forward_progress_guarantee(scheduler) yields the forward progress guarantee of the scheduler’s execution agent. The value of the expression is equivalent to as_const(env).query(get_forward_progress_guarantee) if
- this expression is valid;
- this expression is
noexcept;
@@ -545,6 +563,20 @@ The expression get_scheduler(env) yields the scheduler assoc
Otherwise the expression is invalid.
+get_start_scheduler(env) -> scheduler
+The expression get_start_scheduler(env) yields the scheduler associated with env. The value of the expression is equivalent to as_const(env).query(get_scheduler) if
+
+ - this expression is valid;
+ - this expression is
noexcept;
+ - the expression’s type satisfies
scheduler.
+
+Otherwise the expression is invalid.
+
+If the expression get_start_scheduler(get_env(rcvr))
+is well-formed it should yield the scheduler the operation state resulting
+from connect(sndr>, rcvr) gets started on.
+
+
get_stop_token(env) -> stoppable_token
The expression get_stop_token(env) yields the stop token associated with env. The value is the result of the expression as_const(env).query(get_stop_token) if
@@ -615,13 +647,13 @@ The expression just_stopped() creates a sender which sends a comple
read_env(query) -> sender-of<set_value_t(query-result)>
The expression read_env(query) creates a sender which sends the result of querying query the environment of the receiver it gets connected to on the `set_value` channel when started. Put differently, it calls set_value(move(receiver), query(get_env(receiver))). For example, in a coroutine it may be useful to extra the stop token associated with the coroutine which can be done using read_env:
-```c++\
+```c++
auto token = co_await read_env(get_stop_token);
```
Completions
-set_value_t(decltype(query(get_env(receiver))))
+set_value_t(decltype(query(get_env(receiver))))
@@ -632,7 +664,7 @@ The expression schedule(scheduler) creates a sender which up
set_value_t() upon success
set_error_t(Error) upon failure if scheduler may fail
-set_stopped_t() upon cancellation if scheduler supports cancellation
+set_stopped_t() upon cancellation if scheduler supports cancellation
@@ -646,8 +678,19 @@ a sender which completes on the same scheduler it was started on, even if
The primary use of affine is implementing scheduler affinity for task.
+
+
+associate(sndr, token) -> sender
+
+
-`bulk`
+bulk(sndr, policy, shape, fun) -> sender
+
+
+bulk_chunked(sndr, policy, shape, fun) -> sender
+
+
+bulk_unchunked(sndr, policy, shape, fun) -> sender
continues_on(sender, scheduler) -> sender-of<completions-of(sender) + completions-of(schedule(scheduler))>
@@ -665,83 +708,423 @@ The expression into_variant(sender) creates a sender which t
let_error(upstream, fun) -> sender
+The expression let_error(upstream, fun) yields a sender sndr which uses an error completion (set_error) of upstream as an argument to invoke fun which has to return another sender inner-sndr and the completion of inner-sndr becomes the completion of sndr. If this invocation results in an exception sndr completes with an error completion the result of std::current_exception. If upstream completes successfully (set_value) or with a cancellation (set_stopped) this completion becomes the completion of sndr.
let_stopped(upstream, fun) -> sender
+The expression let_stopped(upstream, fun) yields a sender sndr which uses a cancellation completion (set_stopped) of upstream to invoke fun which has to return another sender inner-sndr and the completion of inner-sndr becomes the completion of sndr. If this invocation results in an exception sndr completes with an error completion the result of std::current_exception. If upstream completes successfully (set_value) or with an error (set_error) this completion becomes the completion of sndr.
let_value(upstream, fun) -> sender
+The expression let_value(upstream, fun) yields a sender sndr which uses a successful completion (set_value) of upstream as arguments to invoke fun which has to return another sender inner-sndr and the completion of inner-sndr becomes the completion of sndr. If this invocation results in an exception sndr completes with an error completion the result of std::current_exception. If upstream completes with a cancellation (set_stopped) or with an error (set_error) this completion becomes the completion of sndr.
+
+
+on(_sched_, _sndr_), on(_sndr, _sched_, _closure_)
+The on algorithm is a pipeable sender adaptor. Let on-sender be
+
+ _sndr_ when the form on(_sched_, _sndr_) is used;
+ _closure_(_sndr_) when the form on(_sndr_, _sched_, _closure_) is used.
+
+The sender on-sndr is started on _sched_'s execution context.
+The on algorithm completes on the original scheduler (obtained using get_start_scheduler) with the result of the on-sndr.
-on(_sched_, _sndr_)
+schedule_from(sender) -> sender
+The expression schedule_from(sender) yields a
+sender which behaves likes sender. The purpose of the schedule_from
+is to allow schedulers to customize the way how to transition off the execution context.
-schedule_from(scheduler, sender) -> sender
+spawn_future(sndr, token) -> sender
`split`
starts_on(scheduler, sender) -> sender
+The expression starts_on(scheduler, sender) yields a sender
+which starts sender on the scheduler's context, i.e.,
+it starts schedule(scheduler) and then starts sender
+where the scheduler's sender completes.
-`stopped_as_error`
+stopped_as_error(sndr)
-`stopped_as_optional`
+stopped_as_optional(sndr)
then(upstream, fun) -> sender
+The expression then(upstream, fun) yields a sender sndr which on successful competion of upstream (set_value) calls fun with the arguments passed to set_value and yields the function return as its own result. If the function throws or upstream completes with an error (set_error) the exception or the error becomes sndr's result. If upstream completes with a cancellation (set_stopped).
+
+
+unstoppable(sender) -> sender
+The expression unstoppable(sender) yields a sender which
+passes its receiver's environment to sender except that
+the get_stop_token query return never_stop_token:
+the resulting sender behaves like sender except that it
+is unstoppable.
upon_error(upstream, fun) -> sender
+The expression upon_error(upstream, fun) yields a sender sndr which passes an error completion (set_error) of upstream to fun and uses this result of this function invocation for its own successful (set_value) completion. If the function invocation throws std::current_exception() becomes sndr's error (set_error) completion. The success (set_value) and cancellation (set_stopped) completions of upstream are forwarded.
upon_stopped(upstream, fun) -> sender
+The expression upon_stopped(upstream, fun) yields a sender sndr which turns a cancellation completion (set_stopped) result of upstream to fun and uses this result of this function invocation for its own successful (set_value) completion. If the function invocation throws std::current_exception() becomes sndr's error (set_error) completion. The success (set_value) and error (set_error) completions of upstream are forwarded.
when_all(sender...) -> sender
+The expression when_all(sender...) yields a sender sndr which completes successfully (set_value) when all nested senders sender... completed successfully using the results of the nested senders in order. If any of the senders completes with an error (set_error) or a cancellation (set_stopped) the first such completion becomes the completion of sndr once all nested senders completed. A stop is requested for the stop source(s) whose token was passed to the nested senders.
when_all_with_variant(sender...) -> sender
write_env(sender, env) -> sender
+The expression write_env(sender, env) creates a sender
+which passes a receiver to sender which combines the environment
+env with the environment from the receiver's environment. The
+queries from env take precedence over those from the receiver's environment.
### Sender Consumers
-- sync_wait(sender) -> std::optional<std::tuple<T...>>
+
+sync_wait(sender) -> std::optional<std::tuple<T...>>
+
+
+sync_wait_with_variant(sender) -> std::optional<std::variant<std::tuple<T...>...>>
+
+
+spawn(sndr, token) -> void
+
## Helpers
-- `as_awaitable`
+
+adapt-for-await-completion(s)
+The expression is equivalent to get_await_completion_adaptor(get_env(s))(s) except
+that s is evaluated only once.
+
+
+
+as_awaitable(expr, promise)
+The expression as_awaitable(expr, promise) tries to
+create an awaitable from expr and promise. It
+tries the following transformations:
+
+expr.as_awaitable(promise) if this expression is well-formed; otherwise
+adapt-for-await-completion(transform_sender(expr, get_env(promise))) if this expression is well-formed; otherwise
+expr if GET-AWAITER(expr) is an awaiter for promise; otherwise.
+sender-awaitable{adapt-for-await-completion(transform_sender(expr, get_env(promise))), promise} if this expression is well-formed; otherwise
+expr
+
+
+
- `with_awaitable_sender`
- `apply_sender`
-- `completion_signatures`
+
+completion_signatures<Sig...>
+The template specialization completion_signatures<Sig...> is a list
+of completion signatures used to declare and compute the result types of senders.
+
+It has two exposition-only members template:
+
+count-of(tag) providing a constant expression with the count of tag completions.
+for-each(fun) invoking fun with a pointer to each of the completion signatures Sig.... The function is used to verify the completion signature types.
+
+
- `completion_signatures_t`
- `connect_result_t`
- `default_domain`
-- `env<T...>`
+
+env<Ev...>
+The expression env(ev...) creates an environment by combining the environments
+ev.... If multiple of the environments support an identical query, the first
+one from the first environment is used.
+
- `env_of_t`
-- `error_types_of_t`
+
+error_types_of_t<Sndr, Env = env<>, Variant = variant-or-empty>
+The template specialization error_types_of_t<<sndr, Env, Variant> gets Sndr error completion signatures when using the environment Env. The results is represented as a Variant<E... where E... is the list of argument types to the completion signatures.
+
- `fwd_env`
- `operation_state_tag`
+
+prop<Query, Value>
+The expression prop(query, value) create an object which can
+be queried for query query which results in value.
+
+
- `receiver_tag`
-- `run_loop`
+
+run_loop
+The class run_loop provides a scheduler to execute work on. It is used
+to implement sync_wait(sndr). The public methods on
+an object loop of type run_loop are:
+
+loop.get_scheduler() to get a scheduler scheduling work on loop.
+loop.finish() to request loop to exit processing work items. Note that run_loop doesn't maintain a stop source, i.e., when this operation is invoked the work doesn't get cancelled.
+loop.run() to have the current thread executed work items scheduled on loop. The thread will continue processing work items as long as loop.finish() wasn't called or there is work scheduled on loop.
+
+
+
- `scheduler_tag`
- `schedule_result_t`
- `sender_adaptor_closure`
- `sender_tag`
+
+
+bool sends_stopped<Sndr, Env = env<>>
+The Boolean variable sends_stopped<Sndr, Env> is true if the completion signatures of Sndr when using the environment Env contain a cancellation signature (set_stopped_t()).
+
+
- `stop_token_of_t`
-- `tag_of_t`
+
+
+tag_of_t<Sndr>
+
+ - if
auto&&[tag, data, children...] = sndr; is well-formed the type decltype(auto(tag));
+ - otherwise ill-formed.
+
+
+
- `transform_sender`
- `transform_completion_signatures`
- `transform_completion_signatures_of`
-- `value_types_of_t`
+
+value_types_of_t<Sndr, Env = env<>, Tuple = decayed-tuple, Variant = variant-or-empty>
+The template specialization value_types_of_t<Sndr, Env, Tuple, Variant> gets Sndr success completion signatures when using the environment Env. The resulting type is a Variant of Tuple elements where each Tuple represents the argument types of one of the value completion signatures.
+
## Stop Token
- `never_stop_token`
- `stop_token`
- `inplace_stop_token`
+
+## Exposition Only
+
+
+as-except-ptr(err)
+Turns err smartly into an exception_ptr:
+
+- if
same_as<decay_t<decltype(err)>, exception_ptr> ⇒ err
+- else if
same_as<decay_t<decltype(err)>, error_code> ⇒ make_exception_ptr(system_error(err))
+- else
make_exception_ptr(err)
+
+
+
+
+awaitable-sender<Sndr, Promise>
+The concept check awaitable-sender<Sndr, Promise> determines
+if the Sndr could work with the environment provided by Promise
+and if Promise supports a suitable unhandled_stopped() method.
+
+
+
+concept class-type<T>
+Determines if the type T is a decayed class type:
+decays-to<T, T> && is_class_v<T>
+
+
+
+COMMON-DOMAIN(domains...)
+The expression COMMON-DOMAIN(domains...) is
+
+
+ common_type_t<decltype(auto(domains))...>() if this expression is valid
+ indeterminate_domain<decltype(auto(domains))...>() with duplicates removed from the template arguments
+
+
+
+
+COMPL-DOMAIN<Tag>(sndr, ev...)
+The expression COMPL-DOMAIN<Tag>(sndr, ev...) gets sndrs completion
+domain given the optional environment ev...:
+
+
+ get_completion_domain(get_env(sndr), ev..) if this expression is well-formed,
+ indeterminate_domain() otherwise.
+
+
+Note: it seems this exposition-only name is actually unused!
+
+
+
+concept completion-signature<Signature>
+This concept determines if the type Signature is a completion signature, i.e.,
+if it has one of these three forms:
+
+set_value_t(T...)
+set_error_t(T)
+set_stopped_t()
+
+
+
+
+concept decays-to<From, To>
+Determines if To is the result of decaying the type From:
+same_as<decay_t<From>, To>
+
+
+
+FWD-ENV(env)
+The expression FWD-ENV(env) yields a queryable object q supporting only forwardable queries. Let qry be a query object and a... be a possibly emnpty pack of arguments. Then q.query(qry, a...) is
+
+ - equivalent to
env.query(qry, a...) if forwarding_query(qry) is true
+ - ill-formed if
forwarding_query(qry) is false
+
+
+
+
+FWD-ENV-T(Env)
+The type FWD-ENV-T(Env) is decltype(FWD-ENV(decl_val<Env>())).
+
+
+
+gather-signatures<Tag, Signatures, Tuple, Variant>
+The template specializaton gather-signatures<Tag, Signatures, Tuple, Variant> represents the completion signatures in the type list Signatures using Tag (one of set_value_t, set_error_t, or set_stopped_t) as a Variant of Tuples. Each Tuple has the element types of of one of the matching completion signatures.
+
+
+
+concept has-completions<Rcvr, Completions>
+This concept determines if an object of type Rcvr supports ech of the completion signatures in Completions.
+
+
+
+HIDE-SCHED(q)
+For a query object tag and arguments a... the
+expressions HIDE-SCHED(q).query(tag, a...) is
+
+ - undefined if
decay_t<decltype(tag)> is get_scheduler_t or get_domain_t
+ - equivalent to
q.query(tag, a...) otherwise
+
+
+
+infallible-scheduler<Sched>
+
+Determines if Sched is a scheduler (i.e., scheduler<Sched> is true)
+and if Sched's sender has only a set_value_t() completion signature when used with
+an environment with an unstoppable_token<Tok> stop token Tok. If the
+stop token Tok is not unstoppable_token<Tok> the completion signatures
+can include a set_stopped_t() completion signature in addition to the set_value_t() completion signature.
+
+
+
+JOIN-ENV(ev1, ev2)
+The expression JOIN-ENV(ev1, ev2) yields a queryable object env such that for a query qry and a pack of arguments a... the result of the expression env.query(qry, a...) is
+
+
+ equivalent to ev1.query(qry, a...) if this expression is well-formed, otherwise
+ equivalent to ev2.query(qry, a...) if this expression is well-formed, otherwise
+ - ill-formed
+
+
+
+
+
+make-sender(tag, data = empty{}, child...)
+Creates and object of type basic-sender<decltype(tag), decay_t<decltype(data)>, decay_t<decltype(child)>...>
+that's direct initialized with the forwarded arguments.
+
+
+
+MAKE-ENV(qry, value)
+The expression MAKE-ENV(qry, value) creates a queryable object env such that for a pack of arguments a ... the expression env.query(qry, a...) yields value.
+
+
+
+constexpr bool MATCHING-SIG<F1, F2>
+Determines if the two function signatures F1 and F2 match:
+
+If same_as<F1, R1(A1...)> and same_as<F2, R2(A2...)> then
+MATCHING-SIG<F1, F2> == same_as<R1(A1&&...), R2(A2&&...)>.
+
+
+
+concept movable-value<T>
+Determines if objects of type T are movable, non-array values:
+move_constructible<decay_t<T>> && constructible_from<decay_t<T>> && (!is_array_v<remove_reference_t<T>>)
+
+
+
+struct product-type<T...>
+The type product-type<T...> is a tuple-like type.
+Instead of constructors it supports only direct initialization, allowing it to hold
+inplace constructed elements. It supports p.get<I>() and p.apply(fun)
+member functions.
+
+
+
+concept queryable<T>
+Determines if objects of type T are queryable:
+destructible<T>. The semantic implication is
+that using the queryable object with query objects behave as required.
+
+
+
+query-with-default(tag, env, value)
+Returns
+
+ tag(env) if this expression is well-formed
+ value otherwise
+
+
+
+
+concept receiver-of<Rcvr, Signatures>
+This concept determines if an object of type Rcvr is a receiver (i.e., receiver<Rcvr> is true) and supports each of the completion signatures in Signatures.
+
+
+
+SCHED-ENV(sch)
+The expression SCHED-ENV(sch) yields a queryable o such that
+
+ get_start_scheduler(o) is equivalent to get_start_scheduler(get_env(o))
+ get_domain(o) is equivalent to get_start_scheduler(get_env(o))
+
+
+
+
+sender-awaitable<Sndr, Promise>
+The specialization sender-awaitable<Sndr, Promise> is an awaiter implemented by getting the result of the Sndr completion.
+
+
+
+concept single-sender<Sndr, Env...>
+The test single-sender<Sndr, Env...> is true if Sndr has exactly one successful completion signature when using an environment of type Env....
+
+
+
+single-sender-value-type<Sndr, Env...>
+The type single-sender-value-type<Sndr, Env...> is defined if Sndr has exactly one successful completion signature set_value_t(T...) when using an environment of type Env.... The type is
+
+T... if 1u == sizeof...(T) (i.e., there is one element);
+void if 0u == sizeof...(T) (i.e., there is no element);
+std::tuple<T...> otherwise.
+
+
+
+
+stop-when(sndr, token)
+
+
+
+TRY-QUERY(q, tag, a...)
+Tries to apply the query tag to the queryable object q:
+if passing the arguments a... is valid passes these arguments (AS-CONST(q).query(tag, a...)), otherwise
+queries q for tag without the arguments (AS-CONST(q).query(tag)), although the
+arguments are evaluated.
+
+
+
+concept valid-completion-for<Signature, Rcvr>
+This concept determines if an object of type Rcvr supports the completion signature Signature.
+
+
+
+concept valid-specialization<T, Args...>
+This concept determines the class template T can be specialized with arguments Args..., i.e., if T<Args...> is valid.
+
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index effe9928..19b8669a 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -19,6 +19,15 @@ endif()
set(TODO stop_token) #-dk:TODO including that causes a linker error
set(TODO suspend_never) #-dk:TODO including that causes ASAN errors
+set(TODO
+ intro_1_hello_world
+ intro_2_hello_async
+ playground
+ sender_demo
+ stackoverflow
+ stopping
+ when_all_cancel
+)
set(EXAMPLES
allocator
@@ -26,14 +35,7 @@ set(EXAMPLES
doc_just_error
doc_just_stopped
inspect
- intro_1_hello_world
- intro_2_hello_async
intro_5_consumer
- playground
- sender_demo
- stackoverflow
- stopping
- when_all_cancel
)
if(BEMAN_USE_MODULES)
diff --git a/examples/allocator.cpp b/examples/allocator.cpp
index b14ed5f0..39ed045c 100644
--- a/examples/allocator.cpp
+++ b/examples/allocator.cpp
@@ -1,12 +1,17 @@
// examples/allocator.cpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#include
+#ifdef BEMAN_HAS_IMPORT_STD
+import std;
+#else
#include
#include
#include
#include
#include
#include
+#endif
#ifdef BEMAN_HAS_MODULES
import beman.execution;
#else
diff --git a/examples/doc_just.cpp b/examples/doc_just.cpp
index 4979b153..4fdeb9dd 100644
--- a/examples/doc_just.cpp
+++ b/examples/doc_just.cpp
@@ -1,8 +1,13 @@
// examples/doc_just.cpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-#include
+#include
+#ifdef BEMAN_HAS_IMPORT_STD
+import std;
+#else
#include
+#endif
+#include
#ifdef BEMAN_HAS_MODULES
import beman.execution;
#else
diff --git a/examples/doc_just_error.cpp b/examples/doc_just_error.cpp
index 48a9f98f..72367e0d 100644
--- a/examples/doc_just_error.cpp
+++ b/examples/doc_just_error.cpp
@@ -1,7 +1,12 @@
// examples/doc_just_error.cpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#include
+#ifdef BEMAN_HAS_IMPORT_STD
+import std;
+#else
#include
+#endif
#include
#ifdef BEMAN_HAS_MODULES
import beman.execution;
diff --git a/examples/doc_just_stopped.cpp b/examples/doc_just_stopped.cpp
index 12971e32..b8d61fea 100644
--- a/examples/doc_just_stopped.cpp
+++ b/examples/doc_just_stopped.cpp
@@ -1,7 +1,12 @@
// examples/doc_just_stopped.cpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#include
+#ifdef BEMAN_HAS_IMPORT_STD
+import std;
+#else
#include
+#endif
#include
#ifdef BEMAN_HAS_MODULES
import beman.execution;
diff --git a/examples/inspect.cpp b/examples/inspect.cpp
index 92d6ade2..fafbe406 100644
--- a/examples/inspect.cpp
+++ b/examples/inspect.cpp
@@ -1,6 +1,10 @@
// examples/inspectc.pp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#include
+#ifdef BEMAN_HAS_IMPORT_STD
+import std;
+#else
#include
#include
#include
@@ -8,6 +12,7 @@
#include
#include
#include
+#endif
#ifdef BEMAN_HAS_MODULES
import beman.execution;
#else
diff --git a/examples/intro_1_hello_world.cpp b/examples/intro_1_hello_world.cpp
index aacdd25d..a24d1b85 100644
--- a/examples/intro_1_hello_world.cpp
+++ b/examples/intro_1_hello_world.cpp
@@ -1,11 +1,16 @@
// examples/intro_1_hello_world.cpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#include
+#ifdef BEMAN_HAS_IMPORT_STD
+import std;
+#else
#include
#include
#include
#include
#include
+#endif
#ifdef BEMAN_HAS_MODULES
import beman.execution;
#else
@@ -20,7 +25,7 @@ using namespace std::string_literals;
int main() {
// clang-format off
- auto [result] =
+ //auto [result] =
ex::sync_wait(
ex::when_all(
ex::just("hello, "s),
@@ -30,5 +35,5 @@ int main() {
;
// clang-format on
- std::cout << result << '\n';
+ // std::cout << result << '\n';
}
diff --git a/examples/intro_2_hello_async.cpp b/examples/intro_2_hello_async.cpp
index e61a4384..d46041b0 100644
--- a/examples/intro_2_hello_async.cpp
+++ b/examples/intro_2_hello_async.cpp
@@ -1,12 +1,17 @@
// examples/intro_2_hello_async.cpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#include
+#ifdef BEMAN_HAS_IMPORT_STD
+import std;
+#else
#include
#include
#include
#include
#include
#include
+#endif
#ifdef BEMAN_HAS_MODULES
import beman.execution;
#else
diff --git a/examples/intro_5_consumer.cpp b/examples/intro_5_consumer.cpp
index 4cabd6eb..371bae8a 100644
--- a/examples/intro_5_consumer.cpp
+++ b/examples/intro_5_consumer.cpp
@@ -1,6 +1,10 @@
// examples/intro_5_consumer.cpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#include
+#ifdef BEMAN_HAS_IMPORT_STD
+import std;
+#else
#include
#include
//-dk:TODO restore if that actually works #include
@@ -9,6 +13,7 @@
#include
#include
#include
+#endif
#ifdef BEMAN_HAS_MODULES
import beman.execution;
import beman.execution.detail;
diff --git a/examples/modules_and_header.cpp b/examples/modules_and_header.cpp
index f7ba4c5b..bcd49cf0 100644
--- a/examples/modules_and_header.cpp
+++ b/examples/modules_and_header.cpp
@@ -1,7 +1,12 @@
// examples/modules_and_header.cpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#include
+#ifdef BEMAN_HAS_IMPORT_STD
+import std;
+#else
#include
+#endif
import beman.execution;
namespace ex = beman::execution;
diff --git a/examples/playground.cpp b/examples/playground.cpp
index 2412f1b6..a3133451 100644
--- a/examples/playground.cpp
+++ b/examples/playground.cpp
@@ -1,10 +1,15 @@
// examples/playground.cpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#include
+#ifdef BEMAN_HAS_IMPORT_STD
+import std;
+#else
#include
#include
#include
#include
+#endif
#ifdef BEMAN_HAS_MODULES
import beman.execution;
#else
@@ -16,8 +21,9 @@ namespace ex = ::beman::execution;
// ----------------------------------------------------------------------------
int main() {
- auto [result] = ex::sync_wait(ex::when_all(ex::just(std::string("hello, ")), ex::just(std::string("world"))) |
- ex::then([](const auto& s1, const auto& s2) { return s1 + s2; }))
- .value_or(std::tuple(std::string("oops")));
- std::cout << "result='" << result << "'\n";
+ // auto [result] =
+ ex::sync_wait(ex::when_all(ex::just(std::string("hello, ")), ex::just(std::string("world"))) |
+ ex::then([](const auto& s1, const auto& s2) { return s1 + s2; }))
+ .value_or(std::tuple(std::string("oops")));
+ // std::cout << "result='" << result << "'\n";
}
diff --git a/examples/sender_demo.cpp b/examples/sender_demo.cpp
index a9a4e63f..ee047fac 100644
--- a/examples/sender_demo.cpp
+++ b/examples/sender_demo.cpp
@@ -1,12 +1,17 @@
// examples/sender_demo.cpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#include
+#ifdef BEMAN_HAS_IMPORT_STD
+import std;
+#else
#include
#include
#include
#include
#include
#include
+#endif
#ifdef BEMAN_HAS_MODULES
import beman.execution;
import beman.execution.detail;
diff --git a/examples/stackoverflow.cpp b/examples/stackoverflow.cpp
index 5d25f1ac..275886d1 100644
--- a/examples/stackoverflow.cpp
+++ b/examples/stackoverflow.cpp
@@ -1,11 +1,16 @@
// examples/stackoverflow.cpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#include
+#ifdef BEMAN_HAS_IMPORT_STD
+import std;
+#else
#include
#include
#include
#include
#include
+#endif
#ifdef BEMAN_HAS_MODULES
import beman.execution;
#else
diff --git a/examples/stop_token.cpp b/examples/stop_token.cpp
index c967e377..e0bae843 100644
--- a/examples/stop_token.cpp
+++ b/examples/stop_token.cpp
@@ -1,12 +1,17 @@
// examples/stop_token.cpp
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#include
+#ifdef BEMAN_HAS_IMPORT_STD
+import std;
+#else
#include
#include
#include
#include
#include
#include
+#endif
#ifdef BEMAN_HAS_MODULES
import beman.execution;
#else
diff --git a/examples/stopping.cpp b/examples/stopping.cpp
index 1816df20..4232e069 100644
--- a/examples/stopping.cpp
+++ b/examples/stopping.cpp
@@ -6,11 +6,16 @@
// which gets started in a thread. To stop this thread
// the corresponding stop source is requested to stop.
+#include
+#ifdef BEMAN_HAS_IMPORT_STD
+import std;
+#else
#include
#include
#include
#include
#include
+#endif
#ifdef BEMAN_HAS_MODULES
import beman.execution;
#else
@@ -19,6 +24,7 @@ import beman.execution;
#endif
using namespace std::chrono;
+using namespace std::chrono_literals;
namespace ex = beman::execution;
// ----------------------------------------------------------------------------
diff --git a/examples/when_all_cancel.cpp b/examples/when_all_cancel.cpp
index 6c8d58e6..20df52b4 100644
--- a/examples/when_all_cancel.cpp
+++ b/examples/when_all_cancel.cpp
@@ -1,6 +1,10 @@
// examples/when_all_cancel.cpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#include
+#ifdef BEMAN_HAS_IMPORT_STD
+import std;
+#else
#include
#include
#include
@@ -10,6 +14,7 @@
#include
#include
#include
+#endif
#ifdef BEMAN_HAS_MODULES
import beman.execution;
#else
diff --git a/include/beman/execution/detail/as_except_ptr.hpp b/include/beman/execution/detail/as_except_ptr.hpp
index 5f9ee471..4e2914d0 100644
--- a/include/beman/execution/detail/as_except_ptr.hpp
+++ b/include/beman/execution/detail/as_except_ptr.hpp
@@ -25,6 +25,7 @@ namespace beman::execution::detail {
* \internal
*/
template
+//-dk:TODO add a proper precondition
decltype(auto) as_except_ptr(Error&& error) {
if constexpr (::std::same_as<::std::exception_ptr, ::std::decay_t>) {
return ::std::forward(error);
diff --git a/include/beman/execution/detail/call_with_default.hpp b/include/beman/execution/detail/call_with_default.hpp
new file mode 100644
index 00000000..5be42729
--- /dev/null
+++ b/include/beman/execution/detail/call_with_default.hpp
@@ -0,0 +1,33 @@
+// include/beman/execution/detail/call_with_default.hpp -*-C++-*-
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#ifndef INCLUDED_INCLUDE_BEMAN_EXECUTION_DETAIL_CALL_WITH_DEFAULT
+#define INCLUDED_INCLUDE_BEMAN_EXECUTION_DETAIL_CALL_WITH_DEFAULT
+
+#include
+#ifdef BEMAN_HAS_IMPORT_STD
+import std;
+#else
+#include
+#endif
+
+// ----------------------------------------------------------------------------
+
+namespace beman::execution::detail {
+template
+ requires requires(const Tag& tag, const Env& env, Args&&... args) { tag(env, ::std::forward(args)...); }
+constexpr auto call_with_default(Tag, DefaultValue&&, const Env& env, Args&&... args) noexcept(
+ noexcept(Tag()(env, ::std::forward(args)...))) -> decltype(auto) {
+ return Tag()(env, ::std::forward(args)...);
+}
+
+template
+constexpr auto call_with_default(Tag, DefaultValue&& value, const Env&, const Args&...) noexcept(
+ noexcept(static_cast(std::forward(value)))) -> decltype(auto) {
+ return static_cast(std::forward(value));
+}
+} // namespace beman::execution::detail
+
+// ----------------------------------------------------------------------------
+
+#endif
diff --git a/include/beman/execution/detail/compl_domain.hpp b/include/beman/execution/detail/compl_domain.hpp
index e9ed7d2d..c69dca0b 100644
--- a/include/beman/execution/detail/compl_domain.hpp
+++ b/include/beman/execution/detail/compl_domain.hpp
@@ -11,11 +11,11 @@ import std;
#include
#endif
#ifdef BEMAN_HAS_MODULES
-import beman.execution.detail.default_domain;
+import beman.execution.detail.indeterminate_domain;
import beman.execution.detail.get_completion_domain;
import beman.execution.detail.get_env;
#else
-#include
+#include
#include
#include
#endif
@@ -30,7 +30,7 @@ constexpr auto compl_domain(const Sndr& sndr, const Envs&... envs) noexcept {
}) {
return ::beman::execution::get_completion_domain(::beman::execution::get_env(sndr), envs...);
} else {
- return ::beman::execution::default_domain();
+ return ::beman::execution::indeterminate_domain();
}
}
diff --git a/include/beman/execution/detail/completion_signatures.hpp b/include/beman/execution/detail/completion_signatures.hpp
index 39da7195..d27f6380 100644
--- a/include/beman/execution/detail/completion_signatures.hpp
+++ b/include/beman/execution/detail/completion_signatures.hpp
@@ -29,8 +29,23 @@ namespace beman::execution {
* any specializaion are empty. Objects may be created to return them from
* functions used for type computations like get_completion_signatures(sender, env).
*/
-template <::beman::execution::detail::completion_signature...>
-struct completion_signatures {};
+template <::beman::execution::detail::completion_signature... Signatures>
+struct completion_signatures {
+ template
+ struct completion_signatures_tag;
+ template
+ struct completion_signatures_tag {
+ using type = Tag;
+ };
+ template
+ static constexpr bool count_of(Tag) {
+ return (::std::same_as::type, Tag> + ... + 0);
+ }
+ template
+ static constexpr void for_each(Fun&& fun) {
+ (fun(static_cast(nullptr)), ...);
+ }
+};
} // namespace beman::execution
// ----------------------------------------------------------------------------
diff --git a/include/beman/execution/detail/data_type.hpp b/include/beman/execution/detail/data_type.hpp
new file mode 100644
index 00000000..a4ffc7a8
--- /dev/null
+++ b/include/beman/execution/detail/data_type.hpp
@@ -0,0 +1,23 @@
+// include/beman/execution/detail/data_type.hpp -*-C++-*-
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#ifndef INCLUDED_INCLUDE_BEMAN_EXECUTION_DETAIL_DATA_TYPE
+#define INCLUDED_INCLUDE_BEMAN_EXECUTION_DETAIL_DATA_TYPE
+
+#include
+#ifdef BEMAN_HAS_IMPORT_STD
+import std;
+#else
+#include
+#endif
+
+// ----------------------------------------------------------------------------
+
+namespace beman::execution::detail {
+template
+using data_type = decltype(::std::declval().template get<1>());
+}
+
+// ----------------------------------------------------------------------------
+
+#endif
diff --git a/include/beman/execution/detail/default_impls.hpp b/include/beman/execution/detail/default_impls.hpp
index a22aa866..7b85b999 100644
--- a/include/beman/execution/detail/default_impls.hpp
+++ b/include/beman/execution/detail/default_impls.hpp
@@ -89,6 +89,9 @@ struct default_impls {
}
};
static constexpr auto complete = complete_impl{};
+
+ template
+ static consteval auto check_types() -> void {}
};
} // namespace beman::execution::detail
diff --git a/include/beman/execution/detail/fwd_env.hpp b/include/beman/execution/detail/fwd_env.hpp
index 8cc7a291..eb332168 100644
--- a/include/beman/execution/detail/fwd_env.hpp
+++ b/include/beman/execution/detail/fwd_env.hpp
@@ -49,6 +49,9 @@ class fwd_env {
};
template
fwd_env(Env&&) -> fwd_env;
+
+template //-dk:TODO detail export
+using fwd_env_t = decltype(::beman::execution::detail::fwd_env(::std::declval()));
} // namespace beman::execution::detail
// ----------------------------------------------------------------------------
diff --git a/include/beman/execution/detail/get_delegation_scheduler.hpp b/include/beman/execution/detail/get_delegation_scheduler.hpp
index c9e58e37..7c070e06 100644
--- a/include/beman/execution/detail/get_delegation_scheduler.hpp
+++ b/include/beman/execution/detail/get_delegation_scheduler.hpp
@@ -24,7 +24,7 @@ namespace beman::execution {
struct get_delegation_scheduler_t {
template
requires requires(Env&& env, const get_delegation_scheduler_t& g) {
- { ::std::as_const(env).query(g) } noexcept -> ::beman::execution::scheduler;
+ { auto(::std::as_const(env).query(g)) } noexcept -> ::beman::execution::scheduler;
}
auto operator()(Env&& env) const noexcept {
return ::std::as_const(env).query(*this);
diff --git a/include/beman/execution/detail/get_forward_progress_guarantee.hpp b/include/beman/execution/detail/get_forward_progress_guarantee.hpp
index bdc0affa..d11cc89e 100644
--- a/include/beman/execution/detail/get_forward_progress_guarantee.hpp
+++ b/include/beman/execution/detail/get_forward_progress_guarantee.hpp
@@ -13,8 +13,10 @@ import std;
#endif
#ifdef BEMAN_HAS_MODULES
import beman.execution.detail.forwarding_query;
+import beman.execution.detail.almost_scheduler;
#else
#include
+#include
#endif
// ----------------------------------------------------------------------------
@@ -24,18 +26,13 @@ namespace beman::execution {
enum class forward_progress_guarantee { concurrent, parallel, weakly_parallel };
struct get_forward_progress_guarantee_t {
- template
+ template
requires requires(const Object& object, const get_forward_progress_guarantee_t& tag) { object.query(tag); }
auto operator()(const Object& object) const noexcept -> forward_progress_guarantee {
static_assert(::std::same_as);
return object.query(*this);
}
- template
- auto operator()(const Object&) const noexcept -> forward_progress_guarantee {
- return forward_progress_guarantee::weakly_parallel;
- }
-
static constexpr auto query(const ::beman::execution::forwarding_query_t&) noexcept -> bool { return true; }
};
diff --git a/include/beman/execution/detail/get_start_scheduler.hpp b/include/beman/execution/detail/get_start_scheduler.hpp
index 3fae8532..43a00bbf 100644
--- a/include/beman/execution/detail/get_start_scheduler.hpp
+++ b/include/beman/execution/detail/get_start_scheduler.hpp
@@ -12,8 +12,10 @@ import std;
#endif
#ifdef BEMAN_HAS_MODULES
import beman.execution.detail.forwarding_query;
+import beman.execution.detail.scheduler;
#else
#include
+#include
#endif
// ----------------------------------------------------------------------------
@@ -21,7 +23,9 @@ import beman.execution.detail.forwarding_query;
namespace beman::execution {
struct get_start_scheduler_t : ::beman::execution::forwarding_query_t {
template
- requires requires(const get_start_scheduler_t& self, const Env& env) { env.query(self); }
+ requires requires(const get_start_scheduler_t& self, const Env& env) {
+ { auto(::std::as_const(env).query(self)) } noexcept -> beman::execution::scheduler;
+ }
auto operator()(const Env& env) const noexcept {
return env.query(*this);
}
diff --git a/include/beman/execution/detail/inline_scheduler.hpp b/include/beman/execution/detail/inline_scheduler.hpp
index 22ab701e..ec9b85c8 100644
--- a/include/beman/execution/detail/inline_scheduler.hpp
+++ b/include/beman/execution/detail/inline_scheduler.hpp
@@ -13,23 +13,27 @@ import std;
#include
#endif
#ifdef BEMAN_HAS_MODULES
+import beman.execution.detail.completion_signatures;
+import beman.execution.detail.get_forward_progress_guarantee;
import beman.execution.detail.get_scheduler;
-import beman.execution.detail.sender;
-import beman.execution.detail.receiver;
-import beman.execution.detail.set_value;
+import beman.execution.detail.inline_attrs;
import beman.execution.detail.operation_state;
+import beman.execution.detail.receiver;
import beman.execution.detail.scheduler;
import beman.execution.detail.scheduler_tag;
-import beman.execution.detail.completion_signatures;
-import beman.execution.detail.inline_attrs;
+import beman.execution.detail.sender;
+import beman.execution.detail.set_value;
#else
-#include
-#include
-#include
-#include
-#include
#include
+#include
+#include
#include
+#include
+#include
+#include
+#include
+#include
+
#endif
namespace beman::execution {
@@ -38,6 +42,10 @@ struct inline_scheduler {
using env = ::beman::execution::detail::inline_attrs<::beman::execution::set_value_t>;
+ auto query(::beman::execution::get_forward_progress_guarantee_t) const noexcept
+ -> ::beman::execution::forward_progress_guarantee {
+ return ::beman::execution::forward_progress_guarantee::weakly_parallel;
+ }
template <::beman::execution::receiver Rcvr>
struct state {
using operation_state_concept = ::beman::execution::operation_state_tag;
diff --git a/include/beman/execution/detail/on.hpp b/include/beman/execution/detail/on.hpp
index d737eb75..fec57ba4 100644
--- a/include/beman/execution/detail/on.hpp
+++ b/include/beman/execution/detail/on.hpp
@@ -12,6 +12,7 @@ import std;
#endif
#ifdef BEMAN_HAS_MODULES
import beman.execution.detail.basic_sender;
+import beman.execution.detail.call_with_default;
import beman.execution.detail.completion_signatures_of_t;
import beman.execution.detail.continues_on;
import beman.execution.detail.default_domain;
@@ -34,6 +35,8 @@ import beman.execution.detail.set_value;
import beman.execution.detail.starts_on;
import beman.execution.detail.transform_sender;
#else
+#include
+#include
#include
#include
#include
diff --git a/include/beman/execution/detail/operation_state_task.hpp b/include/beman/execution/detail/operation_state_task.hpp
index 8209d1a2..148acd38 100644
--- a/include/beman/execution/detail/operation_state_task.hpp
+++ b/include/beman/execution/detail/operation_state_task.hpp
@@ -70,8 +70,8 @@ struct beman::execution::detail::operation_state_task {
using promise_type = ::beman::execution::detail::connect_awaitable_promise;
explicit operation_state_task(::std::coroutine_handle<> hndl) noexcept : handle(hndl) {}
- operation_state_task(const operation_state_task&) = delete;
- operation_state_task(operation_state_task&& other) noexcept : handle(::std::exchange(other.handle, {})) {}
+ operation_state_task(const operation_state_task&) = delete;
+ operation_state_task(operation_state_task&& other) = delete;
~operation_state_task() {
if (this->handle)
this->handle.destroy();
diff --git a/include/beman/execution/detail/product_type.hpp b/include/beman/execution/detail/product_type.hpp
index 83dd0592..3ae2fc64 100644
--- a/include/beman/execution/detail/product_type.hpp
+++ b/include/beman/execution/detail/product_type.hpp
@@ -120,6 +120,7 @@ constexpr auto is_product_type(const ::beman::execution::detail::product_type
struct tuple_size<::beman::execution::detail::product_type>
@@ -131,6 +132,7 @@ struct tuple_element> {
::std::decay_t>().template get())>;
};
} // namespace std
+#endif
// ----------------------------------------------------------------------------
diff --git a/include/beman/execution/detail/query_with_default.hpp b/include/beman/execution/detail/query_with_default.hpp
index f94f315e..14288509 100644
--- a/include/beman/execution/detail/query_with_default.hpp
+++ b/include/beman/execution/detail/query_with_default.hpp
@@ -27,18 +27,6 @@ query_with_default(Tag, const Env&, Value&& value) noexcept(noexcept(static_cast
return static_cast(std::forward(value));
}
-template
- requires requires(const Tag& tag, const Env& env, Args&&... args) { tag(env, ::std::forward(args)...); }
-constexpr auto call_with_default(Tag, DefaultValue&&, const Env& env, Args&&... args) noexcept(
- noexcept(Tag()(env, ::std::forward(args)...))) -> decltype(auto) {
- return Tag()(env, ::std::forward(args)...);
-}
-
-template
-constexpr auto call_with_default(Tag, DefaultValue&& value, const Env&, const Args&...) noexcept(
- noexcept(static_cast(std::forward(value)))) -> decltype(auto) {
- return static_cast(std::forward(value));
-}
} // namespace beman::execution::detail
// ----------------------------------------------------------------------------
diff --git a/include/beman/execution/detail/read_env.hpp b/include/beman/execution/detail/read_env.hpp
index 67fe95b1..74e658c4 100644
--- a/include/beman/execution/detail/read_env.hpp
+++ b/include/beman/execution/detail/read_env.hpp
@@ -9,6 +9,7 @@
import std;
#else
#include
+#include
#include
#include
#endif
@@ -16,6 +17,7 @@ import std;
import beman.execution.detail.basic_sender;
import beman.execution.detail.completion_signatures;
import beman.execution.detail.completion_signatures_for;
+import beman.execution.detail.data_type;
import beman.execution.detail.default_impls;
import beman.execution.detail.env_of_t;
import beman.execution.detail.get_env;
@@ -27,6 +29,7 @@ import beman.execution.detail.set_value;
#else
#include
#include
+#include
#include
#include
#include
@@ -79,7 +82,17 @@ struct read_env_t {
}
}
};
- static constexpr auto start{start_impl{}};
+ static constexpr start_impl start{};
+
+ template
+ static consteval void check_types() {
+ using query_type = ::std::decay_t<::beman::execution::detail::data_type>;
+ if constexpr (!requires(const Env& env) { query_type()(env); }) {
+ throw ::std::logic_error("query is not invocable with the environment of the receiver");
+ } else if constexpr (::std::same_as<::std::invoke_result_t, void>) {
+ throw ::std::logic_error("query returns void with the environment of the receiver");
+ }
+ }
};
};
diff --git a/include/beman/execution/detail/receiver.hpp b/include/beman/execution/detail/receiver.hpp
index ec4557a3..3cee0155 100644
--- a/include/beman/execution/detail/receiver.hpp
+++ b/include/beman/execution/detail/receiver.hpp
@@ -32,7 +32,9 @@ concept receiver =
requires(const ::std::remove_cvref_t& rcvr) {
{ ::beman::execution::get_env(rcvr) } -> ::beman::execution::detail::queryable;
} && ::std::move_constructible<::std::remove_cvref_t> &&
- ::std::constructible_from<::std::remove_cvref_t, Rcvr> && (!::std::is_final_v<::std::remove_cvref_t>);
+ ::std::constructible_from<::std::remove_cvref_t, Rcvr> &&
+ (!::std::is_final_v<::std::remove_cvref_t>) &&
+ ::std::is_nothrow_move_constructible_v<::std::remove_cvref_t>;
} // namespace beman::execution
// ----------------------------------------------------------------------------
diff --git a/include/beman/execution/detail/scheduler.hpp b/include/beman/execution/detail/scheduler.hpp
index 465304d7..ed859cef 100644
--- a/include/beman/execution/detail/scheduler.hpp
+++ b/include/beman/execution/detail/scheduler.hpp
@@ -14,10 +14,12 @@ import std;
#endif
#ifdef BEMAN_HAS_MODULES
import beman.execution.detail.almost_scheduler;
+import beman.execution.detail.get_forward_progress_guarantee;
import beman.execution.detail.schedule;
import beman.execution.detail.sender;
#else
#include
+#include
#include
#include
#endif
@@ -28,6 +30,9 @@ namespace beman::execution {
template
concept scheduler = ::beman::execution::detail::almost_scheduler && requires(Scheduler&& sched) {
{ ::beman::execution::schedule(::std::forward(sched)) } -> ::beman::execution::sender;
+ {
+ ::beman::execution::get_forward_progress_guarantee(sched)
+ } -> ::std::same_as<::beman::execution::forward_progress_guarantee>;
} && ::std::equality_comparable<::std::remove_cvref_t> && ::std::copyable<::std::remove_cvref_t>;
} // namespace beman::execution
diff --git a/include/beman/execution/detail/set_value.hpp b/include/beman/execution/detail/set_value.hpp
index d3216a84..c2e4bdc4 100644
--- a/include/beman/execution/detail/set_value.hpp
+++ b/include/beman/execution/detail/set_value.hpp
@@ -14,6 +14,17 @@ import std;
// ----------------------------------------------------------------------------
+#define BEMAN_EXECUTION_SET_VALUE(rcvr, expr) \
+ [&]() noexcept(noexcept((expr))) -> void { \
+ if constexpr (::std::same_as) { \
+ (expr), ::beman::execution::set_value(::std::move((rcvr))); \
+ } else { \
+ ::beman::execution::set_value(::std::move((rcvr)), (expr)); \
+ } \
+ }()
+
+// ----------------------------------------------------------------------------
+
namespace beman::execution {
/*!
* \brief Type of the customization point object for successful completions.
diff --git a/include/beman/execution/detail/starts_on.hpp b/include/beman/execution/detail/starts_on.hpp
index eb31e8b0..c94dc1a0 100644
--- a/include/beman/execution/detail/starts_on.hpp
+++ b/include/beman/execution/detail/starts_on.hpp
@@ -139,6 +139,14 @@ struct starts_on_t {
return {};
}
+ template
+ requires requires(const Tag& tag, const ChildAttrs& child_attrs, Env&&... env) {
+ tag(::beman::execution::detail::fwd_env(child_attrs), ::std::forward(env)...);
+ }
+ auto query(Tag tag, Env&&... env) const noexcept {
+ return tag(::beman::execution::detail::fwd_env(this->child_attrs), ::std::forward(env)...);
+ }
+
Scheduler sch;
ChildAttrs child_attrs;
};
diff --git a/include/beman/execution/detail/task_scheduler.hpp b/include/beman/execution/detail/task_scheduler.hpp
index 859e7524..0de0adcb 100644
--- a/include/beman/execution/detail/task_scheduler.hpp
+++ b/include/beman/execution/detail/task_scheduler.hpp
@@ -20,6 +20,7 @@ import std;
#endif
#ifdef BEMAN_HAS_MODULES
import beman.execution.detail.bulk;
+import beman.execution.detail.call_with_default;
import beman.execution.detail.completion_signatures;
import beman.execution.detail.connect;
import beman.execution.detail.connect_result_t;
@@ -59,6 +60,7 @@ import beman.execution.detail.unreachable;
import beman.execution.detail.unstoppable_token;
#else
#include
+#include
#include
#include
#include
diff --git a/include/beman/execution/execution.hpp b/include/beman/execution/execution.hpp
index 0f10f604..a56fd3cb 100644
--- a/include/beman/execution/execution.hpp
+++ b/include/beman/execution/execution.hpp
@@ -22,7 +22,6 @@ import beman.execution.detail.dependent_sender;
import beman.execution.detail.enter_scope_sender_in;
import beman.execution.detail.enter_scope_sender;
import beman.execution.detail.env;
-import beman.execution.detail.execution_policy;
import beman.execution.detail.exit_scope_sender_in;
import beman.execution.detail.exit_scope_sender_of_t;
import beman.execution.detail.exit_scope_sender;
diff --git a/src/beman/execution/CMakeLists.txt b/src/beman/execution/CMakeLists.txt
index 6e7a3191..751e9909 100644
--- a/src/beman/execution/CMakeLists.txt
+++ b/src/beman/execution/CMakeLists.txt
@@ -44,6 +44,7 @@ target_sources(
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/bulk.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/call_result_t.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/callable.hpp
+ ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/call_with_default.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/check_type_alias_exist.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/child_type.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/class_type.hpp
@@ -66,6 +67,7 @@ target_sources(
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/counting_scope.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/counting_scope_base.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/counting_scope_join.hpp
+ ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/data_type.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/decayed_same_as.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/decayed_tuple.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/decayed_type_list.hpp
@@ -269,6 +271,7 @@ if(BEMAN_USE_MODULES)
bulk.cppm
call_result_t.cppm
callable.cppm
+ call_with_default.cppm
check_type_alias_exist.cppm
child_type.cppm
class_type.cppm
@@ -289,6 +292,7 @@ if(BEMAN_USE_MODULES)
counting_scope_base.cppm
counting_scope_join.cppm
counting_scope.cppm
+ data_type.cppm
decayed_same_as.cppm
decayed_tuple.cppm
decayed_type_list.cppm
diff --git a/src/beman/execution/basic_sender.cppm b/src/beman/execution/basic_sender.cppm
index f2caf6d2..57ac9527 100644
--- a/src/beman/execution/basic_sender.cppm
+++ b/src/beman/execution/basic_sender.cppm
@@ -2,9 +2,14 @@ module;
// src/beman/execution/basic_sender.cppm -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#include
+#include
+#ifdef BEMAN_HAS_IMPORT_STD
+import std;
+#else
#include
#include
-#include
+#endif
export module beman.execution.detail.basic_sender;
diff --git a/src/beman/execution/call_with_default.cppm b/src/beman/execution/call_with_default.cppm
new file mode 100644
index 00000000..8c2bed5e
--- /dev/null
+++ b/src/beman/execution/call_with_default.cppm
@@ -0,0 +1,11 @@
+module;
+// src/beman/execution/call_with_default.cppm -*-C++-*-
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#include
+
+export module beman.execution.detail.call_with_default;
+
+namespace beman::execution::detail {
+export using beman::execution::detail::call_with_default;
+} // namespace beman::execution::detail
diff --git a/src/beman/execution/data_type.cppm b/src/beman/execution/data_type.cppm
new file mode 100644
index 00000000..4c4c9012
--- /dev/null
+++ b/src/beman/execution/data_type.cppm
@@ -0,0 +1,11 @@
+module;
+// src/beman/execution/data_type.cppm -*-C++-*-
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#include
+
+export module beman.execution.detail.data_type;
+
+namespace beman::execution::detail {
+export using beman::execution::detail::data_type;
+} // namespace beman::execution::detail
diff --git a/src/beman/execution/execution-detail.cppm b/src/beman/execution/execution-detail.cppm
index 916e05da..591f6275 100644
--- a/src/beman/execution/execution-detail.cppm
+++ b/src/beman/execution/execution-detail.cppm
@@ -21,6 +21,7 @@ export import beman.execution.detail.completion_tag;
export import beman.execution.detail.connect_all;
export import beman.execution.detail.connect_all_result;
export import beman.execution.detail.connect_awaitable;
+export import beman.execution.detail.data_type;
export import beman.execution.detail.decayed_tuple;
export import beman.execution.detail.decayed_typeof;
export import beman.execution.detail.decays_to;
diff --git a/src/beman/execution/fwd_env.cppm b/src/beman/execution/fwd_env.cppm
index e0ad2956..9399f0d1 100644
--- a/src/beman/execution/fwd_env.cppm
+++ b/src/beman/execution/fwd_env.cppm
@@ -7,5 +7,6 @@ module;
export module beman.execution.detail.fwd_env;
namespace beman::execution::detail {
+export using beman::execution::detail::fwd_env_t;
export using beman::execution::detail::fwd_env;
} // namespace beman::execution::detail
diff --git a/src/beman/execution/product_type.cppm b/src/beman/execution/product_type.cppm
index 49326247..5c0f9862 100644
--- a/src/beman/execution/product_type.cppm
+++ b/src/beman/execution/product_type.cppm
@@ -2,8 +2,13 @@ module;
// src/beman/execution/product_type.cppm -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-#include
+#define BEMAN_EXECUTION_DETAIL_PRODUCT_TYPE_CPPM
#include
+#ifdef BEMAN_HAS_IMPORT_STD
+import std;
+#else
+#include
+#endif
export module beman.execution.detail.product_type;
@@ -14,11 +19,14 @@ export using beman::execution::detail::product_type;
} // namespace beman::execution::detail
-#if defined(_MSC_VER) && _MSC_VER <= 1944L
namespace std {
template
-struct tuple_size<::beman::execution::detail::product_type>;
+struct tuple_size<::beman::execution::detail::product_type>
+ : ::std::integral_constant::size()> {};
+
template <::std::size_t I, typename... T>
-struct tuple_element>;
+struct tuple_element> {
+ using type =
+ ::std::decay_t>().template get())>;
+};
} // namespace std
-#endif
diff --git a/src/beman/execution/query_with_default.cppm b/src/beman/execution/query_with_default.cppm
index bb348f29..132bdece 100644
--- a/src/beman/execution/query_with_default.cppm
+++ b/src/beman/execution/query_with_default.cppm
@@ -8,5 +8,4 @@ export module beman.execution.detail.query_with_default;
namespace beman::execution::detail {
export using beman::execution::detail::query_with_default;
-export using beman::execution::detail::call_with_default;
} // namespace beman::execution::detail
diff --git a/src/beman/execution/task_scheduler.cppm b/src/beman/execution/task_scheduler.cppm
index 7a8b2af8..752eee8c 100644
--- a/src/beman/execution/task_scheduler.cppm
+++ b/src/beman/execution/task_scheduler.cppm
@@ -2,9 +2,14 @@ module;
// src/beman/execution/task_scheduler.cppm -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#include
+#include
+#ifdef BEMAN_HAS_IMPORT_STD
+import std;
+#else
#include
#include
-#include
+#endif
export module beman.execution.detail.task_scheduler;
diff --git a/tests/beman/execution/CMakeLists.txt b/tests/beman/execution/CMakeLists.txt
index 05e70874..ef8464ad 100644
--- a/tests/beman/execution/CMakeLists.txt
+++ b/tests/beman/execution/CMakeLists.txt
@@ -5,7 +5,7 @@ if(BEMAN_USE_MODULES)
list(APPEND execution_tests execution-module.test stop-token-module.test)
endif()
-list(APPEND unsupported_execution_tests exec-split.test)
+list(APPEND unsupported_execution_tests exec-split.test exec-spawn-future.test)
list(
APPEND execution_tests
@@ -42,6 +42,7 @@ list(
exec-opstate.test
exec-prop.test
exec-queries-expos.test
+ exec-queryable-concept.test
exec-read-env.test
exec-recv-concepts.test
exec-recv.test
@@ -49,6 +50,7 @@ list(
exec-run-loop-types.test
exec-sched.test
exec-schedule.test
+ exec-schedule-from.test
exec-scope-concepts.test
exec-scope-counting.test
exec-scope-simple-counting.test
@@ -61,22 +63,22 @@ list(
exec-snd-concepts.test
exec-snd-expos.test
exec-snd-transform.test
- exec-spawn-future.test
exec-spawn.test
exec-starts-on.test
exec-stop-when.test
- exec-stopped-as-error.test
- exec-stopped-as-optional.test
+ exec-stopped-err.test
+ exec-stopped-opt.test
exec-sync-wait.test
exec-sync-wait-with-variant.test
exec-task.test
exec-task-scheduler.test
exec-then.test
- exec-utils-cmplsigs.test
+ exec-unstoppable.test
+ exec-cmplsigs.test
exec-when-all.test
exec-with-awaitable-senders.test
exec-within.test
- execution-queryable-concept.test
+ exec-write-env.test
execution-syn.test
forward-like.test
function-objects.test
diff --git a/tests/beman/execution/allocator-requirements-general.test.cpp b/tests/beman/execution/allocator-requirements-general.test.cpp
index 2cc29807..2d4dd2b0 100644
--- a/tests/beman/execution/allocator-requirements-general.test.cpp
+++ b/tests/beman/execution/allocator-requirements-general.test.cpp
@@ -1,12 +1,12 @@
// src/beman/execution/tests/allocator-requirements-general.test.cpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-#include
#ifdef BEMAN_HAS_MODULES
import beman.execution.detail.simple_allocator;
#else
#include
#endif
+#include
// ----------------------------------------------------------------------------
diff --git a/tests/beman/execution/exec-affine.test.cpp b/tests/beman/execution/exec-affine.test.cpp
index 47fe92ab..7a54ab6c 100644
--- a/tests/beman/execution/exec-affine.test.cpp
+++ b/tests/beman/execution/exec-affine.test.cpp
@@ -1,11 +1,16 @@
// tests/beman/execution/exec-affine.test.cpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-#include
+#ifdef BEMAN_HAS_IMPORT_STD
+import std;
+#else
#include
#include
#include
#include
+#endif
+#include
+#include
#ifdef BEMAN_HAS_MODULES
import beman.execution;
#else
@@ -66,6 +71,9 @@ receiver(Sched, awaiter* = nullptr) -> receiver;
struct test_scheduler {
using scheduler_concept = test_std::scheduler_tag;
+ auto query(test_std::get_forward_progress_guarantee_t) const noexcept {
+ return test_std::forward_progress_guarantee::weakly_parallel;
+ }
struct data {
std::size_t connected_{};
@@ -153,6 +161,14 @@ auto test_affine_specializations(Sender&& sender, std::size_t count = 0u) -> voi
assert(data.connected_ == count);
assert(data.started_ == count);
}
+
+auto test_affine_attributes() {
+ test::sender_env s{42};
+ test::test_sender_env(42, test::test_forwardable_attr{}, s);
+ test::test_sender_env(84, test::test_non_forwardable_attr{}, s);
+ test::test_sender_env(42, test::test_forwardable_attr{}, test_std::affine(s));
+ test::test_sender_env(84, test::test_non_forwardable_attr{}, test_std::affine(s));
+}
} // namespace
TEST(affine) {
@@ -207,5 +223,7 @@ TEST(affine) {
loop.finish();
t.join();
+ test_affine_attributes();
+
return 0;
}
diff --git a/tests/beman/execution/exec-associate.test.cpp b/tests/beman/execution/exec-associate.test.cpp
index 07144f32..a1ed2e0f 100644
--- a/tests/beman/execution/exec-associate.test.cpp
+++ b/tests/beman/execution/exec-associate.test.cpp
@@ -2,7 +2,6 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include
-#include
#ifdef BEMAN_HAS_IMPORT_STD
import std;
#else
@@ -14,6 +13,8 @@ import std;
#include
#include
#endif
+#include
+#include
#ifdef BEMAN_HAS_MODULES
import beman.execution;
#else
@@ -102,6 +103,18 @@ struct scope {
static_assert(test_std::scope_token);
static_assert(test_std::scope_association);
+auto test_associate_attributes() {
+ test_std::counting_scope scope{};
+ test::sender_env s{42};
+ test::test_sender_env(42, test::test_forwardable_attr{}, s);
+ test::test_sender_env