Race Condition
-
folgender Code ist bei parallelen Aufrüfen von "start" nicht threadsicher. Ich habe alles auskommentiert, was nichts mit dem Fehler zu tun hat.
Wenn ich
pulser_ = std::thread {/*...*/};
auskommentiere ist der Fehler weg.
Mein "if running, stop, restart" muss falsch und nicht atomar sein.
aber dabei ist doch nur noch std::thread, std::atomic_bool und ein lambda über nach dem ich alles auskommentiert habe.
Was ist hier broken?//--------------------------------------------------------------------------------------------------------------------- void Controller::start() { if (running_.load() == true) pause(); pulser_ = std::thread { [this]() { running_.store(true); try { //auto lastRefreshTime = std::chrono::system_clock::now(); //refreshAllCloners(); for (;running_.load();) { std::this_thread::sleep_for(std::chrono::milliseconds(50)); /* bool workDone = pulseAllCloners(); if (!workDone) std::this_thread::sleep_for(std::chrono::milliseconds(50)); // look for new files in system if (std::chrono::system_clock::now() - lastRefreshTime > std::chrono::milliseconds(interval_)) { refreshAllCloners(); lastRefreshTime = std::chrono::system_clock::now(); } */ } } catch (std::exception const& exc) { running_.store(false); //lastError_ = exc.what(); } } }; } //--------------------------------------------------------------------------------------------------------------------- void Controller::pause() { running_.store(false); if (pulser_.joinable()) pulser_.join(); } //---------------------------------------------------------------------------------------------------------------------
Head:
std::thread pulser_; std::atomic_bool running_;
(Der Fehler veräußert sich übrigens so:)
terminate called without an active exception
terminate called recursively
terminate called recursively
terminate called recursively
Oder (selten) gefangen an anderer stelle (std::exception::what):
no such process
-
update:
Das hier reicht für die start methode:void Controller::start() { // auch keine Lösung // std::lock_guard <std::mutex> x (startLock_); if (running_.load() == true) pause(); pulser_ = std::thread { [this]() { running_.store(true); std::this_thread::sleep_for(std::chrono::milliseconds(50)); } } } //--------------------------------------------------------------------------------------------------------------------- void Controller::pause() { running_.store(false); if (pulser_.joinable()) pulser_.join(); }
-
Hab die Lösung:
void Controller::start() { pause(); pulser_ = std::thread { [this]() { running_.store(true); std::this_thread::sleep_for(std::chrono::milliseconds(50)); } } } //--------------------------------------------------------------------------------------------------------------------- void Controller::pause() { running_.store(false); if (pulser_.joinable()) pulser_.join(); }
(Edit: Der Thread wurde assigned, while joinable -> terminate() wird aufgerufen)