</ClCompile>\r
<ClCompile Include="..\..\..\test\unit\set\intrusive_split_michael_rcu_shb.cpp" />\r
<ClCompile Include="..\..\..\test\unit\set\intrusive_split_michael_rcu_sht.cpp" />\r
+ <ClCompile Include="..\..\..\test\unit\set\michael_michael_dhp.cpp" />\r
+ <ClCompile Include="..\..\..\test\unit\set\michael_michael_hp.cpp" />\r
</ItemGroup>\r
<ItemGroup>\r
<ClInclude Include="..\..\..\test\unit\set\test_intrusive_feldman_hashset.h" />\r
<Filter Include="Source Files\intrusive:FeldmanHashSet">\r
<UniqueIdentifier>{852d2603-551b-460b-b17f-f370d91f79e7}</UniqueIdentifier>\r
</Filter>\r
+ <Filter Include="Source Files\MichaelSet">\r
+ <UniqueIdentifier>{4c75be9d-6104-435d-b08f-09fa33b2bfcc}</UniqueIdentifier>\r
+ </Filter>\r
</ItemGroup>\r
<ItemGroup>\r
<ClCompile Include="..\..\..\test\unit\main.cpp">\r
<ClCompile Include="..\..\..\test\unit\set\intrusive_feldman_hashset_rcu_sht.cpp">\r
<Filter>Source Files\intrusive:FeldmanHashSet</Filter>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\test\unit\set\michael_michael_hp.cpp">\r
+ <Filter>Source Files\MichaelSet</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="..\..\..\test\unit\set\michael_michael_dhp.cpp">\r
+ <Filter>Source Files\MichaelSet</Filter>\r
+ </ClCompile>\r
</ItemGroup>\r
<ItemGroup>\r
<ClInclude Include="..\..\..\test\unit\set\test_intrusive_set.h">\r
intrusive_split_michael_rcu_gpt.cpp
intrusive_split_michael_rcu_shb.cpp
intrusive_split_michael_rcu_sht.cpp
+ michael_michael_hp.cpp
+ michael_michael_dhp.cpp
)
include_directories(
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "test_set_hp.h"
+
+#include <cds/container/michael_list_dhp.h>
+#include <cds/container/michael_set.h>
+
+namespace {
+ namespace cc = cds::container;
+ typedef cds::gc::DHP gc_type;
+
+ class MichaelSet_DHP : public cds_test::container_set_hp
+ {
+ protected:
+ typedef cds_test::container_set_hp base_class;
+
+ void SetUp()
+ {
+ typedef cc::MichaelList< gc_type, int_item > list_type;
+ typedef cc::MichaelHashSet< gc_type, list_type > set_type;
+
+ // +1 - for guarded_ptr
+ cds::gc::dhp::GarbageCollector::Construct( 16, set_type::c_nHazardPtrCount );
+ cds::threading::Manager::attachThread();
+ }
+
+ void TearDown()
+ {
+ cds::threading::Manager::detachThread();
+ cds::gc::dhp::GarbageCollector::Destruct();
+ }
+ };
+
+ TEST_F( MichaelSet_DHP, compare )
+ {
+ typedef cc::MichaelList< gc_type, int_item,
+ typename cc::michael_list::make_traits<
+ cds::opt::compare< cmp >
+ >::type
+ > list_type;
+
+ typedef cc::MichaelHashSet< gc_type, list_type,
+ typename cc::michael_set::make_traits<
+ cds::opt::hash< hash_int >
+ >::type
+ > set_type;
+
+ set_type s( kSize, 2 );
+ test( s );
+ }
+
+ TEST_F( MichaelSet_DHP, less )
+ {
+ typedef cc::MichaelList< gc_type, int_item,
+ typename cc::michael_list::make_traits<
+ cds::opt::less< base_class::less >
+ >::type
+ > list_type;
+
+ typedef cc::MichaelHashSet< gc_type, list_type,
+ typename cc::michael_set::make_traits<
+ cds::opt::hash< hash_int >
+ >::type
+ > set_type;
+
+ set_type s( kSize, 2 );
+ test( s );
+ }
+
+ TEST_F( MichaelSet_DHP, cmpmix )
+ {
+ struct list_traits : public cc::michael_list::traits
+ {
+ typedef base_class::less less;
+ typedef cmp compare;
+ };
+ typedef cc::MichaelList< gc_type, int_item, list_traits > list_type;
+
+ typedef cc::MichaelHashSet< gc_type, list_type,
+ typename cc::michael_set::make_traits<
+ cds::opt::hash< hash_int >
+ >::type
+ > set_type;
+
+ set_type s( kSize, 2 );
+ test( s );
+ }
+
+ TEST_F( MichaelSet_DHP, item_counting )
+ {
+ struct list_traits : public cc::michael_list::traits
+ {
+ typedef cmp compare;
+ };
+ typedef cc::MichaelList< gc_type, int_item, list_traits > list_type;
+
+ struct set_traits: public cc::michael_set::traits
+ {
+ typedef hash_int hash;
+ typedef simple_item_counter item_counter;
+ };
+ typedef cc::MichaelHashSet< gc_type, list_type, set_traits >set_type;
+
+ set_type s( kSize, 3 );
+ test( s );
+ }
+
+ TEST_F( MichaelSet_DHP, backoff )
+ {
+ struct list_traits : public cc::michael_list::traits
+ {
+ typedef cmp compare;
+ typedef cds::backoff::exponential<cds::backoff::pause, cds::backoff::yield> back_off;
+ };
+ typedef cc::MichaelList< gc_type, int_item, list_traits > list_type;
+
+ struct set_traits : public cc::michael_set::traits
+ {
+ typedef hash_int hash;
+ typedef cds::atomicity::item_counter item_counter;
+ };
+ typedef cc::MichaelHashSet< gc_type, list_type, set_traits >set_type;
+
+ set_type s( kSize, 4 );
+ test( s );
+ }
+
+ TEST_F( MichaelSet_DHP, seq_cst )
+ {
+ struct list_traits : public cc::michael_list::traits
+ {
+ typedef base_class::less less;
+ typedef cds::backoff::pause back_off;
+ typedef cds::opt::v::sequential_consistent memory_model;
+ };
+ typedef cc::MichaelList< gc_type, int_item, list_traits > list_type;
+
+ struct set_traits : public cc::michael_set::traits
+ {
+ typedef hash_int hash;
+ typedef cds::atomicity::item_counter item_counter;
+ };
+ typedef cc::MichaelHashSet< gc_type, list_type, set_traits >set_type;
+
+ set_type s( kSize, 4 );
+ test( s );
+ }
+
+} // namespace
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "test_set_hp.h"
+
+#include <cds/container/michael_list_hp.h>
+#include <cds/container/michael_set.h>
+
+namespace {
+ namespace cc = cds::container;
+ typedef cds::gc::HP gc_type;
+
+ class MichaelSet_HP : public cds_test::container_set_hp
+ {
+ protected:
+ typedef cds_test::container_set_hp base_class;
+
+ void SetUp()
+ {
+ typedef cc::MichaelList< gc_type, int_item > list_type;
+ typedef cc::MichaelHashSet< gc_type, list_type > set_type;
+
+ // +1 - for guarded_ptr
+ cds::gc::hp::GarbageCollector::Construct( set_type::c_nHazardPtrCount + 1, 1, 16 );
+ cds::threading::Manager::attachThread();
+ }
+
+ void TearDown()
+ {
+ cds::threading::Manager::detachThread();
+ cds::gc::hp::GarbageCollector::Destruct( true );
+ }
+ };
+
+ TEST_F( MichaelSet_HP, compare )
+ {
+ typedef cc::MichaelList< gc_type, int_item,
+ typename cc::michael_list::make_traits<
+ cds::opt::compare< cmp >
+ >::type
+ > list_type;
+
+ typedef cc::MichaelHashSet< gc_type, list_type,
+ typename cc::michael_set::make_traits<
+ cds::opt::hash< hash_int >
+ >::type
+ > set_type;
+
+ set_type s( kSize, 2 );
+ test( s );
+ }
+
+ TEST_F( MichaelSet_HP, less )
+ {
+ typedef cc::MichaelList< gc_type, int_item,
+ typename cc::michael_list::make_traits<
+ cds::opt::less< base_class::less >
+ >::type
+ > list_type;
+
+ typedef cc::MichaelHashSet< gc_type, list_type,
+ typename cc::michael_set::make_traits<
+ cds::opt::hash< hash_int >
+ >::type
+ > set_type;
+
+ set_type s( kSize, 2 );
+ test( s );
+ }
+
+ TEST_F( MichaelSet_HP, cmpmix )
+ {
+ struct list_traits : public cc::michael_list::traits
+ {
+ typedef base_class::less less;
+ typedef cmp compare;
+ };
+ typedef cc::MichaelList< gc_type, int_item, list_traits > list_type;
+
+ typedef cc::MichaelHashSet< gc_type, list_type,
+ typename cc::michael_set::make_traits<
+ cds::opt::hash< hash_int >
+ >::type
+ > set_type;
+
+ set_type s( kSize, 2 );
+ test( s );
+ }
+
+ TEST_F( MichaelSet_HP, item_counting )
+ {
+ struct list_traits : public cc::michael_list::traits
+ {
+ typedef cmp compare;
+ };
+ typedef cc::MichaelList< gc_type, int_item, list_traits > list_type;
+
+ struct set_traits: public cc::michael_set::traits
+ {
+ typedef hash_int hash;
+ typedef simple_item_counter item_counter;
+ };
+ typedef cc::MichaelHashSet< gc_type, list_type, set_traits >set_type;
+
+ set_type s( kSize, 3 );
+ test( s );
+ }
+
+ TEST_F( MichaelSet_HP, backoff )
+ {
+ struct list_traits : public cc::michael_list::traits
+ {
+ typedef cmp compare;
+ typedef cds::backoff::exponential<cds::backoff::pause, cds::backoff::yield> back_off;
+ };
+ typedef cc::MichaelList< gc_type, int_item, list_traits > list_type;
+
+ struct set_traits : public cc::michael_set::traits
+ {
+ typedef hash_int hash;
+ typedef cds::atomicity::item_counter item_counter;
+ };
+ typedef cc::MichaelHashSet< gc_type, list_type, set_traits >set_type;
+
+ set_type s( kSize, 4 );
+ test( s );
+ }
+
+ TEST_F( MichaelSet_HP, seq_cst )
+ {
+ struct list_traits : public cc::michael_list::traits
+ {
+ typedef base_class::less less;
+ typedef cds::backoff::pause back_off;
+ typedef cds::opt::v::sequential_consistent memory_model;
+ };
+ typedef cc::MichaelList< gc_type, int_item, list_traits > list_type;
+
+ struct set_traits : public cc::michael_set::traits
+ {
+ typedef hash_int hash;
+ typedef cds::atomicity::item_counter item_counter;
+ };
+ typedef cc::MichaelHashSet< gc_type, list_type, set_traits >set_type;
+
+ set_type s( kSize, 4 );
+ test( s );
+ }
+
+} // namespace
namespace cds { namespace container {}}
namespace cds_test {
- namespace cc = cds::container;
namespace co = cds::opt;
class container_set : public fixture
}
};
- struct int_item
+ struct int_item: public stat
{
int nKey;
int nVal;
return v1.key() > v2.key() ? 1 : 0;
}
- template <typename T, typename Q>
- int operator ()( T const& v1, const Q& v2 ) const
+ template <typename T>
+ int operator ()( T const& v1, int v2 ) const
{
if ( v1.key() < v2 )
return -1;
return v1.key() > v2 ? 1 : 0;
}
- template <typename T, typename Q>
- int operator ()( const Q& v1, T const& v2 ) const
+ template <typename T>
+ int operator ()( int v1, T const& v2 ) const
{
if ( v1 < v2.key() )
return -1;
case 0:
ASSERT_TRUE( s.insert( i ));
ASSERT_FALSE( s.insert( i ));
- updResult = s.update( i, []( bool bNew, value_type& val, value_type& arg)
+ updResult = s.update( i, []( bool bNew, value_type& val, value_type const& arg)
{
EXPECT_FALSE( bNew );
- EXPECT_EQ( &val, &arg );
+ EXPECT_EQ( val.key(), arg.key() );
}, false );
EXPECT_TRUE( updResult.first );
EXPECT_FALSE( updResult.second );
updResult = s.update( i.key(), []( bool bNew, value_type& val, int arg)
{
EXPECT_FALSE( bNew );
- EXPECT_EQ( &val, &arg );
+ EXPECT_EQ( val.key(), arg );
}, false );
EXPECT_TRUE( updResult.first );
EXPECT_FALSE( updResult.second );
case 2:
ASSERT_TRUE( s.insert( i, []( value_type& v ) { ++v.nFindCount; } ));
ASSERT_FALSE( s.insert( i, []( value_type& v ) { ++v.nFindCount; } ));
- ASSERT_TRUE( s.find( i.nKey, []( value_type const& V, int key )
+ ASSERT_TRUE( s.find( i.nKey, []( value_type const& v, int key )
{
EXPECT_EQ( v.key(), key );
EXPECT_EQ( v.nFindCount, 1 );
case 3:
ASSERT_TRUE( s.insert( i.key(), []( value_type& v ) { ++v.nFindCount; } ));
ASSERT_FALSE( s.insert( i.key(), []( value_type& v ) { ++v.nFindCount; } ));
- ASSERT_TRUE( s.find( i.nKey, []( value_type const& V, int key )
+ ASSERT_TRUE( s.find( i.nKey, []( value_type const& v, int key )
{
EXPECT_EQ( v.key(), key );
EXPECT_EQ( v.nFindCount, 1 );
updResult = s.update( i, []( bool bNew, value_type& v, value_type const& arg )
{
- EXPECT_TRUE( bNew );
+ EXPECT_FALSE( bNew );
EXPECT_EQ( v.key(), arg.key() );
++v.nUpdateNewCount;
- } ), false );
+ }, false );
EXPECT_TRUE( updResult.first );
EXPECT_FALSE( updResult.second );
- ASSERT_TRUE( s.find( i.nKey, []( value_type const& V, int key )
+ ASSERT_TRUE( s.find( i.nKey, []( value_type const& v, int key )
{
EXPECT_EQ( v.key(), key );
- EXPECT_EQ( v.nFindCount, 2 );
+ EXPECT_EQ( v.nUpdateNewCount, 2 );
}));
break;
case 5:
updResult = s.update( i.key(), []( bool bNew, value_type& v, int arg )
{
- EXPECT_TRUE( bNew );
+ EXPECT_FALSE( bNew );
EXPECT_EQ( v.key(), arg );
++v.nUpdateNewCount;
- } ), false );
+ }, false );
EXPECT_TRUE( updResult.first );
EXPECT_FALSE( updResult.second );
- ASSERT_TRUE( s.find( i, []( value_type const& V, value_type const& arg )
+ ASSERT_TRUE( s.find( i, []( value_type const& v, value_type const& arg )
{
EXPECT_EQ( v.key(), arg.key() );
- EXPECT_EQ( v.nFindCount, 2 );
+ EXPECT_EQ( v.nUpdateNewCount, 2 );
}));
break;
case 6:
ASSERT_TRUE( s.emplace( i.key()));
- ASSERT_TRUE( s.find( i, []( value_type const& V, value_type const& arg )
+ ASSERT_TRUE( s.find( i, []( value_type const& v, value_type const& arg )
{
EXPECT_EQ( v.key(), arg.key() );
EXPECT_EQ( v.nVal, arg.nVal );
str = "Hello!";
ASSERT_TRUE( s.emplace( i.key(), std::move( str )));
EXPECT_TRUE( str.empty());
- ASSERT_TRUE( s.find( i, []( value_type const& V, value_type const& arg )
+ ASSERT_TRUE( s.find( i, []( value_type const& v, value_type const& arg )
{
EXPECT_EQ( v.key(), arg.key() );
EXPECT_EQ( v.nVal, arg.nVal );
{
v.nFindCount = 1;
}));
- ASSERT_TRUE( s.find( i, []( value_type& v, int )
+ ASSERT_TRUE( s.find( i, []( value_type& v, value_type const& )
{
EXPECT_EQ( ++v.nFindCount, 2 );
}));
{
EXPECT_EQ( ++v.nFindCount, 3 );
}));
- EXPECT_EQ( i.nFindCount, 2 );
int nKey = i.key() - 1;
switch ( idx % 6 ) {
EXPECT_EQ( i.key(), nKey );
nKey = i.key() - 1;
- ASSERT_FALSE( s.erase( other_item( i.key()), other_less(), [&nKey]( value_type const& v )
+ ASSERT_FALSE( s.erase_with( other_item( i.key()), other_less(), [&nKey]( value_type const& v )
{
nKey = v.key();
} ));
EXPECT_EQ( it->nFindCount, it->key() * 3 );
}
- typedef typename Set::guqrded_ptr guarded_ptr;
+ typedef typename Set::guarded_ptr guarded_ptr;
guarded_ptr gp;
// get()