Как освободить через istream заблокированную тему - PullRequest
1 голос
/ 22 октября 2010

я создал два класса. Один для чтения входных данных (через объект istream) и синтаксического анализа, а другой для обработки выходных данных синтаксического анализатора.
Существует один экземпляр каждого из них.
У меня есть анализатор, работающий в цикле, вызывающий istream :: get () и затем создающий команды для второго объекта на основе ввода. Затем эти команды помещаются в очередь, которую второй объект обрабатывает в отдельном потоке.
Теперь совершенно очевидно, что мне в конечном итоге нужно будет отправить команду «Выйти». Здесь возникает проблема: команда «Quit» также должна завершить цикл синтаксического анализа, но я не могу найти способ сообщить парсеру, что он должен выйти, потому что он перехватывается в istream :: get ().
Мне нужен способ, чтобы разбудить его из этого метода, но я не могу найти какой-либо ...
Я думал написать некую «последовательность завершения» для объекта istream (в данном случае это cin), создав объект ostream из istream :: rdbuf (). Но это не работает - битбит устанавливается после попытки записи в буфер.
В другом вопросе в StackOverflow я увидел упомянутый класс asio библиотеки Boost, но я бы предпочел не зависеть от сторонних библиотек.
Есть ли способ вывести поток из istream :: get () - т.е. есть ли способ записи в буфер istream (возможно, предполагая, что это на самом деле cin) изнутри программы?
Другим подходом было бы уничтожение потока, который я мог бы счесть приемлемым, так как в этом конкретном месте очистки не требуется. Но как это можно сделать? (Я полагаюсь на реализацию потока POSIX)

Ответы [ 2 ]

1 голос
/ 22 октября 2010

Вам придется зависеть от чего-то другого, кроме стандартных классов iostream, потому что они не обеспечивают select() стиль поведения.

Кроме того, уничтожение потока невозможно с помощью POSIX (и полностью нарушено в Windows). Вы можете отправить запрос на отмену через pthread_cancel(), но в вашем случае он может застрять в не отменяемом системном вызове. Особый интерес для вас read() может быть отменен или не отменен, в зависимости от среды. По крайней мере, одна среда говорит, что точка отмены может встречаться в read(), хотя по общему признанию это слой Windows POSIX. Кроме того, в Mac OS X, только в Leopard 10.5.1 , была нарушена реализация read() в отношении отменяемости.

Пройдя через это препятствие, вы также должны учитывать непростую связь между деструкторами C ++ и pthread_cancel. Не все среды гарантируют, что деструкторы будут вызываться, поэтому вы должны быть крайне осторожны при использовании pthread_cancel в коде C ++.

Короче говоря, для прерывистых входов / выходов используйте низкоуровневые входы / выходы и select(): один fd для ввода / вывода, второй fd (созданный pipe()) для сигнализации. Или, если вы смелы, используйте AIO , но вам, вероятно, лучше использовать высокоуровневый интерфейс, такой как Boost.Asio .

1 голос
/ 22 октября 2010

Есть ли шанс, что это реализовано в .NET? - если это так, взгляните на Reactive Framework . Он обеспечивает очень элегантный способ обработки потоков и особенно отмены их на лету. - Помимо этого, вы получаете очень расширяемую библиотеку расширения Linq для всех видов вещей, таких как буферизация, мемоизация, Zip и т. Д.

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

Джефф из команды Reative имеет несколько хороших блогов о Потоковое и Reative здесь :

...