Entrada de consola sin locking C ++

Estoy buscando una forma (multiplataforma) de hacer una entrada de consola sin locking para mi progtwig C ++, para que pueda manejar los comandos del usuario mientras el progtwig se ejecuta continuamente. El progtwig también generará información al mismo tiempo.

¿Cuál es la mejor / más fácil manera de hacer esto? No tengo problemas para utilizar bibliotecas externas como boost, siempre que utilicen una licencia permisiva.

    Haría esto creando un hilo separado que llama al locking normal de las funciones IO y pasarle una función de callback a la que llamaría cuando obtuviera la entrada. ¿Estás seguro de que necesitas hacer lo que dijiste que querías hacer?

    En cuanto a la salida de información al mismo tiempo, ¿qué pasaría si el usuario estuviera escribiendo una entrada e imprimiera algo?

    He hecho esto en QNX4.5 que no admite subprocesos o Boost usando select . Básicamente, select STDIN como el descriptor de archivo que se usará y seleccionará cuando ingrese una nueva línea. He agregado un ciclo de ejemplo simplificado a continuación. Es independiente de la plataforma, al menos para sistemas como Unix. Sin embargo, no estoy seguro acerca de Windows.

     while (!g_quit) { //we want to receive data from stdin so add these file //descriptors to the file descriptor set. These also have to be reset //within the loop since select modifies the sets. FD_ZERO(&read_fds); FD_SET(STDIN_FILENO, &read_fds); result = select(sfd + 1, &read_fds, NULL, NULL, NULL); if (result == -1 && errno != EINTR) { cerr < < "Error in select: " << strerror(errno) << "\n"; break; } else if (result == -1 && errno == EINTR) { //we've received and interrupt - handle this .... } else { if (FD_ISSET(STDIN_FILENO, &read_fds)) { process_cmd(sfd); } } } 

    Hay una manera fácil:

     char buffer[512]; int point = 0; ... while (_kbhit()) { char cur = _getch(); if (point > 511) point = 511; std::cout < < cur; if (cur != 13) buffer[point++] = cur; else{ buffer[point] = '\0'; point = 0; //Run(buffer); } } 

    Sin bloque, todo en 1 hilo En cuanto a mí, esto funciona.

    Entrada de consola sin locking C ++?

    Resp .: Consola IO en un hilo de fondo y proporciona un medio de comunicación entre hilos.

    Aquí hay un progtwig de prueba completo (pero simplista) que implementa async io al diferir el io a un hilo de fondo.

    el progtwig esperará a que ingrese cadenas (finalice con nueva línea) en la consola y luego realice una operación de 10 segundos con esa cadena.

    puede ingresar otra cadena mientras la operación está en progreso.

    ingrese ‘salir’ para que el progtwig se detenga en el próximo ciclo.

     #include  #include  #include  #include  #include  #include  #include  #include  int main() { std::mutex m; std::condition_variable cv; std::string new_string; bool error = false; auto io_thread = std::thread([&]{ std::string s; while(!error && std::getline(std::cin, s, '\n')) { auto lock = std::unique_lock(m); new_string = std::move(s); if (new_string == "quit") { error = true; } lock.unlock(); cv.notify_all(); } auto lock = std::unique_lock(m); error = true; lock.unlock(); cv.notify_all(); }); auto current_string = std::string(); for ( ;; ) { auto lock = std::unique_lock(m); cv.wait(lock, [&] { return error || (current_string != new_string); }); if (error) { break; } current_string = new_string; lock.unlock(); // now use the string that arrived from our non-blocking stream std::cout < < "new string: " << current_string; std::cout.flush(); for (int i = 0 ; i < 10 ; ++i) { std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << " " << i; std::cout.flush(); } std::cout << ". done. next?\n"; std::cout.flush(); } io_thread.join(); return 0; } 

    prueba de muestra ejecutada:

     $ ./async.cpp first new string: first 0 1las 2t 3 4 5 6 7 8 9. done. next? new string: last 0 1 2 3 4 5 6 7 8quit 9. done. next? 

    ncurses puede ser un buen candidato.

    Ejemplo usando C ++ 11:

     #include  #include  #include  #include  static std::string getAnswer() { std::string answer; std::cin >> answer; return answer; } int main() { int timeout = 5; std::cout < < "do you even lift?" << std::endl; std::string answer = "maybe"; //default to maybe std::future future = std::async(getAnswer); if (future.wait_for(std::chrono::seconds(timeout)) == std::future_status::ready) answer = future.get(); std::cout < < "the answer was: " << answer << std::endl; exit(0); } 

    comstackdor en línea: http://rextester.com/XGX58614

    La clase StdinDataIO de la biblioteca de red MUSCLE con licencia de BSD admite lecturas sin locking desde stdin en Windows, MacOS / X y Linux / Unix … puede usar eso (o simplemente examinar el código como un ejemplo de cómo puede ser hecho) si quieres.

    Puede usar la biblioteca tinycon para hacer esto. Simplemente genera un objeto tinycon en un nuevo hilo, y ya casi has terminado. Puedes definir el método de disparo para disparar lo que quieras cuando se presiona enter.

    Puede encontrarlo aquí: https://sourceforge.net/projects/tinycon/

    Además, la licencia es BSD, por lo que será la más permisiva para sus necesidades.

    libuv es una biblioteca C multiplataforma para E / S asíncrona. Utiliza un bucle de eventos para hacer cosas como leer desde la entrada estándar sin bloquear el hilo. libuv es lo que alimenta a Node.JS y otros.