C++ boost::asio数据拥有`ConstBufferSequence`

C++ boost::asio数据拥有`ConstBufferSequence`,c++,asynchronous,boost,object-lifetime,asio,C++,Asynchronous,Boost,Object Lifetime,Asio,在过去的几天里,我阅读了很多asio示例和其他关于传递给asio启动函数的缓冲区的生命周期管理的问题。令我震惊的一个问题是,似乎没有“按值”的解决方案,但相反,启动函数的调用方始终需要确保缓冲区在异步操作完成之前是有效的。这通常是通过创建指向数据的共享指针并将其复制到处理程序中来实现的 在我的例子中,我已经在使用async_write重载,其中传递了一个ConstBufferSequence,它保存下一条消息的大小,然后是下一条消息。即 auto message = std::make_shar

在过去的几天里,我阅读了很多asio示例和其他关于传递给asio启动函数的缓冲区的生命周期管理的问题。令我震惊的一个问题是,似乎没有“按值”的解决方案,但相反,启动函数的调用方始终需要确保缓冲区在异步操作完成之前是有效的。这通常是通过创建指向数据的共享指针并将其复制到处理程序中来实现的

在我的例子中,我已经在使用
async_write
重载,其中传递了一个
ConstBufferSequence
,它保存下一条消息的大小,然后是下一条消息。即

auto message = std::make_shared<std::string>("hello");
auto size = std::make_shared<std::uint32_t>(message.size());
std::vector<asio::const_buffer> buffers = {asio::buffer(size, sizeof(*size)), asio::buffer(*message)};
asio::async_write(_socket, buffers, [message,size](...){...}); // prolong lifetime by coping shared ptrs.
auto message=std::使_共享(“你好”);
auto size=std::make_shared(message.size());
std::vector buffers={asio::buffer(size,sizeof(*size)),asio::buffer(*message)};
asio::异步写入(_套接字,缓冲区,[消息,大小](…){…});//通过应对共享PTR延长寿命。
因此,我正在考虑编写一个自定义的
消息
类,该类实现了
ConstBufferSequence
概念,但也拥有底层消息。我仔细研究了一下代码,发现在一个地方,缓冲区序列参数首先通过
const&
传递到
asio::async_write
中,然后通过
const&
传递,直到最后被复制到
asio::detail::write_op
类的一个成员变量中

下面是实际问题:

  • 这种方法是否适用于火灾和遗忘呼叫?这将把上面的intos翻译成如下内容: asio::异步写入(_socket,Message(“hello”),[](auto,auto){})

  • constbuffer序列参数w.r.t.组合操作的生存期是否存在任何问题

  • 这是个好主意吗?这显然违背了asio处理缓冲区生命周期管理的“正常”方式

好奇你的想法-欢迎批评!;-)


您好,Martin

我以前见过一个
共享缓冲区(我想它在Asio文档/示例中,稍后会搜索)

而且很明显

  • boost::asio::streambuf
  • Beast缓冲区模型(平面缓冲区、多缓冲区、向量缓冲区)
当然,它只是将问题从所有权问题转移到终身问题

Boost Asio的缓冲区概念是“仅引用”或“视图语义”的好处在于

  • 您从未遇到过按值传递这些引用的终身问题,并且
  • 它们非常适合以正确的方式实现组合操作:不需要对缓冲区组织进行假设

找到Asio的例子:现在生活在

  • 示例/cpp03/buffers/reference_counted.cpp
  • 示例/cpp11/buffers/reference_counted.cpp
解决子弹问题 这种方法是否适用于火灾和遗忘呼叫?这将把上面的intos翻译成:asio::async_write(_socket,Message(“hello”),{})

constbuffer序列参数w.r.t.组合操作的生存期是否存在任何问题

如果你管理得好就不会,这是一个要求

这是个好主意吗?这显然违背了asio处理缓冲区生命周期管理的“正常”方式

这取决于你怎么做。如果最终批量复制缓冲区,成本会很高,并且无法处理某些异步操作(这些操作要求缓冲区具有引用稳定性,这意味着:不更改地址,换句话说,不四处移动)

如果使用移动语义,许多缓冲区类型可能仍然能够提供此属性,但按值传递缓冲区的问题是,它们可能会生成多个副本,这会导致

  • 两者都不编译(因为它们不是右值)
  • 或者(如果您使用移动副本构造函数/分配进行攻击),在使用移动副本时可能会导致UB

添加了
shared_const_buffer
示例并解决了单个问题Bullet我想通过boost beast文档了解可用的
DynamicBuffer
实现给了我剩下的:D-我想我计划的与beast Dynamic buffer实现类似,但我不会走这条路。我产生了一种冲动,那就是它只是混淆了我周围发生的事情。而“发射并忘记”的方法实际上只在发送(而不是接收)时才有帮助,所以我想不值得提出一个支持者自己的实现。。。谢谢你给我指路:)@MartiNito干杯。我同意你的评估。对于“fire and forgt”,我发现通常使用
std::list
或类似工具非常方便,因为这也有助于在全双工场景中排队发送消息<代码>标准::列表
具有参考稳定性,因此非常完美。