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

Jea*_*uys 12 c++ atomic c++11

在将一些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;
}
Run Code Online (Sandbox Code Playgroud)

这有用吗?这够好吗?这两行不是原子的,但增量应该是原子的,这是关键.

<atomic>我发现的所有使用示例都不同,其中a 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);
}
Run Code Online (Sandbox Code Playgroud)

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

Sea*_*ine 12

您的示例实现每次都从指针构造一个新的原子.这不是std :: atomic的预期用途,我不相信它会如你所愿.

据我所知,执行您要做的事情的唯一方法(以独立于平台的方式移除对InterlockedIncrement的依赖)是替换当前使用std :: atomic版本调用Win32"interlock"调用的变量的所有声明他们 然后,您可以删除互锁调用并使用常规值语义以原子方式修改变量.无论如何,这更具可读性(并且在将来更易于维护).

我知道您希望保留现有(经过良好测试的)代码,但我认为您不能这样做.

  • 我以前很怕那个.你正确地总结了我的情况.谢谢你的评估. (2认同)

Cir*_*四事件 5

__atomic_add_fetch海湾合作委员会扩展

在GCC 4.8中,C++标准库std::atomic::operator++使用GCC内置实现__atomic_add_fetch,因此您可以编写:

inline long InterlockedIncrement(long* p)
{
    return __atomic_add_fetch(p, 1, __ATOMIC_SEQ_CST);
}
Run Code Online (Sandbox Code Playgroud)

我不确定 clang,但似乎有一些选项,例如__c11_atomic_fetch_add http://clang.llvm.org/docs/LanguageExtensions.html

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