Text formatting, docfix
[libcds.git] / tests / unit / queue / bounded_queue_fulness.cpp
1 //$$CDS-header$$
2
3 #include "cppunit/thread.h"
4 #include "queue/queue_type.h"
5 #include "queue/queue_defs.h"
6
7
8 /*
9     Bounded queue test.
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.
12 */
13 namespace queue {
14
15 #define TEST_BOUNDED( Q, V )    void Q() { test< Types<V>::Q >(); }
16
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;
21     }
22     using namespace ns_BoundedQueue_Fullness;
23
24     class BoundedQueue_Fullness: public CppUnitMini::TestCase
25     {
26         template <class Queue>
27         class Thread: public CppUnitMini::TestThread
28         {
29             virtual TestThread *    clone()
30             {
31                 return new Thread( *this );
32             }
33         public:
34             Queue&              m_Queue;
35             double              m_fTime;
36             size_t              m_nPushError;
37             size_t              m_nPopError;
38
39         public:
40             Thread( CppUnitMini::ThreadPool& pool, Queue& q )
41                 : CppUnitMini::TestThread( pool )
42                 , m_Queue( q )
43             {}
44             Thread( Thread& src )
45                 : CppUnitMini::TestThread( src )
46                 , m_Queue( src.m_Queue )
47             {}
48
49             BoundedQueue_Fullness&  getTest()
50             {
51                 return reinterpret_cast<BoundedQueue_Fullness&>( m_Pool.m_Test );
52             }
53
54             virtual void init()
55             {
56                 cds::threading::Manager::attachThread();
57             }
58             virtual void fini()
59             {
60                 cds::threading::Manager::detachThread();
61             }
62
63             virtual void test()
64             {
65                 m_fTime = m_Timer.duration();
66
67                 m_nPushError = 0;
68                 m_nPopError = 0;
69                 for ( size_t i = 0; i < s_nPassCount; ++i ) {
70                     if ( !m_Queue.push( i ))
71                         ++m_nPushError;
72                     size_t item;
73                     if ( !m_Queue.pop( item ))
74                         ++m_nPopError;
75                 }
76                 m_fTime = m_Timer.duration() - m_fTime;
77             }
78         };
79
80     protected:
81         template <class Queue>
82         void analyze( CppUnitMini::ThreadPool& pool, Queue& testQueue  )
83         {
84             double fTime = 0;
85             size_t nPushError = 0;
86             size_t nPopError = 0;
87             for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
88                 Thread<Queue> * pThread = reinterpret_cast<Thread<Queue> *>(*it);
89                 fTime += pThread->m_fTime;
90                 nPushError += pThread->m_nPushError;
91                 nPopError  += pThread->m_nPopError;
92             }
93             CPPUNIT_MSG( "     Duration=" << (fTime / s_nThreadCount) );
94             CPPUNIT_MSG( "     Errors: push=" << nPushError << ", pop=" << nPopError );
95             CPPUNIT_CHECK( !testQueue.empty());
96             CPPUNIT_CHECK( nPushError == 0 );
97             CPPUNIT_CHECK( nPopError == 0 );
98         }
99
100         template <class Queue>
101         void test()
102         {
103             Queue testQueue( s_nQueueSize );
104
105             CppUnitMini::ThreadPool pool( *this );
106             pool.add( new Thread<Queue>( pool, testQueue ), s_nThreadCount );
107
108             size_t nSize = testQueue.capacity() - s_nThreadCount;
109             for ( size_t i = 0; i < nSize; ++i )
110                 testQueue.push( i );
111
112             CPPUNIT_MSG( "   Thread count=" << s_nThreadCount << ", push/pop pairs=" << s_nPassCount
113
114                          << ", queue capacity=" << testQueue.capacity() << " ...");
115             pool.run();
116
117             analyze( pool, testQueue );
118
119             CPPUNIT_MSG( testQueue.statistics() );
120         }
121         void setUpParams( const CppUnitMini::TestCfg& cfg ) {
122             s_nThreadCount = cfg.getULong("ThreadCount", 8 );
123             s_nQueueSize = cfg.getULong("QueueSize", 1024 );
124             s_nPassCount = cfg.getULong( "PassCount", 1000000 );
125         }
126
127     protected:
128         CDSUNIT_DECLARE_TsigasCycleQueue( size_t )
129         CDSUNIT_DECLARE_VyukovMPMCCycleQueue( size_t )
130
131         CPPUNIT_TEST_SUITE( BoundedQueue_Fullness )
132             CDSUNIT_TEST_TsigasCycleQueue
133             CDSUNIT_TEST_VyukovMPMCCycleQueue
134         CPPUNIT_TEST_SUITE_END();
135     };
136
137 } // namespace queue
138
139 CPPUNIT_TEST_SUITE_REGISTRATION(queue::BoundedQueue_Fullness );