2015-10-11 1 views
1

Я столкнулся с конкретной проблемой с моей реализацией и могу " t найти решение для него.Неблокирует чтение из std :: cin с помощью std :: this_thread :: sleep_for() или std :: this_thread :: yield() (IPC)

У меня есть приложение из двух частей. Одна часть - графический интерфейс Java swing. Вторая часть - это приложение на C++, которое выполняет всю (расчетную) логику вычислений. Эти два процесса взаимодействуют (в обоих направлениях) с их выходными и входными потоками. Моя проблема заключается в том, что в одной части программы на C++ мне приходится ждать ввода пользователем из программы Java. Однако ожидание, похоже, блокируется.

Что прекрасно работает, когда я звоню программу в оболочке:

std::string inputLine1; 
std::cin >> inputLine1; 

При работе с Java UI, это не работает (естественно), потому что чтение из станд :: КИН блокировки, так когда приложение C++ ожидает ввода, приложение Java ничего не может сделать.

Поэтому я сделал другой способ чтения из std :: cin, который должен (по крайней мере, на мой взгляд) работать, но я не могу заставить его работать. Это:

std::string inputLine1; 
while (true) 
{ 
    int c = std::cin.peek(); 
    if (c != EOF) 
    { 
     std::cin >> inputLine1; 
     break; 
    } 
    std::this_thread::yield(); 
} 

Я также попытался заменить строку с выходом() с

std::this_thread::sleep_for(std::chrono::milliseconds(500)); 

На мой взгляд, этот код должен работать следующим образом: Я выглядывать на станд :: КИН. Если что-то там, я прочитал его от cin. Если ничего нет, я уступаю и повторю попытку позже.

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

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

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

+1

Вы решаете не тот конец этого. Оставьте код C++ блокировать и переместите ввод-вывод в программе Java из цикла событий в отдельный поток. – EJP

+0

Библиотека '' C++ '' iostreams', кажется, не написана * без блокировки *. Я смог получить * неблокирующее * чтение, отделив * ios * от 'stdio', используя' std :: ios :: sync_with_stdio (false); 'и затем проверив ввод с использованием' std :: cin.rdbuf () -> in_avail() 'однако я вполне уверен, что поведение зависит от реализации. – Galik

ответ

0

После длительного использования для реализации неблокирующего ввода из cin я уверен, что невозможно заставить его работать последовательно.

Мое текущее решение заключается в том, чтобы положить блокирующий cin в свою собственную крошечную нить и позволить этому сделать это.

Я упростил свою реализацию немного для этого примера, так как вам нужна потоковая система хранения.

#include <iostream> 
#include <thread> 
#include <mutex> 
#include <queue> 

// Super simple thread safe storage 
std::queue<std::string> Database; 
std::mutex Padlock; 
void PushLine(std::string Line) { 
    std::unique_lock<std::mutex> Lock(Padlock); (void)Lock; 
    Database.push(Line); 
} 
bool IsLineAvailable(void) { 
    std::unique_lock<std::mutex> Lock(Padlock); (void)Lock; 
    return !Database.empty(); 
} 
std::string PopLine(void) { 
    std::unique_lock<std::mutex> Lock(Padlock); (void)Lock; 
    std::string Line(std::move(Database.back())); 
    Database.pop(); 
    return Line; 
} 

// Main function with "non-blocking" input from cin 
int main(int argc, char *argv[]) { 
    (void)argc; 
    (void)argv; 
    std::thread InputThread = std::thread([](){ 
     do { 
      // Ensure the input is as clean as possible 
      if (std::cin.rdbuf()->in_avail()) { 
       std::cin.ignore(std::cin.rdbuf()->in_avail()); 
      } 
      std::cin.clear(); 

      // Get a line, cin will block here. 
      std::string Line; 
      std::getline(std::cin, Line); 

      // If the line is not empty attempt to store it. 
      if (!Line.empty()) { 
       PushLine(Line); 
      } 
     } while (1); 
    }); 

    // Detach from the thread, it will never end. 
    InputThread.detach(); 

    // A job to do. 
    unsigned int Counter = 0; 

    // Run your program. 
    bool Running = true; 
    while(Running) { 
     // Perform a job, in this case counting. 
     Counter++; 

     // Check for available input 
     if (IsLineAvailable()) { 
      // If there is input available, first get it 
      std::string Line = PopLine(); 

      // Echo it to the terminal 
      std::cout << "Command: " << Line << std::endl; 

      // Perform actions based on the command 
      if (Line == "quit") { 
       Running = false; 
      } 
      else if (Line == "count") { 
       std::cout << " Count: " << Counter << std::endl; 
      } 
     } 

     // Sleep for a while 
     std::this_thread::sleep_for(std::chrono::milliseconds(100)); 
    } 

    // Done. 
    return 0; 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^