Merge branch 'dev'
[libcds.git] / tests / unit / set2 / set_delodd.h
1 //$$CDS-header$$
2
3 #include "cppunit/thread.h"
4 #include "set2/set_types.h"
5 #include <algorithm> // random_shuffle
6
7 namespace set2 {
8
9 #    define TEST_SET(X)         void X() { test<SetTypes<key_type, value_type>::X >()    ; }
10 #    define TEST_SET_EXTRACT(X) void X() { test_extract<SetTypes<key_type, value_type>::X >()    ; }
11 #    define TEST_SET_NOLF(X)    void X() { test_nolf<SetTypes<key_type, value_type>::X >()    ; }
12 #    define TEST_SET_NOLF_EXTRACT(X)    void X() { test_nolf_extract<SetTypes<key_type, value_type>::X >()    ; }
13
14     namespace {
15         struct key_thread
16         {
17             size_t  nKey;
18             size_t  nThread;
19
20             key_thread( size_t key, size_t threadNo )
21                 : nKey( key )
22                 , nThread( threadNo )
23             {}
24
25             key_thread()
26             {}
27         };
28
29         typedef SetTypes<key_thread, size_t>::key_val     key_value_pair;
30     }
31
32     template <>
33     struct cmp<key_thread> {
34         int operator ()(key_thread const& k1, key_thread const& k2) const
35         {
36             if ( k1.nKey < k2.nKey )
37                 return -1;
38             if ( k1.nKey > k2.nKey )
39                 return 1;
40             if ( k1.nThread < k2.nThread )
41                 return -1;
42             if ( k1.nThread > k2.nThread )
43                 return 1;
44             return 0;
45         }
46         int operator ()(key_thread const& k1, size_t k2) const
47         {
48             if ( k1.nKey < k2 )
49                 return -1;
50             if ( k1.nKey > k2 )
51                 return 1;
52             return 0;
53         }
54         int operator ()(size_t k1, key_thread const& k2) const
55         {
56             if ( k1 < k2.nKey )
57                 return -1;
58             if ( k1 > k2.nKey )
59                 return 1;
60             return 0;
61         }
62     };
63
64 } // namespace set2
65
66 namespace std {
67     template <>
68     struct less<set2::key_thread>
69     {
70         bool operator()(set2::key_thread const& k1, set2::key_thread const& k2) const
71         {
72             if ( k1.nKey <= k2.nKey )
73                 return k1.nKey < k2.nKey || k1.nThread < k2.nThread;
74             return false;
75         }
76     };
77
78     template <>
79     struct hash<set2::key_thread>
80     {
81         typedef size_t              result_type;
82         typedef set2::key_thread    argument_type;
83
84         size_t operator()( set2::key_thread const& k ) const
85         {
86             return std::hash<size_t>()(k.nKey);
87         }
88         size_t operator()( size_t k ) const
89         {
90             return std::hash<size_t>()(k);
91         }
92     };
93
94 } // namespace std
95
96 namespace boost {
97     inline size_t hash_value( set2::key_thread const& k )
98     {
99         return std::hash<size_t>()( k.nKey );
100     }
101
102     template <>
103     struct hash<set2::key_thread>
104     {
105         typedef size_t              result_type;
106         typedef set2::key_thread    argument_type;
107
108         size_t operator()(set2::key_thread const& k) const
109         {
110             return boost::hash<size_t>()( k.nKey );
111         }
112         size_t operator()(size_t k) const
113         {
114             return boost::hash<size_t>()( k );
115         }
116     };
117 } // namespace boost
118
119 namespace set2 {
120
121     class Set_DelOdd: public CppUnitMini::TestCase
122     {
123         static size_t  c_nSetSize;          // max set size
124         static size_t  c_nInsThreadCount;   // insert thread count
125         static size_t  c_nDelThreadCount;   // delete thread count
126         static size_t  c_nExtractThreadCount;  // extract thread count
127         static size_t  c_nMaxLoadFactor;    // maximum load factor
128         static bool    c_bPrintGCState;
129
130         std::vector<size_t>     m_arrData;
131
132     protected:
133         typedef CppUnitMini::TestCase Base;
134         typedef key_thread  key_type;
135         typedef size_t      value_type;
136
137         atomics::atomic<size_t>      m_nInsThreadCount;
138
139         // Inserts keys from [0..N)
140         template <class Set>
141         class InsertThread: public CppUnitMini::TestThread
142         {
143             Set&     m_Set;
144
145             virtual InsertThread *    clone()
146             {
147                 return new InsertThread( *this );
148             }
149
150             struct ensure_func
151             {
152                 template <typename Q>
153                 void operator()( bool /*bNew*/, key_value_pair const&, Q const& )
154                 {}
155             };
156         public:
157             size_t  m_nInsertSuccess;
158             size_t  m_nInsertFailed;
159
160         public:
161             InsertThread( CppUnitMini::ThreadPool& pool, Set& rMap )
162                 : CppUnitMini::TestThread( pool )
163                 , m_Set( rMap )
164             {}
165             InsertThread( InsertThread& src )
166                 : CppUnitMini::TestThread( src )
167                 , m_Set( src.m_Set )
168             {}
169
170             Set_DelOdd&  getTest()
171             {
172                 return reinterpret_cast<Set_DelOdd&>( m_Pool.m_Test );
173             }
174
175             virtual void init() { cds::threading::Manager::attachThread()   ; }
176             virtual void fini() { cds::threading::Manager::detachThread()   ; }
177
178             virtual void test()
179             {
180                 Set& rSet = m_Set;
181
182                 m_nInsertSuccess =
183                     m_nInsertFailed = 0;
184
185                 std::vector<size_t>& arrData = getTest().m_arrData;
186                 for ( size_t i = 0; i < arrData.size(); ++i ) {
187                     if ( rSet.insert( key_type( arrData[i], m_nThreadNo )))
188                         ++m_nInsertSuccess;
189                     else
190                         ++m_nInsertFailed;
191                 }
192
193                 ensure_func f;
194                 for ( size_t i = arrData.size() - 1; i > 0; --i ) {
195                     if ( arrData[i] & 1 ) {
196                         rSet.ensure( key_type( arrData[i], m_nThreadNo ), f );
197                     }
198                 }
199
200                 getTest().m_nInsThreadCount.fetch_sub( 1, atomics::memory_order_release );
201             }
202         };
203
204         struct key_equal {
205             bool operator()( key_type const& k1, key_type const& k2 ) const
206             {
207                 return k1.nKey == k2.nKey;
208             }
209             bool operator()( size_t k1, key_type const& k2 ) const
210             {
211                 return k1 == k2.nKey;
212             }
213             bool operator()( key_type const& k1, size_t k2 ) const
214             {
215                 return k1.nKey == k2;
216             }
217             bool operator ()( key_value_pair const& k1, key_value_pair const& k2 ) const
218             {
219                 return operator()( k1.key, k2.key );
220             }
221             bool operator ()( key_value_pair const& k1, key_type const& k2 ) const
222             {
223                 return operator()( k1.key, k2 );
224             }
225             bool operator ()( key_type const& k1, key_value_pair const& k2 ) const
226             {
227                 return operator()( k1, k2.key );
228             }
229             bool operator ()( key_value_pair const& k1, size_t k2 ) const
230             {
231                 return operator()( k1.key, k2 );
232             }
233             bool operator ()( size_t k1, key_value_pair const& k2 ) const
234             {
235                 return operator()( k1, k2.key );
236             }
237         };
238
239         struct key_less {
240             bool operator()( key_type const& k1, key_type const& k2 ) const
241             {
242                 return k1.nKey < k2.nKey;
243             }
244             bool operator()( size_t k1, key_type const& k2 ) const
245             {
246                 return k1 < k2.nKey;
247             }
248             bool operator()( key_type const& k1, size_t k2 ) const
249             {
250                 return k1.nKey < k2;
251             }
252             bool operator ()( key_value_pair const& k1, key_value_pair const& k2 ) const
253             {
254                 return operator()( k1.key, k2.key );
255             }
256             bool operator ()( key_value_pair const& k1, key_type const& k2 ) const
257             {
258                 return operator()( k1.key, k2 );
259             }
260             bool operator ()( key_type const& k1, key_value_pair const& k2 ) const
261             {
262                 return operator()( k1, k2.key );
263             }
264             bool operator ()( key_value_pair const& k1, size_t k2 ) const
265             {
266                 return operator()( k1.key, k2 );
267             }
268             bool operator ()( size_t k1, key_value_pair const& k2 ) const
269             {
270                 return operator()( k1, k2.key );
271             }
272
273             typedef key_equal   equal_to;
274         };
275
276         // Deletes odd keys from [0..N)
277         template <class Set>
278         class DeleteThread: public CppUnitMini::TestThread
279         {
280             Set&     m_Set;
281
282             virtual DeleteThread *    clone()
283             {
284                 return new DeleteThread( *this );
285             }
286         public:
287             size_t  m_nDeleteSuccess;
288             size_t  m_nDeleteFailed;
289
290         public:
291             DeleteThread( CppUnitMini::ThreadPool& pool, Set& rMap )
292                 : CppUnitMini::TestThread( pool )
293                 , m_Set( rMap )
294             {}
295             DeleteThread( DeleteThread& src )
296                 : CppUnitMini::TestThread( src )
297                 , m_Set( src.m_Set )
298             {}
299
300             Set_DelOdd&  getTest()
301             {
302                 return reinterpret_cast<Set_DelOdd&>( m_Pool.m_Test );
303             }
304
305             virtual void init() { cds::threading::Manager::attachThread()   ; }
306             virtual void fini() { cds::threading::Manager::detachThread()   ; }
307
308             virtual void test()
309             {
310                 Set& rSet = m_Set;
311
312                 m_nDeleteSuccess =
313                     m_nDeleteFailed = 0;
314
315                 std::vector<size_t>& arrData = getTest().m_arrData;
316                 if ( m_nThreadNo & 1 ) {
317                     for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
318                         for ( size_t i = 0; i < arrData.size(); ++i ) {
319                             if ( arrData[i] & 1 ) {
320                                 if ( rSet.erase_with( arrData[i], key_less() ))
321                                     ++m_nDeleteSuccess;
322                                 else
323                                     ++m_nDeleteFailed;
324                             }
325                         }
326                         if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
327                             break;
328                     }
329                 }
330                 else {
331                     for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
332                         for ( size_t i = arrData.size() - 1; i > 0; --i ) {
333                             if ( arrData[i] & 1 ) {
334                                 if ( rSet.erase_with( arrData[i], key_less() ))
335                                     ++m_nDeleteSuccess;
336                                 else
337                                     ++m_nDeleteFailed;
338                             }
339                         }
340                         if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
341                             break;
342                     }
343                 }
344             }
345         };
346
347         // Extracts odd keys from [0..N)
348         template <typename GC, class Set>
349         class ExtractThread: public CppUnitMini::TestThread
350         {
351             Set&     m_Set;
352
353             virtual ExtractThread *    clone()
354             {
355                 return new ExtractThread( *this );
356             }
357         public:
358             size_t  m_nExtractSuccess;
359             size_t  m_nExtractFailed;
360
361         public:
362             ExtractThread( CppUnitMini::ThreadPool& pool, Set& rMap )
363                 : CppUnitMini::TestThread( pool )
364                 , m_Set( rMap )
365             {}
366             ExtractThread( ExtractThread& src )
367                 : CppUnitMini::TestThread( src )
368                 , m_Set( src.m_Set )
369             {}
370
371             Set_DelOdd&  getTest()
372             {
373                 return reinterpret_cast<Set_DelOdd&>( m_Pool.m_Test );
374             }
375
376             virtual void init() { cds::threading::Manager::attachThread()   ; }
377             virtual void fini() { cds::threading::Manager::detachThread()   ; }
378
379             virtual void test()
380             {
381                 Set& rSet = m_Set;
382
383                 m_nExtractSuccess =
384                     m_nExtractFailed = 0;
385
386                 typename Set::guarded_ptr gp;
387
388                 std::vector<size_t>& arrData = getTest().m_arrData;
389                 if ( m_nThreadNo & 1 ) {
390                     for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
391                         for ( size_t i = 0; i < arrData.size(); ++i ) {
392                             if ( arrData[i] & 1 ) {
393                                 gp = rSet.extract_with( arrData[i], key_less());
394                                 if ( gp )
395                                     ++m_nExtractSuccess;
396                                 else
397                                     ++m_nExtractFailed;
398                                 gp.release();
399                             }
400                         }
401                         if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
402                             break;
403                     }
404                 }
405                 else {
406                     for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
407                         for ( size_t i = arrData.size() - 1; i > 0; --i ) {
408                             if ( arrData[i] & 1 ) {
409                                 gp = rSet.extract_with( arrData[i], key_less());
410                                 if ( gp )
411                                     ++m_nExtractSuccess;
412                                 else
413                                     ++m_nExtractFailed;
414                                 gp.release();
415                             }
416                         }
417                         if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
418                             break;
419                     }
420                 }
421             }
422         };
423
424         template <typename RCU, class Set>
425         class ExtractThread< cds::urcu::gc<RCU>, Set >: public CppUnitMini::TestThread
426         {
427             Set&     m_Set;
428
429             virtual ExtractThread *    clone()
430             {
431                 return new ExtractThread( *this );
432             }
433         public:
434             size_t  m_nExtractSuccess;
435             size_t  m_nExtractFailed;
436
437         public:
438             ExtractThread( CppUnitMini::ThreadPool& pool, Set& rMap )
439                 : CppUnitMini::TestThread( pool )
440                 , m_Set( rMap )
441             {}
442             ExtractThread( ExtractThread& src )
443                 : CppUnitMini::TestThread( src )
444                 , m_Set( src.m_Set )
445             {}
446
447             Set_DelOdd&  getTest()
448             {
449                 return reinterpret_cast<Set_DelOdd&>( m_Pool.m_Test );
450             }
451
452             virtual void init() { cds::threading::Manager::attachThread()   ; }
453             virtual void fini() { cds::threading::Manager::detachThread()   ; }
454
455             virtual void test()
456             {
457                 Set& rSet = m_Set;
458
459                 m_nExtractSuccess =
460                     m_nExtractFailed = 0;
461
462                 typename Set::exempt_ptr xp;
463
464                 std::vector<size_t>& arrData = getTest().m_arrData;
465                 if ( m_nThreadNo & 1 ) {
466                     for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
467                         for ( size_t i = 0; i < arrData.size(); ++i ) {
468                             if ( arrData[i] & 1 ) {
469                                 if ( Set::c_bExtractLockExternal ) {
470                                     typename Set::rcu_lock l;
471                                     xp = rSet.extract_with( arrData[i], key_less() );
472                                     if ( xp )
473                                         ++m_nExtractSuccess;
474                                     else
475                                         ++m_nExtractFailed;
476                                 }
477                                 else {
478                                     xp = rSet.extract_with( arrData[i], key_less() );
479                                     if ( xp )
480                                         ++m_nExtractSuccess;
481                                     else
482                                         ++m_nExtractFailed;
483                                 }
484                                 xp.release();
485                             }
486                         }
487                         if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
488                             break;
489                     }
490                 }
491                 else {
492                     for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
493                         for ( size_t i = arrData.size() - 1; i > 0; --i ) {
494                             if ( arrData[i] & 1 ) {
495                                 if ( Set::c_bExtractLockExternal ) {
496                                     typename Set::rcu_lock l;
497                                     xp = rSet.extract_with( arrData[i], key_less() );
498                                     if ( xp )
499                                         ++m_nExtractSuccess;
500                                     else
501                                         ++m_nExtractFailed;
502                                 }
503                                 else {
504                                     xp = rSet.extract_with( arrData[i], key_less() );
505                                     if ( xp )
506                                         ++m_nExtractSuccess;
507                                     else
508                                         ++m_nExtractFailed;
509                                 }
510                                 xp.release();
511                             }
512                         }
513                         if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
514                             break;
515                     }
516                 }
517             }
518         };
519
520     protected:
521         template <class Set>
522         void do_test( size_t nLoadFactor )
523         {
524             Set  testSet( c_nSetSize, nLoadFactor );
525             do_test_with( testSet );
526             analyze( testSet );
527         }
528
529         template <class Set>
530         void do_test_extract( size_t nLoadFactor )
531         {
532             Set  testSet( c_nSetSize, nLoadFactor );
533             do_test_extract_with( testSet );
534             analyze( testSet );
535         }
536
537         template <class Set>
538         void do_test_with( Set& testSet )
539         {
540             typedef InsertThread<Set> insert_thread;
541             typedef DeleteThread<Set> delete_thread;
542
543             m_nInsThreadCount.store( c_nInsThreadCount, atomics::memory_order_release );
544
545             CppUnitMini::ThreadPool pool( *this );
546             pool.add( new insert_thread( pool, testSet ), c_nInsThreadCount );
547             pool.add( new delete_thread( pool, testSet ), c_nDelThreadCount ? c_nDelThreadCount : cds::OS::topology::processor_count());
548             pool.run();
549             CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
550
551             size_t nInsertSuccess = 0;
552             size_t nInsertFailed = 0;
553             size_t nDeleteSuccess = 0;
554             size_t nDeleteFailed = 0;
555             for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
556                 insert_thread * pThread = dynamic_cast<insert_thread *>( *it );
557                 if ( pThread ) {
558                     nInsertSuccess += pThread->m_nInsertSuccess;
559                     nInsertFailed += pThread->m_nInsertFailed;
560                 }
561                 else {
562                     delete_thread * p = static_cast<delete_thread *>( *it );
563                     nDeleteSuccess += p->m_nDeleteSuccess;
564                     nDeleteFailed += p->m_nDeleteFailed;
565                 }
566             }
567
568             CPPUNIT_CHECK( nInsertSuccess == c_nSetSize * c_nInsThreadCount );
569             CPPUNIT_CHECK( nInsertFailed == 0 );
570
571             CPPUNIT_MSG( "  Totals (success/failed): \n\t"
572                       << "      Insert=" << nInsertSuccess << '/' << nInsertFailed << "\n\t"
573                       << "      Delete=" << nDeleteSuccess << '/' << nDeleteFailed << "\n\t"
574             );
575         }
576
577         template <class Set>
578         void do_test_extract_with( Set& testSet )
579         {
580             typedef InsertThread<Set> insert_thread;
581             typedef DeleteThread<Set> delete_thread;
582             typedef ExtractThread< typename Set::gc, Set > extract_thread;
583
584             m_nInsThreadCount.store( c_nInsThreadCount, atomics::memory_order_release );
585
586             CppUnitMini::ThreadPool pool( *this );
587             pool.add( new insert_thread( pool, testSet ), c_nInsThreadCount );
588             if ( c_nDelThreadCount )
589                 pool.add( new delete_thread( pool, testSet ), c_nDelThreadCount );
590             if ( c_nExtractThreadCount )
591                 pool.add( new extract_thread( pool, testSet ), c_nExtractThreadCount );
592             pool.run();
593             CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
594
595             size_t nInsertSuccess = 0;
596             size_t nInsertFailed = 0;
597             size_t nDeleteSuccess = 0;
598             size_t nDeleteFailed = 0;
599             size_t nExtractSuccess = 0;
600             size_t nExtractFailed = 0;
601             for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
602                 insert_thread * pThread = dynamic_cast<insert_thread *>( *it );
603                 if ( pThread ) {
604                     nInsertSuccess += pThread->m_nInsertSuccess;
605                     nInsertFailed += pThread->m_nInsertFailed;
606                 }
607                 else {
608                     delete_thread * p = dynamic_cast<delete_thread *>( *it );
609                     if ( p ) {
610                         nDeleteSuccess += p->m_nDeleteSuccess;
611                         nDeleteFailed += p->m_nDeleteFailed;
612                     }
613                     else {
614                         extract_thread * pExt = dynamic_cast<extract_thread *>( *it );
615                         assert( pExt );
616                         nExtractSuccess += pExt->m_nExtractSuccess;
617                         nExtractFailed += pExt->m_nExtractFailed;
618                     }
619                 }
620             }
621
622             CPPUNIT_CHECK( nInsertSuccess == c_nSetSize * c_nInsThreadCount );
623             CPPUNIT_CHECK( nInsertFailed == 0 );
624
625             CPPUNIT_MSG( "  Totals (success/failed): \n\t"
626                 << "      Insert=" << nInsertSuccess << '/' << nInsertFailed << "\n\t"
627                 << "      Delete=" << nDeleteSuccess << '/' << nDeleteFailed << "\n\t"
628                 << "      Extract=" << nExtractSuccess << '/' << nExtractFailed << "\n\t"
629                 );
630         }
631
632         template <typename Set>
633         void analyze( Set& testSet )
634         {
635             // All even keys must be in the set
636             {
637                 CPPUNIT_MSG( "  Check even keys..." );
638                 size_t nErrorCount = 0;
639                 for ( size_t n = 0; n < c_nSetSize; n +=2 ) {
640                     for ( size_t i = 0; i < c_nInsThreadCount; ++i ) {
641                         if ( !testSet.find( key_type(n, i) ) ) {
642                             if ( ++nErrorCount < 10 ) {
643                                 CPPUNIT_MSG( "key " << n << "-" << i << " is not found!");
644                             }
645                         }
646                     }
647                 }
648                 CPPUNIT_CHECK_EX( nErrorCount == 0, "Totals: " << nErrorCount << " keys is not found");
649             }
650
651             check_before_clear( testSet );
652
653             CPPUNIT_MSG( "  Clear map (single-threaded)..." );
654             cds::OS::Timer    timer;
655             testSet.clear();
656             CPPUNIT_MSG( "   Duration=" << timer.duration() );
657             CPPUNIT_CHECK_EX( testSet.empty(), ((long long) testSet.size()) );
658
659             additional_check( testSet );
660             print_stat( testSet );
661             additional_cleanup( testSet );
662         }
663
664         template <class Set>
665         void test()
666         {
667             CPPUNIT_MSG( "Insert thread count=" << c_nInsThreadCount
668                 << " delete thread count=" << c_nDelThreadCount
669                 << " set size=" << c_nSetSize
670                 );
671
672             for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
673                 CPPUNIT_MSG( "Load factor=" << nLoadFactor );
674                 do_test<Set>( nLoadFactor );
675                 if ( c_bPrintGCState )
676                     print_gc_state();
677             }
678         }
679
680         template <class Set>
681         void test_extract()
682         {
683             CPPUNIT_MSG( "Insert thread count=" << c_nInsThreadCount
684                 << " delete thread count=" << c_nDelThreadCount
685                 << " extract thread count=" << c_nExtractThreadCount
686                 << " set size=" << c_nSetSize
687                 );
688
689             for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
690                 CPPUNIT_MSG( "Load factor=" << nLoadFactor );
691                 do_test_extract<Set>( nLoadFactor );
692                 if ( c_bPrintGCState )
693                     print_gc_state();
694             }
695         }
696
697         template <class Set>
698         void test_nolf()
699         {
700             CPPUNIT_MSG( "Insert thread count=" << c_nInsThreadCount
701                 << " delete thread count=" << c_nDelThreadCount
702                 << " set size=" << c_nSetSize
703                 );
704
705             {
706                 Set s;
707                 do_test_with( s );
708                 analyze( s );
709             }
710
711             if ( c_bPrintGCState )
712                 print_gc_state();
713         }
714
715         template <class Set>
716         void test_nolf_extract()
717         {
718             CPPUNIT_MSG( "Insert thread count=" << c_nInsThreadCount
719                 << " delete thread count=" << c_nDelThreadCount
720                 << " extract thread count=" << c_nExtractThreadCount
721                 << " set size=" << c_nSetSize
722                 );
723
724             {
725                 Set s;
726                 do_test_extract_with( s );
727                 analyze( s );
728             }
729
730             if ( c_bPrintGCState )
731                 print_gc_state();
732         }
733
734         void setUpParams( const CppUnitMini::TestCfg& cfg );
735
736         void run_MichaelSet(const char *in_name, bool invert = false);
737         void run_SplitList(const char *in_name, bool invert = false);
738         void run_CuckooSet(const char *in_name, bool invert = false);
739         void run_SkipListSet(const char *in_name, bool invert = false);
740         void run_EllenBinTreeSet(const char *in_name, bool invert = false);
741
742         virtual void myRun(const char *in_name, bool invert = false);
743
744
745 #   include "set2/set_defs.h"
746         CDSUNIT_DECLARE_MichaelSet
747         CDSUNIT_DECLARE_SplitList
748         CDSUNIT_DECLARE_CuckooSet
749         CDSUNIT_DECLARE_SkipListSet
750         CDSUNIT_DECLARE_EllenBinTreeSet
751     };
752 } // namespace set2