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());