[TOC] # 源码实现 ``` #ifndef OBJECT_POOL_HPP #define OBJECT_POOL_HPP // Author:Simon // Email :476941913@qq.com #include <map> #include <mutex> #include <memory> namespace pool { class noncopyable { protected: noncopyable() {} ~noncopyable() {} private: noncopyable(const noncopyable&); const noncopyable& operator=(const noncopyable&); }; template<typename Key,typename Object> class ObjectPool final :public std::enable_shared_from_this<ObjectPool<Key,Object>>, public noncopyable { typedef ObjectPool<Key, Object> self; public: typedef std::shared_ptr<self> spointer; typedef std::weak_ptr<self> wpointer; private: ObjectPool() {}; ObjectPool(const self &o) = delete; ~ObjectPool() = delete; self& operator=(const self &o) = delete; static void destory(self *o) { } static void weakDestoryCallback(const wpointer& instance, Object *obj) { spointer objectpool(instance.lock()); if (objectpool) if (obj) { { std::unique_lock<std::mutex> lck(objectMutex); objects_.erase(obj->key()); cout << "in deleting key:" << obj->key() << "\n"; } } delete obj; } public: static spointer getInstance() { { std::unique_lock<std::mutex> lck(instanceMutex); if (instance == nullptr) { instance = spointer( new self(), destory ); } } return instance; } std::shared_ptr<Object> getObject(const Key& key) { std::shared_ptr<Object> sObj; { std::unique_lock<std::mutex> lck(objectMutex); std::weak_ptr<Object> &wObj = objects_[key]; sObj = wObj.lock(); if (!sObj) { sObj.reset( new Object(key), std::bind(&self::weakDestoryCallback, std::weak_ptr<self>(shared_from_this()), std::placeholders::_1) ); wObj = sObj; } return sObj; } } private: static std::mutex instanceMutex; static std::mutex objectMutex; static spointer instance; static std::map<Key, std::weak_ptr<Object>> objects_; }; template<typename Key, typename Object> std::mutex ObjectPool<Key, Object>::instanceMutex; template<typename Key, typename Object> std::mutex ObjectPool<Key, Object>::objectMutex; template<typename Key, typename Object> typename std::shared_ptr<ObjectPool<Key, Object>> ObjectPool<Key, Object>::instance = nullptr; template<typename Key, typename Object> std::map<Key, std::weak_ptr<Object>> ObjectPool<Key, Object>::objects_; } #endif ``` #代码解析 如果同一个对象被多个地方使用,那些这些对象应该是共享的,如果对象没有使用,那么他应该是需要析构,这似乎像极了智能指针的行为。 - noncopyable,继承该类的子类,都是不允许使用拷贝,赋值操作。 - 类静态成员需要在类外部声明后使用。 - 对象池为单例模式 - getInstance函数就是获得单例示例的函数,该函数需要加锁。 - 返回的单例为shared_ptr<factory>,所以创建单例shared_ptr<factory>时,需要`静态的`deleter仿函数去手动销毁ptr(虚构函数私有化了)。 - 产生对象 - 根据key判断map有无该对象,如果有,直接返回,如果没有直接新建一个。 - 当第三方调用虚构object后,对象池中的map::size()依然是曾经object的总数,发生内存泄露,所以我们需要在new object的时候,手动利用shared_ptr的定制虚构功能,在创建shared_ptr的时候,提供一个`静态的weakDestoryCallback`,做法如下: - 使用std::bind将自定义虚构和this指针绑定,为了能够使用shared_ptr的this,objectpool需要继承自enable_shared_from_this,然后shared_from_this()就是this的智能指针,另外一点:由于bind拷贝的是是参类型,不是形参类型,所以shared_from_this需要转型为std::weak_ptr,才不会延长生命周期 > 其他c++11/14细节在其他博客有说明:[Simon 's Blog](http://blog.leanote.com/simon88) # 测试函数 ``` void testObjectPool() { typename pool::ObjectPool<int,demo>::spointer factory = pool::ObjectPool<int, demo>::getInstance(); std::vector<std::shared_ptr<demo>> v; for (int i = 0; i < 32; i++) { v.push_back(factory->getObject(i)); } std::for_each(v.begin(), v.end(), [](const std::shared_ptr<demo>& d) {std::cout << "key:" << d->key() << std::endl; }); for (int i = 0; i < 32; i++) { v.at(i).~shared_ptr(); } } ```