Boost logo

Boost :

Subject: Re: [boost] [lockfree] review
From: Gottlob Frege (gottlobfrege_at_[hidden])
Date: 2011-08-25 00:04:35


On Wed, Aug 24, 2011 at 4:27 PM, Dave Abrahams <dave_at_[hidden]> wrote:
>
> on Wed Aug 24 2011, Alexander Terekhov <terekhov-AT-web.de> wrote:
>
>> Dave Abrahams wrote:
>>>
>>> All I'm saying here is that a C++11 default atomic int is equivalent to
>>> an int, coupled with an associated mutex, where accesses to the int are
>>> always protected by locking the associated mutex.  If you're seriously
>>> disagreeing with *that*, please say explicitly on what grounds.
>>
>>   int i; mutex mi,
>>   int j; mutex mj;
>>
>>   mi.lock();
>>   i = 1;
>>   mi.unlock();
>>
>>   mj.lock();
>>   j = 2;
>>   mj.unlock();
>>
>> can be transformed to
>>
>>   multi_lock(mi, mj); // deadlock free
>>   j = 2;
>>   i = 1;
>>   mi.unlock();
>>   mj.unlock();
>>
>> and thus result in reodering i = 1 and j = 2.
>>
>> With C++11 default atomics (SC) for i and j such reodering is
>> prohibited.
>
> As it is with C++11 mutexes, IIUC.  Another thread that locks the same
> mutexes is not allowed to observe the write to j before the write to i.
> If you have contrary evidence, please point to it.
>

FWIW, I agree with Alexander here. It is also a case I've thought
about in the past. I'm not exactly sure about C++ mutexes, but
typically mutexes have acquire on entry/lock, release on exit/unlock,
which allows the lock regions to overlap. I would hope C++ mutexes
match the semantics of posix, etc, mutexes.

I think from C++11 standards perspective, it comes down to the
definition of "happens-before", and the lack of a good single
synchronization point (ie mi and mj don't synchronize with each
other). But I'd need to read that section again clearly to be able to
prove how it works. Instead I'm relying on my understanding of other
mutexes and critical sections (basically, code can drift in, but not
drift out). And my understanding has been that C++ is the same.

C++ atomics (with default SC) are more like having all atomics using
*the same mutex*, not one mutex per atomic. I'm not sure it is
exactly the same, ie whether it is bidirectional, but you do need
stronger than mutex-per.

In relation to Alexander's comments in general, and C++11 MM in general:
1. I wish that C++11 atomics defaulted to acquire-on-read and
release-on-write, and that's how I will almost always use them. It is
also what java and C# use, I believe (on volatiles).
2. they could have gone with more fine grained details and options,
but I think it is complicated enough. If you really want, you can
still always resort to asm. Also, I suspect they would always be
adding new options (write-through cache vs blah blah blah) which blows
away any sense of abstract model.

3. I didn't go to the meetings and voice my concerns, or even email my
national rep (well, maybe once), so I'm not complaining.

Tony


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