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