Merge branch 'dev'
[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         std::ostream& dump( std::ostream& stm ) { return stm; }
134
135         // for testing
136         static CDS_CONSTEXPR bool const c_bExtractSupported = false;
137         static CDS_CONSTEXPR bool const c_bLoadFactorDepended = false;
138         static CDS_CONSTEXPR bool const c_bEraseExactKey = true;
139     };
140
141     template <typename Value, typename Less, typename Lock,
142         class Alloc = typename CDS_DEFAULT_ALLOCATOR::template rebind<Value>::other
143     >
144     class StdSet: public std::set<Value, Less, Alloc>
145     {
146         Lock m_lock;
147         typedef std::unique_lock<Lock> scoped_lock;
148         typedef std::set<Value, Less, Alloc> base_class;
149     public:
150         typedef typename base_class::key_type value_type;
151
152         template <class Config>
153         StdSet( Config const& )
154         {}
155
156         template <typename Key>
157         bool contains( const Key& key )
158         {
159             value_type v( key );
160             scoped_lock al( m_lock );
161             return base_class::find( v ) != base_class::end();
162         }
163
164         bool insert( value_type const& v )
165         {
166             scoped_lock al( m_lock );
167             return base_class::insert( v ).second;
168         }
169
170         template <typename Key, typename Func>
171         bool insert( Key const& key, Func func )
172         {
173             scoped_lock al( m_lock );
174             std::pair<typename base_class::iterator, bool> pRet = base_class::insert( value_type( key ));
175             if ( pRet.second ) {
176                 func( *pRet.first );
177                 return true;
178             }
179             return false;
180         }
181
182         template <typename T, typename Func>
183         std::pair<bool, bool> ensure( const T& key, Func func )
184         {
185             scoped_lock al( m_lock );
186             std::pair<typename base_class::iterator, bool> pRet = base_class::insert( value_type( key ));
187             if ( pRet.second ) {
188                 func( true, *pRet.first, key );
189                 return std::make_pair( true, true );
190             }
191             else {
192                 func( false, *pRet.first, key );
193                 return std::make_pair( true, false );
194             }
195         }
196
197         template <typename Key>
198         bool erase( const Key& key )
199         {
200             scoped_lock al( m_lock );
201             return base_class::erase( value_type(key) ) != 0;
202         }
203
204         template <typename T, typename Func>
205         bool erase( const T& key, Func func )
206         {
207             scoped_lock al( m_lock );
208             typename base_class::iterator it = base_class::find( value_type(key) );
209             if ( it != base_class::end() ) {
210                 func( *it );
211
212                 base_class::erase( it );
213                 return true;
214             }
215             return false;
216         }
217
218         std::ostream& dump( std::ostream& stm ) { return stm; }
219
220         // for testing
221         static CDS_CONSTEXPR bool const c_bExtractSupported = false;
222         static CDS_CONSTEXPR bool const c_bLoadFactorDepended = false;
223     };
224
225     template <typename Key, typename Val>
226     struct set_type< tag_StdSet, Key, Val >: public set_type_base< Key, Val >
227     {
228         typedef set_type_base< Key, Val > base_class;
229         typedef typename base_class::key_val key_val;
230         typedef typename base_class::less less;
231         typedef typename base_class::hash hash;
232         typedef typename base_class::equal_to equal_to;
233
234         typedef StdSet< key_val, less, cds::sync::spin > StdSet_Spin;
235         typedef StdSet< key_val, less, std::mutex > StdSet_Mutex;
236         //typedef StdSet< key_val, less, lock::NoLock>     StdSet_NoLock;
237
238         typedef StdHashSet< key_val, hash, less, equal_to, cds::sync::spin > StdHashSet_Spin;
239         typedef StdHashSet< key_val, hash, less, equal_to, std::mutex > StdHashSet_Mutex;
240         //typedef StdHashSet< key_val, hash, less, equal_to, lock::NoLock >    StdHashSet_NoLock;
241     };
242
243 } // namespace set
244
245 #define CDSSTRESS_StdSet_case( fixture, test_case, std_set_type, key_type, value_type ) \
246     TEST_F( fixture, std_set_type ) \
247     { \
248         typedef set::set_type< tag_StdSet, key_type, value_type >::std_set_type set_type; \
249         test_case<set_type>(); \
250     }
251
252 #define CDSSTRESS_StdSet( fixture, test_case, key_type, value_type ) \
253     CDSSTRESS_StdSet_case( fixture, test_case, StdSet_Spin,      key_type, value_type ) \
254     CDSSTRESS_StdSet_case( fixture, test_case, StdSet_Mutex,     key_type, value_type ) \
255     CDSSTRESS_StdSet_case( fixture, test_case, StdHashSet_Spin,  key_type, value_type ) \
256     CDSSTRESS_StdSet_case( fixture, test_case, StdHashSet_Mutex, key_type, value_type )
257
258 #endif // #ifndef CDSUNIT_SET_TYPE_STD_H