ResourcePool.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*
  2. * Copyright (c) 2016 The ZLToolKit project authors. All Rights Reserved.
  3. *
  4. * This file is part of ZLToolKit(https://github.com/xia-chu/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 <mutex>
  13. #include <deque>
  14. #include <memory>
  15. #include <atomic>
  16. #include <functional>
  17. #include <unordered_set>
  18. #include "Util/List.h"
  19. using namespace std;
  20. namespace toolkit {
  21. #if (defined(__GNUC__) && ( __GNUC__ >= 5 || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 9))) || defined(__clang__) || !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(C *ptr,
  39. const std::weak_ptr<ResourcePool_l<C> > &weakPool,
  40. std::shared_ptr<atomic_bool> quit,
  41. const function<void(C *)> &on_recycle);
  42. /**
  43. * 放弃或恢复回到循环池继续使用
  44. * @param flag
  45. */
  46. void quit(bool flag = true){
  47. if(_quit){
  48. *_quit = flag;
  49. }
  50. }
  51. private:
  52. std::shared_ptr<atomic_bool> _quit;
  53. };
  54. template<typename C>
  55. class ResourcePool_l: public enable_shared_from_this<ResourcePool_l<C> > {
  56. public:
  57. typedef shared_ptr_imp<C> ValuePtr;
  58. friend class shared_ptr_imp<C>;
  59. friend class ResourcePool<C>;
  60. ResourcePool_l() {
  61. _allotter = []()->C* {
  62. return new C();
  63. };
  64. }
  65. #if defined(SUPPORT_DYNAMIC_TEMPLATE)
  66. template<typename ...ArgTypes>
  67. ResourcePool_l(ArgTypes &&...args) {
  68. _allotter = [args...]()->C* {
  69. return new C(args...);
  70. };
  71. }
  72. #endif //defined(SUPPORT_DYNAMIC_TEMPLATE)
  73. ~ResourcePool_l(){
  74. _objs.for_each([](C *ptr){
  75. delete ptr;
  76. });
  77. }
  78. void setSize(size_t size) {
  79. _poolsize = size;
  80. }
  81. ValuePtr obtain(const function<void(C *)> &on_recycle = nullptr) {
  82. C *ptr;
  83. auto is_busy = _busy.test_and_set();
  84. if (!is_busy) {
  85. //获取到锁
  86. if (_objs.size() == 0) {
  87. ptr = _allotter();
  88. } else {
  89. ptr = _objs.front();
  90. _objs.pop_front();
  91. }
  92. _busy.clear();
  93. } else {
  94. //未获取到锁
  95. ptr = _allotter();
  96. }
  97. return ValuePtr(ptr, _weak_self, std::make_shared<atomic_bool>(false), on_recycle);
  98. }
  99. private:
  100. void recycle(C *obj) {
  101. auto is_busy = _busy.test_and_set();
  102. if (!is_busy) {
  103. //获取到锁
  104. if (_objs.size() >= _poolsize) {
  105. delete obj;
  106. } else {
  107. _objs.emplace_back(obj);
  108. }
  109. _busy.clear();
  110. } else {
  111. //未获取到锁
  112. delete obj;
  113. }
  114. }
  115. void setup(){
  116. _weak_self = this->shared_from_this();
  117. }
  118. private:
  119. size_t _poolsize = 8;
  120. List<C*> _objs;
  121. function<C*(void)> _allotter;
  122. atomic_flag _busy{false};
  123. weak_ptr<ResourcePool_l > _weak_self;
  124. };
  125. /**
  126. * 循环池,注意,循环池里面的对象不能继承enable_shared_from_this!
  127. * @tparam C
  128. */
  129. template<typename C>
  130. class ResourcePool {
  131. public:
  132. typedef shared_ptr_imp<C> ValuePtr;
  133. ResourcePool() {
  134. pool.reset(new ResourcePool_l<C>());
  135. pool->setup();
  136. }
  137. #if defined(SUPPORT_DYNAMIC_TEMPLATE)
  138. template<typename ...ArgTypes>
  139. ResourcePool(ArgTypes &&...args) {
  140. pool = std::make_shared<ResourcePool_l<C> >(std::forward<ArgTypes>(args)...);
  141. pool->setup();
  142. }
  143. #endif //defined(SUPPORT_DYNAMIC_TEMPLATE)
  144. void setSize(size_t size) {
  145. pool->setSize(size);
  146. }
  147. ValuePtr obtain(const function<void(C *)> &on_recycle = nullptr) {
  148. return pool->obtain(on_recycle);
  149. }
  150. private:
  151. std::shared_ptr<ResourcePool_l<C> > pool;
  152. };
  153. template<typename C>
  154. shared_ptr_imp<C>::shared_ptr_imp(C *ptr,
  155. const std::weak_ptr<ResourcePool_l<C> > &weakPool,
  156. std::shared_ptr<atomic_bool> quit,
  157. const function<void(C *)> &on_recycle) :
  158. shared_ptr<C>(ptr, [weakPool, quit, on_recycle](C *ptr) {
  159. if (on_recycle) {
  160. on_recycle(ptr);
  161. }
  162. auto strongPool = weakPool.lock();
  163. if (strongPool && !(*quit)) {
  164. //循环池还在并且不放弃放入循环池
  165. strongPool->recycle(ptr);
  166. } else {
  167. delete ptr;
  168. }
  169. }), _quit(std::move(quit)) {}
  170. } /* namespace toolkit */
  171. #endif /* UTIL_RECYCLEPOOL_H_ */