using fgets as non-blocking function c++

2019-01-28 18:57发布

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?

5条回答
相关推荐>>
2楼-- · 2019-01-28 19:12

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.

查看更多
Rolldiameter
3楼-- · 2019-01-28 19:14

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

查看更多
Bombasti
4楼-- · 2019-01-28 19:25

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.

查看更多
Root(大扎)
5楼-- · 2019-01-28 19:31

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.
查看更多
我只想做你的唯一
6楼-- · 2019-01-28 19:31

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.

查看更多
登录 后发表回答