70
Multithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB

Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

  • Upload
    others

  • View
    43

  • Download
    6

Embed Size (px)

Citation preview

Page 1: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 2: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 3: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 4: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 5: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 6: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 7: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 8: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 9: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 10: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 11: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 12: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 13: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 14: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 15: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 16: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 17: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 18: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 19: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 20: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 21: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 22: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 23: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 24: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 25: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 26: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 27: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 28: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 29: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 30: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 31: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 32: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 33: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 34: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 35: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 36: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 37: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 38: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 39: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 40: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 41: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 42: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 43: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 44: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 45: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 46: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 47: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 48: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 49: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 50: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 51: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 52: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 53: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 54: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 55: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 56: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 57: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 58: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 59: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 60: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 61: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 62: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 63: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 64: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 65: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 66: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 67: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

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

Page 68: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

Thread-localstorage

QtandtheStandardLibrarythreadingfacilities p48

Qt StandardLibrary

QThreadStorage thread_local

Samefunctionalitydifferentsyntaxes

Bothlazyinitialized

QThreadStorageallowscheckingskippinginitialization

p49

Questions

Thankyou

wwwkdabcom

giuseppedangelokdabcom

Page 69: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

p49

Questions

Thankyou

wwwkdabcom

giuseppedangelokdabcom

Page 70: Multithreading with Qt - KDABMultithreading with Qt Giuseppe D'Angelo, Senior Software Engineer at KDAB. Agenda p.2 QThread (page 4) Synchronization (page 18) ... Qt has a complete

Thankyou

wwwkdabcom

giuseppedangelokdabcom