14

许多 C++11 CAS 操作(例如 , atomic_compare_exchange_weakatomic_compare_exchange_strong采用两个指针和一个值,即像这样:

bool atomic_compare_exchange(T* pointer, T* expected,       // pseudodeclaration!
                             T desired);

相比之下,来自 Microsoft、gcc 和 Intel 的 CAS 操作都采用一个指针和两个值:

long InterlockedCompareExchange(long* pointer, long desired,       // Microsoft
                                long expected);

int __sync_bool_compare_and_swap (T* pointer, T expected,          // gcc and
                                  T desired);                      // Intel

为什么 C++11 CAS 函数采用两个指针和一个值,而不是看起来更传统的一个指针和两个值?

4

2 回答 2

23

C++11 方式更有用:如果交换失败,则*expected更新新的当前值。这使得在循环中使用函数变得容易:

T value = x.load();
T newvalue = frob(value);

while (!atomic_compare_exchange(&x, &value, newvalue))
{
    newvalue = frob(value);
}

有了微软的签名,测试是否操作成功就比较麻烦了,GCC的__sync_type版本也是如此。使用 GCC __sync_bool,您甚至需要在每次交换失败时执行另一个加载。

于 2013-04-16T17:57:04.460 回答
3

我不明白为什么你不会同时拥有两者。在我的用例中,C++ 版本不太有用。我想等到一个变量有某个值然后我想将它设置为一个新值。

使用 GCC 内在函数:

while (!__sync_bool_compare_and_swap(&value, expected, desired)) { }

使用 C++11:

auto tmp = expected;
while (!value.compare_exchange_weak(tmp,desired)) 
{
  tmp = expected;
}
于 2014-02-21T20:59:54.363 回答