Wenn der Aufrufer immer innerhalb des Strangs läuft, kann der Handler direkt aufgerufen werden. Andernfalls, wenn der Aufrufer nicht immer innerhalb des Strangs läuft, kann man strand.dispatch()
verwenden, um Nebenläufigkeitsanforderungen zu erfüllen, während möglicherweise einige Aufrufketten optimiert werden.
Betrachten Sie zum Beispiel den Fall, in dem ein Anwendungsprotokoll einen Heartbeat erfordert, der sowohl auf periodischer Basis als auch als Antwort auf jede Heartbeat-Anforderung gesendet wird. Man kann die asynchrone Aufrufketten so auszugestalten, dass es zwei separate Anruf Ketten:
a keepalive
Klasse ist verantwortlich für eine Verbindungskette, die periodisch einen Herzschlag sendet. Es wird ein Timer Ablauf und nach Ablauf festgelegt, eine neue Ablaufzeit eingestellt und Herzschlag gesendet:
.---------------------------.
V |
keepalive::start_timer() |
{ |
timer_.expires_from_now(...); |
timer_.async_wait( |
[this](...) |
{ |
this->start_timer(); -----'
io.send_headerbeat();
});
}
keepalive.start_timer();
eine io
Klasse verwaltet die Buchse, einen eigenen Strang mit Zugang zur Steckdose serialisieren. Die Klasse io
liest aus dem Socket und verarbeitet die gelesenen Daten.
.-------------------------------------.
V |
io::read_data() |
{ |
async_read(socket_, buffer_, |
strand_.wrap([this](...) |
{ |
auto message = parse(buffer_); |
this->read_data(); ----------------'
if (is_heartbeat_request(message))
{
this->send_heartbeat();
}
}));
}
io::start()
{
strand_.post([this]{ this->read_data(); });
}
In keepalive
Privat Strang 's Call-Kette wird io::send_heartbeat()
von außerhalb io
aufgerufen', auf die keepalive
keinen Zugriff hat. Auf der anderen Seite wird in der Rufkette io
io::send_heartbeat()
von innerhalb des Stranges aufgerufen. Wenn io::send_heartbeat()
einen Handler auslöst, der einen Schreibvorgang für den Socket initiiert, funktioniert er ordnungsgemäß und transparent mit beiden asynchronen Aufrufketten. Darüber hinaus wird der Handler sofort ausgeführt, wenn er innerhalb der io
Aufrufkette aufgerufen wird, wodurch der Aufwand für das Buchen und Synchronisieren mit dem Strang vermieden wird.
io::send_heartbeat()
{
strand_.dispatch(
[this]()
{
async_write(this->socket_, ...,
this->strand_.wrap(...));
});
}
strand::dispatch()
wird sofort den Handler in dem aktuellen Thread ausgeführt werden, wenn entweder:
strand::running_in_this_thread()
kehrt true
strand::running_in_this_thread()
kehrt false
und der Anrufer wird die io_service
und die Reihenfolge der Behandlungsroutine ausgeführt wird durch Strang spezifizierter Aufruf kann erfüllt werden
Es gibt keine öffentlichen APIs, um alle Bedingungen für den zweiten Fall zu bestimmen. Daher kann nicht festgestellt werden, ob der direkte Aufruf des Handlers sicher ist, und stattdessen strand::dispatch()
verwenden.
Vielen Dank für Ihre Antwort. – suzuiyue
Verwenden Sie eine Art von (Online-) Werkzeug, um die ASCII-Pfeile zu machen? – sehe
@sehe Ich benutze http://asciiflow.com/ für schnelle Linien und Formen, dann modifiziere einige der Zeichen. –