对象池的设计及其实现

对象池概述:

对象池模型创建并拥有固定数量的对象,当程序需要一个新的对象时,如果对象池中有空闲对象,则立即返回,否则才创建新的该类对象。当一个对象不再被使用时,其应该应该将其放回对象池,以便后来的程序使用。由于系统资源有限,一个对象池模型应该指定其可容纳的最大对象数量。当达到该数量时,如果仍然有对象创建请求,则抛出异常或者阻塞当前调用线程,直到一个对象被放回对象池中。

 

对象池模型适用的场景:

(1)需要使用大量对象

(2)这些对象的实例化开销比较大且生存期比较短

 

对象池优势:

一个对象池可以在可容忍时间内创建成功并投入使用。但是创建对象时并不总是这样,尤其是当这些对象的创建过程比较耗时,而且创建和销毁频率又比较大时更是如此。比如数据库连接网络套接字连接线程对象、诸如字体或位图等图像对象等。

 

实现:

假设有如下类定义:

复制代码
 1 class Object
 2 {
 3 public:
 4     Object(const string& name) : name_(name)
 5     {
 6         printf("Construct Object[%p] %s.\n", this, name_.c_str());
 7     }
 8 
 9     ~Object()
10     {
11         printf("~Destruct Object[%p] %s.\n", this, name_.c_str());
12     }
13 
14     const string& key() const { return name_; }
15 
16 private:
17     string name_;
18 };
复制代码

如下对象池类的设计,用来提供Object类对象,分为2个版本介绍:(注意,如下仅考虑了对象池本身所涉及的特性,没有涉及同步控制机制)

版本1:

复制代码
 1 class ObjectPool
 2 {
 3 public:
 4     boost::shared_ptr<Object> get(const string& key)
 5     {
 6         boost::shared_ptr<Object> pObject;
 7         boost::weak_ptr<Object>& k_object = objects_[key];
 8         pObject = k_object.lock();
 9         if (!pObject)
10         {
11             pObject.reset(new Object(key),
12                          boost::bind(&ObjectPool::releaseObject, this, _1));
13             k_object = pObject;
14         }
15         return pObject;
16   }
17 
18 private:
19     void releaseObject(Object* object)
20     {
21         printf("releaseObject[%p].\n", object);
22         if (object)
23         {
24             objects_.erase(object->key());
25         }
26         delete object;
27     }
28 
29     std::map<string, boost::weak_ptr<Object> > objects_;
30 };
复制代码

ObjectPool的get函数返回map中key对应的Object对象。如果该对象不存在,则新建一个Object,将其放入map中,然后返回这个新建的Object。同时,重置shared_ptr(新增Object对象)时指定析构器releaseObject,使得对象析构时执行releaseObject(object);

但是上述实现存在一个问题:将this传入bind函数中,如果ObjectPool对象先于Object对象析构了,那么在析构Object对象时,如何调用releaseObject函数呢?(因为releaseObject函数属于ObjectPool类)

版本2:

复制代码
 1 class ObjectPool : public boost::enable_shared_from_this<ObjectPool>
 2 {
 3 public:
 4     boost::shared_ptr<Object> get(const string& key)
 5     {
 6         boost::shared_ptr<Object> pObject;
 7         boost::weak_ptr<Object>& k_object = objects_[key];
 8         pObject = k_object.lock();
 9         if (!pObject)
10         {
11             pObject.reset(new Object(key),
12                          boost::bind(&ObjectPool::releaseObject, shared_from_this(), _1));
13             k_object = pObject;
14         }
15         return pObject;
16   }
17 
18 private:
19     void releaseObject(Object* object)
20     {
21         printf("releaseObject[%p].\n", object);
22         if (object)
23         {
24             objects_.erase(object->key());
25         }
26         delete object;
27     }
28 
29     std::map<string, boost::weak_ptr<Object> > objects_;
30 };
复制代码

要解决版本1中的问题,只需增加ObjectPool的寿命就可以了。可以利用boost::enable_shared_from_this模板类中的shared_from_this(),如此可以将this转换为shared_ptr<ObjectPool>。如此,由于bind是值传递语义,因此其必然保存一份shared_ptr<ObjectPool>的副本,可以保证shared_ptr的引用计数不为0。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值