簡體   English   中英

為異步發送緩沖區保留內存(增強的asio套接字)

[英]Reserving memory for asynchronous send buffers (boost asio sockets)

我正在嘗試將即發即棄UDP發送功能的實現從同步更改為異步。

當前的簡化同步函數如下所示:

ssize_t UDPTransport::send_to(const char * buffer, size_t bufferSize) {
    return mPSocket->send_to(boost::asio::buffer(buffer, bufferSize), mOutputEndpoint);
}

我已經設置了thread_group並將io_service::run()設置為使用它。 但是,問題是我無法保證此調用完成后buffer將存在。 我需要存儲緩沖區的內容,然后知道什么時候空閑,以便以后可以重用或刪除它。 以下內容很簡單,但是如果我觸發了兩個send_to調用,那么我無法保證將以相同的順序調用handle_send ,那么我可能會pop仍然需要的內容!

ssize_t UDPTransport::send_to(const char * buffer, size_t bufferSize) {

    boost::asio::mutable_buffer b1 = boost::asio::buffer(buffer,bufferSize);
    mMutex.lock();
    mQueue.push(b1);

    mPSocket->async_send_to(mQueue.back(), mOutputEndpoint,
                            boost::bind(&UDPTransport::handle_send, this,
                                        boost::asio::placeholders::error,
                                        boost::asio::placeholders::bytes_transferred));

    mMutex.unlock();
    return bufferSize;
}

void UDPTransport::handle_send(const boost::system::error_code& error,
                               std::size_t bytes_transferred)
{
    mMutex.lock();
    mQueue.pop();
    mMutex.unlock();
}

什么是存儲異步緩沖區,然后在不再需要它時清理它的好方法?

下面可能是更簡單的在線閱讀方式,但是我不知道自己是否信任它。 為什么共享指針決定在調用處理程序之后才自行取消分配?

ssize_t UDPTransport::send_to(const char * buffer, size_t bufferSize) 
{
    auto buf = std::make_shared<std::string>(buffer, bufferSize);
    mPSocket->async_send_to(boost::asio::buffer(*buf), mOutputEndpoint,
                            boost::bind(&UDPTransport::handle_send, this,
                                        boost::asio::placeholders::error,
                                        boost::asio::placeholders::bytes_transferred));
    return bufferSize;
}

我通常要做的是將其包裝在從std :: enable_shared_from_this <>繼承的類中,內容如下:

class Sender : public std::enable_shared_from_this<Sender> {
 public:
  using CompletionHandler =
      std::function<void(const boost::system::error_code& ec,
                         size_t bytes_transferred,
                         std::shared_ptr<Sender> sender)>;

  ~Sender() = default;

  template<typename... Args>
  static std::shared_ptr<Sender> Create(Args&&... args) {
    return std::shared_ptr<Sender>(new Sender(std::forward<Args>(args)...));
  }

  void AsyncSendTo(const char* buffer, size_t buffer_size,
                   CompletionHandler completion_handler) {
    data_.append(buffer, buffer_size);
    socket.async_send_to(
        boost::asio::buffer(data_), endpoint_,
        [self = shared_from_this(),
         completion_handler = std::move(completion_handler)]
        (const boost::system::error_code& ec,
         size_t bytes_transferred) mutable {
          completion_handler(ec, bytes_transferred, std::move(self));
        });
  }

 private:
  Sender() = default;
  Sender(const Sender&) = delete;
  Sender(Sender&&) = delete;
  Sender& operator=(const Sender&) = delete;
  Sender& operator=(Sender&&) = delete;

  SocketType socket_;
  EndpointType endpoint_;
  std::string data_;
}

顯然,您必須保證completion_handler的生命周期。 但是除此之外,完成處理程序將在完成后返回有效的std::shared_ptr<Sender> ,並且您可以使用Sender攜帶的數據進行任何所需的操作。

在您發布的示例中, buf將離開scope並在send_to返回時被銷毀,除非您首先在bind捕獲了它。

腳注1:可能需要刪除那些std::move() ,具體取決於您的編譯器在lambda上是否兼容C ++ 14。

腳注2:除非絕對需要利用它的動態特性,否則請遠離bind

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM