|
|
@@ -6,29 +6,44 @@
|
|
|
#include <mutex>
|
|
|
#include <condition_variable>
|
|
|
|
|
|
-#define DEFAULT_OBJECT_POOL_SIZE 4
|
|
|
-#define DEFAULT_GET_TIMEOUT 3000 // ms
|
|
|
+#define DEFAULT_OBJECT_POOL_INIT_NUM 0
|
|
|
+#define DEFAULT_OBJECT_POOL_MAX_NUM 4
|
|
|
+#define DEFAULT_OBJECT_POOL_TIMEOUT 3000 // ms
|
|
|
|
|
|
-template<typename T>
|
|
|
-class HObjectPool {
|
|
|
+template<class T>
|
|
|
+class HObjectFactory {
|
|
|
public:
|
|
|
- HObjectPool(int size = DEFAULT_OBJECT_POOL_SIZE)
|
|
|
- : pool_size(size), timeout(DEFAULT_GET_TIMEOUT), object_num(0) {
|
|
|
+ static T* create() {
|
|
|
+ return new T;
|
|
|
}
|
|
|
+};
|
|
|
|
|
|
- ~HObjectPool() {
|
|
|
+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();
|
|
|
}
|
|
|
|
|
|
- virtual bool CreateObject(std::shared_ptr<T>& pObj) {
|
|
|
- pObj = std::shared_ptr<T>(new T);
|
|
|
- return true;
|
|
|
- }
|
|
|
+ ~HObjectPool() {}
|
|
|
|
|
|
- virtual bool InitObject(std::shared_ptr<T>& pObj) {
|
|
|
- return true;
|
|
|
- }
|
|
|
+ int ObjectNum() { return _object_num; }
|
|
|
+ int IdleNum() { return objects_.size(); }
|
|
|
+ int BorrowNum() { return ObjectNum() - IdleNum(); }
|
|
|
|
|
|
- std::shared_ptr<T> TryGet() {
|
|
|
+ std::shared_ptr<T> TryBorrow() {
|
|
|
std::shared_ptr<T> pObj = NULL;
|
|
|
std::lock_guard<std::mutex> locker(mutex_);
|
|
|
if (!objects_.empty()) {
|
|
|
@@ -38,22 +53,25 @@ public:
|
|
|
return pObj;
|
|
|
}
|
|
|
|
|
|
- std::shared_ptr<T> Get() {
|
|
|
- std::shared_ptr<T> pObj = TryGet();
|
|
|
+ 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 < pool_size) {
|
|
|
- if (CreateObject(pObj) && InitObject(pObj)) {
|
|
|
- ++object_num;
|
|
|
- return pObj;
|
|
|
- }
|
|
|
+ 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 (_timeout > 0) {
|
|
|
+ std::cv_status status = cond_.wait_for(locker, std::chrono::milliseconds(_timeout));
|
|
|
if (status == std::cv_status::timeout) {
|
|
|
return NULL;
|
|
|
}
|
|
|
@@ -63,24 +81,26 @@ public:
|
|
|
return pObj;
|
|
|
}
|
|
|
else {
|
|
|
- // WARN: objects too little
|
|
|
+ // WARN: No idle object
|
|
|
}
|
|
|
}
|
|
|
return pObj;
|
|
|
}
|
|
|
|
|
|
- void Release(std::shared_ptr<T>& 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 >= pool_size) {
|
|
|
+ if (_object_num >= _max_num) {
|
|
|
return false;
|
|
|
}
|
|
|
objects_.push_back(pObj);
|
|
|
- ++object_num;
|
|
|
+ ++_object_num;
|
|
|
cond_.notify_one();
|
|
|
return true;
|
|
|
}
|
|
|
@@ -91,25 +111,67 @@ public:
|
|
|
while (iter != objects_.end()) {
|
|
|
if (*iter == pObj) {
|
|
|
iter = objects_.erase(iter);
|
|
|
- --object_num;
|
|
|
+ --_object_num;
|
|
|
return true;
|
|
|
}
|
|
|
+ else {
|
|
|
+ ++iter;
|
|
|
+ }
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- void RemoveAll() {
|
|
|
+ void Clear() {
|
|
|
std::lock_guard<std::mutex> locker(mutex_);
|
|
|
objects_.clear();
|
|
|
+ _object_num = 0;
|
|
|
}
|
|
|
|
|
|
- int pool_size;
|
|
|
- int timeout;
|
|
|
+ int _object_num;
|
|
|
+ int _max_num;
|
|
|
+ int _timeout;
|
|
|
private:
|
|
|
- int object_num;
|
|
|
std::list<std::shared_ptr<T>> objects_;
|
|
|
std::mutex mutex_;
|
|
|
std::condition_variable cond_;
|
|
|
};
|
|
|
|
|
|
+template <typename T>
|
|
|
+class HPoolObject {
|
|
|
+public:
|
|
|
+ HPoolObject(HObjectPool<T>& 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:
|
|
|
+ HObjectPool<T>& pool_;
|
|
|
+ std::shared_ptr<T> sptr_;
|
|
|
+};
|
|
|
+
|
|
|
#endif // HV_OBJECT_POOL_H_
|