使用C中的std :: atomic

时间:2015-10-05 22:00:17

标签: c multithreading c++11

我有一个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。

2 个答案:

答案 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兼容的结构中并转发所有方法。