2017-01-09 1 views
1

Existe-t-il une méthode pour appeler getline() et, si aucune entrée n'est donnée, ne pas bloquer et attendre?Comment utiliser getline sans blocage pour l'entrée?

J'ai le code suivant:

while(true){ 
    if(recv(sd, tBuffer, sizeof(tBuffer), MSG_PEEK | MSG_DONTWAIT) > 0) break; 
    getline(cin,send); 
} 

Je veux attendre une entrée, mais si je reçois des données à sd socket, je veux arrêter d'attendre les données et quitter le while. Mon code en ce moment, juste coincé sur la première itération au getline(). Je veux évaluer getline(), et si aucune entrée n'est disponible, retournez au if.

Est-ce possible? PS: J'ai essayé avec cin.peek(), mais cela bloque aussi pour l'entrée.

+1

Pour répondre à la question posée: oui, c'est possible. Au moins sur Linux. –

+0

J'utilise Ubuntu .. Comment est-ce possible? Pouvez-vous me donner des liens ou m'expliquer? – Darius

+1

La réponse courte est: 1) Utiliser des E/S de bas niveau, pas 'getline'. 2) Utilisez 'select'. –

Répondre

3

Vous devriez être en mesure de le faire en réglant le mode non-bloquant sur l'entrée standard, descripteur de fichier 0:

int flags = fcntl(0, F_GETFL, 0); 
fcntl(0, F_SETFL, flags | O_NONBLOCK); 

Maintenant, s'il n'y a pas d'entrée disponible, l'appel système read() sous-jacent retourne 0, et std::cin va penser que c'est la fin du fichier, et mettre eof() sur .

Lorsque vous souhaitez relire l'entrée standard, clear() l'état du flux.

Le seul facteur de complication ici est qu'il est difficile de détecter une véritable condition de fin de fichier sur std::cin. Pas beaucoup de problème quand l'entrée standard est un terminal interactif; mais si l'entrée standard peut être un fichier, cela va poser un problème.

Dans ce cas, votre seule option réaliste est de renoncer complètement std::cin, mis en mode non-blocage sur le descripteur de fichier 0, poll() ou select() il, pour déterminer quand il y a quelque chose à lire, puis read() il.

Bien que vous pouvez aussi l'utiliser est poll() ou select() avec std::cin, va se compliquer, parce que vous aurez besoin de vérifier explicitement si parce que cela, de toute évidence, il y a quelque chose déjà en mémoire tampon dans std::cin « s streambuf, préempter toute sorte de poll() ou select() vérification; mais en essayant de lire quelque chose de std::cin, vous courez toujours le risque de lire les données mises en mémoire tampon, puis d'essayer de read() à partir du descripteur de fichier sous-jacent qui est maintenant en mode non-bloquant, ce qui entraîne une fausse condition de fin de fichier. Pour récapituler: vous avez besoin de consacrer du temps supplémentaire à la lecture et à la compréhension du fonctionnement des flux de fichiers et des tampons de flux; et comment fonctionnent les descripteurs de fichiers et comment fonctionne le mode non bloquant; afin de comprendre la logique correcte, vous devrez utiliser.

Oh, et si vous insistez pour y aller la route non bloquante avec std::cin et getline(), vous aurez pas facile de déterminer si la chaîne retournée par getline() se termine parce que getline() lire en fait un retour à la ligne d'entrée standard, ou atteint une fausse fin prématurée de la condition du fichier et pas toute la ligne d'entrée a été réellement lu.Donc, avec le mode non-bloquant, et std::cin, vous serez obligé d'utiliser read(), au lieu de getline().