2017-02-25 8 views
1

Viele Beispiele, die ich online gefunden habe schlagen vor, eine Warteschlange verwenden, um Nachrichten von async_write, die wiederum einen Abschluss-Handler i..e, Lambda, die Daten nach dem async_write löscht verworfen Komplett. Zum Beispiel der Chat-Server von Boost-Beispielen: http://www.boost.org/doc/libs/1_62_0/doc/html/boost_asio/example/cpp11/chat/chat_server.cpp. Der anwendbare Code ist folgendes:Erzwingen maximale Größe für Boost ASIO-Warteschlange

void do_write() 
    { 
    auto self(shared_from_this()); 
    boost::asio::async_write(socket_, 
     boost::asio::buffer(write_msgs_.front().data(), 
      write_msgs_.front().length()), 
     [this, self](boost::system::error_code ec, std::size_t /*length*/) 
     { 
      if (!ec) 
      { 
      write_msgs_.pop_front(); 
      if (!write_msgs_.empty()) 
      { 
       do_write(); 
      } 
      } 
      else 
      { 
      room_.leave(shared_from_this()); 
      } 
     }); 
    } 

jedoch in der Anwendung ich bin mit für, es ist möglich, dass Nachrichten in write_msgs_ geschoben werden, schneller als die async_write abgeschlossen werden kann und damit wächst die Warteschlange beliebig groß im Speicher, bis Die Anwendung stürzt ab.

Ich habe versucht, eine threadsichere Warteschlange zu verwenden, die Nachrichten von der Vorderseite löscht, wenn die Warteschlange eine bestimmte Größe erreicht. Das Problem ist, dass der Completion-Handler der einzige ist, der entscheidet, wann die Daten verwendet werden, daher ist mein Ansatz fehlgeschlagen, da Nachrichten ausgeblendet werden, bevor sie verwendet werden.

Kann jemand einen Schub in die richtige Richtung geben? Kann ich zwei Warteschlangen verwenden, um dieses Problem zu lösen?

Antwort

0

Sie benötigen eine beschränkte Warteschlange, und Sie müssen irgendwie den Fall der Warteschlange behandeln, die voll ist.

Wenn Sie keine Fadensicherheit benötigen (d. H. Wenn Sie einen Strang verwenden), können Sie boost::circular_buffer in Betracht ziehen.

Ansonsten gibt es boost::sync_bounded_queue in Boost.Thread.

+0

Ich fühle die Datenstruktur, die ich benutze, ist nicht das Hauptproblem. Es sind die Algorithmen, die mit dem Verwerfen von Daten verbunden sind. Die Daten, die von async_write "write_msgs_.front(). Data()" verwendet werden, müssen woanders leben. Es muss nur im Gültigkeitsbereich bleiben, bis der Beendigungshandler aufgerufen wird: "Obwohl das Pufferobjekt nach Bedarf kopiert werden kann, wird das Eigentum der zugrunde liegenden Speicherblöcke vom Aufrufer beibehalten, der garantieren muss, dass sie gültig bleiben, bis der Handler ist namens." –

+0

@BrockHargreaves 'muss woanders leben. Das kann entweder eine andere Warteschlange sein (was nicht hilft), oder der Stapel der Funktion, der die' async_write' in die Warteschlange stellt. Im zweiten Fall müssen Sie blockieren (zum Beispiel mit einer Zukunft). Denken Sie mal darüber nach: Wenn der Produzent schneller ist als der Konsument (der 'async_write'), gibt es keine mögliche Lösung, also schmeißen wir entweder Daten weg oder wir lassen den Produzenten auf den Konsumenten warten. – sbabbi