Removed redundant spaces
[libcds.git] / test / unit / intrusive-set / test_intrusive_feldman_hashset_rcu.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_TEST_INTRUSIVE_FELDMAN_HASHSET_RCU_H
32 #define CDSUNIT_SET_TEST_INTRUSIVE_FELDMAN_HASHSET_RCU_H
33
34 #include "test_intrusive_feldman_hashset.h"
35
36 #include <cds/intrusive/feldman_hashset_rcu.h>
37
38 namespace ci = cds::intrusive;
39 namespace co = cds::opt;
40
41 template <class RCU>
42 class IntrusiveFeldmanHashSet : public cds_test::intrusive_feldman_hashset
43 {
44     typedef cds_test::intrusive_feldman_hashset base_class;
45
46 protected:
47     typedef cds::urcu::gc<RCU> rcu_type;
48
49     template <class Set>
50     void test( Set& s )
51     {
52         // Precondition: set is empty
53         // Postcondition: set is empty
54
55         base_class::test( s );
56
57         ASSERT_TRUE( s.empty());
58         ASSERT_CONTAINER_SIZE( s, 0 );
59
60         typedef typename Set::value_type value_type;
61         size_t const nSetSize = std::max( s.head_size() * 2, static_cast<size_t>(100));
62
63         std::vector< value_type > data;
64         std::vector< size_t> indices;
65         data.reserve( nSetSize );
66         indices.reserve( nSetSize );
67         for ( size_t key = 0; key < nSetSize; ++key ) {
68             data.push_back( value_type( static_cast<int>(key)) );
69             indices.push_back( key );
70         }
71         shuffle( indices.begin(), indices.end());
72
73         typename Set::exempt_ptr xp;
74         value_type * rp;
75         typedef typename Set::rcu_lock rcu_lock;
76
77         // get/extract from empty set
78         for ( auto idx : indices ) {
79             auto& i = data[idx];
80
81             {
82                 rcu_lock l;
83                 rp = s.get( i.key());
84                 ASSERT_TRUE( !rp );
85             }
86
87             xp = s.extract( i.key());
88             ASSERT_TRUE( !xp );
89         }
90
91         // fill set
92         for ( auto& i : data ) {
93             i.nDisposeCount = 0;
94             ASSERT_TRUE( s.insert( i ));
95         }
96
97         // get/extract
98         for ( auto idx : indices ) {
99             auto& i = data[idx];
100
101             {
102                 rcu_lock l;
103                 EXPECT_EQ( i.nFindCount, 0u );
104                 rp = s.get( i.key());
105                 ASSERT_FALSE( !rp );
106                 ++rp->nFindCount;
107                 EXPECT_EQ( i.nFindCount, 1u );
108             }
109
110             EXPECT_EQ( i.nEraseCount, 0u );
111             xp = s.extract( i.key());
112             ASSERT_FALSE( !xp );
113             ++xp->nEraseCount;
114             EXPECT_EQ( i.nEraseCount, 1u );
115
116             xp = s.extract( i.key());
117             ASSERT_TRUE( !xp );
118         }
119
120         ASSERT_TRUE( s.empty());
121         ASSERT_CONTAINER_SIZE( s, 0 );
122
123         // Force retiring cycle
124         Set::gc::force_dispose();
125         for ( auto& i : data ) {
126             EXPECT_EQ( i.nDisposeCount, 1u );
127         }
128     }
129
130     void SetUp()
131     {
132         RCU::Construct();
133         cds::threading::Manager::attachThread();
134     }
135
136     void TearDown()
137     {
138         cds::threading::Manager::detachThread();
139         RCU::Destruct();
140     }
141 };
142
143 TYPED_TEST_CASE_P( IntrusiveFeldmanHashSet );
144
145 TYPED_TEST_P( IntrusiveFeldmanHashSet, compare )
146 {
147     typedef typename TestFixture::rcu_type rcu_type;
148
149     struct traits : public ci::feldman_hashset::traits
150     {
151         typedef typename TestFixture::hash_accessor hash_accessor;
152         typedef typename TestFixture::cmp compare;
153         typedef typename TestFixture::mock_disposer disposer;
154     };
155
156     typedef ci::FeldmanHashSet< rcu_type, typename TestFixture::int_item, traits > set_type;
157
158     set_type s;
159     this->test( s );
160 }
161
162 TYPED_TEST_P( IntrusiveFeldmanHashSet, less )
163 {
164     typedef ci::FeldmanHashSet< typename TestFixture::rcu_type, typename TestFixture::int_item,
165         typename ci::feldman_hashset::make_traits<
166             ci::feldman_hashset::hash_accessor< typename TestFixture::hash_accessor >
167             , ci::opt::less< std::less<int>>
168             , ci::opt::disposer< typename TestFixture::mock_disposer>
169         >::type
170     > set_type;
171
172     set_type s( 5, 2 );
173     this->test( s );
174 }
175
176 TYPED_TEST_P( IntrusiveFeldmanHashSet, cmpmix )
177 {
178     struct traits : public ci::feldman_hashset::traits
179     {
180         typedef typename TestFixture::hash_accessor hash_accessor;
181         typedef typename TestFixture::cmp compare;
182         typedef std::less<int> less;
183         typedef typename TestFixture::mock_disposer disposer;
184         typedef typename TestFixture::simple_item_counter item_counter;
185     };
186
187     typedef ci::FeldmanHashSet< typename TestFixture::rcu_type, typename TestFixture::int_item, traits > set_type;
188
189     set_type s( 3, 4 );
190     this->test( s );
191 }
192
193 TYPED_TEST_P( IntrusiveFeldmanHashSet, backoff )
194 {
195     struct traits : public ci::feldman_hashset::traits
196     {
197         typedef typename TestFixture::hash_accessor hash_accessor;
198         typedef typename TestFixture::cmp compare;
199         typedef typename TestFixture::mock_disposer disposer;
200         typedef cds::backoff::empty back_off;
201         typedef ci::opt::v::sequential_consistent memory_model;
202     };
203
204     typedef ci::FeldmanHashSet< typename TestFixture::rcu_type, typename TestFixture::int_item, traits > set_type;
205
206     set_type s( 8, 3 );
207     this->test( s );
208 }
209
210 TYPED_TEST_P( IntrusiveFeldmanHashSet, stat )
211 {
212     struct traits : public ci::feldman_hashset::traits
213     {
214         typedef typename TestFixture::hash_accessor hash_accessor;
215         typedef typename TestFixture::cmp compare;
216         typedef typename TestFixture::mock_disposer disposer;
217         typedef ci::feldman_hashset::stat<> stat;
218     };
219
220     typedef ci::FeldmanHashSet< typename TestFixture::rcu_type, typename TestFixture::int_item, traits > set_type;
221
222     set_type s( 8, 3 );
223     this->test( s );
224 }
225
226 // GCC 5: All test names should be written on single line, otherwise a runtime error will be encountered like as
227 // "No test named <test_name> can be found in this test case"
228 REGISTER_TYPED_TEST_CASE_P( IntrusiveFeldmanHashSet,
229     compare, less, cmpmix, backoff, stat
230     );
231
232
233 #endif // #ifndef CDSUNIT_SET_TEST_INTRUSIVE_FELDMAN_HASHSET_RCU_H