const auto duration = Returns_10_seconds();
while(cv.wait_for(lock, duration) == std::cv_status::timeout);
questo è sicuramente una cosa sbagliata da fare e quindi non ha senso discutere come risolvere il problema per il caso di wakeups spuri, come si è rotto, anche per il caso di wakeups ordinari, in quanto il la condizione di attesa non viene riesaminata dopo il ritorno dall'attesa.
const auto duration = Returns_10_seconds();
while(!Predicate())
cv.wait_for(lock, duration);
Anche dopo la modifica, la risposta rimane la stessa: non si può davvero gestire "wakeups spurie", perché non si può davvero dire la ragione per la sveglia - può ben essere completamente wake wake a causa di una chiamata a condition_variable::notifyXXX
prima che il timeout sia scaduto.
In primo luogo, si noti che non è possibile distinguere realmente tra una sveglia causata da una chiamata a condition_variable::notifyXXX
e un risveglio causato, ad esempio, da un segnale POSIX [1]. Secondo, anche se i segnali POSIX non sono preoccupanti, il thread in attesa deve ancora riesaminare la condizione in quanto è possibile che la condizione cambi tra il momento in cui la variabile di condizione viene segnalata e il thread in attesa ritorna dalla condizione wait.
Quello che devi fare è trattare in modo speciale non svegliarsi prima del timeout, ma svegliarsi allo a causa del timeout.E questo dipende interamente dalle ragioni per avere un timeout in primo luogo, vale a dire sulle specifiche del dominio applicazione/problema.
[1] se aspettare su una variabile condizione è interrotto da un segnale, dopo l'esecuzione del gestore di segnale il filo è consentito sia di riprendere aspettare o tornare
Non è così. Devi controllarlo tu stesso o usare il sovraccarico che fa per te (quello che prende un predicato). –
@MaiLongdong, il predicato viene utilizzato solo per contrastare tali wakeup. Anche 'wait_for()' se funziona bene nella mia piattaforma, non garantisce che funzionerà ovunque, perché i risvegli spuri dipendono dalla piattaforma. – iammilind
Se non vuoi 'wait_for' 10 secondi usa' wait_until'' now() '+ 10 secondi :-) –