#c #io #stdin
#c #io #стандартный интерфейс
Вопрос:
В программе, которую я пишу, у меня есть основной поток, который содержит цикл для приема ввода с консоли. Однако в какой-то момент создается новый поток, который также пытается читать из stdin. Существует переменная, которая указывает, что этот другой поток запущен, но fgets все еще ожидает ввода в основном потоке, поэтому первый консольный ввод, введенный после запуска нового потока, ошибочно считывается основным потоком вместо нового потока.
Есть ли какой-то способ решить эту проблему?
Одна вещь, которую я пробовал, это (в основном потоке):
while(foo) {
if(busy) continue;
fgets(input,200,stdin);
if(busy) {
fputs(input,stdin);
} else {
// do whatever was supposed to be done with input intended for main thread
}
}
Но, похоже, я неправильно понимаю, как работают потоки, потому что другой вызов fgets не считывает данные, записанные через fputs.
Комментарии:
1. Почему вы пытаетесь это сделать? Вы уверены, что нет лучшего дизайна, который сохраняет все операции ввода-вывода в одном потоке?
2. Это было бы идеально. Наверное, у меня возникли проблемы с видением леса за деревьями. Я попробую это.
Ответ №1:
Создайте логическую переменную, защищенную соответствующим примитивом синхронизации. Инициализируйте его значением false. Когда потоку нужно задать пользователю вопрос и получить ответ, дождитесь, пока переменная станет «ложной» (в соответствии с выбранным вами примитивом синхронизации), а затем установите для нее значение true. Выполните все выходные данные и получите все необходимые входные данные. Затем установите для переменной значение ‘false’ и разблокируйте все ожидающие потоки (в зависимости от выбранного вами примитива синхронизации).
Для pthreads, вероятно, лучше всего использовать переменную mutex и condition. Для Windows, вероятно, лучше всего использовать критический раздел и событие автоматического сброса.
В вашем вопросе не хватает некоторых деталей, которые могут предложить другой ответ. Как пользователь должен взаимодействовать с программой, когда он не может быть уверен, какой из двух отдельных путей кода получит ввод, который он вводит? Если он что-то вводит, а затем нажимает «enter», какой путь кода он переходит, по-видимому, зависит от того, нажмет ли он «enter» до того, как другой поток будет готов или нет, что, по-видимому, делает программу непригодной для использования. Почти в каждом реалистичном случае вам нужно будет запросить пользователя, а затем дождаться ответа, а затем отпустить ввод и вывод вместе.
Комментарии:
1. Спасибо за информацию! Это определенно будет полезно в какой-то момент, но для этой программы я переработал, чтобы только один поток имел дело с stdin.
Ответ №2:
Для потомков, вот как я решил это.
Вместо того, чтобы оба потока ожидали ввода с консоли, теперь только один поток ожидает ввода и делегирует обработку этого ввода функциям, специфичным для состояния программы.
Приведенный выше фрагмент становится:
while(foo) {
fgets(input,200,stdin);
if(busy) {
busyStuff(input);
} else {
nonBusyStuff(input);
}
}
и никакой другой pthread, у которого есть вызов fgets, никогда не создается.