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 #ifndef CDSTEST_HDR_INTRUSIVE_SEGMENTED_QUEUE_H
32 #define CDSTEST_HDR_INTRUSIVE_SEGMENTED_QUEUE_H
34 #include "cppunit/cppunit_proxy.h"
35 #include <cds/intrusive/details/base.h>
36 #include "size_check.h"
40 class HdrIntrusiveSegmentedQueue : public CppUnitMini::TestCase
46 size_t nDispose2Count;
61 struct big_item : public item
75 void operator()( item * p )
83 void operator()( item * p )
89 template <typename Queue>
92 for ( size_t nQuasiFactor = 2; nQuasiFactor <= 256; ++nQuasiFactor ) {
93 CPPUNIT_MSG( "QuasiFactor=" << nQuasiFactor << "..." );
94 test_qf<Queue>( nQuasiFactor );
98 template <typename Queue>
99 void test_qf( size_t nQuasiFactor )
101 typedef typename Queue::value_type value_type;
103 static size_t const c_nItemCount = 1000;
104 value_type val[c_nItemCount];
105 for ( int i = 0; i < static_cast<int>(sizeof(val)/sizeof(val[0])); ++i )
109 Queue q( nQuasiFactor );
110 CPPUNIT_CHECK( q.quasi_factor() == cds::beans::ceil2(nQuasiFactor) );
111 CPPUNIT_CHECK( misc::check_size( q, 0 ));
112 CPPUNIT_CHECK( q.empty() );
115 for ( size_t i = 0; i < sizeof(val)/sizeof(val[0]); ++i ) {
117 CPPUNIT_ASSERT( q.push( val[i] ));
120 CPPUNIT_ASSERT( q.enqueue( val[i] ));
123 CPPUNIT_CHECK( misc::check_size( q, i + 1 ));
125 CPPUNIT_CHECK( !q.empty() );
129 while ( !q.empty() ) {
136 CPPUNIT_ASSERT( pVal != nullptr );
138 int nSegment = int( nCount / q.quasi_factor() );
139 int nMin = nSegment * int(q.quasi_factor());
140 int nMax = nMin + int(q.quasi_factor()) - 1;
141 CPPUNIT_CHECK_EX( nMin <= pVal->nValue && pVal->nValue <= nMax, nMin << " <= " << pVal->nValue << " <= " << nMax );
144 CPPUNIT_CHECK( misc::check_size( q, sizeof(val)/sizeof(val[0]) - nCount ));
146 CPPUNIT_CHECK( nCount == sizeof(val)/sizeof(val[0]) );
147 CPPUNIT_CHECK( q.empty() );
148 CPPUNIT_CHECK( misc::check_size( q, 0 ));
150 // pop from empty queue
151 CPPUNIT_ASSERT( q.pop() == nullptr );
152 CPPUNIT_CHECK( q.empty() );
153 CPPUNIT_CHECK( misc::check_size( q, 0 ));
155 // check if Disposer has not been called
156 Queue::gc::force_dispose();
157 for ( int i = 0; i < static_cast<int>( sizeof(val)/sizeof(val[0]) ); ++i ) {
158 CPPUNIT_CHECK( val[i].nDisposeCount == 0 );
159 CPPUNIT_CHECK( val[i].nDispose2Count == 0 );
162 // Manually dispose the items
163 for ( int i = 0; i < static_cast<int>( sizeof(val)/sizeof(val[0])); ++i )
164 Queue::gc::template retire<Disposer>( &(val[i]) );
166 // check if Disposer has been called
167 Queue::gc::force_dispose();
168 for ( int i = 0; i < static_cast<int>( sizeof(val)/sizeof(val[0])); ++i ) {
169 CPPUNIT_CHECK( val[i].nDisposeCount == 1 );
170 CPPUNIT_CHECK( val[i].nDispose2Count == 0 );
175 for ( int i = 0; i < static_cast<int>( sizeof(val)/sizeof(val[0])); ++i )
176 CPPUNIT_CHECK( q.push( val[i] ) );
177 CPPUNIT_CHECK( misc::check_size( q, sizeof(val)/sizeof(val[0]) ));
178 CPPUNIT_CHECK( !q.empty() );
181 CPPUNIT_CHECK( misc::check_size( q, 0));
182 CPPUNIT_CHECK( q.empty() );
184 // check if Disposer has been called
185 Queue::gc::force_dispose();
186 for ( int i = 0; i < static_cast<int>( sizeof(val)/sizeof(val[0])); ++i ) {
187 CPPUNIT_CHECK( val[i].nDisposeCount == 2 );
188 CPPUNIT_CHECK( val[i].nDispose2Count == 0 );
192 for ( int i = 0; i < static_cast<int>( sizeof(val)/sizeof(val[0])); ++i )
193 CPPUNIT_CHECK( q.push( val[i] ) );
194 CPPUNIT_CHECK( misc::check_size( q, sizeof(val)/sizeof(val[0]) ));
195 CPPUNIT_CHECK( !q.empty() );
197 q.clear_with( Disposer2() );
198 CPPUNIT_CHECK( misc::check_size( q, 0));
199 CPPUNIT_CHECK( q.empty() );
201 // check if Disposer has been called
202 Queue::gc::force_dispose();
203 for ( int i = 0; i < static_cast<int>( sizeof(val)/sizeof(val[0])); ++i ) {
204 CPPUNIT_CHECK( val[i].nDisposeCount == 2 );
205 CPPUNIT_CHECK( val[i].nDispose2Count == 1 );
208 // check clear on destruct
209 for ( int i = 0; i < static_cast<int>( sizeof(val)/sizeof(val[0])); ++i )
210 CPPUNIT_CHECK( q.push( val[i] ) );
211 CPPUNIT_CHECK( misc::check_size( q, sizeof(val)/sizeof(val[0]) ));
212 CPPUNIT_CHECK( !q.empty() );
215 // check if Disposer has been called
216 Queue::gc::force_dispose();
217 for ( int i = 0; i < static_cast<int>( sizeof(val)/sizeof(val[0])); ++i ) {
218 CPPUNIT_CHECK( val[i].nDisposeCount == 3 );
219 CPPUNIT_CHECK( val[i].nDispose2Count == 1 );
224 void SegmQueue_HP_mutex();
225 void SegmQueue_HP_shuffle();
226 void SegmQueue_HP_stat();
227 void SegmQueue_HP_cacheline_padding();
228 void SegmQueue_HP_mutex_cacheline_padding();
229 void SegmQueue_HP_shuffle_cacheline_padding();
230 void SegmQueue_HP_stat_cacheline_padding();
231 void SegmQueue_HP_256_padding();
232 void SegmQueue_HP_mutex_256_padding();
233 void SegmQueue_HP_shuffle_256_padding();
234 void SegmQueue_HP_stat_256_padding();
235 void SegmQueue_HP_cacheline_padding_bigdata();
236 void SegmQueue_HP_mutex_cacheline_padding_bigdata();
237 void SegmQueue_HP_shuffle_cacheline_padding_bigdata();
238 void SegmQueue_HP_stat_cacheline_padding_bigdata();
240 void SegmQueue_DHP();
241 void SegmQueue_DHP_mutex();
242 void SegmQueue_DHP_shuffle();
243 void SegmQueue_DHP_stat();
244 void SegmQueue_DHP_cacheline_padding();
245 void SegmQueue_DHP_mutex_cacheline_padding();
246 void SegmQueue_DHP_shuffle_cacheline_padding();
247 void SegmQueue_DHP_stat_cacheline_padding();
248 void SegmQueue_DHP_256_padding();
249 void SegmQueue_DHP_mutex_256_padding();
250 void SegmQueue_DHP_shuffle_256_padding();
251 void SegmQueue_DHP_stat_256_padding();
252 void SegmQueue_DHP_cacheline_padding_bigdata();
253 void SegmQueue_DHP_mutex_cacheline_padding_bigdata();
254 void SegmQueue_DHP_shuffle_cacheline_padding_bigdata();
255 void SegmQueue_DHP_stat_cacheline_padding_bigdata();
257 CPPUNIT_TEST_SUITE(HdrIntrusiveSegmentedQueue)
258 CPPUNIT_TEST( SegmQueue_HP )
259 CPPUNIT_TEST( SegmQueue_HP_mutex )
260 CPPUNIT_TEST( SegmQueue_HP_shuffle )
261 CPPUNIT_TEST( SegmQueue_HP_stat )
262 CPPUNIT_TEST( SegmQueue_HP_cacheline_padding )
263 CPPUNIT_TEST( SegmQueue_HP_mutex_cacheline_padding )
264 CPPUNIT_TEST( SegmQueue_HP_shuffle_cacheline_padding )
265 CPPUNIT_TEST( SegmQueue_HP_stat_cacheline_padding )
266 CPPUNIT_TEST( SegmQueue_HP_256_padding )
267 CPPUNIT_TEST( SegmQueue_HP_mutex_256_padding )
268 CPPUNIT_TEST( SegmQueue_HP_shuffle_256_padding )
269 CPPUNIT_TEST( SegmQueue_HP_stat_256_padding )
270 CPPUNIT_TEST( SegmQueue_HP_cacheline_padding_bigdata )
271 CPPUNIT_TEST( SegmQueue_HP_mutex_cacheline_padding_bigdata )
272 CPPUNIT_TEST( SegmQueue_HP_shuffle_cacheline_padding_bigdata )
273 CPPUNIT_TEST( SegmQueue_HP_stat_cacheline_padding_bigdata )
275 CPPUNIT_TEST( SegmQueue_DHP )
276 CPPUNIT_TEST( SegmQueue_DHP_mutex )
277 CPPUNIT_TEST( SegmQueue_DHP_shuffle )
278 CPPUNIT_TEST( SegmQueue_DHP_stat )
279 CPPUNIT_TEST( SegmQueue_DHP_cacheline_padding )
280 CPPUNIT_TEST( SegmQueue_DHP_mutex_cacheline_padding )
281 CPPUNIT_TEST( SegmQueue_DHP_shuffle_cacheline_padding )
282 CPPUNIT_TEST( SegmQueue_DHP_stat_cacheline_padding )
283 CPPUNIT_TEST( SegmQueue_DHP_256_padding )
284 CPPUNIT_TEST( SegmQueue_DHP_mutex_256_padding )
285 CPPUNIT_TEST( SegmQueue_DHP_shuffle_256_padding )
286 CPPUNIT_TEST( SegmQueue_DHP_stat_256_padding )
287 CPPUNIT_TEST( SegmQueue_DHP_cacheline_padding_bigdata )
288 CPPUNIT_TEST( SegmQueue_DHP_mutex_cacheline_padding_bigdata )
289 CPPUNIT_TEST( SegmQueue_DHP_shuffle_cacheline_padding_bigdata )
290 CPPUNIT_TEST( SegmQueue_DHP_stat_cacheline_padding_bigdata )
291 CPPUNIT_TEST_SUITE_END()
296 #endif // CDSTEST_HDR_INTRUSIVE_SEGMENTED_QUEUE_H