【C++编程】函数__atomic_compare_exchange_n
函数__atomic_compare_exchange_n
1. 函数原型:
bool __atomic_compare_exchange_n (type *ptr, type *expected, type desired, bool weak, int success_memorder, int failure_memorder)
函数说明:
它会将 *ptr 的内容与 *expected 的内容进行比较:
-
如果两者相等,则执行一次**读-修改-写(read-modify-write)**操作,把
desired写入*ptr。 -
如果两者不相等,则执行一次读取操作,并将当前
*ptr的内容写入*expected。
参数 weak:
-
当
weak = true时,表示使用弱 compare_exchange,这种方式可能会发生“伪失败”(即即使值相等也可能失败)。 -
当
weak = false时,表示使用强 compare_exchange,它不会发生伪失败。 -
许多目标平台只提供强版本,并会忽略该参数。
-
如果不确定,建议使用强版本。
如果成功将 desired 写入 *ptr:
-
函数返回
true -
内存顺序(memory order)按照
success_memorder指定的方式生效 -
这里对可使用的内存顺序没有限制
如果没有写入成功:
-
函数返回
false -
内存顺序按照
failure_memorder指定的方式生效 -
该内存顺序不能是
__ATOMIC_RELEASE或__ATOMIC_ACQ_REL -
并且不能比
success_memorder指定的内存顺序更强
his built-in function implements an atomic compare and exchange operation. This compares the contents of *ptr with the contents of *expected. If equal, the operation is a read-modify-write operation that writes desired into *ptr. If they are not equal, the operation is a read and the current contents of *ptr are written into *expected. weak is true for weak compare_exchange, which may fail spuriously, and false for the strong variation, which never fails spuriously. Many targets only offer the strong variation and ignore the parameter. When in doubt, use the strong variation.
If desired is written into *ptr then true is returned and memory is affected according to the memory order specified by success_memorder. There are no restrictions on what memory order can be used here.
Otherwise, false is returned and memory is affected according to failure_memorder. This memory order cannot be __ATOMIC_RELEASE nor __ATOMIC_ACQ_REL. It also cannot be a stronger order than that specified by success_memorder.
1. 例子:gcc内置CAS函数实现spinlock:
#include <stdio.h>
#include <stdbool.h>
#include <pthread.h>
#define THREAD_NUM 32
volatile unsigned int sum = 0;
unsigned int max = 10000000;
volatile bool cond = true;
typedef int slock_t;
static __inline__ int cas(volatile slock_t *lock)
{
slock_t expected = 0;
return !(__atomic_compare_exchange_n(lock, &expected, (slock_t)1, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE));
}
#define S_UNLOCK(lock) __atomic_store_n(lock, (slock_t)0, __ATOMIC_RELEASE)
#define S_INIT_LOCK(lock) S_UNLOCK(lock)
#define SPIN(lock) (*(lock) ? 1 : cas(lock))
volatile slock_t g_lock;
int s_lock(volatile slock_t *lock)
{
int i = 0;
while (SPIN(lock)) {
++i;
}
return i;
}
void *thread_func(void *args)
{
while ((cond = sum < max)) {
s_lock(&g_lock);
++sum;
S_UNLOCK(&g_lock);
}
return NULL;
}
int main(void)
{
pthread_t pids[THREAD_NUM];
int i, ret;
void *val;
double start, end;
S_INIT_LOCK(&g_lock);
for (i = 0; i < THREAD_NUM; ++i) {
ret = pthread_create(&pids[i], NULL, thread_func, NULL);
}
for (i = 0; i < THREAD_NUM; ++i) {
pthread_join(pids[i], &val);
}
printf("final sum: %d\n", sum);
return 0;
}

浙公网安备 33010602011771号