You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

206 lines
5.6KB

  1. /*
  2. * Copyright (c) 2016 The ZLToolKit project authors. All Rights Reserved.
  3. *
  4. * This file is part of ZLToolKit(https://github.com/ZLMediaKit/ZLToolKit).
  5. *
  6. * Use of this source code is governed by MIT license that can be found in the
  7. * LICENSE file in the root of the source tree. All contributing project authors
  8. * may be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #ifndef UTIL_RECYCLEPOOL_H_
  11. #define UTIL_RECYCLEPOOL_H_
  12. #include "List.h"
  13. #include <atomic>
  14. #include <deque>
  15. #include <functional>
  16. #include <memory>
  17. #include <mutex>
  18. #include <unordered_set>
  19. namespace toolkit {
  20. #if (defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 9))) || defined(__clang__) \
  21. || !defined(__GNUC__)
  22. #define SUPPORT_DYNAMIC_TEMPLATE
  23. #endif
  24. template <typename C>
  25. class ResourcePool_l;
  26. template <typename C>
  27. class ResourcePool;
  28. template <typename C>
  29. class shared_ptr_imp : public std::shared_ptr<C> {
  30. public:
  31. shared_ptr_imp() {}
  32. /**
  33. * 构造智能指针
  34. * @param ptr 裸指针
  35. * @param weakPool 管理本指针的循环池
  36. * @param quit 对接是否放弃循环使用
  37. */
  38. shared_ptr_imp(
  39. C *ptr, const std::weak_ptr<ResourcePool_l<C>> &weakPool, std::shared_ptr<std::atomic_bool> quit,
  40. const std::function<void(C *)> &on_recycle);
  41. /**
  42. * 放弃或恢复回到循环池继续使用
  43. * @param flag
  44. */
  45. void quit(bool flag = true) {
  46. if (_quit) {
  47. *_quit = flag;
  48. }
  49. }
  50. private:
  51. std::shared_ptr<std::atomic_bool> _quit;
  52. };
  53. template <typename C>
  54. class ResourcePool_l : public std::enable_shared_from_this<ResourcePool_l<C>> {
  55. public:
  56. using ValuePtr = shared_ptr_imp<C>;
  57. friend class shared_ptr_imp<C>;
  58. friend class ResourcePool<C>;
  59. ResourcePool_l() {
  60. _alloc = []() -> C * { return new C(); };
  61. }
  62. #if defined(SUPPORT_DYNAMIC_TEMPLATE)
  63. template <typename... ArgTypes>
  64. ResourcePool_l(ArgTypes &&...args) {
  65. _alloc = [args...]() -> C * { return new C(args...); };
  66. }
  67. #endif // defined(SUPPORT_DYNAMIC_TEMPLATE)
  68. ~ResourcePool_l() {
  69. for (auto ptr : _objs) {
  70. delete ptr;
  71. }
  72. }
  73. void setSize(size_t size) {
  74. _pool_size = size;
  75. _objs.reserve(size);
  76. }
  77. ValuePtr obtain(const std::function<void(C *)> &on_recycle = nullptr) {
  78. return ValuePtr(getPtr(), _weak_self, std::make_shared<std::atomic_bool>(false), on_recycle);
  79. }
  80. std::shared_ptr<C> obtain2() {
  81. auto weak_self = _weak_self;
  82. return std::shared_ptr<C>(getPtr(), [weak_self](C *ptr) {
  83. auto strongPool = weak_self.lock();
  84. if (strongPool) {
  85. //放入循环池
  86. strongPool->recycle(ptr);
  87. } else {
  88. delete ptr;
  89. }
  90. });
  91. }
  92. private:
  93. void recycle(C *obj) {
  94. auto is_busy = _busy.test_and_set();
  95. if (!is_busy) {
  96. //获取到锁
  97. if (_objs.size() >= _pool_size) {
  98. delete obj;
  99. } else {
  100. _objs.emplace_back(obj);
  101. }
  102. _busy.clear();
  103. } else {
  104. //未获取到锁
  105. delete obj;
  106. }
  107. }
  108. C *getPtr() {
  109. C *ptr;
  110. auto is_busy = _busy.test_and_set();
  111. if (!is_busy) {
  112. //获取到锁
  113. if (_objs.size() == 0) {
  114. ptr = _alloc();
  115. } else {
  116. ptr = _objs.back();
  117. _objs.pop_back();
  118. }
  119. _busy.clear();
  120. } else {
  121. //未获取到锁
  122. ptr = _alloc();
  123. }
  124. return ptr;
  125. }
  126. void setup() { _weak_self = this->shared_from_this(); }
  127. private:
  128. size_t _pool_size = 8;
  129. std::vector<C *> _objs;
  130. std::function<C *(void)> _alloc;
  131. std::atomic_flag _busy { false };
  132. std::weak_ptr<ResourcePool_l> _weak_self;
  133. };
  134. /**
  135. * 循环池,注意,循环池里面的对象不能继承enable_shared_from_this!
  136. * @tparam C
  137. */
  138. template <typename C>
  139. class ResourcePool {
  140. public:
  141. using ValuePtr = shared_ptr_imp<C>;
  142. ResourcePool() {
  143. pool.reset(new ResourcePool_l<C>());
  144. pool->setup();
  145. }
  146. #if defined(SUPPORT_DYNAMIC_TEMPLATE)
  147. template <typename... ArgTypes>
  148. ResourcePool(ArgTypes &&...args) {
  149. pool = std::make_shared<ResourcePool_l<C>>(std::forward<ArgTypes>(args)...);
  150. pool->setup();
  151. }
  152. #endif // defined(SUPPORT_DYNAMIC_TEMPLATE)
  153. void setSize(size_t size) { pool->setSize(size); }
  154. //获取一个对象,性能差些,但是功能丰富些
  155. ValuePtr obtain(const std::function<void(C *)> &on_recycle = nullptr) { return pool->obtain(on_recycle); }
  156. //获取一个对象,性能好些
  157. std::shared_ptr<C> obtain2() { return pool->obtain2(); }
  158. private:
  159. std::shared_ptr<ResourcePool_l<C>> pool;
  160. };
  161. template<typename C>
  162. shared_ptr_imp<C>::shared_ptr_imp(C *ptr,
  163. const std::weak_ptr<ResourcePool_l<C> > &weakPool,
  164. std::shared_ptr<std::atomic_bool> quit,
  165. const std::function<void(C *)> &on_recycle) :
  166. std::shared_ptr<C>(ptr, [weakPool, quit, on_recycle](C *ptr) {
  167. if (on_recycle) {
  168. on_recycle(ptr);
  169. }
  170. auto strongPool = weakPool.lock();
  171. if (strongPool && !(*quit)) {
  172. //循环池还在并且不放弃放入循环池
  173. strongPool->recycle(ptr);
  174. } else {
  175. delete ptr;
  176. }
  177. }), _quit(std::move(quit)) {}
  178. } /* namespace toolkit */
  179. #endif /* UTIL_RECYCLEPOOL_H_ */