2012-07-25 64 views
3

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

  1. 类要求的异步请求提供的功能与使用ASIO一个缓冲区中读取,并负责其释放。这是一个明显的解决方案,但我不喜欢它。传递一个你不需要的函数看起来很奇怪。

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

现在我使用的是第二个解决方案,但是但是我感觉,我发明了车轮。异步调用中缓冲区清理的常见做法是什么?我的问题中有没有隐藏的问题?

回答

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.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()都指向同一个实例。这有助于防止难以找到内存泄漏。例如,在原始示例代码中,如果在尝试调用AsyncReadMessageAsyncReadHandler的复制构造函数抛出,则Protocol::AsyncReadMessage中发生内存泄漏。 Boost.Asio的asynchronous TCP daytime server和许多examples显示enable_shared_from_this正在使用Boost.Asio内。为了更深入的了解,this问题明确涵盖了异步Boost.Asio函数和shared_ptr


另外,在原来的代码,它可以更容易地使Protocol::AsyncHelper模板类代替具有它是一个非模板类与模板构件的功能。这将允许AsyncHelper接受协议,流和处理程序作为构造函数参数,将它们存储为成员变量。另外,它使得bind调用稍微容易阅读,因为它减少了需要传递的参数数量,并且由于成员函数不再是模板,所以不需要指定它们的完整类型。 Here是一个例子的快速传递。