3 #include "cppunit/thread.h"
4 #include "queue/queue_type.h"
5 #include "queue/queue_defs.h"
10 The test checks the behaviour of bounded queue when it is almost full.
11 Many algorithms says the queue is full when it is not, and vice versa.
15 #define TEST_BOUNDED( Q, V ) void Q() { test< Types<V>::Q >(); }
17 namespace ns_BoundedQueue_Fullness {
18 static size_t s_nThreadCount = 8;
19 static size_t s_nQueueSize = 1024;
20 static size_t s_nPassCount = 1000000;
22 using namespace ns_BoundedQueue_Fullness;
24 class VyukovMPMCCycleQueue_dyn_fair_ : public Types<size_t>::VyukovMPMCCycleQueue_dyn_ic
26 typedef Types<size_t>::VyukovMPMCCycleQueue_dyn_ic base_class;
28 typedef base_class::value_type value_type;
30 VyukovMPMCCycleQueue_dyn_fair_()
34 VyukovMPMCCycleQueue_dyn_fair_( size_t nCapacity )
35 : base_class( nCapacity )
38 bool enqueue( value_type const& data )
42 ret = base_class::enqueue( data );
43 } while ( !ret && size() != capacity() );
47 bool push( value_type const& data )
49 return enqueue( data );
52 bool dequeue( value_type& dest )
56 ret = base_class::dequeue( dest );
57 } while ( !ret && size() != capacity() );
61 bool pop( value_type& dest )
63 return dequeue( dest );
66 size_t size() const { return base_class::size(); }
67 size_t capacity() const { return base_class::capacity(); }
70 class BoundedQueue_Fullness: public CppUnitMini::TestCase
72 template <class Queue>
73 class Thread: public CppUnitMini::TestThread
75 virtual TestThread * clone()
77 return new Thread( *this );
86 Thread( CppUnitMini::ThreadPool& pool, Queue& q )
87 : CppUnitMini::TestThread( pool )
91 : CppUnitMini::TestThread( src )
92 , m_Queue( src.m_Queue )
95 BoundedQueue_Fullness& getTest()
97 return reinterpret_cast<BoundedQueue_Fullness&>( m_Pool.m_Test );
102 cds::threading::Manager::attachThread();
106 cds::threading::Manager::detachThread();
111 m_fTime = m_Timer.duration();
115 for ( size_t i = 0; i < s_nPassCount; ++i ) {
116 if ( !m_Queue.push( i ))
119 if ( !m_Queue.pop( item ))
122 m_fTime = m_Timer.duration() - m_fTime;
127 template <class Queue>
128 void analyze( CppUnitMini::ThreadPool& pool, Queue& testQueue )
131 size_t nPushError = 0;
132 size_t nPopError = 0;
133 for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
134 Thread<Queue> * pThread = reinterpret_cast<Thread<Queue> *>(*it);
135 fTime += pThread->m_fTime;
136 nPushError += pThread->m_nPushError;
137 nPopError += pThread->m_nPopError;
139 CPPUNIT_MSG( " Duration=" << (fTime / s_nThreadCount) );
140 CPPUNIT_MSG( " Errors: push=" << nPushError << ", pop=" << nPopError );
141 CPPUNIT_CHECK( !testQueue.empty());
142 CPPUNIT_CHECK( nPushError == 0 );
143 CPPUNIT_CHECK( nPopError == 0 );
146 template <class Queue>
149 Queue testQueue( s_nQueueSize );
151 CppUnitMini::ThreadPool pool( *this );
152 pool.add( new Thread<Queue>( pool, testQueue ), s_nThreadCount );
154 size_t nSize = testQueue.capacity() - s_nThreadCount;
155 for ( size_t i = 0; i < nSize; ++i )
158 CPPUNIT_MSG( " Thread count=" << s_nThreadCount << ", push/pop pairs=" << s_nPassCount
159 << ", queue capacity=" << testQueue.capacity() << " ...");
162 analyze( pool, testQueue );
164 CPPUNIT_MSG( testQueue.statistics() );
166 void setUpParams( const CppUnitMini::TestCfg& cfg ) {
167 s_nThreadCount = cfg.getULong("ThreadCount", 8 );
168 s_nQueueSize = cfg.getULong("QueueSize", 1024 );
169 s_nPassCount = cfg.getULong( "PassCount", 1000000 );
173 CDSUNIT_DECLARE_TsigasCycleQueue( size_t )
174 CDSUNIT_DECLARE_VyukovMPMCCycleQueue( size_t )
175 void VyukovMPMCCycleQueue_dyn_fair()
177 test< VyukovMPMCCycleQueue_dyn_fair_ >();
180 CPPUNIT_TEST_SUITE( BoundedQueue_Fullness )
181 CDSUNIT_TEST_TsigasCycleQueue
182 CDSUNIT_TEST_VyukovMPMCCycleQueue
183 CPPUNIT_TEST( VyukovMPMCCycleQueue_dyn_fair_ ) \
184 CPPUNIT_TEST_SUITE_END();
189 CPPUNIT_TEST_SUITE_REGISTRATION(queue::BoundedQueue_Fullness );