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