问题 如何使用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;
}

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

所有使用的例子 <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);
}

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


7478
2017-11-15 14:16


起源

我认为你不能拥有 atomic<T&>。并且指针版本是错误的(存储的指针本身将是原子的,而不是指向的值)。 - interjay
不,如果没有特定于实现的东西,这根本不起作用。 - R. Martinho Fernandes
也许是时候把它转换成了 std::atomic<int> 对于港口?考虑到这一点 long 在Windows和OSX上有不同的大小,你可能不得不做一些特定于操作系统的东西。 - Bo Persson
你确定? iOS有4字节的整数和长整数,我也想过Win32。那你是什么意思?假设我可以在这里到处使用整数。这对我有什么帮助? - Jean-Denis Muys
如果你可以使用 std::atomic<int> 要么 std::atomic<long> 你可以用 atomic_fetch_add 增加变量的操作。看看我的回答。 - Robertas


答案:


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

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

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


11
2017-11-15 17:11



我以前很怕那个。你正确地总结了我的情况。谢谢你的评估。 - Jean-Denis Muys


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


2
2017-11-15 14:44



这需要现有的 std::atomic 变量。 - R. Martinho Fernandes
由于他从Windows移植代码,他可以考虑到这一点并引入原子变量(long - > std :: atomic <long>) - Robertas
他当然可以,但这不是他要问的问题。问题具体说他想要通过 long* 代替 std::atomic<long>。 - interjay
嗯,对不起我错过了这部分: 在这里,我想使用一个现有的长变量,调用者通过地址传递给我... - Robertas


__atomic_add_fetch GCC扩展

在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);
}

我不确定铿锵,但似乎有一些选择 __c11_atomic_fetch_add  http://clang.llvm.org/docs/LanguageExtensions.html

正如其他人提到的,争论 p 本身就必须如此 std::atomic 让你只使用标准的库方法:将指针转换为原子并没有帮助,因为原子指针只作用于指针,而不是它指向的指针。


2
2018-06-17 07:06



另请注意,GCC内置可能会或可能不会在clang中提供。 - caps
@caps他们在什么条件下可用? clang版本,构建选项等 - Ciro Santilli 新疆改造中心 六四事件 法轮功
就我而言,在CentOS 6上使用Clang 3.7.0 std=c++14 并使用gcc的标准库实现。最后一点可能是关键点,因为我想这就是拉动它的地方 __atomic_add_fetch 从。我的IDE(在OSX上运行)无法识别该功能。 - caps