C++异步调用最佳实践

标签 c++ boost-asio

我正在使用 boost::asio。我写了一个类负责从套接字异步读取。 在我的应用程序中,io_service 可以在一个应用程序运行期间多次停止和启动。 所以我不得不担心服务停止时的内存泄漏。 我得出了两个解决方案:

  1. 请求异步请求的类为函数提供了用于 asio 读取的缓冲区,并负责释放缓冲区。这是一个显而易见的解决方案,但我不喜欢它。将不需要的参数传递给函数看起来真的很奇怪。

  2. 绑定(bind)到回调的智能指针。这里的例子: http://pastebin.com/p8nQ5NFi

现在我正在使用第二种解决方案,但不管我怎么想,我正在发明一个轮子。异步调用中缓冲区清理的常见做法是什么?我的方法有什么隐患吗?

最佳答案

shared_ptr方法相当普遍。然而,而不是通过 shared_ptr作为 bind 的附加参数, 可以传递 shared_ptr作为实例对象代替 this .

boost::shared_ptr< my_class > ptr( this );

boost::asio::async_read( stream, buffer, 
  boost::bind( &my_class::read_handler, ptr, 
     boost::asio::placeholders::error
     boost::asio::placeholders::bytes_transferred ) );

通常,因为实例将通过 shared_ptr 进行管理, 可能在也可能不在 this 的上下文中, 使用 Boost.SmartPointer 的 enable_shared_from_this 是个好主意.当一个类继承自 boost::enable_shared_from_this , 它提供了一个 shared_from_this()返回有效 shared_ptr 的成员函数实例到 this .

class my_class: public boost::enable_shared_from_this< my_class >
{
  void read()
  {
     boost::asio::async_read( stream, buffer, 
       boost::bind( &my_class::read_handler, shared_from_this(), 
          boost::asio::placeholders::error
          boost::asio::placeholders::bytes_transferred ) );
  }
};

boost::shared_ptr< my_class > foo( new my_class() );
foo->read();

在此代码段中,foo.get()foo->shared_from_this()两者都指向同一个实例。这有助于防止难以定位的内存泄漏。例如,在原始示例代码中,内存泄漏发生在Protocol::AsyncReadMessage。如果AsyncReadHandler的复制构造函数在尝试调用时抛出 AsyncReadMessage . Boost.Asio 的 asynchronous TCP daytime server和许多 examples显示 enable_shared_from_this在 Boost.Asio 中使用。为了更深入的了解,this问题具体涉及异步 Boost.Asio 函数和 shared_ptr .


此外,在原始代码中,可能更容易制作Protocol::AsyncHelper。一个模板类,而不是让它成为一个具有模板成员函数的非模板类。这将允许 AsyncHelper接受协议(protocol)、流和处理程序作为构造函数参数,并将它们存储为成员变量。此外,它使 bind调用稍微更容易阅读,因为它减少了需要传递的参数数量,并且由于成员函数不再是模板,因此无需指定它们的完整类型。 Here是一个示例的快速传递。

关于C++异步调用最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11641620/

相关文章:

c++ - 使用迭代器进行二进制搜索,为什么我们使用 "(end - begin)/2"?

c++ - boost daytime7 服务器示例不响应 netcat 客户端

c++ - boost::asio::spawn yield 作为回调

c++ - 如何停止 boost asio io_service 并完成所有已发布的处理程序?

c++ - LNK2019 当包含 asio header 时,使用 cmake 生成的解决方案

c++ - 在 BOOST_FOREACH 遍历容器时更改容器?

c++ - 在没有回调的情况下调用升压函数

c++ - 如何设置 VS2008 以进行高效的 C++ 开发

c++ - 如何使用 C++ 使用 VLC 播放器运行视频文件

c++ - 在 boost::asio 中多次写入单个套接字