Kernelcoder’s Blog.

Bare et annet WordPress.com-nettsted.

Merket med Qt.

Qt’s Synkroniserings Primitives.

Nar du ringer las () pa en trad, blokkeres andre anrop for a lase () fra andre trad til traden som eier lasene, lases opp (). Denne metoden blokkerer mate a eie en las pa. Den ikke-blokkerende maten er a ringe tryLock (), som returnerer sant hvis en las eier, falsk pa annen mate. La oss se na hvordan du bruker QMutex-klassen. Vurder folgende kode & # 8230;

Hvis ovennevnte metode blir kalt to ganger suksessivt i en enkelt trad, er verdien av dataene 8.

Hvis den ovennevnte metoden blir kalt samtidig fra to trad, kan folgende hende: & # 8230;

Na, hvis vi bruker en mutex, kan vi lose det som folger & # 8230;

Sa, vi fikk at QMutex-klassen gir tilgangsserialisering mellom trader.

Bruke QWaitCondition med QMutex.

Du vet, det er noen situasjon som oppstar nar en trad ma vente a fortsette for at noen forhold skal motes. Tenk en ventetilstand som det alltid signaliserer at tilstanden er sant til et anrop for a vente () mens det signaliserer at tilstanden er feil. Igjen nar en samtale til wakeOne () eller wakeAll () er laget, signaliserer den at tilstanden er sann. For a angi situasjonen kan vi vurdere et problemomrade, produsent & # 8211; Forbrukerproblem.

Produsenten skriver data til bufferen til den nar slutten av bufferen, hvorpa den starter pa nytt fra begynnelsen, overskriver eksisterende data. Forbrukerens trad leser dataene som den er produsert og skriver den til standardfeil.

Ventevilkar gjor det mulig a ha hoyere grad av samtidighet enn det som er mulig med mutexes alene. Hvis tilgang til bufferen bare var bevoktet av en QMutex, kunne forbruker-traden ikke fa tilgang til bufferen samtidig som produsentens trad. Likevel er det ingen skade i a ha begge tradene som arbeider pa forskjellige deler av bufferen samtidig.

La oss begynne med a gjennomga den sirkul re bufferen og tilhorende synkroniseringsverktoy:

DataSize er mengden data som produsenten vil generere. For a holde eksemplet sa enkelt som mulig, gjor vi det til en konstant. BufferSize er storrelsen pa den sirkul re bufferen. Det er mindre enn DataSize, noe som betyr at produsenten til en viss tid vil na slutten pa bufferen og starte pa nytt fra begynnelsen.

For a synkronisere produsenten og forbrukeren trenger vi to ventetilstander og en mutex. Bufferen er ikke til stede nar produsenten har generert noen data, og forteller forbrukeren at den kan begynne a lese den. BufferenNotFull-tilstanden signaliseres nar forbrukeren har lest noen data, og forteller produsenten at den kan generere mer. NumUsedBytes er antall byte i bufferen som inneholder data.

Sammen venter ventetilstandene, mutexen og NumUsedBytes-telleren at produsenten aldri er mer enn BufferSize bytes foran forbrukeren, og at forbrukeren aldri leser data som forbrukeren ikke har generert enna.

Produsentklasse: La oss se koden for produsentklassen & # 8230;

Produsenten genererer DataSize bytes data. For den skriver en byte til den sirkul re bufferen, ma den forst sjekke om bufferen er full (dvs. numUsedBytes er lik BufferSize). Hvis bufferen er full, venter traden pa bufferNotFull-tilstanden.

Pa slutten, produsentene oker numUsedBytes og signaliserer at tilstanden bufferNotEmpty er sant, siden numUsedBytes er nodvendigvis storre enn 0.

Vi beskytter alle tilgangene til NumUsedBytes-variabelen med en mutex. I tillegg aksepterer QWaitCondition :: wait () -funksjonen en mutex som argument. Denne mutexen er last opp for traden blir satt og last nar traden blir vaken. Videre er overgangen fra last tilstand til ventetilstand atomisk for a forhindre at raseforhold oppstar.

