I'm trying to prevent a race condition with a thread that I pass some variables to by std::ref, but not quite sure how to do it.
I've got essentially:
#include <thread>
#include <mutex>
#include <vector>
std::mutex mtx;
float getXData();
float getYData();
void plot(std::vector<float> x, std::vector<float> y);
void calculateMeasurements(bool& currentlyRunning, std::vector<float>& xMeasurements,
std::vector<float>& yMeasurements){
while (true){
xMeasurements.push_back(getXData());
yMeasurements.push_back(getYData());
...
if (someCondition){
currentlyRunning=false;
xMeasurements.clear();xMeasurements.push_back(0);
yMeasurements.clear();yMeasurements.push_back(0);
currentlyRunning=true;
}
}
}
int main(){
std::vector<float> xMeasurements;
std::vector<float> yMeasurements;
xMeasurements.push_back(0);
yMeasurements.push_back(0);
bool currentlyRunning{true};
auto thread = std::thread(calculateMeasurements, std::ref(currentlyRunning),
std::ref(xMeasurements), std::ref(yMeasurements));
while (true){
...
mtx.lock();
if(currentlyRunning==true && xMeasurements.size()==yMeasurements.size()){
plot(xMeasurements,yMeasurements);
}
}
mtx.unlock();
}
So essentially what happens is there's one thread in the background pushing back elements to xMeasurements and yMeasurements, that also occasionally resets xMeasurements and yMeasurements to just one element of 0. The function plot requires that xMeasurements and Ymeasurements have the same size.
I thought that std::mutex::lock makes all the variables between std::mutex::lock and std::mutex::unlock only editable by the thread that calls std::mutex::lock until it unlocks, so here it should prevent the other thread from changing currentlyRunning,xMeasurements & yMeasurements. Howevever occasionally it fails on line plot(xMeasurements,yMeasurements); because of xMeasurements.size()!=yMeasurements.size() (so plot tries to read it between xMeasurements.push_back(getXData()); and yMeasurements.push_back(getYData());, which if I was correct about how mutex works shouldn't happen since it checks they're the same size within the lock) or it fails because either xMeasurements or yMeasurements are empty (which if I was correct about how mutex works shouldn't happen because it checks if currentlyRunning==true within the lock, and they can only be empty when currentlyRunning==false).
How do I correctly prevent another thread from changing the variables passed by reference to it?
Thanks
Aucun commentaire:
Enregistrer un commentaire