12

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

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

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

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

<atomic>我发现的所有使用示例都是不同的,其中 astd::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);
}

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

4

3 回答 3

12

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

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

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

于 2012-11-15T17:11:49.140 回答
3

__atomic_add_fetchGCC 扩展

在 GCC 4.8 中,C++ 标准库std::atomic::operator++使用 GCC built-in实现__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让您仅使用标准库方法:将指针转换为原子没有帮助,因为原子指针仅作用于指针,而不作用于它指向的内容。

于 2015-06-17T07:06:32.290 回答
2

我相信你可以使用atomic_fetch_add手术。看看这里的例子。

于 2012-11-15T14:44:49.090 回答