C++ wait condition vysvětlení

vyvojar

C++ wait condition vysvětlení
« kdy: 11. 12. 2017, 19:35:15 »
Toto je pro opravdové borce, teď se ukažte :)
Dokázal by někdo říct, proč ta implementace používá 2 mutexy? Wait condition se vždycky používá s mutexem, to jo, ale proč se tady používají 2? Jeden ten "klasický", co jen a vstupu a pak jeden ještě interně. Jediné, co mě napadá, jak na to koukám, že to možná umožňuje
ten wait condition používat i s různými mutexy na vstupu?

https://github.com/qt/qtbase/blob/5.10/src/corelib/thread/qwaitcondition.h
https://github.com/qt/qtbase/blob/5.10/src/corelib/thread/qwaitcondition_unix.cpp


MD

Re:C++ wait condition vysvětlení
« Odpověď #1 kdy: 11. 12. 2017, 19:59:30 »
Myslíte ten mutex uvnitř té implementace condition variable? Používá se na synchronizaci přístupu k položkám dané c.v. (na rozdíl od mutexu, který předáváte při wait a který slouží k zajištění atomického testování podmínky pro čekání spolu s případným zahájením toho čekání).

drtzuj

Re:C++ wait condition vysvětlení
« Odpověď #2 kdy: 11. 12. 2017, 20:02:39 »
Toto je pro opravdové borce, teď se ukažte :)
Dokázal by někdo říct, proč ta implementace používá 2 mutexy? Wait condition se vždycky používá s mutexem, to jo, ale proč se tady používají 2? Jeden ten "klasický", co jen a vstupu a pak jeden ještě interně. Jediné, co mě napadá, jak na to koukám, že to možná umožňuje
ten wait condition používat i s různými mutexy na vstupu?

https://github.com/qt/qtbase/blob/5.10/src/corelib/thread/qwaitcondition.h
https://github.com/qt/qtbase/blob/5.10/src/corelib/thread/qwaitcondition_unix.cpp

Já jsem na tohle teda Pepa z Horní Dolní, ale v prvním uváděném odkazu vidím pouze jeden mutex. Sice je tam napsaný dvakrát, ale jednou je napsaný v bloku
Kód: [Vybrat]
#ifndef a jednou v bloku
Kód: [Vybrat]
#else. Ale jak říkám, jsem na to Pepa z Horní Dolní a upřímně - ani pořádně nevím, co je to mutex (něco zběžně).

vyvojar

Re:C++ wait condition vysvětlení
« Odpověď #3 kdy: 11. 12. 2017, 20:06:11 »
Myslíte ten mutex uvnitř té implementace condition variable? Používá se na synchronizaci přístupu k položkám dané c.v. (na rozdíl od mutexu, který předáváte při wait a který slouží k zajištění atomického testování podmínky pro čekání spolu s případným zahájením toho čekání).

A k čemu je potřeba synchronizovat tím dalším mutexem přístup k datovým členům, když to už by mělo být zajištěno tím mutexem, co vstupuje, protože při volání libovolné metody by měl být locknutý, ne?

MD

Re:C++ wait condition vysvětlení
« Odpověď #4 kdy: 11. 12. 2017, 20:18:25 »
Citace
A k čemu je potřeba synchronizovat tím dalším mutexem přístup k datovým členům, když to už by mělo být zajištěno tím mutexem, co vstupuje, protože při volání libovolné metody by měl být locknutý, ne?

Při provádění operace signal/notify váš mutex (ten, který předáváte do wait) zamykat nemusíte. Musí být zaměčený pouze při volání wait, jinak si jej můžete zamykat a odemykat, jak chcete (aniž byste pracoval s c.v.).


trouba

Re:C++ wait condition vysvětlení
« Odpověď #5 kdy: 11. 12. 2017, 20:18:41 »
Vidim tam jeden mutex v implementaci  QWaitConditionPrivate (https://github.com/qt/qtbase/blob/5.10/src/corelib/thread/qwaitcondition_unix.cpp#L117).

A tu samotnou tam vidim instancovanou take jen jednou v implementaci konstruktoru QWaitCondition() (https://github.com/qt/qtbase/blob/5.10/src/corelib/thread/qwaitcondition_unix.cpp#L170).


vyvojar

Re:C++ wait condition vysvětlení
« Odpověď #6 kdy: 11. 12. 2017, 20:41:45 »
Citace
A k čemu je potřeba synchronizovat tím dalším mutexem přístup k datovým členům, když to už by mělo být zajištěno tím mutexem, co vstupuje, protože při volání libovolné metody by měl být locknutý, ne?

Při provádění operace signal/notify váš mutex (ten, který předáváte do wait) zamykat nemusíte. Musí být zaměčený pouze při volání wait, jinak si jej můžete zamykat a odemykat, jak chcete (aniž byste pracoval s c.v.).

Máte pravdu, i když je asi běžnou praxí, že se ten mutex zamýká i před notify, tak to tak  být nemusí.  Díky :)

Re:C++ wait condition vysvětlení
« Odpověď #7 kdy: 12. 12. 2017, 00:39:53 »
A k čemu je potřeba synchronizovat tím dalším mutexem přístup k datovým členům, když to už by mělo být zajištěno tím mutexem, co vstupuje, protože při volání libovolné metody by měl být locknutý, ne?

Napadají mě tři důvody:
  • Implementace interně používá pthread_mutex_t, ale interface nabízí volání wait s QMutex nebo QReadWriteLock
  • Autorovi kódu připadalo lepší/bezpečnější zařídit si zamykání interně, než se spoléhat na externě dodaný zamčený zámek.
  • Metody wakeOne() a wakeAll() nevyžadují volání se zamčeným zámkem (i když takové volání většinou není dobrý nápad). Navíc je takto kód připravený na případné přidání dalších (např. ladicích) metod, které zafungují i bez externího zámku.

qt_lopata

Re:C++ wait condition vysvětlení
« Odpověď #8 kdy: 12. 12. 2017, 11:24:34 »
Ono je to prosté, milý Watsone. Musíš rozlišovat public interface a privátní implementaci.

Tohle: https://github.com/qt/qtbase/blob/5.10/src/corelib/thread/qwaitcondition.h#L62 je public interface a dostává to QMutex.

Tohle: https://github.com/qt/qtbase/blob/5.10/src/corelib/thread/qwaitcondition_unix.cpp#L117 je privátní implementace a používá to pthread mutex.

Jsou to úplně jiné datové typy. Na unixu je v privátní implementaci pthread mutex, na Windows tam může být nějaký WINAPI mutex nebo cokoliv jiného. Přitom nemusí platit, že implementace QMutexu odpovídá privátní implementaci mutexu v qwaitcondition.

V privátní imlementaci je metoda, která opravu čeká: https://github.com/qt/qtbase/blob/5.10/src/corelib/thread/qwaitcondition_unix.cpp#L136, ta musí používat ten privátní mutex, nelze do toho dát QMutex, o kterém vůbec nevíš, jak je interně implementovaný. Teoreticky, kdyby i QMutex interně využíval pthread mutex, dal by se použít a privátní mutex by tam nemusel být, ale byla by to architektonická prasárna.