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