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()
m_BadTail.reset();
m_TryAddBasket.reset();
m_AddBasketCount.reset();
+ m_EmptyDequeue.reset();
}
stat& operator +=( stat const& s )
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
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& )
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;
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);
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; }
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()
m_DequeueRace.reset();
m_AdvanceTailError.reset();
m_BadTail.reset();
+ m_EmptyDequeue.reset();
}
stat& operator +=( stat const& s )
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;
}
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& )
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 ) {
{
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; }
void onBadTail() { ++m_BadTail; }
/// Register fix list event
void onFixList() { ++m_FixListCount; }
+ /// Register dequeuing from empty queue
+ void onEmptyDequeue() { ++m_EmptyDequeue; }
//@cond
void reset()
m_AdvanceTailError.reset();
m_BadTail.reset();
m_FixListCount.reset();
+ m_EmptyDequeue.reset();
}
stat& operator +=( stat const& s )
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
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& )
}
else {
// the queue is empty
+ m_Stat.onEmptyDequeue();
return false;
}
}
// *********************************************
// 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)
<< "\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"
<< "\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";
<< "\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"