hobjectpool.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #ifndef HV_OBJECT_POOL_H_
  2. #define HV_OBJECT_POOL_H_
  3. /*
  4. * @usage unittest/objectpool_test.cpp
  5. */
  6. #include <list>
  7. #include <memory>
  8. #include <mutex>
  9. #include <condition_variable>
  10. #define DEFAULT_OBJECT_POOL_INIT_NUM 0
  11. #define DEFAULT_OBJECT_POOL_MAX_NUM 4
  12. #define DEFAULT_OBJECT_POOL_TIMEOUT 3000 // ms
  13. template<class T>
  14. class HObjectFactory {
  15. public:
  16. static T* create() {
  17. return new T;
  18. }
  19. };
  20. template<class T, class TFactory = HObjectFactory<T>>
  21. class HObjectPool {
  22. public:
  23. HObjectPool(
  24. int init_num = DEFAULT_OBJECT_POOL_INIT_NUM,
  25. int max_num = DEFAULT_OBJECT_POOL_MAX_NUM,
  26. int timeout = DEFAULT_OBJECT_POOL_TIMEOUT)
  27. : _max_num(max_num)
  28. , _timeout(timeout)
  29. {
  30. for (int i = 0; i < init_num; ++i) {
  31. T* p = TFactory::create();
  32. if (p) {
  33. objects_.push_back(std::shared_ptr<T>(p));
  34. }
  35. }
  36. _object_num = objects_.size();
  37. }
  38. ~HObjectPool() {}
  39. int ObjectNum() { return _object_num; }
  40. int IdleNum() { return objects_.size(); }
  41. int BorrowNum() { return ObjectNum() - IdleNum(); }
  42. std::shared_ptr<T> TryBorrow() {
  43. std::shared_ptr<T> pObj = NULL;
  44. std::lock_guard<std::mutex> locker(mutex_);
  45. if (!objects_.empty()) {
  46. pObj = objects_.front();
  47. objects_.pop_front();
  48. }
  49. return pObj;
  50. }
  51. std::shared_ptr<T> Borrow() {
  52. std::shared_ptr<T> pObj = TryBorrow();
  53. if (pObj) {
  54. return pObj;
  55. }
  56. std::unique_lock<std::mutex> locker(mutex_);
  57. if (_object_num < _max_num) {
  58. ++_object_num;
  59. // NOTE: unlock to avoid TFactory::create block
  60. mutex_.unlock();
  61. T* p = TFactory::create();
  62. mutex_.lock();
  63. if (!p) --_object_num;
  64. return std::shared_ptr<T>(p);
  65. }
  66. if (_timeout > 0) {
  67. std::cv_status status = cond_.wait_for(locker, std::chrono::milliseconds(_timeout));
  68. if (status == std::cv_status::timeout) {
  69. return NULL;
  70. }
  71. if (!objects_.empty()) {
  72. pObj = objects_.front();
  73. objects_.pop_front();
  74. return pObj;
  75. }
  76. else {
  77. // WARN: No idle object
  78. }
  79. }
  80. return pObj;
  81. }
  82. void Return(std::shared_ptr<T>& pObj) {
  83. if (!pObj) return;
  84. std::lock_guard<std::mutex> locker(mutex_);
  85. objects_.push_back(pObj);
  86. cond_.notify_one();
  87. }
  88. bool Add(std::shared_ptr<T>& pObj) {
  89. std::lock_guard<std::mutex> locker(mutex_);
  90. if (_object_num >= _max_num) {
  91. return false;
  92. }
  93. objects_.push_back(pObj);
  94. ++_object_num;
  95. cond_.notify_one();
  96. return true;
  97. }
  98. bool Remove(std::shared_ptr<T>& pObj) {
  99. std::lock_guard<std::mutex> locker(mutex_);
  100. auto iter = objects_.begin();
  101. while (iter != objects_.end()) {
  102. if (*iter == pObj) {
  103. iter = objects_.erase(iter);
  104. --_object_num;
  105. return true;
  106. }
  107. else {
  108. ++iter;
  109. }
  110. }
  111. return false;
  112. }
  113. void Clear() {
  114. std::lock_guard<std::mutex> locker(mutex_);
  115. objects_.clear();
  116. _object_num = 0;
  117. }
  118. int _object_num;
  119. int _max_num;
  120. int _timeout;
  121. private:
  122. std::list<std::shared_ptr<T>> objects_;
  123. std::mutex mutex_;
  124. std::condition_variable cond_;
  125. };
  126. template<class T, class TFactory = HObjectFactory<T>>
  127. class HPoolObject {
  128. public:
  129. typedef HObjectPool<T, TFactory> PoolType;
  130. HPoolObject(PoolType& pool) : pool_(pool)
  131. {
  132. sptr_ = pool_.Borrow();
  133. }
  134. ~HPoolObject() {
  135. if (sptr_) {
  136. pool_.Return(sptr_);
  137. }
  138. }
  139. HPoolObject(const HPoolObject<T>&) = delete;
  140. HPoolObject<T>& operator=(const HPoolObject<T>&) = delete;
  141. T* get() {
  142. return sptr_.get();
  143. }
  144. operator bool() {
  145. return sptr_.get() != NULL;
  146. }
  147. T* operator->() {
  148. return sptr_.get();
  149. }
  150. T operator*() {
  151. return *sptr_.get();
  152. }
  153. private:
  154. PoolType& pool_;
  155. std::shared_ptr<T> sptr_;
  156. };
  157. #endif // HV_OBJECT_POOL_H_