userinput einlesen mit pthread



  • Hallo!

    Ich arbeite mich gerade in pthreads ein. Ich möchte nun mit einem thread arbeiten, welcher einen input vom user übernimmt und an den main_thread übergibt.

    Dies wäre die input funktion:

    void* input_thread(void* arg) {
    	int ch;
    
    	while((ch = getchar() )) {
    
    		if(ch == 'a')	// left
                    {
    			//user_input = 1;
                           return (void*) 1; // NEU
                    }
    		if(ch == 'd')	// right
                    {
                             //user_input = 2;
    			return (void*) 2; //NEU
                    }
    		if(ch == 'q')	// quit
    			//user_input = 3;
                            return (void*) 3; //NEU
    
    	}
    	return NULL;
    }
    

    hier die main funktion(auszug):

    ....
    pthread_t thread1; 
    pthread_create( &thread1, NULL, input_thread, &user_input  );
    .....
    

    user_input ist eine globale variable. ich brauche sie noch in einer anderen funktion, welche auch in der main funktion aufgerufen wird.

    wie schaffe ich es , das in unser_input "gspeichert" ist, was für eine taste vom user gedrückt wird. (dies muss natürlich laufend geschehen,da das drücken der taste eine richtungsänderung darsellt. ist mein Ansatz da richtig?)

    Danke für eure Unterstützung!

    lg

    Ergänzung:

    pthread_join (p1, (void**)&user_input); s

    so könnte ich ih ja bekommen, allerdings ist der thread dann beendet. er sollte aber weiterlaufen, das der user ja ständig eingaben vornehmen kann...



  • In deinem Fall würde ich eher eine einfache Event-Schleife implementieren, also das normale Abarbeiten von Fenster-Nachrichten, und in den Idle Events (Leerlauf) deine eigentliche Arbeit verrichten. Somit brauchst du keine zusätzlichen Threads.



  • Eine Event-Schleife ist sicher die elegantere Lösung. Aber im Prinzip funktioniert das genau so, wie Du das vorgesehen hast. Wenn user_input eine globale Variable ist, sieht der Main-Thread den Inhalt genau so, wie der Thread ihn rein schreibt. In der Regel sollte man allerdings solche geteilten Variablen mit einem Mutex schützen, was aber bei einem char nicht notwendig ist.



  • tntnet schrieb:

    In der Regel sollte man allerdings solche geteilten Variablen mit einem Mutex schützen, was aber bei einem char nicht notwendig ist.

    Err, was? Wie ist dann garantiert, dass der andere Thread den geänderten Wert jemals zu Gesicht bekommt? Wenn er das in C schreibt, wird ihm doch bereits der Compiler einen Strich durch die Rechnung machen.



  • also ich habs gestern noch selber zusammengebracht und im prinzip so gelöst wie von @tntnet vorgeschlagen. Der eine input_theard schreibt immer in die globale variable den wert rein. ich mach dann noch zusätzlich ein sleep danach und setzte den wert wieder auf 0, damit er nicht dauerhaft in der globalen_variable gespeichert ist. es funktioniert wie gewünscht 🙂

    danke für die Hilfe!



  • bbraun schrieb:

    tntnet schrieb:

    In der Regel sollte man allerdings solche geteilten Variablen mit einem Mutex schützen, was aber bei einem char nicht notwendig ist.

    Err, was? Wie ist dann garantiert, dass der andere Thread den geänderten Wert jemals zu Gesicht bekommt? Wenn er das in C schreibt, wird ihm doch bereits der Compiler einen Strich durch die Rechnung machen.

    Wo ist das Problem? In der globalen Variablen steht immer der Wert der zuletzt gedrückten Taste. Und der Hauptthread kann diesen Wert jederzeit lesen.

    Und was hat das mit dem Compiler zu tun? Wo macht er ihm einen Strick durch die Rechnung?

    nero08 schrieb:

    also ich habs gestern noch selber zusammengebracht und im prinzip so gelöst wie von @tntnet vorgeschlagen. Der eine input_theard schreibt immer in die globale variable den wert rein. ich mach dann noch zusätzlich ein sleep danach und setzte den wert wieder auf 0, damit er nicht dauerhaft in der globalen_variable gespeichert ist. es funktioniert wie gewünscht 🙂

    danke für die Hilfe!

    Sleep ist fast immer die falsche Lösung. Wie auch in diesem Fall. Geht es Dir darum, alle Tastendrücke zu empfangen, dann solltest Du das über eine Warteschlange lösen. Das ist nicht ganz trivial. Eine Warteschlange ist im einfachsten Fall einfach ein Array, welches durch einen Mutex geschützt ist. Eine Condition dient zum wecken des Lesers.

    Wobei es jetzt natürlich darauf ankommt, was der Hauptthread eigentlich macht. Es macht ja keinen Sinn, auf die Condition zu warten. Ansonsten könnte er auch gleich auf einen Tastendruck warten. Irgendwie muss er ja so etwas wie eine Hauptschleife haben. Dort könnte er bei jedem Durchlauf die Warteschlange abfragen.

    Wobei insgesamt sollte das mit dem Thread eher als Übung zu betrachten sein. Für die Tastaturüberwachung braucht man keinen Thread. Das kann man auch mit non-blocking I/O lösen.



  • tntnet schrieb:

    Und was hat das mit dem Compiler zu tun? Wo macht er ihm einen Strick durch die Rechnung?

    Wenn der Compiler nicht sieht, dass der Wert der Variable sich verändern kann, warum sollte er mehr als eine Load-Instruktion emittieren?

    Ein C-Compiler kann folgenden Code:

    while (c == 'a');
    

    durchaus so umordnen:

    if (c == 'a')
            while(1);
    

    Will man das verhindern, sollte man die Atomic-Store/Load-Funktionialität seines Compiler benutzen, die als "Optimization Barrier" wirken. Außerdem sorgt der Compiler damit auch dafür, dass die je nach Architektur und Memory-Model nötigen Memory-Fencing-Befehle ausgegeben werden.

    http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/_005f_005fatomic-Builtins.html
    http://gcc.gnu.org/wiki/Atomic


Anmelden zum Antworten