Does the CAS operation that writes the same value theoretically have a higher probability of detecting a version change than a pure load?

3 days ago 11
ARTICLE AD BOX

Consider this example:

#include <atomic> #include <iostream> #include <thread> std::atomic<int> canceller = {0}; int main() { auto t1 = std::thread([]() { auto v = canceller.fetch_add(1, std::memory_order::relaxed); // #0 std::thread([v]() { int current = v + 1; if (canceller.compare_exchange_strong( current, current, std::memory_order::relaxed, std::memory_order::relaxed)) { // #1 // post_data_to_network(current); } }).join(); }); auto t2 = std::thread([]() { canceller.fetch_add(1, std::memory_order::relaxed); // #2 }); t1.join(); t2.join(); }

Assuming there are two buttons, clicking button A will send some data to the remote server, and clicking button B will change the value of canceller to cancel the task in A(if A can detect the change).

The above code models such two events. For this case, #1 must fail(detect the change) and cancel the task if #2 reads #0 and writes 2. However, if change #1 to a pure load, as follows:

if(canceller.load(memory_order::relaxed)==current){ // post_data_to_network(v); }

According to [intro.races] p14

If a side effect X on an atomic object M happens before a value computation B of M, then the evaluation B takes its value from X or from a side effect Y that follows X in the modification order of M.

[atomics.order] p12

The implementation should make atomic stores visible to atomic loads, and atomic loads should observe atomic stores, within a reasonable amount of time.

Theoretically, the pure load in A can keep reading 1 for a limited time, which cannot detect the change of #0 in B, even though #2 has changed the value.

So, I wonder, does CAS that writes the same value have a higher probability of detecting the change than a pure load?

Read Entire Article