2533. [concurr.ts] Constrain threads where future::then can run a continuation

Section: 99 [concurr.ts::futures.unique_future] Status: SG1 Submitter: Agustín K-ballo Bergé Opened: 2015-09-03 Last modified: 2017-03-01

Priority: Not Prioritized

View other active issues in [concurr.ts::futures.unique_future].

View all other issues in [concurr.ts::futures.unique_future].

View all issues with SG1 status.

Discussion:

Addresses: concurr.ts

In N4538, the continuation given to future::then can be run "on an unspecified thread of execution". This is too broad, as it allows the continuation to be run on the main thread, a UI thread, or any other thread. In comparison, functions given to async run "as if in a new thread of execution", while the Parallelism TS gives less guarantees by running "in either the invoking thread or in a thread implicitly created by the library to support parallel algorithm execution". The threads on which the continuation given to future::then can run should be similarly constrained.

[2017-03-01, Kona, SG1]

Agreement that this is a problem. Suggested addition to the issue is below. We have no immediate delivery vehicle for a fix at the moment, but we would like to make the intended direction clear.

There is SG1 consensus that .then continuations should, by default, and in the absence of executors, be run only in the following ways:

  1. If the future is not ready when .then() is called, the .then argument may be run on the execution agent that fulfills the promise.

  2. In all cases, the .then argument may be run on an implementation-provided thread, i.e. a thread that is neither the main thread nor explicitly created by the user.

In the absence of an executor argument (which currently cannot be supplied), running of the .then() continuation will not block the thread calling .then(), even if the future is ready at the time.

Straw polls:

SF | F | N | A | SA

For the default behaviour:

"1. Run on completed task or new execution agent"

0 | 7 | 5 | 1 | 0

"2. Run on completed task or .then caller"

0 | 0 | 5 | 5 | 3

"3. Leave as implementation defined"

1 | 2 | 4 | 3 | 3

"4. Always new execution agent"

2 | 3 | 6 | 2 | 0

The actual conclusion was to allow either (1) or (4) for now, since they are quite close, but present a very different programming mode from (2).

Proposed resolution: