7156d54da3bd60ab1a43e42f0d24cc24ff639dcf
[libcds.git] / tests / unit / map2 / map_insdel_item_string.h
1 //$$CDS-header$$
2
3 #include "map2/map_type.h"
4 #include "cppunit/thread.h"
5
6 #include <vector>
7
8 namespace map2 {
9
10 #define TEST_CASE(TAG, X)  void X();
11
12     class Map_InsDel_Item_string: public CppUnitMini::TestCase
13     {
14     public:
15         size_t  c_nMapSize = 1000000;       // map size
16         size_t  c_nThreadCount = 4;         // thread count
17         size_t  c_nAttemptCount = 100000;   // count of SUCCESS insert/delete for each thread
18         size_t  c_nMaxLoadFactor = 8;       // maximum load factor
19         bool    c_bPrintGCState = true;
20
21         size_t c_nCuckooInitialSize = 1024; // initial size for CuckooMap
22         size_t c_nCuckooProbesetSize = 16;  // CuckooMap probeset size (only for list-based probeset)
23         size_t c_nCuckooProbesetThreshold = 0; // CUckooMap probeset threshold (o - use default)
24
25         size_t c_nMultiLevelMap_HeadBits = 10;
26         size_t c_nMultiLevelMap_ArrayBits = 4;
27
28         size_t  c_nGoalItem;
29         size_t  c_nLoadFactor = 2;  // current load factor
30
31     private:
32         typedef CppUnitMini::TestCase Base;
33         typedef std::string  key_type;
34         typedef size_t  value_type;
35
36         const std::vector<std::string> *  m_parrString;
37
38         template <class Map>
39         class Inserter: public CppUnitMini::TestThread
40         {
41             Map&     m_Map;
42
43             virtual Inserter *    clone()
44             {
45                 return new Inserter( *this );
46             }
47         public:
48             size_t  m_nInsertSuccess;
49             size_t  m_nInsertFailed;
50
51         public:
52             Inserter( CppUnitMini::ThreadPool& pool, Map& rMap )
53                 : CppUnitMini::TestThread( pool )
54                 , m_Map( rMap )
55             {}
56             Inserter( Inserter& src )
57                 : CppUnitMini::TestThread( src )
58                 , m_Map( src.m_Map )
59             {}
60
61             Map_InsDel_Item_string&  getTest()
62             {
63                 return reinterpret_cast<Map_InsDel_Item_string&>( m_Pool.m_Test );
64             }
65
66             virtual void init() { cds::threading::Manager::attachThread()   ; }
67             virtual void fini() { cds::threading::Manager::detachThread()   ; }
68
69             virtual void test()
70             {
71                 Map& rMap = m_Map;
72
73                 m_nInsertSuccess =
74                     m_nInsertFailed = 0;
75
76                 size_t nGoalItem = getTest().c_nGoalItem;
77                 std::string strGoal = (*getTest().m_parrString)[nGoalItem];
78                 size_t const nAttemptCount = getTest().c_nAttemptCount;
79
80                 for ( size_t nAttempt = 0; nAttempt < nAttemptCount; ) {
81                     if ( rMap.insert( strGoal, nGoalItem )) {
82                         ++m_nInsertSuccess;
83                         ++nAttempt;
84                     }
85                     else
86                         ++m_nInsertFailed;
87                 }
88             }
89         };
90
91         template <class Map>
92         class Deleter: public CppUnitMini::TestThread
93         {
94             Map&     m_Map;
95
96             struct erase_cleaner {
97                 void operator ()(std::pair<typename Map::key_type const, typename Map::mapped_type>& val )
98                 {
99                     val.second = 0;
100                 }
101                 // for boost::container::flat_map
102                 void operator ()(std::pair< typename std::remove_const< typename Map::key_type >::type, typename Map::mapped_type>& val )
103                 {
104                     val.second = 0;
105                 }
106                 // for BronsonAVLTreeMap
107                 void operator()( typename Map::key_type const& /*key*/, typename Map::mapped_type& val )
108                 {
109                     val = 0;
110                 }
111             };
112
113             virtual Deleter *    clone()
114             {
115                 return new Deleter( *this );
116             }
117         public:
118             size_t  m_nDeleteSuccess;
119             size_t  m_nDeleteFailed;
120
121         public:
122             Deleter( CppUnitMini::ThreadPool& pool, Map& rMap )
123                 : CppUnitMini::TestThread( pool )
124                 , m_Map( rMap )
125             {}
126             Deleter( Deleter& src )
127                 : CppUnitMini::TestThread( src )
128                 , m_Map( src.m_Map )
129             {}
130
131             Map_InsDel_Item_string&  getTest()
132             {
133                 return reinterpret_cast<Map_InsDel_Item_string&>( m_Pool.m_Test );
134             }
135
136             virtual void init() { cds::threading::Manager::attachThread()   ; }
137             virtual void fini() { cds::threading::Manager::detachThread()   ; }
138
139             virtual void test()
140             {
141                 Map& rMap = m_Map;
142
143                 m_nDeleteSuccess =
144                     m_nDeleteFailed = 0;
145
146                 size_t nGoalItem = getTest().c_nGoalItem;
147                 std::string strGoal = (*getTest().m_parrString)[nGoalItem];
148                 size_t const nAttemptCount = getTest().c_nAttemptCount;
149
150                 for ( size_t nAttempt = 0; nAttempt < nAttemptCount; ) {
151                     if ( rMap.erase( strGoal, erase_cleaner() )) {
152                         ++m_nDeleteSuccess;
153                         ++nAttempt;
154                     }
155                     else
156                         ++m_nDeleteFailed;
157                 }
158             }
159         };
160
161     protected:
162
163         template <class Map>
164         void do_test( Map& testMap )
165         {
166             typedef Inserter<Map>       InserterThread;
167             typedef Deleter<Map>        DeleterThread;
168             cds::OS::Timer    timer;
169
170             // Fill the map
171             CPPUNIT_MSG( "  Fill map (" << c_nMapSize << " items)...");
172             timer.reset();
173             for ( size_t i = 0; i < c_nMapSize; ++i ) {
174                 CPPUNIT_ASSERT_EX( testMap.insert( (*m_parrString)[i], i ), i );
175             }
176             CPPUNIT_MSG( "   Duration=" << timer.duration() );
177
178             CPPUNIT_MSG( "  Insert/delete the key " << c_nGoalItem << " (" << c_nAttemptCount << " successful times)...");
179             CppUnitMini::ThreadPool pool( *this );
180             pool.add( new InserterThread( pool, testMap ), (c_nThreadCount + 1) / 2 );
181             pool.add( new DeleterThread( pool, testMap ), (c_nThreadCount + 1) / 2 );
182             pool.run();
183             CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
184
185             size_t nInsertSuccess = 0;
186             size_t nInsertFailed = 0;
187             size_t nDeleteSuccess = 0;
188             size_t nDeleteFailed = 0;
189             for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
190                 InserterThread * pThread = dynamic_cast<InserterThread *>( *it );
191                 if ( pThread ) {
192                     CPPUNIT_CHECK( pThread->m_nInsertSuccess == c_nAttemptCount );
193                     nInsertSuccess += pThread->m_nInsertSuccess;
194                     nInsertFailed += pThread->m_nInsertFailed;
195                 }
196                 else {
197                     DeleterThread * p = static_cast<DeleterThread *>( *it );
198                     CPPUNIT_CHECK( p->m_nDeleteSuccess == c_nAttemptCount );
199                     nDeleteSuccess += p->m_nDeleteSuccess;
200                     nDeleteFailed += p->m_nDeleteFailed;
201                 }
202             }
203             CPPUNIT_CHECK_EX( nInsertSuccess == nDeleteSuccess, "nInsertSuccess=" << nInsertSuccess << ", nDeleteSuccess=" << nDeleteSuccess );
204             CPPUNIT_MSG( "    Totals: Ins fail=" << nInsertFailed << " Del fail=" << nDeleteFailed );
205
206             // Check if the map contains all items
207             CPPUNIT_MSG( "    Check if the map contains all items" );
208             timer.reset();
209             for ( size_t i = 0; i < c_nMapSize; ++i ) {
210                 CPPUNIT_CHECK_EX( testMap.contains( (*m_parrString)[i] ), "Key \"" << (*m_parrString)[i] << "\" not found" );
211             }
212             CPPUNIT_MSG( "    Duration=" << timer.duration() );
213
214             check_before_cleanup( testMap );
215
216             testMap.clear();
217             additional_check( testMap );
218             print_stat( testMap );
219             additional_cleanup( testMap );
220         }
221
222         template <class Map>
223         void run_test()
224         {
225             m_parrString = &CppUnitMini::TestCase::getTestStrings();
226             if ( c_nMapSize > m_parrString->size() )
227                 c_nMapSize = m_parrString->size();
228             if ( c_nGoalItem > m_parrString->size() )
229                 c_nGoalItem = m_parrString->size() / 2;
230
231             CPPUNIT_MSG( "Thread count= " << c_nThreadCount
232                 << " pass count=" << c_nAttemptCount
233                 << " map size=" << c_nMapSize
234                 );
235
236             if ( Map::c_bLoadFactorDepended ) {
237                 for ( c_nLoadFactor = 1; c_nLoadFactor <= c_nMaxLoadFactor; c_nLoadFactor *= 2 ) {
238                     CPPUNIT_MSG( "Load factor=" << c_nLoadFactor );
239                     Map  testMap( *this );
240                     do_test( testMap );
241                     if ( c_bPrintGCState )
242                         print_gc_state();
243                 }
244             }
245             else {
246                 Map testMap( *this );
247                 do_test( testMap );
248                 if ( c_bPrintGCState )
249                     print_gc_state();
250             }
251         }
252
253         void setUpParams( const CppUnitMini::TestCfg& cfg );
254
255 #   include "map2/map_defs.h"
256         CDSUNIT_DECLARE_MichaelMap
257         CDSUNIT_DECLARE_SplitList
258         CDSUNIT_DECLARE_SkipListMap
259         CDSUNIT_DECLARE_EllenBinTreeMap
260         CDSUNIT_DECLARE_BronsonAVLTreeMap
261         CDSUNIT_DECLARE_MultiLevelHashMap
262         CDSUNIT_DECLARE_StripedMap
263         CDSUNIT_DECLARE_RefinableMap
264         CDSUNIT_DECLARE_CuckooMap
265         // CDSUNIT_DECLARE_StdMap // very slow!!
266
267         CPPUNIT_TEST_SUITE(Map_InsDel_Item_string)
268             CDSUNIT_TEST_MichaelMap
269             CDSUNIT_TEST_SplitList
270             CDSUNIT_TEST_SkipListMap
271             CDSUNIT_TEST_EllenBinTreeMap
272             CDSUNIT_TEST_BronsonAVLTreeMap
273             CDSUNIT_TEST_MultiLevelHashMap
274             CDSUNIT_TEST_CuckooMap
275             CDSUNIT_TEST_StripedMap
276             CDSUNIT_TEST_RefinableMap
277             // CDSUNIT_TEST_StdMap // very slow!!
278         CPPUNIT_TEST_SUITE_END();
279
280     };
281 } // namespace map2