2017-02-22 4 views
0

J'ai commencé deux threads, thread t1 attend la saisie via cin. Puis-je mettre quelque chose comme EOF bit à cin de thread t2 pour arrêter cin de lire? J'ai essayé '\n' et ios::eofbit. Les deux ne fonctionnaient pas.Comment arrêter, à partir d'un autre thread, std :: cin de lire plus d'entrée?

#include <thread> 
#include <iostream> 
#include <string> 
#include <condition_variable> 

std::condition_variable cv; 

void Foo() 
{ 
    std::string sFoo; 
    std::cin >> sFoo; 
    // Do stuff with sFoo 
} 

void Bar() 
{ 
    // Do stuff 
    // If a condition is fullfilled I don't need the input in Foo anymore and so I want to cancel cin. 

    std::cin.setstate(std::ios::setstate(std::ios::eofbit); // Does not work 
    std::cin.putback('\n'); // Does not work 

    // maybe something similar like these above 
} 

int main() 
{ 
    std::thread t1(Foo); 
    std::thread t2(Bar); 
} 
+0

@KerrekSB Il n'y a pas de fonction cin.close() ... S'il vous plaît me corriger si je me trompe – Mario

+0

Vous avez raison, cela ne tienne: -S –

+0

@mario 'Essayez :: close (STDIN_FILENO) ; 'ou' :: fclose (stdin); 'ou même' :: close (0); '. Voir http://stackoverflow.com/questions/288062/is-close-fclose-on-stdin-guaranteed-to-be-correct C'est un peu drastique ... –

Répondre

0

Je ne pense pas qu'il y ait une lecture non bloquante standard d'istream ou un moyen d'interrompre un thread en attente d'entrée. Vous pouvez essayer de regarder asio boost ou booster iostreams - peut-être qu'ils ont cette fonctionnalité.

Vous pouvez utiliser select/poll sur les systèmes POSIX ou leurs équivalents sur d'autres systèmes pour vérifier si des données sont disponibles ou utiliser une forme de lecture interruptive - l'API dépend également du système. Ci-dessous une solution sale qui fonctionne - vous vous retrouvez avec un thread qui fuit qui attendra toujours sur stdin, mais il fait ce que vous voulez.

#include <thread> 
#include <iostream> 
#include <string> 
#include <condition_variable> 
#include <chrono> 
#include <mutex> 
#include <queue> 

std::mutex m; 
bool dataEnd = false; 
std::queue<std::string> data; 
std::condition_variable sAvail; 

void Reader() { 
    while (std::cin) { 
     auto s = std::string(); 
     std::cin >> s; 

     auto lock = std::unique_lock<std::mutex>(m); 
     data.push(std::move(s)); 
     sAvail.notify_all(); 
    } 
} 

void Foo() { 
    for (;;) { 
     auto lock = std::unique_lock<std::mutex>(m); 
     if (data.empty()) { 
      sAvail.wait(lock); 
      if (dataEnd) { 
       std::cerr << "No more data!\n"; 
       break; 
      } 
     } 

     if (!data.empty()) { 
      auto s = std::move(data.front()); 
      data.pop(); 
      std::cerr << "Got " << s << '\n'; 
     } 
    } 
} 

void Bar(std::thread& reader) { 
    // Do stuff 
    // If a condition is fullfilled I don't need the input in Foo anymore and so I want to cancel cin. 

    { 
     auto lock = std::unique_lock<std::mutex>(m); 
     dataEnd = true; 
     sAvail.notify_all(); 
     reader.detach(); 
    } 

    // maybe something similar like these above 
} 

int main() { 
    std::thread r(Reader); 
    std::thread t1(Foo); 
    std::this_thread::sleep_for(std::chrono::milliseconds(5000)); 
    std::thread t2(Bar, std::ref(r)); 

    t1.join(); 
    t2.join(); 
}