2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
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 "queue_type.h"
32 #include "../misc/common.h"
34 // Multi-threaded queue test for pop operation
37 static size_t s_nThreadCount = 8;
38 static size_t s_nQueueSize = 20000000 ; // no more than 20 million records
43 SimpleValue(): nNo(0) {}
44 SimpleValue( size_t n ): nNo(n) {}
45 size_t getNo() const { return nNo; }
48 class queue_pop: public cds_test::stress_fixture
59 value_type( size_t n )
64 template <class Queue>
65 class Consumer: public cds_test::thread
67 typedef cds_test::thread base_class;
70 Consumer( cds_test::thread_pool& pool, Queue& queue )
73 , m_arr( new uint8_t[ s_nQueueSize ])
77 Consumer( Consumer& src )
79 , m_Queue( src.m_Queue )
80 , m_arr( new uint8_t[ s_nQueueSize ])
84 virtual thread * clone()
86 return new Consumer( *this );
91 memset( m_arr.get(), 0, sizeof( m_arr[0] ) * s_nQueueSize );
92 typedef typename Queue::value_type value_type;
95 while ( m_Queue.pop( value )) {
99 m_nPopCount = nPopCount;
104 std::unique_ptr< uint8_t[] > m_arr;
109 static void SetUpTestCase()
111 cds_test::config const& cfg = get_config( "queue_pop" );
113 s_nThreadCount = cfg.get_size_t( "ThreadCount", s_nThreadCount );
114 s_nQueueSize = cfg.get_size_t( "QueueSize", s_nQueueSize );
116 if ( s_nThreadCount == 0 )
118 if ( s_nQueueSize == 0 )
122 //static void TearDownTestCase();
125 template <class Queue>
126 void analyze( Queue& q )
128 cds_test::thread_pool& pool = get_pool();
129 std::unique_ptr< uint8_t[] > arr( new uint8_t[s_nQueueSize] );
130 memset(arr.get(), 0, sizeof(arr[0]) * s_nQueueSize );
132 size_t nTotalPops = 0;
133 for ( size_t i = 0; i < pool.size(); ++i ) {
134 Consumer<Queue>& thread = static_cast<Consumer<Queue>&>(pool.get( i ));
135 for ( size_t j = 0; j < s_nQueueSize; ++j )
136 arr[j] += thread.m_arr[j];
137 nTotalPops += thread.m_nPopCount;
139 EXPECT_EQ( nTotalPops, s_nQueueSize );
140 EXPECT_TRUE( q.empty());
142 for ( size_t i = 0; i < s_nQueueSize; ++i ) {
143 EXPECT_EQ( arr[i], 1 ) << "i=" << i;
147 template <class Queue>
148 void test( Queue& q )
150 cds_test::thread_pool& pool = get_pool();
152 pool.add( new Consumer<Queue>( pool, q ), s_nThreadCount );
154 for ( size_t i = 0; i < s_nQueueSize; ++i )
157 propout() << std::make_pair( "thread_count", s_nThreadCount )
158 << std::make_pair( "push_count", s_nQueueSize );
160 std::chrono::milliseconds duration = pool.run();
162 propout() << std::make_pair( "duration", duration );
166 propout() << q.statistics();
170 CDSSTRESS_MSQueue( queue_pop )
171 CDSSTRESS_MoirQueue( queue_pop )
172 CDSSTRESS_BasketQueue( queue_pop )
173 CDSSTRESS_OptimsticQueue( queue_pop )
174 CDSSTRESS_RWQueue( queue_pop )
176 #undef CDSSTRESS_Queue_F
177 #define CDSSTRESS_Queue_F( test_fixture, type_name ) \
178 TEST_F( test_fixture, type_name ) \
180 typedef queue::Types< value_type >::type_name queue_type; \
181 queue_type queue( s_nQueueSize ); \
185 CDSSTRESS_VyukovQueue( queue_pop )
187 #undef CDSSTRESS_Queue_F
190 // ********************************************************************
191 // SegmentedQueue test
193 class segmented_queue_pop
195 , public ::testing::WithParamInterface< size_t >
197 typedef queue_pop base_class;
200 template <typename Queue>
203 size_t quasi_factor = GetParam();
205 Queue q( quasi_factor );
206 propout() << std::make_pair( "quasi_factor", quasi_factor );
207 base_class::test( q );
211 static std::vector< size_t > get_test_parameters()
213 cds_test::config const& cfg = cds_test::stress_fixture::get_config( "queue_pop" );
214 bool bIterative = cfg.get_bool( "SegmentedQueue_Iterate", false );
215 size_t quasi_factor = cfg.get_size_t( "SegmentedQueue_SegmentSize", 256 );
217 std::vector<size_t> args;
218 if ( bIterative && quasi_factor > 4 ) {
219 for ( size_t qf = 4; qf <= quasi_factor; qf *= 2 )
220 args.push_back( qf );
223 if ( quasi_factor > 2 )
224 args.push_back( quasi_factor );
233 #define CDSSTRESS_Queue_F( test_fixture, type_name ) \
234 TEST_P( test_fixture, type_name ) \
236 typedef typename queue::Types<value_type>::type_name queue_type; \
237 test< queue_type >(); \
240 CDSSTRESS_SegmentedQueue( segmented_queue_pop )
242 #ifdef CDSTEST_GTEST_INSTANTIATE_TEST_CASE_P_HAS_4TH_ARG
243 static std::string get_test_parameter_name( testing::TestParamInfo<size_t> const& p )
245 return std::to_string( p.param );
247 INSTANTIATE_TEST_CASE_P( SQ,
249 ::testing::ValuesIn( segmented_queue_pop::get_test_parameters()), get_test_parameter_name );
251 INSTANTIATE_TEST_CASE_P( SQ,
253 ::testing::ValuesIn( segmented_queue_pop::get_test_parameters()));