对象池
背景:
假设有一个Stock类,代表一只股票的价格,且每个股票有std::string唯一标识符。Stock对象是个主动对象,能不断获取股票的最新价格。为节省系统资源,每个程序每只出现的股票只有一个Stock对象。如果多处用到一只股票,那么Stock对象要被共享,如果这只股票没有被用到,那么对应的Stock对象应该被析构,以释放资源。下面设计一个StockFactory。
Version1:
代码:
1 class StockFactory : boost::noncopyable 2 { 3 public: 4 shared_ptr<Stock> get(const string& key); 5 private: 6 mutable MutexLock mutex_; 7 std::map<string, shared_ptr<Stock>> stocks_; 8 };
问题:
由于map中存放的市shared_ptr,因此Stock永远不会被析构。
SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。Version2:
代码:
class StockFactory : boost::noncopyable { public: shared_ptr<Stock> get(const string& key); private: mutable MutexLock mutex_; std::map<string, weak_ptr<Stock>> stocks_; }; shared_ptr<Stock> StockFactory::get(const string& key) { shared_ptr<Stock> pStock; MutexLockGuard lock(mutex_); weak_ptr<Stock>& wStock = stocks_[key]; pStock = wStock.lock(); if (!pStock) { pStock.reset(new Stock(key)); wStock = pStock; } return pStock; }
问题:
造成了内存泄漏,stock_大小只增不减,stock_.size()的大小是曾经被用到的Stock对象的总数。
Version3:
代码:
class StockFactory : boost::noncopyable { public: shared_ptr<Stock> get(const string& key); private: mutable MutexLock mutex_; std::map<string, weak_ptr<Stock>> stocks_; void deleteStock(Stock* stock) { if (stock) { MutexLockGuard lock(mutex_); stocks_.erase(stock->key()); } delete stock; } }; shared_ptr<Stock> StockFactory::get(const string& key) { shared_ptr<Stock> pStock; MutexLockGuard lock(mutex_); weak_ptr<Stock>& wStock = stocks_[key]; pStock = wStock.lock(); if (!pStock) { pStock.reset(new Stock(key), [this](auto stock) { deleteStock(stock); }); wStock = pStock; } return pStock; }
问题:
出现了线程不安全的问题,this指针被传入lambda的deleteStock中,若StockFactory先于Stock析构,将core dump。
Version4:
代码:
class StockFactory : boost::noncopyable, public enable_shared_from_this<StockFactory> { public: shared_ptr<Stock> get(const string& key); private: mutable MutexLock mutex_; std::map<string, weak_ptr<Stock>> stocks_; void deleteStock(Stock* stock) { if (stock) { MutexLockGuard lock(mutex_); stocks_.erase(stock->key()); } delete stock; } }; shared_ptr<Stock> StockFactory::get(const string& key) { shared_ptr<Stock> pStock; MutexLockGuard lock(mutex_); weak_ptr<Stock>& wStock = stocks_[key]; pStock = wStock.lock(); if (!pStock) { pStock.reset(new Stock(key), [shared_from_this()](auto stock) { deleteStock(stock); }); wStock = pStock; } return pStock; }
问题:
虽然能够保证在调用deleteStock时,StockFactory对象仍然“存活”,但是shared_from_this()使得StockFactory对象的声明周期被延长了。
Version5:
代码:
class StockFactory : boost::noncopyable, public enable_shared_from_this<StockFactory> { public: shared_ptr<Stock> get(const string& key); private: mutable MutexLock mutex_; std::map<string, weak_ptr<Stock>> stocks_; void deleteStock(const weak_ptr<StockFactory>& wFactory, Stock* stock) { shared_ptr<StockFactory> factory(wFactory.lock()); if (factory) { if (stock) { MutexLockGuard lock(mutex_); stocks_.erase(stock->key()); } } delete stock; } }; shared_ptr<Stock> StockFactory::get(const string& key) { shared_ptr<Stock> pStock; MutexLockGuard lock(mutex_); weak_ptr<Stock>& wStock = stocks_[key]; pStock = wStock.lock(); if (!pStock) { pStock.reset(new Stock(key), [=](auto stock) { deleteStock(weak_ptr<StockFactory>(shared_from_this()), stock); }); wStock = pStock; } return pStock; }

更多精彩