Path: csiph.com!x330-a1.tempe.blueboxinc.net!usenet.pasdenom.info!goblin2!goblin.stu.neva.ru!newsfeed2.atman.pl!newsfeed.atman.pl!.POSTED!not-for-mail From: Edek Newsgroups: comp.programming.threads Subject: Re: questions about memory_order_seq_cst fence Date: Thu, 16 Jun 2011 00:21:01 +0200 Organization: ATMAN - ATM S.A. Lines: 88 Message-ID: References: <43eb372b-6517-4914-b647-860f1f7136ba@k15g2000pri.googlegroups.com> NNTP-Posting-Host: tarket-cp.krakow.sint.pl Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Trace: node2.news.atman.pl 1308176436 31281 213.241.90.249 (15 Jun 2011 22:20:36 GMT) X-Complaints-To: usenet@atman.pl NNTP-Posting-Date: Wed, 15 Jun 2011 22:20:36 +0000 (UTC) User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.17) Gecko/20110428 Linux/3.1.0-15 Thunderbird/3.1.0 In-Reply-To: Xref: x330-a1.tempe.blueboxinc.net comp.programming.threads:284 On 06/14/2011 05:27 PM, Masakuni Oishi wrote: > Edek wrote: >> I'm tired and I haven't followed the C++11 discussion, >> but are the fences relevant to the atomic operations >> themselves? I mean, aren't they for enforcing regular >> variables around atomics? > > The fences enforce ordering for not only regular variables > but also atomic variables. > For example: > > // Initially > atomic x(0), y(0); > > // Thread 1: > y.store(1, memory_order_relaxed); <--- this needn't be atomic, it just happens to be > x.store(1, memory_order_release); <---- This is like releasing a lock so y store must be done earlier > > // Thread 2: > r1 = x.load(memory_order_acquire); <--- This is like acquiring a lock so y load must be done later > r2 = y.load(memory_order_relaxed); <--- Might not be atomic > > > In this code, if r1 is 1, then r2 must be 1, not 0. > > -- masakuni Yes, that is what I actually meant (sorry, I'm a plain novice in this weird atomic stuff). See my above small comments. But what I also meant is the following, simplifying things > // Thread 2: > x.store(1, memory_order_release); This seems not to enforce anything, if there is no code above it in thread 2. Does it enforce anything (apart from atomicity of write)? (Quite antique these days) quote, from n2427 memory_order_release Performs a release operation on the affected memory locations, thus making regular memory writes visible to other threads through the atomic variable to which it is applied. This, however, is a sequence point (interacts with thread 1's and thread 2's fences): > // Thread 2: > x.store(1, memory_order_seq_cst); // (3) Quote: ...in addition, has sequentially-consistent operation ordering. So, if I understand this mail thread correctly, the question is whether in the code 1 case from your question the change to x made by thread 2, but - to my understanding - not really ordered in any way in code 1, is visible by threads 1 and 3 in a specified order enforced by these threads' (1 & 3) fences, or not necessarily (and y is just to show the constraints - if we can look at it for a moment from this aspect). Is everything above right, or is it more subtle? Edek PS. As a side note, I compiled all ops on x86_64, and atomic::load is mfence/load/mfence even for relaxed. I'd need some time to analyse the thing from perspective of other ops implementations in all orderings, and this leads me to the not so subtle question: I understand people _should definitely_ use the default. I assume the goal, or the official word for it is 'rationale', was to let people 'who understand' write code that would be both portable and more efficient than the default. I am somehow beginning to doubt both my capabilities and whether this will be at all possible - I mean the efficiency, not portability (the latter can be simply done right). Though maybe the bottom line is that at least the precise implementation will have at least a couple of fences less than the default, at the price of - I think no one argues about that - complexity.