以原子方式减少联盟的数据成员?

时间:2022-07-06 23:54:01

I have a struct in a union with uint64_t, providing access to two int32_t. I would like to decrement one of the struct members atomically. I came up with this:

我在与uint64_t的联合中有一个结构,提供对两个int32_t的访问。我想原子地减少一个struct成员。我想出了这个:

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, &currentStruct, newUnion._data));
}

private:
    struct MyStruct{
        int a;
        int b;
    };

    union MyUnion{
        MyUnion(){
            _data.a = 0;
            _data.b = 0;
        }

        MyStruct _data;
        uint64_t _atomic;
    } _union;
};

but it seems the first argument to atomic_compare_exchange_weak() must be an atomic type itself. Is there any way to perform this operation without changing the uint64_t data member to be std::atomic<uint64_t>?

但似乎atomic_compare_exchange_weak()的第一个参数必须是原子类型本身。有没有办法在不将uint64_t数据成员更改为std :: atomic 的情况下执行此操作?

I am using GCC 5.2

我正在使用GCC 5.2

2 个解决方案

#1


1  

GCC has atomic operations as built-ins. They are described on this page.

GCC将内核操作作为内置函数。它们在此页面上进行了描述。

The operation you are looking for is

您正在寻找的操作是

type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...)

or

要么

bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...)

These builtins perform an atomic compare and swap. That is, if the current value of *ptr is oldval, then write newval into *ptr.

这些内置函数执行原子比较和交换。也就是说,如果* ptr的当前值是oldval,则将newval写入* ptr。

For Windows users the corresponding capability is

对于Windows用户,相应的功能是

LONG __cdecl InterlockedCompareExchange(
  _Inout_ LONG volatile *Destination,
  _In_    LONG          Exchange,
  _In_    LONG          Comparand
);

Which is described here

这是在这里描述的

Example using the bool form of the gcc intrinsic:

使用gcc内在的bool形式的示例:

do{
   int oldVal = protectedVal;
   int newVal = someFunction(oldVal);
} while (__sync_bool_compare_and_swap(&protectedVal, oldVal, newVal);

#2


1  

Yes, there are ways to do this. You can either use GCC atomic builtins found here: https://gcc.gnu.org/onlinedocs/gcc-4.4.5/gcc/Atomic-Builtins.html or you can use atomic functions provided by your OS. The third option is to use atomic assembly instructions.

是的,有办法做到这一点。您可以使用此处的GCC原子内置函数:https://gcc.gnu.org/onlinedocs/gcc-4.4.5/gcc/Atomic-Builtins.html,也可以使用操作系统提供的原子函数。第三种选择是使用原子汇编指令。

#1


1  

GCC has atomic operations as built-ins. They are described on this page.

GCC将内核操作作为内置函数。它们在此页面上进行了描述。

The operation you are looking for is

您正在寻找的操作是

type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...)

or

要么

bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...)

These builtins perform an atomic compare and swap. That is, if the current value of *ptr is oldval, then write newval into *ptr.

这些内置函数执行原子比较和交换。也就是说,如果* ptr的当前值是oldval,则将newval写入* ptr。

For Windows users the corresponding capability is

对于Windows用户,相应的功能是

LONG __cdecl InterlockedCompareExchange(
  _Inout_ LONG volatile *Destination,
  _In_    LONG          Exchange,
  _In_    LONG          Comparand
);

Which is described here

这是在这里描述的

Example using the bool form of the gcc intrinsic:

使用gcc内在的bool形式的示例:

do{
   int oldVal = protectedVal;
   int newVal = someFunction(oldVal);
} while (__sync_bool_compare_and_swap(&protectedVal, oldVal, newVal);

#2


1  

Yes, there are ways to do this. You can either use GCC atomic builtins found here: https://gcc.gnu.org/onlinedocs/gcc-4.4.5/gcc/Atomic-Builtins.html or you can use atomic functions provided by your OS. The third option is to use atomic assembly instructions.

是的,有办法做到这一点。您可以使用此处的GCC原子内置函数:https://gcc.gnu.org/onlinedocs/gcc-4.4.5/gcc/Atomic-Builtins.html,也可以使用操作系统提供的原子函数。第三种选择是使用原子汇编指令。