Add a Timeout for getchar()

10,167

Solution 1

This is usually achieved by using select() on stdin. Another solution would be using alarm() and a dummy SIGALRM handler to interrupt the getchar() call (only working on POSIX systems though).

Solution 2

How to add a timeout when reading from `stdin` I found this question is helpful.

Another method is using multithreading.

If you are using c++11, you can make use of condition_variable::wait_for() as a timer thread. And the original getchar() is blocking on another thread.

Here is an example:

#include <termios.h>
#include <unistd.h>
#include <thread>
#include <chrono>
#include <iostream>

std::mutex mtx;
std::condition_variable cv;

int ch;
bool INPUT_SIGNAL = false;

void getch ( void ) {
  struct termios oldt, newt;

  tcgetattr ( STDIN_FILENO, &oldt );
  newt = oldt;
  newt.c_lflag &= ~( ICANON | ECHO );

  tcsetattr ( STDIN_FILENO, TCSANOW, &newt );
  ch = getchar();
  tcsetattr ( STDIN_FILENO, TCSANOW, &oldt );

  INPUT_SIGNAL = true;  

  cv.notify_one();
}

void timer ( int period ) {
    for(;;) {
        std::unique_lock<std::mutex> lck(mtx);

        cv.wait_for(lck, std::chrono::seconds(period), []{return INPUT_SIGNAL;});   

        if(INPUT_SIGNAL) {
            INPUT_SIGNAL = false;
            std::cout << ch << "\n";
        } else {
            std::cout << 0 << "\n";
        }
    }
}

int main() {
    std::thread worker(timer, 1);
    for(;;) {
        getch();
    }
    worker.join();
    return 0;
}

When there is a keystroke, main thread will notify the worker thread.

Share:
10,167
brain56
Author by

brain56

Whatcha doin' here?

Updated on June 11, 2022

Comments

  • brain56
    brain56 almost 2 years

    I need to add a timeout function for getchar() in my program.

    What do I do so that when my program reaches the instruction getchar(), it will only wait for a certain amount of time for the user to make a keystroke and if the user does not make a keystroke within the given time limit, the program will "skip" the getchar()?

    The operating system does not support the conio.h library so kbhit is not an option.

  • brain56
    brain56 about 13 years
    I think alarm() should do the trick. The problem is...I don't know how to use alarm()! Could you post some kind of example of using alarm() with getchar()? I can't get anything out of Google.
  • ThiefMaster
    ThiefMaster about 13 years
    You simply call alarm(duration); before your getchar() call. Also, install a dummy sighandler using signal(SIGALRM, your_handler_func); so the alarm signal doesn't kill your program.