Можно ли установить таймаут для std :: cin? - PullRequest
11 голосов
/ 29 января 2012

Можно ли установить таймаут для std :: cin? Например, std :: cin не получает никаких данных в течение 10 секунд - выдает исключение или возвращает ошибку.

Отредактировано:

А как насчет таймера от Boost library? Насколько я знаю, это портативная библиотека. Можно ли попросить таймер библиотеки Boost генерировать исключения по истечении заданного периода времени? Я думаю, что это может решить эту проблему.

Ответы [ 2 ]

8 голосов
/ 29 января 2012

Невозможно установить время ожидания для std::cin в переносном режиме. Даже если прибегнуть к непереносимым методам, это не совсем тривиально: вам нужно заменить потоковый буфер std::cin.

В системе UNIX я бы заменил потоковый буфер по умолчанию, используемый std::cin, на собственный, который использует файловый дескриптор 0 для чтения ввода. Чтобы фактически прочитать ввод, я бы использовал poll(), чтобы обнаружить присутствие ввода и установить таймаут для этой функции. В зависимости от результата poll() я либо прочитал бы доступный ввод, либо потерпел неудачу. Чтобы, возможно, справиться с набранными символами, которые не пересылаются в файловый дескриптор, все же может быть разумно также отключить буферизацию до ввода новой строки.

При использовании нескольких потоков вы можете создать переносимый буфер потока фильтрации, который будет использовать поток для чтения фактических данных, а другой поток для использования временной переменной условия, ожидающей либо того, что первый поток сообщит о получении данных, либо времени ожидания. истекать. Обратите внимание, что вам нужно защититься от ложных пробуждений, чтобы убедиться, что тайм-аут действительно достигнут, когда нет ввода. Это избавило бы от необходимости возиться с фактическим способом чтения данных из std::cin, хотя он по-прежнему заменяет буфер потока, используемый std::cin, чтобы сделать функциональность доступной через это имя.

2 голосов
/ 25 января 2016

Я только что выяснил, как это сделать, опросив дескриптор файла std :: cin.

Функция poll возвращает 0, если истекло время ожидания и событие не произошло, 1, если что-то произошло, и -1, если произошла ошибка.

#include <iostream>

#include <signal.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>


bool stop = false;

void intHandler(int dummy)
{
    stop = true;
}

std::string readStdIn()
{
    struct pollfd pfd = { STDIN_FILENO, POLLIN, 0 };

    std::string line;
    int ret = 0;
    while(ret == 0)
    {
        ret = poll(&pfd, 1, 1000);  // timeout of 1000ms
        if(ret == 1) // there is something to read
        {
            std::getline(std::cin, line);
        }
        else if(ret == -1)
        {
            std::cout << "Error: " << strerror(errno) << std::endl;
        }
    }
    return line;
}

int main(int argc, char * argv[])
{
    signal(SIGINT, intHandler);
    signal(SIGKILL, intHandler);

    while(!stop)
    {
        std::string line = readStdIn();
        std::cout << "Read: " << line << std::endl;
    }
    std::cout << "gracefully shutdown" << std::endl;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...