| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- #ifndef HV_OBJECT_POOL_H_
- #define HV_OBJECT_POOL_H_
- /*
- * @usage unittest/objectpool_test.cpp
- */
- #include <list>
- #include <memory>
- #include <mutex>
- #include <condition_variable>
- #define DEFAULT_OBJECT_POOL_INIT_NUM 0
- #define DEFAULT_OBJECT_POOL_MAX_NUM 4
- #define DEFAULT_OBJECT_POOL_TIMEOUT 3000 // ms
- template<class T>
- class HObjectFactory {
- public:
- static T* create() {
- return new T;
- }
- };
- template<class T, class TFactory = HObjectFactory<T>>
- class HObjectPool {
- public:
- HObjectPool(
- int init_num = DEFAULT_OBJECT_POOL_INIT_NUM,
- int max_num = DEFAULT_OBJECT_POOL_MAX_NUM,
- int timeout = DEFAULT_OBJECT_POOL_TIMEOUT)
- : _max_num(max_num)
- , _timeout(timeout)
- {
- for (int i = 0; i < init_num; ++i) {
- T* p = TFactory::create();
- if (p) {
- objects_.push_back(std::shared_ptr<T>(p));
- }
- }
- _object_num = objects_.size();
- }
- ~HObjectPool() {}
- int ObjectNum() { return _object_num; }
- int IdleNum() { return objects_.size(); }
- int BorrowNum() { return ObjectNum() - IdleNum(); }
- std::shared_ptr<T> TryBorrow() {
- std::shared_ptr<T> pObj = NULL;
- std::lock_guard<std::mutex> locker(mutex_);
- if (!objects_.empty()) {
- pObj = objects_.front();
- objects_.pop_front();
- }
- return pObj;
- }
- std::shared_ptr<T> Borrow() {
- std::shared_ptr<T> pObj = TryBorrow();
- if (pObj) {
- return pObj;
- }
- std::unique_lock<std::mutex> locker(mutex_);
- if (_object_num < _max_num) {
- ++_object_num;
- // NOTE: unlock to avoid TFactory::create block
- mutex_.unlock();
- T* p = TFactory::create();
- mutex_.lock();
- if (!p) --_object_num;
- return std::shared_ptr<T>(p);
- }
- if (_timeout > 0) {
- std::cv_status status = cond_.wait_for(locker, std::chrono::milliseconds(_timeout));
- if (status == std::cv_status::timeout) {
- return NULL;
- }
- if (!objects_.empty()) {
- pObj = objects_.front();
- objects_.pop_front();
- return pObj;
- }
- else {
- // WARN: No idle object
- }
- }
- return pObj;
- }
- void Return(std::shared_ptr<T>& pObj) {
- if (!pObj) return;
- std::lock_guard<std::mutex> locker(mutex_);
- objects_.push_back(pObj);
- cond_.notify_one();
- }
- bool Add(std::shared_ptr<T>& pObj) {
- std::lock_guard<std::mutex> locker(mutex_);
- if (_object_num >= _max_num) {
- return false;
- }
- objects_.push_back(pObj);
- ++_object_num;
- cond_.notify_one();
- return true;
- }
- bool Remove(std::shared_ptr<T>& pObj) {
- std::lock_guard<std::mutex> locker(mutex_);
- auto iter = objects_.begin();
- while (iter != objects_.end()) {
- if (*iter == pObj) {
- iter = objects_.erase(iter);
- --_object_num;
- return true;
- }
- else {
- ++iter;
- }
- }
- return false;
- }
- void Clear() {
- std::lock_guard<std::mutex> locker(mutex_);
- objects_.clear();
- _object_num = 0;
- }
- int _object_num;
- int _max_num;
- int _timeout;
- private:
- std::list<std::shared_ptr<T>> objects_;
- std::mutex mutex_;
- std::condition_variable cond_;
- };
- template<class T, class TFactory = HObjectFactory<T>>
- class HPoolObject {
- public:
- typedef HObjectPool<T, TFactory> PoolType;
- HPoolObject(PoolType& pool) : pool_(pool)
- {
- sptr_ = pool_.Borrow();
- }
- ~HPoolObject() {
- if (sptr_) {
- pool_.Return(sptr_);
- }
- }
- HPoolObject(const HPoolObject<T>&) = delete;
- HPoolObject<T>& operator=(const HPoolObject<T>&) = delete;
- T* get() {
- return sptr_.get();
- }
- operator bool() {
- return sptr_.get() != NULL;
- }
- T* operator->() {
- return sptr_.get();
- }
- T operator*() {
- return *sptr_.get();
- }
- private:
- PoolType& pool_;
- std::shared_ptr<T> sptr_;
- };
- #endif // HV_OBJECT_POOL_H_
|