【问题标题】:Acquire/release semantics on atomic variables accessed via []-operator获取/释放通过 []-operator 访问的原子变量的语义
【发布时间】:2014-08-01 10:58:13
【问题描述】:

假设一个原子变量数组和一个通过重载类'[]-operator 来控制对该数组的访问的类,以返回对位置idx处的原子变量的引用:

class MyClass {
public:
    MyClass()
    {
        //initalize every array element with nullptr
        for (auto& it : array) {
            it = nullptr;
        }
    }
    std::atomic<int*>& operator[](const size_t idx)
    {
         //there is some more code here, doing basic safety checks,...
         return array[idx];
    }
private:
    std::array<std::atomic<int*>, 1000> array;

}

我们可以像这样访问array的元素:

MyClass foo();
int *a = foo[0];
int b = 3;
foo[1] = &b

请注意,默认情况下,对此类元素的任何访问都将使用memory_order_seq_cst 完成。要更改强制的内存顺序,可以这样做:

int *a = foo[0].load(memory_order_acquire);
foo[1].store(&b, memory_order_release);

但是如何更改 []-operator 的实现,使 memory_order_acquire 用于所有读取,memory_order_release 用于所有写入?我想在[]-operator 的定义中这样做的原因是在源中的很多不同位置有很多访问array 的元素,我不想传播使用过的对他们所有人的记忆排序。

编辑:正如 cmets 中所讨论的,可以将 []-operator 替换为 getter 和 setter。但是,这将需要用适当的函数替换所有访问;另外,我很感兴趣是否可以按照我上面概述的方式进行操作。

【问题讨论】:

  • 我会为此做两种不同的方法并删除operator []
  • @Jarod42:我也想过这个问题,但是需要用 getter/setter 替换 [] 运算符的所有用法。可以肯定,但不是那么好。另外,我真的很好奇这是否可能。

标签: c++ arrays c++11 shared-memory


【解决方案1】:

您可以使用作为operator[] 结果的中间引用对象。然后,此对象根据该对象在未来表达式中的使用方式应用加载或存储操作。

class MyClass {
    struct Ref {
        std::atomic<int *> &ref_;
        Ref (std::atomic<int *> &r) : ref_(r) {}
        operator int * () const {
            return ref_.load(std::memory_order_acquire);
        }
        int * operator = (int *ptr) const {
            ref_.store(ptr, std::memory_order_release);
            return ptr;
        }
    };
public:
    //...
    Ref operator[](const size_t idx)
    {
         //there is some more code here, doing basic safety checks,...
         return array[idx];
    }
    //...
};

然后,转换运算符或赋值运算符将使用正确的内存顺序约束:

MyClass foo;
int *a = foo[0];  // uses conversion operator, load(acquire)
int b = 3;
foo[1] = &b;      // uses assignment operator, store(release)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-03
    • 2011-06-16
    • 2016-10-02
    • 1970-01-01
    • 2020-12-01
    • 2017-03-24
    • 1970-01-01
    相关资源
    最近更新 更多