我有一个C库,为原子操作定义了一堆特定于平台的宏。如何使用std::atomic
作为此实现?
例如,C代码有:
#define mylib_atomic_int_add(_pi, _val) do_atomic_int_add(_pi, _val)
int number = 0;
mylib_atomic_int_add(&number, 7);
C ++平台抽象层(即编译为C ++ 11的静态库与C代码链接)具有:
extern "C"
{
int do_atomic_int_add(volatile int* i, volatile int v)
{
return *i + v;
}
}
显然这不安全,因为它不是原子的,因为在C代码std::atomic
中声明的int不能在那里使用,但是有一些方法可以在{{1}中使用它}?比如do_atomic_int_add()
?
编辑:
我不知道为什么没有人理解我想要做的事情。它基本上是如何在C ++中以原子方式递增已从C函数传递的int。
答案 0 :(得分:4)
C ++ 11 atomics 要求使用C ++ 11原子类型进行原子操作。您可以通过从非原子类型转换为原子类型来超出标准,但这不是可移植代码,即使它经常有效。它甚至不是来自完全C ++代码,更不用说C和C ++的混合了。
由于这个限制,您将无法编写带有C接口的C ++原子库,因为您无法在C代码中声明C ++ 11原子类型。
Hans Boehm是编程语言并发功能的最重要权威之一,他提出了一个标题为N4013: Atomic operations on non-atomic data的C ++ 0提案,解释了这里的一些问题。您可以在C中完全解决这个问题,这是最安全,最便携的解决方案。
C atomics至少有两种不同的开源实现和许可许可证:
此外,OpenMP 3+使您能够使用C89代码中的原子,但我不知道MSVC是否支持它。
最后,C11 atomics将以完全ISO标准的方式精美地解决您的问题。但是,编译器支持现在相当有限。我已经将这些功能用于GCC 5+和后期型号Clang,也许还有Intel 16,但我不认为MSVC会支持它们。
答案 1 :(得分:1)
正式来说,问题是std::atomic<int>
是一种类型,其对象可以通过.load()
只返回.store()
d的值进行修改。 C不会调用.load
,因此无法直接使用int
。
当然,您可以使用明显的实现来定义extern "C" int atomic_load(struct atomic_int*, enum std_memory_order)
。您必须将std::atomic_int
基本上包装在C兼容的结构中并转发所有方法。