__sync_val_compare_and_swap vs __sync_bool_compare_and_swap
__sync_val_compare_and_swap vs __sync_bool_compare_and_swap
我一直在考虑这两个函数的返回值。__sync_bool_compare_and_swap函数的返回值似乎有明显的好处,即我可以用它来判断交换操作是否发生。但是,我看不出__sync_val_compare_and_swap的返回值有多大用处。
首先,让我们有一个函数签名供参考(来自GCC文档减去var args):
type __sync_val_compare_and_swap (type *ptr, type oldval type newval);
我看到的问题是__sync_val_compare_and_swap的返回值是*ptr的旧值。准确地说,这是在设置了适当的内存屏障后,该函数的实现所看到的值。我明确指出这一点是为了满足这样一个事实,即在调用__sync_val_compare_and_swap和执行指令以强制执行内存屏障之间,*ptr的值可以很容易地更改。
现在,当函数返回时,我该如何处理该返回值?尝试将它与*ptr进行比较是没有意义的,因为*ptr现在可以在其他线程上更改。同样,比较newval和*ptr对我也没有真正的帮助(除非我锁定*ptr,这可能会首先破坏我对原子的使用)。
因此,我真正要做的就是询问返回值是否=oldval,这实际上是在询问交换操作是否发生。所以我本可以使用__sync_bool_compare_and_swap。
我刚才提到的警告是,我在这里看到的唯一细微的区别是,这样做并不能告诉我是否发生了交换,它只是"告诉"我在内存屏障释放之前的某个时刻*ptr与newval具有相同的值。我正在考虑oldval==newval的可能性(尽管我很难找到一种有效实现函数的方法,这样它就可以首先检查这些值,如果它们相同,就不会交换,所以这可能是一个没有意义的问题)。然而,在呼叫现场,我看不出知道这种差异会对我产生什么影响。事实上,我无法想象我会将oldval和newval设置为相等的情况。
因此,我的问题是:
是否存在使用__sync_val_compare_and_swap和__sync_bool_compare-and_swap不等效的用例,即是否存在一个提供的信息多于另一个的情况
ASIDE
我之所以考虑这一点,是因为我发现了一个根据sync_bool_compare_and_swap实现的__sync_val_compare-and_swap,它有一个种族:
inline int32_t __sync_val_compare_and_swap(volatile int32_t* ptr, int32_t oldval, int32_t newval)
{
int32_t ret = *ptr;
(void)__sync_bool_compare_and_swap(ptr, oldval, newval);
return ret;
}
竞争是在ret中存储*ptr,因为*ptr可能在调用__sync_bool_compare_and_swap之前发生更改。这让我意识到,在sync_bool_compare_and_swap方面,似乎没有一种安全的方法(没有额外的屏障或锁)来实现__sync_val_compare-and_swap。这让我想到前者必须比后者提供更多的"信息",但根据我的问题,我认为它并没有真正提供信息。
__sync_val_compare_and_swap
提供的操作总是可以根据__sync_bool_compare_and_swap
来实现(当然,另一个方向显然是可能的),因此就功率而言,两者是等价的。然而,根据__sync_bool_compare_and_swap
来实现__sync_val_compare_and_swap
不是很有效。它看起来像:
for (;;) {
bool success = __sync_bool_compare_and_swap(ptr, oldval, newval);
if (success) return oldval;
type tmp = *ptr;
__sync_synchronize();
if (tmp != oldval) return tmp;
}
需要额外的工作,因为您可以观察到__sync_bool_compare_and_swap
的故障,但随后从*ptr
中读取恰好与oldval
匹配的新值。
至于为什么您可能更喜欢__sync_val_compare_and_swap
行为,导致失败的值可能会为您提供一个更有效地重试操作的起点,或者可能指示某个不会"重试"的操作失败的有意义的原因。例如,请参阅musl-libc中pthread_spin_trylock
的代码(我是该代码的作者):
http://git.musl-libc.org/cgit/musl/tree/src/thread/pthread_spin_trylock.c?id=afbcac6826988d12d9a874359cab735049c17500
其中a_cas
相当于__sync_val_compare_and_swap
。在某些方面,这是一个愚蠢的例子,因为它只是通过使用旧值来保存分支或条件移动,但在其他情况下,可能存在多个旧值,并且知道导致操作失败的那个值很重要。
- C++核心准则 C35 对于接口类"A base class destructor should be either public and virtual, or protected and nonv
- 为什么C++逐位AND运算符在不同大小的操作数中表现为这样
- 为什么 Clang 不允许"and"作为函数名称?
- 位阵列上的快速AND运算
- 是否可以在 C++03 中定义'move-and-swap idiom'等效项
- 如何使 std::sort 在 std::swap 和我的命名空间的模板化交换之间没有名称冲突?
- BoostPython and CMake
- OpenSSL BIO and SSL_read
- Gurobi GRBModel and GRBmodel in C++
- std::visit and std::variant usage
- 我可以使用 std::vector::swap 来修改共享向量吗?
- SHBrowseForFolder with BIF_BROWSEFORCOMPUTER and SHGetPathFr
- Directx12 and keystrokes
- different between int **arr =new int [ n]; and int a[i][j]?
- C++ getenv and setenv
- Inference pytorch C++ with alexnet and cv::imread image
- Valgrind 在 std::string::swap 中报告 SIGILL
- Visual Studio 2019 C++ and std::filesystem
- 保证逻辑 AND 表达式中的函数调用
- 标准::矢量::擦除与"swap and pop"