enable_shared_from_this详解

东阳的学习笔记

shared_from_this()是C++多线程编程中经常会使用的到的一种方法。

问题提出:

见 linux 多线程服务器编程 P23. 如果 StockFactory 的生命期比 Stock 短,那么下列语句就会 core dump

// ...
pStock.reset(new Stock(key), 
		     boost::bind(&StockFactory::deleteStock, 
		     this, 
		     _1));
// ...

为了解决这个问题,我们似乎应该祭出惯用的 shared_ptr 大法, 问题来了:

如何获得一个指向当前对象的 shared_ptr 呢?

shared_from_this

enable_shared_from_this是一个类,将有上述需求的类继承自它,就可以解决上面所提出的问题。

enable_shared_from_this 有一个私有成员变量,保存了一个 weak_ptr指针, 可以看到其保存的就是 this

我们只需要将问题中的代码修改为下面的就可以解决问题了:

  1. 继承 enable_shared_from_this
  2. 在bind中使用
class StockFactory : public boost::enable_shared_from_this<StockFactory>, 
					 boost::noncopyable
{ /* ... */ }
pStock.reset(new Stock(key), 
		     boost::bind(&StockFactory::deleteStock, 
		     shared_from_this(), 
		     _1));

我们先来看看源码:

template<class T> class enable_shared_from_this
{
protected:
    BOOST_CONSTEXPR enable_shared_from_this() BOOST_SP_NOEXCEPT{}
    BOOST_CONSTEXPR enable_shared_from_this(enable_shared_from_this const &) BOOST_SP_NOEXCEPT{}
    enable_shared_from_this & operator=(enable_shared_from_this const &) BOOST_SP_NOEXCEPT { return *this; }
     // ~weak_ptr newer throws, so this call also must not throw
    ~enable_shared_from_this() BOOST_SP_NOEXCEPT{}
public:
    shared_ptr<T> shared_from_this()
    {
        shared_ptr<T> p( weak_this_ );
        BOOST_ASSERT( p.get() == this );
        return p;
    }

    shared_ptr<T const> shared_from_this() const
    {
        shared_ptr<T const> p( weak_this_ );
        BOOST_ASSERT( p.get() == this );
        return p;
    }

    weak_ptr<T> weak_from_this() BOOST_SP_NOEXCEPT
    {
        return weak_this_;
    }

    weak_ptr<T const> weak_from_this() const BOOST_SP_NOEXCEPT
    {
        return weak_this_;
    }

public: // actually private, but avoids compiler template friendship issues

    // Note: invoked automatically by shared_ptr; do not call
    template<class X, class Y> void _internal_accept_owner( shared_ptr<X> const * ppx, Y * py ) const BOOST_SP_NOEXCEPT
    {
        if( weak_this_.expired() )
        {
            weak_this_ = shared_ptr<T>( *ppx, py );
        }
    }

private:
    mutable weak_ptr<T> weak_this_;
};

但是,StockFactory的生命期似乎被意外延长了,不小于boost::function对象

弱回调

有时候我们需要“如果对象还活着,就调用它的成员函数,否则忽略之的语义”。
弱回调使用示例。(Factory通常是个 singleton,在程序正常运行期间不会销毁,这是只是为了展示弱回调的用法)

pStock.reset(new Stock(key),
             boost::bind(&StockFactory::weakDeleteCallback,
             boost::weak_ptr<StockFactory>(shared_from_this()),
             _1));
// 上面必须把 shared_from_this() 转型为 weak_ptr, 才不会延长生命期
// 因为 bind 绑定的是实参类型而不是形参类型

// ...

static void weakDeleteCallback(const boost::weak_ptr<StockFactory>& wkFactory, Stock *stock)
{
	shared_ptr<StockFactory> factory(wkFactory.lock());  // 尝试提升
	if (factory)    // 如果 factory 还在,那就清理stocks_
	{
		factory->removeStock(stock);
	}
	delete stock;  // sorry, i lied
}

你可能感兴趣的:(muduo网络库)