diff --git a/docs/overview.md b/docs/overview.md index 82efafde..c7a697ba 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -352,8 +352,8 @@ static_assert(not std::execution::unstoppable_token ## Queries -The queries are used to obtain properties associated with an object. Except forwarding_query, get_env, and get_completion_signatures the queries work on environments. The -environment queries are defined by providing a member query(query_t, a...) const on the environment object. +The queries are used to obtain properties associated with an object. +
Example defining a query on an environment This example shows how to define an environment class which provides a get_allocator query. The objects stores a `std::pmr::memory_resource*` and returns a correspondingly initialized `std::pmr::polymorphic_allocator<>`. @@ -372,7 +372,14 @@ struct alloc_env { forwarding_query(query) -> bool **Default**: `false`
-forwarding_query(query) is a `constexpr` query used to determine if the query query should be forwarded when wrapping an environment. +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. + +The result of the expression is determined as follows: +
    +
  1. The result is the value of the expression query.query(forwarding_query) if this expression is valid and `noexcept`.
  2. +
  3. The result is true if the type of query is publicly derived from forwarding_query.
  4. +
  5. Otherwise the result is false. +
Example @@ -402,7 +409,11 @@ struct custom_t: forwarding_query_t { get_env(queryable) -> env **Default**: `empty_env`
-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 empty_env is returned. +The expresion 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 empty_env is returned. +The value of the expression is
    +
  1. the result of as_const(queryable).get_env() if this expression is valid and noexcept.
  2. +
  3. empty_env otherwise. +
Example @@ -428,7 +439,14 @@ Note that the `get_env` member is both `const` and `noexcept`. get_allocator(env) -> allocator **Default**: none
-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 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 +
    +
  • the expression is valid;
  • +
  • the expression is noexcept;
  • +
  • the result of the expression satisfies simple-allocator.
  • +
+Otherwise the expression is ill-formed. +
Example @@ -447,47 +465,119 @@ struct alloc_env {
-get_completion_scheduler<tag>(env) -> scheduler +get_completion_scheduler<>(env) -> scheduler **Default**: none
-If the expression get_completion_scheduler<tag>(get_env(sender)) is well-formed and returns a scheduler it defines the scheduler on which the completion tag executes. In particular get_completion_scheduler<set_value_t>(schedule(sched)) returns sched. +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 +
    +
  1. Tag is one of the types set_value_t, set_error_t, or set_stopped_t; +
  2. this expression is valid;
  3. +
  4. this expression is noexcept;
  5. +
  6. the expression’s type satisfies scheduler. +
+Otherwise the expression is invalid.
get_completion_signatures(sender, env) The expression get_completion_signatures(sender, env) returns an object whose type is a specialization of completion_signatures defining the possible completion signatures of sender when connected to a receiver whose environment get_env(receiver) is env. A sender can define the result of this query either by defining a member function get_completion_signatures or using a type alias completion_signatures. + +To determine the result the sender is first transformed using transform_sender(domain, sender, env) to get new-sender with type New-Sender-Type. With that the result type is +
    +
  1. the type of new-sender.get_completion_signatures(env) if this expression is valid;
  2. +
  3. the type remove_cvref_t<New-Sender-Type>::completion_signatures if this type exists;
  4. +
  5. completion_signatures<set_value_t(T), set_error_t(exception_ptr), set_stopped_t()> if New-Sender-Type is an awaitable type which would yield an object of type T when it is co_awaited;
  6. +
  7. invalid otherwise. +
Example -When a sender doesn’t need to compute the completion signatures based on an environment it is easiest to use a the type alias: - - +When a sender doesn’t need to compute the completion signatures based on an environment it is easiest to use a the type alias, e.g.: +```c++ +struct sender { + using sender_concept = std::execution::sender_t; + using completion_signatures = std::completion_signatures< + std::execution::set_value_t(int), + std::execution::set_error_t(std::error_code), + std::execution::set_stopped() + >; + // ... +}; +```
-get_delegation_scheduler(env) +get_delegation_scheduler(env) -> scheduler +The expression get_delegation_scheduler(env) yields the scheduler associated with env which is used for forward progress delegation. The value of the expression is equivalent to as_const(env).query(get_delegation_scheduler) -> scheduler if +
    +
  1. this expression is valid;
  2. +
  3. this expression is noexcept;
  4. +
  5. the expression’s type satisfies scheduler. +
+Otherwise the expression is invalid.
-get_domain(env) +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 +
    +
  1. this expression is valid;
  2. +
  3. this expression is noexcept.
  4. +
+Otherwise the expression is invalid.
-get_forward_progress_guarantee(env) +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 +
    +
  1. this expression is valid;
  2. +
  3. this expression is noexcept;
  4. +
  5. the expression’s type is forward_progress_guarantee. +
+Otherwise the expression is invalid.
-get_scheduler(env) +get_scheduler(env) -> scheduler +The expression get_scheduler(env) yields the scheduler associated with env. The value of the expression is equivalent to as_const(env).query(get_scheduler) if +
    +
  1. this expression is valid;
  2. +
  3. this expression is noexcept;
  4. +
  5. the expression’s type satisfies scheduler. +
+Otherwise the expression is invalid.
-get_stop_token(env) +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 +
    +
  • the expression is valid;
  • +
  • the expression is noexcept;
  • +
  • the expression satisfies stoppable_token.
  • +
+Otherwise the value is never_stop_token{}.
-### Customization Point Objects +## Customization Point Objects -- connect(sender, receiver) -> operation_state -- set_error(error) noexcept -> void -- set_stopped(receiver) noexcept -> void -- set_value(receiver, value...) noexcept -> void -- start(state&) noexcept -> void +
+connect(sender, receiver) -> operation_state +
+
+set_error(receiver, error) noexcept -> void +The expression set_error(receiver, error) invokes the set_error completion signal on receiver with the argument error, i.e., it invokes receiver.set_error(error). +
+
+set_stopped(receiver) noexcept -> void +The expression set_stopped(receiver) invokes the set_stopped completion signal on receiver, i.e., it invokes receiver.set_stopped(). +
+
+set_value(receiver, value...) noexcept -> void +The expression set_value(receiver, value...) invokes the set_value completion signal on receiver with the argument(s) value..., i.e., it invokes receiver.set_value(value...). +
+
+start(state) noexcept -> void +The expression start(state) starts the execution of the operation_state object state. Once this expression started executing the object state is required to stay valid at least until one of the completion signals of state’s receiver is invoked. Once started exactly one of the completion signals is eventually called. +
## Senders