Forbrukerklasse: La & # 8217; s vende seg til forbrukerklassen & # 8230;

Koden er veldig lik produsenten. For vi leser byten, kontrollerer vi om bufferen er tom (numUsedBytes er 0) i stedet for om den er full og vent pa bufferNotEmpty-tilstanden hvis den er tom. Etter at vi har lest byten, senker vi numUsedBytes (i stedet for a oke det), og vi signaliserer bufferNotFull-tilstanden (i stedet for bufferNotEmpty-tilstanden).

Bruke klassene: I hoved () lager vi de to trader og ringer QThread :: wait () for a sikre at begge trader far tid til slutt for vi avslutter:

Sa hva skjer nar vi kjorer programmet? I utgangspunktet er produsentens trad den eneste som kan gjore noe; forbrukeren er blokkert og venter pa at bufferNotEmpty-tilstanden skal signaleres (numUsedBytes er 0). Nar produsenten har satt en byte i bufferen, er numUsedBytes BufferSize & # 8211; 1 og bufferNotEmpty-tilstanden er signalert. Pa det tidspunktet kan to ting skje: Enten forbrukertraden tar over og leser den byte, eller forbrukeren far til a produsere en andre byte.

En semafor er en generalisering av en mutex. Mens en mutex kun kan lases en gang, er det mulig a anskaffe en semafor flere ganger. Semaforer brukes vanligvis til a beskytte et visst antall like ressurser.

Semaforer stotter to grunnleggende operasjoner, erverver () og frigjor ():

anskaffe (n) prover a skaffe n ressurser. Hvis det ikke er mange tilgjengelige ressurser, vil samtalen blokkeres til dette er tilfelle. slipp (n) utgivelser n ressurser.

Lose Produsent-Forbrukerproblem med QSemaphore & # 8230;

Qt Threading System.

Bare arve QThread klasse og overstyr kjore metode. Na mens du ringer startsporet gjennom en forekomst av den arvelige klassen, sa mens din overstyrte lop blir utfort, begynner en annen trad av kontroll med utgangspunktet som lopemetode. Det vil si, kjor metodeutforelse livssyklus (omfang) kjore pa en annen trad.

Hvis du vil kjore en hendelseslokke pa en trad, ring exec-metoden i lopemetoden som folger.

Objektomfanget i gjenget system.

Qt’s forventning er at et objekt som er opprettet i en trad, ogsa slettes fra den traden. Alle objektene pa objektstakken (barn-forelder-treet) av et objekt vil ogsa v re pa den aktuelle traden. Du ma slette alle objekter i en objektbunke pa egen trad (du kan fa en trad som en gjenstand bor etter tradmetode og du kan endre en gjenstands trad med moveToThread-metoden) eller ring deleteLater metode for utsatt sletting fra en annen trad.

Du ma ikke bruke tradobjektet selv som foreldre for objektene som skal opprettes i kjoremetode, fordi tradobjektet selv er opprettet pa en annen trad. Faktisk ma du folge kodingsformatet som du bruker i hovedmetoden (Hovedvinduet er konstruert pa stakken uten at noen forelder og hovedvindu er den overste mesteparten av alle objekter i hovedtraden).

Nar du jobber med samme data fra flere trader, bruker du synkroniseringsteknikker (mutex, semafor etc) for a gi synkronisering mellom trader.

Signaler og spor over tradene.

Qt stotter disse signal-sluttforbindelsestyper:

