использование fgets в качестве неблокирующей функции c ++ - PullRequest
2 голосов
/ 19 мая 2011

Я пишу программу, которая читает цикл из stdin, используя функцию fgets, следующим образом:

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

Я хочу, чтобы мой код был неблокирующим, то естьне хочу, чтобы программа удерживала строку 'fgets', когда в данный момент нет ввода от пользователя.
Как я могу это сделать?

Ответы [ 5 ]

3 голосов
/ 19 мая 2011

fgets() является функцией блокировки, она предназначена для ожидания получения данных.

Если вы хотите выполнить асинхронный ввод-вывод, вы можете использовать select(), poll() или epoll().А затем выполните чтение из дескриптора файла, когда есть доступные данные.

В этих функциях используется дескриптор файла дескриптора FILE *, полученный с помощью:

int fd = fileno(f);

Если вы используете Unixили Linux, то одним из решений может быть пометка дескриптора файла, используемого файлом как неблокирующего.Пример:

#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 теперь должен быть неблокирующим, возвращать нулевое значение и устанавливать для вас код ошибки.

2 голосов
/ 19 мая 2011

Если у вас подходящая среда POSIX, вы можете использовать select() или poll() для проверки ввода в дескрипторе stdin перед вызовом fgets() ... read().

Комментарий Яна ниже (спасибо!) Объясняет, почему вы не можете использовать fgets() с таким подходом ... кратко, в объекте FILE есть дополнительный уровень буферизации, и данные уже могут ожидать, хотя select() больше ничего не находит в файловом дескрипторе ... препятствует своевременной реакции вашей программы и, возможно, зависает, если какая-либо другая система ожидает ответа на уже отправленные данные, прежде чем отправлять больше на stdin.

1 голос
/ 19 мая 2011

У вас есть два варианта:

  1. Запустить этот цикл в отдельном потоке.
  2. Проверить, поддерживает ли ваша ОС какой-либо API для неблокирующего ввода-вывода.
0 голосов
/ 19 мая 2011

В Linux вы можете указать конец ввода, нажав ctrl-d , и, конечно, вы можете сделать это, используя отдельный поток.

0 голосов
/ 19 мая 2011

Это звучало бы немного как излишнее, но это то, что приходит мне в голову.

Используйте 2 разных потока - один, использующий этот цикл и ожидающий блокировку (я не думаю, что это можетбыть сделано неблокирующим).И когда что-то читается, вставьте это в трубу.

Тем временем другой поток будет делать все, что ему нужно, и время от времени проверять данные в канале (очевидно, вы хотите, чтобы это было асинхронно, или, по крайней мере, я получаю это так.это означает, что разные потоки)

Но тогда вам нужно будет очень хорошо синхронизировать два потока.Вам следует проверить свою ОС на предмет многопоточности и операций ввода-вывода.

...