| 133 | |
| 134 | template <class Stack> |
| 135 | void analyze( Stack& testStack ) |
| 136 | { |
| 137 | cds_test::thread_pool& pool = get_pool(); |
| 138 | |
| 139 | size_t nThreadItems = s_nStackSize / s_nThreadCount; |
| 140 | std::vector<size_t> aThread; |
| 141 | aThread.resize( s_nThreadCount ); |
| 142 | |
| 143 | for ( size_t i = 0; i < pool.size(); ++i ) { |
| 144 | Producer<Stack>& producer = static_cast<Producer<Stack>&>( pool.get( i )); |
| 145 | EXPECT_EQ( producer.m_nPushError, 0u ) << "Producer=" << i; |
| 146 | aThread[producer.id()] = producer.m_nEndItem - 1; |
| 147 | } |
| 148 | EXPECT_FALSE( testStack.empty()); |
| 149 | |
| 150 | std::unique_ptr< uint8_t[] > uarr( new uint8_t[s_nStackSize] ); |
| 151 | uint8_t * arr = uarr.get(); |
| 152 | memset( arr, 0, sizeof( arr[0] ) * s_nStackSize ); |
| 153 | |
| 154 | auto time_start = std::chrono::steady_clock::now(); |
| 155 | size_t nPopped = 0; |
| 156 | value_type val; |
| 157 | while ( testStack.pop( val )) { |
| 158 | nPopped++; |
| 159 | ASSERT_LT( val.nNo, s_nStackSize ); |
| 160 | ++arr[val.nNo]; |
| 161 | ASSERT_LT( val.nThread, s_nThreadCount ); |
| 162 | ASSERT_EQ( aThread[val.nThread], val.nNo ); |
| 163 | aThread[val.nThread]--; |
| 164 | } |
| 165 | propout() << std::make_pair( "pop_duration", std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - time_start)); |
| 166 | |
| 167 | size_t nTotalItems = nThreadItems * s_nThreadCount; |
| 168 | size_t nError = 0; |
| 169 | for ( size_t i = 0; i < nTotalItems; ++i ) { |
| 170 | EXPECT_EQ( arr[i], 1 ) << "i=" << i; |
| 171 | if ( ++nError > 10 ) { |
| 172 | ASSERT_EQ( arr[i], 1 ); |
| 173 | } |
| 174 | } |
| 175 | } |
| 176 | }; |
| 177 | |
| 178 | CDSSTRESS_TreiberStack( stack_push ) |