3 #ifndef __CDSHDR_QUEUE_INTRUSIVE_SEGMENTED_QUEUE_H
4 #define __CDSHDR_QUEUE_INTRUSIVE_SEGMENTED_QUEUE_H
6 #include "cppunit/cppunit_proxy.h"
7 #include <cds/intrusive/details/base.h>
8 #include "size_check.h"
12 class HdrIntrusiveSegmentedQueue: public CppUnitMini::TestCase
18 size_t nDispose2Count;
35 void operator()( item * p )
43 void operator()( item * p )
49 template <typename Queue>
52 for ( size_t nQuasiFactor = 2; nQuasiFactor <= 256; ++nQuasiFactor ) {
53 CPPUNIT_MSG( "QuasiFactor=" << nQuasiFactor << "..." );
54 test_qf<Queue>( nQuasiFactor );
58 template <typename Queue>
59 void test_qf( size_t nQuasiFactor )
61 typedef typename Queue::value_type value_type;
63 static size_t const c_nItemCount = 1000;
64 value_type val[c_nItemCount];
65 for ( int i = 0; i < static_cast<int>(sizeof(val)/sizeof(val[0])); ++i )
69 Queue q( nQuasiFactor );
70 CPPUNIT_CHECK( q.quasi_factor() == cds::beans::ceil2(nQuasiFactor) );
71 CPPUNIT_CHECK( misc::check_size( q, 0 ));
72 CPPUNIT_CHECK( q.empty() );
75 for ( size_t i = 0; i < sizeof(val)/sizeof(val[0]); ++i ) {
77 CPPUNIT_ASSERT( q.push( val[i] ));
80 CPPUNIT_ASSERT( q.enqueue( val[i] ));
83 CPPUNIT_CHECK( misc::check_size( q, i + 1 ));
85 CPPUNIT_CHECK( !q.empty() );
89 while ( !q.empty() ) {
96 CPPUNIT_ASSERT( pVal != nullptr );
98 int nSegment = int( nCount / q.quasi_factor() );
99 int nMin = nSegment * int(q.quasi_factor());
100 int nMax = nMin + int(q.quasi_factor()) - 1;
101 CPPUNIT_CHECK_EX( nMin <= pVal->nValue && pVal->nValue <= nMax, nMin << " <= " << pVal->nValue << " <= " << nMax );
104 CPPUNIT_CHECK( misc::check_size( q, sizeof(val)/sizeof(val[0]) - nCount ));
106 CPPUNIT_CHECK( nCount == sizeof(val)/sizeof(val[0]) );
107 CPPUNIT_CHECK( q.empty() );
108 CPPUNIT_CHECK( misc::check_size( q, 0 ));
110 // pop from empty queue
111 CPPUNIT_ASSERT( q.pop() == nullptr );
112 CPPUNIT_CHECK( q.empty() );
113 CPPUNIT_CHECK( misc::check_size( q, 0 ));
115 // check if Disposer has not been called
116 Queue::gc::force_dispose();
117 for ( int i = 0; i < static_cast<int>( sizeof(val)/sizeof(val[0]) ); ++i ) {
118 CPPUNIT_CHECK( val[i].nDisposeCount == 0 );
119 CPPUNIT_CHECK( val[i].nDispose2Count == 0 );
122 // Manually dispose the items
123 for ( int i = 0; i < static_cast<int>( sizeof(val)/sizeof(val[0])); ++i )
124 Queue::gc::template retire<Disposer>( &(val[i]) );
126 // check if Disposer has been called
127 Queue::gc::force_dispose();
128 for ( int i = 0; i < static_cast<int>( sizeof(val)/sizeof(val[0])); ++i ) {
129 CPPUNIT_CHECK( val[i].nDisposeCount == 1 );
130 CPPUNIT_CHECK( val[i].nDispose2Count == 0 );
135 for ( int i = 0; i < static_cast<int>( sizeof(val)/sizeof(val[0])); ++i )
136 CPPUNIT_CHECK( q.push( val[i] ) );
137 CPPUNIT_CHECK( misc::check_size( q, sizeof(val)/sizeof(val[0]) ));
138 CPPUNIT_CHECK( !q.empty() );
141 CPPUNIT_CHECK( misc::check_size( q, 0));
142 CPPUNIT_CHECK( q.empty() );
144 // check if Disposer has been called
145 Queue::gc::force_dispose();
146 for ( int i = 0; i < static_cast<int>( sizeof(val)/sizeof(val[0])); ++i ) {
147 CPPUNIT_CHECK( val[i].nDisposeCount == 2 );
148 CPPUNIT_CHECK( val[i].nDispose2Count == 0 );
152 for ( int i = 0; i < static_cast<int>( sizeof(val)/sizeof(val[0])); ++i )
153 CPPUNIT_CHECK( q.push( val[i] ) );
154 CPPUNIT_CHECK( misc::check_size( q, sizeof(val)/sizeof(val[0]) ));
155 CPPUNIT_CHECK( !q.empty() );
157 q.clear_with( Disposer2() );
158 CPPUNIT_CHECK( misc::check_size( q, 0));
159 CPPUNIT_CHECK( q.empty() );
161 // check if Disposer has been called
162 Queue::gc::force_dispose();
163 for ( int i = 0; i < static_cast<int>( sizeof(val)/sizeof(val[0])); ++i ) {
164 CPPUNIT_CHECK( val[i].nDisposeCount == 2 );
165 CPPUNIT_CHECK( val[i].nDispose2Count == 1 );
168 // check clear on destruct
169 for ( int i = 0; i < static_cast<int>( sizeof(val)/sizeof(val[0])); ++i )
170 CPPUNIT_CHECK( q.push( val[i] ) );
171 CPPUNIT_CHECK( misc::check_size( q, sizeof(val)/sizeof(val[0]) ));
172 CPPUNIT_CHECK( !q.empty() );
175 // check if Disposer has been called
176 Queue::gc::force_dispose();
177 for ( int i = 0; i < static_cast<int>( sizeof(val)/sizeof(val[0])); ++i ) {
178 CPPUNIT_CHECK( val[i].nDisposeCount == 3 );
179 CPPUNIT_CHECK( val[i].nDispose2Count == 1 );
184 void SegmQueue_HP_mutex();
185 void SegmQueue_HP_shuffle();
186 void SegmQueue_HP_stat();
188 void SegmQueue_PTB();
189 void SegmQueue_PTB_mutex();
190 void SegmQueue_PTB_shuffle();
191 void SegmQueue_PTB_stat();
193 CPPUNIT_TEST_SUITE(HdrIntrusiveSegmentedQueue)
194 CPPUNIT_TEST( SegmQueue_HP )
195 CPPUNIT_TEST( SegmQueue_HP_mutex )
196 CPPUNIT_TEST( SegmQueue_HP_shuffle )
197 CPPUNIT_TEST( SegmQueue_HP_stat )
199 CPPUNIT_TEST( SegmQueue_PTB )
200 CPPUNIT_TEST( SegmQueue_PTB_mutex )
201 CPPUNIT_TEST( SegmQueue_PTB_shuffle )
202 CPPUNIT_TEST( SegmQueue_PTB_stat )
203 CPPUNIT_TEST_SUITE_END()
208 #endif // __CDSHDR_QUEUE_INTRUSIVE_SEGMENTED_QUEUE_H