Encountered race even after using std :: atomic types
Could you please tell me if the following code is thread safe?
I think I ran into a race condition because Task2 is not running, although I set the params.b value to true from the GUI.
struct params {
params() {}
~params() {}
atomic_bool a;
atomic_bool b;
};
struct driver {
driver() {}
~driver() {}
params myParams;
void tFun() {
while (1) {
if (myParams.a) { /* DoTask1 */ }
if (myParams.b) { /* DoTask2 */ }
}
}
void DoSome() {
std::thread t(&driver::tFun, this);
t.detach();
while (1) {
myParams.a = fromGui.val;
myParams.b = fromGui.val;
}
}
};
int main() {
driver myDriver;
myDriver.DoSome();
return 0;
}
Please use my use of fromGui.val, it should indicate that this value will be loaded from the GUI.
source to share
The situation I see is that fTun()
there is a mileage between the function and DoSome()
:
For example:
1. DoSome() sets a,b true
2. tFun() executes in while loop, as a is true, it starts DoTask1
2. DoSome() sets a,b to false
3. tFun() finishes DoTask1 and come to check myParams.b which is false;
DoTask2 is ignored!!
4. loop continues to step 1
If you always set a, b to true then there is no race to compare, tasks DoTask1 & DoTask2
should be done
source to share
I can't find any real race conditions here, but I believe this code may not work as expected on ALL OSes.
Let's see how to fix the problem.
void tFun() {
while (1) {
bool nop = false;
if (myParams.a) { /* DoTask1 */ }
else { nop = true; }
if (myParams.b) { /* DoTask2 */ }
else { nop = true; }
if (nop) { std::this_thread::yield(); }
}
}
void DoSome() {
std::thread t(&driver::tFun, this);
t.detach();
while (1) {
myParams.a = fromGui.val;
myParams.b = fromGui.val;
std::this_thread::yield();
}
}
source to share