C ++异步调用最佳实践

时间:2012-07-25 01:53:21

标签: c++ boost-asio

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

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

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

  3. 现在我正在使用第二种解决方案但是我感觉到,我正在发明一个轮子。异步调用中缓冲区清理的常见做法是什么?我的方法有什么隐藏的问题吗?

1 个答案:

答案 0 :(得分:4)

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::enable_shared_from_this的上下文中进行管理,因此最好使用Boost.SmartPointer {{3 }}。当一个类继承自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的copy-constructor在尝试调用enable_shared_from_this时抛出,则会发生内存泄漏。 Boost.Asio的enable_shared_from_this和许多asynchronous TCP daytime server显示shared_ptr在Boost.Asio中使用。为了更深入地理解,examples问题专门涵盖了异步Boost.Asio函数和Protocol::AsyncHelper


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