Blocked Destructors in Asynchronous Futures
When a future is returned from std::async, its destructor becomes implicitly blocking, leading to the calling thread pausing. While this behavior may seem surprising, it is intentional for safety and correctness.
Reasons for Blocking Destructors
As stated by Hans Boehm in the whitepaper "N3679: Async() future destructors must wait," futures returned by async() wait for their associated shared state to become ready in their destructors. This prevents a scenario where the associated thread continues running without any way to wait for its completion once the future is destroyed. Without additional measures, such a "runaway" thread could extend beyond the lifetime of its dependent objects, potentially causing a cross-thread "memory smash" and security vulnerabilities.
Example
Consider this code snippet:
std::future<int> future = std::async(std::launch::async, run_async_task);
If the future's destructor is not blocking, the thread executing run_async_task could continue running even after the future is destroyed. If this thread accesses any objects that have already been destroyed, a runtime error will occur.
Alternative Approach
To avoid blocking behavior, explicitly call future.get() or future.wait() before destroying the future. This ensures that the associated task has completed and no longer depends on the destroyed future.
Update
Michael Wong's "Trip Report" following the C Standard meeting in September 2013 provides an updated perspective on this topic. While there was significant discussion, no changes to the blocking behavior of std::future destructors were made. Additionally, a proposal to deprecate the use of async was ultimately rejected.
The above is the detailed content of Why do Futures Returned by std::async() Have Blocking Destructors?. For more information, please follow other related articles on the PHP Chinese website!