Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Valore ritorno std::condition_variable::wait_for

31 views
Skip to first unread message

_merlinO_

unread,
Jan 24, 2019, 12:00:11 PM1/24/19
to
Ho un problema col valore di ritorno di std::condition_variable::wait_for.

Il mio test usa due thread che condividono lo stesso oggetto di sincronizzazione:

-T1 rimane in attesa su una condition_variabile::wait_for con un timeout X secondi.
-T2 attende N secondi e poi sveglia i thread in attesa (notify_all).

1- Se N < X (la notifica arriva prima del timeout) il valore di ritorno di wait_for è sempre no_timeout.

2- Se N > X (la notifica arriva dopo il timeout) il valore di ritorno di wait_for è a intermittenza timeout e no_timeout.

Nel secondo caso il tempo di attesa è coerente, è solo il valore di ritorno che varia. Non riesco a capire il motivo.

enoquick

unread,
Jan 24, 2019, 11:14:57 PM1/24/19
to
Il 24/01/19 11:00, _merlinO_ ha scritto:
difficile dire il motivo
un bug nella implementazione usata o nel tuo programma ?
poiche ne sono incuriosito hai un piccolo programma per testare questa
cosa specificando l'os e la versione del compilatore che hai usato ?

logica mente

unread,
Jan 25, 2019, 4:19:05 AM1/25/19
to
Semplice, hai X < N < 2X (quasi sicuramente)
supponiamo che i due thread partano in contemporanea,
1) il 1° thread arriva al timeout e quindi riparte.
2) Il 2° thread arriva a N, manda la notifica ed hai no_timeout.
3) I due thread ripartono da zero e si ritorna al caso (1)

Se provi con 2X < N < 3X avrai in sequenza due timeout ed un no_timeout

_merlinO_

unread,
Jan 25, 2019, 5:08:43 AM1/25/19
to
Il giorno venerdì 25 gennaio 2019 10:19:05 UTC+1, logica mente ha scritto:

> Semplice, hai X < N < 2X (quasi sicuramente)
> supponiamo che i due thread partano in contemporanea,
> 1) il 1° thread arriva al timeout e quindi riparte.
> 2) Il 2° thread arriva a N, manda la notifica ed hai no_timeout.
> 3) I due thread ripartono da zero e si ritorna al caso (1)
>
> Se provi con 2X < N < 3X avrai in sequenza due timeout ed un no_timeout

Non ho ripartenza, sono test spot, creo tutto ad ogni giro

logica mente

unread,
Jan 25, 2019, 5:43:13 AM1/25/19
to
Ma X e N sono fissi? Chi causa la chiusura dei thread?
Se è l'evento che ferma tutto è normale che sia così, si ricade sempre
nella condizione iniziale.
Ad ogni avvio si va nel caso (1) se X < N altrimenti si salta
direttamente al caso (2) ed infine il caso (3) diventa la chiusura.

... scusa, sopra avevo scritto 'riparte' ma intendevo che si rimette in
wait.


_merlinO_

unread,
Jan 25, 2019, 6:23:03 AM1/25/19
to
Il giorno venerdì 25 gennaio 2019 05:14:57 UTC+1, enoquick ha scritto:

> difficile dire il motivo
> un bug nella implementazione usata o nel tuo programma ?
> poiche ne sono incuriosito hai un piccolo programma per testare questa
> cosa specificando l'os e la versione del compilatore che hai usato ?

Windows con VS2015

Ho messo un esempio qui:
http://cpp.sh/4vpuu

anche in questo caso si verifica il problema
Message has been deleted

logica mente

unread,
Jan 25, 2019, 9:46:21 AM1/25/19
to
commenta la riga:
while (!m_notified) // avoid spurious wakeup

non esce dal ciclo finché non diventa true



_merlinO_

unread,
Jan 25, 2019, 11:04:50 AM1/25/19
to
Il giorno venerdì 25 gennaio 2019 15:46:21 UTC+1, logica mente ha scritto:

> commenta la riga:
> while (!m_notified) // avoid spurious wakeup
>
> non esce dal ciclo finché non diventa true

Lo so ma prima di inviare la notify_one viene messa a true, comunque non è questo il problema, nella prima versione non c'era.

Ho provato a reimplementare con un altro sistema di sincronizzazione ma non cambia, a questo punto credo che il problema sia il thread che produce la notifica.

