Upload
others
View
43
Download
6
Embed Size (px)
Citation preview
MultithreadingwithQtGiuseppeDAngeloSeniorSoftwareEngineeratKDAB
Agenda
p2
QThread(page4)
Synchronization(page18)
ThreadsafetyinQt(page26)
QtandtheStandardLibrarythreadingfacilities(page38)
p3
Doyouknowwhatathreadis
QThread
QThread p4
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
QThread
QThread p5
QThreadisthecentralclassinQttoruncodeinadifferentthread
ItsaQObjectsubclassNotcopiablemoveableHassignalstonotifywhenthethreadstartsfinishes
Itismeanttomanageathread
QThreadusage
QThread p6
TocreateanewthreadexecutingsomecodesubclassQThreadandreimplementrun()
Thencreateaninstanceofthesubclassandcallstart()
Threadshaveprioritiesthatyoucanspecifyasanoptionalparametertostart()orchangewithsetPriority()
QThreadusage
QThread p7
1 classMyThreadpublicQThread2 private3 voidrun()override4 codetoruninthenewthread5 6
1 MyThreadthread=newMyThread2 thread-gtstart()startsanewthreadwhichcallsrun()3 4 thread-gtwait()waitsforthethreadtofinish
QThreadusage
QThread p8
Thethreadwillstoprunningwhen(sometimeafter)returningfromrun()
QThreadisRunning()andQThreadisFinished()provideinformationabouttheexecutionofthethread
YoucanalsoconnecttotheQThreadstarted()andQThreadfinished()signals
AthreadcanstopitsexecutiontemporarilybycallingoneoftheQThreadsleep()functionsGenerallyabadideabeingeventdriven(orpolling)ismuchmuchbetter
YoucanwaitforaQThreadtofinishbycallingwait()onitOptionallypassingamaximumnumberofmillisecondstowait
QThreadcaveats
QThread p9
Fromanon-mainthreadyoucannot
PerformanyGUIoperationIncludingbutnotlimitedtousinganyQWidgetQtQuickQPixmapAPIsUsingQImageQPainteretc(ieclientside)isOKUsingOpenGLmaybeOKcheckatruntimeQOpenGLContextsupportsThreadedOpenGL()
CallQ(Core|Gui)Applicationexec()
QThreadcaveats
QThread p10
BesuretoalwaysdestroyalltheQObjectslivinginsecondarythreadsbeforedestroyingthecorrespondingQThreadobject
DonoteverblocktheGUIthread
EnsuringdestructionofQObjects
QThread p11
CreatethemonQThreadrun()stack
ConnecttheirQObjectdeleteLater()slottotheQThreadfinished()signalYesthiswillwork
Movethemoutofthethread
EnsuringdestructionofQObjects
QThread p12
1 classMyThreadpublicQThread2 private3 voidrun()override4 MyQObjectobj1obj2obj356 QScopedPointerltOtherQObjectgtp7 if(condition)8 preset(newOtherQObject)910 autoanotherObj=newAnotherQObject11 connect(thisampQThreadfinished12 anotherObjampQObjectdeleteLater)1314 autoyetAnother=newYetAnotherQObject1516 dostuff1718 Beforequittingthethreadmovethisobjecttothemainthread19 yetAnother-gtmoveToThread(qApp-gtthread())20 Somehownotifythemainthreadaboutthisobject21 soitcanbedeletedthere22 Donottouchtheobjectfromthisthreadafterthispoint23 24
QThreadusage
QThread p13
TherearetwobasicstrategiesofrunningcodeinaseparatethreadwithQThread
Withoutaneventloop
Withaneventloop
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()1 classMyThreadpublicQThread2 private3 voidrun()override4 loadFilesFromDisk()5 doCalculations()6 saveResults()7 8
1 autothread=newMyThread2 thread-gtstart()3 sometimelater4 thread-gtwait()
QThreadusagewithaneventloop
QThread p15
Aneventloopisnecessarywhendealingwithtimersnetworkingqueuedconnectionsandsoon
Qtsupportsper-threadeventloops
Eachthread-localeventloopdeliverseventsfortheQObjectslivinginthatthread
QThreadusagewithaneventloop
QThread p16
Wecanstartathread-localeventloopbycallingQThreadexec()fromwithinrun()1 classMyThreadpublicQThread2 private3 voidrun()override4 autosocket=newQTcpSocket5 socket-gtconnectToHost()67 exec()runtheeventloop89 cleanup10 11
QThreadquit()orQThreadexit()willquittheeventloop
WecanalsouseQEventLoopOrmanualcallstoQCoreApplicationprocessEvents()
QThreadusagewithaneventloop
QThread p17
ThedefaultimplementationofQThreadrun()actuallycallsQThreadexec()
ThisallowsustoruncodeinotherthreadswithoutsubclassingQThread1 autothread=newQThread23 autoworker=newWorker45 connect(threadampQThreadstartedworkerampWorkerdoWork)6 connect(workerampWorkerworkDonethreadampQThreadquit)78 connect(threadampQThreadfinishedworkerampWorkerdeleteLater)910 worker-gtmoveToThread(thread)11 thread-gtstart()
Synchronization
Synchronization p18
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Synchronization p19
Whatisthesingle
mostimportantthingaboutthreads
Synchronization
Synchronization p20
Anyconcurrentaccesstosharedresourcesmustnotresultinadatarace
Twoconditionsforthistohappen1Atleastoneoftheaccessesisawrite2Theaccessesarenotatomicandnoaccesshappensbeforetheother
Synchronization
Synchronization p21
Qthasacompletesetofcross-platformlow-levelAPIsfordealingwithsynchronization
QMutexisamutexclass(recursiveandnon-recursive)
QSemaphoreisasemaphore
QWaitConditionisaconditionvariable
QReadWriteLockisasharedmutex
QAtomicIntisanatomicint
QAtomicPointerltTgtisanatomicpointertoT
TherearealsoRAIIclassesforlockmanagementsuchasQMutexLockerQReadLockerandsoon
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
Agenda
p2
QThread(page4)
Synchronization(page18)
ThreadsafetyinQt(page26)
QtandtheStandardLibrarythreadingfacilities(page38)
p3
Doyouknowwhatathreadis
QThread
QThread p4
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
QThread
QThread p5
QThreadisthecentralclassinQttoruncodeinadifferentthread
ItsaQObjectsubclassNotcopiablemoveableHassignalstonotifywhenthethreadstartsfinishes
Itismeanttomanageathread
QThreadusage
QThread p6
TocreateanewthreadexecutingsomecodesubclassQThreadandreimplementrun()
Thencreateaninstanceofthesubclassandcallstart()
Threadshaveprioritiesthatyoucanspecifyasanoptionalparametertostart()orchangewithsetPriority()
QThreadusage
QThread p7
1 classMyThreadpublicQThread2 private3 voidrun()override4 codetoruninthenewthread5 6
1 MyThreadthread=newMyThread2 thread-gtstart()startsanewthreadwhichcallsrun()3 4 thread-gtwait()waitsforthethreadtofinish
QThreadusage
QThread p8
Thethreadwillstoprunningwhen(sometimeafter)returningfromrun()
QThreadisRunning()andQThreadisFinished()provideinformationabouttheexecutionofthethread
YoucanalsoconnecttotheQThreadstarted()andQThreadfinished()signals
AthreadcanstopitsexecutiontemporarilybycallingoneoftheQThreadsleep()functionsGenerallyabadideabeingeventdriven(orpolling)ismuchmuchbetter
YoucanwaitforaQThreadtofinishbycallingwait()onitOptionallypassingamaximumnumberofmillisecondstowait
QThreadcaveats
QThread p9
Fromanon-mainthreadyoucannot
PerformanyGUIoperationIncludingbutnotlimitedtousinganyQWidgetQtQuickQPixmapAPIsUsingQImageQPainteretc(ieclientside)isOKUsingOpenGLmaybeOKcheckatruntimeQOpenGLContextsupportsThreadedOpenGL()
CallQ(Core|Gui)Applicationexec()
QThreadcaveats
QThread p10
BesuretoalwaysdestroyalltheQObjectslivinginsecondarythreadsbeforedestroyingthecorrespondingQThreadobject
DonoteverblocktheGUIthread
EnsuringdestructionofQObjects
QThread p11
CreatethemonQThreadrun()stack
ConnecttheirQObjectdeleteLater()slottotheQThreadfinished()signalYesthiswillwork
Movethemoutofthethread
EnsuringdestructionofQObjects
QThread p12
1 classMyThreadpublicQThread2 private3 voidrun()override4 MyQObjectobj1obj2obj356 QScopedPointerltOtherQObjectgtp7 if(condition)8 preset(newOtherQObject)910 autoanotherObj=newAnotherQObject11 connect(thisampQThreadfinished12 anotherObjampQObjectdeleteLater)1314 autoyetAnother=newYetAnotherQObject1516 dostuff1718 Beforequittingthethreadmovethisobjecttothemainthread19 yetAnother-gtmoveToThread(qApp-gtthread())20 Somehownotifythemainthreadaboutthisobject21 soitcanbedeletedthere22 Donottouchtheobjectfromthisthreadafterthispoint23 24
QThreadusage
QThread p13
TherearetwobasicstrategiesofrunningcodeinaseparatethreadwithQThread
Withoutaneventloop
Withaneventloop
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()1 classMyThreadpublicQThread2 private3 voidrun()override4 loadFilesFromDisk()5 doCalculations()6 saveResults()7 8
1 autothread=newMyThread2 thread-gtstart()3 sometimelater4 thread-gtwait()
QThreadusagewithaneventloop
QThread p15
Aneventloopisnecessarywhendealingwithtimersnetworkingqueuedconnectionsandsoon
Qtsupportsper-threadeventloops
Eachthread-localeventloopdeliverseventsfortheQObjectslivinginthatthread
QThreadusagewithaneventloop
QThread p16
Wecanstartathread-localeventloopbycallingQThreadexec()fromwithinrun()1 classMyThreadpublicQThread2 private3 voidrun()override4 autosocket=newQTcpSocket5 socket-gtconnectToHost()67 exec()runtheeventloop89 cleanup10 11
QThreadquit()orQThreadexit()willquittheeventloop
WecanalsouseQEventLoopOrmanualcallstoQCoreApplicationprocessEvents()
QThreadusagewithaneventloop
QThread p17
ThedefaultimplementationofQThreadrun()actuallycallsQThreadexec()
ThisallowsustoruncodeinotherthreadswithoutsubclassingQThread1 autothread=newQThread23 autoworker=newWorker45 connect(threadampQThreadstartedworkerampWorkerdoWork)6 connect(workerampWorkerworkDonethreadampQThreadquit)78 connect(threadampQThreadfinishedworkerampWorkerdeleteLater)910 worker-gtmoveToThread(thread)11 thread-gtstart()
Synchronization
Synchronization p18
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Synchronization p19
Whatisthesingle
mostimportantthingaboutthreads
Synchronization
Synchronization p20
Anyconcurrentaccesstosharedresourcesmustnotresultinadatarace
Twoconditionsforthistohappen1Atleastoneoftheaccessesisawrite2Theaccessesarenotatomicandnoaccesshappensbeforetheother
Synchronization
Synchronization p21
Qthasacompletesetofcross-platformlow-levelAPIsfordealingwithsynchronization
QMutexisamutexclass(recursiveandnon-recursive)
QSemaphoreisasemaphore
QWaitConditionisaconditionvariable
QReadWriteLockisasharedmutex
QAtomicIntisanatomicint
QAtomicPointerltTgtisanatomicpointertoT
TherearealsoRAIIclassesforlockmanagementsuchasQMutexLockerQReadLockerandsoon
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
p3
Doyouknowwhatathreadis
QThread
QThread p4
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
QThread
QThread p5
QThreadisthecentralclassinQttoruncodeinadifferentthread
ItsaQObjectsubclassNotcopiablemoveableHassignalstonotifywhenthethreadstartsfinishes
Itismeanttomanageathread
QThreadusage
QThread p6
TocreateanewthreadexecutingsomecodesubclassQThreadandreimplementrun()
Thencreateaninstanceofthesubclassandcallstart()
Threadshaveprioritiesthatyoucanspecifyasanoptionalparametertostart()orchangewithsetPriority()
QThreadusage
QThread p7
1 classMyThreadpublicQThread2 private3 voidrun()override4 codetoruninthenewthread5 6
1 MyThreadthread=newMyThread2 thread-gtstart()startsanewthreadwhichcallsrun()3 4 thread-gtwait()waitsforthethreadtofinish
QThreadusage
QThread p8
Thethreadwillstoprunningwhen(sometimeafter)returningfromrun()
QThreadisRunning()andQThreadisFinished()provideinformationabouttheexecutionofthethread
YoucanalsoconnecttotheQThreadstarted()andQThreadfinished()signals
AthreadcanstopitsexecutiontemporarilybycallingoneoftheQThreadsleep()functionsGenerallyabadideabeingeventdriven(orpolling)ismuchmuchbetter
YoucanwaitforaQThreadtofinishbycallingwait()onitOptionallypassingamaximumnumberofmillisecondstowait
QThreadcaveats
QThread p9
Fromanon-mainthreadyoucannot
PerformanyGUIoperationIncludingbutnotlimitedtousinganyQWidgetQtQuickQPixmapAPIsUsingQImageQPainteretc(ieclientside)isOKUsingOpenGLmaybeOKcheckatruntimeQOpenGLContextsupportsThreadedOpenGL()
CallQ(Core|Gui)Applicationexec()
QThreadcaveats
QThread p10
BesuretoalwaysdestroyalltheQObjectslivinginsecondarythreadsbeforedestroyingthecorrespondingQThreadobject
DonoteverblocktheGUIthread
EnsuringdestructionofQObjects
QThread p11
CreatethemonQThreadrun()stack
ConnecttheirQObjectdeleteLater()slottotheQThreadfinished()signalYesthiswillwork
Movethemoutofthethread
EnsuringdestructionofQObjects
QThread p12
1 classMyThreadpublicQThread2 private3 voidrun()override4 MyQObjectobj1obj2obj356 QScopedPointerltOtherQObjectgtp7 if(condition)8 preset(newOtherQObject)910 autoanotherObj=newAnotherQObject11 connect(thisampQThreadfinished12 anotherObjampQObjectdeleteLater)1314 autoyetAnother=newYetAnotherQObject1516 dostuff1718 Beforequittingthethreadmovethisobjecttothemainthread19 yetAnother-gtmoveToThread(qApp-gtthread())20 Somehownotifythemainthreadaboutthisobject21 soitcanbedeletedthere22 Donottouchtheobjectfromthisthreadafterthispoint23 24
QThreadusage
QThread p13
TherearetwobasicstrategiesofrunningcodeinaseparatethreadwithQThread
Withoutaneventloop
Withaneventloop
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()1 classMyThreadpublicQThread2 private3 voidrun()override4 loadFilesFromDisk()5 doCalculations()6 saveResults()7 8
1 autothread=newMyThread2 thread-gtstart()3 sometimelater4 thread-gtwait()
QThreadusagewithaneventloop
QThread p15
Aneventloopisnecessarywhendealingwithtimersnetworkingqueuedconnectionsandsoon
Qtsupportsper-threadeventloops
Eachthread-localeventloopdeliverseventsfortheQObjectslivinginthatthread
QThreadusagewithaneventloop
QThread p16
Wecanstartathread-localeventloopbycallingQThreadexec()fromwithinrun()1 classMyThreadpublicQThread2 private3 voidrun()override4 autosocket=newQTcpSocket5 socket-gtconnectToHost()67 exec()runtheeventloop89 cleanup10 11
QThreadquit()orQThreadexit()willquittheeventloop
WecanalsouseQEventLoopOrmanualcallstoQCoreApplicationprocessEvents()
QThreadusagewithaneventloop
QThread p17
ThedefaultimplementationofQThreadrun()actuallycallsQThreadexec()
ThisallowsustoruncodeinotherthreadswithoutsubclassingQThread1 autothread=newQThread23 autoworker=newWorker45 connect(threadampQThreadstartedworkerampWorkerdoWork)6 connect(workerampWorkerworkDonethreadampQThreadquit)78 connect(threadampQThreadfinishedworkerampWorkerdeleteLater)910 worker-gtmoveToThread(thread)11 thread-gtstart()
Synchronization
Synchronization p18
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Synchronization p19
Whatisthesingle
mostimportantthingaboutthreads
Synchronization
Synchronization p20
Anyconcurrentaccesstosharedresourcesmustnotresultinadatarace
Twoconditionsforthistohappen1Atleastoneoftheaccessesisawrite2Theaccessesarenotatomicandnoaccesshappensbeforetheother
Synchronization
Synchronization p21
Qthasacompletesetofcross-platformlow-levelAPIsfordealingwithsynchronization
QMutexisamutexclass(recursiveandnon-recursive)
QSemaphoreisasemaphore
QWaitConditionisaconditionvariable
QReadWriteLockisasharedmutex
QAtomicIntisanatomicint
QAtomicPointerltTgtisanatomicpointertoT
TherearealsoRAIIclassesforlockmanagementsuchasQMutexLockerQReadLockerandsoon
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QThread
QThread p4
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
QThread
QThread p5
QThreadisthecentralclassinQttoruncodeinadifferentthread
ItsaQObjectsubclassNotcopiablemoveableHassignalstonotifywhenthethreadstartsfinishes
Itismeanttomanageathread
QThreadusage
QThread p6
TocreateanewthreadexecutingsomecodesubclassQThreadandreimplementrun()
Thencreateaninstanceofthesubclassandcallstart()
Threadshaveprioritiesthatyoucanspecifyasanoptionalparametertostart()orchangewithsetPriority()
QThreadusage
QThread p7
1 classMyThreadpublicQThread2 private3 voidrun()override4 codetoruninthenewthread5 6
1 MyThreadthread=newMyThread2 thread-gtstart()startsanewthreadwhichcallsrun()3 4 thread-gtwait()waitsforthethreadtofinish
QThreadusage
QThread p8
Thethreadwillstoprunningwhen(sometimeafter)returningfromrun()
QThreadisRunning()andQThreadisFinished()provideinformationabouttheexecutionofthethread
YoucanalsoconnecttotheQThreadstarted()andQThreadfinished()signals
AthreadcanstopitsexecutiontemporarilybycallingoneoftheQThreadsleep()functionsGenerallyabadideabeingeventdriven(orpolling)ismuchmuchbetter
YoucanwaitforaQThreadtofinishbycallingwait()onitOptionallypassingamaximumnumberofmillisecondstowait
QThreadcaveats
QThread p9
Fromanon-mainthreadyoucannot
PerformanyGUIoperationIncludingbutnotlimitedtousinganyQWidgetQtQuickQPixmapAPIsUsingQImageQPainteretc(ieclientside)isOKUsingOpenGLmaybeOKcheckatruntimeQOpenGLContextsupportsThreadedOpenGL()
CallQ(Core|Gui)Applicationexec()
QThreadcaveats
QThread p10
BesuretoalwaysdestroyalltheQObjectslivinginsecondarythreadsbeforedestroyingthecorrespondingQThreadobject
DonoteverblocktheGUIthread
EnsuringdestructionofQObjects
QThread p11
CreatethemonQThreadrun()stack
ConnecttheirQObjectdeleteLater()slottotheQThreadfinished()signalYesthiswillwork
Movethemoutofthethread
EnsuringdestructionofQObjects
QThread p12
1 classMyThreadpublicQThread2 private3 voidrun()override4 MyQObjectobj1obj2obj356 QScopedPointerltOtherQObjectgtp7 if(condition)8 preset(newOtherQObject)910 autoanotherObj=newAnotherQObject11 connect(thisampQThreadfinished12 anotherObjampQObjectdeleteLater)1314 autoyetAnother=newYetAnotherQObject1516 dostuff1718 Beforequittingthethreadmovethisobjecttothemainthread19 yetAnother-gtmoveToThread(qApp-gtthread())20 Somehownotifythemainthreadaboutthisobject21 soitcanbedeletedthere22 Donottouchtheobjectfromthisthreadafterthispoint23 24
QThreadusage
QThread p13
TherearetwobasicstrategiesofrunningcodeinaseparatethreadwithQThread
Withoutaneventloop
Withaneventloop
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()1 classMyThreadpublicQThread2 private3 voidrun()override4 loadFilesFromDisk()5 doCalculations()6 saveResults()7 8
1 autothread=newMyThread2 thread-gtstart()3 sometimelater4 thread-gtwait()
QThreadusagewithaneventloop
QThread p15
Aneventloopisnecessarywhendealingwithtimersnetworkingqueuedconnectionsandsoon
Qtsupportsper-threadeventloops
Eachthread-localeventloopdeliverseventsfortheQObjectslivinginthatthread
QThreadusagewithaneventloop
QThread p16
Wecanstartathread-localeventloopbycallingQThreadexec()fromwithinrun()1 classMyThreadpublicQThread2 private3 voidrun()override4 autosocket=newQTcpSocket5 socket-gtconnectToHost()67 exec()runtheeventloop89 cleanup10 11
QThreadquit()orQThreadexit()willquittheeventloop
WecanalsouseQEventLoopOrmanualcallstoQCoreApplicationprocessEvents()
QThreadusagewithaneventloop
QThread p17
ThedefaultimplementationofQThreadrun()actuallycallsQThreadexec()
ThisallowsustoruncodeinotherthreadswithoutsubclassingQThread1 autothread=newQThread23 autoworker=newWorker45 connect(threadampQThreadstartedworkerampWorkerdoWork)6 connect(workerampWorkerworkDonethreadampQThreadquit)78 connect(threadampQThreadfinishedworkerampWorkerdeleteLater)910 worker-gtmoveToThread(thread)11 thread-gtstart()
Synchronization
Synchronization p18
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Synchronization p19
Whatisthesingle
mostimportantthingaboutthreads
Synchronization
Synchronization p20
Anyconcurrentaccesstosharedresourcesmustnotresultinadatarace
Twoconditionsforthistohappen1Atleastoneoftheaccessesisawrite2Theaccessesarenotatomicandnoaccesshappensbeforetheother
Synchronization
Synchronization p21
Qthasacompletesetofcross-platformlow-levelAPIsfordealingwithsynchronization
QMutexisamutexclass(recursiveandnon-recursive)
QSemaphoreisasemaphore
QWaitConditionisaconditionvariable
QReadWriteLockisasharedmutex
QAtomicIntisanatomicint
QAtomicPointerltTgtisanatomicpointertoT
TherearealsoRAIIclassesforlockmanagementsuchasQMutexLockerQReadLockerandsoon
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QThread
QThread p5
QThreadisthecentralclassinQttoruncodeinadifferentthread
ItsaQObjectsubclassNotcopiablemoveableHassignalstonotifywhenthethreadstartsfinishes
Itismeanttomanageathread
QThreadusage
QThread p6
TocreateanewthreadexecutingsomecodesubclassQThreadandreimplementrun()
Thencreateaninstanceofthesubclassandcallstart()
Threadshaveprioritiesthatyoucanspecifyasanoptionalparametertostart()orchangewithsetPriority()
QThreadusage
QThread p7
1 classMyThreadpublicQThread2 private3 voidrun()override4 codetoruninthenewthread5 6
1 MyThreadthread=newMyThread2 thread-gtstart()startsanewthreadwhichcallsrun()3 4 thread-gtwait()waitsforthethreadtofinish
QThreadusage
QThread p8
Thethreadwillstoprunningwhen(sometimeafter)returningfromrun()
QThreadisRunning()andQThreadisFinished()provideinformationabouttheexecutionofthethread
YoucanalsoconnecttotheQThreadstarted()andQThreadfinished()signals
AthreadcanstopitsexecutiontemporarilybycallingoneoftheQThreadsleep()functionsGenerallyabadideabeingeventdriven(orpolling)ismuchmuchbetter
YoucanwaitforaQThreadtofinishbycallingwait()onitOptionallypassingamaximumnumberofmillisecondstowait
QThreadcaveats
QThread p9
Fromanon-mainthreadyoucannot
PerformanyGUIoperationIncludingbutnotlimitedtousinganyQWidgetQtQuickQPixmapAPIsUsingQImageQPainteretc(ieclientside)isOKUsingOpenGLmaybeOKcheckatruntimeQOpenGLContextsupportsThreadedOpenGL()
CallQ(Core|Gui)Applicationexec()
QThreadcaveats
QThread p10
BesuretoalwaysdestroyalltheQObjectslivinginsecondarythreadsbeforedestroyingthecorrespondingQThreadobject
DonoteverblocktheGUIthread
EnsuringdestructionofQObjects
QThread p11
CreatethemonQThreadrun()stack
ConnecttheirQObjectdeleteLater()slottotheQThreadfinished()signalYesthiswillwork
Movethemoutofthethread
EnsuringdestructionofQObjects
QThread p12
1 classMyThreadpublicQThread2 private3 voidrun()override4 MyQObjectobj1obj2obj356 QScopedPointerltOtherQObjectgtp7 if(condition)8 preset(newOtherQObject)910 autoanotherObj=newAnotherQObject11 connect(thisampQThreadfinished12 anotherObjampQObjectdeleteLater)1314 autoyetAnother=newYetAnotherQObject1516 dostuff1718 Beforequittingthethreadmovethisobjecttothemainthread19 yetAnother-gtmoveToThread(qApp-gtthread())20 Somehownotifythemainthreadaboutthisobject21 soitcanbedeletedthere22 Donottouchtheobjectfromthisthreadafterthispoint23 24
QThreadusage
QThread p13
TherearetwobasicstrategiesofrunningcodeinaseparatethreadwithQThread
Withoutaneventloop
Withaneventloop
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()1 classMyThreadpublicQThread2 private3 voidrun()override4 loadFilesFromDisk()5 doCalculations()6 saveResults()7 8
1 autothread=newMyThread2 thread-gtstart()3 sometimelater4 thread-gtwait()
QThreadusagewithaneventloop
QThread p15
Aneventloopisnecessarywhendealingwithtimersnetworkingqueuedconnectionsandsoon
Qtsupportsper-threadeventloops
Eachthread-localeventloopdeliverseventsfortheQObjectslivinginthatthread
QThreadusagewithaneventloop
QThread p16
Wecanstartathread-localeventloopbycallingQThreadexec()fromwithinrun()1 classMyThreadpublicQThread2 private3 voidrun()override4 autosocket=newQTcpSocket5 socket-gtconnectToHost()67 exec()runtheeventloop89 cleanup10 11
QThreadquit()orQThreadexit()willquittheeventloop
WecanalsouseQEventLoopOrmanualcallstoQCoreApplicationprocessEvents()
QThreadusagewithaneventloop
QThread p17
ThedefaultimplementationofQThreadrun()actuallycallsQThreadexec()
ThisallowsustoruncodeinotherthreadswithoutsubclassingQThread1 autothread=newQThread23 autoworker=newWorker45 connect(threadampQThreadstartedworkerampWorkerdoWork)6 connect(workerampWorkerworkDonethreadampQThreadquit)78 connect(threadampQThreadfinishedworkerampWorkerdeleteLater)910 worker-gtmoveToThread(thread)11 thread-gtstart()
Synchronization
Synchronization p18
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Synchronization p19
Whatisthesingle
mostimportantthingaboutthreads
Synchronization
Synchronization p20
Anyconcurrentaccesstosharedresourcesmustnotresultinadatarace
Twoconditionsforthistohappen1Atleastoneoftheaccessesisawrite2Theaccessesarenotatomicandnoaccesshappensbeforetheother
Synchronization
Synchronization p21
Qthasacompletesetofcross-platformlow-levelAPIsfordealingwithsynchronization
QMutexisamutexclass(recursiveandnon-recursive)
QSemaphoreisasemaphore
QWaitConditionisaconditionvariable
QReadWriteLockisasharedmutex
QAtomicIntisanatomicint
QAtomicPointerltTgtisanatomicpointertoT
TherearealsoRAIIclassesforlockmanagementsuchasQMutexLockerQReadLockerandsoon
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QThreadusage
QThread p6
TocreateanewthreadexecutingsomecodesubclassQThreadandreimplementrun()
Thencreateaninstanceofthesubclassandcallstart()
Threadshaveprioritiesthatyoucanspecifyasanoptionalparametertostart()orchangewithsetPriority()
QThreadusage
QThread p7
1 classMyThreadpublicQThread2 private3 voidrun()override4 codetoruninthenewthread5 6
1 MyThreadthread=newMyThread2 thread-gtstart()startsanewthreadwhichcallsrun()3 4 thread-gtwait()waitsforthethreadtofinish
QThreadusage
QThread p8
Thethreadwillstoprunningwhen(sometimeafter)returningfromrun()
QThreadisRunning()andQThreadisFinished()provideinformationabouttheexecutionofthethread
YoucanalsoconnecttotheQThreadstarted()andQThreadfinished()signals
AthreadcanstopitsexecutiontemporarilybycallingoneoftheQThreadsleep()functionsGenerallyabadideabeingeventdriven(orpolling)ismuchmuchbetter
YoucanwaitforaQThreadtofinishbycallingwait()onitOptionallypassingamaximumnumberofmillisecondstowait
QThreadcaveats
QThread p9
Fromanon-mainthreadyoucannot
PerformanyGUIoperationIncludingbutnotlimitedtousinganyQWidgetQtQuickQPixmapAPIsUsingQImageQPainteretc(ieclientside)isOKUsingOpenGLmaybeOKcheckatruntimeQOpenGLContextsupportsThreadedOpenGL()
CallQ(Core|Gui)Applicationexec()
QThreadcaveats
QThread p10
BesuretoalwaysdestroyalltheQObjectslivinginsecondarythreadsbeforedestroyingthecorrespondingQThreadobject
DonoteverblocktheGUIthread
EnsuringdestructionofQObjects
QThread p11
CreatethemonQThreadrun()stack
ConnecttheirQObjectdeleteLater()slottotheQThreadfinished()signalYesthiswillwork
Movethemoutofthethread
EnsuringdestructionofQObjects
QThread p12
1 classMyThreadpublicQThread2 private3 voidrun()override4 MyQObjectobj1obj2obj356 QScopedPointerltOtherQObjectgtp7 if(condition)8 preset(newOtherQObject)910 autoanotherObj=newAnotherQObject11 connect(thisampQThreadfinished12 anotherObjampQObjectdeleteLater)1314 autoyetAnother=newYetAnotherQObject1516 dostuff1718 Beforequittingthethreadmovethisobjecttothemainthread19 yetAnother-gtmoveToThread(qApp-gtthread())20 Somehownotifythemainthreadaboutthisobject21 soitcanbedeletedthere22 Donottouchtheobjectfromthisthreadafterthispoint23 24
QThreadusage
QThread p13
TherearetwobasicstrategiesofrunningcodeinaseparatethreadwithQThread
Withoutaneventloop
Withaneventloop
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()1 classMyThreadpublicQThread2 private3 voidrun()override4 loadFilesFromDisk()5 doCalculations()6 saveResults()7 8
1 autothread=newMyThread2 thread-gtstart()3 sometimelater4 thread-gtwait()
QThreadusagewithaneventloop
QThread p15
Aneventloopisnecessarywhendealingwithtimersnetworkingqueuedconnectionsandsoon
Qtsupportsper-threadeventloops
Eachthread-localeventloopdeliverseventsfortheQObjectslivinginthatthread
QThreadusagewithaneventloop
QThread p16
Wecanstartathread-localeventloopbycallingQThreadexec()fromwithinrun()1 classMyThreadpublicQThread2 private3 voidrun()override4 autosocket=newQTcpSocket5 socket-gtconnectToHost()67 exec()runtheeventloop89 cleanup10 11
QThreadquit()orQThreadexit()willquittheeventloop
WecanalsouseQEventLoopOrmanualcallstoQCoreApplicationprocessEvents()
QThreadusagewithaneventloop
QThread p17
ThedefaultimplementationofQThreadrun()actuallycallsQThreadexec()
ThisallowsustoruncodeinotherthreadswithoutsubclassingQThread1 autothread=newQThread23 autoworker=newWorker45 connect(threadampQThreadstartedworkerampWorkerdoWork)6 connect(workerampWorkerworkDonethreadampQThreadquit)78 connect(threadampQThreadfinishedworkerampWorkerdeleteLater)910 worker-gtmoveToThread(thread)11 thread-gtstart()
Synchronization
Synchronization p18
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Synchronization p19
Whatisthesingle
mostimportantthingaboutthreads
Synchronization
Synchronization p20
Anyconcurrentaccesstosharedresourcesmustnotresultinadatarace
Twoconditionsforthistohappen1Atleastoneoftheaccessesisawrite2Theaccessesarenotatomicandnoaccesshappensbeforetheother
Synchronization
Synchronization p21
Qthasacompletesetofcross-platformlow-levelAPIsfordealingwithsynchronization
QMutexisamutexclass(recursiveandnon-recursive)
QSemaphoreisasemaphore
QWaitConditionisaconditionvariable
QReadWriteLockisasharedmutex
QAtomicIntisanatomicint
QAtomicPointerltTgtisanatomicpointertoT
TherearealsoRAIIclassesforlockmanagementsuchasQMutexLockerQReadLockerandsoon
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QThreadusage
QThread p7
1 classMyThreadpublicQThread2 private3 voidrun()override4 codetoruninthenewthread5 6
1 MyThreadthread=newMyThread2 thread-gtstart()startsanewthreadwhichcallsrun()3 4 thread-gtwait()waitsforthethreadtofinish
QThreadusage
QThread p8
Thethreadwillstoprunningwhen(sometimeafter)returningfromrun()
QThreadisRunning()andQThreadisFinished()provideinformationabouttheexecutionofthethread
YoucanalsoconnecttotheQThreadstarted()andQThreadfinished()signals
AthreadcanstopitsexecutiontemporarilybycallingoneoftheQThreadsleep()functionsGenerallyabadideabeingeventdriven(orpolling)ismuchmuchbetter
YoucanwaitforaQThreadtofinishbycallingwait()onitOptionallypassingamaximumnumberofmillisecondstowait
QThreadcaveats
QThread p9
Fromanon-mainthreadyoucannot
PerformanyGUIoperationIncludingbutnotlimitedtousinganyQWidgetQtQuickQPixmapAPIsUsingQImageQPainteretc(ieclientside)isOKUsingOpenGLmaybeOKcheckatruntimeQOpenGLContextsupportsThreadedOpenGL()
CallQ(Core|Gui)Applicationexec()
QThreadcaveats
QThread p10
BesuretoalwaysdestroyalltheQObjectslivinginsecondarythreadsbeforedestroyingthecorrespondingQThreadobject
DonoteverblocktheGUIthread
EnsuringdestructionofQObjects
QThread p11
CreatethemonQThreadrun()stack
ConnecttheirQObjectdeleteLater()slottotheQThreadfinished()signalYesthiswillwork
Movethemoutofthethread
EnsuringdestructionofQObjects
QThread p12
1 classMyThreadpublicQThread2 private3 voidrun()override4 MyQObjectobj1obj2obj356 QScopedPointerltOtherQObjectgtp7 if(condition)8 preset(newOtherQObject)910 autoanotherObj=newAnotherQObject11 connect(thisampQThreadfinished12 anotherObjampQObjectdeleteLater)1314 autoyetAnother=newYetAnotherQObject1516 dostuff1718 Beforequittingthethreadmovethisobjecttothemainthread19 yetAnother-gtmoveToThread(qApp-gtthread())20 Somehownotifythemainthreadaboutthisobject21 soitcanbedeletedthere22 Donottouchtheobjectfromthisthreadafterthispoint23 24
QThreadusage
QThread p13
TherearetwobasicstrategiesofrunningcodeinaseparatethreadwithQThread
Withoutaneventloop
Withaneventloop
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()1 classMyThreadpublicQThread2 private3 voidrun()override4 loadFilesFromDisk()5 doCalculations()6 saveResults()7 8
1 autothread=newMyThread2 thread-gtstart()3 sometimelater4 thread-gtwait()
QThreadusagewithaneventloop
QThread p15
Aneventloopisnecessarywhendealingwithtimersnetworkingqueuedconnectionsandsoon
Qtsupportsper-threadeventloops
Eachthread-localeventloopdeliverseventsfortheQObjectslivinginthatthread
QThreadusagewithaneventloop
QThread p16
Wecanstartathread-localeventloopbycallingQThreadexec()fromwithinrun()1 classMyThreadpublicQThread2 private3 voidrun()override4 autosocket=newQTcpSocket5 socket-gtconnectToHost()67 exec()runtheeventloop89 cleanup10 11
QThreadquit()orQThreadexit()willquittheeventloop
WecanalsouseQEventLoopOrmanualcallstoQCoreApplicationprocessEvents()
QThreadusagewithaneventloop
QThread p17
ThedefaultimplementationofQThreadrun()actuallycallsQThreadexec()
ThisallowsustoruncodeinotherthreadswithoutsubclassingQThread1 autothread=newQThread23 autoworker=newWorker45 connect(threadampQThreadstartedworkerampWorkerdoWork)6 connect(workerampWorkerworkDonethreadampQThreadquit)78 connect(threadampQThreadfinishedworkerampWorkerdeleteLater)910 worker-gtmoveToThread(thread)11 thread-gtstart()
Synchronization
Synchronization p18
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Synchronization p19
Whatisthesingle
mostimportantthingaboutthreads
Synchronization
Synchronization p20
Anyconcurrentaccesstosharedresourcesmustnotresultinadatarace
Twoconditionsforthistohappen1Atleastoneoftheaccessesisawrite2Theaccessesarenotatomicandnoaccesshappensbeforetheother
Synchronization
Synchronization p21
Qthasacompletesetofcross-platformlow-levelAPIsfordealingwithsynchronization
QMutexisamutexclass(recursiveandnon-recursive)
QSemaphoreisasemaphore
QWaitConditionisaconditionvariable
QReadWriteLockisasharedmutex
QAtomicIntisanatomicint
QAtomicPointerltTgtisanatomicpointertoT
TherearealsoRAIIclassesforlockmanagementsuchasQMutexLockerQReadLockerandsoon
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QThreadusage
QThread p8
Thethreadwillstoprunningwhen(sometimeafter)returningfromrun()
QThreadisRunning()andQThreadisFinished()provideinformationabouttheexecutionofthethread
YoucanalsoconnecttotheQThreadstarted()andQThreadfinished()signals
AthreadcanstopitsexecutiontemporarilybycallingoneoftheQThreadsleep()functionsGenerallyabadideabeingeventdriven(orpolling)ismuchmuchbetter
YoucanwaitforaQThreadtofinishbycallingwait()onitOptionallypassingamaximumnumberofmillisecondstowait
QThreadcaveats
QThread p9
Fromanon-mainthreadyoucannot
PerformanyGUIoperationIncludingbutnotlimitedtousinganyQWidgetQtQuickQPixmapAPIsUsingQImageQPainteretc(ieclientside)isOKUsingOpenGLmaybeOKcheckatruntimeQOpenGLContextsupportsThreadedOpenGL()
CallQ(Core|Gui)Applicationexec()
QThreadcaveats
QThread p10
BesuretoalwaysdestroyalltheQObjectslivinginsecondarythreadsbeforedestroyingthecorrespondingQThreadobject
DonoteverblocktheGUIthread
EnsuringdestructionofQObjects
QThread p11
CreatethemonQThreadrun()stack
ConnecttheirQObjectdeleteLater()slottotheQThreadfinished()signalYesthiswillwork
Movethemoutofthethread
EnsuringdestructionofQObjects
QThread p12
1 classMyThreadpublicQThread2 private3 voidrun()override4 MyQObjectobj1obj2obj356 QScopedPointerltOtherQObjectgtp7 if(condition)8 preset(newOtherQObject)910 autoanotherObj=newAnotherQObject11 connect(thisampQThreadfinished12 anotherObjampQObjectdeleteLater)1314 autoyetAnother=newYetAnotherQObject1516 dostuff1718 Beforequittingthethreadmovethisobjecttothemainthread19 yetAnother-gtmoveToThread(qApp-gtthread())20 Somehownotifythemainthreadaboutthisobject21 soitcanbedeletedthere22 Donottouchtheobjectfromthisthreadafterthispoint23 24
QThreadusage
QThread p13
TherearetwobasicstrategiesofrunningcodeinaseparatethreadwithQThread
Withoutaneventloop
Withaneventloop
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()1 classMyThreadpublicQThread2 private3 voidrun()override4 loadFilesFromDisk()5 doCalculations()6 saveResults()7 8
1 autothread=newMyThread2 thread-gtstart()3 sometimelater4 thread-gtwait()
QThreadusagewithaneventloop
QThread p15
Aneventloopisnecessarywhendealingwithtimersnetworkingqueuedconnectionsandsoon
Qtsupportsper-threadeventloops
Eachthread-localeventloopdeliverseventsfortheQObjectslivinginthatthread
QThreadusagewithaneventloop
QThread p16
Wecanstartathread-localeventloopbycallingQThreadexec()fromwithinrun()1 classMyThreadpublicQThread2 private3 voidrun()override4 autosocket=newQTcpSocket5 socket-gtconnectToHost()67 exec()runtheeventloop89 cleanup10 11
QThreadquit()orQThreadexit()willquittheeventloop
WecanalsouseQEventLoopOrmanualcallstoQCoreApplicationprocessEvents()
QThreadusagewithaneventloop
QThread p17
ThedefaultimplementationofQThreadrun()actuallycallsQThreadexec()
ThisallowsustoruncodeinotherthreadswithoutsubclassingQThread1 autothread=newQThread23 autoworker=newWorker45 connect(threadampQThreadstartedworkerampWorkerdoWork)6 connect(workerampWorkerworkDonethreadampQThreadquit)78 connect(threadampQThreadfinishedworkerampWorkerdeleteLater)910 worker-gtmoveToThread(thread)11 thread-gtstart()
Synchronization
Synchronization p18
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Synchronization p19
Whatisthesingle
mostimportantthingaboutthreads
Synchronization
Synchronization p20
Anyconcurrentaccesstosharedresourcesmustnotresultinadatarace
Twoconditionsforthistohappen1Atleastoneoftheaccessesisawrite2Theaccessesarenotatomicandnoaccesshappensbeforetheother
Synchronization
Synchronization p21
Qthasacompletesetofcross-platformlow-levelAPIsfordealingwithsynchronization
QMutexisamutexclass(recursiveandnon-recursive)
QSemaphoreisasemaphore
QWaitConditionisaconditionvariable
QReadWriteLockisasharedmutex
QAtomicIntisanatomicint
QAtomicPointerltTgtisanatomicpointertoT
TherearealsoRAIIclassesforlockmanagementsuchasQMutexLockerQReadLockerandsoon
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QThreadcaveats
QThread p9
Fromanon-mainthreadyoucannot
PerformanyGUIoperationIncludingbutnotlimitedtousinganyQWidgetQtQuickQPixmapAPIsUsingQImageQPainteretc(ieclientside)isOKUsingOpenGLmaybeOKcheckatruntimeQOpenGLContextsupportsThreadedOpenGL()
CallQ(Core|Gui)Applicationexec()
QThreadcaveats
QThread p10
BesuretoalwaysdestroyalltheQObjectslivinginsecondarythreadsbeforedestroyingthecorrespondingQThreadobject
DonoteverblocktheGUIthread
EnsuringdestructionofQObjects
QThread p11
CreatethemonQThreadrun()stack
ConnecttheirQObjectdeleteLater()slottotheQThreadfinished()signalYesthiswillwork
Movethemoutofthethread
EnsuringdestructionofQObjects
QThread p12
1 classMyThreadpublicQThread2 private3 voidrun()override4 MyQObjectobj1obj2obj356 QScopedPointerltOtherQObjectgtp7 if(condition)8 preset(newOtherQObject)910 autoanotherObj=newAnotherQObject11 connect(thisampQThreadfinished12 anotherObjampQObjectdeleteLater)1314 autoyetAnother=newYetAnotherQObject1516 dostuff1718 Beforequittingthethreadmovethisobjecttothemainthread19 yetAnother-gtmoveToThread(qApp-gtthread())20 Somehownotifythemainthreadaboutthisobject21 soitcanbedeletedthere22 Donottouchtheobjectfromthisthreadafterthispoint23 24
QThreadusage
QThread p13
TherearetwobasicstrategiesofrunningcodeinaseparatethreadwithQThread
Withoutaneventloop
Withaneventloop
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()1 classMyThreadpublicQThread2 private3 voidrun()override4 loadFilesFromDisk()5 doCalculations()6 saveResults()7 8
1 autothread=newMyThread2 thread-gtstart()3 sometimelater4 thread-gtwait()
QThreadusagewithaneventloop
QThread p15
Aneventloopisnecessarywhendealingwithtimersnetworkingqueuedconnectionsandsoon
Qtsupportsper-threadeventloops
Eachthread-localeventloopdeliverseventsfortheQObjectslivinginthatthread
QThreadusagewithaneventloop
QThread p16
Wecanstartathread-localeventloopbycallingQThreadexec()fromwithinrun()1 classMyThreadpublicQThread2 private3 voidrun()override4 autosocket=newQTcpSocket5 socket-gtconnectToHost()67 exec()runtheeventloop89 cleanup10 11
QThreadquit()orQThreadexit()willquittheeventloop
WecanalsouseQEventLoopOrmanualcallstoQCoreApplicationprocessEvents()
QThreadusagewithaneventloop
QThread p17
ThedefaultimplementationofQThreadrun()actuallycallsQThreadexec()
ThisallowsustoruncodeinotherthreadswithoutsubclassingQThread1 autothread=newQThread23 autoworker=newWorker45 connect(threadampQThreadstartedworkerampWorkerdoWork)6 connect(workerampWorkerworkDonethreadampQThreadquit)78 connect(threadampQThreadfinishedworkerampWorkerdeleteLater)910 worker-gtmoveToThread(thread)11 thread-gtstart()
Synchronization
Synchronization p18
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Synchronization p19
Whatisthesingle
mostimportantthingaboutthreads
Synchronization
Synchronization p20
Anyconcurrentaccesstosharedresourcesmustnotresultinadatarace
Twoconditionsforthistohappen1Atleastoneoftheaccessesisawrite2Theaccessesarenotatomicandnoaccesshappensbeforetheother
Synchronization
Synchronization p21
Qthasacompletesetofcross-platformlow-levelAPIsfordealingwithsynchronization
QMutexisamutexclass(recursiveandnon-recursive)
QSemaphoreisasemaphore
QWaitConditionisaconditionvariable
QReadWriteLockisasharedmutex
QAtomicIntisanatomicint
QAtomicPointerltTgtisanatomicpointertoT
TherearealsoRAIIclassesforlockmanagementsuchasQMutexLockerQReadLockerandsoon
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QThreadcaveats
QThread p10
BesuretoalwaysdestroyalltheQObjectslivinginsecondarythreadsbeforedestroyingthecorrespondingQThreadobject
DonoteverblocktheGUIthread
EnsuringdestructionofQObjects
QThread p11
CreatethemonQThreadrun()stack
ConnecttheirQObjectdeleteLater()slottotheQThreadfinished()signalYesthiswillwork
Movethemoutofthethread
EnsuringdestructionofQObjects
QThread p12
1 classMyThreadpublicQThread2 private3 voidrun()override4 MyQObjectobj1obj2obj356 QScopedPointerltOtherQObjectgtp7 if(condition)8 preset(newOtherQObject)910 autoanotherObj=newAnotherQObject11 connect(thisampQThreadfinished12 anotherObjampQObjectdeleteLater)1314 autoyetAnother=newYetAnotherQObject1516 dostuff1718 Beforequittingthethreadmovethisobjecttothemainthread19 yetAnother-gtmoveToThread(qApp-gtthread())20 Somehownotifythemainthreadaboutthisobject21 soitcanbedeletedthere22 Donottouchtheobjectfromthisthreadafterthispoint23 24
QThreadusage
QThread p13
TherearetwobasicstrategiesofrunningcodeinaseparatethreadwithQThread
Withoutaneventloop
Withaneventloop
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()1 classMyThreadpublicQThread2 private3 voidrun()override4 loadFilesFromDisk()5 doCalculations()6 saveResults()7 8
1 autothread=newMyThread2 thread-gtstart()3 sometimelater4 thread-gtwait()
QThreadusagewithaneventloop
QThread p15
Aneventloopisnecessarywhendealingwithtimersnetworkingqueuedconnectionsandsoon
Qtsupportsper-threadeventloops
Eachthread-localeventloopdeliverseventsfortheQObjectslivinginthatthread
QThreadusagewithaneventloop
QThread p16
Wecanstartathread-localeventloopbycallingQThreadexec()fromwithinrun()1 classMyThreadpublicQThread2 private3 voidrun()override4 autosocket=newQTcpSocket5 socket-gtconnectToHost()67 exec()runtheeventloop89 cleanup10 11
QThreadquit()orQThreadexit()willquittheeventloop
WecanalsouseQEventLoopOrmanualcallstoQCoreApplicationprocessEvents()
QThreadusagewithaneventloop
QThread p17
ThedefaultimplementationofQThreadrun()actuallycallsQThreadexec()
ThisallowsustoruncodeinotherthreadswithoutsubclassingQThread1 autothread=newQThread23 autoworker=newWorker45 connect(threadampQThreadstartedworkerampWorkerdoWork)6 connect(workerampWorkerworkDonethreadampQThreadquit)78 connect(threadampQThreadfinishedworkerampWorkerdeleteLater)910 worker-gtmoveToThread(thread)11 thread-gtstart()
Synchronization
Synchronization p18
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Synchronization p19
Whatisthesingle
mostimportantthingaboutthreads
Synchronization
Synchronization p20
Anyconcurrentaccesstosharedresourcesmustnotresultinadatarace
Twoconditionsforthistohappen1Atleastoneoftheaccessesisawrite2Theaccessesarenotatomicandnoaccesshappensbeforetheother
Synchronization
Synchronization p21
Qthasacompletesetofcross-platformlow-levelAPIsfordealingwithsynchronization
QMutexisamutexclass(recursiveandnon-recursive)
QSemaphoreisasemaphore
QWaitConditionisaconditionvariable
QReadWriteLockisasharedmutex
QAtomicIntisanatomicint
QAtomicPointerltTgtisanatomicpointertoT
TherearealsoRAIIclassesforlockmanagementsuchasQMutexLockerQReadLockerandsoon
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
EnsuringdestructionofQObjects
QThread p11
CreatethemonQThreadrun()stack
ConnecttheirQObjectdeleteLater()slottotheQThreadfinished()signalYesthiswillwork
Movethemoutofthethread
EnsuringdestructionofQObjects
QThread p12
1 classMyThreadpublicQThread2 private3 voidrun()override4 MyQObjectobj1obj2obj356 QScopedPointerltOtherQObjectgtp7 if(condition)8 preset(newOtherQObject)910 autoanotherObj=newAnotherQObject11 connect(thisampQThreadfinished12 anotherObjampQObjectdeleteLater)1314 autoyetAnother=newYetAnotherQObject1516 dostuff1718 Beforequittingthethreadmovethisobjecttothemainthread19 yetAnother-gtmoveToThread(qApp-gtthread())20 Somehownotifythemainthreadaboutthisobject21 soitcanbedeletedthere22 Donottouchtheobjectfromthisthreadafterthispoint23 24
QThreadusage
QThread p13
TherearetwobasicstrategiesofrunningcodeinaseparatethreadwithQThread
Withoutaneventloop
Withaneventloop
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()1 classMyThreadpublicQThread2 private3 voidrun()override4 loadFilesFromDisk()5 doCalculations()6 saveResults()7 8
1 autothread=newMyThread2 thread-gtstart()3 sometimelater4 thread-gtwait()
QThreadusagewithaneventloop
QThread p15
Aneventloopisnecessarywhendealingwithtimersnetworkingqueuedconnectionsandsoon
Qtsupportsper-threadeventloops
Eachthread-localeventloopdeliverseventsfortheQObjectslivinginthatthread
QThreadusagewithaneventloop
QThread p16
Wecanstartathread-localeventloopbycallingQThreadexec()fromwithinrun()1 classMyThreadpublicQThread2 private3 voidrun()override4 autosocket=newQTcpSocket5 socket-gtconnectToHost()67 exec()runtheeventloop89 cleanup10 11
QThreadquit()orQThreadexit()willquittheeventloop
WecanalsouseQEventLoopOrmanualcallstoQCoreApplicationprocessEvents()
QThreadusagewithaneventloop
QThread p17
ThedefaultimplementationofQThreadrun()actuallycallsQThreadexec()
ThisallowsustoruncodeinotherthreadswithoutsubclassingQThread1 autothread=newQThread23 autoworker=newWorker45 connect(threadampQThreadstartedworkerampWorkerdoWork)6 connect(workerampWorkerworkDonethreadampQThreadquit)78 connect(threadampQThreadfinishedworkerampWorkerdeleteLater)910 worker-gtmoveToThread(thread)11 thread-gtstart()
Synchronization
Synchronization p18
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Synchronization p19
Whatisthesingle
mostimportantthingaboutthreads
Synchronization
Synchronization p20
Anyconcurrentaccesstosharedresourcesmustnotresultinadatarace
Twoconditionsforthistohappen1Atleastoneoftheaccessesisawrite2Theaccessesarenotatomicandnoaccesshappensbeforetheother
Synchronization
Synchronization p21
Qthasacompletesetofcross-platformlow-levelAPIsfordealingwithsynchronization
QMutexisamutexclass(recursiveandnon-recursive)
QSemaphoreisasemaphore
QWaitConditionisaconditionvariable
QReadWriteLockisasharedmutex
QAtomicIntisanatomicint
QAtomicPointerltTgtisanatomicpointertoT
TherearealsoRAIIclassesforlockmanagementsuchasQMutexLockerQReadLockerandsoon
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
EnsuringdestructionofQObjects
QThread p12
1 classMyThreadpublicQThread2 private3 voidrun()override4 MyQObjectobj1obj2obj356 QScopedPointerltOtherQObjectgtp7 if(condition)8 preset(newOtherQObject)910 autoanotherObj=newAnotherQObject11 connect(thisampQThreadfinished12 anotherObjampQObjectdeleteLater)1314 autoyetAnother=newYetAnotherQObject1516 dostuff1718 Beforequittingthethreadmovethisobjecttothemainthread19 yetAnother-gtmoveToThread(qApp-gtthread())20 Somehownotifythemainthreadaboutthisobject21 soitcanbedeletedthere22 Donottouchtheobjectfromthisthreadafterthispoint23 24
QThreadusage
QThread p13
TherearetwobasicstrategiesofrunningcodeinaseparatethreadwithQThread
Withoutaneventloop
Withaneventloop
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()1 classMyThreadpublicQThread2 private3 voidrun()override4 loadFilesFromDisk()5 doCalculations()6 saveResults()7 8
1 autothread=newMyThread2 thread-gtstart()3 sometimelater4 thread-gtwait()
QThreadusagewithaneventloop
QThread p15
Aneventloopisnecessarywhendealingwithtimersnetworkingqueuedconnectionsandsoon
Qtsupportsper-threadeventloops
Eachthread-localeventloopdeliverseventsfortheQObjectslivinginthatthread
QThreadusagewithaneventloop
QThread p16
Wecanstartathread-localeventloopbycallingQThreadexec()fromwithinrun()1 classMyThreadpublicQThread2 private3 voidrun()override4 autosocket=newQTcpSocket5 socket-gtconnectToHost()67 exec()runtheeventloop89 cleanup10 11
QThreadquit()orQThreadexit()willquittheeventloop
WecanalsouseQEventLoopOrmanualcallstoQCoreApplicationprocessEvents()
QThreadusagewithaneventloop
QThread p17
ThedefaultimplementationofQThreadrun()actuallycallsQThreadexec()
ThisallowsustoruncodeinotherthreadswithoutsubclassingQThread1 autothread=newQThread23 autoworker=newWorker45 connect(threadampQThreadstartedworkerampWorkerdoWork)6 connect(workerampWorkerworkDonethreadampQThreadquit)78 connect(threadampQThreadfinishedworkerampWorkerdeleteLater)910 worker-gtmoveToThread(thread)11 thread-gtstart()
Synchronization
Synchronization p18
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Synchronization p19
Whatisthesingle
mostimportantthingaboutthreads
Synchronization
Synchronization p20
Anyconcurrentaccesstosharedresourcesmustnotresultinadatarace
Twoconditionsforthistohappen1Atleastoneoftheaccessesisawrite2Theaccessesarenotatomicandnoaccesshappensbeforetheother
Synchronization
Synchronization p21
Qthasacompletesetofcross-platformlow-levelAPIsfordealingwithsynchronization
QMutexisamutexclass(recursiveandnon-recursive)
QSemaphoreisasemaphore
QWaitConditionisaconditionvariable
QReadWriteLockisasharedmutex
QAtomicIntisanatomicint
QAtomicPointerltTgtisanatomicpointertoT
TherearealsoRAIIclassesforlockmanagementsuchasQMutexLockerQReadLockerandsoon
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QThreadusage
QThread p13
TherearetwobasicstrategiesofrunningcodeinaseparatethreadwithQThread
Withoutaneventloop
Withaneventloop
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()1 classMyThreadpublicQThread2 private3 voidrun()override4 loadFilesFromDisk()5 doCalculations()6 saveResults()7 8
1 autothread=newMyThread2 thread-gtstart()3 sometimelater4 thread-gtwait()
QThreadusagewithaneventloop
QThread p15
Aneventloopisnecessarywhendealingwithtimersnetworkingqueuedconnectionsandsoon
Qtsupportsper-threadeventloops
Eachthread-localeventloopdeliverseventsfortheQObjectslivinginthatthread
QThreadusagewithaneventloop
QThread p16
Wecanstartathread-localeventloopbycallingQThreadexec()fromwithinrun()1 classMyThreadpublicQThread2 private3 voidrun()override4 autosocket=newQTcpSocket5 socket-gtconnectToHost()67 exec()runtheeventloop89 cleanup10 11
QThreadquit()orQThreadexit()willquittheeventloop
WecanalsouseQEventLoopOrmanualcallstoQCoreApplicationprocessEvents()
QThreadusagewithaneventloop
QThread p17
ThedefaultimplementationofQThreadrun()actuallycallsQThreadexec()
ThisallowsustoruncodeinotherthreadswithoutsubclassingQThread1 autothread=newQThread23 autoworker=newWorker45 connect(threadampQThreadstartedworkerampWorkerdoWork)6 connect(workerampWorkerworkDonethreadampQThreadquit)78 connect(threadampQThreadfinishedworkerampWorkerdeleteLater)910 worker-gtmoveToThread(thread)11 thread-gtstart()
Synchronization
Synchronization p18
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Synchronization p19
Whatisthesingle
mostimportantthingaboutthreads
Synchronization
Synchronization p20
Anyconcurrentaccesstosharedresourcesmustnotresultinadatarace
Twoconditionsforthistohappen1Atleastoneoftheaccessesisawrite2Theaccessesarenotatomicandnoaccesshappensbeforetheother
Synchronization
Synchronization p21
Qthasacompletesetofcross-platformlow-levelAPIsfordealingwithsynchronization
QMutexisamutexclass(recursiveandnon-recursive)
QSemaphoreisasemaphore
QWaitConditionisaconditionvariable
QReadWriteLockisasharedmutex
QAtomicIntisanatomicint
QAtomicPointerltTgtisanatomicpointertoT
TherearealsoRAIIclassesforlockmanagementsuchasQMutexLockerQReadLockerandsoon
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()1 classMyThreadpublicQThread2 private3 voidrun()override4 loadFilesFromDisk()5 doCalculations()6 saveResults()7 8
1 autothread=newMyThread2 thread-gtstart()3 sometimelater4 thread-gtwait()
QThreadusagewithaneventloop
QThread p15
Aneventloopisnecessarywhendealingwithtimersnetworkingqueuedconnectionsandsoon
Qtsupportsper-threadeventloops
Eachthread-localeventloopdeliverseventsfortheQObjectslivinginthatthread
QThreadusagewithaneventloop
QThread p16
Wecanstartathread-localeventloopbycallingQThreadexec()fromwithinrun()1 classMyThreadpublicQThread2 private3 voidrun()override4 autosocket=newQTcpSocket5 socket-gtconnectToHost()67 exec()runtheeventloop89 cleanup10 11
QThreadquit()orQThreadexit()willquittheeventloop
WecanalsouseQEventLoopOrmanualcallstoQCoreApplicationprocessEvents()
QThreadusagewithaneventloop
QThread p17
ThedefaultimplementationofQThreadrun()actuallycallsQThreadexec()
ThisallowsustoruncodeinotherthreadswithoutsubclassingQThread1 autothread=newQThread23 autoworker=newWorker45 connect(threadampQThreadstartedworkerampWorkerdoWork)6 connect(workerampWorkerworkDonethreadampQThreadquit)78 connect(threadampQThreadfinishedworkerampWorkerdeleteLater)910 worker-gtmoveToThread(thread)11 thread-gtstart()
Synchronization
Synchronization p18
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Synchronization p19
Whatisthesingle
mostimportantthingaboutthreads
Synchronization
Synchronization p20
Anyconcurrentaccesstosharedresourcesmustnotresultinadatarace
Twoconditionsforthistohappen1Atleastoneoftheaccessesisawrite2Theaccessesarenotatomicandnoaccesshappensbeforetheother
Synchronization
Synchronization p21
Qthasacompletesetofcross-platformlow-levelAPIsfordealingwithsynchronization
QMutexisamutexclass(recursiveandnon-recursive)
QSemaphoreisasemaphore
QWaitConditionisaconditionvariable
QReadWriteLockisasharedmutex
QAtomicIntisanatomicint
QAtomicPointerltTgtisanatomicpointertoT
TherearealsoRAIIclassesforlockmanagementsuchasQMutexLockerQReadLockerandsoon
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QThreadusagewithoutaneventloop
QThread p14
SubclassQThreadandoverrideQThreadrun()
CreateaninstanceandstartthenewthreadviaQThreadstart()1 classMyThreadpublicQThread2 private3 voidrun()override4 loadFilesFromDisk()5 doCalculations()6 saveResults()7 8
1 autothread=newMyThread2 thread-gtstart()3 sometimelater4 thread-gtwait()
QThreadusagewithaneventloop
QThread p15
Aneventloopisnecessarywhendealingwithtimersnetworkingqueuedconnectionsandsoon
Qtsupportsper-threadeventloops
Eachthread-localeventloopdeliverseventsfortheQObjectslivinginthatthread
QThreadusagewithaneventloop
QThread p16
Wecanstartathread-localeventloopbycallingQThreadexec()fromwithinrun()1 classMyThreadpublicQThread2 private3 voidrun()override4 autosocket=newQTcpSocket5 socket-gtconnectToHost()67 exec()runtheeventloop89 cleanup10 11
QThreadquit()orQThreadexit()willquittheeventloop
WecanalsouseQEventLoopOrmanualcallstoQCoreApplicationprocessEvents()
QThreadusagewithaneventloop
QThread p17
ThedefaultimplementationofQThreadrun()actuallycallsQThreadexec()
ThisallowsustoruncodeinotherthreadswithoutsubclassingQThread1 autothread=newQThread23 autoworker=newWorker45 connect(threadampQThreadstartedworkerampWorkerdoWork)6 connect(workerampWorkerworkDonethreadampQThreadquit)78 connect(threadampQThreadfinishedworkerampWorkerdeleteLater)910 worker-gtmoveToThread(thread)11 thread-gtstart()
Synchronization
Synchronization p18
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Synchronization p19
Whatisthesingle
mostimportantthingaboutthreads
Synchronization
Synchronization p20
Anyconcurrentaccesstosharedresourcesmustnotresultinadatarace
Twoconditionsforthistohappen1Atleastoneoftheaccessesisawrite2Theaccessesarenotatomicandnoaccesshappensbeforetheother
Synchronization
Synchronization p21
Qthasacompletesetofcross-platformlow-levelAPIsfordealingwithsynchronization
QMutexisamutexclass(recursiveandnon-recursive)
QSemaphoreisasemaphore
QWaitConditionisaconditionvariable
QReadWriteLockisasharedmutex
QAtomicIntisanatomicint
QAtomicPointerltTgtisanatomicpointertoT
TherearealsoRAIIclassesforlockmanagementsuchasQMutexLockerQReadLockerandsoon
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QThreadusagewithaneventloop
QThread p15
Aneventloopisnecessarywhendealingwithtimersnetworkingqueuedconnectionsandsoon
Qtsupportsper-threadeventloops
Eachthread-localeventloopdeliverseventsfortheQObjectslivinginthatthread
QThreadusagewithaneventloop
QThread p16
Wecanstartathread-localeventloopbycallingQThreadexec()fromwithinrun()1 classMyThreadpublicQThread2 private3 voidrun()override4 autosocket=newQTcpSocket5 socket-gtconnectToHost()67 exec()runtheeventloop89 cleanup10 11
QThreadquit()orQThreadexit()willquittheeventloop
WecanalsouseQEventLoopOrmanualcallstoQCoreApplicationprocessEvents()
QThreadusagewithaneventloop
QThread p17
ThedefaultimplementationofQThreadrun()actuallycallsQThreadexec()
ThisallowsustoruncodeinotherthreadswithoutsubclassingQThread1 autothread=newQThread23 autoworker=newWorker45 connect(threadampQThreadstartedworkerampWorkerdoWork)6 connect(workerampWorkerworkDonethreadampQThreadquit)78 connect(threadampQThreadfinishedworkerampWorkerdeleteLater)910 worker-gtmoveToThread(thread)11 thread-gtstart()
Synchronization
Synchronization p18
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Synchronization p19
Whatisthesingle
mostimportantthingaboutthreads
Synchronization
Synchronization p20
Anyconcurrentaccesstosharedresourcesmustnotresultinadatarace
Twoconditionsforthistohappen1Atleastoneoftheaccessesisawrite2Theaccessesarenotatomicandnoaccesshappensbeforetheother
Synchronization
Synchronization p21
Qthasacompletesetofcross-platformlow-levelAPIsfordealingwithsynchronization
QMutexisamutexclass(recursiveandnon-recursive)
QSemaphoreisasemaphore
QWaitConditionisaconditionvariable
QReadWriteLockisasharedmutex
QAtomicIntisanatomicint
QAtomicPointerltTgtisanatomicpointertoT
TherearealsoRAIIclassesforlockmanagementsuchasQMutexLockerQReadLockerandsoon
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QThreadusagewithaneventloop
QThread p16
Wecanstartathread-localeventloopbycallingQThreadexec()fromwithinrun()1 classMyThreadpublicQThread2 private3 voidrun()override4 autosocket=newQTcpSocket5 socket-gtconnectToHost()67 exec()runtheeventloop89 cleanup10 11
QThreadquit()orQThreadexit()willquittheeventloop
WecanalsouseQEventLoopOrmanualcallstoQCoreApplicationprocessEvents()
QThreadusagewithaneventloop
QThread p17
ThedefaultimplementationofQThreadrun()actuallycallsQThreadexec()
ThisallowsustoruncodeinotherthreadswithoutsubclassingQThread1 autothread=newQThread23 autoworker=newWorker45 connect(threadampQThreadstartedworkerampWorkerdoWork)6 connect(workerampWorkerworkDonethreadampQThreadquit)78 connect(threadampQThreadfinishedworkerampWorkerdeleteLater)910 worker-gtmoveToThread(thread)11 thread-gtstart()
Synchronization
Synchronization p18
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Synchronization p19
Whatisthesingle
mostimportantthingaboutthreads
Synchronization
Synchronization p20
Anyconcurrentaccesstosharedresourcesmustnotresultinadatarace
Twoconditionsforthistohappen1Atleastoneoftheaccessesisawrite2Theaccessesarenotatomicandnoaccesshappensbeforetheother
Synchronization
Synchronization p21
Qthasacompletesetofcross-platformlow-levelAPIsfordealingwithsynchronization
QMutexisamutexclass(recursiveandnon-recursive)
QSemaphoreisasemaphore
QWaitConditionisaconditionvariable
QReadWriteLockisasharedmutex
QAtomicIntisanatomicint
QAtomicPointerltTgtisanatomicpointertoT
TherearealsoRAIIclassesforlockmanagementsuchasQMutexLockerQReadLockerandsoon
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QThreadusagewithaneventloop
QThread p17
ThedefaultimplementationofQThreadrun()actuallycallsQThreadexec()
ThisallowsustoruncodeinotherthreadswithoutsubclassingQThread1 autothread=newQThread23 autoworker=newWorker45 connect(threadampQThreadstartedworkerampWorkerdoWork)6 connect(workerampWorkerworkDonethreadampQThreadquit)78 connect(threadampQThreadfinishedworkerampWorkerdeleteLater)910 worker-gtmoveToThread(thread)11 thread-gtstart()
Synchronization
Synchronization p18
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Synchronization p19
Whatisthesingle
mostimportantthingaboutthreads
Synchronization
Synchronization p20
Anyconcurrentaccesstosharedresourcesmustnotresultinadatarace
Twoconditionsforthistohappen1Atleastoneoftheaccessesisawrite2Theaccessesarenotatomicandnoaccesshappensbeforetheother
Synchronization
Synchronization p21
Qthasacompletesetofcross-platformlow-levelAPIsfordealingwithsynchronization
QMutexisamutexclass(recursiveandnon-recursive)
QSemaphoreisasemaphore
QWaitConditionisaconditionvariable
QReadWriteLockisasharedmutex
QAtomicIntisanatomicint
QAtomicPointerltTgtisanatomicpointertoT
TherearealsoRAIIclassesforlockmanagementsuchasQMutexLockerQReadLockerandsoon
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
Synchronization
Synchronization p18
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Synchronization p19
Whatisthesingle
mostimportantthingaboutthreads
Synchronization
Synchronization p20
Anyconcurrentaccesstosharedresourcesmustnotresultinadatarace
Twoconditionsforthistohappen1Atleastoneoftheaccessesisawrite2Theaccessesarenotatomicandnoaccesshappensbeforetheother
Synchronization
Synchronization p21
Qthasacompletesetofcross-platformlow-levelAPIsfordealingwithsynchronization
QMutexisamutexclass(recursiveandnon-recursive)
QSemaphoreisasemaphore
QWaitConditionisaconditionvariable
QReadWriteLockisasharedmutex
QAtomicIntisanatomicint
QAtomicPointerltTgtisanatomicpointertoT
TherearealsoRAIIclassesforlockmanagementsuchasQMutexLockerQReadLockerandsoon
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
Synchronization p19
Whatisthesingle
mostimportantthingaboutthreads
Synchronization
Synchronization p20
Anyconcurrentaccesstosharedresourcesmustnotresultinadatarace
Twoconditionsforthistohappen1Atleastoneoftheaccessesisawrite2Theaccessesarenotatomicandnoaccesshappensbeforetheother
Synchronization
Synchronization p21
Qthasacompletesetofcross-platformlow-levelAPIsfordealingwithsynchronization
QMutexisamutexclass(recursiveandnon-recursive)
QSemaphoreisasemaphore
QWaitConditionisaconditionvariable
QReadWriteLockisasharedmutex
QAtomicIntisanatomicint
QAtomicPointerltTgtisanatomicpointertoT
TherearealsoRAIIclassesforlockmanagementsuchasQMutexLockerQReadLockerandsoon
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
Synchronization
Synchronization p20
Anyconcurrentaccesstosharedresourcesmustnotresultinadatarace
Twoconditionsforthistohappen1Atleastoneoftheaccessesisawrite2Theaccessesarenotatomicandnoaccesshappensbeforetheother
Synchronization
Synchronization p21
Qthasacompletesetofcross-platformlow-levelAPIsfordealingwithsynchronization
QMutexisamutexclass(recursiveandnon-recursive)
QSemaphoreisasemaphore
QWaitConditionisaconditionvariable
QReadWriteLockisasharedmutex
QAtomicIntisanatomicint
QAtomicPointerltTgtisanatomicpointertoT
TherearealsoRAIIclassesforlockmanagementsuchasQMutexLockerQReadLockerandsoon
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
Synchronization
Synchronization p21
Qthasacompletesetofcross-platformlow-levelAPIsfordealingwithsynchronization
QMutexisamutexclass(recursiveandnon-recursive)
QSemaphoreisasemaphore
QWaitConditionisaconditionvariable
QReadWriteLockisasharedmutex
QAtomicIntisanatomicint
QAtomicPointerltTgtisanatomicpointertoT
TherearealsoRAIIclassesforlockmanagementsuchasQMutexLockerQReadLockerandsoon
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
MutexExample
Synchronization p22
1 classThreadpublicQThread2 3 boolm_cancel4 public5 explicitThread(QObjectparent=nullptr)6 QThread(parent)m_cancel(false)78 voidcancel()calledbyGUI9 10 m_cancel=true11 1213 private14 boolisCanceled()constcalledbyrun()15 16 returnm_cancel17 1819 voidrun()overridereimplementedfromQThread20 while(isCanceled())21 doSomething()22 23
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
MutexExample(contd)
Synchronization p23
1 classThreadpublicQThread2 3 mutableQMutexm_mutexprotectsm_cancel4 boolm_cancel5 public6 explicitThread(QObjectparent=nullptr)7 QThread(parent)m_cancel(false)89 voidcancel()calledbyGUI10 constQMutexLockerlocker(ampm_mutex)11 m_cancel=true12 1314 private15 boolisCanceled()constcalledbyrun()16 constQMutexLockerlocker(ampm_mutex)17 returnm_cancel18 1920 voidrun()overridereimplementedfromQThread21 while(isCanceled())22 doSomething()23 24
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QThreadsbuilt-incancel
Synchronization p24
QThreadactuallyhasthisalreadybuilt-in
QThreadrequestInterruption()tosettheflag
QThreadisInterruptionRequested()tochecktheflag1 voidrun()overridereimplementedfromQThread2 constintcheckAtNthIteration=1034 intiteration=05 while(true)6 ++iteration7 if(iteration==checkAtNthIteration)8 iteration=09 if(isInterruptionRequested())10 return11 1213 doSomething()14 15
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QuickQuizMutexExample
Synchronization p25
InthiscodeexplicitThread(QObjectparent=nullptr) QThread(parent)m_cancel(false)
dontyouneedtoprotectm_cancel(false)
withm_mutextoolikeincancel()1 voidcancel()calledbyGUI2 constQMutexLockerlocker(ampm_mutex)3 m_cancel=true4
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
ThreadsafetyinQt
ThreadsafetyinQt p26
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
Reentrancydefinitions
ThreadsafetyinQt p27
Afunctionis
Threadsafeifitssafeforittobeinvokedatthesametimefrommultiplethreadsonthesamedatawithoutsynchronization
Reentrantifitssafeforittobeinvokedatthesametimefrommultiplethreadsondifferentdataotherwiseitrequiresexternalsynchronization
Non-reentrant(threadunsafe)ifitcannotbeinvokedfrommorethanonethreadatall
Forclassestheabovedefinitionsapplytonon-staticmemberfunctionswheninvokedonthesameinstance(Inotherwordsconsideringthethispointerasanargument)
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
Examples
ThreadsafetyinQt p28
ThreadsafeQMutexQObjectconnect()QCoreApplicationpostEvent()
ReentrantQStringQVectorQImagevalueclassesingeneral
Non-reentrantQWidget(includingallofitssubclasses)QQuickItemQPixmapingeneralGUIclassesareusableonlyfromthemainthread
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
ThreadsafetyforQtclassesfunctions
ThreadsafetyinQt p29
ThedocumentationofeachclassfunctioninQthasnotesaboutitsthreadsafety
Unlessotherwisespecifiedclassesandfunctionsarenon-reentrant
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectthreadaffinity
ThreadsafetyinQt p30
WhataboutQObject
QObjectitselfisthread-aware
EveryQObjectinstanceholdsareferencetothethreaditwascreatedinto(QObjectthread())Wesaythattheobjectlivesinorhasaffinitywiththatthread
WecanmoveaninstancetoanotherthreadbycallingQObjectmoveToThread(QThread)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectthreadsafety
ThreadsafetyinQt p31
QObjectisreentrantaccordingtothedocumentationhowever
Event-basedclassesarenon-reentrant(timerssockets)
TheeventdispatchingforagivenQObjecthappensinthethreadithasaffinitywith
AlltheQObjectsinthesameparentchildtreemusthavethesamethreadaffinityNotablyyoucantparentQObjectscreatedinathreadtotheQThreadobjectitself
YoumustdeleteallQObjectslivinginacertainQThreadbeforedestroyingtheQThreadinstance
YoucanonlycallmoveToThread()onaQObjectfromthesamethreadtheobjecthasaffinitywith(moveToThread()isnon-reentrant)
InpracticeitseasiertothinkofQObjectasnon-reentrantasitwillmakeyouavoidmanymistakes
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectqueuedconnections
ThreadsafetyinQt p32
IfQObjectisnon-reentranthowcanIcommunicatewithaQObjectlivinginanotherthread
Qthasasolutioncross-threadsignalsandslots
YoucanemitasignalfromonethreadandhavetheslotinvokedbyanotherthreadNotjustanythreadthethreadthereceiverobjectislivingin
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectqueuedconnections
ThreadsafetyinQt p33
Ifthereceiverobjectofaconnectionlivesinadifferentthreadthanthethreadthesignalwasemittedintheslotinvocationwillbequeued
UnderthehoodametacalleventispostedinthereceiversthreadseventqueueTheeventwillthengetdispatchedtotheobjectbytherightthreadHandlingsuchmetacalleventsmeansinvokingtheslot
Thisrequiresthatthereceiverobjectislivinginathreadwitharunningeventloop
AlsoqRegisterMetaType()isrequiredfortheargumenttypespassed
Wecanforceanyconnectiontobequeuedconnect(senderampSendersignalreceiverampReceiverslotQtQueuedConnection)
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectqueuedconnectionsexample
ThreadsafetyinQt p34
1 classMyThreadpublicQThread2 Producerm_producer3 public4 explicitMyThread(ProducerpQObjectparent=nullptr)5 QThread(parent)m_producer(p)67 voidrun()override8 Consumerconsumer9 connect(m_producerampProducerunitProduced10 ampconsumerampConsumerconsume)11 exec()12 13 1415 inmainthread16 autoproducer=newProducer17 autothread=newMyThread(producer)18 thread-gtstart()1920 ProducerunitProducedgetsemittedsometimelaterfromthemainthread21 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectqueuedconnectionsexample(2)
ThreadsafetyinQt p35
1 Sameasbeforebutwithouttherace23 autoproducer=newProducer4 autoconsumer=newConsumer5 autothread=newQThread67 connect(m_producerampProducerunitProduced8 consumerampConsumerconsume)9 connect(threadampQThreadfinished10 consumerampQObjectdeleteLater)1112 consumer-gtmoveToThread(thread)1314 thread-gtstart()1516 ProducerunitProducedgetsemittedsometimelaterfromthemainthread17 Consumerconsumegetsruninthesecondarythread
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectqueuedconnectionsexample(3)
ThreadsafetyinQt p36
1 classMyThreadpublicQThread2 public3 explicitMyThread(QObjectparent=nullptr)4 QThread(parent)56 private7 voidrun()override8 emitmySignal()9 1011 signals12 voidmySignal()13 1415 inmainthread16 autothread=newMyThread17 connect(threadampMyThreadmySignalreceiverampReceiversomeSlot)18 thread-gtstart()
ItisperfectlyOKtoaddsignalstoQThread
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
someSlot()getsinvokedbythemainthreadseventloop
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QObjectqueuedconnectionsexample(4)
ThreadsafetyinQt p37
1 classMyThreadpublicQThread2 Socketm_socket3 public4 explicitMyThread(QObjectparent=nullptr)5 QThread(parent)67 private8 voidrun()override9 m_socket=newSocket10 connect(m_socketampSocketconnectedthisampMyThreadonConnected)11 m_socket-gtconnectToHost()12 exec()13 1415 privateslots16 voidonConnected()qDebug()ltltDatareceivedltltm_socket-gtdata()17
QThreadisaQObjectandassuchhasitsownthreadaffinity(itsthethreadthatcreatedtheMyThreadinstancenotitself)
Theconnectionisqueuedthethreadthatemitsthesignalisnotthethreadthereceiverhasaffinitywith
Thisisnotwhatwewanted
HugerecommendationavoidaddingslotstoQThread
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QtandtheStandardLibrarythreadingfacilities
QtandtheStandardLibrarythreadingfacilities p38
QThread
Synchronization
ThreadsafetyinQt
QtandtheStandardLibrarythreadingfacilities
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
Generalremarks
QtandtheStandardLibrarythreadingfacilities p39
ItisperfectlypossibletomixnmatchQtandstdthreadingclasses
TheStandardLibraryismovingextremelyfastandQtwillnot(andshouldnot)catchupwithallofitsnewdevelopmentsparallelalgorithmscontinuationslatchesbarriersatomicsmartpointersexecutorsconcurrentqueuesdistributedcounterscoroutines
MoreandmoretoolingwillstartcheckingforcorrectusagesofstdAPIsbutnotQtones(unlesstheygetreimplementedontopofthestdones)
QThreadisstillmoreconvenientwhendealingwithQObjectsandeventloops
AcomparisonoftheAPIsisinthenextslides
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QThreadvsstdthread
QtandtheStandardLibrarythreadingfacilities p40
QThread stdthread
Noneedtosubclassitinordertouseit
sup1
Function(jobtask)runner
Detachsupport sup2
Interruptionrequest sup3
sup1onlyifwegoforasignalevent-baseddesignwhichlikelyrequiressubclassingQObject
sup2wecanemulatethatbyconnectingQThreadfinished()toQThreaddeleteLater()
sup3asshownbeforeitstrivialtoemulate
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
QThreadvsstdthread(2)
QtandtheStandardLibrarythreadingfacilities p41
QThread stdthread
Eventloopsupport sup1
QObjectscanbecreatedinto
QObjectscanbemovedto sup2
Signalscanbeemittedfrom
Slotsworkindirectconnections
Slotsworkinqueuedconnections
sup1ButwecanuseQEventLooptorunathread-localeventloop
sup2WecanuseQThreadcurrentThread()togetaQThread(tomoveaQObjecttoetc)
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
Synchronizationprimitives
QtandtheStandardLibrarythreadingfacilities p42
Qt StandardLibrary
QMutex stdmutexstdtimed_mutexstdrecursive_mutexstdrecursive_timed_mutex
QSemaphore
QReadWriteLock stdshared_mutexstdshared_timed_mutex
QWaitCondition stdcondition_variable
stdcall_once
Q_GLOBAL_STATIC
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
Synchronizationprimitivesremarks
QtandtheStandardLibrarythreadingfacilities p43
QMutexandQReadWriteLockarefasterthanthestdequivalents
Anon-recursiveQMutexneverallocatesnorthrowsexceptionsonLinux
QMutexin58modelstheTimedLockableconceptCanbeusedtogetherwithstdlockmanagers
NostdcompatibilityfunctionsinQReadWriteLock(yet)
stdcondition_variable(_any)moregenericconvenientthanQWaitConditionSupportsanyBasicLockablePasspredicatetotestinwait()callinsteadofusingthemandatorywhileloop
Q_GLOBAL_STATICissupersededbyC++11ssemanticsforthread-safefunctionstatics(andorstdcall_once)
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
Lockmanagement
QtandtheStandardLibrarythreadingfacilities p44
Qt StandardLibrary
QMutexLocker stdlock_guard
QReadLocker stdshared_lock
QWriteLocker stdlock_guard
stdunique_lock
stdlock()
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
Lockmanagementremarks
QtandtheStandardLibrarythreadingfacilities p45
StandardLibrarylockmanagementismuchmorepowerfulandflexible
Movablelockguards(stdunique_lock)toreturnamanagedlock
Lockmanagersalsohavetimedtry_lock()s
Tagclassestodecidewhatalockmanagershoulddowiththelock
InC++17stdlock_guardmanagesmultiplelocks(inadeadlock-freefashion)
QOrderedMutexLockerisC++17sstdlock_guardfortwoQMutexesprivateAPI
UnlessyouredealingwithQReadWriteLockpreferthestdalternatives
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
Atomics
QtandtheStandardLibrarythreadingfacilities p46
Qt StandardLibrary
QBasicAtomicIntegerltTgtQAtomicIntegerltTgtQAtomicIntQBasicAtomicPointerltTgtQAtomicPointerltTgt
stdatomicltTgt
stdatomic_operation()
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
Atomicsremarks
QtandtheStandardLibrarythreadingfacilities p47
StartingwithQt57QtatomicsactuallyusesC++11atomicsunderthehoodExceptonMSVCsinceitdoesnt(properly)implementthemyet
Thestdatomicssupportextra(advanced)featurescomparedtotheQtonesConsumeacq+relmemoryorderingDifferentmemoryorderingsavailableforsuccessfailureinread-modify-writeoperations
Thenon-memberatomicoperationsallowforgenericcodeandspecializationsstdatomic_store(stdshared_ptrltTgtpstdshared_ptrltTgtq)
IfyoudouseatomicsstartthinkingtomovetowardstheStandardLibrary
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
Thread-localstorage
QtandtheStandardLibrarythreadingfacilities p48
Qt StandardLibrary
QThreadStorage thread_local
Samefunctionalitydifferentsyntaxes
Bothlazyinitialized
QThreadStorageallowscheckingskippinginitialization
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
p49
Questions
Thankyou
wwwkdabcom
giuseppedangelokdabcom
Thankyou
wwwkdabcom
giuseppedangelokdabcom