cplusplus / sender-receiver

Issues list for P2300
Apache License 2.0
19 stars 3 forks source link

The use of `JOIN-ENV` leads to inefficient implementations of composed environments #229

Open lewissbaker opened 4 months ago

lewissbaker commented 4 months ago

The current specification of the helper JOIN-ENV(env1, env2) and its use in algorithms can potentially lead to large environment objects which can be inefficient.

Several algorithms are specified as passing a receiver to a child operation that has a get_env() method whose return-value is specified in terms of JOIN-ENV.

For example, the let_value algorithm is specified to pass a receiver to the child operation such that the receiver's get_env() is specified to return JOIN-ENV(env, FWD-ENV(execution::get_env(rcvr))).

This requires the get_env() method to return a new aggregate that either holds a copy of these two environments or at least holds a reference to the two environments.

If the let_value() algorithm is applied in a nested fashion N times, then the leaf operation will have an environment that contains N references to environments. Further, computing the leaf environment requires walking the full chain of senders every call to get_env(), even if the query we want to perform is satisfied by the first parent operation's env.

To avoid this, the receiver's get_env() method should be specified to return a new env object that contains a pointer to the parent operation-state and whose .query() method is implemented to either forwward to op.env if that provides a query value, or otherwise to op.receiver.get_env().

This way, the get_env() call always completes in constant time, and a given .query() only needs to traverse up the chain of parents until it finds an env that satisfies the query.

Note that adopting this suggestion potentially has impacts on the way we do completion-signature calculations as we would need to be able to compute the type of the env returned by the receiver's get_env(), but the env type passed to child operation-states would now be dependent on the type of the parent operation-state, which depends on the receiver. This may require solving the original cyclic dependency/instantiation issue that splitting envs from receivers was originally hoping to do in another way.

lewissbaker commented 4 months ago

See also #199 for an example of this applied to when_all.

This issue is for solving the problem more generally.