原子递减联合的数据成员?
Atomically decrement data member of a union?
我在与 uint64_t 的联合中有一个结构,提供对两个 int32_t 的访问。我想以原子方式递减其中一个结构成员。我想到了这个:
class{
public:
void atomicallyDecrement_B(const int32_t decrementByThisValue){
MyUnion newUnion;
MyStruct currentStruct = _union._data;
do{
const int32_t currentB = currentStruct.b;
const int32_t currentA = currentStruct.a;
const int32_t newB = currentB - decrementByThisValue;
newUnion._data.a = currentA;
newUnion._data.b = newB;
}
while(!std::atomic_compare_exchange_weak(&_union._data, ¤tStruct, newUnion._data));
}
private:
struct MyStruct{
int a;
int b;
};
union MyUnion{
MyUnion(){
_data.a = 0;
_data.b = 0;
}
MyStruct _data;
uint64_t _atomic;
} _union;
};
但似乎 atomic_compare_exchange_weak()
的第一个参数本身必须是原子类型。有什么方法可以执行此操作 而无需 将 uint64_t 数据成员更改为 std::atomic<uint64_t>
?
我正在使用 GCC 5.2
是的,有很多方法可以做到这一点。您可以使用此处找到的 GCC 原子内置函数:https://gcc.gnu.org/onlinedocs/gcc-4.4.5/gcc/Atomic-Builtins.html 或者您可以使用 OS 提供的原子函数。第三种选择是使用原子汇编指令。
GCC 具有内置的原子操作。它们在 this page.
上有描述
您要查找的操作是
type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...)
或
bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...)
这些内置函数执行原子比较和交换。即如果*ptr当前值为oldval,则将newval写入*ptr.
Windows 用户对应的能力是
LONG __cdecl InterlockedCompareExchange(
_Inout_ LONG volatile *Destination,
_In_ LONG Exchange,
_In_ LONG Comparand
);
描述的是here
使用 gcc 内在函数的 bool 形式的示例:
do{
int oldVal = protectedVal;
int newVal = someFunction(oldVal);
} while (__sync_bool_compare_and_swap(&protectedVal, oldVal, newVal);
我在与 uint64_t 的联合中有一个结构,提供对两个 int32_t 的访问。我想以原子方式递减其中一个结构成员。我想到了这个:
class{
public:
void atomicallyDecrement_B(const int32_t decrementByThisValue){
MyUnion newUnion;
MyStruct currentStruct = _union._data;
do{
const int32_t currentB = currentStruct.b;
const int32_t currentA = currentStruct.a;
const int32_t newB = currentB - decrementByThisValue;
newUnion._data.a = currentA;
newUnion._data.b = newB;
}
while(!std::atomic_compare_exchange_weak(&_union._data, ¤tStruct, newUnion._data));
}
private:
struct MyStruct{
int a;
int b;
};
union MyUnion{
MyUnion(){
_data.a = 0;
_data.b = 0;
}
MyStruct _data;
uint64_t _atomic;
} _union;
};
但似乎 atomic_compare_exchange_weak()
的第一个参数本身必须是原子类型。有什么方法可以执行此操作 而无需 将 uint64_t 数据成员更改为 std::atomic<uint64_t>
?
我正在使用 GCC 5.2
是的,有很多方法可以做到这一点。您可以使用此处找到的 GCC 原子内置函数:https://gcc.gnu.org/onlinedocs/gcc-4.4.5/gcc/Atomic-Builtins.html 或者您可以使用 OS 提供的原子函数。第三种选择是使用原子汇编指令。
GCC 具有内置的原子操作。它们在 this page.
上有描述您要查找的操作是
type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...)
或
bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...)
这些内置函数执行原子比较和交换。即如果*ptr当前值为oldval,则将newval写入*ptr.
Windows 用户对应的能力是
LONG __cdecl InterlockedCompareExchange(
_Inout_ LONG volatile *Destination,
_In_ LONG Exchange,
_In_ LONG Comparand
);
描述的是here
使用 gcc 内在函数的 bool 形式的示例:
do{
int oldVal = protectedVal;
int newVal = someFunction(oldVal);
} while (__sync_bool_compare_and_swap(&protectedVal, oldVal, newVal);