#include <iostream>
#include <list>
#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include "boost/noncopyable.hpp"
template<class T>
class SharedAllocator {
public:
static T *create() {
T *ptr = nullptr;
try {
ptr = new T;
}
catch (std::exception &e) {
std::cerr << e.what() << std::endl;
return nullptr;
}
return ptr;
}
static void destory(T *ptr) {
if (nullptr != ptr) {
delete ptr;
}
}
};
template<class T, class UserAllocator = SharedAllocator<T>>
class SharedPool : public boost::noncopyable {
public:
SharedPool() {
max_idle_count_ = 3;
max_count_ = 5;
used_objects_count_ = 0;
waited_threads_count_ = 0;
}
inline unsigned get_used_objects_count() const {
std::lock_guard<std::mutex>lk(lock_);
return used_objects_count_;
}
inline unsigned get_idle_count() const {
std::lock_guard<std::mutex>lk(lock_);
return free_objects_.size();
}
inline unsigned get_waited_threads_count() const {
std::lock_guard<std::mutex>lk(lock_);
return waited_threads_count_;
}
inline void set_max_idle_count(int max_idle_count) {
std::lock_guard<std::mutex>lk(lock_);
max_idle_count_ = max_idle_count;
}
inline void set_max_count(int max_count) {
std::lock_guard<std::mutex>lk(lock_);
max_count_ = max_count;
}
std::shared_ptr<T> get_object() {
std::unique_lock<std::mutex>lk(lock_);
if (true == free_objects_.empty() && used_objects_count_ >= max_count_) {
std::cerr << "no object must waiting." << std::endl;
++waited_threads_count_;
condition_.wait(lk, [&] {
return false == free_objects_.empty() || used_objects_count_ < max_count_;
});
--waited_threads_count_;
}
T *value = nullptr;
if (false == free_objects_.empty()) {
value = free_objects_.front();
free_objects_.pop_front();
}
else if (used_objects_count_ < max_count_) {
value = UserAllocator::create();
if (nullptr != value) {
++used_objects_count_;
}
}
if (nullptr == value) {
std::cerr << __func__ << "cannot get object." << std::endl;
return nullptr;
}
auto shareObject = std::shared_ptr<T>(value, std::bind(&SharedPool<T>::return_object, this, std::placeholders::_1));
return shareObject;
}
void return_object(T *obj) {
std::cout << "function = " << __func__ << " return object address = " << obj << std::endl;
std::lock_guard<std::mutex>lk(lock_);
if (free_objects_.size() >= max_idle_count_ && 0 == waited_threads_count_) {
UserAllocator::destory(obj);
--used_objects_count_;
return;
}
free_objects_.emplace_back(obj);
if (waited_threads_count_ > 0) {
condition_.notify_one();
}
}
private:
unsigned max_idle_count_;
unsigned max_count_;
std::list<T *>free_objects_;
unsigned used_objects_count_;
unsigned waited_threads_count_;
std::mutex lock_;
std::condition_variable condition_;
};
class Test {
public:
Test() {
std::cout << "I am test." << std::endl;
}
};
int main() {
SharedPool<Test>pool;
auto ptr = pool.get_object();
return 0;
}