Updated copyright
[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-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 #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         template <typename Key>
168         bool insert( Key const& k )
169         {
170             scoped_lock al( m_lock );
171             return base_class::insert( value_type( k )).second;
172         }
173
174         template <typename Key, typename Func>
175         bool insert( Key const& key, Func func )
176         {
177             scoped_lock al( m_lock );
178             std::pair<typename base_class::iterator, bool> pRet = base_class::insert( value_type( key ));
179             if ( pRet.second ) {
180                 func( *pRet.first );
181                 return true;
182             }
183             return false;
184         }
185
186         template <typename T, typename Func>
187         std::pair<bool, bool> ensure( const T& key, Func func )
188         {
189             scoped_lock al( m_lock );
190             std::pair<typename base_class::iterator, bool> pRet = base_class::insert( value_type( key ));
191             if ( pRet.second ) {
192                 func( true, *pRet.first, key );
193                 return std::make_pair( true, true );
194             }
195             else {
196                 func( false, *pRet.first, key );
197                 return std::make_pair( true, false );
198             }
199         }
200
201         template <typename Key>
202         bool erase( const Key& key )
203         {
204             scoped_lock al( m_lock );
205             return base_class::erase( value_type(key)) != 0;
206         }
207
208         template <typename T, typename Func>
209         bool erase( const T& key, Func func )
210         {
211             scoped_lock al( m_lock );
212             typename base_class::iterator it = base_class::find( value_type(key));
213             if ( it != base_class::end()) {
214                 func( *it );
215
216                 base_class::erase( it );
217                 return true;
218             }
219             return false;
220         }
221
222         empty_stat statistics() const
223         {
224             return empty_stat();
225         }
226
227         // for testing
228         static CDS_CONSTEXPR bool const c_bExtractSupported = false;
229         static CDS_CONSTEXPR bool const c_bLoadFactorDepended = false;
230     };
231
232     template <typename Key, typename Val>
233     struct set_type< tag_StdSet, Key, Val >: public set_type_base< Key, Val >
234     {
235         typedef set_type_base< Key, Val > base_class;
236         typedef typename base_class::key_val key_val;
237         typedef typename base_class::less less;
238         typedef typename base_class::hash hash;
239         typedef typename base_class::equal_to equal_to;
240
241         typedef StdSet< key_val, less, cds::sync::spin > StdSet_Spin;
242         typedef StdSet< key_val, less, std::mutex > StdSet_Mutex;
243         //typedef StdSet< key_val, less, lock::NoLock>     StdSet_NoLock;
244
245         typedef StdHashSet< key_val, hash, less, equal_to, cds::sync::spin > StdHashSet_Spin;
246         typedef StdHashSet< key_val, hash, less, equal_to, std::mutex > StdHashSet_Mutex;
247         //typedef StdHashSet< key_val, hash, less, equal_to, lock::NoLock >    StdHashSet_NoLock;
248     };
249
250 } // namespace set
251
252 #define CDSSTRESS_StdSet_case( fixture, test_case, std_set_type, key_type, value_type ) \
253     TEST_F( fixture, std_set_type ) \
254     { \
255         typedef set::set_type< tag_StdSet, key_type, value_type >::std_set_type set_type; \
256         test_case<set_type>(); \
257     }
258
259 #define CDSSTRESS_StdSet( fixture, test_case, key_type, value_type ) \
260     CDSSTRESS_StdSet_case( fixture, test_case, StdSet_Spin,      key_type, value_type ) \
261     CDSSTRESS_StdSet_case( fixture, test_case, StdSet_Mutex,     key_type, value_type ) \
262     CDSSTRESS_StdSet_case( fixture, test_case, StdHashSet_Spin,  key_type, value_type ) \
263     CDSSTRESS_StdSet_case( fixture, test_case, StdHashSet_Mutex, key_type, value_type )
264
265 #endif // #ifndef CDSUNIT_SET_TYPE_STD_H