Asynchronous console input

Started by
15 comments, last by loufoque 14 years, 10 months ago
I am trying to find a way to perform asynchronous input on the command line, as for a chat client (which may receive messages whilst awaiting user input). This is for C++ (though a Python method wouldn't hurt), and the solution needs to be cross-platform. Since I don't know of any way to make std::cin non-blocking, the obvious method seemed to spawn another thread, which reads a line from std::cin in a loop, and communicates it to the server thread over a loackless-queue. This works pretty well, except when it comes to exiting the program - my threading library (boost::thread) provides no way to forcibly kill another thread, and the input thread is blocked on std::cin, so can't receive a message to quit. A call to exit(0) solves this, but it doesn't seem to be the cleanest of solutions. So, my question to you: is there anyway to make std::cin non-blocking, or to test for available data before calling std::getline()?

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Advertisement
Did you try checking std::cin.rdbuf()->in_avail() ?
Quote:Original post by SiCrane
Did you try checking std::cin.rdbuf()->in_avail() ?
As I understand it, streambuf.in_avail() only returns the number of characters remaining after a read operation underflows - and the only way to generate an underflow is a blocking read call.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

If the streambuf input buffer is empty, in_avail() calls showmanyc(), which is used to check if a subsequent call to underflow() will succeed or not.
Quote:Original post by SiCrane
If the streambuf input buffer is empty, in_avail() calls showmanyc(), which is used to check if a subsequent call to underflow() will succeed or not.
Nevertheless, it doesn't work - calling in_avail() in a loop always returns 0, no matter how many characters and lines I type at the command prompt. Perhaps the buffering is interfering?

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

No, it's probably because your standard library implementation just doesn't probe stream for input when showmanyc() is called. A lot of the C++ standard is more suggestive than proscriptive.
Quote:Original post by SiCrane
No, it's probably because your standard library implementation just doesn't probe stream for input when showmanyc() is called. A lot of the C++ standard is more suggestive than proscriptive.
Right, makes sense. Is multi-threading the only other solution? I mean, multi-threading works, but it seems a little bit like overkill.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

AFAIK in_avail() and showmanyc() are the only ways to check for input status without a blocking call in standard C++. However, there are other portable alternatives. For example, a curses library like pdcurses can be used to detect if there's keyboard input, though it may not play happily with any buffering done by std::cin.
I am sure there are cross platform libraries that can do this. I haven't used it, but something like curses probably has this functionality without worrying about threading. There might be smaller libraries that let you do the same thing too.
Quote:Original post by SiCrane
However, there are other portable alternatives. For example, a curses library like pdcurses can be used to detect if there's keyboard input, though it may not play happily with any buffering done by std::cin.
Quote:Original post by rip-off
I am sure there are cross platform libraries that can do this. I haven't used it, but something like curses probably has this functionality without worrying about threading. There might be smaller libraries that let you do the same thing too.
Ja, curses and friends do expose this functionality. They appear to do this in a fairly naive way, by completely disable buffering for stdin, and emulating line-buffering.

I am not entirely happy with that approach, as curses is a fairly heavy (and unfortunately antiquated) dependency. All of the newer (and lighter) curses replacements seem to depend on curses for this functionality.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

This topic is closed to new replies.

Advertisement