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 push operation
37 static size_t s_nThreadCount = 8;
38 static size_t s_nQueueSize = 20000000 ; // no more than 20 million records
40 class queue_push: public cds_test::stress_fixture
51 value_type( size_t n )
56 template <class Queue>
57 class Producer: public cds_test::thread
59 typedef cds_test::thread base_class;
62 Producer( cds_test::thread_pool& pool, Queue& queue )
70 Producer( Producer& src )
72 , m_Queue( src.m_Queue )
78 virtual thread * clone()
80 return new Producer( *this );
85 for ( size_t nItem = m_nStartItem; nItem < m_nEndItem; ++nItem ) {
86 if ( !m_Queue.push( nItem ))
99 static void SetUpTestCase()
101 cds_test::config const& cfg = get_config( "queue_push" );
103 s_nThreadCount = cfg.get_size_t( "ThreadCount", s_nThreadCount );
104 s_nQueueSize = cfg.get_size_t( "QueueSize", s_nQueueSize );
106 if ( s_nThreadCount == 0u )
108 if ( s_nQueueSize == 0u )
112 //static void TearDownTestCase();
115 template <class Queue>
116 void test( Queue& q )
118 cds_test::thread_pool& pool = get_pool();
120 pool.add( new Producer<Queue>( pool, q ), s_nThreadCount );
123 size_t nThreadItemCount = s_nQueueSize / s_nThreadCount;
124 for ( size_t i = 0; i < pool.size(); ++i ) {
125 Producer<Queue>& thread = static_cast<Producer<Queue>&>(pool.get( i ));
126 thread.m_nStartItem = nStart;
127 nStart += nThreadItemCount;
128 thread.m_nEndItem = nStart;
131 s_nQueueSize = nThreadItemCount * s_nThreadCount;
132 propout() << std::make_pair( "thread_count", s_nThreadCount )
133 << std::make_pair( "push_count", s_nQueueSize );
135 std::chrono::milliseconds duration = pool.run();
137 propout() << std::make_pair( "duration", duration );
141 propout() << q.statistics();
144 template <class Queue>
145 void analyze( Queue& q )
147 size_t nThreadItems = s_nQueueSize / s_nThreadCount;
148 cds_test::thread_pool& pool = get_pool();
150 for ( size_t i = 0; i < pool.size(); ++i ) {
151 Producer<Queue>& thread = static_cast<Producer<Queue>&>(pool.get( i ));
152 EXPECT_EQ( thread.m_nPushError, 0u ) << " producer thread " << i;
154 EXPECT_TRUE( !q.empty());
156 std::unique_ptr< uint8_t[] > arr( new uint8_t[s_nQueueSize] );
157 memset( arr.get(), 0, sizeof(arr[0]) * s_nQueueSize );
161 while ( q.pop( val )) {
166 size_t nTotalItems = nThreadItems * s_nThreadCount;
167 for ( size_t i = 0; i < nTotalItems; ++i ) {
168 EXPECT_EQ( arr[i], 1 ) << "i=" << i;
173 CDSSTRESS_MSQueue( queue_push )
174 CDSSTRESS_MoirQueue( queue_push )
175 CDSSTRESS_BasketQueue( queue_push )
176 CDSSTRESS_OptimsticQueue( queue_push )
177 CDSSTRESS_RWQueue( queue_push )
179 #undef CDSSTRESS_Queue_F
180 #define CDSSTRESS_Queue_F( test_fixture, type_name ) \
181 TEST_F( test_fixture, type_name ) \
183 typedef queue::Types< value_type >::type_name queue_type; \
184 queue_type queue( s_nQueueSize ); \
188 CDSSTRESS_VyukovQueue( queue_push )
190 #undef CDSSTRESS_Queue_F
193 // ********************************************************************
194 // SegmentedQueue test
196 class segmented_queue_push
198 , public ::testing::WithParamInterface< size_t >
200 typedef queue_push base_class;
203 template <typename Queue>
206 size_t quasi_factor = GetParam();
208 Queue q( quasi_factor );
209 propout() << std::make_pair( "quasi_factor", quasi_factor );
210 base_class::test( q );
214 static std::vector< size_t > get_test_parameters()
216 cds_test::config const& cfg = cds_test::stress_fixture::get_config( "queue_push" );
217 bool bIterative = cfg.get_bool( "SegmentedQueue_Iterate", false );
218 size_t quasi_factor = cfg.get_size_t( "SegmentedQueue_SegmentSize", 256 );
220 std::vector<size_t> args;
221 if ( bIterative && quasi_factor > 4 ) {
222 for ( size_t qf = 4; qf <= quasi_factor; qf *= 2 )
223 args.push_back( qf );
226 if ( quasi_factor > 2 )
227 args.push_back( quasi_factor );
236 #define CDSSTRESS_Queue_F( test_fixture, type_name ) \
237 TEST_P( test_fixture, type_name ) \
239 typedef typename queue::Types<value_type>::type_name queue_type; \
240 test< queue_type >(); \
243 CDSSTRESS_SegmentedQueue( segmented_queue_push )
245 #ifdef CDSTEST_GTEST_INSTANTIATE_TEST_CASE_P_HAS_4TH_ARG
246 static std::string get_test_parameter_name( testing::TestParamInfo<size_t> const& p )
248 return std::to_string( p.param );
250 INSTANTIATE_TEST_CASE_P( SQ,
251 segmented_queue_push,
252 ::testing::ValuesIn( segmented_queue_push::get_test_parameters()), get_test_parameter_name );
254 INSTANTIATE_TEST_CASE_P( SQ,
255 segmented_queue_push,
256 ::testing::ValuesIn( segmented_queue_push::get_test_parameters()));