2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
6 Source code repo: http://github.com/khizmax/libcds/
7 Download: http://sourceforge.net/projects/libcds/files/
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice, this
13 list of conditions and the following disclaimer.
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.
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.
31 #ifndef CDSUNIT_SET_TEST_INTRUSIVE_SET_H
32 #define CDSUNIT_SET_TEST_INTRUSIVE_SET_H
34 #include <cds_test/check_size.h>
35 #include <cds_test/fixture.h>
37 #include <cds/opt/hash.h>
39 #ifdef CDSTEST_REQUIRES_IMPLICIT_CONVERSION_WORKAROUND
40 # define CDSTEST_EXPLICIT
42 # define CDSTEST_EXPLICIT explicit
45 // forward declaration
46 namespace cds { namespace intrusive {}}
50 namespace ci = cds::intrusive;
51 namespace co = cds::opt;
53 class intrusive_set: public fixture
56 static size_t const kSize = 1000;
60 unsigned int nDisposeCount ; // count of disposer calling
61 unsigned int nFindCount ; // count of find-functor calling
62 unsigned int nUpdateNewCount;
63 unsigned int nUpdateCount;
64 mutable unsigned int nEraseCount;
73 memset( this, 0, sizeof( *this ) );
77 template <typename Node>
89 CDSTEST_EXPLICIT base_int_item( int key )
94 base_int_item(int key, int val)
99 base_int_item( base_int_item const& v )
112 template <typename Node>
113 struct member_int_item: public stat
115 typedef Node member_type;
127 CDSTEST_EXPLICIT member_int_item( int key )
132 member_int_item(int key, int val)
137 member_int_item(member_int_item const& v )
150 size_t operator()( int i ) const
152 return co::v::hash<int>()( i );
154 template <typename Item>
155 size_t operator()( const Item& i ) const
157 return (*this)( i.key() );
160 typedef hash_int hash1;
162 struct hash2: private hash1
164 typedef hash1 base_class;
166 size_t operator()( int i ) const
168 size_t h = ~(base_class::operator()( i ));
169 return ~h + 0x9e3779b9 + (h << 6) + (h >> 2);
171 template <typename Item>
172 size_t operator()( const Item& i ) const
174 size_t h = ~(base_class::operator()( i ));
175 return ~h + 0x9e3779b9 + (h << 6) + (h >> 2);
179 struct simple_item_counter {
182 simple_item_counter()
201 operator size_t() const
208 template <typename T>
211 bool operator ()(const T& v1, const T& v2 ) const
213 return v1.key() < v2.key();
216 bool operator ()(const T& v1, int v2 ) const
218 return v1.key() < v2;
221 bool operator ()(int v1, const T& v2 ) const
223 return v1 < v2.key();
226 bool operator()( int v1, int v2 ) const
232 template <typename T>
234 int operator ()(const T& v1, const T& v2 ) const
236 if ( v1.key() < v2.key() )
238 return v1.key() > v2.key() ? 1 : 0;
241 template <typename Q>
242 int operator ()(const T& v1, const Q& v2 ) const
246 return v1.key() > v2 ? 1 : 0;
249 template <typename Q>
250 int operator ()(const Q& v1, const T& v2 ) const
254 return v1 > v2.key() ? 1 : 0;
258 template <typename T>
260 int operator ()( const T& v1, const T& v2 ) const
262 return v1.key() == v2.key();
265 template <typename Q>
266 int operator ()( const T& v1, const Q& v2 ) const
268 return v1.key() == v2;
271 template <typename Q>
272 int operator ()( const Q& v1, const T& v2 ) const
274 return v1 == v2.key();
281 explicit other_item( int k )
292 template <typename T>
293 bool operator()( other_item const& lhs, T const& rhs ) const
295 return lhs.key() < rhs.key();
298 template <typename T>
299 bool operator()( T const& lhs, other_item const& rhs ) const
301 return lhs.key() < rhs.key();
304 bool operator()( other_item const& lhs, int rhs ) const
306 return lhs.key() < rhs;
309 bool operator()( int lhs, other_item const& rhs ) const
311 return lhs < rhs.key();
315 struct other_equal_to {
316 template <typename Q, typename T>
317 bool operator()( Q const& lhs, T const& rhs ) const
319 return lhs.key() == rhs.key();
325 template <typename T>
326 void operator ()( T * p )
333 template <typename Set>
339 template <bool Sorted, class Set>
342 // Precondition: set is empty
343 // Postcondition: set is empty
345 ASSERT_TRUE( s.empty() );
346 ASSERT_CONTAINER_SIZE( s, 0 );
348 typedef typename Set::value_type value_type;
349 typedef typename std::conditional< Sorted, other_less, other_equal_to >::type other_predicate;
350 size_t const nSetSize = kSize;
352 std::vector< value_type > data;
353 std::vector< size_t> indices;
354 data.reserve( kSize );
355 indices.reserve( kSize );
356 for ( size_t key = 0; key < kSize; ++key ) {
357 data.push_back( value_type( static_cast<int>( key )));
358 indices.push_back( key );
360 shuffle( indices.begin(), indices.end() );
363 for ( auto idx : indices ) {
364 auto& i = data[ idx ];
366 ASSERT_FALSE( s.contains( i.nKey ));
367 ASSERT_FALSE( s.contains( i ));
368 ASSERT_FALSE( s.contains( other_item( i.key()), other_predicate()));
369 ASSERT_FALSE( s.find( i.nKey, []( value_type&, int ) {} ));
370 ASSERT_FALSE( s.find_with( other_item( i.key()), other_predicate(), []( value_type&, other_item const& ) {} ));
372 std::pair<bool, bool> updResult;
374 updResult = s.update( i, []( bool bNew, value_type&, value_type& )
376 ASSERT_TRUE( false );
378 EXPECT_FALSE( updResult.first );
379 EXPECT_FALSE( updResult.second );
381 switch ( i.key() % 3 ) {
383 ASSERT_TRUE( s.insert( i ));
384 ASSERT_FALSE( s.insert( i ));
385 updResult = s.update( i, []( bool bNew, value_type& val, value_type& arg)
387 EXPECT_FALSE( bNew );
388 EXPECT_EQ( &val, &arg );
390 EXPECT_TRUE( updResult.first );
391 EXPECT_FALSE( updResult.second );
394 EXPECT_EQ( i.nUpdateNewCount, 0 );
395 ASSERT_TRUE( s.insert( i, []( value_type& v ) { ++v.nUpdateNewCount;} ));
396 EXPECT_EQ( i.nUpdateNewCount, 1 );
397 ASSERT_FALSE( s.insert( i, []( value_type& v ) { ++v.nUpdateNewCount;} ) );
398 EXPECT_EQ( i.nUpdateNewCount, 1 );
399 i.nUpdateNewCount = 0;
402 updResult = s.update( i, []( bool bNew, value_type& val, value_type& arg )
405 EXPECT_EQ( &val, &arg );
407 EXPECT_TRUE( updResult.first );
408 EXPECT_TRUE( updResult.second );
412 ASSERT_TRUE( s.contains( i.nKey ) );
413 ASSERT_TRUE( s.contains( i ) );
414 ASSERT_TRUE( s.contains( other_item( i.key() ), other_predicate()));
415 EXPECT_EQ( i.nFindCount, 0 );
416 ASSERT_TRUE( s.find( i.nKey, []( value_type& v, int ) { ++v.nFindCount; } ));
417 EXPECT_EQ( i.nFindCount, 1 );
418 ASSERT_TRUE( s.find_with( other_item( i.key() ), other_predicate(), []( value_type& v, other_item const& ) { ++v.nFindCount; } ));
419 EXPECT_EQ( i.nFindCount, 2 );
421 ASSERT_FALSE( s.empty() );
422 ASSERT_CONTAINER_SIZE( s, nSetSize );
424 std::for_each( data.begin(), data.end(), []( value_type& v ) { v.clear_stat(); });
427 shuffle( indices.begin(), indices.end() );
428 for ( auto idx : indices ) {
429 auto& i = data[ idx ];
431 ASSERT_TRUE( s.contains( i.nKey ) );
432 ASSERT_TRUE( s.contains( i ) );
433 ASSERT_TRUE( s.contains( other_item( i.key() ), other_predicate() ) );
434 EXPECT_EQ( i.nFindCount, 0 );
435 ASSERT_TRUE( s.find( i.nKey, []( value_type& v, int ) { ++v.nFindCount; } ) );
436 EXPECT_EQ( i.nFindCount, 1 );
437 ASSERT_TRUE( s.find_with( other_item( i.key() ), other_predicate(), []( value_type& v, other_item const& ) { ++v.nFindCount; } ) );
438 EXPECT_EQ( i.nFindCount, 2 );
441 switch ( i.key() % 6 ) {
443 ASSERT_FALSE( s.unlink( v ));
444 ASSERT_TRUE( s.unlink( i ));
445 ASSERT_FALSE( s.unlink( i ) );
448 ASSERT_TRUE( s.erase( i.key()));
449 ASSERT_FALSE( s.erase( i.key() ) );
452 ASSERT_TRUE( s.erase( v ));
453 ASSERT_FALSE( s.erase( v ) );
456 ASSERT_TRUE( s.erase_with( other_item( i.key()), other_predicate()));
457 ASSERT_FALSE( s.erase_with( other_item( i.key() ), other_predicate() ) );
460 EXPECT_EQ( i.nEraseCount, 0 );
461 ASSERT_TRUE( s.erase( v, []( value_type& val ) { ++val.nEraseCount; } ));
462 EXPECT_EQ( i.nEraseCount, 1 );
463 ASSERT_FALSE( s.erase( v, []( value_type& val ) { ++val.nEraseCount; } ));
464 EXPECT_EQ( i.nEraseCount, 1 );
467 EXPECT_EQ( i.nEraseCount, 0 );
468 ASSERT_TRUE( s.erase_with( other_item( i.key() ), other_predicate(), []( value_type& val ) { ++val.nEraseCount; } ));
469 EXPECT_EQ( i.nEraseCount, 1 );
470 ASSERT_FALSE( s.erase_with( other_item( i.key() ), other_predicate(), []( value_type& val ) { ++val.nEraseCount; } ));
471 EXPECT_EQ( i.nEraseCount, 1 );
475 ASSERT_FALSE( s.contains( i.nKey ));
476 ASSERT_FALSE( s.contains( i ));
477 ASSERT_FALSE( s.contains( other_item( i.key()), other_predicate()));
478 ASSERT_FALSE( s.find( i.nKey, []( value_type&, int ) {} ));
479 ASSERT_FALSE( s.find_with( other_item( i.key()), other_predicate(), []( value_type&, other_item const& ) {} ));
481 ASSERT_TRUE( s.empty() );
482 ASSERT_CONTAINER_SIZE( s, 0 );
485 for ( auto& i : data ) {
487 ASSERT_TRUE( s.insert( i ));
489 ASSERT_FALSE( s.empty() );
490 ASSERT_CONTAINER_SIZE( s, nSetSize );
494 ASSERT_TRUE( s.empty() );
495 ASSERT_CONTAINER_SIZE( s, 0 );
498 for ( auto& i : data ) {
500 ASSERT_TRUE( s.insert( i ) );
502 ASSERT_FALSE( s.empty() );
503 ASSERT_CONTAINER_SIZE( s, nSetSize );
505 s.clear_and_dispose( mock_disposer() );
507 ASSERT_TRUE( s.empty() );
508 ASSERT_CONTAINER_SIZE( s, 0 );
509 for ( auto& i : data ) {
510 EXPECT_EQ( i.nDisposeCount, 1 );
516 } // namespace cds_test
518 #endif // #ifndef CDSUNIT_SET_TEST_INTRUSIVE_SET_H