Linux多线程服务端编程对象池问题思考
几个知识点的思考
在陈硕所注的Linux多线程服务端编程中,有点小困惑,写下来给以后看看。理解可能有误:
代码如下:
class StockFactory : boost::noncopyable
{
public:
boost::shared_ptr<Stock> get(const string& key)
{
boost::shared_ptr<Stock> pStock;
muduo::MutexLockGuard lock(mutex_);
boost::weak_ptr<Stock>& wkStock = stocks_[key];//在STL源码中,Map::operator[]()中调用了insert_equal(),这个函数直接调用了红黑树的insert()接口。
pStock = wkStock.lock();
if (!pStock)
{
pStock.reset(new Stock(key),
boost::bind(&StockFactory::deleteStock, this, _1)); //为什么会绑定this指针?
wkStock = pStock;
}
return pStock;
}
private:
void deleteStock(Stock* stock) //在shared_ptr<Stock>对象析构时会被调用,如何制定Stock指针?
{
printf("deleteStock[%p]\n", stock);
if (stock)
{
muduo::MutexLockGuard lock(mutex_);
stocks_.erase(stock->key()); // This is wrong, see removeStock below for correct implementation.
}//此处无法保证stocks(StockFactory对象)依然存活
delete stock; // sorry, I lied
}
mutable muduo::MutexLock mutex_;
std::map<string, boost::weak_ptr<Stock> > stocks_;
};
在此困惑我的几个点如下:
1.
pStock.reset(new Stock(key),
boost::bind(&StockFactory::deleteStock, this, _1)); //为什么会绑定this指针?
为什么绑定this指针?
很明显,deleteStock作为一个成员函数,在编译器扩充期间,会添加第一个参数StockFactory * this,指向当前StockFactory对象。其中,sotcks.erase(stock->key());.会被填充位StockFactory.stocks.erase(stock->key());
注:在C++对象模型中,对普通成员函数取地址返回的是函数的真实地址,对虚函数取地址操作返回的是vtable的索引值。
2.
void deleteStock(Stock* stock) //在shared_ptr<Stock>对象析构时会被调用,如何指定Stock指针?
通过boost::bind将this绑定到deleteStock后,返回一个boost::function对象,此时相当于
void deleteStock(this, stock)
比较困惑的是形参Stock* stock在调用的时候赋予了什么值,因为,我并未分析过std::tr1::share_ptr的源码,此时唯一能考虑到的就是在调用的时候Share_ptr对象赋予此为Share_ptr所管理的指针share_ptr::stock(本质上不可访问,为private)。
3.此处为我最为困惑的点:
deleteStock(Stock *stock)调用的时机是什么?
一开始我考虑时机为在share_ptr析构函数中直接调用,这是说不通的,如果share_ptr维护的指针指向一个Map节点,若指针不为空,直接删除Stock对象,说不通。
真相应该在引用计数为0之后。
deleteStock(Stock stock)成员函数,将stock所指的Stock对象从Map底层的红黑树上移除,并将stock对象空间释放还给自由存储区,唯一比较合理的解释是:在判定引用计数为0后:
user_count--;
if(user_count == 0)
deleteStock(stock);