hobjectpool.h 4.2 KB

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