$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [boost] [atomic] Generalized read-modify-write operation
From: Andrey Semashev (andrey.semashev_at_[hidden])
Date: 2015-09-01 20:11:48
On 02.09.2015 02:20, Gavin Lambert wrote:
> On 1/09/2015 21:35, Andrey Semashev wrote:
>> I was wondering is there would be interest in a generalized
>> read-modify-write operation in Boost.Atomic. The idea is to have a
>> atomic<T>::read_modify_write method that would take a function that
>> would perform the modify on the atomic value. The interface could be
>> roughly this:
> [...]
>> Does this look interesting to anyone? Comments?
>
> It's not strictly necessary since it's equivalent to a do { r =
> modify(n); } while (!var.compare_exchange_weak(n, r, order)) loop, which
> isn't that much more typing. (Although I elided the initial load, so
> it's a bit more typing than it appears here.)
Yes, correct. r and n also have to be declared outside the loop, which
is kind of annoying.
> (And the above is also supposed to use LL/SC on architectures where this
> is cheaper than CAS, although I'm not sure if this is the case.)
I'm not sure there are architectures that implement both CAS and LL/SC
instructions, at least I'm not aware of such. On the architectures that
support LL/SC, the instructions will be used to implement
compare_exchange_weak. The modify function in this CAS loop will not be
executed within the LL/SC region, which is why the additional load
before the loop is required. There is also a probability of CAS failure.
There is another point to consider. compare_exchange_weak/strong
opereation on an LL/SC architecure is more complex than what is required
to implement a simple RMW operation. For example, let's see it in
Boost.Atomic code for ARM. Here is fetch_add, which can be used as a
prototype of what could be done with a generic RMW operation:
"1:\n"
"ldrex %[original], %[storage]\n"
"add %[result], %[original], %[value]\n" // modify
"strex %[tmp], %[result], %[storage]\n"
"teq %[tmp], #0\n"
"bne 1b\n"
Frankly, I'd like to be able to generate code like this for operations
other than those defined by the standard atomic<> interface.
And here is CAS (weak):
"mov %[success], #0\n"
"ldrex %[original], %[storage]\n"
"cmp %[original], %[expected]\n"
"itt eq\n"
"strexeq %[success], %[desired], %[storage]\n"
"eoreq %[success], %[success], #1\n"
To this we will also have to add the load, the modify and the loop.
> But provided that the code generated is no worse than this (in
> particular that the compiler can inline the function call in optimised
> builds, at least where the function is relatively simple) then it would
> still be useful, particularly for people who aren't used to using weak
> exchange loops.
I certainly hope the compiler will be able to inline the modify
function. If it doesn't, for relatively simple functions, then it
probably isn't worth it.