consolidate multiple buffers from async_write_some to single SendBuffer

This commit is contained in:
orignal
2026-07-22 21:34:18 -04:00
parent db701c7928
commit 3e56fddad3
3 changed files with 61 additions and 9 deletions
+35 -6
View File
@@ -19,6 +19,26 @@ namespace i2p
{
namespace stream
{
SendBuffer::SendBuffer (const std::vector<std::pair<const uint8_t *, size_t> >& bufs, size_t totalLen, SendHandler&& h):
len(totalLen), offset (0), handler(std::move (h))
{
buf = new uint8_t[len];
size_t offset1 = 0;
for (const auto& [b, l]: bufs)
{
if (offset1 + l <= totalLen)
{
memcpy (buf + offset1, b, l);
offset1 += l;
}
else
{
memcpy (buf + offset1, b, totalLen - offset1);
break;
}
}
}
void SendBufferQueue::Add (std::shared_ptr<SendBuffer>&& buf)
{
if (buf)
@@ -939,13 +959,22 @@ namespace stream
std::shared_ptr<i2p::stream::SendBuffer> buffer;
if (len > 0 && buf)
buffer = std::make_shared<i2p::stream::SendBuffer>(buf, len, std::move (handler));
else if (handler)
handler(boost::system::error_code ());
auto s = shared_from_this ();
boost::asio::post (m_Service, [s, buffer = std::move(buffer)]() mutable
else
{
if (handler)
handler(boost::system::error_code ());
return;
}
Send (std::move (buffer));
}
void Stream::Send (std::shared_ptr<i2p::stream::SendBuffer>&& buf)
{
if (!buf) return;
boost::asio::post (m_Service, [s = shared_from_this (), buf = std::move(buf)]() mutable
{
if (buffer)
s->m_SendBuffer.Add (std::move(buffer));
if (buf)
s->m_SendBuffer.Add (std::move(buf));
s->SendBuffer ();
});
}
+2
View File
@@ -144,6 +144,7 @@ namespace stream
{
buf = new uint8_t[len];
}
SendBuffer (const std::vector<std::pair<const uint8_t *, size_t> >& bufs, size_t totalLen, SendHandler&& h);
~SendBuffer ()
{
delete[] buf;
@@ -209,6 +210,7 @@ namespace stream
void HandlePing (Packet * packet);
size_t Send (const uint8_t * buf, size_t len);
void AsyncSend (const uint8_t * buf, size_t len, SendHandler&& handler);
void Send (std::shared_ptr<i2p::stream::SendBuffer>&& buf);
void SendPing ();
template<typename Buffer, typename ReceiveHandler>
+24 -3
View File
@@ -57,15 +57,36 @@ namespace client
template<typename ConstBufferSequence, typename WriteHandler>
void async_write_some(const ConstBufferSequence& bufs, WriteHandler&& handler)
{
std::vector<std::pair<const uint8_t *, size_t> > bufsToSend;
size_t sent = 0;
for (auto it = boost::asio::buffer_sequence_begin (bufs); it != boost::asio::buffer_sequence_end (bufs); it++)
{
const auto& buf = *it;
sent += buf.size ();
m_Stream->Send ((const uint8_t *)buf.data (), buf.size ());
// TODO: AsyncSend wiht callback for last buf, but not possible below C++23
bufsToSend.push_back ({ (const uint8_t *)buf.data (), buf.size () });
}
handler (boost::system::error_code (), sent);
if (sent)
{
#ifdef __cpp_lib_move_only_function // with C++23
// we can save handler with SendBuffer
auto sendBuffer = std::make_shared<i2p::stream::SendBuffer>(bufsToSend, sent,
[handler = std::move (handler), sent](const boost::system::error_code& ecode) mutable
{
handler (ecode, sent);
});
#else
// we can't save handler with SendBuffer due to lack of std::move_only_function
auto sendBuffer = std::make_shared<i2p::stream::SendBuffer>(bufsToSend, sent, nullptr);
#endif
m_Stream->Send (std::move (sendBuffer));
#ifndef __cpp_lib_move_only_function // no std::move_only_function
// invoke handler right after send
handler (boost::system::error_code (), sent);
#endif
}
else
handler (boost::system::error_code (), 0);
}
private: