added "pop from empty queue" counter to queue statistics
authorkhizmax <libcds.dev@gmail.com>
Sat, 17 Jan 2015 10:44:08 +0000 (13:44 +0300)
committerkhizmax <libcds.dev@gmail.com>
Sat, 17 Jan 2015 10:44:08 +0000 (13:44 +0300)
cds/intrusive/basket_queue.h
cds/intrusive/moir_queue.h
cds/intrusive/msqueue.h
cds/intrusive/optimistic_queue.h
tests/unit/queue/queue_type.h

index bdcf27a3209a072782dbd1cf929a101668879129..da402502ab1e67798ee082075a3287bbf6ccdd5f 100644 (file)
@@ -122,23 +122,27 @@ namespace cds { namespace intrusive {
             counter_type m_BadTail;         ///< Count of events "Tail is not pointed to the last item in the queue"
             counter_type m_TryAddBasket;    ///< Count of attemps adding new item to a basket (only or BasketQueue, for other queue this metric is not used)
             counter_type m_AddBasketCount;  ///< Count of events "Enqueue a new item into basket" (only or BasketQueue, for other queue this metric is not used)
+            counter_type m_EmptyDequeue;    ///< Count of dequeue from empty queue
 
             /// Register enqueue call
-            void onEnqueue() { ++m_EnqueueCount; }
+            void onEnqueue()                { ++m_EnqueueCount; }
             /// Register dequeue call
-            void onDequeue() { ++m_DequeueCount; }
+            void onDequeue()                { ++m_DequeueCount; }
             /// Register enqueue race event
-            void onEnqueueRace() { ++m_EnqueueRace; }
+            void onEnqueueRace()            { ++m_EnqueueRace; }
             /// Register dequeue race event
-            void onDequeueRace() { ++m_DequeueRace; }
+            void onDequeueRace()            { ++m_DequeueRace; }
             /// Register "advance tail failed" event
-            void onAdvanceTailFailed() { ++m_AdvanceTailError; }
+            void onAdvanceTailFailed()      { ++m_AdvanceTailError; }
             /// Register event "Tail is not pointed to last item in the queue"
-            void onBadTail() { ++m_BadTail; }
+            void onBadTail()                { ++m_BadTail; }
             /// Register an attempt t add new item to basket
             void onTryAddBasket()           { ++m_TryAddBasket; }
             /// Register event "Enqueue a new item into basket" (only or BasketQueue, for other queue this metric is not used)
             void onAddBasket()              { ++m_AddBasketCount; }
+            /// Register dequeuing from empty queue
+            void onEmptyDequeue()           { ++m_EmptyDequeue; }
+
 
             //@cond
             void reset()
@@ -151,6 +155,7 @@ namespace cds { namespace intrusive {
                 m_BadTail.reset();
                 m_TryAddBasket.reset();
                 m_AddBasketCount.reset();
+                m_EmptyDequeue.reset();
             }
 
             stat& operator +=( stat const& s )
@@ -163,6 +168,7 @@ namespace cds { namespace intrusive {
                 m_BadTail       += s.m_BadTail.get();
                 m_TryAddBasket  += s.m_TryAddBasket.get();
                 m_AddBasketCount += s.m_AddBasketCount.get();
+                m_EmptyDequeue  += s.m_EmptyDequeue.get();
                 return *this;
             }
             //@endcond
@@ -172,14 +178,15 @@ namespace cds { namespace intrusive {
         struct empty_stat
         {
             //@cond
-            void onEnqueue()            {}
-            void onDequeue()            {}
-            void onEnqueueRace()        {}
-            void onDequeueRace()        {}
-            void onAdvanceTailFailed()  {}
-            void onBadTail()            {}
-            void onTryAddBasket()       {}
-            void onAddBasket()          {}
+            void onEnqueue()            const {}
+            void onDequeue()            const {}
+            void onEnqueueRace()        const {}
+            void onDequeueRace()        const {}
+            void onAdvanceTailFailed()  const {}
+            void onBadTail()            const {}
+            void onTryAddBasket()       const {}
+            void onAddBasket()          const {}
+            void onEmptyDequeue()       const {}
 
             void reset() {}
             empty_stat& operator +=( empty_stat const& )
@@ -494,8 +501,10 @@ namespace cds { namespace intrusive {
 
                 if ( h == m_pHead.load( memory_model::memory_order_acquire ) ) {
                     if ( h.ptr() == t.ptr() ) {
-                        if ( !pNext.ptr() )
+                        if ( !pNext.ptr() ) {
+                            m_Stat.onEmptyDequeue();
                             return false;
+                        }
 
                         {
                             typename gc::Guard g;
index 0d2d62a852f8ee5ffcbd93fb7b99c3b7245e05f6..0f0607df01a4148e82c35c98488bf25d5773af8a 100644 (file)
@@ -117,8 +117,10 @@ namespace cds { namespace intrusive {
                 h = res.guards.protect( 0, base_class::m_pHead, node_to_value() );
                 pNext = res.guards.protect( 1, h->m_pNext, node_to_value() );
 
-                if ( pNext == nullptr )
-                    return false    ;    // queue is empty
+                if ( pNext == nullptr ) {
+                    base_class::m_Stat.onEmptyDequeue();
+                    return false;    // queue is empty
+                }
 
                 if ( base_class::m_pHead.compare_exchange_strong( h, pNext, memory_model::memory_order_release, atomics::memory_order_relaxed )) {
                     node_type * t = base_class::m_pTail.load(memory_model::memory_order_acquire);
index 2fad6f9634076a1c4fee488b56dcdd1355d1d2db..7a63639167ce4e28f7aa0b8a185b8571e893d2c5 100644 (file)
@@ -75,6 +75,7 @@ namespace cds { namespace intrusive {
             counter_type m_DequeueRace       ;  ///< Count of dequeue race conditions encountered
             counter_type m_AdvanceTailError  ;  ///< Count of "advance tail failed" events
             counter_type m_BadTail           ;  ///< Count of events "Tail is not pointed to the last item in the queue"
+            counter_type m_EmptyDequeue      ;  ///< Count of dequeue from empty queue
 
             /// Register enqueue call
             void onEnqueue()                { ++m_EnqueueCount; }
@@ -88,6 +89,8 @@ namespace cds { namespace intrusive {
             void onAdvanceTailFailed()      { ++m_AdvanceTailError; }
             /// Register event "Tail is not pointed to last item in the queue"
             void onBadTail()                { ++m_BadTail; }
+            /// Register dequeuing from empty queue
+            void onEmptyDequeue()           { ++m_EmptyDequeue; }
 
             //@cond
             void reset()
@@ -98,6 +101,7 @@ namespace cds { namespace intrusive {
                 m_DequeueRace.reset();
                 m_AdvanceTailError.reset();
                 m_BadTail.reset();
+                m_EmptyDequeue.reset();
             }
 
             stat& operator +=( stat const& s )
@@ -108,6 +112,7 @@ namespace cds { namespace intrusive {
                 m_DequeueRace += s.m_DequeueRace.get();
                 m_AdvanceTailError += s.m_AdvanceTailError.get();
                 m_BadTail += s.m_BadTail.get();
+                m_EmptyDequeue += s.m_EmptyDequeue.get();
 
                 return *this;
             }
@@ -118,12 +123,13 @@ namespace cds { namespace intrusive {
         struct empty_stat
         {
             //@cond
-            void onEnqueue()                {}
-            void onDequeue()                {}
-            void onEnqueueRace()            {}
-            void onDequeueRace()            {}
-            void onAdvanceTailFailed()      {}
-            void onBadTail()                {}
+            void onEnqueue()                const {}
+            void onDequeue()                const {}
+            void onEnqueueRace()            const {}
+            void onDequeueRace()            const {}
+            void onAdvanceTailFailed()      const {}
+            void onBadTail()                const {}
+            void onEmptyDequeue()           const {}
 
             void reset() {}
             empty_stat& operator +=( empty_stat const& )
@@ -371,8 +377,10 @@ namespace cds { namespace intrusive {
                 if ( m_pHead.load(memory_model::memory_order_acquire) != h )
                     continue;
 
-                if ( pNext == nullptr )
-                    return false ;    // empty queue
+                if ( pNext == nullptr ) {
+                    m_Stat.onEmptyDequeue();
+                    return false;    // empty queue
+                }
 
                 node_type * t = m_pTail.load(memory_model::memory_order_acquire);
                 if ( h == t ) {
index f2b4254358241cdc2f0c19f81e1bd47d834db9d6..43f676c866b04894bfb618e57bb8bf5a7c66fbfc 100644 (file)
@@ -159,13 +159,14 @@ namespace cds { namespace intrusive {
         {
             typedef Counter     counter_type;   ///< Counter type
 
-            counter_type m_EnqueueCount;  ///< Enqueue call count
-            counter_type m_DequeueCount;  ///< Dequeue call count
-            counter_type m_EnqueueRace;  ///< Count of enqueue race conditions encountered
-            counter_type m_DequeueRace;  ///< Count of dequeue race conditions encountered
-            counter_type m_AdvanceTailError;  ///< Count of "advance tail failed" events
-            counter_type m_BadTail;  ///< Count of events "Tail is not pointed to the last item in the queue"
-            counter_type    m_FixListCount;   ///< Count of fix list event
+            counter_type m_EnqueueCount;    ///< Enqueue call count
+            counter_type m_DequeueCount;    ///< Dequeue call count
+            counter_type m_EnqueueRace;     ///< Count of enqueue race conditions encountered
+            counter_type m_DequeueRace;     ///< Count of dequeue race conditions encountered
+            counter_type m_AdvanceTailError; ///< Count of "advance tail failed" events
+            counter_type m_BadTail;         ///< Count of events "Tail is not pointed to the last item in the queue"
+            counter_type m_FixListCount;    ///< Count of fix list event
+            counter_type m_EmptyDequeue;    ///< Count of dequeue from empty queue
 
             /// Register enqueue call
             void onEnqueue() { ++m_EnqueueCount; }
@@ -181,6 +182,8 @@ namespace cds { namespace intrusive {
             void onBadTail() { ++m_BadTail; }
             /// Register fix list event
             void onFixList()    { ++m_FixListCount; }
+            /// Register dequeuing from empty queue
+            void onEmptyDequeue() { ++m_EmptyDequeue; }
 
             //@cond
             void reset()
@@ -192,6 +195,7 @@ namespace cds { namespace intrusive {
                 m_AdvanceTailError.reset();
                 m_BadTail.reset();
                 m_FixListCount.reset();
+                m_EmptyDequeue.reset();
             }
 
             stat& operator +=( stat const& s )
@@ -203,6 +207,8 @@ namespace cds { namespace intrusive {
                 m_AdvanceTailError += s.m_AdvanceTailError.get();
                 m_BadTail += s.m_BadTail.get();
                 m_FixListCount += s.m_FixListCount.get();
+                m_EmptyDequeue += s.m_EmptyDequeue.get();
+
                 return *this;
             }
             //@endcond
@@ -212,13 +218,14 @@ namespace cds { namespace intrusive {
         struct empty_stat
         {
             //@cond
-            void onEnqueue() {}
-            void onDequeue() {}
-            void onEnqueueRace() {}
-            void onDequeueRace() {}
-            void onAdvanceTailFailed() {}
-            void onBadTail() {}
-            void onFixList() {}
+            void onEnqueue()            const {}
+            void onDequeue()            const {}
+            void onEnqueueRace()        const {}
+            void onDequeueRace()        const {}
+            void onAdvanceTailFailed()  const {}
+            void onBadTail()            const {}
+            void onFixList()            const {}
+            void onEmptyDequeue()       const {}
 
             void reset() {}
             empty_stat& operator +=( empty_stat const& )
@@ -473,6 +480,7 @@ namespace cds { namespace intrusive {
                     }
                     else {
                         // the queue is empty
+                        m_Stat.onEmptyDequeue();
                         return false;
                     }
                 }
index 818e05febc32daca3b12b4ef207ba38c3638b857..a1a58ec9d851a48b676fffb629306dfca6f29131 100644 (file)
@@ -511,24 +511,6 @@ namespace queue {
 // *********************************************
 // Queue statistics
 namespace std {
-    /*
-    template <typename Counter>
-    static inline std::ostream& operator <<(std::ostream& o, cds::intrusive::queue_stat<Counter> const& s)
-    {
-        return o
-            << "\tStatistics:\n"
-            << "\t\t      Enqueue count: " << s.m_EnqueueCount.get() << "\n"
-            << "\t\t       Enqueue race: " << s.m_EnqueueRace.get() << "\n"
-            << "\t\t      Dequeue count: " << s.m_DequeueCount.get() << "\n"
-            << "\t\t       Dequeue race: " << s.m_DequeueRace.get() << "\n"
-            << "\t\t Advance tail error: " << s.m_AdvanceTailError.get() << "\n"
-            << "\t\t           Bad tail: " << s.m_BadTail.get() << "\n";
-    }
-    static inline std::ostream& operator <<(std::ostream& o, cds::intrusive::queue_dummy_stat const& s)
-    {
-        return o;
-    }
-    */
 
     template <typename Counter>
     static inline std::ostream& operator <<(std::ostream& o, cds::container::basket_queue::stat<Counter> const& s)
@@ -538,6 +520,7 @@ namespace std {
             << "\t\t      Enqueue count: " << s.m_EnqueueCount.get() << "\n"
             << "\t\t       Enqueue race: " << s.m_EnqueueRace.get() << "\n"
             << "\t\t      Dequeue count: " << s.m_DequeueCount.get() << "\n"
+            << "\t\t      Dequeue empty: " << s.m_EmptyDequeue.get() << "\n"
             << "\t\t       Dequeue race: " << s.m_DequeueRace.get() << "\n"
             << "\t\t Advance tail error: " << s.m_AdvanceTailError.get() << "\n"
             << "\t\t           Bad tail: " << s.m_BadTail.get() << "\n"
@@ -557,6 +540,7 @@ namespace std {
             << "\t\t     Enqueue count: " << s.m_EnqueueCount.get() << "\n"
             << "\t\t      Enqueue race: " << s.m_EnqueueRace.get()  << "\n"
             << "\t\t     Dequeue count: " << s.m_DequeueCount.get() << "\n"
+            << "\t\t     Dequeue empty: " << s.m_EmptyDequeue.get() << "\n"
             << "\t\t      Dequeue race: " << s.m_DequeueRace.get()  << "\n"
             << "\t\tAdvance tail error: " << s.m_AdvanceTailError.get() << "\n"
             << "\t\t          Bad tail: " << s.m_BadTail.get() << "\n";
@@ -581,6 +565,7 @@ namespace std {
             << "\t\t      Enqueue count: " << s.m_EnqueueCount.get() << "\n"
             << "\t\t       Enqueue race: " << s.m_EnqueueRace.get() << "\n"
             << "\t\t      Dequeue count: " << s.m_DequeueCount.get() << "\n"
+            << "\t\t      Dequeue empty: " << s.m_EmptyDequeue.get() << "\n"
             << "\t\t       Dequeue race: " << s.m_DequeueRace.get() << "\n"
             << "\t\t Advance tail error: " << s.m_AdvanceTailError.get() << "\n"
             << "\t\t           Bad tail: " << s.m_BadTail.get() << "\n"