c++ - 包装原子类型并确保它保持原子性

标签 c++ multithreading c++11 boost thread-safety

我有一个有点独特和有趣(而且很糟糕)的场景,它迫使我做一些棘手的事情。问题如下:

  1. 我们需要一个原子类型来在实时线程和后台加载线程之间进行无锁同步。
  2. 类型(不幸的是)必须编译:

    一个。 QNX 只有 c++03,但支持 boost::atomic

    具有 c++11 但无法构建 boost::atomic

  3. 的 Nucleus

这迫使我考虑同时使用 boost::atomicstd::atomic。我处理这个问题的方法是生成一个新类型,将所有功能转发给平台上相关的 atomic 类型。这个想法是这样的:


原子.hpp

namespace osal { namespace detail {

template <typename T, template <class> class TAtomic >
struct AtomicImpl {

    void store(T desired, memory_order order = osal::memory_order_seq_cst) 
    {
        _atomic.store(desired, order);
    }

    // ... Other api

private:

    AtomicImpl& operator=(const AtomicImpl& rhs);
    // ... Other blocked operations
    TAtomic<T> _atomic;
};

}}


#if defined QNX
    #include <osal/QNX/Atomic.hpp>
#elif defined NUCLEUS
    #include <osal/NUCLEUS/Atomic.hpp>
#endif

这布置了一个类,该类将使用正确的 API 转发到 atomic 类型。幸运的是,booststd 实现几乎完全匹配。


然后在每个单独的操作系统文件中,像这样:

Nucleus/Atomic.hpp

#include <atomic>

namespace osal 
{ 

template <typename T> struct atomic
   {
      typedef detail::AtomicImpl<T, std::atomic> type;
   };
}

这将创建具有 std::atomic 的原子类型,允许像这样使用:

osal::atomic<uint8_t>::type a;
a.store(1);

为了处理内存顺序的概念,存在一个类似的系统,其中有一个文件可以委托(delegate)给使用预处理器的每个 OS 实现。在实现中,例如。 Nucleus,我们有这个:

Nucleus/MemoryOrder.hpp

#include <memory>
namespace osal {

using std::memory_order;
using std::memory_order_relaxed;
...
}

显然,等效的 using boost::... 将出现在 QNX 文件中(幸运的是它们再次匹配!)。

问题

这似乎有效。我可以创建一个原子并对其进行操作。我有一个问题:

这仍然是原子的吗?

既然我们在 API 中引入了间接寻址,那么调用原子对象的顺序会不会有问题?

作为附加问题,考虑到限制条件,有没有更好的方法来做到这一点?

最佳答案

Nucleus which has c++11 but cannot build boost::atomic

boost::atomic<T> type 是 header-only,你可以使用它而无需构建 boost::atomic图书馆。

您可以使用 boost::atomic<T>直接无条件地在两个平台上使用(前提是您的平台受支持)。

有几位boost::atomic需要构建的库,请参阅 srctest https://github.com/boostorg/atomic 中的目录, 但是,使用 boost::atomic<T>不需要这些。

关于c++ - 包装原子类型并确保它保持原子性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54804154/

相关文章:

c++ - 关于为什么 Windows 的 .dll 不适用于 Linux 的细节

c++ - QList 的问题

c++ - 继承类的默认构造函数

Java:ExecutorService 的效率不如手动线程执行?

c++11 - vector 不转换大括号括起来的列表

超过 "tuple"的 C++11 范围

c++ - 我应该为 C 函数 noexcept 声明包装器吗?

c++ - 使用数组作为 While 循环条件

c# - 在单独的线程中执行长时间操作是否安全?

java - 如果我在同一个类上同步了两个方法,它们可以同时运行吗?