Frage

Ich schreibe eine Anwendung, die Sie auf eine Eingabe von zwei istreams.

von entweder istream Lesen ist ein synchroner (Blockierung) Anruf, so habe ich zwei Boost::threads zu schaffen beschlossen, das Lesen zu tun.

Entweder eines dieser Fäden zum „Ende“ erhalten kann (bezogen auf einer Eingabe empfangen wird), und wenn „Ende“ erreicht ist, strömt sowohl Eingang mehr erhalten. Leider kann ich nicht wissen, welche so tun wird.

So kann ich nicht auf beiden Fäden join(), weil nur ein Thread (kann nicht vorgegeben werden, welches) tatsächlich return (entblocken).

Ich muss irgendwie die andere Kraft zu verlassen, aber es wird für die Eingabe gesperrt warten, so kann sie selbst es Zeit nicht entscheiden, zurückzukehren (Bedingungsvariablen oder was nicht).

Gibt es einen Weg, um entweder:

  • Senden ein Signal mit einem boost :: Thread oder
  • Zwingen eine istream zu "nicht bestanden" oder
  • Kill a boost :: Thread?

Hinweis:

  • Eine der istreams ist cin
  • Ich versuche, den Prozess neu zu starten, so kann ich die Eingangsströme in einer Art und Weise nicht schließen, die ihnen verbietet Reseting.

