Bugfix
[libcds.git] / tests / unit / map2 / map_insfind_int.cpp
1 //$$CDS-header$$
2
3 #include "map2/map_types.h"
4 #include "cppunit/thread.h"
5
6 #include <cds/os/topology.h>
7 #include <vector>
8 #include <algorithm> // random_shuffle
9
10 namespace map2 {
11
12 #    define TEST_MAP(X)         void X() { test<MapTypes<key_type, value_type>::X >()    ; }
13 #    define TEST_MAP_NOLF(X)    void X() { test_nolf<MapTypes<key_type, value_type>::X >()    ; }
14 #   define TEST_MAP_EXTRACT(X)  TEST_MAP(X)
15 #   define TEST_MAP_NOLF_EXTRACT(X) TEST_MAP_NOLF(X)
16
17     namespace {
18         static size_t  c_nMapSize = 1000000    ;  // map size
19         static size_t  c_nThreadCount = 4      ;  // count of insertion thread
20         static size_t  c_nMaxLoadFactor = 8    ;  // maximum load factor
21         static bool    c_bPrintGCState = true;
22     }
23
24     class Map_InsFind_int: public CppUnitMini::TestCase
25     {
26         typedef size_t  key_type;
27         typedef size_t  value_type;
28
29         template <typename Iterator, typename Map>
30         static bool check_result( Iterator const& it, Map const& map )
31         {
32             return it != map.end();
33         }
34         template <typename Map>
35         static bool check_result( bool b, Map const& )
36         {
37             return b;
38         }
39
40         template <class Map>
41         class Inserter: public CppUnitMini::TestThread
42         {
43             Map&     m_Map;
44             std::vector<size_t> m_arrVal;
45
46             virtual Inserter *    clone()
47             {
48                 return new Inserter( *this );
49             }
50
51             void make_array()
52             {
53                 size_t const nSize = c_nMapSize / c_nThreadCount + 1;
54                 m_arrVal.resize( nSize );
55                 size_t nItem = m_nThreadNo;
56                 for ( size_t i = 0; i < nSize; nItem += c_nThreadCount, ++i )
57                     m_arrVal[i] = nItem;
58                 std::random_shuffle( m_arrVal.begin(), m_arrVal.end() );
59             }
60         public:
61             size_t  m_nInsertSuccess;
62             size_t  m_nInsertFailed;
63             size_t  m_nFindSuccess;
64             size_t  m_nFindFail;
65
66         public:
67             Inserter( CppUnitMini::ThreadPool& pool, Map& rMap )
68                 : CppUnitMini::TestThread( pool )
69                 , m_Map( rMap )
70             {}
71             Inserter( Inserter& src )
72                 : CppUnitMini::TestThread( src )
73                 , m_Map( src.m_Map )
74             {}
75
76             Map_InsFind_int&  getTest()
77             {
78                 return reinterpret_cast<Map_InsFind_int&>( m_Pool.m_Test );
79             }
80
81             virtual void init()
82             {
83                 cds::threading::Manager::attachThread();
84                 make_array();
85             }
86             virtual void fini() { cds::threading::Manager::detachThread()   ; }
87
88             virtual void test()
89             {
90                 Map& rMap = m_Map;
91
92                 m_nInsertSuccess =
93                     m_nInsertFailed =
94                     m_nFindSuccess =
95                     m_nFindFail = 0;
96
97                 size_t const nArrSize = m_arrVal.size();
98                 for ( size_t i = 0; i < nArrSize; ++i ) {
99                     size_t const nItem = m_arrVal[i];
100                     if ( check_result( rMap.insert( nItem, nItem * 8 ), rMap ))
101                         ++m_nInsertSuccess;
102                     else
103                         ++m_nInsertFailed;
104
105                     for ( size_t k = 0; k <= i; ++k ) {
106                         if ( check_result( rMap.find( m_arrVal[k] ), rMap ))
107                             ++m_nFindSuccess;
108                         else
109                             ++m_nFindFail;
110                     }
111                 }
112             }
113         };
114
115     protected:
116
117         template <class Map>
118         void do_test( Map& testMap )
119         {
120             typedef Inserter<Map>       InserterThread;
121             cds::OS::Timer    timer;
122
123             CppUnitMini::ThreadPool pool( *this );
124             pool.add( new InserterThread( pool, testMap ), c_nThreadCount );
125             pool.run();
126             CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
127
128             size_t nInsertSuccess = 0;
129             size_t nInsertFailed = 0;
130             size_t nFindSuccess = 0;
131             size_t nFindFailed = 0;
132             for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
133                 InserterThread * pThread = static_cast<InserterThread *>( *it );
134
135                 nInsertSuccess += pThread->m_nInsertSuccess;
136                 nInsertFailed += pThread->m_nInsertFailed;
137                 nFindSuccess += pThread->m_nFindSuccess;
138                 nFindFailed += pThread->m_nFindFail;
139             }
140
141             CPPUNIT_MSG( "    Totals: Ins succ=" << nInsertSuccess << " fail=" << nInsertFailed << "\n"
142                       << "           Find succ=" << nFindSuccess << " fail=" << nFindFailed
143             );
144
145             CPPUNIT_ASSERT( nInsertFailed == 0 );
146             CPPUNIT_ASSERT( nFindFailed == 0 );
147
148             testMap.clear();
149             additional_check( testMap );
150             print_stat( testMap );
151             additional_cleanup( testMap );
152         }
153
154         template <class Map>
155         void test()
156         {
157             static_assert( (!std::is_same< typename Map::item_counter, cds::atomicity::empty_item_counter >::value),
158                 "Empty item counter is not suitable for this test");
159
160             CPPUNIT_MSG( "Thread count: " << c_nThreadCount
161                 << " map size=" << c_nMapSize
162                 );
163
164             for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
165                 CPPUNIT_MSG( "Load factor=" << nLoadFactor );
166                 Map  testMap( c_nMapSize, nLoadFactor );
167                 do_test( testMap );
168                 if ( c_bPrintGCState )
169                     print_gc_state();
170             }
171         }
172
173         template <class Map>
174         void test_nolf()
175         {
176             static_assert( (!std::is_same< typename Map::item_counter, cds::atomicity::empty_item_counter >::value),
177                 "Empty item counter is not suitable for this test");
178
179             CPPUNIT_MSG( "Thread count: " << c_nThreadCount
180                 << " map size=" << c_nMapSize
181                 );
182
183             Map testMap;
184             do_test( testMap );
185             if ( c_bPrintGCState )
186                 print_gc_state();
187         }
188
189         void setUpParams( const CppUnitMini::TestCfg& cfg ) {
190             c_nThreadCount = cfg.getULong("ThreadCount", 0 );
191             c_nMapSize = cfg.getULong("MapSize", 10000 );
192             c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", 8 );
193             c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
194             if ( c_nThreadCount == 0 )
195                 c_nThreadCount = cds::OS::topology::processor_count();
196         }
197
198 #   include "map2/map_defs.h"
199         CDSUNIT_DECLARE_MichaelMap
200         CDSUNIT_DECLARE_MichaelMap_nogc
201         CDSUNIT_DECLARE_SplitList
202         CDSUNIT_DECLARE_SplitList_nogc
203         CDSUNIT_DECLARE_SkipListMap
204         CDSUNIT_DECLARE_SkipListMap_nogc
205         CDSUNIT_DECLARE_EllenBinTreeMap
206         CDSUNIT_DECLARE_StripedMap
207         CDSUNIT_DECLARE_RefinableMap
208         CDSUNIT_DECLARE_CuckooMap
209         CDSUNIT_DECLARE_StdMap
210
211         CPPUNIT_TEST_SUITE( Map_InsFind_int )
212             CDSUNIT_TEST_MichaelMap
213             CDSUNIT_TEST_MichaelMap_nogc
214             CDSUNIT_TEST_SplitList
215             CDSUNIT_TEST_SplitList_nogc
216             CDSUNIT_TEST_SkipListMap
217             CDSUNIT_TEST_SkipListMap_nogc
218             CDSUNIT_TEST_EllenBinTreeMap
219             CDSUNIT_TEST_StripedMap
220             CDSUNIT_TEST_RefinableMap
221             CDSUNIT_TEST_CuckooMap
222             CDSUNIT_TEST_StdMap
223         CPPUNIT_TEST_SUITE_END()
224
225     };
226
227     CPPUNIT_TEST_SUITE_REGISTRATION( Map_InsFind_int );
228 } // namespace map2