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