I want to atomically swap two big memory locations defined as the struct VValue
. Since the size of the struct is bigger that long
, there is no architectural support to directly compare and swap the two structs. However, one way is to swap the pointers of the two structs and indirectly swap the memory locations.
Below is my code that is supposed to swap oldValue
with b
. The compare and swap builtin is used inside a do-while
loop to make sure that the value of oldValue
has not changed possibly by other threads while the swap is taking place (this code snippet is the simplified version of a more complicated swap with other conditions. Conditions are removed for brevity).
template<typename A, typename B, typename C, typename D>
struct VStructType{
A a;
B b;
C c;
D d;
VStructType () {
;
}
VStructType (A a, B b, C c, D d) {
this->a = a;
this->b = b;
this->c = c;
this->d = d;
}
};
typedef VStructType<uint32_t,uint32_t,uint32_t,uint32_t> VValue;
bool swap(VValue* oldValue, VValue b)
{
bool r = 0;
VValue* c;
VValue *w = new VValue();
do{
c = oldValue;
w->a = b.a;
w->b = b.b;
w->c = b.c;
w->d = b.d;
} while (!(r = __sync_bool_compare_and_swap(&oldValue, c, w)));
return r;
}
int main()
{
VValue oldValue = VValue(1,2,3,4);
VValue b = VValue(10,12,2,8);
swap(&oldValue, b);
}
The problem is that after the swap inside the swap function, the value of the oldValue
is changed to the new value, but after returning from the swap function the oldValue
is not changed. It seems like the reference to the oldValue
is a temporary reference and when the swap happens it only swaps the new reference not the actual pointer to the oldValue
. The reason that the reference is passed to the __sync_bool_compare_and_swap
function is that the first argument is the pointer to a variable whose value is to be compared with.
My questions:
1) Is there a way to pass the pointer of the pointer of oldValue
directly to the __sync_bool_compare_and_swap
function?
2) Is this approach possible when the oldValue
is an element in an array?
Note: use g++ -latomic -std=gnu++11
to compile.