Nicht blockierendes cin?



  • Ich bin dabei, ein kleines Konsolen-Userinterface für meine Anwendung zu schreiben. Die Anwendungslogik läuft dabei in einem eigenen Thread und kommuniziert über Message-queues mit dem Userinterface. Die Konsolen-UI soll
    a) Ggf. nötige Azeigen ausgeben
    b) quasi jederzeit Nutzereingaben entgegennehmen können
    c) Eine Abschiedsmeldung ausgeben und Nutzereingaben ncihtmehr entgegennehmen nachdem eine entsprechende Message von der Anwendungslogik gekommen ist.

    Mein Problem dabei ist, dass Eingaben bei cin blockieren (z.B. getline), ich könnte also wenn ich auf eine Eingabe warte, nicht gleichzeitig was ausgeben. Ich kann aber afaik das Warten auf Eingaben auch nicht abbrechen. Ich habe die Ausgabe in einen anderen Thread verlegt, so dass ich was ausgeben kann während ich auf Eingaben warte. Das ist zwar unschön weil theoretisch während der Ausgabe der Nutzer was tippen kann aber darauf kommts nicht an.
    Schwieriger ist Punkt c), da weiß ich grade nicht weiter. Ich kann dem Input-Thread zwar auf verschiedene Weise sagen dass nichts mehr eingegeben werden soll, aber das zieht alles erst, wenn getline() oder cin << xy zurückgekehrt ist, so dass dann doch noch auf die nächste Eingabe gewartet wird, obwohl sie nicht mehr verarbeitet wird. Kenn jemand ne Lösung, das zu unterbrechen?

    Damit könnte dann auch die gleichzeitige Ausgabe und Eingabe verhindert werden - Eingabe unterbrechen, Ausgabe, Eingabe wieder "freischalten".



  • Meines wissens nach kannst du das nicht lösen ohne auf OS spezifische Ein-/Ausgabe APIs zurückzugreifen.

    Es gibt dafür natürlich auch libraries die das für diverse OS abstrahieren. Z.B. ncurses könnte dafür etwas haben.



  • Falls dein Compiler die <conio.h> bereitstellt, dann kannst du auch z.B. kbhit() verwenden, s.a. http://www.c-plusplus.net/forum/viewtopic-var-t-is-39320.html



  • Th69 schrieb:

    Falls dein Compiler die <conio.h> bereitstellt, dann kannst du auch z.B. kbhit() verwenden, s.a. http://www.c-plusplus.net/forum/viewtopic-var-t-is-39320.html

    Welches OS abhängig ist da dieser header Windows Only ist.



  • Ich habs befürchtet dass das nicht mit standard- oder boost-Mitteln geht. Hab schon überlegt, den input-Thread einfach per interrupt wegzuschießen, aber dann gelesen dass das erst bei bestimmten interrupt-Punkten greift - getline() ist nicht einer davon 😞



  • pumuckl schrieb:

    Ich habs befürchtet dass das nicht mit standard- oder boost-Mitteln geht. Hab schon überlegt, den input-Thread einfach per interrupt wegzuschießen, aber dann gelesen dass das erst bei bestimmten interrupt-Punkten greift - getline() ist nicht einer davon 😞

    Naja mit boost könntest du bestimmt was mit hilfe von ASIO machen.
    Dafür müsstest du halt etwas extra arbeit leisten aber es wäre möglich. Da die standard ein-/ausgabe meistens auch nur auf handle basiert. Unter Unix und Windows sind das File handle.



  • Nach nem ersten Überfliegen schauts aus als obs in Linux mit POSIX-Handles in ASIO möglich wäre, in Windows gibts zwar auch was zu den Handles mit asio, aber da sind standard-I/O und unnamed pipes ausgeschlossen.

    Aber das ist alles vieeel zu kompliziert für "mal eben". Bevor ich mir jetzt n Zacken aus der Krone breche um ein Konsolen-Provisorium hinzuschustern, setz ich mich mit irgendeinem entsprechenden Framework auseinander und löte mir einen Prototypen für die GUI...



  • pumuckl schrieb:

    Nach nem ersten Überfliegen schauts aus als obs in Linux mit POSIX-Handles in ASIO möglich wäre, in Windows gibts zwar auch was zu den Handles mit asio, aber da sind standard-I/O und unnamed pipes ausgeschlossen.

    Aber das ist alles vieeel zu kompliziert für "mal eben". Bevor ich mir jetzt n Zacken aus der Krone breche um ein Konsolen-Provisorium hinzuschustern, setz ich mich mit irgendeinem entsprechenden Framework auseinander und löte mir einen Prototypen für die GUI...

    Ach crap 😞 Wäre ja zu schön gewesen



  • evilissimo schrieb:

    Ach crap 😞 Wäre ja zu schön gewesen

    Ja... Wäre allerdings auch zu schön gewesen wenn ich die ganze Anwendungslogik per Template-Metaprogrammierung zur Compilezeit hätte zusammenschmieden können. Ging leider auch nicht, und diesmal lags nicht an der Template-Rekursionstiefe 😉 😃



  • pumuckl schrieb:

    evilissimo schrieb:

    Ach crap 😞 Wäre ja zu schön gewesen

    Ja... Wäre allerdings auch zu schön gewesen wenn ich die ganze Anwendungslogik per Template-Metaprogrammierung zur Compilezeit hätte zusammenschmieden können. Ging leider auch nicht, und diesmal lags nicht an der Template-Rekursionstiefe 😉 😃

    Haha hatte ich schon ganz vergessen das du auch ein Fan von TMP bist 😃



  • pumuckl, was machst du jetzt? Weisst du das schon? 🙂

    Für plattformunabhängige Texteingaben/Events gäbe es noch SFML, aber da kannst du wahrscheinlich gerade so gut ein GUI-Framework nehmen... Beschränkst du dich momentan auf StdLib und Boost?

    P.S. Wenn du so Freude an der Template-Metaprogrammierung (+ein wenig Zeit) hast, könntest du vielleicht mal eine funktionale Programmiersprache anschauen, das geht in eine ähnliche Richtung, nur eben gesamthaft. Mir gefällt z.B. Haskell... 😉



  • Nexus schrieb:

    pumuckl, was machst du jetzt? Weisst du das schon? 🙂

    Ne Noob-GUI mit SDL oder was ähnlichem, wenn nicht jemand mit ner super-einfachen Lösung ankommt 🙂

    Für plattformunabhängige Texteingaben/Events gäbe es noch SFML, aber da kannst du wahrscheinlich gerade so gut ein GUI-Framework nehmen... Beschränkst du dich momentan auf StdLib und Boost?

    Bisher ja.

    P.S. Wenn du so Freude an der Template-Metaprogrammierung (+ein wenig Zeit) hast, könntest du vielleicht mal eine funktionale Programmiersprache anschauen, das geht in eine ähnliche Richtung, nur eben gesamthaft. Mir gefällt z.B. Haskell... 😉

    Ich hab ein wenig durchs EOPL Buch gestöbert, dort nehmen sie Scheme für alles, inklusiver der Aufgaben (die ich brav bearbeitet hab). Ich bleib bei C++ 😉 Funktionale Konzepte sind mir durchaus bekannt - dank Concepts, Techniques, and Models of Computer Programming | ISBN: 0262220695



  • könntest du nicht stdin auf O_NOBLOCK stellen?

    int flags = fcntl(0, F_GETFL);
    fcntl(0, F_SETFL, flags | O_NONBLOCK);
    

    😕



  • aus der coder hölle schrieb:

    könntest du nicht stdin auf O_NOBLOCK stellen?

    int flags = fcntl(0, F_GETFL);
    fcntl(0, F_SETFL, flags | O_NONBLOCK);
    

    😕

    Das wäre aber nicht portabel 😉



  • pumuckl schrieb:

    Ne Noob-GUI mit SDL oder was ähnlichem, wenn nicht jemand mit ner super-einfachen Lösung ankommt 🙂

    Wenn du eh auf ein Grafikframework zurückgreifst, würde ich wenn schon SFML nehmen. Damit könntest du was Kleines mit relativ wenig Code hinkriegen:

    sf::RenderWindow window(sf::VideoMode(300, 200), "Konsole");
    window.SetFramerateLimit(30); // damit musst du dich nicht um die Zeit kümmern
    std::string inputString; // vom User eingegebener Text
    
    sf::Text inputText; // grafischer Text
    // Grafikprimitive (Rechteck) mit angegebenen Massen, schwarzer Füll- und blauer Rahmenfarbe erstellen
    sf::Shape frame = sf::Shape::Rectangle(0, 0, 50, 20, sf::Color::Black, 1.f, sf::Color::Blue);
    
    for (;;) // Hauptschleife
    {
    	// Events abfragen
    	sf::Event event;
    	while (window.GetEvent(event))
    	{
    		switch (event.Type)
    		{
    			case sf::Event::TextEntered: // Texteingabe
    				inputString.push_back(event.Text.Unicode);
    				inputText.SetString(inputString);
    				break;
    			case sf::Event::Closed: // Klick auf [X]
    				return 0;
    		}
    	}
    
    	// Hintergrund leeren, Elemente zeichnen und anzeigen
    	window.Clear();
    	window.Draw(inputText);
    	window.Draw(frame);
    	window.Display();
    }
    


  • Nexus schrieb:

    Wenn du eh auf ein Grafikframework zurückgreifst, würde ich wenn schon SFML nehmen. Damit könntest du was Kleines mit relativ wenig Code hinkriegen

    Ich werds mir mal anschauen. Wird eh auch im Endstadium nichts besonders aufwändiges (Kartenspiel).


Anmelden zum Antworten