私はfire-and-forget 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
の呼び出しを2回発射した場合、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();
}
非同期バッファを保存して不要になったときにクリーンアップするとよいでしょうか?
Reading onlineさらに簡単な方法でも下のように表示されますが、信頼できるかどうかはわかりません。ハンドラが呼び出された後でなければ、共有ポインタは自分自身の割り付けを解除しないのはなぜですか?
明らか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 :: enable_shared_from_this <>何かを継承するクラスでそれをラップすることです私は通常行うこと
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;
}
あなたがおそらくリンクしているshared_ptrソリューションは、shared_ptrをラムダの値で取得するため、おそらく正しいです。ですから、ハンドラが呼び出されると、ハンドラ自体の割り当てを解除する必要があります。しかし、shared_ptrを使ったコードはそれをしません。 –