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"
33 // Multi-threaded queue test for push operation
36 static size_t s_nThreadCount = 8;
37 static size_t s_nQueueSize = 20000000 ; // no more than 20 million records
39 class queue_push: public cds_test::stress_fixture
50 value_type( size_t n )
55 template <class Queue>
56 class Producer: public cds_test::thread
58 typedef cds_test::thread base_class;
61 Producer( cds_test::thread_pool& pool, Queue& queue )
69 Producer( Producer& src )
71 , m_Queue( src.m_Queue )
77 virtual thread * clone()
79 return new Producer( *this );
84 for ( size_t nItem = m_nStartItem; nItem < m_nEndItem; ++nItem ) {
85 if ( !m_Queue.push( nItem ))
98 static void SetUpTestCase()
100 cds_test::config const& cfg = get_config( "queue_push" );
102 s_nThreadCount = cfg.get_size_t( "ThreadCount", s_nThreadCount );
103 s_nQueueSize = cfg.get_size_t( "QueueSize", s_nQueueSize );
105 if ( s_nThreadCount == 0u )
107 if ( s_nQueueSize == 0u )
111 //static void TearDownTestCase();
114 template <class Queue>
115 void test( Queue& q )
117 cds_test::thread_pool& pool = get_pool();
119 pool.add( new Producer<Queue>( pool, q ), s_nThreadCount );
122 size_t nThreadItemCount = s_nQueueSize / s_nThreadCount;
123 for ( size_t i = 0; i < pool.size(); ++i ) {
124 Producer<Queue>& thread = static_cast<Producer<Queue>&>(pool.get( i ));
125 thread.m_nStartItem = nStart;
126 nStart += nThreadItemCount;
127 thread.m_nEndItem = nStart;
130 s_nQueueSize = nThreadItemCount * s_nThreadCount;
131 propout() << std::make_pair( "thread_count", s_nThreadCount )
132 << std::make_pair( "push_count", s_nQueueSize );
134 std::chrono::milliseconds duration = pool.run();
136 propout() << std::make_pair( "duration", duration );
140 propout() << q.statistics();
143 template <class Queue>
144 void analyze( Queue& q )
146 size_t nThreadItems = s_nQueueSize / s_nThreadCount;
147 cds_test::thread_pool& pool = get_pool();
149 for ( size_t i = 0; i < pool.size(); ++i ) {
150 Producer<Queue>& thread = static_cast<Producer<Queue>&>(pool.get( i ));
151 EXPECT_EQ( thread.m_nPushError, 0u ) << " producer thread " << i;
153 EXPECT_TRUE( !q.empty());
155 std::unique_ptr< uint8_t[] > arr( new uint8_t[s_nQueueSize] );
156 memset( arr.get(), 0, sizeof(arr[0]) * s_nQueueSize );
160 while ( q.pop( val )) {
165 size_t nTotalItems = nThreadItems * s_nThreadCount;
166 for ( size_t i = 0; i < nTotalItems; ++i ) {
167 EXPECT_EQ( arr[i], 1 ) << "i=" << i;
172 CDSSTRESS_MSQueue( queue_push )
173 CDSSTRESS_MoirQueue( queue_push )
174 CDSSTRESS_BasketQueue( queue_push )
175 CDSSTRESS_OptimsticQueue( queue_push )
176 CDSSTRESS_FCQueue( queue_push )
177 CDSSTRESS_FCDeque( queue_push )
178 CDSSTRESS_RWQueue( queue_push )
179 CDSSTRESS_StdQueue( queue_push )
181 #undef CDSSTRESS_Queue_F
182 #define CDSSTRESS_Queue_F( test_fixture, type_name ) \
183 TEST_F( test_fixture, type_name ) \
185 typedef queue::Types< value_type >::type_name queue_type; \
186 queue_type queue( s_nQueueSize ); \
190 CDSSTRESS_VyukovQueue( queue_push )
192 #undef CDSSTRESS_Queue_F
195 // ********************************************************************
196 // SegmentedQueue test
198 class segmented_queue_push
200 , public ::testing::WithParamInterface< size_t >
202 typedef queue_push base_class;
205 template <typename Queue>
208 size_t quasi_factor = GetParam();
210 Queue q( quasi_factor );
211 propout() << std::make_pair( "quasi_factor", quasi_factor );
212 base_class::test( q );
216 static std::vector< size_t > get_test_parameters()
218 cds_test::config const& cfg = cds_test::stress_fixture::get_config( "queue_push" );
219 bool bIterative = cfg.get_bool( "SegmentedQueue_Iterate", false );
220 size_t quasi_factor = cfg.get_size_t( "SegmentedQueue_SegmentSize", 256 );
222 std::vector<size_t> args;
223 if ( bIterative && quasi_factor > 4 ) {
224 for ( size_t qf = 4; qf <= quasi_factor; qf *= 2 )
225 args.push_back( qf );
228 if ( quasi_factor > 2 )
229 args.push_back( quasi_factor );
238 #define CDSSTRESS_Queue_F( test_fixture, type_name ) \
239 TEST_P( test_fixture, type_name ) \
241 typedef typename queue::Types<value_type>::type_name queue_type; \
242 test< queue_type >(); \
245 CDSSTRESS_SegmentedQueue( segmented_queue_push )
247 #ifdef CDSTEST_GTEST_INSTANTIATE_TEST_CASE_P_HAS_4TH_ARG
248 static std::string get_test_parameter_name( testing::TestParamInfo<size_t> const& p )
250 return std::to_string( p.param );
252 INSTANTIATE_TEST_CASE_P( SQ,
253 segmented_queue_push,
254 ::testing::ValuesIn( segmented_queue_push::get_test_parameters() ), get_test_parameter_name );
256 INSTANTIATE_TEST_CASE_P( SQ,
257 segmented_queue_push,
258 ::testing::ValuesIn( segmented_queue_push::get_test_parameters() ) );