Разблокировка потока от другого потока - PullRequest
0 голосов
/ 10 марта 2019

Я ищу способ ввода данных в терминал при одновременном получении данных из сети.

Для этого я создал новый поток dataCapture (std::thread)который получит данные, используя std::cin.Основным потоком является получатель.

Программа должна завершиться, когда сеть отправляет строку «конец».

Вот упрощенный код:

void dataCapture()
    while (! quit) {
        std::string data;
        std::cout << "Enter data: ";
        std::cin >> data;
    }
}

bool quit=false;

int main() {
    // socket creation
    // connection to server
    const std::string quit_value = "end";


    std::thread datacapture_T(dataCapture);

    while (! quit) {
        char recep[1024];
        recv(sd, recep, sizeof(recep),0);
        if (recep == quit_value) {
            quit=true;
        }
    }
    datacapture_T.join();
    return 0;
}

Тоне работает, потому что после получения "end", main блоков на datacapture_T.join(), потому что dataCapture заблокирован в вызове std::cin.

Можно ли разблокировать поток dataCapture от основного?

Если нет, то можно ли принудительно убить его?

пс: Я не включил блокировки для упрощения.

Помощь приветствуется!

Ответы [ 2 ]

0 голосов
/ 10 марта 2019

Не существует чистого способа программно уничтожить поток, как в теории, так и на практике.

Стандартный способ разблокировать и закрыть поток программно, который ожидает ввода (любого вида), заключается виспользуйте select() и pipe():

  • Создайте канал ().
  • Создайте набор файловых дескрипторов для select(), который содержит ваш дескриптор входного файла и read() и pipe().
  • Вместо блокирующего чтения на cin, выполните блокирующий вызов select().
  • Если select() говорит вам, что есть что-то дляпрочитайте с pipe(), выйдите из ветки.Вы можете очистить все ресурсы и завершить всю обработку, так как вы обнаруживаете запрос на завершение в потоке.Это ключ.
  • Если select() говорит вам, что есть что-то, что можно прочитать из cin, прочитайте и обработайте это.
  • Из любого другого потока, например, в конце main ():
    • Всякий раз, когда вы хотите завершить поток, запишите один байт (значение не имеет значения) в pipe().
    • join() поток.

Вы думаете, этот метод звучит произвольно и сложно?Это!Тем не менее, это обычная практика, и вы можете положиться на нее, так как она используется многими платформами и программами.

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

Потоки не являются полезным механизмом для достижения параллелизма ввода-вывода.Потоки полезны для создания параллельной обработки ЦП.

0 голосов
/ 10 марта 2019

Вы можете закрыть std::cin с помощью ctrl-z.

Еще один способ исправить это, зайдя в свой dataCapture() и проверив там quit_value, выполнив break.

РЕДАКТИРОВАТЬ: Рассмотрите возможность использования атомарного, а также чтобы чтение / запись в параллельные потоки были как можно более четкими.Не думаю, что это добавляет слишком много сложности

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...