The following test case results in a deadlock: #include <chrono> #include <future> #include <iostream> #include <utility> template <typename T> struct weird { std::future<weird<T>> f; explicit weird(std::future<weird<T>> f) : f(std::move(f)) {} weird(weird&& other) : f(std::move(other.f)) { if (f.wait_for(std::chrono::seconds(1)) == std::future_status::timeout) { std::cout << "Moving but the future is not ready yet\n"; } } }; int main() { std::promise<weird<int>> p; weird<int> w(p.get_future()); p.set_value(std::move(w)); } This is caused by executing arbitrary user code under a lock.
Yikes... Thanks for the report.
@K-Ballo. Do you think that this code should actually work? It seems to me that this is likely non-standard.
(In reply to comment #2) > @K-Ballo. Do you think that this code should actually work? It seems to me > that this is likely non-standard. Yes, I think this code is required to actually work. What makes you think this is non-standard?
I think the only possible way to fix this (without breaking the ABI) is to: 1. Release the lock while constructing the value. 2. Use the top bits of the `__state_` variable to implement a "construction lock" that will allow us to serialize multiple calls to "set_value(...)" I'm not yet sure if this is going to work. I think it's likely that these changes aren't going to play nice with older versions of libc++.