C++异步调用最佳实践

C++ asynchronous call best practice

本文关键字:最佳 调用 异步 C++      更新时间:2023-10-16

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

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

  2. 智能指针绑定到回调。这里的例子: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() 都指向同一实例。 这有助于防止难以定位的内存泄漏。 例如,在原始示例代码中,如果 AsyncReadHandler 的复制构造函数在尝试调用 AsyncReadMessage 时抛出,则Protocol::AsyncReadMessage中会发生内存泄漏。 Boost.Asio的异步TCP日间服务器和许多示例显示了enable_shared_from_this在Boost.Asio中使用。 为了更深入地理解,这个问题专门介绍了异步 Boost.Asio 函数和shared_ptr


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