On Wed, Jul 1, 2015 at 6:29 AM, Niall Douglas
On 30 Jun 2015 at 22:37, Michael Marcin wrote:
I'm not sure that _need_locks being changed inside of get_future is always going to be visible other threads. The documentation says it will be thread safe after you have called get_future but I don't see anything that necessarily creates a happens-before relationship between other threads reading _needs_locks. I am not an expert though.
It's a good question, and thank you for taking the time to review the code and the design.
What you are missing is that we assume that whoever is calling get_future() must issue some form of memory synchronisation to transmit the newly constructed future to another thread. That synchronises the changed _needs_locks to other threads. I suppose it is possible that someone could send the future to one thread, and have a different thread do a state read and in theory the state reading thread doesn't see any new state.
_needs_locks concerned me as well, but I haven't had enough time to look at it closely (and I have some faith in Niall :-) Any time there is a flag about locks, but it isn't synchronized, it look suspicious. My first thought was the same as what Niall is saying - there will be synchronization elsewhere. But I still think it needs to be thought through to be sure. The common case is future<int> fi = someFunction(a, b, c); so someFunction() typically builds a promise (or something with a promise) and gets a future from it, _then_ sends the promise off to another thread to fulfill the promise (with synchronization happening when sending it off). So at that point, the value of _needs_locks, whatever it is, is valid for both the future thread and the promise thread. But without looking at all the code, I'm not sure who/what/when _needs_locks ever changes. Assuming both the promise and the future side READ it, and one of them can WRITE it, then the writer needs a release on setting, and the other side needs an acquire on every read. If only one side can set, the setter side never needs anything beyond the release, and only needs release after the other side has gone off onto its own thread. But I haven't looked at the code enough to know the details of which cases apply. As for multiple threads reading the future: No. IIUC, std::future isn't thread-safe on its own. It can only be used by one thread (without extra external synchronization). It only guarantees no data races relative to the other thread holding the promise, not to other threads trying to read the same future. Tony