logica mente

unread,
Jan 25, 2019, 12:21:47 PM1/25/19
to
Il 25/01/2019 17:04, _merlinO_ ha scritto:
> Il giorno venerdì 25 gennaio 2019 15:46:21 UTC+1, logica mente ha scritto:
>
>> commenta la riga:
>> while (!m_notified) // avoid spurious wakeup
>>
>> non esce dal ciclo finché non diventa true
>
> Lo so ma prima di inviare la notify_one viene messa a true, comunque non è questo il problema, nella prima versione non c'era.
>

in quell'esempio è quello il problema, se poi c'è altro codice ...

> Ho provato a reimplementare con un altro sistema di sincronizzazione ma non cambia, a questo punto credo che il problema sia il thread che produce la notifica.
>

anziché usare il main thread non è più semplice usare due thread
separati dal flusso principale?

enoquick

unread,
Jan 27, 2019, 10:18:58 AM1/27/19
to
Il 24/01/19 11:00, _merlinO_ ha scritto:
Ho esaminato il programma e mi sembra corretto.
Il Timeout succede perche avviene proprio un timeout

Qui: const auto result = obj->Wait(1s);
gli dici al thread di attendere al max 1 secondo oppure che venga
notificato
E' normale che alcuni threads con tempi cosi bassi vadano in timeout
Se porti il tempo di attesa ad esempio a 10s il timeout non si verifica


Compilato sotto linux con
const auto result = obj->Wait(1s);

g++ -std=c++17 -Wall main.cpp -lpthread

1: 0ms Timeout
2: 2000ms Timeout
3: 4000ms Timeout
4: 6000ms Timeout
5: 8000ms No timeout
6: 10001ms Timeout
7: 12001ms Timeout
8: 14001ms Timeout
9: 16001ms Timeout
10: 18001ms Timeout
11: 20002ms Timeout
12: 22002ms Timeout
13: 24002ms Timeout
14: 26002ms Timeout
15: 28002ms Timeout
16: 30003ms Timeout
17: 32003ms No timeout
18: 34003ms Timeout
19: 36003ms Timeout
20: 38003ms Timeout

con
const auto result = obj->Wait(10s);

1: 0ms No timeout
2: 2000ms No timeout
3: 4000ms No timeout
4: 6000ms No timeout
5: 8000ms No timeout
6: 10001ms No timeout
7: 12001ms No timeout
8: 14001ms No timeout
9: 16001ms No timeout
10: 18002ms No timeout
11: 20002ms No timeout
12: 22002ms No timeout
13: 24003ms No timeout
14: 26003ms No timeout
15: 28003ms No timeout
16: 30003ms No timeout
17: 32004ms No timeout
18: 34004ms No timeout
19: 36004ms No timeout
20: 38004ms No timeout

I threads vengono tutti notificati


Quello che non capisco e' questa:
inline string Time()
{
static auto start = high_resolution_clock::now();
return
std::to_string(duration_cast<milliseconds>(high_resolution_clock::now()
- start).count()) + "ms ";
}


Che senso ha misurare l'esecuzione di due istruzione in sequenza (now -
start) ?
dove poi Time() viene usata nella print ?





enoquick

unread,
Jan 27, 2019, 10:21:26 AM1/27/19
to
Il 27/01/19 09:18, enoquick ha scritto:
Rettifico sulla Time()
start e' static quindi viene calcolata solo la prima volta

_merlinO_

unread,
Jan 28, 2019, 4:54:18 AM1/28/19
to
Il giorno domenica 27 gennaio 2019 16:18:58 UTC+1, enoquick ha scritto:

> Ho esaminato il programma e mi sembra corretto.
> Il Timeout succede perche avviene proprio un timeout
>
> Qui: const auto result = obj->Wait(1s);
> gli dici al thread di attendere al max 1 secondo oppure che venga
> notificato
> E' normale che alcuni threads con tempi cosi bassi vadano in timeout
> Se porti il tempo di attesa ad esempio a 10s il timeout non si verifica
[...]

>
> Quello che non capisco e' questa:
> inline string Time()
> {
> static auto start = high_resolution_clock::now();
> return
> std::to_string(duration_cast<milliseconds>(high_resolution_clock::now()
> - start).count()) + "ms ";
> }
>
>
> Che senso ha misurare l'esecuzione di due istruzione in sequenza (now -
> start) ?
> dove poi Time() viene usata nella print ?

