Migrated map_find_int stress test to gtest
[libcds.git] / test / stress / map / map_type_std.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-2016
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 #ifndef CDSUNIT_MAP_TYPE_STD_H
32 #define CDSUNIT_MAP_TYPE_STD_H
33
34 #include "map_type.h"
35
36 #include <map>
37 #include <unordered_map>
38
39 namespace map {
40
41     struct empty_lock
42     {
43         void lock() {}
44         void unlock() {}
45     };
46
47     template <typename Key, typename Value, typename Lock,
48         class Alloc = typename CDS_DEFAULT_ALLOCATOR::template rebind<std::pair<Key const, Value> >::other
49     >
50         class StdMap: public std::map<Key, Value, std::less<Key>, Alloc>
51     {
52         Lock m_lock;
53         typedef std::unique_lock<Lock> scoped_lock;
54         typedef std::map<Key, Value, std::less<Key>, Alloc> base_class;
55     public:
56         typedef typename base_class::mapped_type value_type;
57         typedef typename base_class::value_type  pair_type;
58         typedef size_t      item_counter;
59
60         StdMap()
61         {}
62
63         template <class Config>
64         StdMap( Config const& )
65         {}
66
67         bool contains( const Key& key )
68         {
69             scoped_lock al( m_lock );
70             return base_class::find( key ) != base_class::end();
71         }
72
73         bool insert( const Key& key, const Value& val )
74         {
75             scoped_lock al( m_lock );
76             return base_class::insert( typename base_class::value_type( key, val ) ).second;
77         }
78
79         template <typename T, typename Func>
80         bool insert( const Key& key, const T& val, Func func )
81         {
82             scoped_lock al( m_lock );
83             std::pair<typename base_class::iterator, bool> pRet = base_class::insert( typename base_class::value_type( key, Value() ) );
84             if ( pRet.second ) {
85                 func( pRet.first->second, val );
86                 return true;
87             }
88             return false;
89         }
90
91         template <typename T, typename Func>
92         std::pair<bool, bool> update( const T& key, Func func, bool /*bAllowInsert*/ = true )
93         {
94             scoped_lock al( m_lock );
95             std::pair<typename base_class::iterator, bool> pRet = base_class::insert( typename base_class::value_type( key, Value() ) );
96             if ( pRet.second ) {
97                 func( true, *pRet.first );
98                 return std::make_pair( true, true );
99             }
100             else {
101                 func( false, *pRet.first );
102                 return std::make_pair( true, false );
103             }
104         }
105
106         bool erase( const Key& key )
107         {
108             scoped_lock al( m_lock );
109             return base_class::erase( key ) != 0;
110         }
111
112         template <typename T, typename Func>
113         bool erase( const T& key, Func func )
114         {
115             scoped_lock al( m_lock );
116             typename base_class::iterator it = base_class::find( key );
117             if ( it != base_class::end() ) {
118                 func( (*it) );
119                 base_class::erase( it );
120                 return true;
121             }
122             return false;
123         }
124
125         std::ostream& dump( std::ostream& stm ) { return stm; }
126
127
128         // for testing
129         static CDS_CONSTEXPR bool const c_bExtractSupported = false;
130         static CDS_CONSTEXPR bool const c_bLoadFactorDepended = false;
131         static CDS_CONSTEXPR bool const c_bEraseExactKey = false;
132     };
133
134     template <typename Key, typename Value, typename Lock,
135         class Alloc = typename CDS_DEFAULT_ALLOCATOR::template rebind<std::pair<Key const, Value> >::other
136     >
137     class StdHashMap
138         : public std::unordered_map<
139             Key, Value
140             , std::hash<Key>
141             , std::equal_to<Key>
142             , Alloc
143         >
144     {
145     public:
146         Lock m_lock;
147         typedef std::unique_lock<Lock> scoped_lock;
148         typedef std::unordered_map<
149             Key, Value
150             , std::hash<Key>
151             , std::equal_to<Key>
152             , Alloc
153         >   base_class;
154     public:
155         typedef typename base_class::mapped_type value_type;
156         typedef size_t      item_counter;
157
158         StdHashMap()
159         {}
160
161         template <class Config>
162         StdHashMap( Config const& )
163         {}
164
165         bool contains( const Key& key )
166         {
167             scoped_lock al( m_lock );
168             return base_class::find( key ) != base_class::end();
169         }
170
171         bool insert( const Key& key, const Value& val )
172         {
173             scoped_lock al( m_lock );
174             return base_class::insert( typename base_class::value_type(key, val)).second;
175         }
176
177         template <typename T, typename Func>
178         bool insert( const Key& key, const T& val, Func func )
179         {
180             scoped_lock al( m_lock );
181             std::pair<typename base_class::iterator, bool> pRet = base_class::insert( typename base_class::value_type(key, Value() ));
182             if ( pRet.second ) {
183                 func( pRet.first->second, val );
184                 return true;
185             }
186             return false;
187         }
188
189         template <typename T, typename Func>
190         std::pair<bool, bool> update( const T& key, Func func, bool /*bAllowInsert*/ = true )
191         {
192             scoped_lock al( m_lock );
193             std::pair<typename base_class::iterator, bool> pRet = base_class::insert( typename base_class::value_type( key, Value() ));
194             if ( pRet.second ) {
195                 func( true, *pRet.first );
196                 return std::make_pair( true, true );
197             }
198             else {
199                 func( false, *pRet.first );
200                 return std::make_pair( true, false );
201             }
202         }
203
204         bool erase( const Key& key )
205         {
206             scoped_lock al( m_lock );
207             return base_class::erase( key ) != 0;
208         }
209
210         template <typename T, typename Func>
211         bool erase( const T& key, Func func )
212         {
213             scoped_lock al( m_lock );
214             typename base_class::iterator it = base_class::find( key );
215             if ( it != base_class::end() ) {
216                 func( *it );
217                 return base_class::erase( key ) != 0;
218             }
219             return false;
220         }
221
222         std::ostream& dump( std::ostream& stm ) { return stm; }
223
224
225         // for testing
226         static CDS_CONSTEXPR bool const c_bExtractSupported = false;
227         static CDS_CONSTEXPR bool const c_bLoadFactorDepended = false;
228         static CDS_CONSTEXPR bool const c_bEraseExactKey = false;
229     }; 
230
231     struct tag_StdMap;
232
233     template <typename Key, typename Value>
234     struct map_type< tag_StdMap, Key, Value >: public map_type_base< Key, Value >
235     {
236         typedef map_type_base< Key, Value >      base_class;
237         typedef typename base_class::key_compare compare;
238         typedef typename base_class::key_less    less;
239
240         typedef StdMap< Key, Value, cds::sync::spin > StdMap_Spin;
241         typedef StdMap< Key, Value, std::mutex >      StdMap_Mutex;
242         typedef StdMap< Key, Value, empty_lock>       StdMap_NoLock;
243
244         typedef StdHashMap< Key, Value, cds::sync::spin > StdHashMap_Spin;
245         typedef StdHashMap< Key, Value, std::mutex >      StdHashMap_Mutex;
246         typedef StdHashMap< Key, Value, empty_lock >      StdHashMap_NoLock;
247     };
248 }   // namespace map
249
250 #define CDSSTRESS_StdMap_case( fixture, test_case, std_map_type, key_type, value_type ) \
251     TEST_F( fixture, std_map_type ) \
252     { \
253         typedef map::map_type< tag_StdMap, key_type, value_type >::std_map_type map_type; \
254         test_case<map_type>(); \
255     }
256
257 #define CDSSTRESS_StdMap( fixture, test_case, key_type, value_type ) \
258     CDSSTRESS_StdMap_case( fixture, test_case, StdMap_Spin,      key_type, value_type ) \
259     CDSSTRESS_StdMap_case( fixture, test_case, StdMap_Mutex,     key_type, value_type ) \
260     CDSSTRESS_StdMap_case( fixture, test_case, StdHashMap_Spin,  key_type, value_type ) \
261     CDSSTRESS_StdMap_case( fixture, test_case, StdHashMap_Mutex, key_type, value_type )
262
263 #define CDSSTRESS_StdMap_nolock( fixture, test_case, key_type, value_type ) \
264     CDSSTRESS_StdMap_case( fixture, test_case, StdMap_NoLock,      key_type, value_type ) \
265     CDSSTRESS_StdMap_case( fixture, test_case, StdHashMap_NoLock,  key_type, value_type )
266
267 #endif // ifndef CDSUNIT_MAP_TYPE_STD_H