2016-06-03 2 views
2

der Code:Boost.Asio bestehend Betrieb laufen in Strang

In Gewinde 1:

boost::async_read(socket, buffer, strand.wrap(read_handler)); 

In Gewinde 2:

strand.post([](){socket.async_write_some(buffer, strand.wrap(write_handler))}); 

Es ist klar, dass read_handler, async_write_some, write_handler geschützt durch Strang, werden sie nicht concu rrent. Allerdings async_read ist eine zusammengesetzte Operation, wird es null oder mehr Male rufen async_read_some, jene async_read_some auch für Strähne schützen müssen oder sonst könnten sie mit async_write_some in Gewinde 2.

Aber aus dem Code Concurrent, Strang nur wickeln read_handler, wie asio macht alle Zwischenoperationen (async_read_some) auch vom Strang umwickelt?

Antwort

2

Kurz gesagt, asio_handler_invoke ermöglicht es, den Aufruf von Handlern im Kontext eines anderen Handlers anzupassen. In diesem Fall verfügt das Objekt, das von strand.wrap() zurückgegeben wird, über eine benutzerdefinierte asio_handler_invoke-Strategie, die Handler in den Strang sendet, der den ursprünglichen Handler eingewickelt hat. Konzeptionell ist wie folgt:

template <typename Handler> 
struct strand_handler 
{ 
    void operator()(); 
    Handler handler_; 
    boost::asio::strand dispatcher_; 
}; 

// Customize invocation of Function within context of custom_handler. 
template <typename Function> 
void asio_handler_invoke(Function function, strand_handler* context) 
{ 
    context->dispatcher_.dispatch(function); 
} 

strand_handler wrapped_completion_handler = strand.wrap(completion_handler); 
using boost::asio::asio_handler_invoke; 
asio_handler_invoke(intermediate_handler, &wrapped_completion_handler); 

Die benutzerdefinierte asio_handler_invoke Haken über argument-dependent lookup befindet. Dieses Detail ist in den Handler requirement dokumentiert:

Verursacht die Funktion Objekt f wie von f() Aufruf ausgeführt werden.

Die asio_handler_invoke()-Funktion wird mithilfe der argumentabhängigen Suche gefunden. Die Funktion boost::asio::asio_handler_invoke() dient als Standard, wenn keine vom Benutzer bereitgestellte Funktion verfügbar ist.

Für weitere Informationen über asio_handler_invoke, lesen Sie this Antwort.


Seien Sie sich bewusst, dass ein Betrieb innerhalb der initiierenden Funktion versucht werden. Die Dokumentation ist spezifisch, dass die Intermediate Handler im selben Kontext aufgerufen werden wie der Final Completion-Handler. Daher gegeben:

assert(strand.running_in_this_thread()); 
boost::async_read(socket, buffer, strand.wrap(read_handler)); 

die boost::async_read selbst muss im Rahmen der strand aufgerufen werden Thread-sicher zu sein. Siehe this Antwort für weitere Details zu Fadensicherheit und Strängen.