| 172 | protected: |
| 173 | template <class Queue> |
| 174 | void analyze( Queue& q, size_t /*nLeftOffset*/ = 0, size_t nRightOffset = 0 ) |
| 175 | { |
| 176 | cds_test::thread_pool& pool = get_pool(); |
| 177 | |
| 178 | typedef Consumer<Queue> consumer_type; |
| 179 | typedef Producer<Queue> producer_type; |
| 180 | |
| 181 | size_t nPostTestPops = 0; |
| 182 | { |
| 183 | value_type v; |
| 184 | while ( q.pop( v )) |
| 185 | ++nPostTestPops; |
| 186 | } |
| 187 | |
| 188 | size_t nTotalPops = 0; |
| 189 | size_t nPopFalse = 0; |
| 190 | size_t nPoppedItems = 0; |
| 191 | size_t nPushFailed = 0; |
| 192 | |
| 193 | std::vector< consumer_type * > arrConsumer; |
| 194 | |
| 195 | for ( size_t i = 0; i < pool.size(); ++i ) { |
| 196 | cds_test::thread& thr = pool.get(i); |
| 197 | if ( thr.type() == consumer_thread ) { |
| 198 | consumer_type& consumer = static_cast<consumer_type&>( thr ); |
| 199 | nTotalPops += consumer.m_nPopped; |
| 200 | nPopFalse += consumer.m_nPopEmpty; |
| 201 | arrConsumer.push_back( &consumer ); |
| 202 | EXPECT_EQ( consumer.m_nBadWriter, 0u ) << "consumer_thread_no " << i; |
| 203 | |
| 204 | size_t nPopped = 0; |
| 205 | for ( size_t n = 0; n < s_nProducerThreadCount; ++n ) |
| 206 | nPopped += consumer.m_WriterData[n].size(); |
| 207 | |
| 208 | nPoppedItems += nPopped; |
| 209 | } |
| 210 | else { |
| 211 | assert( thr.type() == producer_thread ); |
| 212 | |
| 213 | producer_type& producer = static_cast<producer_type&>( thr ); |
| 214 | nPushFailed += producer.m_nPushFailed; |
| 215 | EXPECT_EQ( producer.m_nPushFailed, 0u ) << "producer_thread_no " << i; |
| 216 | } |
| 217 | } |
| 218 | EXPECT_EQ( nTotalPops, nPoppedItems ); |
| 219 | |
| 220 | EXPECT_EQ( nTotalPops + nPostTestPops, s_nQueueSize ) << "nTotalPops=" << nTotalPops << ", nPostTestPops=" << nPostTestPops; |
| 221 | EXPECT_TRUE( q.empty()); |
| 222 | |
| 223 | // Test consistency of popped sequence |
| 224 | for ( size_t nWriter = 0; nWriter < s_nProducerThreadCount; ++nWriter ) { |
| 225 | std::vector<size_t> arrData; |
| 226 | arrData.reserve( m_nThreadPushCount ); |
| 227 | for ( size_t nReader = 0; nReader < arrConsumer.size(); ++nReader ) { |
| 228 | auto it = arrConsumer[nReader]->m_WriterData[nWriter].begin(); |
| 229 | auto itEnd = arrConsumer[nReader]->m_WriterData[nWriter].end(); |
| 230 | if ( it != itEnd ) { |
| 231 | auto itPrev = it; |