zoukankan      html  css  js  c++  java
  • 对象池的设计及其实现

    对象池概述:

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

    对象池模型适用的场景:

    (1)需要使用大量对象

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

     

    对象池优势:

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

     

    实现:

    假设有如下类定义:

     1 class Object
     2 {
     3 public:
     4     Object(const string& name) : name_(name)
     5     {
     6         printf("Construct Object[%p] %s.
    ", this, name_.c_str());
     7     }
     8 
     9     ~Object()
    10     {
    11         printf("~Destruct Object[%p] %s.
    ", 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].
    ", 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].
    ", 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。

    测试用例: 

      1 // object_pool.cc
      2 #include <map>
      3 
      4 #include <boost/bind.hpp>
      5 #include <boost/enable_shared_from_this.hpp>
      6 #include <boost/shared_ptr.hpp>
      7 #include <boost/weak_ptr.hpp>
      8 
      9 #include <stdio.h>
     10 
     11 using std::string;
     12 const int MAXNUM = 5;  // the largest amounts of objects
     13 int nums = 0;          // the current amounts of objects
     14 
     15 class Object
     16 {
     17 public:
     18     Object(const string& name) : name_(name)
     19     {
     20         printf("Construct Object[%p] %s.
    ", this, name_.c_str());
     21     }
     22 
     23     ~Object()
     24     {
     25         printf("~Destruct Object[%p] %s.
    ", this, name_.c_str());
     26     }
     27 
     28     const string& key() const { return name_; }
     29 
     30 private:
     31     string name_;
     32 };
     33 
     34 
     35 namespace version1
     36 {
     37 
     38 class ObjectPool
     39 {
     40 public:
     41     boost::shared_ptr<Object> get(const string& key)
     42     {
     43         boost::shared_ptr<Object> pObject;
     44         boost::weak_ptr<Object>& k_object = objects_[key];
     45         pObject = k_object.lock();
     46         if (!pObject)
     47         {
     48             ++nums;
     49             BOOST_ASSERT(nums <= MAXNUM);
     50             pObject.reset(new Object(key),
     51                          boost::bind(&ObjectPool::releaseObject, this, _1));
     52             k_object = pObject;
     53         }
     54         return pObject;
     55   }
     56 
     57 private:
     58     void releaseObject(Object* object)
     59     {
     60         printf("releaseObject[%p].
    ", object);
     61         if (object)
     62         {
     63             --nums;
     64             objects_.erase(object->key());
     65         }
     66         delete object;
     67     }
     68 
     69     std::map<string, boost::weak_ptr<Object> > objects_;
     70 };
     71 
     72 }
     73 
     74 namespace version2
     75 {
     76 
     77 class ObjectPool : public boost::enable_shared_from_this<ObjectPool>
     78 {
     79 public:
     80     boost::shared_ptr<Object> get(const string& key)
     81     {
     82         boost::shared_ptr<Object> pObject;
     83         boost::weak_ptr<Object>& k_object = objects_[key];
     84         pObject = k_object.lock();
     85         if (!pObject)
     86         {
     87             ++nums;
     88             BOOST_ASSERT(nums <= MAXNUM);
     89             pObject.reset(new Object(key),
     90                          boost::bind(&ObjectPool::releaseObject, shared_from_this(), _1));
     91             k_object = pObject;
     92         }
     93         return pObject;
     94   }
     95 
     96 private:
     97     void releaseObject(Object* object)
     98     {
     99         printf("releaseObject[%p].
    ", object);
    100         if (object)
    101         {
    102             --nums;
    103             objects_.erase(object->key());
    104         }
    105         delete object;
    106     }
    107 
    108     std::map<string, boost::weak_ptr<Object> > objects_;
    109 };
    110 
    111 }
    112 
    113 
    114 int main()
    115 {
    116     boost::shared_ptr<version1::ObjectPool> op1(new version1::ObjectPool);
    117 
    118     boost::shared_ptr<Object> object1 = op1->get("object1");
    119     boost::shared_ptr<Object> object2 = op1->get("object2");
    120     boost::shared_ptr<Object> object3 = op1->get("object3");
    121     boost::shared_ptr<Object> object4 = op1->get("object4");
    122     boost::shared_ptr<Object> object5 = op1->get("object5");
    123     boost::shared_ptr<Object> object6 = op1->get("object5");
    124 
    125     //boost::shared_ptr<version2::ObjectPool> op2(new version2::ObjectPool);
    126     //boost::shared_ptr<Object> object7 = op2->get("object2");
    127     //boost::shared_ptr<Object> object8 = op2->get("object2");
    128 
    129     return 0;
    130 }
    131 
    132 // output
    133 Construct Object[003e1060] object1.
    134 Construct Object[003e10e0] object2.
    135 Construct Object[003e1160] object3.
    136 Construct Object[003e11e0] object4.
    137 Construct Object[003e1260] object5.
    138 releaseObject[003e1260].
    139 ~Destruct Object[003e1260] object5.
    140 releaseObject[003e11e0].
    141 ~Destruct Object[003e11e0] object4.
    142 releaseObject[003e1160].
    143 ~Destruct Object[003e1160] object3.
    144 releaseObject[003e10e0].
    145 ~Destruct Object[003e10e0] object2.
    146 releaseObject[003e1060].
    147 ~Destruct Object[003e1060] object1.
    View Code

    References

    https://en.wikipedia.org/wiki/Object_pool_pattern

     

  • 相关阅读:
    OK335x mksd.sh hacking
    Qt jsoncpp 对象拷贝、删除、函数调用 demo
    OK335xS 256M 512M nand flash make ubifs hacking
    Qt QScrollArea and layout in code
    JsonCpp Documentation
    Qt 4.8.5 jsoncpp lib
    Oracle数据库生成UUID
    freemarker得到数组的长度
    FreeMarker中if标签内的判断条件
    freemarker语法
  • 原文地址:https://www.cnblogs.com/benxintuzi/p/4868105.html
Copyright © 2011-2022 走看看