考虑以下代码:
void TCP::sendMessage(const std::string& msg) {
std::ostream os{&m_send_streambuf};
os << msg;
if (not m_pending_send) {
doSend();
}
}
void TCP::doSend() {
m_pending_send = true;
boost::asio::async_write( m_socket, m_send_streambuf
, [this](boost::system::error_code ec, std::size_t len)
{
if (ec) {
throw std::runtime_error(ec.message());
}
m_send_streambuf.consume(len);
if (m_send_streambuf.size() >= 1) {
// There's still some data to send
doSend();
}
else {
m_pending_send = false;
}
});
}
m_send_streambuf
是一个 boost::asio::streambuf
并且 m_pending_send
指示异步写入是否正在等待。
我不确定像这样使用 streambuf
是否是个好主意,因为对 sendMessage
的调用将修改缓冲区,而异步写入可能正在运行.
那么,像这样使用streambuf
安全吗?或者我应该使用某种双缓冲?
最佳答案
The documentation of async_write关于 buffers 参数状态:
One or more buffers containing the data to be written. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.
因此您不应该对流缓冲区执行任何其他写操作,因为这可能会使传递给 async_write
的底层内存块无效。
您可以做的是简单地使用 stringstream
来缓冲传入的数据,一旦挂起的异步写入完成,将内容刷新到提升流缓冲区并分派(dispatch)新的异步写入。当然,您可以使用更复杂的机制,例如维护一个流缓冲区池以保留其状态信息(待定或可用),并在每次调用 sendMessage
时从池中获取一个新的流缓冲区并分派(dispatch)一个新的流缓冲区异步写入。这完全取决于您的要求 - 吞吐量和延迟或内存消耗。
关于c++ - 在 async_write 挂起时写入 streambuf 是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33078400/