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

时间:2012-11-15 14:16:36

标签: c++ c++11 atomic

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

但是,我想知道是否有可能仅使用C ++ 11工具以OS {无关的方式编写它,主要是<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);
}

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

3 个答案:

答案 0 :(得分:12)

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

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

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

答案 1 :(得分:2)

我相信你可以使用atomic_fetch_add操作。看一下示例here

答案 2 :(得分:2)

__atomic_add_fetch GCC扩展程序

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

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

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

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