Consider the following scenario:
2 threads: 1 main, and 1 daemon(a detached std::thread).
The daemon thread uses data the main thread manages (in this example the daemon could manage it just as well, but for the sake of the discussion, imagine that only the main thread can)
std::mutex someAccessMutex;
std::condition wakeMeUpCond;
std::atomic<bool> bStopDaemonThread;
int* pdata;
void daemonThread(){
while (1) {
std::unique_lock<std::mutex> locker(someAccessMutex);
wakeMeUpCond.wait(locker);
if (bStopDaemonThread.load())
return;
//Stage 1. do some other work
//Stage 2. retrieve the int from "data"
}
}
//executed on the main thread
void killerFunction(){
delete data;
bStopDaemonThread.store(true);
wakeMeUpCond.notify_all();
}
What can sometimes happen is:
- the daemonThread is already awake, doing work on Stage 1.
- the main thread with Killerfunction deletes what pointer pdata points to
- main thread uses killerFunction to wake up daemon and stop. but daemon is already awake thus it won't check the stopping condition
- daemon tries to read from pdata, but the data was deleted, an exception will be thrown
Sure, I could check every time before accessing pdata if its still valid. Even if that worked, daemon might pass stage 2 and go in waiting mode again, but it will never wake up to stop, because it already missed the nodify to wake up & stop, it was already awake doing work at the time.
My question is, in that described scenario: how would the daemon know to stop, given it can end up missing notifies sent by the main thread, to stop, because daemon passed the line of code that checks if it should stop.
Aucun commentaire:
Enregistrer un commentaire