Zach
Zach

Reputation: 537

using fgets as non-blocking function c++

I'm writing a program that reads in a loop from the stdin, using the function fgets, as follows:

while(fgets(buffer2, BUFFERSIZE , stdin) != NULL){
  //Some code  
}

I want my code to be non-blocking, that is: I don't want the program to hold on the 'fgets' line when there's no input at the moment from the user.
How can i do it?

Upvotes: 2

Views: 18036

Answers (5)

Alok Save
Alok Save

Reputation: 206596

fgets() is a blocking function, it is meant to wait until data is available.

If you want to perform asynchronous I/O, you can use select(), poll(), or epoll(). And then perform a read from the file descriptor when there is data available.

These functions use the file descriptor of the FILE* handle, retrieved by:

int fd = fileno(f);

If you are using Unix or Linux, then one solution can be to mark the file descriptor used by the file to be non-blocking. Example:

#include <fcntl.h>  
FILE *handle = popen("tail -f /als/als_test.txt", "r"); 
int fd = fileno(handle);  
flags = fcntl(fd, F_GETFL, 0); 
flags |= O_NONBLOCK; 
fcntl(fd, F_SETFL, flags); 

fgets should be non-blockng now and will return a null and set an error code for you.

Upvotes: 6

Tony Delroy
Tony Delroy

Reputation: 106226

If you have a proper POSIX environment, you can use select() or poll() to check for input on stdin's descriptor before calling fgets()... read().

Jan's comment below (thanks!) explains why you can't use fgets() with this approach... summarily, there's an extra layer of buffering in the FILE object, and data can already be waiting in though the select() finds nothing more on the file descriptor... preventing your program from responding in a timely way, and potentially hanging if some other system is waiting for a response to already sent data before sending more on stdin.

Upvotes: 2

user760613
user760613

Reputation:

On Linux, you can specify the end of input by pressing ctrl-d, and of-course you can do this using separate thread.

Upvotes: -1

Kiril Kirov
Kiril Kirov

Reputation: 38173

This would sound a little like overkill, but this is the one, that comes to my mind.

Use 2 different threads - one using this loop and waiting blocking ( I don't think that this could be done non-blocking). And when something is read, push it into a pipe.

Meanwhile, the other thread will do whatever it needs to do and check for data in the pipe from time to time ( apparently, you want this to be asynchronous, or at least I get it this way. If so, this means different threads )

But then, you'll need to synchronize the two threads very well. You should check your OS about multithreading and IO operations.

Upvotes: 0

Bj&#246;rn Pollex
Bj&#246;rn Pollex

Reputation: 76856

You basically have two options:

  1. Run that loop in a separate thread.
  2. Check if your OS supports some API for non-blocking IO.

Upvotes: 1

Related Questions