Auto-tilkobling (standard): Oppforelsen er den samme som direkte tilkobling, hvis sender og mottaker er i samme trad. Oppforselen er den samme som den kjopte tilkoblingen, hvis sender og mottaker er i forskjellige trader. Direkte tilkobling: Sporet er pakalt umiddelbart nar signalet sendes ut. Sporet blir utfort i emitterens trad, som ikke nodvendigvis er mottakers trad. Koble tilkobling: Sporet er pakalt nar kontrollen returnerer til hendelseslokken til mottakerens trad. Sporet blir utfort i mottakerens trad. Blokkering i ko-tilkobling: Sporet er pakalt som for den kjopte tilkoblingen, unntatt de gjeldende tradblokkene til sporet returnerer. Merk: Ved a bruke denne typen for a koble til objekter i samme trad, vil det fore til dodlas. Unik tilkobling: Oppforselen er den samme som den automatiske tilkoblingen, men forbindelsen er bare laget hvis den ikke dupliserer en eksisterende tilkobling. d.v.s. hvis det samme signalet allerede er koblet til samme spor for det samme par objekter, blir forbindelsen ikke laget og forbindelsen () returnerer false.

Tilkoblingstypen kan spesifiseres ved a sende et ekstra argument til a koble til (). V r oppmerksom pa at bruk av direkte tilkoblinger nar avsender og mottaker bor i forskjellige trader, er usikkert hvis en hendelseslokke kjorer i mottakerens trad, av samme grunn som at en hvilken som helst funksjon pa et objekt som lever i en annen trad, er usikkert.

Bruke Qt ‘s Timer.

QTimer arver QObject. QTimer-klassen gir et programmeringsgrensesnitt pa hoyt niva for timere. Det gir gjentagende & amp; single-shot timer.

For single-shot timer bruk singleShot statisk metode for QTimer klasse.

For a bruke repeterende timer, opprett et objekt for QTimer, koble timeout-signalet og amp; klassestartsmetode for det.

Som et spesielt tilfelle vil en QTimer med en timeout pa 0 utelukkes sa snart alle hendelsene i vinduets systemko har blitt behandlet. Dette kan brukes til a gjore tungt arbeid mens du gir et snill brukergrensesnitt:

processOneThing () vil fra da av bli kalt gjentatte ganger. Den skal skrives pa en slik mate at den alltid kommer raskt tilbake (vanligvis etter a ha behandlet en datapost) slik at Qt kan levere hendelser til widgets og stoppe timeren sa snart den har gjort alt sitt arbeid. Dette er den tradisjonelle maten a gjennomfore tungt arbeid i GUI-applikasjoner; multithreading blir na tilgjengelig pa flere og flere plattformer, og Qt forventer at QTimers pa null millisekund gradvis vil bli erstattet av QThreads.

Dette er en rask, lett og lav klasse som brukes av Qt internt. Qt anbefaler a bruke QTimer-klassen pa hoyere niva enn denne klassen hvis du vil bruke timere i programmene dine.

QBasicTimer-klassen gir tidsbegivenheter for QObject arvede klasser. Det vil si, det kaller timerEvent-metode for QObject arvede klasser.

Bruk timer-ID fra pEvent-objektet for a avgjore hvilken tidtaker som postet denne hendelsen, og arbeid deretter.

Qt’s Property System.

Qt gir et sv rt sofistikert eiendomssystem som leveres av kompilatorselger (ved hjelp av sokeord __property eller [property]). Men det avhenger av den kompilatoren. Men Qt gir lignende system med kompilator uavhengig og plattform uavhengig.

Hvordan erkl re en eiendom?

type: er datatypen som denne egenskapen vil angi & amp; fa navn: er eiendommens navn getFunction, setFunction & amp; resetFunction: er setet & amp; Tilbakestill funksjonen til denne egenskapen henholdsvis. notifySignal:

vil bli sendt mens eiendomsverdien endres.

DESIGNABLE true / false (standard true): angir om denne egenskapen kan brukes pa eiendomsarket pa Qt Designer. SCRIPTABLE true / false (standard sant): Angir om denne egenskapen skal v re tilgjengelig med en skriptmotor (standard sant). I stedet for sann eller falsk, kan du angi en boolean medlemsfunksjon STORED true / false (standard true): angir om denne egenskapen skal brukes til et fast datafelt eller vil bruke et felles datafelt. USER true / false (standard false): Angir om denne egenskapen vil bli endret direkte av bruker fra Gui pa kjoretid. Tilstedev relsen av CONSTANT-attibutt indikerer at eiendomsverdien er konstant. Sa settFunksjon & amp; resetFunction vil ikke eksistere.

