如何使用 C++11 实现指向整数的指针的原子增量<atomic>?

How to implement an atomic increment of a pointer to an integer using C++11 <atomic>?

本文关键字:gt lt atomic 实现 C++11 何使用 指针 整数      更新时间:2023-10-16

在将一些Windows C++代码移植到iOS时,我需要提供Win32的long InterlockedIncrement(long *p)调用的实现。使用<libkern/OSAtomic.h>中定义的函数,这就足够容易了。

然而,我想知道是否可以只使用C++11工具(主要是<atomic>)以与操作系统无关的方式编写它。我想出了这个,我不确定它是否能实现我想要的:

inline long InterlockedIncrement(long* p)
{
std::atomic<long&> atomicP(*p);
return ++atomicP;
}

这行得通吗?这足够好吗?这两行不是原子的,但增量应该是原子的,这是这里的关键。

我发现的<atomic>的所有使用示例都是不同的,其中std::atomic<T>是直接定义和使用的。在这里,我想使用一个现有的长变量,调用者通过地址传递给我。我找不到这样的例子。

编辑:Clang 3.2(在Xcode 4.x中)无法编译++atomicP,错误为"不能增加类型std::atomic<long&>的值"(也不能增加atomicP += 1)。

正确的方法是什么?

再次编辑:指针实现正在编译。。。

inline long InterlockedIncrement(long* p)
{
std::atomic<long*> atomicP(p);
return ++(*atomicP);
}

但我担心这不起作用,因为我不增加原子类型,而是增加指针指向的值,这不是原子类型。

您的示例实现是每次从指针构建一个新的原子。这不是std::atomic的预期用途,我不相信它能按照您的意愿工作。

据我所知,实现您想要做的事情(以独立于平台的方式消除对InterlockdIncrement的依赖)的唯一方法是将您当前调用Win32"interlock"调用的变量的所有声明替换为它们的std::原子版本。然后,您可以删除互锁调用,并使用正则值语义来原子地修改变量。无论如何,这更可读(将来也更可维护)。

我理解您希望保留现有的(经过良好测试的)代码,但我认为在您的情况下不能。

__atomic_add_fetchGCC扩展

在GCC 4.8中,C++标准库实现了带有GCC内置__atomic_add_fetchstd::atomic::operator++,因此您可以编写:

inline long InterlockedIncrement(long* p)
{
return __atomic_add_fetch(p, 1, __ATOMIC_SEQ_CST);
}

我不确定clang,但似乎有一些选择,比如__c11_atomic_fetch_addhttp://clang.llvm.org/docs/LanguageExtensions.html

正如其他人所提到的,参数p本身必须是std::atomic才能仅使用标准库方法:将指针转换为原子指针没有帮助,因为原子指针只作用于指针,而不作用于它所指向的内容。

我相信您可以使用atomic_fetch_add操作。看看这里的例子。