我想我在这里遗漏了一些明显的东西。我有这样的代码:
int *a = <some_address>;
int *b = <another_address>;
[...]
int *tmp = a;
a = b; b = tmp;
我想原子地这样做。我一直在研究__c11_atomic_exchange
和OSX OSAtomic方法,但似乎没有任何东西可以原子地执行直接交换。他们都可以原子地将2个变量的 1 写入一个值,但不能同时写两个。
有什么想法吗?
答案 0 :(得分:5)
这取决于您的架构,有效和高效的可能性。在任何情况下,您都需要将要交换的两个指针在内存中相邻,最简单的就是像
那样。typedef struct pair { void *a[2]; } pair;
然后你可以,如果你有一个完整的C11编译器使用_Atomic(pair)
作为原子类型来交换这样的pair
的内容:首先加载临时的实际对,构造一个新的如果交换了两个值,则执行比较交换以存储新值并在必要时进行迭代:
inline
void pair_swap(_Atomic(pair) *myPair) {
pair actual = { 0 };
pair future = { 0 };
while (!atomic_compare_exchange_weak(myPair, &actual, future)) {
future.a[0] = actual.a[1];
future.a[1] = actual.a[0];
}
}
根据您的体系结构,这可能是通过无锁原语操作实现的。现代64位架构通常具有128位原子,这可能导致只有128位汇编指令。
但这很大程度上取决于平台上原子实现的质量。 P99将为您提供一个实现,它实现原子操作的“功能”部分,并在检测到时支持128位交换;在我的机器上(64位Intel linux),这有效地编译成lock cmpxchg16b
指令。