C++0x |为什么 std::atomic 使用 volatile 限定符重载每个方法?

发布于 2024-10-15 14:06:24 字数 1837 浏览 9 评论 0原文

当前草案的以下摘录显示了我的意思:

namespace std {
    typedef struct atomic_bool {
        bool is_lock_free() const volatile;
        bool is_lock_free() const;
        void store(bool, memory_order = memory_order_seq_cst) volatile;
        void store(bool, memory_order = memory_order_seq_cst);
        bool load(memory_order = memory_order_seq_cst) const volatile;
        bool load(memory_order = memory_order_seq_cst) const;
        operator bool() const volatile;
        operator bool() const;
        bool exchange(bool, memory_order = memory_order_seq_cst) volatile;
        bool exchange(bool, memory_order = memory_order_seq_cst);
        bool compare_exchange_weak(bool&, bool, memory_order, memory_order) volatile;
        bool compare_exchange_weak(bool&, bool, memory_order, memory_order);
        bool compare_exchange_strong(bool&, bool, memory_order, memory_order) volatile;
        bool compare_exchange_strong(bool&, bool, memory_order, memory_order);
        bool compare_exchange_weak(bool&, bool, memory_order = memory_order_seq_cst) volatile;
        bool compare_exchange_weak(bool&, bool, memory_order = memory_order_seq_cst);
        bool compare_exchange_strong(bool&, bool, memory_order = memory_order_seq_cst) volatile;
        bool compare_exchange_strong(bool&, bool, memory_order = memory_order_seq_cst);
        atomic_bool() = default;
        constexpr atomic_bool(bool);
        atomic_bool(const atomic_bool&) = delete;
        atomic_bool& operator=(const atomic_bool&) = delete;
        atomic_bool& operator=(const atomic_bool&) volatile = delete;
        bool operator=(bool) volatile;
    } atomic_bool;
}

易失性是传递的。因此,您不能从易失性对象调用非易失性成员函数。另一方面,允许从非易失性对象调用易失性成员函数。

那么,原子类中的易失性和非易失性成员函数在实现上有什么区别吗?换句话说,是否需要非易失性重载?

The following excerpt from the current draft shows what I mean:

namespace std {
    typedef struct atomic_bool {
        bool is_lock_free() const volatile;
        bool is_lock_free() const;
        void store(bool, memory_order = memory_order_seq_cst) volatile;
        void store(bool, memory_order = memory_order_seq_cst);
        bool load(memory_order = memory_order_seq_cst) const volatile;
        bool load(memory_order = memory_order_seq_cst) const;
        operator bool() const volatile;
        operator bool() const;
        bool exchange(bool, memory_order = memory_order_seq_cst) volatile;
        bool exchange(bool, memory_order = memory_order_seq_cst);
        bool compare_exchange_weak(bool&, bool, memory_order, memory_order) volatile;
        bool compare_exchange_weak(bool&, bool, memory_order, memory_order);
        bool compare_exchange_strong(bool&, bool, memory_order, memory_order) volatile;
        bool compare_exchange_strong(bool&, bool, memory_order, memory_order);
        bool compare_exchange_weak(bool&, bool, memory_order = memory_order_seq_cst) volatile;
        bool compare_exchange_weak(bool&, bool, memory_order = memory_order_seq_cst);
        bool compare_exchange_strong(bool&, bool, memory_order = memory_order_seq_cst) volatile;
        bool compare_exchange_strong(bool&, bool, memory_order = memory_order_seq_cst);
        atomic_bool() = default;
        constexpr atomic_bool(bool);
        atomic_bool(const atomic_bool&) = delete;
        atomic_bool& operator=(const atomic_bool&) = delete;
        atomic_bool& operator=(const atomic_bool&) volatile = delete;
        bool operator=(bool) volatile;
    } atomic_bool;
}

Volatile is transitive. Thus, you cannot call a non-volatile member function from a volatile object. On the other hand, calling a volatile member function from a non-volatile object is allowed.

So, is there any implementation difference between the volatile and non-volatile member functions in the atomic classes? In other words, is there any need for the non-volatile overload?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

放血 2024-10-22 14:06:24

我认为挥发性重载的存在是出于效率原因。在 C++0x 中,易失性读写本质上比非易失性读写更昂贵,因为内存模型提出了一些严格的要求,阻止缓存易失性变量的值。如果所有函数仅被标记为易失性,那么代码不一定能够进行某些可以提高性能的优化。具有这种区别允许编译器在可能的情况下优化非易失性读取和写入,同时在需要易失性读取和写入时优雅地降级。

I think that the volatile overloads exist for efficiency reasons. Volatile reads and writes are inherently more expensive than non-volatile reads and writes in C++0x, since the memory model puts some stringent requirements that prevent caching of values of volatile variables. If all the functions were only marked volatile, then the code couldn't necessarily make certain optimizations that would otherwise improve performance. Having the distinction allows the compiler to optimize non-volatile reads and writes when possible while degrading gracefully when volatile reads and writes are required.

第七度阳光i 2024-10-22 14:06:24

首先,创建一个易失性的 std::atomic 听起来是多余的。事实上,我可以想象一个有用的情况。假设我们有一个要操作的固定设备(内存)地址。由于 std::atomic_xxx 类以及 std::atomic<> 类都是事实。模板类的大小应该与其相应的内置类型的大小相同,您可能想要同时处理这两者:通过控制内存排序来执行原子操作,并确保对原子对象的访问永远不会被优化。因此,我们可以声明如下:

std::atomic<long> volatile* vmem_first4 = reinterpret_cast<std::atomic<long> volatile*>(0xxB8000);

First, it sounds redundant to make a volatile std::atomic. Actually, I can imagine an useful situation. Assuming we have an fixed device (memory-)address we want to operate on. Due to the fact that the std::atomic_xxx classes as well as the std::atomic<> template class sizes should be same size as their corresponding built-in-types, you might want to handle both: Performing atomic operations with control over memory ordering and make sure that the access to our atomic-object is never optimized. Thus, we could declare something like:

std::atomic<long> volatile* vmem_first4 = reinterpret_cast<std::atomic<long> volatile*>(0xxB8000);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文