boost::asio Problem
-
Dravere schrieb:
Stefan schrieb:
io_service::run() ist ja angeblich von mehreren Threads aufrufbar.
Wie kommst du auf diese Idee? Das wäre mir ganz neu.
Grüssli
Aus der Doku:
Multiple threads may call io_service::run() to set up a pool of threads from which completion handlers may be invoked. This approach may also be used with io_service::post() to use a means to perform any computational tasks across a thread pool.
http://www.boost.org/doc/libs/1_42_0/doc/html/boost_asio/overview/core/threads.html
-
Was ich letztendlich erreichen will ist simultanes schreiben und lesen auf einem Socket, ohne dass das eine das andere blockiert. Also, ein Thread sendet Daten, der andere empfängt. Falls jemand weiss wie man das mit boost::asio realisieren kann, wäre ich dankbar für einen Tipp.
-
Dravere schrieb:
Stefan schrieb:
io_service::run() ist ja angeblich von mehreren Threads aufrufbar.
Wie kommst du auf diese Idee? Das wäre mir ganz neu.
Grüssli
Das ist sogar die Idee... der Fall, dass run(..) nur von einem Thread aus aufgerufen wird ist eher ein spezial Fall.
Die Idee ist, dass alle Threads, die run(..) aufrufen zum Thread Pool gehören (implizit). Handler werden dann auf einem dieser Threads aufgerufen.
Mit io_service::strand können die Handler aufrufe serialisiert werden.
Simon
-
Stefan schrieb:
Was ich letztendlich erreichen will ist simultanes schreiben und lesen auf einem Socket, ohne dass das eine das andere blockiert. Also, ein Thread sendet Daten, der andere empfängt. Falls jemand weiss wie man das mit boost::asio realisieren kann, wäre ich dankbar für einen Tipp.
Du benutzt einfach async_write(..) und async_read(..) und fertig.
-
Man lernt immer wieder was neues. Aber eine geile Sache! Ich glaube sogar, dass ich das in einem konkreten zukünftigen Projekt gebrauchen könnte *Notiz macht*

Und wo liegt hier jetzt das Problem oder ist das nun beseitigt? Die Problembeschreibung ist ja nicht wirklich berauschend

Grüssli
-
@Dravere: Kompiliere dir doch den Code oben
Dann sag mir was die Fehlermeldungen verursacht.Ich wollte eben zuerst paralleles Warten ausprobieren (anstatt lesen und Schreiben), weil mir das Protokoll noch fehlt.
-
Stefan schrieb:
Dann sag mir was die Fehlermeldungen verursacht.
Welche Fehlermeldung?
-
Also erstmal:
Wieso einstrand-Objekt und ein Mutex? Dasstrand-Objekt soll ja gerade explizites Verriegeln überflüssig machen. Du brauchst also nicht noch zusätzlich einen Mutex.Zweitens:
Stefan schrieb:
Aber offenbar gibts hier ein Problem dass jeder Thread run() nur einmal ausführen kann.
Da ist auch so. Jeder Thread in dem
io_service::runausgeführt wird stellt eine eigenständige Queue zur asynchronen Verarbeitung dar. Damit ist der Thread dann vollzeitbeschäftigt.Dein Handler kann allerdings durch den Stand (und den Mutex) nur jeweils in einem Thread gleichzeitig ausgeführt werden.
PS: Dein
deadline_timerlebt nicht lange genug:void operator ()() { //hier legst Du ihn als auto-Variable an. boost::asio::deadline_timer t(*m_io); for(int i = 0; i < m_n; ++i) { t.expires_from_now(boost::posix_time::milliseconds(m_t)); t.async_wait(m_strand.wrap(boost::bind(&Thread::Handler, this, _1))); m_io->run(); } //hier, also beim Verlassen der Funktion stirbt Dein Timer //(während er auf den Timeout wartet) //der Handler wird dadurch abgeschossen, //so als wenn man cancel() aufruft. Daher die "Fehlermeldung". }
-
@Tachyon:
Der mutex ist nur für std::cout, das von verschiedenen Threads benutzt wird. Ansonsten müsste ich wohl für alle Handler die std::cout benutzen den gleichen strand nehemen. Es ist doch so dass alle Handler, die in den gleichen Strand gewrapt wurden, in dem Thread ausgeführt werden, in dem das Strand-Objekt erzeugt wurde. Oder habe ich das falsch verstanden?
-
Stefan schrieb:
[...]Es ist doch so dass alle Handler, die in den gleichen Strand gewrapt wurden, in dem Thread ausgeführt werden, in dem das Strand-Objekt erzeugt wurde. Oder habe ich das falsch verstanden?
Das
strand-Objekt wurde ja nicht in einem Thread erzeugt, sondern er benutzt einio_service-Objekt. Wenn dierun-Methode desio_service-Objektes in mehreren Threads ausgeführt wird, dann können Handler, die in demio_servicehängen normalerweise parallel ausgeführt werden. Von allen Handlern, die in einen strand gepackt werden, kann jeweils nur noch einer zur Zeit aktiv sein. Alle anderen müssen warten, bis der gerade aktive Handler fertig ist.Beispiel:
Du hast einen TCP-Server, der asynchron Verbindungen annehmen kann (async_accept). Jede erfolgreich angenommene Verbindung soll zur weiteren Verarbeitung in einen Container gelegt werden. Damit Dein Server besser skaliert, hast Du nun dierun-Methode desio_service-Objektes auf demasync_acceptarbeitet in mehreren Threads gestartet. Dadurch können nun mehrereconnect-Anfragen zur gleichen Zeit behandelt werden. Das heisst dann auch, dass mehrereaccept-Handler versuchen können, die Verbindungen in den Container einzutragen. Wenn der nicht threadsafe ist, dann knallt es. Wenn Du denaccept-Handler nun in einenstrandwickelst, wird kann nur jeweils ein Handler zur Zeit ausgeführt werden. Es geht bei einemstrandalso darum, dass von verschiedenen Threads, welche in den durch denstrandgeschützten Bereich eintreten wollen nur jeweils einer aktiv sein darf.
-
Ok, das ist nachvollziehbar. Danke!