Tråde i aRts

Det basale

At bruge tråde er ikke muligt på alle platforme. Dette er grunden til at aRts oprindeligt blev skrevet uden at bruge tråde overhovedet. For næsten alle problemer, findes der en løsning uden tråde som gør det samme som hvert løsning med tråde.

For eksempel, i stedet for at placere lyduddata i en separat tråd, og gøre den blokerende, bruger aRts lyduddata som ikke blokerer, og regner ud hvornår næste del af uddata skal skrives med select().

aRts understøtter i det mindste (i de nyeste versioner) støtte for dem som vil implementere deres objekter med tråde. Hvis du for eksempel allerede har kode for en mp3-afspiller, og koden forventer at mp3-afkoderen skal køres i en separat tråd, er det oftest lettest at beholde denne konstruktion.

Implementeringen af aRts/MCOP er opbygget ved at dele tilstanden mellem forskellige objekter på tydelige og mindre tydlige måder. En kort liste af delte tilstande omfatter:

  • Afsenderobjektet som laver MCOP-kommunikation

  • Referenceregningen (Smartwrappers).

  • I/O-håndteringen som håndterer tidsgrænser og fd-tidsmåling.

  • Objekthåndteringen som laver objekter og indlæser plugin dynamisk.

  • Flydesystemet som kalder calculateBlock i passende tilfælde.

Ingen af de ovenstående objekter forventer at blive brugt samtidigt (dvs. at blive kaldt fra forskellige tråde samtidigt). I almindelighed er der to måder at løse dette:

  • Kræv at den som kalder hvilken som helst funktion i objektet skaffer sig en lås inden den bruges.

  • Gør objekterne virkeligt trådsikre og/eller opret instanser af dem for hver tråd.

aRts bruger den første måde. Du behøver en lås hver gang du skal have adgang til et af disse objekter. Den anden måde er sværere at gøre. Et hurtigt fiks som forsøger at opnå dette findes på http://space.twc.de/~stefan/kde/download/arts-mt.tar.gz, men for øjeblikket virker en minimal måde formodentlig bedre, og forårsager mindre problemer med eksisterende programmer.

Hvornår/hvordan skal låsning ske?

Du kan få/slippe låsen med de to funktioner:

Generelt behøver du ikke at skaffe en lås (og du skal ikke forsøge at gøre det), hvis den allerede holdes. En liste over betingelser når dette er tilfældet er:

  • Du tager imod et tilbagekald fra I/O-håndteringen (tidsgrænse eller fd).

  • Du kaldes på grund af nogle MCOP-forespørgsler.

  • Du kaldes fra NotificationManager.

  • Du kaldes fra flydesystemet (calculateBlock)

Der er også nogle undtagelse for funktioner som du kun kan kalde i hovedtråden, og af den grund aldrig behøver et låse for at kalde dem:

  • Opret og fjern afsenderen eller I/O-håndteringen.

  • Dispatcher::run() / IOManager::run()

  • IOManager::processOneEvent()

Men det er alt. For alt andet som på nogen måde hører sammen med aRts, skal du skaffe låsen, og slippe den igen når du er klar. Her er et enkelt eksempel:

class SuspendTimeThread : Arts::Thread {
public:
    void run() {
        /*
         * du behøver denne lås fordi:
         *  - oprettelse af en reference behøver en lås (eftersom global: går til
         *    objekthåndteringen, som derefter kunne have brug for GlobalComm
         *    objektet for at slå hver forbindelse der skal gøres op)
         *  - tildeling af en smartwrapper behøver en lås
         *  - oprettelse af et objekt fra en reference behøver en lås (eftersom
         *    den kan få brug for at forbinde til en server)
         */
        Arts::Dispatcher::lock();
        Arts::SoundServer server = Arts::Reference("global:Arts_SoundServer");
        Arts::Dispatcher::unlock();

        for(;;) {            /*
             * du behøver en lås her, eftersom
             *  - følge en reference for en smartwrapper behøver en lås
             *    (eftersom den kan oprette objektet når den bruges)
             *  - at gøre et MCOP-kald behøver en lås
             */
            Arts::Dispatcher::lock();
            long seconds = server.secondsUntilSuspend();
            Arts::Dispatcher::unlock();

            printf("sekunder til ventetilstand = %d",seconds);
            sleep(1);
        }
    }
}

Trådrelaterede klasser

Følgende trådrelaterede klasser er tilgængelige for øjeblikket:

  • Arts::Thread - som indkapsler en tråd.

  • Arts::Mutex - som indkapsler en mutex.

  • Arts::ThreadCondition - som giver støtte for at vække tråde som venter på at en vis betingelse skal blive sand.

  • Arts::SystemThreads - som indkapsler operativsystemets trådningslager (og giver nogle hjælpefunktioner for anvendelsesprogrammører).

Se linkene for dokumentationen.