/*
This file is a part of libcds - Concurrent Data Structures library
- (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
Source code repo: http://github.com/khizmax/libcds/
Download: http://sourceforge.net/projects/libcds/files/
-
+
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
#include <vector>
#include <algorithm>
+#include <type_traits>
// Multi-threaded queue push/pop test
namespace {
static size_t s_nConsumerThreadCount = 4;
static size_t s_nProducerThreadCount = 4;
static size_t s_nQueueSize = 4000000;
+ static size_t s_nHeavyValueSize = 100;
static std::atomic<size_t> s_nProducerDone( 0 );
+ struct old_value
+ {
+ size_t nNo;
+ size_t nWriterNo;
+ };
+
+ template<class Value = old_value>
class queue_push_pop: public cds_test::stress_fixture
{
protected:
- struct value_type
- {
- size_t nNo;
- size_t nWriterNo;
- };
+ using value_type = Value;
enum {
producer_thread,
const size_t nTotalWriters = s_nProducerThreadCount;
value_type v;
while ( true ) {
- if ( m_Queue.pop( v ) ) {
+ if ( m_Queue.pop( v )) {
++m_nPopped;
if ( v.nWriterNo < nTotalWriters )
m_WriterData[ v.nWriterNo ].push_back( v.nNo );
++m_nPopEmpty;
if ( s_nProducerDone.load() >= nTotalWriters ) {
- if ( m_Queue.empty() )
+ if ( m_Queue.empty())
break;
}
}
{
cds_test::thread_pool& pool = get_pool();
- typedef Consumer<Queue> Consumer;
- typedef Producer<Queue> Producer;
+ typedef Consumer<Queue> consumer_type;
+ typedef Producer<Queue> producer_type;
size_t nPostTestPops = 0;
{
size_t nPoppedItems = 0;
size_t nPushFailed = 0;
- std::vector< Consumer * > arrConsumer;
+ std::vector< consumer_type * > arrConsumer;
for ( size_t i = 0; i < pool.size(); ++i ) {
cds_test::thread& thr = pool.get(i);
if ( thr.type() == consumer_thread ) {
- Consumer& consumer = static_cast<Consumer&>( thr );
+ consumer_type& consumer = static_cast<consumer_type&>( thr );
nTotalPops += consumer.m_nPopped;
nPopFalse += consumer.m_nPopEmpty;
arrConsumer.push_back( &consumer );
- EXPECT_EQ( consumer.m_nBadWriter, 0 ) << "consumer_thread_no " << i;
+ EXPECT_EQ( consumer.m_nBadWriter, 0u ) << "consumer_thread_no " << i;
size_t nPopped = 0;
for ( size_t n = 0; n < s_nProducerThreadCount; ++n )
else {
assert( thr.type() == producer_thread );
- Producer& producer = static_cast<Producer&>( thr );
+ producer_type& producer = static_cast<producer_type&>( thr );
nPushFailed += producer.m_nPushFailed;
- EXPECT_EQ( producer.m_nPushFailed, 0 ) << "producer_thread_no " << i;
+ EXPECT_EQ( producer.m_nPushFailed, 0u ) << "producer_thread_no " << i;
}
}
EXPECT_EQ( nTotalPops, nPoppedItems );
EXPECT_EQ( nTotalPops + nPostTestPops, s_nQueueSize ) << "nTotalPops=" << nTotalPops << ", nPostTestPops=" << nPostTestPops;
- EXPECT_TRUE( q.empty() );
+ EXPECT_TRUE( q.empty());
// Test consistency of popped sequence
for ( size_t nWriter = 0; nWriter < s_nProducerThreadCount; ++nWriter ) {
arrData.push_back( *it );
}
- std::sort( arrData.begin(), arrData.end() );
+ std::sort( arrData.begin(), arrData.end());
for ( size_t i=1; i < arrData.size(); ++i ) {
EXPECT_EQ( arrData[i - 1] + 1, arrData[i] ) << "producer=" << nWriter;
}
- EXPECT_EQ( arrData[0], 0 ) << "producer=" << nWriter;
+ EXPECT_EQ( arrData[0], 0u ) << "producer=" << nWriter;
EXPECT_EQ( arrData[arrData.size() - 1], m_nThreadPushCount - 1 ) << "producer=" << nWriter;
}
}
propout() << q.statistics();
}
+ private:
+ static void set_array_size( size_t size ) {
+ const bool tmp = fc_test::has_set_array_size<value_type>::value;
+ set_array_size(size, std::integral_constant<bool, tmp>());
+ }
+
+ static void set_array_size(size_t size, std::true_type){
+ value_type::set_array_size(size);
+ }
+
+ static void set_array_size(size_t, std::false_type)
+ {
+ }
+
public:
- static void SetUpTestCase()\r
- {\r
- cds_test::config const& cfg = get_config( "queue_push_pop" );\r
-\r
+ static void SetUpTestCase()
+ {
+ cds_test::config const& cfg = get_config( "queue_push_pop" );
+
s_nConsumerThreadCount = cfg.get_size_t( "ConsumerCount", s_nConsumerThreadCount );
s_nProducerThreadCount = cfg.get_size_t( "ProducerCount", s_nProducerThreadCount );
s_nQueueSize = cfg.get_size_t( "QueueSize", s_nQueueSize );
+ s_nHeavyValueSize = cfg.get_size_t( "HeavyValueSize", s_nHeavyValueSize );
- if ( s_nConsumerThreadCount == 0 )
+ if ( s_nConsumerThreadCount == 0u )
s_nConsumerThreadCount = 1;
- if ( s_nProducerThreadCount == 0 )
+ if ( s_nProducerThreadCount == 0u )
s_nProducerThreadCount = 1;
- if ( s_nQueueSize == 0 )
+ if ( s_nQueueSize == 0u )
s_nQueueSize = 1000;
- }\r
-\r
- //static void TearDownTestCase();\r
+ if ( s_nHeavyValueSize == 0 )
+ s_nHeavyValueSize = 1;
+
+ set_array_size( s_nHeavyValueSize );
+ }
+
+ //static void TearDownTestCase();
};
- CDSSTRESS_MSQueue( queue_push_pop )
- CDSSTRESS_MoirQueue( queue_push_pop )
- CDSSTRESS_BasketQueue( queue_push_pop )
- CDSSTRESS_OptimsticQueue( queue_push_pop )
- CDSSTRESS_FCQueue( queue_push_pop )
- CDSSTRESS_FCDeque( queue_push_pop )
- CDSSTRESS_RWQueue( queue_push_pop )
- CDSSTRESS_StdQueue( queue_push_pop )
+ using fc_with_heavy_value = queue_push_pop< fc_test::heavy_value<36000> >;
+ using simple_queue_push_pop = queue_push_pop<>;
+
+ CDSSTRESS_MSQueue( simple_queue_push_pop )
+ CDSSTRESS_MoirQueue( simple_queue_push_pop )
+ CDSSTRESS_BasketQueue( simple_queue_push_pop )
+ CDSSTRESS_OptimsticQueue( simple_queue_push_pop )
+ CDSSTRESS_FCQueue( simple_queue_push_pop )
+ CDSSTRESS_FCDeque( simple_queue_push_pop )
+ CDSSTRESS_FCDeque_HeavyValue( fc_with_heavy_value )
+ CDSSTRESS_RWQueue( simple_queue_push_pop )
+ CDSSTRESS_StdQueue( simple_queue_push_pop )
#undef CDSSTRESS_Queue_F
-#define CDSSTRESS_Queue_F( test_fixture, type_name, level ) \
+#define CDSSTRESS_Queue_F( test_fixture, type_name ) \
TEST_F( test_fixture, type_name ) \
{ \
- if ( !check_detail_level( level )) return; \
typedef queue::Types< value_type >::type_name queue_type; \
queue_type queue( s_nQueueSize ); \
test( queue ); \
}
- CDSSTRESS_TsigasQueue( queue_push_pop )
- CDSSTRESS_VyukovQueue( queue_push_pop )
+ CDSSTRESS_VyukovQueue( simple_queue_push_pop )
#undef CDSSTRESS_Queue_F
// SegmentedQueue test
class segmented_queue_push_pop
- : public queue_push_pop
+ : public queue_push_pop<>
, public ::testing::WithParamInterface< size_t >
{
- typedef queue_push_pop base_class;
+ typedef queue_push_pop<> base_class;
protected:
if ( bIterative && quasi_factor > 4 ) {
for ( size_t qf = 4; qf <= quasi_factor; qf *= 2 )
args.push_back( qf );
- }
- else {
+ } else {
if ( quasi_factor > 2 )
args.push_back( quasi_factor );
else
}
};
-#define CDSSTRESS_Queue_F( test_fixture, type_name, level ) \
+#define CDSSTRESS_Queue_F( test_fixture, type_name ) \
TEST_P( test_fixture, type_name ) \
{ \
- if ( !check_detail_level( level )) return; \
typedef typename queue::Types<value_type>::type_name queue_type; \
test< queue_type >(); \
}
CDSSTRESS_SegmentedQueue( segmented_queue_push_pop )
+#ifdef CDSTEST_GTEST_INSTANTIATE_TEST_CASE_P_HAS_4TH_ARG
+ static std::string get_test_parameter_name( testing::TestParamInfo<size_t> const& p )
+ {
+ return std::to_string( p.param );
+ }
+ INSTANTIATE_TEST_CASE_P( SQ,
+ segmented_queue_push_pop,
+ ::testing::ValuesIn( segmented_queue_push_pop::get_test_parameters()), get_test_parameter_name );
+#else
INSTANTIATE_TEST_CASE_P( SQ,
segmented_queue_push_pop,
::testing::ValuesIn( segmented_queue_push_pop::get_test_parameters()));
+#endif
} // namespace