Added more statistics, improved memory ordering
[libcds.git] / cds / memory / vyukov_queue_pool.h
index c7be7f43273605dadf121021d48f97b97451bb0c..edd75f03a65934269b0cbb641e6dcce766a7f10d 100644 (file)
@@ -15,6 +15,9 @@ namespace cds { namespace memory {
     {
         /// Allocator type
         typedef CDS_DEFAULT_ALLOCATOR allocator;
+
+        /// Back-off stratey
+        typedef cds::backoff::yield   back_off;
     };
 
     /// Free-list based on bounded lock-free queue \p cds::intrusive::VyukovMPMCCycleQueue
@@ -91,6 +94,7 @@ namespace cds { namespace memory {
         typedef T  value_type ; ///< Value type
         typedef Traits traits;  ///< Traits type
         typedef typename traits::allocator::template rebind<value_type>::other allocator_type  ;   ///< allocator type
+        typedef typename traits::back_off back_off; ///< back-off strategy
 
     protected:
         //@cond
@@ -157,7 +161,7 @@ namespace cds { namespace memory {
                 assert( from_pool(p) );
                 return p;
             }
-
+            // The pool is empty - allocate new from the heap
             return cxx_allocator().New();
         }
 
@@ -175,8 +179,13 @@ namespace cds { namespace memory {
             CDS_UNUSED(n);
 
             if ( p ) {
-                if ( from_pool( p ) )
-                    m_Queue.push( *p );
+                if ( from_pool(p) ) {
+                    // The queue can notify about false fullness state
+                    // so we push in loop 
+                    back_off bkoff;
+                    while ( !m_Queue.push( *p ))
+                        bkoff();
+                }
                 else
                     cxx_allocator().Delete( p );
             }
@@ -310,6 +319,7 @@ namespace cds { namespace memory {
             CDS_UNUSED(n);
 
             if ( p ) {
+                // Here we ignore false fullness state of the queue
                 if ( !m_Queue.push( *p ))
                     cxx_allocator().Delete( p );
             }
@@ -384,13 +394,19 @@ namespace cds { namespace memory {
     template <typename T, typename Traits = vyukov_queue_pool_traits >
     class bounded_vyukov_queue_pool
     {
+        //@cond
+        struct internal_traits : public Traits {
+            typedef cds::atomicity::item_counter item_counter;
+        };
+        //@endcond
     public:
-        typedef cds::intrusive::VyukovMPMCCycleQueue< T, Traits > queue_type  ;   ///< Queue type
+        typedef cds::intrusive::VyukovMPMCCycleQueue< T, internal_traits > queue_type  ;   ///< Queue type
 
     public:
         typedef T  value_type;  ///< Value type
         typedef Traits traits;  ///< Pool traits
         typedef typename traits::allocator::template rebind<value_type>::other allocator_type  ;   ///< allocator type
+        typedef typename traits::back_off back_off; ///< back-off strategy
 
     protected:
         //@cond
@@ -453,12 +469,23 @@ namespace cds { namespace memory {
             CDS_UNUSED( n );
 
             value_type * p = m_Queue.pop();
-            if ( p ) {
-                assert( from_pool(p) );
-                return p;
+
+            if ( !p ) {
+                back_off bkoff;
+                while ( m_Queue.size() ) {
+                    p = m_Queue.pop();
+                    if ( p )
+                        goto ok;
+                    bkoff();
+                }
+
+                // The pool is empty
+                throw std::bad_alloc();
             }
 
-            throw std::bad_alloc();
+        ok:
+            assert( from_pool(p) );
+            return p;
         }
 
         /// Deallocated the object \p p
@@ -475,7 +502,11 @@ namespace cds { namespace memory {
 
             if ( p ) {
                 assert( from_pool( p ));
-                CDS_VERIFY( m_Queue.push( *p ));
+                back_off bkoff;
+                // The queue can notify it is full but that is false fullness state
+                // So, we push in loop
+                while ( !m_Queue.push(*p) )
+                    bkoff();
             }
         }
     };