读-修改-写操作是一个不可分割的操作吗?

jac*_*k X 6 c++ atomic language-lawyer

在CWG 问题下的评论中,Jens Maurer 说

\n
\n

读-比较-写是一个单一的、不可分割的操作(“原子地”)。

\n
\n

然而,正如所讨论的

\n
\n
    \n
  1. 出于排序目的,原子读-修改-写是一个操作还是两个操作?
  2. \n
  3. 不同两个线程中的“compare_exchange_strong”读取操作是否可以读取相同的值?
  4. \n
\n
\n

尽管我们还没有得到任何 100% 确认的答案,但我们似乎认为读取-修改-写入操作包含两个操作:读取和写入操作,这也由这个正式措辞 [atomics.order] p10 暗示

\n
\n

原子读-修改-写操作应始终读取在与读-修改-写操作关联的写操作之前写入的最后一个值(按修改顺序) 。

\n
\n

该措辞提到了与读-修改-写操作相关的“读”和“写”。然而,Jens 认为读取-修改-写入操作是一个不可分割的操作。

\n

这里的标准的意图是什么?

\n

更新

\n

一个相关的例子是:

\n
std::atomic<int> x{0};\n\n// Thread 1:\n int expected  = 0;\n x.compare_exchange_strong(expected,1,std::memory_order\xe2\x80\x8b::\xe2\x80\x8brelease,std::memory_order\xe2\x80\x8b::relaxed); // #1\n\n// Thread 2:\n int expected  = 1;\n while(\n    /*#2*/ \n    x.compare_exchange_strong(expected,2,std::memory_order\xe2\x80\x8b::acquire,std::memory_order\xe2\x80\x8b::relaxed)\n){}\n
Run Code Online (Sandbox Code Playgroud)\n

假设线程 2 中的 RMW 操作读取线程 1 中的 RMW 操作写入的值(即 #2 只运行一次迭代)

\n

[atomics.order] p2 说:

\n
\n

对原子对象 M执行释放操作的原子操作 A 与对 M执行获取操作的原子操作 B 同步,并从以 A 为首的释放序列中的任何副作用中获取其值。

\n
\n

[atomics.order] p1 说:

\n
\n

内存_order\xe2\x80\x8b::\xe2\x80\x8brelease、内存_order\xe2\x80\x8b::\xe2\x80\x8bacq_rel 和内存_order\xe2\x80\x8b::\xe2\x80\x8bseq_cst :存储操作执行释放操作存储操作对受影响的内存位置

\n

内存_order\xe2\x80\x8b::\xe2\x80\x8bacquire、内存_order\xe2\x80\x8b::\xe2\x80\x8bacq_rel 和内存_order\xe2\x80\x8b::\xe2\x80\x8bseq_cst: a加载操作执行对受影响的内存位置执行获取操作。

\n
\n

这意味着,如果A是一个存储操作并且B是加载操作,并且它们满足 [atomics.order] p2,则它们同步。

\n

IIUC#1与 同步#2,但是,#1都是#2RMW 操作, 是#1执行释放操作的存储操作,并且#2是加载操作执行获取操作吗?

\n