FINAL attributt indikerer at ingen arvet klasse vil overstyre denne egenskapen.

Q_PROPERTY (QCursor markor READ markor WRITE setCursor RESET unsetCursor)

Og klassestrukturen er & # 8230;

Lese og skrive egenskaper med Meta-Object System.

Vi vil bruke setProperty & amp; Eiendomsmetoder for QObject for innstilling & amp; fa en eiendomsverdi gjennom QObject-pekeren i en klasse. Merk at denne maten er tregere enn a bruke direkte setFunction & amp; getFunction.

Hvis typen vi bruker for en eiendom er en enum type, registrer den til meta-object-system ved hjelp av Q_ENUM makro. Hvis det er en ORed eller ANDed verdi av enum type bruk Q_FLAGS makro. Hvis det er en cumtom-klasse, registrer du det med Q_DECLARE_METATYPE.

QObject :: setProperty () kan ogsa brukes til a legge til nye egenskaper i en forekomst av en klasse ved kjoretid. Nar det kalles med et navn og en verdi, hvis en eiendom med det oppgitte navnet eksisterer i QObject, og hvis den oppgitte verdien er kompatibel med egenskapens type, lagres verdien i egenskapen, og sann er returnert. Hvis verdien ikke er kompatibel med egenskapen til eiendommen, blir eiendommen ikke endret, og falsk returneres. Men hvis eiendommen med det oppgitte navnet ikke eksisterer i QObject (dvs. hvis det ikke ble oppgitt med Q_PROPERTY (), blir en ny eiendom med det oppgitte navnet og verdien automatisk lagt til QObject, men falsk er fortsatt returnert. Dette betyr at en retur av falsk kan ikke brukes til a avgjore om en bestemt eiendom faktisk ble satt, med mindre du vet pa forhand at eiendommen allerede eksisterer i QObject.

Legg merke til at dynamiske egenskaper legges til per forekomst, dvs. de legges til QObject, ikke QMetaObject. En egenskap kan fjernes fra en forekomst ved a sende eiendomsnavnet og en ugyldig QVariant-verdi til QObject :: setProperty (). Standardkonstruktoren for QVariant konstruerer en ugyldig QVariant.

Dynamiske egenskaper kan foresporres med QObject :: property (), akkurat som egenskaper som er oppgitt pa kompileringstid med Q_PROPERTY ().

Denne egenskapsmekanismen brukes med eiendomsanimasjon, state-machine rammeverk.

Qt-preferanseinnstillinger Grunnleggende.

Det er veldig enkelt a arbeide med preferanseinnstillinger i Qt.

Anta at du foretrekker a holde hovedvinduets storrelse og posisjon synkronisert med den siste gangen du lukket hovedvinduet.

Du trenger bare a konstruere et objekt av typen QSetting og bruke det verdsettelsesmetode for a oppna lagringsverdien. Den forste parameteren er et unikt navn. Det er bedre a folge en protokoll nar du navngir denne unike parameteren (jeg brukte Property / Object-protokollen). Den andre parameteren er standardverdien. Denne ma brukes kun for forste gang soknaden din kjorer.

Anta at du foretrekker a holde hovedvinduets storrelse og posisjon lagret slik at du kan synkronisere nar neste gang du vil se hovedvinduet.

Det er bedre a angi programnavn og organisasjonsnavn mens du konstruerer QApplication-objekt ved setApplicationName og setOrganizationName. Denne informasjonen blir brukt av QSettings-objektet for a opprette innstillingsfilen din.

Event Qt gir noen praktiske metoder som gjor arbeidet ditt enkelt. Som eksempel QMainWindow gir saveGeometry og saveState metoder for a lagre hovedvinduet geometri og tilstander av verktoylinjer & amp; dock-widgets.