标签:
对象池模型创建并拥有固定数量的对象,当程序需要一个新的对象时,如果对象池中有空闲对象,则立即返回,否则才创建新的该类对象。当一个对象不再被使用时,其应该应该将其放回对象池,以便后来的程序使用。由于系统资源有限,一个对象池模型应该指定其可容纳的最大对象数量。当达到该数量时,如果仍然有对象创建请求,则抛出异常或者阻塞当前调用线程,直到一个对象被放回对象池中。
(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。
// object_pool.cc
#include <map>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <stdio.h>
using std::string;
const int MAXNUM = 5; // the largest amounts of objects
int nums = 0; // the current amounts of objects
class Object
{
public:
Object(const string& name) : name_(name)
{
printf("Construct Object[%p] %s.\n", this, name_.c_str());
}
~Object()
{
printf("~Destruct Object[%p] %s.\n", this, name_.c_str());
}
const string& key() const { return name_; }
private:
string name_;
};
namespace version1
{
class ObjectPool
{
public:
boost::shared_ptr<Object> get(const string& key)
{
boost::shared_ptr<Object> pObject;
boost::weak_ptr<Object>& k_object = objects_[key];
pObject = k_object.lock();
if (!pObject)
{
++nums;
BOOST_ASSERT(nums <= MAXNUM);
pObject.reset(new Object(key),
boost::bind(&ObjectPool::releaseObject, this, _1));
k_object = pObject;
}
return pObject;
}
private:
void releaseObject(Object* object)
{
printf("releaseObject[%p].\n", object);
if (object)
{
--nums;
objects_.erase(object->key());
}
delete object;
}
std::map<string, boost::weak_ptr<Object> > objects_;
};
}
namespace version2
{
class ObjectPool : public boost::enable_shared_from_this<ObjectPool>
{
public:
boost::shared_ptr<Object> get(const string& key)
{
boost::shared_ptr<Object> pObject;
boost::weak_ptr<Object>& k_object = objects_[key];
pObject = k_object.lock();
if (!pObject)
{
++nums;
BOOST_ASSERT(nums <= MAXNUM);
pObject.reset(new Object(key),
boost::bind(&ObjectPool::releaseObject, shared_from_this(), _1));
k_object = pObject;
}
return pObject;
}
private:
void releaseObject(Object* object)
{
printf("releaseObject[%p].\n", object);
if (object)
{
--nums;
objects_.erase(object->key());
}
delete object;
}
std::map<string, boost::weak_ptr<Object> > objects_;
};
}
int main()
{
boost::shared_ptr<version1::ObjectPool> op1(new version1::ObjectPool);
boost::shared_ptr<Object> object1 = op1->get("object1");
boost::shared_ptr<Object> object2 = op1->get("object2");
boost::shared_ptr<Object> object3 = op1->get("object3");
boost::shared_ptr<Object> object4 = op1->get("object4");
boost::shared_ptr<Object> object5 = op1->get("object5");
boost::shared_ptr<Object> object6 = op1->get("object5");
//boost::shared_ptr<version2::ObjectPool> op2(new version2::ObjectPool);
//boost::shared_ptr<Object> object7 = op2->get("object2");
//boost::shared_ptr<Object> object8 = op2->get("object2");
return 0;
}
// output
Construct Object[003e1060] object1.
Construct Object[003e10e0] object2.
Construct Object[003e1160] object3.
Construct Object[003e11e0] object4.
Construct Object[003e1260] object5.
releaseObject[003e1260].
~Destruct Object[003e1260] object5.
releaseObject[003e11e0].
~Destruct Object[003e11e0] object4.
releaseObject[003e1160].
~Destruct Object[003e1160] object3.
releaseObject[003e10e0].
~Destruct Object[003e10e0] object2.
releaseObject[003e1060].
~Destruct Object[003e1060] object1.
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.\n", this, name_.c_str());
21 }
22
23 ~Object()
24 {
25 printf("~Destruct Object[%p] %s.\n", 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].\n", 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].\n", 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.
References
https://en.wikipedia.org/wiki/Object_pool_pattern
标签:
原文地址:http://www.cnblogs.com/Leo_wl/p/4870439.html