我有一个有点独特和有趣(而且很糟糕)的场景,它迫使我做一些棘手的事情。问题如下:
- 我们需要一个原子类型来在实时线程和后台加载线程之间进行无锁同步。
类型(不幸的是)必须编译:
一个。 QNX 只有 c++03,但支持
boost::atomic
。具有 c++11 但无法构建
boost::atomic
的 Nucleus
这迫使我考虑同时使用 boost::atomic
和 std::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
类型。幸运的是,boost
和 std
实现几乎完全匹配。
然后在每个单独的操作系统文件中,像这样:
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
需要构建的库,请参阅 src
和 test
https://github.com/boostorg/atomic 中的目录, 但是,使用 boost::atomic<T>
不需要这些。
关于c++ - 包装原子类型并确保它保持原子性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54804154/