我红色了这篇文章Seqlocks 可以与编程语言内存模型相处吗?
并发现其中一个示例(图6)从c++内存模型的角度来看是不正确的。
atomic<unsigned> seq; // seqlock representation
// assume big enough to ignore overflow
atomic<int> data1, data2; // protected by seq
T reader() {
int r1, r2;
unsigned seq0, seq1;
do {
seq0 = seq.load(m_o_acquire);
r1 = data1.load(m_o_relaxed);
r2 = data2.load(m_o_relaxed);
atomic_thread_fence(m_o_acquire);
seq1 = seq.load(m_o_relaxed);
} while (seq0 != seq1 || seq0 & 1);
// do something with r1 and r2;
}
void writer(...) { ... }
// continues to use seq_cst or
// acquire/release operations on data
Figure 6. Seqlock reader with acquire fence
这里假设在读取 seq0 时,与读取器和“最后一个”写入器进行同步,但内存模型并不能保证这一点。为此,我们必须在读取 seq1 和 if seq1 == seq0 时强制 与 RMW 操作(例如 seq.fetch_add(0) 或 seq.cas(seq0, seq0))同步,因此读取 seq0 的时间与“最后一个”作者进行 同步 => 发生在之前