项目中使用boost::asio,其中的异步调用往往会有一个handler参数,这个参数一般使用动态内存申请的对象和其成员函数构建。

因此如果在asio线程和对象管理线程中间没有适当的同步机制,则很容易造成内存访问错误,如pure virtual method called等。这时候可以使用boost::shared_ptr和enable_shared_from_this(从类实例内获取管理自身的shared_ptr拷贝,引用计数会加1,这个拷贝如果不失效则类实例不能析构)来解决动态内存管理问题

下面是一个验证enable_shared_from_this的例子

#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
class Good;
class Good: public boost::enable_shared_from_this<Good>{
private:
    virtual int callback() = 0;
public:
    void init_cb()
    {
        cb = boost::bind(&Good::callback,shared_from_this());
    }
    void run()
    {
        cb();
    }
    boost::shared_ptr<Good> get_shared_ptr()
    {
        return shared_from_this();
    }
    virtual ~Good()
    {
        std::cout<<"~Good"<<std::endl;
    }
private:
    boost::function<int()> cb;
};
class SonOfGood:public Good{
    virtual int callback(){
        std::cout<<"Callback"<<std::endl;
    }
public:
    virtual ~SonOfGood()
    {
        std::cout<<"~SonOfGood"<<std::endl;
    }
};
void func(boost::shared_ptr<Good> & gp1)
{
        std::cout << "gp1.use_count() = " << gp1.use_count() << '\n';
        boost::shared_ptr<Good>  cb = gp1->get_shared_ptr();
        std::cout << "gp1.use_count() = " << gp1.use_count() << '\n'; // 计数应该加1
}
int main(){
        boost::shared_ptr<Good> gp1(new SonOfGood);
        std::cout << "gp1.use_count() = " << gp1.use_count() << '\n'; // 应该为1

        func(gp1); 
        std::cout << "gp1.use_count() = " << gp1.use_count() << '\n'; // 应该为1

        std::cout << "gp1.use_count() = " << gp1.use_count() << '\n'; // 应该为1
        gp1->init_cb(); // 从gp1创建了boost::function<int()>,使用了shared_from_this(),use_count会加1
        std::cout << "gp1.use_count() = " << gp1.use_count() << '\n'; // 应该为2
        gp1->run();
        std::cout << "gp1.use_count() = " << gp1.use_count() << '\n'; // 应该为2
}

具体使用还可以参考mongodb代码,其中的message_server_asio.cpp文件中有非常好的例子。


posted on 2013-02-21 15:19  #hanhui  阅读(137)  评论(0编辑  收藏  举报