Edit:

  • Ich weiß, wenn das „Ende“ erreicht ist, und ich weiß, welcher Thread erfolgreich beendet hat, und die getötet werden muss. Es ist die Tötung ich brauche, um herauszufinden (oder eine andere Strategie für von einem istream lesen).
  • Ich brauche beide Threads zu beenden und die Bereinigung richtig: (

Danke!

War es hilfreich?

Lösung

Ich glaube nicht, gibt es eine Möglichkeit, es Cross-Plattform zu tun, aber pthread_cancel sollte das sein, was Sie suchen. Mit einem Boost-Thread können Sie den native_handle aus einem Thread, und rufen sie pthread_cancel auf sie.

Darüber hinaus ein besserer Weg könnte sein, die Verstärkung zu verwenden Asio Äquivalent eines ausgewählten Anruf auf mehrere Dateien. Auf diese Weise ein Thread wird für die Eingabe wartet blockiert, aber es könnte kommen entweder von Eingangsstrom. Ich weiß nicht, wie einfach es ist, wenn auch mit iostreams, so etwas zu tun.

Andere Tipps

Ja, es ist!

boost::thread::terminate() wird die Arbeit nach Ihren Vorgaben tun.

Es wird den gezielten Thread verursacht eine Ausnahme zu werfen. Unter der Annahme, es ist nicht abgefangene, wird der Stapel richtig entspannt alle Ressourcen zerstört und Thread-Ausführung beendet wird.

Die Kündigung ist nicht sofort. (Der falsche Thread wird in diesem Moment läuft jedenfalls.)

Es geschieht unter vorgegebenen Bedingungen -. Die für Sie am bequemsten wäre wahrscheinlich, wenn boost::this_thread::sleep(); Aufruf, mit dem Sie das Gewinde regelmäßig zu tun haben könnten,

Wenn ein Boost-Thread auf einer I / O-Operation blockiert (z cin>>whatever), boost::thread::terminate() den Faden nicht töten. cin i / o ist kein gültiger Abschlusspunkt. Catch 22.

Nun auf Linux, benutze ich pthread_signal (SIGUSR1), wie es IO-Interrupts blockiert. Es gibt keine solche Aufforderung an Fenstern als entdeckte ich, wenn mein Code zu portieren. Nur ein veralteter einer in Call-Socket-Lesen. In Windows müssen Sie explizit ein Ereignis definieren, die Ihren blockierenden Anruf unterbrechen werden. So gibt es so etwas (AFAIK) als generische Art und Weise zu unterbrechen IO blockiert.

Das Boost.Thread Design handhabt dies gut identifiziert Unterbrechungspunkte zu verwalten. Ich weiß nicht, gut Boost.Asio und es scheint, dass Sie nicht wollen, ohnehin darauf verlassen. Wenn Sie nicht-blockierend Paradigma nicht benutzen Refactoring wollen, Was können Sie tun, ist mit etwas zwischen non-blocking (Polling) und Blockierung IO. Das ist so etwas wie (Pseudo-Code?):

while(!stopped && !interrupted)
{
    io.blockingCall(timeout);
    if(!stopped && !interrupted)
    {
        doSomething();
    }
}

Dann unterbrechen Sie Ihre zwei Threads und sich ihnen anzuschließen ...

Vielleicht ist es einfacher, in Ihrem Fall? Wenn Sie einen Master-Thread, der ein Thread weiß beendet haben Sie nur noch die IO des anderen Thread zu schließen?

Edit: Durch die Art, wie ich bin interessiert an der Endlösung Sie haben ...

Ich hatte ein ähnliches Problem selbst und haben diese Lösung erreicht, die einige andere Leser dieser Frage könnte nützlich finden:

Unter der Annahme, dass Sie mit einem wait () Befehl, um eine Zustandsgröße verwenden, ist es wichtig für Sie, dass in-Boost zu wissen, die wait () Anweisung eine natürliche Unterbrechungsstelle ist. So setzen Sie einfach einen try / catch-Block um den Code mit der wait-Anweisung und lassen Sie die Funktion, die normalerweise in der catch-Block zu beenden.

Wenn man nun annimmt Sie einen Container mit Fädelzeigern haben, iterieren Thread Zeiger und rufen Sie Interrupt () auf jeden Thread, gefolgt von join ().

Nun sind alle Threads wird beendet, anmutig und jede Verstärkung bezogenen Speicherbereinigung sollte sauber arbeiten.

Anstatt zu versuchen, Ihren Thread zu töten, können Sie immer tryjoin den Faden statt, und wenn es scheitert, kommen Sie den anderen statt. (Vorausgesetzt, dass Sie mindestens eine Ihrer beiden Fäden verbinden immer in der Lage sein).

In boost: fädeln Sie suchen die timed_join Funktion.

Wenn Sie auf die richtige Antwort aussehen wollen, aber die nutzen würde nicht blockierenden io mit zeitlich wartet. So dass Sie die Strömungsstruktur der synchronen io, mit dem nicht-blockierend von Asynchrone Kommunikation erhalten.

Sie sprechen Form ein istream über das Lesen, sondern ein istream ist nur eine Schnittstelle. für stdin, können Sie die stdin Dateideskriptors fclose nur die Lese zu unterbrechen. Wie bei den anderen hängt es davon ein, wo Sie ...

gerade lesen

Es scheint, dass Threads nicht helfen Sie tun, was Sie auf einfache Art und Weise wollen. Wenn Boost.Asio nicht nach Ihrem Geschmack ist, betrachtet select() verwenden.

Die Idee ist, zwei Dateideskriptoren zu erhalten und verwenden select(), Ihnen zu sagen, wer von ihnen Eingang zur Verfügung hat. Der Dateideskriptor für cin ist typischerweise STDIN_FILENO; wie der andere zu bekommen auf Ihre Besonderheiten abhängt (wenn es sich um eine Datei ist, open() es nur statt ifstream zu verwenden).

Anruf select() in einer Schleife, um herauszufinden, welcher Eingang zu lesen, und wenn Sie aufhören wollen, bricht nur aus der Schleife.

Unter Windows verwenden QueueUserAPC eine proc in der Warteschlange, die eine Ausnahme auslöst. Dieser Ansatz funktioniert gut für mich.

JEDOCH : Ich habe gerade, dass boost mutexes usw. sind nicht "Warnbare" auf win32, so QueueUserAPC sie nicht unterbrechen kann.

Sehr spät, aber in Windows (und es ist Vorläufer wie VMS oder RSX für diejenigen, die solche Dinge rember) ich so etwas wie ReadFileEx mit einer Abschlussroutine verwenden würde, die, wenn Sie fertig signalisiert, und CancelIO wenn die Lese abgebrochen werden muss früh .

Linux / BSD hat einen ganz anderen zugrunde liegenden API, die nicht so flexibel ist. Mit pthread_kill ein Signal für mich arbeitet zu senden, dass die Lese- / Öffnen-Operation beenden.

Es lohnt sich für jede Plattform unterschiedlichen Code in diesem Bereich Implementierung, IMHO.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top