为什么将memory_order作为std :: atomic函数的运行时参数给出

era*_*ran 17 c++ atomic memory-model c++11

std::atomic功能,诸如storeload采取一个std::memory_order参数.可以在运行时确定参数,就像任何其他函数参数一样.但是,实际值可能会影响编译期间代码的优化.考虑以下:

std::atomic<int> ai1, ai2;
int value = whatever;

void foo() {
    std::memory_order memOrd = getMemoryOrder();
    register int v = value; // load value from memory
    ai1.store(v, memOrd);   // dependency on v's value
    ai2.store(1, memOrd);   // no dependency. could this be move up?
}
Run Code Online (Sandbox Code Playgroud)

如果memOrd碰巧memory_order_relaxed,第二个商店可以安全地移动到第一个商店前面.这将在加载value和使用它之间增加一些额外的工作,这可能会阻止其他需要的停顿.但是,如果memOrdmemory_order_seq_cst,则不应该允许切换存储,因为如果设置为1 ai1,value则某些其他线程可能指望已经设置为ai2.

我想知道为什么内存顺序被定义为运行时参数而不是编译时间.在决定最佳内存操作语义之前,有人在运行时检查环境是否有任何理由?

Ant*_*ams 7

作为运行时参数而不是编译时参数实现的原因是启用组合.

假设您正在编写一个函数,该函数使用提供的原子操作来执行等效的加载操作,但是在更高级别的构造上操作.通过将存储器顺序指定为运行时参数,较高级别的负载然后可以将用户提供的存储器顺序参数传递给提供排序所需的低级原子操作,而不需要更高级别的操作必须是模板.

通常,原子指令将是内联的,并且编译器将在它实际上是编译时常量的情况下消除对内存顺序参数的测试.