Boost logo

Boost :

Subject: Re: [boost] Lightweight futures (was: Re: Final lightweight monad, next gen futures and upcoming AFIO review
From: Gottlob Frege (gottlobfrege_at_[hidden])
Date: 2015-07-02 14:26:08


On Wed, Jul 1, 2015 at 6:29 AM, Niall Douglas <s_sourceforge_at_[hidden]> wrote:
> 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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk