f1b03bf8c784e3deb7274ec40f94c31a12c01718
[libcds.git] / test / stress / sequential / sequential-map / insdelfind / map_insdelfind.h
1 /*
2     This file is a part of libcds - Concurrent Data Structures library
3
4     (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
5
6     Source code repo: http://github.com/khizmax/libcds/
7     Download: http://sourceforge.net/projects/libcds/files/
8
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions are met:
11
12     * Redistributions of source code must retain the above copyright notice, this
13       list of conditions and the following disclaimer.
14
15     * Redistributions in binary form must reproduce the above copyright notice,
16       this list of conditions and the following disclaimer in the documentation
17       and/or other materials provided with the distribution.
18
19     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "map_type.h"
32
33 namespace map {
34
35
36     class Map_InsDelFind: public cds_test::stress_fixture
37     {
38     public:
39         static size_t s_nMapSize;           // initial map size
40
41         static size_t s_nPassCount;
42         static size_t s_nBronsonAVLTreeMapPassCount;
43         static size_t s_nEllenBinTreeMapPassCount;
44         static size_t s_nFeldmanPassCount;
45         static size_t s_nMichaelMapPassCount;
46         static size_t s_nSkipListMapPassCount;
47         static size_t s_nSplitListMapPassCount;
48
49         static size_t s_nThreadCount;       // thread count
50         static size_t s_nMaxLoadFactor;     // maximum load factor
51         static unsigned int s_nInsertPercentage;
52         static unsigned int s_nDeletePercentage;
53         static unsigned int s_nDuration;    // test duration, seconds
54
55         static size_t s_nCuckooInitialSize;         // initial size for CuckooMap
56         static size_t s_nCuckooProbesetSize;        // CuckooMap probeset size (only for list-based probeset)
57         static size_t s_nCuckooProbesetThreshold;   // CuckooMap probeset threshold (o - use default)
58
59         static size_t s_nFeldmanMap_HeadBits;
60         static size_t s_nFeldmanMap_ArrayBits;
61
62         static size_t  s_nLoadFactor;  // current load factor
63
64         static void SetUpTestCase();
65         //static void TearDownTestCase();
66
67     public:
68         enum actions
69         {
70             do_find,
71             do_insert,
72             do_delete
73         };
74         static const unsigned int c_nShuffleSize = 100;
75         static actions s_arrShuffle[c_nShuffleSize];
76
77     protected:
78         typedef size_t  key_type;
79         typedef size_t  value_type;
80
81         template <class Map>
82         class Worker: public cds_test::thread
83         {
84             typedef cds_test::thread base_class;
85             Map&     m_Map;
86
87         public:
88             size_t  m_nInsertSuccess = 0;
89             size_t  m_nInsertFailed = 0;
90             size_t  m_nDeleteSuccess = 0;
91             size_t  m_nDeleteFailed = 0;
92             size_t  m_nFindSuccess = 0;
93             size_t  m_nFindFailed = 0;
94
95         public:
96             Worker( cds_test::thread_pool& pool, Map& map )
97                 : base_class( pool )
98                 , m_Map( map )
99             {}
100
101             Worker( Worker& src )
102                 : base_class( src )
103                 , m_Map( src.m_Map )
104             {}
105
106             virtual thread * clone()
107             {
108                 return new Worker( *this );
109             }
110
111             typedef std::pair< key_type const, value_type > map_value_type;
112
113             struct update_functor {
114                 template <typename Q>
115                 void operator()( bool /*bNew*/, map_value_type& /*cur*/, Q const& /*val*/ ) const
116                 {}
117
118                 // FeldmanHashMap
119                 void operator()( map_value_type& /*cur*/, map_value_type* /*old*/) const
120                 {}
121
122                 // MichaelMap
123                 void operator()( bool /*bNew*/, map_value_type& /*cur*/ ) const
124                 {}
125
126                 // BronsonAVLTreeMap
127                 void operator()( bool /*bNew*/, key_type /*key*/, value_type& /*val*/ ) const
128                 {}
129             };
130
131             virtual void test()
132             {
133                 Map& rMap = m_Map;
134                 Map_InsDelFind& fixture = pool().template fixture<Map_InsDelFind>();
135                 size_t pass_count = fixture.s_nPassCount;
136
137                 unsigned int i = 0;
138                 size_t const nNormalize = size_t(-1) / ( s_nMapSize * 2 );
139
140                 size_t nRand = 0;
141                 while ( pass_count-- ) {
142                     nRand = cds::bitop::RandXorShift( nRand );
143                     size_t n = nRand / nNormalize;
144                     switch ( s_arrShuffle[i] ) {
145                     case do_find:
146                         if ( rMap.contains( n ))
147                             ++m_nFindSuccess;
148                         else
149                             ++m_nFindFailed;
150                         break;
151                     case do_insert:
152                         if ( n % 2 ) {
153                             if ( rMap.insert( n, n ))
154                                 ++m_nInsertSuccess;
155                             else
156                                 ++m_nInsertFailed;
157                         }
158                         else {
159                             if ( rMap.update( n, update_functor(), true ).first )
160                                 ++m_nInsertSuccess;
161                             else
162                                 ++m_nInsertFailed;
163                         }
164                         break;
165                     case do_delete:
166                         if ( rMap.erase( n ))
167                             ++m_nDeleteSuccess;
168                         else
169                             ++m_nDeleteFailed;
170                         break;
171                     }
172
173                     if ( ++i >= c_nShuffleSize )
174                         i = 0;
175                 }
176             }
177         };
178
179     protected:
180         template <class Map>
181         void do_test( Map& testMap )
182         {
183             typedef Worker<Map> worker;
184
185             // fill map - only odd number
186             {
187                 std::vector<size_t> arr;
188                 arr.reserve( s_nMapSize );
189                 for ( size_t i = 0; i < s_nMapSize; ++i )
190                     arr.push_back( i * 2 + 1);
191                 shuffle( arr.begin(), arr.end());
192                 for ( size_t i = 0; i < s_nMapSize; ++i )
193                     testMap.insert( arr[i], arr[i] );
194             }
195
196             cds_test::thread_pool& pool = get_pool();
197             std::unique_ptr<worker> worker_thrd(new worker(pool, testMap));
198             worker_thrd->test();
199
200             testMap.clear();
201             EXPECT_TRUE( testMap.empty());
202             additional_cleanup( testMap );
203         }
204
205         template <class Map>
206         void run_test()
207         {
208             Map testMap( *this );
209             do_test( testMap );
210         }
211
212         template <class Map>
213         void run_bronson_avl_tree() {
214           Map_InsDelFind::s_nPassCount =
215               Map_InsDelFind::s_nBronsonAVLTreeMapPassCount;
216           run_test<Map>();
217         }
218
219         template <class Map>
220         void run_ellen_bin_tree() {
221           Map_InsDelFind::s_nPassCount =
222               Map_InsDelFind::s_nEllenBinTreeMapPassCount;
223           run_test<Map>();
224         }
225
226         template <class Map>
227         void run_skip_list() {
228           Map_InsDelFind::s_nPassCount =
229               Map_InsDelFind::s_nSkipListMapPassCount;
230           run_test<Map>();
231         }
232
233         template <class Map>
234         void run_feldman() {
235           Map_InsDelFind::s_nPassCount =
236               Map_InsDelFind::s_nFeldmanPassCount;
237           run_test<Map>();
238         }
239     };
240
241     class Map_InsDelFind_LF: public Map_InsDelFind
242         , public ::testing::WithParamInterface<size_t>
243     {
244     public:
245         template <class Map>
246         void run_test()
247         {
248             s_nLoadFactor = GetParam();
249             propout() << std::make_pair( "load_factor", s_nLoadFactor );
250             Map_InsDelFind::run_test<Map>();
251         }
252
253                                 template <class Map>
254         void run_michael() {
255           Map_InsDelFind::s_nPassCount =
256               Map_InsDelFind::s_nMichaelMapPassCount;
257           Map_InsDelFind_LF::run_test<Map>();
258         }
259
260         template <class Map>
261         void run_split_list() {
262           Map_InsDelFind::s_nPassCount =
263               Map_InsDelFind::s_nSplitListMapPassCount;
264           Map_InsDelFind_LF::run_test<Map>();
265         }
266
267         static std::vector<size_t> get_load_factors();
268     };
269
270 } // namespace map