2016-07-01 2 views
1

Ich bin neu bei boost :: asio. Der Boost doc sagte:boost :: asio :: strang :: dispatch (handle) oder rufen Sie den Handle direkt?

Das Strangobjekt garantiert, dass Handler, die über den Strang gebucht oder versandt werden, nicht gleichzeitig ausgeführt werden. Innerhalb dieser Funktion kann der Handler ausgeführt werden, wenn die Garantie erfüllt werden kann. Wenn diese Funktion von einem Handler aufgerufen wird, der über denselben Strang gesendet oder versendet wurde, wird der neue Handler sofort ausgeführt.

Also ich möchte wissen, wann der neue Handler sofort ausgeführt wird, warum nicht einfach direkt anrufen, anstatt den Versand zu verwenden?

Antwort

2

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 ioio::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.

+0

Vielen Dank für Ihre Antwort. – suzuiyue

+0

Verwenden Sie eine Art von (Online-) Werkzeug, um die ASCII-Pfeile zu machen? – sehe

+0

@sehe Ich benutze http://asciiflow.com/ für schnelle Linien und Formen, dann modifiziere einige der Zeichen. –