1266. shared_future::get and deferred async functions

Section: 32.10.8 [futures.shared.future] Status: Resolved Submitter: Anthony Williams Opened: 2009-11-17 Last modified: 2021-06-06

Priority: Not Prioritized

View all other issues in [futures.shared.future].

View all issues with Resolved status.

Discussion:

If a shared_future is constructed with the result of an async call with a deferred function, and two or more copies of that shared_future are created, with multiple threads calling get(), it is not clear which thread runs the deferred function. [futures.shared_future]p22 from N3000 says (minus editor's note):

Effects: if the associated state contains a deferred function, executes the deferred function. Otherwise, blocks until the associated state is ready.

In the absence of wording to the contrary, this implies that every thread that calls wait() will execute the deferred function.

[ 2010 Pittsburgh: Moved to NAD EditorialResolved. Rationale added below. ]

Rationale:

Solved by N3058.

Proposed resolution:

Replace [futures.shared_future]p22 with the following:

Effects: If the associated state contains a deferred function, executes the deferred function. Otherwise, blocks until the associated state is ready. was created by a promise or packaged_task object, block until the associated state is ready. If the associated state is associated with a thread created for an async call (32.10.9 [futures.async]), as if associated-thread.join().

If the associated state contains a deferred function, calls to wait() on all shared_future objects that share the same associated state are serialized. The first call to wait() that shares a given associated state executes the deferred function and stores the return value or exception in the associated state.

Synchronization: if the associated state was created by a promise object, the completion of set_value() or set_exception() to that promise happens before (6.9.2 [intro.multithread]) wait() returns. If the associated state was created by a packaged_task object, the completion of the associated task happens before wait() returns. If the associated state is associated with a thread created for an async call (32.10.9 [futures.async]), the completion of the associated thread happens-before wait() returns.

If the associated state contained a deferred function, the invocation of the deferred function happens-before any call to wait() on a future that shares that state returns.