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