d7b5096c8f96f87060784955c329d43c04f255d6
[libcds.git] / tests / unit / map2 / map_insdel_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_MAP(IMPL, C, X)         void C::X() { test<map_type<IMPL, key_type, value_type>::X >(); }
11 #   define TEST_MAP_NOLF(IMPL, C, X)    void C::X() { test_nolf<map_type<IMPL, key_type, value_type>::X >(); }
12 #   define TEST_MAP_EXTRACT(IMPL, C, X)  TEST_MAP(IMPL, C, X)
13 #   define TEST_MAP_NOLF_EXTRACT(IMPL, C, X) TEST_MAP_NOLF(IMPL, C, X)
14
15     class Map_InsDel_string: public CppUnitMini::TestCase
16     {
17         static size_t  c_nMapSize;            // map size
18         static size_t  c_nInsertThreadCount;  // count of insertion thread
19         static size_t  c_nDeleteThreadCount;  // count of deletion thread
20         static size_t  c_nThreadPassCount;    // pass count for each thread
21         static size_t  c_nMaxLoadFactor;      // maximum load factor
22         static bool    c_bPrintGCState;
23
24         typedef CppUnitMini::TestCase Base;
25         typedef std::string key_type;
26         typedef size_t      value_type;
27
28         const std::vector<std::string> *  m_parrString;
29
30         template <class MAP>
31         class Inserter: public CppUnitMini::TestThread
32         {
33             MAP&     m_Map;
34
35             virtual Inserter *    clone()
36             {
37                 return new Inserter( *this );
38             }
39         public:
40             size_t  m_nInsertSuccess;
41             size_t  m_nInsertFailed;
42
43         public:
44             Inserter( CppUnitMini::ThreadPool& pool, MAP& rMap )
45                 : CppUnitMini::TestThread( pool )
46                 , m_Map( rMap )
47             {}
48             Inserter( Inserter& src )
49                 : CppUnitMini::TestThread( src )
50                 , m_Map( src.m_Map )
51             {}
52
53             Map_InsDel_string&  getTest()
54             {
55                 return reinterpret_cast<Map_InsDel_string&>( m_Pool.m_Test );
56             }
57
58             virtual void init() { cds::threading::Manager::attachThread()   ; }
59             virtual void fini() { cds::threading::Manager::detachThread()   ; }
60
61             virtual void test()
62             {
63                 MAP& rMap = m_Map;
64
65                 m_nInsertSuccess =
66                     m_nInsertFailed = 0;
67
68                 const std::vector<std::string>& arrString = *getTest().m_parrString;
69                 size_t nArrSize = arrString.size();
70
71                 if ( m_nThreadNo & 1 ) {
72                     for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
73                         for ( size_t nItem = 0; nItem < c_nMapSize; ++nItem ) {
74                             if ( rMap.insert( arrString[nItem % nArrSize], nItem * 8 ) )
75                                 ++m_nInsertSuccess;
76                             else
77                                 ++m_nInsertFailed;
78                         }
79                     }
80                 }
81                 else {
82                     for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
83                         for ( size_t nItem = c_nMapSize; nItem > 0; --nItem ) {
84                             if ( rMap.insert( arrString[nItem % nArrSize], nItem * 8 ) )
85                                 ++m_nInsertSuccess;
86                             else
87                                 ++m_nInsertFailed;
88                         }
89                     }
90                 }
91             }
92         };
93
94         template <class MAP>
95         class Deleter: public CppUnitMini::TestThread
96         {
97             MAP&     m_Map;
98
99             virtual Deleter *    clone()
100             {
101                 return new Deleter( *this );
102             }
103         public:
104             size_t  m_nDeleteSuccess;
105             size_t  m_nDeleteFailed;
106
107         public:
108             Deleter( CppUnitMini::ThreadPool& pool, MAP& rMap )
109                 : CppUnitMini::TestThread( pool )
110                 , m_Map( rMap )
111             {}
112             Deleter( Deleter& src )
113                 : CppUnitMini::TestThread( src )
114                 , m_Map( src.m_Map )
115             {}
116
117             Map_InsDel_string&  getTest()
118             {
119                 return reinterpret_cast<Map_InsDel_string&>( m_Pool.m_Test );
120             }
121
122             virtual void init() { cds::threading::Manager::attachThread()   ; }
123             virtual void fini() { cds::threading::Manager::detachThread()   ; }
124
125             virtual void test()
126             {
127                 MAP& rMap = m_Map;
128
129                 m_nDeleteSuccess =
130                     m_nDeleteFailed = 0;
131
132                 const std::vector<std::string>& arrString = *getTest().m_parrString;
133                 size_t nArrSize = arrString.size();
134
135                 if ( m_nThreadNo & 1 ) {
136                     for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
137                         for ( size_t nItem = 0; nItem < c_nMapSize; ++nItem ) {
138                             if ( rMap.erase( arrString[nItem % nArrSize] ) )
139                                 ++m_nDeleteSuccess;
140                             else
141                                 ++m_nDeleteFailed;
142                         }
143                     }
144                 }
145                 else {
146                     for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
147                         for ( size_t nItem = c_nMapSize; nItem > 0; --nItem ) {
148                             if ( rMap.erase( arrString[nItem % nArrSize] ) )
149                                 ++m_nDeleteSuccess;
150                             else
151                                 ++m_nDeleteFailed;
152                         }
153                     }
154                 }
155             }
156         };
157
158     protected:
159
160         template <class MAP>
161         void do_test( MAP& testMap )
162         {
163             typedef Inserter<MAP>       InserterThread;
164             typedef Deleter<MAP>        DeleterThread;
165             cds::OS::Timer    timer;
166
167             CppUnitMini::ThreadPool pool( *this );
168             pool.add( new InserterThread( pool, testMap ), c_nInsertThreadCount );
169             pool.add( new DeleterThread( pool, testMap ), c_nDeleteThreadCount );
170             pool.run();
171             CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
172
173             size_t nInsertSuccess = 0;
174             size_t nInsertFailed = 0;
175             size_t nDeleteSuccess = 0;
176             size_t nDeleteFailed = 0;
177             for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
178                 InserterThread * pThread = dynamic_cast<InserterThread *>( *it );
179                 if ( pThread ) {
180                     nInsertSuccess += pThread->m_nInsertSuccess;
181                     nInsertFailed += pThread->m_nInsertFailed;
182                 }
183                 else {
184                     DeleterThread * p = static_cast<DeleterThread *>( *it );
185                     nDeleteSuccess += p->m_nDeleteSuccess;
186                     nDeleteFailed += p->m_nDeleteFailed;
187                 }
188             }
189
190             CPPUNIT_MSG( "    Totals: Ins succ=" << nInsertSuccess
191                 << " Del succ=" << nDeleteSuccess << "\n"
192                       << "          : Ins fail=" << nInsertFailed
193                 << " Del fail=" << nDeleteFailed
194                 << " Map size=" << testMap.size()
195                 );
196
197             check_before_cleanup( testMap );
198
199             CPPUNIT_MSG( "  Clear map (single-threaded)..." );
200             timer.reset();
201             for ( size_t i = 0; i < m_parrString->size(); ++i )
202                 testMap.erase( (*m_parrString)[i] );
203             CPPUNIT_MSG( "   Duration=" << timer.duration() );
204             CPPUNIT_CHECK( testMap.empty() );
205
206             additional_check( testMap );
207             print_stat( testMap );
208             additional_cleanup( testMap );
209         }
210
211         template <class MAP>
212         void test()
213         {
214             m_parrString = &CppUnitMini::TestCase::getTestStrings();
215
216             CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
217                 << " delete=" << c_nDeleteThreadCount
218                 << " pass count=" << c_nThreadPassCount
219                 << " map size=" << c_nMapSize
220                 );
221
222             for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
223                 CPPUNIT_MSG( "Load factor=" << nLoadFactor );
224                 MAP  testMap( c_nMapSize, nLoadFactor );
225                 do_test( testMap );
226                 if ( c_bPrintGCState )
227                     print_gc_state();
228             }
229         }
230
231         template <class MAP>
232         void test_nolf()
233         {
234             m_parrString = &CppUnitMini::TestCase::getTestStrings();
235
236             CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
237                 << " delete=" << c_nDeleteThreadCount
238                 << " pass count=" << c_nThreadPassCount
239                 << " map size=" << c_nMapSize
240                 );
241
242             MAP testMap;
243             do_test( testMap );
244             if ( c_bPrintGCState )
245                 print_gc_state();
246         }
247
248         void setUpParams( const CppUnitMini::TestCfg& cfg );
249
250         void run_MichaelMap(const char *in_name, bool invert = false);
251         void run_SplitList(const char *in_name, bool invert = false);
252         void run_StripedMap(const char *in_name, bool invert = false);
253         void run_RefinableMap(const char *in_name, bool invert = false);
254         void run_CuckooMap(const char *in_name, bool invert = false);
255         void run_SkipListMap(const char *in_name, bool invert = false);
256         void run_EllenBinTreeMap(const char *in_name, bool invert = false);
257         void run_BronsonAVLTreeMap(const char *in_name, bool invert = false);
258         void run_StdMap(const char *in_name, bool invert = false);
259
260         virtual void myRun(const char *in_name, bool invert = false);
261
262
263 #   include "map2/map_defs.h"
264         CDSUNIT_DECLARE_MichaelMap
265         CDSUNIT_DECLARE_SplitList
266         CDSUNIT_DECLARE_SkipListMap
267         CDSUNIT_DECLARE_EllenBinTreeMap
268         CDSUNIT_DECLARE_BronsonAVLTreeMap
269         CDSUNIT_DECLARE_StripedMap
270         CDSUNIT_DECLARE_RefinableMap
271         CDSUNIT_DECLARE_CuckooMap
272         CDSUNIT_DECLARE_StdMap
273     };
274 } // namespace map2