3 #include "cppunit/thread.h"
4 #include "pqueue/pqueue_item.h"
5 #include "pqueue/pqueue_type.h"
8 #include <algorithm> // random_shuffle
13 #define TEST_CASE( Q ) void Q() { test< Types<pqueue::SimpleValue>::Q >(); }
14 #define TEST_BOUNDED( Q ) void Q() { test_bounded< Types<pqueue::SimpleValue>::Q >(); }
17 static size_t s_nPushThreadCount = 4;
18 static size_t s_nPopThreadCount = 4;
19 static size_t s_nQueueSize = 2000000;
25 class PQueue_PushPop: public CppUnitMini::TestCase
28 template <class PQueue>
29 class Pusher: public CppUnitMini::TestThread
31 virtual TestThread * clone()
33 return new Pusher( *this );
39 typedef std::vector<size_t> array_type;
43 Pusher( CppUnitMini::ThreadPool& pool, PQueue& q )
44 : CppUnitMini::TestThread( pool )
48 : CppUnitMini::TestThread( src )
49 , m_Queue( src.m_Queue )
52 PQueue_PushPop& getTest()
54 return static_cast<PQueue_PushPop&>( m_Pool.m_Test );
59 cds::threading::Manager::attachThread();
63 cds::threading::Manager::detachThread();
70 for ( array_type::const_iterator it = m_arr.begin(); it != m_arr.end(); ++it ) {
71 if ( !m_Queue.push( SimpleValue( *it ) ))
75 getTest().end_pusher();
78 void prepare( size_t nStart, size_t nEnd )
80 m_arr.reserve( nEnd - nStart );
81 for ( size_t i = nStart; i < nEnd; ++i )
83 std::random_shuffle( m_arr.begin(), m_arr.end() );
87 template <class PQueue>
88 class Popper: public CppUnitMini::TestThread
90 virtual TestThread * clone()
92 return new Popper( *this );
99 typedef std::vector<size_t> array_type;
103 Popper( CppUnitMini::ThreadPool& pool, PQueue& q )
104 : CppUnitMini::TestThread( pool )
107 Popper( Popper& src )
108 : CppUnitMini::TestThread( src )
109 , m_Queue( src.m_Queue )
112 PQueue_PushPop& getTest()
114 return static_cast<PQueue_PushPop&>( m_Pool.m_Test );
119 cds::threading::Manager::attachThread();
123 cds::threading::Manager::detachThread();
132 while ( getTest().pushing() || !m_Queue.empty() ) {
133 if ( m_Queue.pop( val ))
141 size_t m_nPusherCount;
148 return m_nPusherCount != 0;
152 template <class PQueue>
156 test_with( testQueue );
159 template <class PQueue>
162 std::unique_ptr<PQueue> pq( new PQueue(s_nQueueSize) );
163 test_with( *pq.get() );
166 template <class PQueue>
167 void test_with( PQueue& testQueue )
169 size_t const nThreadItemCount = s_nQueueSize / s_nPushThreadCount;
171 CppUnitMini::ThreadPool pool( *this );
172 pool.add( new Pusher<PQueue>( pool, testQueue ), s_nPushThreadCount );
175 for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
176 Pusher<PQueue> * pThread = static_cast<Pusher<PQueue> *>(*it);
177 pThread->prepare( nStart, nStart + nThreadItemCount );
178 nStart += nThreadItemCount;
181 pool.add( new Popper<PQueue>( pool, testQueue ), s_nPopThreadCount );
183 m_nPusherCount = s_nPushThreadCount;
184 CPPUNIT_MSG( " push thread count=" << s_nPushThreadCount << " pop thread count=" << s_nPopThreadCount
185 << ", item count=" << nThreadItemCount * s_nPushThreadCount << " ..." );
187 CPPUNIT_MSG( " Duration=" << pool.avgDuration() );
190 size_t nTotalPopped = 0;
191 size_t nPushFailed = 0;
192 size_t nPopFailed = 0;
193 for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
194 Popper<PQueue> * pPopper = dynamic_cast<Popper<PQueue> *>(*it);
196 nTotalPopped += pPopper->m_nPopSuccess;
197 nPopFailed += pPopper->m_nPopFailed;
200 Pusher<PQueue> * pPusher = dynamic_cast<Pusher<PQueue> *>(*it);
202 nPushFailed += pPusher->m_nPushError;
206 CPPUNIT_MSG( " Total: popped=" << nTotalPopped << ", empty pop=" << nPopFailed << ", push error=" << nPushFailed );
207 CPPUNIT_CHECK( nTotalPopped == nThreadItemCount * s_nPushThreadCount );
208 CPPUNIT_CHECK( nPushFailed == 0 );
210 check_statistics( testQueue.statistics() );
211 CPPUNIT_MSG( testQueue.statistics() );
214 void setUpParams( const CppUnitMini::TestCfg& cfg ) {
215 s_nPushThreadCount = cfg.getULong("PushThreadCount", (unsigned long) s_nPushThreadCount );
216 s_nPopThreadCount = cfg.getULong("PopThreadCount", (unsigned long) s_nPopThreadCount );
217 s_nQueueSize = cfg.getULong("QueueSize", (unsigned long) s_nQueueSize );
221 #include "pqueue/pqueue_defs.h"
222 CDSUNIT_DECLARE_MSPriorityQueue
223 CDSUNIT_DECLARE_EllenBinTree
224 CDSUNIT_DECLARE_SkipList
225 CDSUNIT_DECLARE_FCPriorityQueue
226 CDSUNIT_DECLARE_StdPQueue
228 CPPUNIT_TEST_SUITE(PQueue_PushPop)
229 CDSUNIT_TEST_MSPriorityQueue
230 CDSUNIT_TEST_EllenBinTree
231 CDSUNIT_TEST_SkipList
232 CDSUNIT_TEST_FCPriorityQueue
233 CDUNIT_TEST_StdPQueue
234 CPPUNIT_TEST_SUITE_END();
239 CPPUNIT_TEST_SUITE_REGISTRATION(pqueue::PQueue_PushPop);