3 #ifndef __CDSHDR_QUEUE_SEGMENTED_QUEUE_H
4 #define __CDSHDR_QUEUE_SEGMENTED_QUEUE_H
6 #include "cppunit/cppunit_proxy.h"
7 #include <cds/intrusive/details/base.h>
8 #include "size_check.h"
12 class HdrSegmentedQueue: public CppUnitMini::TestCase
18 item( size_t v ): nVal(v) {}
19 item( size_t nMajor, size_t nMinor ): nVal( nMajor * 16 + nMinor ) {}
26 template <typename Queue>
29 for ( size_t nQuasiFactor = 2; nQuasiFactor <= 256; ++nQuasiFactor ) {
30 CPPUNIT_MSG( "QuasiFactor=" << nQuasiFactor << "..." );
31 test_qf<Queue>( nQuasiFactor );
35 template <typename Queue>
36 void test_qf( size_t nQuasiFactor )
38 typedef typename Queue::value_type value_type;
40 static size_t const c_nItemCount = 1000;
43 Queue q( nQuasiFactor );
44 CPPUNIT_CHECK( q.quasi_factor() == cds::beans::ceil2(nQuasiFactor) );
45 CPPUNIT_CHECK( q.empty() );
46 CPPUNIT_CHECK( misc::check_size( q, 0 ));
49 for ( size_t i = 0; i < c_nItemCount; ++i ) {
51 CPPUNIT_ASSERT( q.push(item(i)) );
54 CPPUNIT_ASSERT( q.enqueue(item(i)) );
56 CPPUNIT_CHECK( misc::check_size( q, i + 1 ));
57 CPPUNIT_CHECK( !q.empty() );
62 while ( !q.empty() ) {
65 CPPUNIT_ASSERT( q.pop( v ) );
68 CPPUNIT_ASSERT( q.dequeue( v ));
71 int nSegment = int( nCount / q.quasi_factor() );
72 int nMin = nSegment * int(q.quasi_factor());
73 int nMax = nMin + int(q.quasi_factor()) - 1;
74 CPPUNIT_CHECK_EX( nMin <= static_cast<int>(v.nVal) && static_cast<int>( v.nVal ) <= nMax, nMin << " <= " << v.nVal << " <= " << nMax );
77 CPPUNIT_CHECK( misc::check_size( q, c_nItemCount - nCount ));
79 CPPUNIT_CHECK( nCount == c_nItemCount );
80 CPPUNIT_CHECK( q.empty() );
81 CPPUNIT_CHECK( misc::check_size( q, 0 ));
84 // push/pop with functor
85 for ( size_t i = 0; i < c_nItemCount; ++i ) {
89 CPPUNIT_ASSERT( q.push_with( [&itm]( item& dest ) { dest.nVal = itm.nVal; } ));
92 CPPUNIT_ASSERT( q.enqueue_with( [&itm]( item& dest ) { dest.nVal = itm.nVal; } ));
94 CPPUNIT_CHECK( misc::check_size( q, i + 1 ));
95 CPPUNIT_CHECK( !q.empty() );
102 size_t nFuncCount = 0;
103 while ( !q.empty() ) {
105 CPPUNIT_ASSERT( q.pop_with( [&v, &nFuncCount]( item& src ) {v.nVal = src.nVal; ++nFuncCount; } ));
108 CPPUNIT_ASSERT( q.dequeue_with( [&v, &nFuncCount]( item& src ) {v.nVal = src.nVal; ++nFuncCount; } ));
111 // It is possible c_nItemCount % quasi_factor() != 0
112 // In this case the segment cannot be calculated here
113 size_t nMin = nCount > q.quasi_factor() ? nCount - q.quasi_factor() : 0;
114 size_t nMax = nCount + q.quasi_factor();
115 CPPUNIT_CHECK_EX( nMin <= v.nVal && v.nVal <= nMax, nMin << " <= " << v.nVal << " <= " << nMax );
118 CPPUNIT_CHECK( nFuncCount == nCount );
119 CPPUNIT_CHECK( misc::check_size( q, c_nItemCount - nCount ));
121 CPPUNIT_CHECK( nCount == c_nItemCount );
122 CPPUNIT_CHECK( q.empty() );
123 CPPUNIT_CHECK( misc::check_size( q, 0 ));
130 for ( size_t i = 0; i < c_nItemCount; ++i ) {
131 CPPUNIT_CHECK( q.emplace( nMajor, nMinor ));
132 if ( nMinor == 15 ) {
138 CPPUNIT_CHECK( !q.empty() );
140 CPPUNIT_CHECK( misc::check_size( q, c_nItemCount ));
143 while ( !q.empty() ) {
146 CPPUNIT_ASSERT( q.pop( v ) );
149 CPPUNIT_ASSERT( q.dequeue( v ));
152 size_t nMin = nCount > q.quasi_factor() ? nCount - q.quasi_factor() : 0;
153 size_t nMax = nCount + q.quasi_factor();
154 CPPUNIT_CHECK_EX( nMin <= v.nVal && v.nVal <= nMax, nMin << " <= " << v.nVal << " <= " << nMax );
157 CPPUNIT_CHECK( misc::check_size( q, c_nItemCount - nCount ));
159 CPPUNIT_CHECK( nCount == c_nItemCount );
160 CPPUNIT_CHECK( q.empty() );
161 CPPUNIT_CHECK( misc::check_size( q, 0 ));
164 // pop from empty queue
167 v.nVal = c_nItemCount + 1;
168 CPPUNIT_CHECK( q.empty() );
169 CPPUNIT_ASSERT( !q.pop( v ));
170 CPPUNIT_CHECK( q.empty() );
171 CPPUNIT_CHECK( misc::check_size( q, 0 ));
172 CPPUNIT_CHECK( v.nVal == c_nItemCount + 1 );
176 for ( size_t i = 0; i < c_nItemCount; ++i ) {
178 CPPUNIT_ASSERT( q.push(item(i)) );
181 CPPUNIT_ASSERT( q.enqueue(item(i)) );
183 CPPUNIT_CHECK( misc::check_size( q, i + 1 ));
184 CPPUNIT_CHECK( !q.empty() );
188 CPPUNIT_CHECK( misc::check_size( q, 0 ));
189 CPPUNIT_CHECK( q.empty() );
194 void SegmQueue_HP_mutex();
195 void SegmQueue_HP_shuffle();
196 void SegmQueue_HP_stat();
197 void SegmQueue_HP_cacheline_padding();
198 void SegmQueue_HP_mutex_cacheline_padding();
199 void SegmQueue_HP_shuffle_cacheline_padding();
200 void SegmQueue_HP_stat_cacheline_padding();
202 void SegmQueue_DHP();
203 void SegmQueue_DHP_mutex();
204 void SegmQueue_DHP_shuffle();
205 void SegmQueue_DHP_stat();
206 void SegmQueue_DHP_cacheline_padding();
207 void SegmQueue_DHP_mutex_cacheline_padding();
208 void SegmQueue_DHP_shuffle_cacheline_padding();
209 void SegmQueue_DHP_stat_cacheline_padding();
211 CPPUNIT_TEST_SUITE(HdrSegmentedQueue)
212 CPPUNIT_TEST( SegmQueue_HP )
213 CPPUNIT_TEST( SegmQueue_HP_mutex )
214 CPPUNIT_TEST( SegmQueue_HP_shuffle )
215 CPPUNIT_TEST( SegmQueue_HP_stat )
216 CPPUNIT_TEST( SegmQueue_HP_cacheline_padding )
217 CPPUNIT_TEST( SegmQueue_HP_mutex_cacheline_padding )
218 CPPUNIT_TEST( SegmQueue_HP_shuffle_cacheline_padding )
219 CPPUNIT_TEST( SegmQueue_HP_stat_cacheline_padding )
221 CPPUNIT_TEST( SegmQueue_DHP )
222 CPPUNIT_TEST( SegmQueue_DHP_mutex )
223 CPPUNIT_TEST( SegmQueue_DHP_shuffle )
224 CPPUNIT_TEST( SegmQueue_DHP_stat )
225 CPPUNIT_TEST( SegmQueue_DHP_cacheline_padding )
226 CPPUNIT_TEST( SegmQueue_DHP_mutex_cacheline_padding )
227 CPPUNIT_TEST( SegmQueue_DHP_shuffle_cacheline_padding )
228 CPPUNIT_TEST( SegmQueue_DHP_stat_cacheline_padding )
229 CPPUNIT_TEST_SUITE_END()
234 #endif //#ifndef __CDSHDR_QUEUE_SEGMENTED_QUEUE_H