Skip to content

The current structure of get_completion_signatures() does not permit accurate calculation of completion-signatures when the child env needs access to the operation-state #235

Open
@lewissbaker

Description

@lewissbaker

In some algorithms I want to be able to store some state in a parent operation-state and then pass a receiver to child operations whose get_env() returns a queryable that resolves a certain query from the operation-state.

e.g. Consider a simple algorithm something like:

template<typename Receiver, typename ChildSender, typename Allocator>
struct with_allocator_op {
  struct child_env {
    with_allocator_op* op;

    decltype(auto) query(auto tag) const
      noexcept(noexcept(std::declval<Receiver>().get_env().query(tag)))
      requires queryable_for<receiver_env_t<Receiver>, decltype(tag)> {
      return std::execution::get_env(op->receiver).query(tag);
    }

    Allocator query(get_allocator_t) const noexcept {
      return op->allocator;
    }
  };

  struct child_receiver {
    with_allocator_op* op;

    template<typename... Vs> void set_value(Vs&&... vs) noexcept {
      op->receiver.set_value(std::forward<Vs>(vs)...);
    }

    template<typename E> void set_error(E&& e) noexcept {
      op->receiver.set_error(std::forward<E>(e));
    }
    
    void set_stopped() noexcept  { op->receiver.set_stopped(); }

    child_env get_env() const noexcept {
      return child_env{op};
    }    
  };
  
  void start() noexcept { child_op.start(); }

  Receiver receiver;
  Allocator allocator;
  connect_result_t<ChildSender, child_receiver> child_op;
};

However, since the receiver that I connect the ChildSender to in this case has an environment whose type depends on the with_allocator_op type, which in turn depends on the Receiver, there is no way for the corresponding with_allocator_sender that produces this operation state upon connect to implement the get_completion_signatures() query accurately, as it cannot pass through the exact environment type to the get_completion_signatures() query on the ChildSender type.

Is this something we want to be able to support?
It seems like it might be necessary to solve #229.

If we want to support this I think we would require one of two approaches:

  • Go back to making get_completion_signatures() take the receiver type rather than the environment type and solve the circular dependencies some other way.
  • Require get_completion_signatures() to produce the same set of completion-signatures for any environment type that has an equivalent set of supported queries.
    This would, however, make it impossible to implement something like let_env() whose completion-signatures would depend on the exact environment type rather than the set of queries that the environment supports.

If we don't want to support this then we are basically restricted to environment aggregation, with the potential performance issues described in #229.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0designneeds-proposed-resolutionThis issue does not yet have a proposed resolution but needs oneprocessedprocessed in a meeting

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions