在将一些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"调用的变量的所有声明他们 然后,您可以删除互锁调用并使用常规值语义以原子方式修改变量.无论如何,这更具可读性(并且在将来更易于维护).
我知道您希望保留现有(经过良好测试的)代码,但我认为您不能这样做.
__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您仅使用标准库方法:将指针转换为原子并没有帮助,因为原子指针仅作用于指针,而不作用于它指向的内容。
| 归档时间: |
|
| 查看次数: |
13434 次 |
| 最近记录: |