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_nThreadCount = 8;
18 static size_t s_nQueueSize = 2000000;
24 class PQueue_Pop: public CppUnitMini::TestCase
27 template <class PQueue>
28 class Pusher: public CppUnitMini::TestThread
30 virtual TestThread * clone()
32 return new Pusher( *this );
38 typedef std::vector<size_t> array_type;
42 Pusher( CppUnitMini::ThreadPool& pool, PQueue& q )
43 : CppUnitMini::TestThread( pool )
47 : CppUnitMini::TestThread( src )
48 , m_Queue( src.m_Queue )
53 return static_cast<PQueue_Pop&>( m_Pool.m_Test );
58 cds::threading::Manager::attachThread();
62 cds::threading::Manager::detachThread();
69 for ( array_type::const_iterator it = m_arr.begin(); it != m_arr.end(); ++it ) {
70 if ( !m_Queue.push( SimpleValue( *it ) ))
75 void prepare( size_t nStart, size_t nEnd )
77 m_arr.reserve( nEnd - nStart );
78 for ( size_t i = nStart; i < nEnd; ++i )
80 std::random_shuffle( m_arr.begin(), m_arr.end() );
84 template <class PQueue>
85 class Popper: public CppUnitMini::TestThread
87 virtual TestThread * clone()
89 return new Popper( *this );
98 typedef std::vector<size_t> array_type;
102 Popper( CppUnitMini::ThreadPool& pool, PQueue& q )
103 : CppUnitMini::TestThread( pool )
106 Popper( Popper& src )
107 : CppUnitMini::TestThread( src )
108 , m_Queue( src.m_Queue )
111 PQueue_Pop& getTest()
113 return static_cast<PQueue_Pop&>( m_Pool.m_Test );
118 cds::threading::Manager::attachThread();
122 cds::threading::Manager::detachThread();
134 if ( m_Queue.pop( val )) {
138 while ( !m_Queue.empty() ) {
139 if ( m_Queue.pop( val )) {
141 if ( val.key > nPrevKey )
143 else if ( val.key == nPrevKey )
155 template <class PQueue>
159 test_with( testQueue );
162 template <class PQueue>
165 std::unique_ptr<PQueue> pq( new PQueue(s_nQueueSize) );
166 test_with( *pq.get() );
169 template <class PQueue>
170 void test_with( PQueue& testQueue )
172 size_t const nThreadItemCount = s_nQueueSize / s_nThreadCount;
176 CppUnitMini::ThreadPool pool( *this );
177 pool.add( new Pusher<PQueue>( pool, testQueue ), s_nThreadCount );
180 for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
181 Pusher<PQueue> * pThread = static_cast<Pusher<PQueue> *>(*it);
182 pThread->prepare( nStart, nStart + nThreadItemCount );
183 nStart += nThreadItemCount;
186 CPPUNIT_MSG( " Push, thread count=" << s_nThreadCount << ", item count=" << nThreadItemCount * s_nThreadCount << " ..." );
188 CPPUNIT_MSG( " Duration=" << pool.avgDuration() );
193 CppUnitMini::ThreadPool pool( *this );
194 pool.add( new Popper<PQueue>( pool, testQueue ), s_nThreadCount );
196 CPPUNIT_MSG( " Pop, thread count=" << s_nThreadCount << ", item count=" << nThreadItemCount * s_nThreadCount << " ..." );
198 CPPUNIT_MSG( " Duration=" << pool.avgDuration() );
201 size_t nTotalPopped = 0;
202 size_t nTotalError = 0;
203 size_t nTotalErrorEq = 0;
204 size_t nTotalFailed = 0;
205 for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
206 Popper<PQueue> * pThread = static_cast<Popper<PQueue> *>(*it);
208 nTotalPopped += pThread->m_nPopSuccess;
209 nTotalError += pThread->m_nPopError;
210 nTotalErrorEq += pThread->m_nPopErrorEq;
211 nTotalFailed += pThread->m_nPopFailed;
214 CPPUNIT_MSG( " Total: popped=" << nTotalPopped << ", empty pop=" << nTotalFailed
215 << "\n Errors: pop equal=" << nTotalErrorEq << ", priority violation=" << nTotalError
217 CPPUNIT_CHECK( nTotalPopped == nThreadItemCount * s_nThreadCount );
218 CPPUNIT_CHECK( nTotalError == 0 );
219 CPPUNIT_CHECK( nTotalErrorEq == 0 );
222 CPPUNIT_MSG( testQueue.statistics() );
225 void setUpParams( const CppUnitMini::TestCfg& cfg ) {
226 s_nThreadCount = cfg.getULong("ThreadCount", (unsigned long) s_nThreadCount );
227 s_nQueueSize = cfg.getULong("QueueSize", (unsigned long) s_nQueueSize );
231 #include "pqueue/pqueue_defs.h"
232 CDSUNIT_DECLARE_MSPriorityQueue
233 CDSUNIT_DECLARE_EllenBinTree
234 CDSUNIT_DECLARE_SkipList
235 CDSUNIT_DECLARE_FCPriorityQueue
236 CDSUNIT_DECLARE_StdPQueue
238 CPPUNIT_TEST_SUITE_(PQueue_Pop, "PQueue_Push")
239 CDSUNIT_TEST_MSPriorityQueue
240 CDSUNIT_TEST_EllenBinTree
241 CDSUNIT_TEST_SkipList
242 CDSUNIT_TEST_FCPriorityQueue
243 CDUNIT_TEST_StdPQueue
244 CPPUNIT_TEST_SUITE_END();
249 CPPUNIT_TEST_SUITE_REGISTRATION(pqueue::PQueue_Pop);