Dienstag, 9. September 2014

nonblocking input - kbhit() example

This is a useful utility, when being in an endless loop and waiting for some user input without blocking the loop.

int kbhit()
{
    struct timeval tv;
    fd_set fds;
    tv.tv_sec = 0;
    tv.tv_usec = 0;
    FD_ZERO(&fds);
    FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0
    select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
    return FD_ISSET(STDIN_FILENO, &fds);

}

This function performs a non-blocking check on the standard input (stdin) without timeout 0, tv.tv_sec and tv.tv_usec are both set to zero. "select" is usually used in the case where multiple I/O's need to process, or performing a check at the same time. But in this case, I'm only interested in standard input, therefore only one FD_SET(STDIN_FILENO, &fds) is the trigger. For details of the select parameters, please check out the manual. As we are only interested in input, we place out fd set at second parameter of select(), the 3rd is for output and 4th is for the exception.

Important part, after select if user input is trigger, FD_ISSET will return non zero value, else return 0. So, we now can use it like this:

while(!kbhit())
{
      //do certain operation..
}
//user hits enter.

(c) by Neil Matthew und Richard Stones in their book "Beginning Linux Programming (Programmer to Programmer)", Wiley, 3rd edition (30.12.2003), ISBN-10: 0764544977