2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
6 Source code repo: http://github.com/khizmax/libcds/
7 Download: http://sourceforge.net/projects/libcds/files/
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice, this
13 list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice,
16 this list of conditions and the following disclaimer in the documentation
17 and/or other materials provided with the distribution.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "pqueue_type.h"
35 static size_t s_nThreadCount = 8;
36 static size_t s_nQueueSize = 2000000;
38 class pqueue_pop: public cds_test::stress_fixture
40 typedef cds_test::stress_fixture base_class;
43 template <class PQueue>
44 class Consumer: public cds_test::thread
46 typedef cds_test::thread base_class;
49 Consumer( cds_test::thread_pool& pool, PQueue& queue )
54 Consumer( Consumer& src )
56 , m_Queue( src.m_Queue )
59 virtual thread * clone()
61 return new Consumer( *this );
66 typedef typename PQueue::value_type value_type;
69 if ( m_Queue.pop( val )) {
74 while ( !m_Queue.empty() ) {
75 if ( m_Queue.pop( val )) {
77 if ( val.key > nPrevKey ) {
79 m_arrFailedPops.emplace_back( failed_pops{ nPrevKey, val.key } );
81 else if ( val.key == nPrevKey ) {
83 m_arrFailedPops.emplace_back( failed_pops{ nPrevKey, val.key } );
92 while ( m_Queue.pop( val )) {
94 if ( val.key > nPrevKey ) {
96 m_arrFailedPops.emplace_back( failed_pops{ nPrevKey, val.key } );
98 else if ( val.key == nPrevKey ) {
100 m_arrFailedPops.emplace_back( failed_pops{ nPrevKey, val.key } );
112 size_t m_nPopError = 0;
113 size_t m_nPopErrorEq = 0;
114 size_t m_nPopSuccess = 0;
115 size_t m_nPopFailed = 0;
121 std::vector< failed_pops > m_arrFailedPops;
126 template <class PQueue>
127 void test( PQueue& q )
129 cds_test::thread_pool& pool = get_pool();
131 propout() << std::make_pair( "thread_count", s_nThreadCount )
132 << std::make_pair( "push_count", s_nQueueSize );
136 std::vector< size_t > arr;
137 arr.reserve( s_nQueueSize );
138 for ( size_t i = 0; i < s_nQueueSize; ++i )
140 shuffle( arr.begin(), arr.end() );
142 size_t nPushError = 0;
143 typedef typename PQueue::value_type value_type;
144 for ( auto it = arr.begin(); it != arr.end(); ++it ) {
145 if ( !q.push( value_type( *it ) ))
148 s_nQueueSize -= nPushError;
153 pool.add( new Consumer<PQueue>( pool, q ), s_nThreadCount );
155 std::chrono::milliseconds duration = pool.run();
156 propout() << std::make_pair( "consumer_duration", duration );
159 size_t nTotalPopped = 0;
160 size_t nTotalError = 0;
161 size_t nTotalErrorEq = 0;
162 size_t nTotalFailed = 0;
163 for ( size_t i = 0; i < pool.size(); ++i ) {
164 Consumer<PQueue>& cons = static_cast<Consumer<PQueue>&>( pool.get(i));
166 nTotalPopped += cons.m_nPopSuccess;
167 nTotalError += cons.m_nPopError;
168 nTotalErrorEq += cons.m_nPopErrorEq;
169 nTotalFailed += cons.m_nPopFailed;
171 if ( !cons.m_arrFailedPops.empty() ) {
172 std::cerr << "Priority violations, thread " << i;
173 for ( size_t k = 0; k < cons.m_arrFailedPops.size(); ++k ) {
174 std::cerr << "\n " << "prev_key=" << cons.m_arrFailedPops[k].prev_key << " popped_key=" << cons.m_arrFailedPops[k].popped_key;
176 std::cerr << std::endl;
181 << std::make_pair( "total_popped", nTotalPopped )
182 << std::make_pair( "error_pop_double", nTotalErrorEq )
183 << std::make_pair( "error_priority_violation", nTotalError );
185 EXPECT_EQ( nTotalPopped, s_nQueueSize );
186 EXPECT_EQ( nTotalError, 0 ) << "priority violations";
187 EXPECT_EQ( nTotalErrorEq, 0 ) << "double key";
190 propout() << q.statistics();
194 static void SetUpTestCase()
\r
196 cds_test::config const& cfg = get_config( "pqueue_pop" );
\r
198 s_nThreadCount = cfg.get_size_t( "ThreadCount", s_nThreadCount );
199 s_nQueueSize = cfg.get_size_t( "QueueSize", s_nQueueSize );
201 if ( s_nThreadCount == 0 )
203 if ( s_nQueueSize == 0 )
204 s_nQueueSize = 1000;
\r
207 //static void TearDownTestCase();
210 #define CDSSTRESS_MSPriorityQueue( fixture_t, pqueue_t ) \
211 TEST_F( fixture_t, pqueue_t ) \
213 typedef pqueue::Types<pqueue::simple_value>::pqueue_t pqueue_type; \
214 pqueue_type pq( s_nQueueSize + 1 ); \
217 CDSSTRESS_MSPriorityQueue( pqueue_pop, MSPriorityQueue_dyn_less )
218 CDSSTRESS_MSPriorityQueue( pqueue_pop, MSPriorityQueue_dyn_less_stat )
219 CDSSTRESS_MSPriorityQueue( pqueue_pop, MSPriorityQueue_dyn_cmp )
220 //CDSSTRESS_MSPriorityQueue( pqueue_pop, MSPriorityQueue_dyn_mutex ) // too slow
222 #define CDSSTRESS_MSPriorityQueue_static( fixture_t, pqueue_t ) \
223 TEST_F( fixture_t, pqueue_t ) \
225 typedef pqueue::Types<pqueue::simple_value>::pqueue_t pqueue_type; \
226 std::unique_ptr< pqueue_type > pq( new pqueue_type ); \
229 //CDSSTRESS_MSPriorityQueue( pqueue_pop, MSPriorityQueue_static_less )
230 //CDSSTRESS_MSPriorityQueue( pqueue_pop, MSPriorityQueue_static_less_stat )
231 //CDSSTRESS_MSPriorityQueue( pqueue_pop, MSPriorityQueue_static_cmp )
232 //CDSSTRESS_MSPriorityQueue( pqueue_pop, 1MSPriorityQueue_static_mutex )
235 #define CDSSTRESS_PriorityQueue( fixture_t, pqueue_t ) \
236 TEST_F( fixture_t, pqueue_t ) \
238 typedef pqueue::Types<pqueue::simple_value>::pqueue_t pqueue_type; \
242 CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_vector )
243 CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_vector_stat )
244 CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_deque )
245 CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_deque_stat )
246 CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_boost_deque )
247 CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_boost_deque_stat )
248 CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_boost_stable_vector )
249 CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_boost_stable_vector_stat )
251 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_HP_max )
252 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_HP_max_stat )
253 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_HP_min )
254 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_HP_min_stat )
255 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_DHP_max )
256 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_DHP_max_stat )
257 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_DHP_min )
258 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_DHP_min_stat )
259 // CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpi_max )
260 // CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpi_max_stat )
261 // CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpi_min )
262 // CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpi_min_stat )
263 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpb_max )
264 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpb_max_stat )
265 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpb_min )
266 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpb_min_stat )
267 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpt_max )
268 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpt_max_stat )
269 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpt_min )
270 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpt_min_stat )
271 #ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
272 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_shb_max )
273 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_shb_max_stat )
274 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_shb_min )
275 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_shb_min_stat )
276 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_sht_max )
277 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_sht_max_stat )
278 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_sht_min )
279 CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_sht_min_stat )
282 CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_HP_max )
283 CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_HP_max_stat )
284 CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_HP_min )
285 CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_HP_min_stat )
286 CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_DHP_max )
287 CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_DHP_max_stat )
288 CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_DHP_min )
289 CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_DHP_min_stat )
290 CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_gpi_max )
291 CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_gpi_min )
292 CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_gpb_max )
293 CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_gpb_min )
294 CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_gpt_max )
295 CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_gpt_min )
296 #ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
297 CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_shb_max )
298 CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_shb_min )
299 CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_sht_max )
300 CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_sht_min )
303 CDSSTRESS_PriorityQueue( pqueue_pop, StdPQueue_vector_spin )
304 CDSSTRESS_PriorityQueue( pqueue_pop, StdPQueue_vector_mutex )
305 CDSSTRESS_PriorityQueue( pqueue_pop, StdPQueue_deque_spin )
306 CDSSTRESS_PriorityQueue( pqueue_pop, StdPQueue_deque_mutex )