设为首页 加入收藏

TOP

1.11.2 弱回调
2013-10-07 16:03:22 来源: 作者: 【 】 浏览:60
Tags:1.11.2

1.11.2 弱回调

把shared_ptr 绑(boost::bind)到boost:function 里,那么回调的时候Stock-Factory 对象始终存在,是安全的。这同时也延长了对象的生命期,使之不短于绑得的boost:function 对象。

有时候我们需要“如果对象还活着,就调用它的成员函数,否则忽略之”的语意,就像Observable::notifyObservers() 那样,我称之为“弱回调”。这也是可以实现的,利用weak_ptr,我们可以把weak_ptr 绑到boost::function 里,这样对象的生命期就不会被延长。然后在回调的时候先尝试提升为shared_ptr,如果提升成功,说明接受回调的对象还健在,那么就执行回调;如果提升失败,就不必劳神了。

使用这一技术的完整StockFactory 代码如下:

  1. class StockFactory : public boost::enable_shared_from_this<StockFactory>,  
  2. boost::noncopyable  
  3. {  
  4. public:  
  5. shared_ptr<Stock> get(const string& key)  
  6. {  
  7. shared_ptr<Stock> pStock;  
  8. MutexLockGuard lock(mutex_);  
  9. weak_ptr<Stock>wkStock = stocks_[key]; // 注意wkStock 是引用  
  10. pStock = wkStock.lock();  
  11. if (!pStock)  
  12. {  
  13. pStock.reset(new Stock(key),  
  14. boost::bind(&StockFactory::weakDeleteCallback,  
  15. boost::weak_ptr<StockFactory>(shared_from_this()),  
  16. _1));  
  17. // 上面必须强制把shared_from_this() 转型为weak_ptr,才不会延长生命期,  
  18. // 因为boost::bind 拷贝的是实参类型,不是形参类型  
  19. wkStock = pStock;  
  20. }  
  21. return pStock;  
  22. }  
  23. private:  
  24. static void weakDeleteCallback(const boost::weak_ptr<StockFactory>& wkFactory,  
  25. Stock* stock)  
  26. {  
  27. shared_ptr<StockFactory> factory(wkFactory.lock()); // 尝试提升  
  28. if (factory) // 如果factory 还在,那就清理stocks_  
  29. {  
  30. factory->removeStock(stock);  
  31. }  
  32. delete stock; // sorry, I lied  
  33. }  
  34. void removeStock(Stock* stock)  
  35. {  
  36. if (stock)  
  37. {  
  38. MutexLockGuard lock(mutex_);  
  39. stocks_.erase(stock->key());  
  40. }  
  41. }  
  42. private:  
  43. mutable MutexLock mutex_;  
  44. std::map<string, weak_ptr<Stock> > stocks_;  
  45. };  
  46. 两个简单的测试:  
  47. void testLongLifeFactory()  
  48. {  
  49. shared_ptr<StockFactory> factory(new StockFactory);  
  50. {  
  51. shared_ptr<Stock> stock = factory->get("NYSE:IBM");  
  52. shared_ptr<Stock> stock2 = factory->get("NYSE:IBM");  
  53. assert(stock == stock2);  
  54. // stock destructs here  
  55. }  
  56. // factory destructs here  
  57. }  
  58. void testShortLifeFactory()  
  59. {  
  60. shared_ptr<Stock> stock;  
  61. {  
  62. shared_ptr<StockFactory> factory(new StockFactory);  
  63. stock = factory->get("NYSE:IBM");  
  64. shared_ptr<Stock> stock2 = factory->get("NYSE:IBM");  
  65. assert(stock == stock2);  
  66. // factory destructs here  
  67. }  
  68. // stock destructs here  

这下完美了,无论Stock 和StockFactory 谁先挂掉都不会影响程序的正确运行。这里我们借助shared_ptr 和weak_ptr 完美地解决了两个对象相互引用的问题。

当然,通常Factory 对象是个singleton,在程序正常运行期间不会销毁,这里只是为了展示弱回调技术15,这个技术在事件通知中非常有用。

本节的StockFactory 只有针对单个Stock 对象的操作,如果程序需要遍历整个stocks_,稍不注意就会造成死锁或数据损坏(§2.1),请参考§2.8 的解决办法。

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇1.11.1 enable_shared_from_this 下一篇1.12 替代方案

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·MySQL 安装及连接-腾 (2025-12-25 06:20:28)
·MySQL的下载、安装、 (2025-12-25 06:20:26)
·MySQL 中文网:探索 (2025-12-25 06:20:23)
·Shell脚本:Linux Sh (2025-12-25 05:50:11)
·VMware虚拟机安装Lin (2025-12-25 05:50:08)