shared_ptr的 deleter, weak_ptr.lock 在多线程的运用举例

1.shared_ptr的删除器(deleter)

可以在 shared_ptr 的构造函数 和 reset 函数里面给 shared_ptr 加入 deleter。

定义:

 template<class Y, class D> shared_ptr::shared_ptr(Y* p, D d);


 template<class Y, class D> void shared_ptr::reset(Y* p, D d);

 

deleter的作用是:deleter可以是一个函数或者是仿函数。在调用 shared_ptr 的析构函数的时候会有一个 delete 操作,现在提供的这个 deleter,就是用来替代delete的。

会执行:d(p)

ex:

shared_ptr<int> tem(new int, delFun);

那么在调用 shared_ptr的析构函数的时候 delete p 会被替换为 delFun(p)

 

2.weak_ptr的lock函数:

weak_ptr.lock() 会把weak_ptr提升为一个 shared_ptr 对象,当 引用计数为0 ,那么 shared_ptr 为空。

ex:

shared_ptr<int> shPtr = weakPtr.lock();

if(! shPtr)

{

    //进入这里,表示引用计数为0;

    return;

}

//在这里,说明引用计数不为0,成功的构造了一个 shared_ptr

 

3.下面一个例子来说明deleter和 weak.lock() 的使用

 

假设有 Stock 类,代表一只股票的价格。每一只股票有一个惟一的字符串标识,比如 Google 的 key 是 "NASDAQ:GOOG",IBM 是 "NYSE:IBM"。Stock 对象是个主动对象,它能不断获取新价格。为了节省系统资源,同一个程序里边每一只出现的股票只有一个 Stock 对象,如果多处用到同一只股票,那么 Stock 对象应该被共享。

为了达到上述要求,我们可以设计一个对象池 StockFactory。它的接口很简单,根据 key 返回 Stock 对象。如果stock对象不存在就创建一个。

(1)为了管理这个对象池StockFactory, 我们最初的设计如下:

class StockFactory : boost::noncopyable    

{ // questionable code  

 public:  

  shared_ptr<Stock> get(const string& key);

 private:  

  std::map<string, shared_ptr<Stock> > stocks_;  

  mutable Mutex mutex_;  

};

这里有一个问题,shared_ptr<Stock> 使得stock的生命周期被延长了。stock的生命周期与 StockFactory一样长了。

 

(2)我们知道weak_ptr不会延长对象的生命周期, weak_ptr只是对象一个observer。于是我们有下面的设计:

class StockFactory : boost::noncopyable 

 public: 
  shared_ptr<Stock> get(const string& key) 
  { 
    shared_ptr<Stock> pStock; 
    MutexLock lock(mutex_); 
    weak_ptr<Stock>& wkStock = stocks_[key];  // 如果 key 不存在,会默认构造一个 
    pStock = wkStock.lock();  // 尝试把weak_ptr提升为shared_ptr

    if (!pStock) { 
      pStock.reset(new Stock(key)); 
      wkStock = pStock;  // 这里更新了 stocks_[key],注意 wkStock 是个引用 
    } 
    return pStock; 
  }    

 private: 

  std::map<string, weak_ptr<Stock> > stocks_; 
  mutable Mutex mutex_; 

};

 

(3).上面的代码解决了延长对象生命周期的问题,但是仍然有问题,那就是即使对象已经不存在了,它仍然在 stocks_ 里面存在。 这样也可以叫做内存泄露。

为了解决这个问题,我们现在就要用到 shared_ptr 的 deleter 功能:这里deleter保证在删除stock的同时也删除 这个stock在 stocks_ 里面的存在。

class StockFactory : public boost::enable_shared_from_this<StockFactory>,boost::noncopyable 

 public: 
  shared_ptr<Stock> get(const string& key) 
  { 
    shared_ptr<Stock> pStock; 
    MutexLock lock(mutex_); 
   
    weak_ptr<Stock>& wkStock = stocks_[key]; 
    pStock = wkStock.lock(); 

    if (!pStock) { 
      pStock.reset(new Stock(key), 
                    boost::bind(&StockFactory::weakDeleteCallback, 
                                 boost::weak_ptr<StockFactory>(shared_from_this()), 
                                 _1)); 
      // 上面必须强制把 shared_from_this() 转型为 weak_ptr,才不会延长生命期 

      wkStock = pStock; 
    } 
    return pStock; 
  } 

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

  void removeStock(Stock* stock) 
  { 
    if (stock) { 
      MutexLock lock(mutex_); 
      stocks_.erase(stock->key()); 
    } 
  } 
 
 private: 
  std::map<string, weak_ptr<Stock> > stocks_;
  mutable Mutex mutex_; 
};

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值