-
Notifications
You must be signed in to change notification settings - Fork 7
Description
Full name of submitter (unless configured in github; will be published with the issue): Jim X
[intro.execution] p7 says:
Evaluation of an expression (or a subexpression) in general includes both value computations (including determining the identity of an object for glvalue evaluation and fetching a value previously assigned to an object for prvalue evaluation) and initiation of side effects.
This wording only says evaluation includes initiating the side effect. However, it says nothing about whether the evaluation needs to be executed by the thread in which the expression appears. Consider this example:
#include <atomic>
#include <iostream>
#include <chrono>
#include <thread>
#include <cassert>
int main(){
std::atomic<int> val = {0};
auto t1 = std::thread([&]() {
auto r = val.load(std::memory_order::relaxed); // #1
assert(r==1);
});
auto t2 = std::thread([&]() {
std::this_thread::sleep_for(std::chrono::milliseconds(6000)); // #2
val.store(1,std::memory_order::release); // #4
});
t1.join();
std::cout<<"t1 completed\n";
t2.join();
}#1 and #4 are unordered, so the allowed values read by #1 are regulated by [intro.races] p10
The value of an atomic object M, as determined by evaluation B, is the value stored by some unspecified side effect A that modifies M, where B does not happen before A.
So, #4 is allowed to be loaded by #1. This could cause a possible execution that #1 loads 1 and t1 exits, but simultaneously #4 has not been executed by thread t2 due to the sleep.
The issue is that if #1 loads value 1, does it mean thread t2 has executed #4? If t2 has not executed #4 yet, where is that side effect produced from? It sounds like #1 loads a future value.
Does the evaluation need to be executed by the thread to produce the side effect, instead that the evaluation merely appear in the source code? If a load reads the value, does the corresponding evaluation need to have already been executed by the thread, or is the evaluation only required to be executed somewhere in the lifetime of the program?
This seems to be vague in the current standard.