有没有一种方法可以让 std::atomic 的 compare_exchange_strong 方法在不平等问题上进行交流?
Is there a way to have a version of std::atomic's compare_exchange_strong method that exchanges on inequality?
我有一个原子类型,我需要将它与一个值进行原子比较,如果两个值不相等,则交换原子的值。
换句话说,compare_exchange_strong
基本上以原子方式执行此操作:
if (atomic_value == expected)
atomic_value = desired;
...我正在寻找一种方法来做到这一点:
if (atomic_value != expected)
atomic_value = desired;
(是的,我知道 compare_exchange_strong
使用按位相等进行比较,而不是 ==
运算符。而且我知道 expected
的值在比较失败时被分配。这只是出于说明目的。在我的用例中,无论比较结果如何,我都不需要原子的值。)
有什么方法可以做到这一点而不必退而求其次使用锁而不是 std::atomic
?
只需使用通常用于比较和交换的循环,但不是循环直到(新的)预期值匹配,而是循环 either 直到它匹配(并且store happens) 或者它等于你的 != expected
条件中的值,因为在这种情况下你不需要做任何事情。 (当然不要把初始值设置成那个“unless”的值,这样你就不可能第一次“成功”。)
auto observed = atomic_value.load();
for (;;)
{
if (observed == expected){
break; // no exchange
}
if (atomic_value.compare_exchange_weak(observed, desired)) {
break; // successfully exchanged observed with desired
}
}
当然,它在硬件具有 LL/SC 的架构上不是最优的,因为 C++ 不公开它。用LL/SC可以有任意条件。
你可以使用这样的东西:
#include <atomic>
#include <random>
std::atomic<int> atomVal;
int store_if_not_equal(int desired)
{
while (true) // or maxloop....
{
int expected = desired;
if (atomVal.compare_exchange_strong(expected, desired))
{
// values matched - do nothing
return 0;
}
else
{
//expected now contains the "current value"
// another thread could have sneaked in and changed it,
// so only replace it if it still matches
if (atomVal.compare_exchange_strong(expected, desired))
{
// success
return 1;
}
}
// if we arrive here, retry
}
}
int main()
{
atomVal.store(rand());
return store_if_not_equal(2);
}
我有一个原子类型,我需要将它与一个值进行原子比较,如果两个值不相等,则交换原子的值。
换句话说,compare_exchange_strong
基本上以原子方式执行此操作:
if (atomic_value == expected)
atomic_value = desired;
...我正在寻找一种方法来做到这一点:
if (atomic_value != expected)
atomic_value = desired;
(是的,我知道 compare_exchange_strong
使用按位相等进行比较,而不是 ==
运算符。而且我知道 expected
的值在比较失败时被分配。这只是出于说明目的。在我的用例中,无论比较结果如何,我都不需要原子的值。)
有什么方法可以做到这一点而不必退而求其次使用锁而不是 std::atomic
?
只需使用通常用于比较和交换的循环,但不是循环直到(新的)预期值匹配,而是循环 either 直到它匹配(并且store happens) 或者它等于你的 != expected
条件中的值,因为在这种情况下你不需要做任何事情。 (当然不要把初始值设置成那个“unless”的值,这样你就不可能第一次“成功”。)
auto observed = atomic_value.load();
for (;;)
{
if (observed == expected){
break; // no exchange
}
if (atomic_value.compare_exchange_weak(observed, desired)) {
break; // successfully exchanged observed with desired
}
}
当然,它在硬件具有 LL/SC 的架构上不是最优的,因为 C++ 不公开它。用LL/SC可以有任意条件。
你可以使用这样的东西:
#include <atomic>
#include <random>
std::atomic<int> atomVal;
int store_if_not_equal(int desired)
{
while (true) // or maxloop....
{
int expected = desired;
if (atomVal.compare_exchange_strong(expected, desired))
{
// values matched - do nothing
return 0;
}
else
{
//expected now contains the "current value"
// another thread could have sneaked in and changed it,
// so only replace it if it still matches
if (atomVal.compare_exchange_strong(expected, desired))
{
// success
return 1;
}
}
// if we arrive here, retry
}
}
int main()
{
atomVal.store(rand());
return store_if_not_equal(2);
}