/* * Copyright (c) 2016 The ZLToolKit project authors. All Rights Reserved. * * This file is part of ZLToolKit(https://github.com/ZLMediaKit/ZLToolKit). * * Use of this source code is governed by MIT license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ #ifndef UTIL_RECYCLEPOOL_H_ #define UTIL_RECYCLEPOOL_H_ #include "List.h" #include #include #include #include #include #include namespace toolkit { #if (defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 9))) || defined(__clang__) \ || !defined(__GNUC__) #define SUPPORT_DYNAMIC_TEMPLATE #endif template class ResourcePool_l; template class ResourcePool; template class shared_ptr_imp : public std::shared_ptr { public: shared_ptr_imp() {} /** * 构造智能指针 * @param ptr 裸指针 * @param weakPool 管理本指针的循环池 * @param quit 对接是否放弃循环使用 */ shared_ptr_imp( C *ptr, const std::weak_ptr> &weakPool, std::shared_ptr quit, const std::function &on_recycle); /** * 放弃或恢复回到循环池继续使用 * @param flag */ void quit(bool flag = true) { if (_quit) { *_quit = flag; } } private: std::shared_ptr _quit; }; template class ResourcePool_l : public std::enable_shared_from_this> { public: using ValuePtr = shared_ptr_imp; friend class shared_ptr_imp; friend class ResourcePool; ResourcePool_l() { _alloc = []() -> C * { return new C(); }; } #if defined(SUPPORT_DYNAMIC_TEMPLATE) template ResourcePool_l(ArgTypes &&...args) { _alloc = [args...]() -> C * { return new C(args...); }; } #endif // defined(SUPPORT_DYNAMIC_TEMPLATE) ~ResourcePool_l() { for (auto ptr : _objs) { delete ptr; } } void setSize(size_t size) { _pool_size = size; _objs.reserve(size); } ValuePtr obtain(const std::function &on_recycle = nullptr) { return ValuePtr(getPtr(), _weak_self, std::make_shared(false), on_recycle); } std::shared_ptr obtain2() { auto weak_self = _weak_self; return std::shared_ptr(getPtr(), [weak_self](C *ptr) { auto strongPool = weak_self.lock(); if (strongPool) { //放入循环池 strongPool->recycle(ptr); } else { delete ptr; } }); } private: void recycle(C *obj) { auto is_busy = _busy.test_and_set(); if (!is_busy) { //获取到锁 if (_objs.size() >= _pool_size) { delete obj; } else { _objs.emplace_back(obj); } _busy.clear(); } else { //未获取到锁 delete obj; } } C *getPtr() { C *ptr; auto is_busy = _busy.test_and_set(); if (!is_busy) { //获取到锁 if (_objs.size() == 0) { ptr = _alloc(); } else { ptr = _objs.back(); _objs.pop_back(); } _busy.clear(); } else { //未获取到锁 ptr = _alloc(); } return ptr; } void setup() { _weak_self = this->shared_from_this(); } private: size_t _pool_size = 8; std::vector _objs; std::function _alloc; std::atomic_flag _busy { false }; std::weak_ptr _weak_self; }; /** * 循环池,注意,循环池里面的对象不能继承enable_shared_from_this! * @tparam C */ template class ResourcePool { public: using ValuePtr = shared_ptr_imp; ResourcePool() { pool.reset(new ResourcePool_l()); pool->setup(); } #if defined(SUPPORT_DYNAMIC_TEMPLATE) template ResourcePool(ArgTypes &&...args) { pool = std::make_shared>(std::forward(args)...); pool->setup(); } #endif // defined(SUPPORT_DYNAMIC_TEMPLATE) void setSize(size_t size) { pool->setSize(size); } //获取一个对象,性能差些,但是功能丰富些 ValuePtr obtain(const std::function &on_recycle = nullptr) { return pool->obtain(on_recycle); } //获取一个对象,性能好些 std::shared_ptr obtain2() { return pool->obtain2(); } private: std::shared_ptr> pool; }; template shared_ptr_imp::shared_ptr_imp(C *ptr, const std::weak_ptr > &weakPool, std::shared_ptr quit, const std::function &on_recycle) : std::shared_ptr(ptr, [weakPool, quit, on_recycle](C *ptr) { if (on_recycle) { on_recycle(ptr); } auto strongPool = weakPool.lock(); if (strongPool && !(*quit)) { //循环池还在并且不放弃放入循环池 strongPool->recycle(ptr); } else { delete ptr; } }), _quit(std::move(quit)) {} } /* namespace toolkit */ #endif /* UTIL_RECYCLEPOOL_H_ */