[anfänger] frage zu threads



  • hallo,

    folgendes problem: ich muss daten von unterschiedlichen quellen in meinem programm pollen, einmal von nem tcp/ip-socket und einmal von ner seriellen schnittstelle, ohne das sich die beiden loops in die quere kommen und gegenseitig blockieren. zum schluss bin ich auf die idee gekommen das ganze mit threads zu programmieren.

    was ist nun besser, erst alles initialisieren, dann die loops(threads) starten und bei ende alles deinitialisieren. oder kann ich die init, polling, deinit geschichte auch direkt im thread machen? ich meine, wenn ein thread abbricht aus irgendeinem grund wird dann der zweite thread ordentlich beendet oder steigt der auch sofort aus?

    beispiel 1:

    int terminate = 0;
    
    void thread_1(void)
    {
        init_socket();
    
        do {
            if(!socket_poll()) {
                break;
            }
        } while(!terminate);
    
        deinit_socket();
    
        pthread_exit((void *) 0);
    }
    
    void thread_2(void)
    {
        init_tty();
    
        do {
            if(!tty_poll()) {
                break;
            }
        } while(!terminate);
    
        deinit_tty();
    
        pthread_exit((void *) 0);
    }
    
    int main(int argc, char *argv[])
    {
        pthread_t t1, t2;
    
        pthread_create(&t1, NULL, (void *)&thread_1, NULL);
        pthread_create(&t1, NULL, (void *)&thread_2, NULL);
    
        pthread_join(t1, NULL);
        pthread_join(t2, NULL);
    
        // signal-handler um terminate auf 1 zu setzen
        .
        .
        .
    }
    

    beispiel 2:

    int terminate = 0;
    
    void thread_1(void)
    {
        do {
            if(!socket_poll()) {
                break;
            }
        } while(!terminate);
    
        pthread_exit((void *) 0);
    }
    
    void thread_2(void)
    {
        do {
            if(!tty_poll()) {
                break;
            }
        } while(!terminate);
    
        pthread_exit((void *) 0);
    }
    
    int main(int argc, char *argv[])
    {
        pthread_t t1, t2;
    
        init_socket();
        init_tty();
    
        pthread_create(&t1, NULL, (void *)&thread_1, NULL);
        pthread_create(&t1, NULL, (void *)&thread_2, NULL);
    
        pthread_join(t1, NULL);
        pthread_join(t2, NULL);
    
        // signal-handler um terminate auf 1 zu setzen
        .
        .
        .
    
        deinit_tty();
        deinit_socket();
    }
    

    fragen:

    beispiel1: wenn eine der init-funktionen fehlschlägt, kann ich vorzeitig mit return aussteigen aus der funktion oder muss explizit immer pthread_exit() aufgerufen werden?

    oder wie gestalte ich am besten das abfangen von fehlern? müssen in solchen fällen immer die pthread_exit() funktionen aufgerufen werden?

    ich hab mich auch schon bei amazon.de umgeguckt, aber bücher auf deutsch zu diesem thema habe ich keine gefunden.

    fragen über fragen, hoffe mir kann einer weiterhelfen 😉

    gruss, marco



  • ich wuerde im socket die initalisierung/deinitalisierung durchfuehren, weil das bei einem SMP System (oder auch nur bei Hyperthreading) schneller sein sollte.

    du kannst Threads auch durch return verlassen AFAIK. Wenn ein Thread normal beendet wird, arbeitet der andere noch bis zum Ende weiter.

    http://www-106.ibm.com/developerworks/linux/library/l-posix1.html
    http://www.humanfactor.com/pthreads/



  • Ich würde schon aus Gründen der Übersichtlichkeit die Deinitialisierung in derselben logischen Einheit wie die Initialisierung machen. Allerdings stellt sich für mich eher die Frage, ob du die Initialisierung in die Threads packen solltest. Auf den ersten Blick erscheint mir das hier am sinnvollsten:

    int terminate = 0; 
    
    void thread_1(void) 
    { 
        do { 
            if(!socket_poll()) { 
                break; 
            } 
        } while(!terminate); 
    
        pthread_exit((void *) 0); 
    } 
    
    void thread_2(void) 
    { 
        do { 
            if(!tty_poll()) { 
                break; 
            } 
        } while(!terminate); 
    
        pthread_exit((void *) 0); 
    } 
    
    int main(int argc, char *argv[]) 
    { 
        pthread_t t1, t2; 
    
        init_tty(); 
        init_socket(); 
    
        pthread_create(&t1, NULL, (void *)&thread_1, NULL); 
        pthread_create(&t1, NULL, (void *)&thread_2, NULL); 
    
        pthread_join(t1, NULL); 
        pthread_join(t2, NULL); 
    
        deinit_tty(); 
        deinit_socket(); 
    
        // signal-handler um terminate auf 1 zu setzen 
        . 
        . 
        . 
    }
    

    Jedenfalls, wenn ich recht in der Annahme gehe, dass init_tty und init_socket nur einmal pro Programmaufruf ausgeführt weeden sollen, aber sonst hättest du wohl kaum gefragt, ob du die deinitialisierung ins Hauptprogramm packen solltest.



  • ja, die init-funktionen werden nur einmal aufgerufen. was ich an der geschichte am kniffligsten fand war eben die fehlerbehandlung, falls der daemon mit dem ich über tcp/ip kommuniziere bzw. das device am tty nicht initialisiert werden kann bzw. falls während dem polling der daten die verbindung abreisst.

    hab gestern nacht allerdings noch eine interessante seite gefunden auf der beschrieben wird wie ich auf signale reagiere und wie ich cancel und cleanup-handler einrichten kann. denke von daher kann ich auch die init/denit geschichte direkt in den thread packen, allein wegen der übersichtlichkeit.


Anmelden zum Antworten