diff --git a/pool.hpp b/pool.hpp index ac9c3fdb69ef9710b7c87daee39694fed0c964e4..13c208ae188b3163edeca19b838524f717dc86b0 100644 --- a/pool.hpp +++ b/pool.hpp @@ -74,26 +74,21 @@ namespace rlib { // } // } - // `new` an object. Return nullptr if pool is full. + // "get" an object to use. Return nullptr if pool is full. + // try_borrow_one might fail and return nullptr, but it does not block. + // borrow_one might wait for a long time, but it always success. obj_t *try_borrow_one() { - std::lock_guard<std::mutex> _l(buffer_mutex); return do_try_borrow_one(); } obj_t *borrow_one() { - auto result = try_borrow_one(); - if(result) - return result; - // Not available. Wait for release_one. - std::unique_lock<std::mutex> lk(buffer_mutex); - - // wait for a release - borrow_cv.wait(lk, [this]{return this->new_obj_ready;}); + while(true) { + auto result = try_borrow_one(); + if(result) + return result; - result = do_try_borrow_one(); - lk.unlock(); - if(!result) - throw std::logic_error("unknown par error."); - return result; + // wait for a release + borrow_cv.wait(lk, [this]{return this->new_obj_ready;}); + } } void release_one(obj_t *which) { { @@ -107,6 +102,7 @@ namespace rlib { borrow_cv.notify_one(); } + // manually call constructor of this object again. void reconstruct_one(obj_t *which) { reconstruct_impl(which, std::make_index_sequence<sizeof...(_bound_construct_args_t)>()); } @@ -122,7 +118,7 @@ namespace rlib { protected: buffer_t buffer; // list<obj_t obj, bool is_free> private: - std::list<obj_t *> free_list; + std::list<obj_t *> free_list; // for speedup std::mutex buffer_mutex; // mutex for buffer and free_list std::tuple<_bound_construct_args_t ...> _bound_args; @@ -130,8 +126,8 @@ namespace rlib { size_t inuse_objects = 0; const policy_t policy; std::condition_variable borrow_cv; // use buffer_mutex on notifying alloc event. - volatile bool new_obj_ready = false; - void notify_new_object_allocated(size_t how_many) { + std::atomic<bool> new_obj_ready = false; + void notify_new_object_available(size_t how_many) { new_obj_ready = true; for(auto cter = 0; cter < how_many; ++cter) borrow_cv.notify_one(); @@ -140,7 +136,7 @@ namespace rlib { // try_borrow_one without lock. obj_t *do_try_borrow_one() { // Optimize here if is performance bottleneck (lockless list... etc...) - // NOT THREAD SAFE. USE buffer_mutex. + std::lock_guard<std::mutex> _l(buffer_mutex); if(policy.borrow_should_alloc()) { new_obj_to_buffer(); free_list.push_back(&*--buffer.end());