c++ - 拥有 `ConstBufferSequence`的boost::asio数据

标签 c++ asynchronous boost object-lifetime asio

最后几天,我大量阅读了asio示例以及关于SO的其他问题,这些问题与传递给asios启动函数的缓冲区的生命周期管理有关。让我印象深刻的一个问题是,似乎没有“按值”解决方案,但是初始化函数的调用者始终需要确保缓冲区有效,直到异步操作完成为止。通常,这是通过创建指向数据的共享指针并将其复制到处理程序中来实现的。
就我而言,我已经在使用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.
因此,我正在考虑编写一个自定义Message类,该类既可以满足ConstBufferSequence概念,又可以让拥有基础消息。我仔细研究了一下代码,发现在某个地方,首先通过asio::async_write传递到const&的缓冲区序列参数通过const&传递,直到最终被复制到asio::detail::write_op类的成员变量中。
所以这里是实际的问题:
  • 这种方法可以解决火灾并忘记打电话吗?这将在上面翻译成类似:asio::async_write(_socket, Message("hello"),[](auto,auto){});
  • constbuffer序列参数w.r.t的生存期是否存在任何问题。组合操作?
  • 这会是个好主意吗?显然,这与处理缓冲区生存期管理的“常规” asio方法背道而驰。

  • 对您的想法感到好奇-欢迎批评! ;-)
    问候,马丁

    最佳答案

    我之前看过shared_buffer(我认为它在Asio docs / exmples中,稍后会搜索)。
    此外,显然有

  • boost::asio::streambuf
  • Beast缓冲区模型(flat_buffer,multi_buffer,vector_buffer)

  • 当然,它只是将问题从所有权问题转移到生命周期问题。
    将Boost Asio的缓冲区概念设为“仅引用”或“ View 语义”的好处是
  • 您永远不会遇到生命周期问题,这些问题是通过value和
  • 传递这些引用的
  • 它们非常适合以正确的方式实现组合操作:无需假设缓冲区组织

  • 找到了Asio示例:https://www.boost.org/doc/libs/1_42_0/doc/html/boost_asio/example/buffers/reference_counted.cpp这些天住在
  • 示例/cpp03/buffers/reference_counted.cpp
  • 示例/cpp11/buffers/reference_counted.cpp

  • 解决项目符号

    Can this approach work for a fire and forget call? This would translate above intos something like: asio::async_write(_socket, Message("hello"),{});



    Are there any issues with the lifetime of the constbuffer sequence arguments w.r.t. composed operations?


    如果您管理得好,那就不是,这仍然是要求

    Would this be a good idea? It obviously goes against the "normal" asio way of dealing with buffer lifetime management.


    取决于您的操作方式。如果最终复制批发的缓冲区,那将是昂贵的,并且也将无法使用某些异步操作(这要求缓冲区具有引用稳定性,这意味着:不要更改地址,换句话说,不要四处走动)。
    通过移动语义可以使许多缓冲区类型仍然能够提供此属性,但是按值传递缓冲区的问题是它们可能会创建多个副本,
  • 要么不编译(因为它们不是右值)
  • 或(如果您使用移动副本构造函数/分配对其进行破解)可能会在使用移动副本时导致UB

  • 关于c++ - 拥有 `ConstBufferSequence`的boost::asio数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62599431/

    相关文章:

    c++ - Boost::Asio聊天示例程序---如何实现私聊

    c++ - 为什么这样的循环在输入字符串时不会捕获错误?

    c++ - 在 C++ 中不受控制的循环和函数跳过?

    c++ - 传递指针 - 用于写入流

    c# - Async TestInitialize 保证测试失败

    node.js - 使用 cy.task 动态创建测试

    c++ - 在 jam 文件中指定 Boost.build 内置功能

    c++ - OpenCV - 来自两个垂直 2D 图像的 3D 真实世界坐标

    c++ - 用 C++17 功能替换 Boost MPL 容器

    c# - 异步执行的排队操作/委托(delegate)