E' voluto, volevo calcolare il ritardo che si accumula di volta in volta. Poiché i tempi sono semplici (1s timeout, 2s evento) è comunque facile fare il calcolo di cosa è accaduto.

Il mio scopo è proprio quello di testare il timeout, quando non lo raggiungo e l'evento viene segnalato in tempo tutto funziona.
Se invece l'evento non viene segnalato in tempo wait_for (al netto di errori miei) sembra sempre aspettare l'evento.

*La cosa strana* è che i cicli sono ogni 2s anziché 1s (timeout), la wait_for dovrebbe uscire prima che la notifica arrivi.
I tempi di test dovrebbero essere sufficienti, di solito i thread reagiscono nell'ordine dei ms.

Ho implementato lo stesso template con QT e funziona come mi aspetto. Non riesco proprio a capire perché...

_merlinO_

unread,
Jan 28, 2019, 6:38:29 AM1/28/19
to
Il giorno domenica 27 gennaio 2019 16:21:26 UTC+1, enoquick ha scritto:

Ho fatto una versione ultra-semplificata, sul sito funziona, su Windows il risultato è questo:

1: waitTime=1001ms (Timeout) / loopTime=5003ms
2: waitTime=1000ms (Timeout) / loopTime=5000ms
3: waitTime=1000ms (Timeout) / loopTime=5000ms
4: waitTime=1000ms (Timeout) / loopTime=5000ms
5: waitTime=999ms (No timeout) / loopTime=5000ms
6: waitTime=999ms (No timeout) / loopTime=5000ms
7: waitTime=1000ms (Timeout) / loopTime=5001ms
8: waitTime=1000ms (Timeout) / loopTime=5001ms
9: waitTime=1000ms (Timeout) / loopTime=5000ms
10: waitTime=999ms (No timeout) / loopTime=5000ms
11: waitTime=999ms (No timeout) / loopTime=5000ms
12: waitTime=1000ms (Timeout) / loopTime=5000ms
13: waitTime=1000ms (Timeout) / loopTime=5000ms
14: waitTime=999ms (No timeout) / loopTime=5000ms
15: waitTime=1000ms (Timeout) / loopTime=5000ms
16: waitTime=1000ms (Timeout) / loopTime=5000ms
17: waitTime=999ms (No timeout) / loopTime=5000ms
18: waitTime=1000ms (Timeout) / loopTime=5000ms
19: waitTime=999ms (No timeout) / loopTime=5000ms
20: waitTime=1000ms (Timeout) / loopTime=5000ms

http://cpp.sh/8z2xk

_merlinO_

unread,
Jan 30, 2019, 4:24:41 AM1/30/19
to
Il giorno lunedì 28 gennaio 2019 10:54:18 UTC+1, _merlinO_ ha scritto:

[...]
> Ho implementato lo stesso template con QT e funziona come mi aspetto. Non riesco proprio a capire perché...

Alla fine è un baco dell'implementazione Microsoft
https://developercommunity.visualstudio.com/content/problem/193041/the-visual-c-2017-condition-variable-implementatio.html

enoquick

unread,
Jan 30, 2019, 9:36:29 PM1/30/19
to
Il 30/01/19 03:24, _merlinO_ ha scritto:
Ma era segnalato nel febbraio 2018,quasi un anno fa
Possibile che non lo abbiano ancora corretto ?
Hai provato con vs2017 aggiornato all'ultima patch ?


_merlinO_

unread,
Jan 31, 2019, 5:37:10 AM1/31/19
to
Il giorno giovedì 31 gennaio 2019 03:36:29 UTC+1, enoquick ha scritto:

> Ma era segnalato nel febbraio 2018,quasi un anno fa
> Possibile che non lo abbiano ancora corretto ?
> Hai provato con vs2017 aggiornato all'ultima patch ?

Sì, non l'hanno ancora corretto, o non è semplice o non è importante (per loro).

enoquick

unread,
Jan 31, 2019, 9:38:05 PM1/31/19
to
Il 31/01/19 04:37, _merlinO_ ha scritto:
Avranno altre priorita da sistemare
Vs2017 ha ancora bachi a correggere segnalati nell'apposito forum.
E non solo c++ ovviamente

0 new messages