| 110 | typedef typename base_class::dequeue_result dequeue_result; |
| 111 | |
| 112 | bool do_dequeue( dequeue_result& res ) |
| 113 | { |
| 114 | back_off bkoff; |
| 115 | |
| 116 | node_type * pNext; |
| 117 | node_type * h; |
| 118 | while ( true ) { |
| 119 | h = res.guards.protect( 0, base_class::m_pHead, []( node_type * p ) -> value_type * { return node_traits::to_value_ptr( p );}); |
| 120 | pNext = res.guards.protect( 1, h->m_pNext, []( node_type * p ) -> value_type * { return node_traits::to_value_ptr( p );}); |
| 121 | |
| 122 | if ( pNext == nullptr ) { |
| 123 | base_class::m_Stat.onEmptyDequeue(); |
| 124 | return false; // queue is empty |
| 125 | } |
| 126 | |
| 127 | if ( base_class::m_pHead.compare_exchange_strong( h, pNext, memory_model::memory_order_release, atomics::memory_order_relaxed )) { |
| 128 | node_type * t = base_class::m_pTail.load(memory_model::memory_order_acquire); |
| 129 | if ( h == t ) |
| 130 | base_class::m_pTail.compare_exchange_strong( t, pNext, memory_model::memory_order_release, atomics::memory_order_relaxed ); |
| 131 | break; |
| 132 | } |
| 133 | |
| 134 | base_class::m_Stat.onDequeueRace(); |
| 135 | bkoff(); |
| 136 | } |
| 137 | |
| 138 | --base_class::m_ItemCounter; |
| 139 | base_class::m_Stat.onDequeue(); |
| 140 | |
| 141 | res.pHead = h; |
| 142 | res.pNext = pNext; |
| 143 | return true; |
| 144 | } |
| 145 | //@endcond |
| 146 | |
| 147 | public: |
nothing calls this directly
no test coverage detected