Removes randomness in sequential map test case
[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                 size_t pass_count = Map_InsDelFind::s_nPassCount;
135
136                 for (size_t count = 0; count < pass_count; count++) {
137                   bool shouldUpdate = true;
138                   for (size_t i = 0; i < s_nMapSize; ++i) {
139                     // The number to operate on the map.
140                     size_t n = i;
141                     // Insert
142                     if (i % s_nInsertPercentage == 1) {
143                       if (!shouldUpdate) {
144                         if (rMap.insert(n, n))
145                           ++m_nInsertSuccess;
146                         else
147                           ++m_nInsertFailed;
148                         shouldUpdate = true;
149                       } else {
150                         if (rMap.update(n, update_functor(), true).first)
151                           ++m_nInsertSuccess;
152                         else
153                           ++m_nInsertFailed;
154                         shouldUpdate = false;
155                       }
156                     }
157                     // Find
158                     if (rMap.contains(n))
159                       ++m_nFindSuccess;
160                     else
161                       ++m_nFindFailed;
162                     // Delete
163                     if (i % s_nInsertPercentage == 1) {
164
165                       if (rMap.erase(n))
166                         ++m_nDeleteSuccess;
167                       else
168                         ++m_nDeleteFailed;
169                       break;
170                     }
171                   }
172                 }
173             }
174         };
175
176     protected:
177         template <class Map>
178         void do_test( Map& testMap )
179         {
180             typedef Worker<Map> worker;
181             cds_test::thread_pool& pool = get_pool();
182             std::unique_ptr<worker> worker_thrd(new worker(pool, testMap));
183             worker_thrd->test();
184
185             testMap.clear();
186             EXPECT_TRUE( testMap.empty());
187             additional_cleanup( testMap );
188         }
189
190         template <class Map>
191         void run_test()
192         {
193             Map testMap( *this );
194             do_test( testMap );
195         }
196
197         template <class Map>
198         void run_bronson_avl_tree() {
199           Map_InsDelFind::s_nPassCount =
200               Map_InsDelFind::s_nBronsonAVLTreeMapPassCount;
201           run_test<Map>();
202         }
203
204         template <class Map>
205         void run_ellen_bin_tree() {
206           Map_InsDelFind::s_nPassCount =
207               Map_InsDelFind::s_nEllenBinTreeMapPassCount;
208           run_test<Map>();
209         }
210
211         template <class Map>
212         void run_skip_list() {
213           Map_InsDelFind::s_nPassCount =
214               Map_InsDelFind::s_nSkipListMapPassCount;
215           run_test<Map>();
216         }
217
218         template <class Map>
219         void run_feldman() {
220           Map_InsDelFind::s_nPassCount =
221               Map_InsDelFind::s_nFeldmanPassCount;
222           run_test<Map>();
223         }
224     };
225
226     class Map_InsDelFind_LF: public Map_InsDelFind
227         , public ::testing::WithParamInterface<size_t>
228     {
229     public:
230         template <class Map>
231         void run_test()
232         {
233             s_nLoadFactor = GetParam();
234             propout() << std::make_pair( "load_factor", s_nLoadFactor );
235             Map_InsDelFind::run_test<Map>();
236         }
237
238                                 template <class Map>
239         void run_michael() {
240           Map_InsDelFind::s_nPassCount =
241               Map_InsDelFind::s_nMichaelMapPassCount;
242           Map_InsDelFind_LF::run_test<Map>();
243         }
244
245         template <class Map>
246         void run_split_list() {
247           Map_InsDelFind::s_nPassCount =
248               Map_InsDelFind::s_nSplitListMapPassCount;
249           Map_InsDelFind_LF::run_test<Map>();
250         }
251
252         static std::vector<size_t> get_load_factors();
253     };
254
255 } // namespace map