2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
6 Source code repo: http://github.com/khizmax/libcds/
7 Download: http://sourceforge.net/projects/libcds/files/
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice, this
13 list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice,
16 this list of conditions and the following disclaimer in the documentation
17 and/or other materials provided with the distribution.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "cppunit/thread.h"
32 #include "queue/queue_type.h"
33 #include "queue/queue_defs.h"
35 // Multi-threaded queue test for pop operation
38 #define TEST_CASE( Q, V ) void Q() { test< Types<V>::Q >(); }
39 #define TEST_BOUNDED( Q, V ) void Q() { test_bounded< Types<V>::Q >(); }
40 #define TEST_SEGMENTED( Q, V ) void Q() { test_segmented< Types<V>::Q >(); }
42 namespace ns_Queue_Pop {
43 static size_t s_nThreadCount = 8;
44 static size_t s_nQueueSize = 20000000 ; // no more than 20 million records
49 SimpleValue(): nNo(0) {}
50 SimpleValue( size_t n ): nNo(n) {}
51 size_t getNo() const { return nNo; }
54 using namespace ns_Queue_Pop;
56 class Queue_Pop: public CppUnitMini::TestCase
58 template <class Queue>
59 class Thread: public CppUnitMini::TestThread
61 virtual TestThread * clone()
63 return new Thread( *this );
72 Thread( CppUnitMini::ThreadPool& pool, Queue& q )
73 : CppUnitMini::TestThread( pool )
76 m_arr = new long[s_nQueueSize];
79 : CppUnitMini::TestThread( src )
80 , m_Queue( src.m_Queue )
82 m_arr = new long[s_nQueueSize];
91 return reinterpret_cast<Queue_Pop&>( m_Pool.m_Test );
96 cds::threading::Manager::attachThread();
97 memset(m_arr, 0, sizeof(m_arr[0]) * s_nQueueSize );
101 cds::threading::Manager::detachThread();
106 m_fTime = m_Timer.duration();
108 typedef typename Queue::value_type value_type;
109 value_type value = value_type();
110 size_t nPopCount = 0;
111 while ( m_Queue.pop( value ) ) {
112 ++m_arr[ value.getNo() ];
115 m_nPopCount = nPopCount;
117 m_fTime = m_Timer.duration() - m_fTime;
123 template <class Queue>
124 void analyze( CppUnitMini::ThreadPool& pool, Queue& testQueue )
126 size_t * arr = new size_t[ s_nQueueSize ];
127 memset(arr, 0, sizeof(arr[0]) * s_nQueueSize );
130 size_t nTotalPops = 0;
131 for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
132 Thread<Queue> * pThread = reinterpret_cast<Thread<Queue> *>(*it);
133 for ( size_t i = 0; i < s_nQueueSize; ++i )
134 arr[i] += pThread->m_arr[i];
135 nTotalPops += pThread->m_nPopCount;
136 fTime += pThread->m_fTime;
138 CPPUNIT_MSG( " Duration=" << (fTime / s_nThreadCount) );
139 CPPUNIT_CHECK_EX( nTotalPops == s_nQueueSize, "Total pop=" << nTotalPops << ", queue size=" << s_nQueueSize);
140 CPPUNIT_CHECK( testQueue.empty() )
143 for ( size_t i = 0; i < s_nQueueSize; ++i ) {
145 CPPUNIT_MSG( " ERROR: Item " << i << " has not been popped" );
146 CPPUNIT_ASSERT( ++nError <= 10 );
153 template <class Queue>
157 CppUnitMini::ThreadPool pool( *this );
158 pool.add( new Thread<Queue>( pool, testQueue ), s_nThreadCount );
160 CPPUNIT_MSG( " Create queue size =" << s_nQueueSize << " ...");
161 cds::OS::Timer timer;
162 for ( size_t i = 0; i < s_nQueueSize; ++i )
164 CPPUNIT_MSG( " Duration=" << timer.duration() );
166 CPPUNIT_MSG( " Pop test, thread count=" << s_nThreadCount << " ...");
169 analyze( pool, testQueue );
171 CPPUNIT_MSG( testQueue.statistics() );
174 template <class Queue>
177 Queue testQueue( s_nQueueSize );
178 CppUnitMini::ThreadPool pool( *this );
179 pool.add( new Thread<Queue>( pool, testQueue ), s_nThreadCount );
181 CPPUNIT_MSG( " Create queue size =" << s_nQueueSize << " ...");
182 cds::OS::Timer timer;
183 for ( size_t i = 0; i < s_nQueueSize; ++i )
185 CPPUNIT_MSG( " Duration=" << timer.duration() );
187 CPPUNIT_MSG( " Pop test, thread count=" << s_nThreadCount << " ...");
190 analyze( pool, testQueue );
192 CPPUNIT_MSG( testQueue.statistics() );
195 template <class Queue>
196 void test_segmented()
198 for ( size_t nSegmentSize = 4; nSegmentSize <= 256; nSegmentSize *= 4 ) {
199 CPPUNIT_MSG( "Segment size: " << nSegmentSize );
201 Queue testQueue( nSegmentSize );
202 CppUnitMini::ThreadPool pool( *this );
203 pool.add( new Thread<Queue>( pool, testQueue ), s_nThreadCount );
205 CPPUNIT_MSG( " Create queue size =" << s_nQueueSize << " ...");
206 cds::OS::Timer timer;
207 for ( size_t i = 0; i < s_nQueueSize; ++i )
209 CPPUNIT_MSG( " Duration=" << timer.duration() );
211 CPPUNIT_MSG( " Pop test, thread count=" << s_nThreadCount << " ...");
214 analyze( pool, testQueue );
216 CPPUNIT_MSG( testQueue.statistics() );
220 void setUpParams( const CppUnitMini::TestCfg& cfg ) {
221 s_nThreadCount = cfg.getULong("ThreadCount", 8 );
222 s_nQueueSize = cfg.getULong("QueueSize", 20000000 );
226 CDSUNIT_DECLARE_MoirQueue( SimpleValue )
227 CDSUNIT_DECLARE_MSQueue( SimpleValue )
228 CDSUNIT_DECLARE_OptimisticQueue( SimpleValue )
229 CDSUNIT_DECLARE_BasketQueue( SimpleValue )
230 CDSUNIT_DECLARE_FCQueue( SimpleValue )
231 CDSUNIT_DECLARE_FCDeque( SimpleValue )
232 CDSUNIT_DECLARE_SegmentedQueue( SimpleValue )
233 CDSUNIT_DECLARE_RWQueue( SimpleValue )
234 CDSUNIT_DECLARE_TsigasCycleQueue( SimpleValue )
235 CDSUNIT_DECLARE_VyukovMPMCCycleQueue( SimpleValue )
236 CDSUNIT_DECLARE_StdQueue( SimpleValue )
238 CPPUNIT_TEST_SUITE(Queue_Pop)
239 CDSUNIT_TEST_MoirQueue
241 CDSUNIT_TEST_OptimisticQueue
242 CDSUNIT_TEST_BasketQueue
245 CDSUNIT_TEST_SegmentedQueue
247 CDSUNIT_TEST_TsigasCycleQueue
248 CDSUNIT_TEST_VyukovMPMCCycleQueue
249 CDSUNIT_TEST_StdQueue
250 CPPUNIT_TEST_SUITE_END();
255 CPPUNIT_TEST_SUITE_REGISTRATION(queue::Queue_Pop);