${CMAKE_CURRENT_SOURCE_DIR}
)
+add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/sequential)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/misc)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/freelist)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/map)
-#ifndef _COMMON_H
-#define _COMMON_H
+#ifndef _CDS_STRESS_TEST_COMMON_H
+#define _CDS_STRESS_TEST_COMMON_H
#include <cds_test/stress_test.h>
#define GetConfig(field) s_n##field = cfg.get_size_t(#field, s_n##field)
+
+#ifdef PERFORMANCE
+#define DEBUG(stmt)
+#else
+#define DEBUG(stmt) stmt
+#endif
+
#endif
--- /dev/null
+set(PACKAGE_NAME stress-sequential)
+
+add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/sequential-set)
+
+set(CDSSTRESS_STACK_SOURCES
+ ../main.cpp
+ sequential_queue.cpp
+ sequential_freelist_put_get_single.cpp
+ sequential_freelist_put_get.cpp
+ sequential_stack.cpp
+)
+
+include_directories(
+ ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+add_executable(${PACKAGE_NAME} ${CDSSTRESS_STACK_SOURCES})
+target_link_libraries(${PACKAGE_NAME} ${CDS_TEST_LIBRARIES} ${CDSSTRESS_FRAMEWORK_LIBRARY})
+
+add_test(NAME ${PACKAGE_NAME} COMMAND ${PACKAGE_NAME} WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
+
+add_custom_target( stress-sequential-all
+ DEPENDS
+ stress-sequential
+ stress-sequential-set
+)
--- /dev/null
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCDSUNIT_USE_URCU")
+
+add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/delodd)
+add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/del3)
+add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/insdel_find)
+add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/insdel_func)
+add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/insdel_string)
+add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/iteration)
+add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/iter_erase)
+
+add_custom_target( stress-sequential-set
+ DEPENDS
+ stress-sequential-set-delodd
+ stress-sequential-set-del3
+ stress-sequential-set-insdelfind
+ stress-sequential-set-insdel-func
+ stress-sequential-set-insdel-string
+ stress-sequential-set-iteration
+ stress-sequential-set-iter-erase
+)
--- /dev/null
+set(PACKAGE_NAME stress-sequential-set-del3)
+
+set(CDSSTRESS_SET_DEL3_SOURCES
+ ../../../main.cpp
+ set_del3.cpp
+ set_del3_feldman_hashset.cpp
+ set_del3_cuckoo.cpp
+ set_del3_michael.cpp
+ set_del3_skip.cpp
+ set_del3_split.cpp
+ set_del3_ellentree.cpp
+)
+
+include_directories(
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/..
+)
+
+add_executable(${PACKAGE_NAME} ${CDSSTRESS_SET_DEL3_SOURCES})
+target_link_libraries(${PACKAGE_NAME} ${CDS_TEST_LIBRARIES} ${CDSSTRESS_FRAMEWORK_LIBRARY})
+
+add_test(NAME ${PACKAGE_NAME} COMMAND ${PACKAGE_NAME} WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_del3.h"
+#include <string>
+
+namespace set {
+
+ size_t Set_Del3::s_nSetSize = 1000000;
+ size_t Set_Del3::s_nInsThreadCount = 4;
+ size_t Set_Del3::s_nDelThreadCount = 4;
+ size_t Set_Del3::s_nExtractThreadCount = 4;
+ size_t Set_Del3::s_nFindThreadCount = 2;
+ size_t Set_Del3::s_nMaxLoadFactor = 8;
+ size_t Set_Del3::s_nPassCount = 100;
+ size_t Set_Del3::s_nFeldmanPassCount = 100;
+ size_t Set_Del3::s_nInsertPassCount = 1;
+ size_t Set_Del3::s_nDeletePassCount = 1;
+ size_t Set_Del3::s_nFindPassCount = 10;
+
+ size_t Set_Del3::s_nCuckooInitialSize = 1024;
+ size_t Set_Del3::s_nCuckooProbesetSize = 16;
+ size_t Set_Del3::s_nCuckooProbesetThreshold = 0;
+
+ size_t Set_Del3::s_nFeldmanSet_HeadBits = 10;
+ size_t Set_Del3::s_nFeldmanSet_ArrayBits = 4;
+
+
+ size_t Set_Del3::s_nLoadFactor = 1;
+ std::vector<size_t> Set_Del3::m_arrData;
+
+ void Set_Del3::SetUpTestCase()
+ {
+ cds_test::config const& cfg = get_config( "sequential_map_delodd" );
+
+ s_nSetSize = cfg.get_size_t( "MapSize", s_nSetSize );
+ if ( s_nSetSize < 1000 )
+ s_nSetSize = 1000;
+
+ s_nInsThreadCount = cfg.get_size_t( "InsThreadCount", s_nInsThreadCount );
+ if ( s_nInsThreadCount == 0 )
+ s_nInsThreadCount = 1;
+
+ s_nDelThreadCount = cfg.get_size_t( "DelThreadCount", s_nDelThreadCount );
+ s_nExtractThreadCount = cfg.get_size_t( "ExtractThreadCount", s_nExtractThreadCount );
+ s_nFindThreadCount = cfg.get_size_t( "FindThreadCount", s_nFindThreadCount );
+
+ s_nMaxLoadFactor = cfg.get_size_t( "MaxLoadFactor", s_nMaxLoadFactor );
+ if ( s_nMaxLoadFactor == 0 )
+ s_nMaxLoadFactor = 1;
+
+ s_nPassCount = cfg.get_size_t("PassCount", s_nPassCount);
+ if (s_nPassCount == 0)
+ s_nPassCount = 100;
+
+ s_nFeldmanPassCount =
+ cfg.get_size_t("FeldmanPassCount", s_nFeldmanPassCount);
+ if (s_nFeldmanPassCount == 0)
+ s_nFeldmanPassCount = 500;
+
+ s_nInsertPassCount = cfg.get_size_t( "InsertPassCount", s_nInsertPassCount );
+ if ( s_nInsertPassCount == 0 )
+ s_nInsertPassCount = 1;
+
+ s_nDeletePassCount = cfg.get_size_t( "DeletePassCount", s_nDeletePassCount );
+ if ( s_nDeletePassCount == 0 )
+ s_nDeletePassCount = 1;
+
+ s_nFindPassCount = cfg.get_size_t( "FindPassCount", s_nFindPassCount );
+ if ( s_nFindPassCount == 0 )
+ s_nFindPassCount = 10;
+
+
+ s_nCuckooInitialSize = cfg.get_size_t( "CuckooInitialSize", s_nCuckooInitialSize );
+ if ( s_nCuckooInitialSize < 256 )
+ s_nCuckooInitialSize = 256;
+
+ s_nCuckooProbesetSize = cfg.get_size_t( "CuckooProbesetSize", s_nCuckooProbesetSize );
+ if ( s_nCuckooProbesetSize < 8 )
+ s_nCuckooProbesetSize = 8;
+
+ s_nCuckooProbesetThreshold = cfg.get_size_t( "CuckooProbesetThreshold", s_nCuckooProbesetThreshold );
+
+ s_nFeldmanSet_HeadBits = cfg.get_size_t( "FeldmanMapHeadBits", s_nFeldmanSet_HeadBits );
+ if ( s_nFeldmanSet_HeadBits == 0 )
+ s_nFeldmanSet_HeadBits = 2;
+
+ s_nFeldmanSet_ArrayBits = cfg.get_size_t( "FeldmanMapArrayBits", s_nFeldmanSet_ArrayBits );
+ if ( s_nFeldmanSet_ArrayBits == 0 )
+ s_nFeldmanSet_ArrayBits = 2;
+
+ m_arrData.resize( s_nSetSize );
+ for ( size_t i = 0; i < s_nSetSize; ++i )
+ m_arrData[i] = i;
+ shuffle( m_arrData.begin(), m_arrData.end());
+ }
+
+ void Set_Del3::TearDownTestCase()
+ {
+ m_arrData.clear();
+ }
+
+ std::vector<size_t> Set_Del3_LF::get_load_factors()
+ {
+ cds_test::config const& cfg = get_config( "map_delodd" );
+
+ s_nMaxLoadFactor = cfg.get_size_t( "MaxLoadFactor", s_nMaxLoadFactor );
+ if ( s_nMaxLoadFactor == 0 )
+ s_nMaxLoadFactor = 1;
+
+ std::vector<size_t> lf;
+ for ( size_t n = 1; n <= s_nMaxLoadFactor; n *= 2 )
+ lf.push_back( n );
+
+ return lf;
+ }
+
+#ifdef CDSTEST_GTEST_INSTANTIATE_TEST_CASE_P_HAS_4TH_ARG
+ static std::string get_test_parameter_name( testing::TestParamInfo<size_t> const& p )
+ {
+ return std::to_string( p.param );
+ }
+ INSTANTIATE_TEST_CASE_P( a, Set_Del3_LF, ::testing::ValuesIn( Set_Del3_LF::get_load_factors()), get_test_parameter_name );
+#else
+ INSTANTIATE_TEST_CASE_P( a, Set_Del3_LF, ::testing::ValuesIn( Set_Del3_LF::get_load_factors()));
+#endif
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "../../../misc/common.h"
+#include "set_type.h"
+#include <cds/os/topology.h>
+#include <chrono>
+
+namespace set {
+
+ struct key_thread
+ {
+ uint32_t nKey;
+ uint16_t nThread;
+
+ key_thread( size_t key, size_t threadNo )
+ : nKey( static_cast<uint32_t>(key))
+ , nThread( static_cast<uint16_t>(threadNo))
+ {}
+
+ key_thread()
+ : nKey()
+ , nThread()
+ {}
+ };
+
+ static_assert(sizeof( key_thread ) % 8 == 0, "Key type size mismatch");
+
+ typedef set_type_base<key_thread, size_t>::key_val key_value_pair;
+
+ template <>
+ struct cmp<key_thread> {
+ int operator ()(key_thread const& k1, key_thread const& k2) const
+ {
+ if ( k1.nKey < k2.nKey )
+ return -1;
+ if ( k1.nKey > k2.nKey )
+ return 1;
+ if ( k1.nThread < k2.nThread )
+ return -1;
+ if ( k1.nThread > k2.nThread )
+ return 1;
+ return 0;
+ }
+ int operator ()(key_thread const& k1, size_t k2) const
+ {
+ if ( k1.nKey < k2 )
+ return -1;
+ if ( k1.nKey > k2 )
+ return 1;
+ return 0;
+ }
+ int operator ()(size_t k1, key_thread const& k2) const
+ {
+ if ( k1 < k2.nKey )
+ return -1;
+ if ( k1 > k2.nKey )
+ return 1;
+ return 0;
+ }
+ };
+
+ template <>
+ struct less<set::key_thread>
+ {
+ bool operator()( set::key_thread const& k1, set::key_thread const& k2 ) const
+ {
+ if ( k1.nKey <= k2.nKey )
+ return k1.nKey < k2.nKey || k1.nThread < k2.nThread;
+ return false;
+ }
+ };
+
+ template <>
+ struct hash<set::key_thread>
+ {
+ typedef size_t result_type;
+ typedef set::key_thread argument_type;
+
+ size_t operator()( set::key_thread const& k ) const
+ {
+ return std::hash<size_t>()(k.nKey);
+ }
+
+ size_t operator()( size_t k ) const
+ {
+ return std::hash<size_t>()(k);
+ }
+ };
+
+
+ class Set_Del3: public cds_test::stress_fixture
+ {
+ public:
+ static size_t s_nSetSize; // max set size
+ static size_t s_nInsThreadCount; // insert thread count
+ static size_t s_nDelThreadCount; // delete thread count
+ static size_t s_nExtractThreadCount; // extract thread count
+ static size_t s_nMaxLoadFactor; // maximum load factor
+ static size_t s_nPassCount;
+ static size_t s_nFeldmanPassCount;
+
+ static size_t s_nInsertPassCount;
+ static size_t s_nDeletePassCount;
+ static size_t s_nFindPassCount;
+ static size_t s_nFindThreadCount; // find thread count
+
+ static size_t s_nCuckooInitialSize; // initial size for CuckooSet
+ static size_t s_nCuckooProbesetSize; // CuckooSet probeset size (only for list-based probeset)
+ static size_t s_nCuckooProbesetThreshold; // CUckooSet probeset threshold (0 - use default)
+
+ static size_t s_nFeldmanSet_HeadBits;
+ static size_t s_nFeldmanSet_ArrayBits;
+
+ static size_t s_nLoadFactor;
+
+ static std::vector<size_t> m_arrData;
+
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+
+ template <typename Pred>
+ static void prepare_array( std::vector<size_t>& arr, Pred pred )
+ {
+ arr.reserve( m_arrData.size());
+ for ( auto el : m_arrData ) {
+ if ( pred( el ))
+ arr.push_back( el );
+ }
+ arr.resize( arr.size());
+ shuffle( arr.begin(), arr.end());
+ }
+
+ protected:
+ typedef key_thread key_type;
+ typedef size_t value_type;
+
+ enum {
+ inserter_thread,
+ deleter_thread,
+ extractor_thread,
+ find_thread
+ };
+
+
+ // Inserts keys from [0..N)
+ template <class Set>
+ class Inserter: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Set& m_Set;
+
+ struct update_functor
+ {
+ template <typename Q>
+ void operator()( bool /*bNew*/, key_value_pair const&, Q const& ) const
+ {}
+
+ void operator()(key_value_pair& /*cur*/, key_value_pair * /*prev*/) const
+ {}
+ };
+
+ void init_data()
+ {
+ prepare_array( m_arr, []( size_t ) -> bool { return true; } );
+ }
+
+ public:
+ size_t m_nInsertSuccess = 0;
+ size_t m_nInsertFailed = 0;
+ size_t m_nInsertInitSuccess = 0;
+ size_t m_nInsertInitFailed = 0;
+
+ std::vector<size_t> m_arr;
+
+ public:
+ Inserter(cds_test::thread_pool &pool, Set &set)
+ : base_class(pool, inserter_thread), m_Set(set) {
+ init_data();
+ }
+
+ Inserter(Inserter &src) : base_class(src), m_Set(src.m_Set) {
+ init_data();
+ }
+
+ virtual thread * clone()
+ {
+ return new Inserter( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+ for (size_t nPass = 0; nPass < s_nInsertPassCount; ++nPass) {
+ if (nPass & 1) {
+ // insert pass
+ for (auto el : m_arrData) {
+ if (rSet.insert(key_type(el, 0)))
+ ++m_nInsertSuccess;
+ else
+ ++m_nInsertFailed;
+ }
+ } else {
+ // update pass
+ for (auto el : m_arrData) {
+ bool success;
+ bool inserted;
+ std::tie(success, inserted) =
+ rSet.update(key_type(el, 0), update_functor());
+ if (success && inserted)
+ ++m_nInsertSuccess;
+ else
+ ++m_nInsertFailed;
+ }
+ }
+ }
+ }
+ };
+
+ struct key_equal {
+ bool operator()( key_type const& k1, key_type const& k2 ) const
+ {
+ return k1.nKey == k2.nKey;
+ }
+ bool operator()( size_t k1, key_type const& k2 ) const
+ {
+ return k1 == k2.nKey;
+ }
+ bool operator()( key_type const& k1, size_t k2 ) const
+ {
+ return k1.nKey == k2;
+ }
+ bool operator ()( key_value_pair const& k1, key_value_pair const& k2 ) const
+ {
+ return operator()( k1.key, k2.key );
+ }
+ bool operator ()( key_value_pair const& k1, key_type const& k2 ) const
+ {
+ return operator()( k1.key, k2 );
+ }
+ bool operator ()( key_type const& k1, key_value_pair const& k2 ) const
+ {
+ return operator()( k1, k2.key );
+ }
+ bool operator ()( key_value_pair const& k1, size_t k2 ) const
+ {
+ return operator()( k1.key, k2 );
+ }
+ bool operator ()( size_t k1, key_value_pair const& k2 ) const
+ {
+ return operator()( k1, k2.key );
+ }
+ };
+
+ struct key_less {
+ bool operator()( key_type const& k1, key_type const& k2 ) const
+ {
+ return k1.nKey < k2.nKey;
+ }
+ bool operator()( size_t k1, key_type const& k2 ) const
+ {
+ return k1 < k2.nKey;
+ }
+ bool operator()( key_type const& k1, size_t k2 ) const
+ {
+ return k1.nKey < k2;
+ }
+ bool operator ()( key_value_pair const& k1, key_value_pair const& k2 ) const
+ {
+ return operator()( k1.key, k2.key );
+ }
+ bool operator ()( key_value_pair const& k1, key_type const& k2 ) const
+ {
+ return operator()( k1.key, k2 );
+ }
+ bool operator ()( key_type const& k1, key_value_pair const& k2 ) const
+ {
+ return operator()( k1, k2.key );
+ }
+ bool operator ()( key_value_pair const& k1, size_t k2 ) const
+ {
+ return operator()( k1.key, k2 );
+ }
+ bool operator ()( size_t k1, key_value_pair const& k2 ) const
+ {
+ return operator()( k1, k2.key );
+ }
+
+ typedef key_equal equal_to;
+ };
+
+ // Deletes odd keys from [0..N)
+ template <class Set>
+ class Deleter: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Set& m_Set;
+
+ void init_data()
+ {
+ prepare_array( m_arr, []( size_t el ) ->bool { return ( el & 3 ) != 0; } );
+ }
+
+ public:
+ size_t m_nDeleteSuccess = 0;
+ size_t m_nDeleteFailed = 0;
+
+ std::vector<size_t> m_arr;
+
+ public:
+ Deleter( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, deleter_thread )
+ , m_Set( set )
+ {}
+
+ Deleter( Deleter& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Deleter( *this );
+ }
+
+ template <typename SetType, bool>
+ struct eraser {
+ static bool erase( SetType& s, size_t key, size_t /*thread*/)
+ {
+ return s.erase_with( key, key_less());
+ }
+ };
+
+ template <typename SetType>
+ struct eraser<SetType, true> {
+ static bool erase(SetType& s, size_t key, size_t thread)
+ {
+ return s.erase( key_type(key, thread));
+ }
+ };
+
+ virtual void test() {
+ Set &rSet = m_Set;
+ for (auto el : m_arrData) {
+ if (el & 3) {
+ if (rSet.erase(key_type(el, 0)))
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ }
+ }
+ }
+ };
+
+ // Extracts odd keys from [0..N)
+ template <typename GC, class Set>
+ class Extractor: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Set& m_Set;
+
+ std::vector<size_t> m_arr;
+
+ void init_data()
+ {
+ prepare_array( m_arr, []( size_t el ) ->bool { return ( el & 3 ) != 0; } );
+ }
+
+ public:
+ size_t m_nExtractSuccess = 0;
+ size_t m_nExtractFailed = 0;
+
+ public:
+ Extractor( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, extractor_thread )
+ , m_Set( set )
+ {
+ }
+
+ Extractor( Extractor& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {
+ }
+
+ virtual thread * clone()
+ {
+ return new Extractor( *this );
+ }
+
+ virtual void test() {
+ Set &rSet = m_Set;
+ typename Set::guarded_ptr gp;
+
+ for (auto el : m_arrData) {
+ if (el & 3) {
+ gp = rSet.extract(key_type(el, 0));
+ if (gp)
+ ++m_nExtractSuccess;
+ else
+ ++m_nExtractFailed;
+ gp.release();
+ }
+ }
+ }
+ };
+
+ template <typename RCU, class Set>
+ class Extractor< cds::urcu::gc<RCU>, Set >: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Set& m_Set;
+ std::vector<size_t> m_arr;
+
+ void init_data()
+ {
+ prepare_array( m_arr, []( size_t el ) -> bool { return ( el & 3 ) != 0; } );
+ }
+
+ public:
+ size_t m_nExtractSuccess = 0;
+ size_t m_nExtractFailed = 0;
+
+ public:
+ Extractor( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, extractor_thread )
+ , m_Set( set )
+ {}
+
+ Extractor( Extractor& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Extractor( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+ typename Set::exempt_ptr xp;
+
+ Set_Del3& fixture = pool().template fixture<Set_Del3>();
+ size_t const nInsThreadCount = fixture.s_nInsThreadCount;
+
+ do {
+ if ( id() & 1 ) {
+ for ( size_t k = 0; k < nInsThreadCount; ++k ) {
+ for ( auto el : m_arr ) {
+ if ( Set::c_bExtractLockExternal ) {
+ typename Set::rcu_lock l;
+ xp = rSet.extract( key_type( el, k ));
+ if ( xp )
+ ++m_nExtractSuccess;
+ else
+ ++m_nExtractFailed;
+ }
+ else {
+ xp = rSet.extract( key_type( el, k ));
+ if ( xp )
+ ++m_nExtractSuccess;
+ else
+ ++m_nExtractFailed;
+ }
+ xp.release();
+ }
+ }
+ }
+ else {
+ for ( auto el : m_arr ) {
+ for ( size_t k = 0; k < nInsThreadCount; ++k ) {
+ if ( Set::c_bExtractLockExternal ) {
+ typename Set::rcu_lock l;
+ xp = rSet.extract( key_type( el, k ));
+ if ( xp )
+ ++m_nExtractSuccess;
+ else
+ ++m_nExtractFailed;
+ }
+ else {
+ xp = rSet.extract( key_type( el, k ));
+ if ( xp )
+ ++m_nExtractSuccess;
+ else
+ ++m_nExtractFailed;
+ }
+ xp.release();
+ }
+ }
+ }
+ } while ( false );
+
+ m_arr.resize( 0 );
+ }
+ };
+
+ // Finds keys
+ template <class Set>
+ class Observer: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Set& m_Set;
+
+ public:
+ size_t m_nFindEvenSuccess = 0;
+ size_t m_nFindEvenFailed = 0;
+ size_t m_nFindOddSuccess = 0;
+ size_t m_nFindOddFailed = 0;
+
+ public:
+ Observer( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, find_thread )
+ , m_Set( set )
+ {}
+
+ Observer( Observer& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Observer( *this );
+ }
+
+ virtual void test() {
+ Set &set = m_Set;
+ std::vector<size_t> const &arr = m_arrData;
+
+ for (size_t nPass = 0; nPass < s_nInsertPassCount; ++nPass) {
+ for (size_t key : arr) {
+ if (key & 3) {
+ if (set.contains(key_thread(key, 0)))
+ ++m_nFindOddSuccess;
+ else
+ ++m_nFindOddFailed;
+ } else {
+ // even keys MUST be in the map
+ if (set.contains(key_thread(key, 0)))
+ ++m_nFindEvenSuccess;
+ else
+ ++m_nFindEvenFailed;
+ }
+ }
+ }
+ }
+ };
+
+ protected:
+ template <class Set>
+ void do_test_with( Set& testSet )
+ {
+ typedef Inserter<Set> insert_thread;
+ typedef Deleter<Set> delete_thread;
+ typedef Observer<Set> observer_thread;
+
+ cds_test::thread_pool& pool = get_pool();
+ pool.add( new insert_thread( pool, testSet ), s_nInsThreadCount );
+ pool.add( new delete_thread( pool, testSet ), s_nDelThreadCount ? s_nDelThreadCount : cds::OS::topology::processor_count());
+ if ( s_nFindThreadCount )
+ pool.add( new observer_thread( pool, testSet ), s_nFindThreadCount );
+
+ propout() << std::make_pair( "insert_thread_count", s_nInsThreadCount )
+ << std::make_pair( "delete_thread_count", s_nDelThreadCount )
+ << std::make_pair( "find_thread_count", s_nFindThreadCount )
+ << std::make_pair( "set_size", s_nSetSize )
+ << std::make_pair( "pass_count", s_nInsertPassCount );
+
+
+
+ size_t nInsertInitFailed = 0;
+ size_t nInsertInitSuccess = 0;
+ size_t nInsertSuccess = 0;
+ size_t nInsertFailed = 0;
+ size_t nDeleteSuccess = 0;
+ size_t nDeleteFailed = 0;
+
+ size_t nFindEvenSuccess = 0;
+ size_t nFindEvenFailed = 0;
+ size_t nFindOddSuccess = 0;
+ size_t nFindOddFailed = 0;
+
+ for ( size_t i = 0; i < pool.size(); ++i ) {
+ cds_test::thread& thr = pool.get( i );
+ switch ( thr.type()) {
+ case inserter_thread:
+ {
+ insert_thread& inserter = static_cast<insert_thread&>(thr);
+ nInsertSuccess += inserter.m_nInsertSuccess;
+ nInsertFailed += inserter.m_nInsertFailed;
+ nInsertInitSuccess += inserter.m_nInsertInitSuccess;
+ nInsertInitFailed += inserter.m_nInsertInitFailed;
+ }
+ break;
+ case deleter_thread:
+ {
+ delete_thread& deleter = static_cast<delete_thread&>(thr);
+ nDeleteSuccess += deleter.m_nDeleteSuccess;
+ nDeleteFailed += deleter.m_nDeleteFailed;
+ }
+ break;
+ case find_thread:
+ {
+ observer_thread& observer = static_cast<observer_thread&>( thr );
+ nFindEvenSuccess = observer.m_nFindEvenSuccess;
+ nFindEvenFailed = observer.m_nFindEvenFailed;
+ nFindOddSuccess = observer.m_nFindOddSuccess;
+ nFindOddFailed = observer.m_nFindOddFailed;
+ }
+ break;
+ default:
+ assert( false );
+ }
+ }
+
+ size_t const nInitialOddKeys = ( s_nSetSize * s_nInsThreadCount ) * 3 / 4;
+
+ EXPECT_EQ( nInsertInitFailed, 0u );
+ EXPECT_EQ( nInsertInitSuccess, s_nSetSize * s_nInsThreadCount );
+ EXPECT_EQ( nFindEvenFailed, 0u );
+ EXPECT_GE( nInsertSuccess + nInitialOddKeys, nDeleteSuccess );
+ EXPECT_LE( nInsertSuccess, nDeleteSuccess );
+
+ propout()
+ << std::make_pair( "insert_init_success", nInsertInitSuccess )
+ << std::make_pair( "insert_init_failed", nInsertInitFailed )
+ << std::make_pair( "insert_success", nInsertSuccess )
+ << std::make_pair( "insert_failed", nInsertFailed )
+ << std::make_pair( "delete_success", nDeleteSuccess )
+ << std::make_pair( "delete_failed", nDeleteFailed )
+ << std::make_pair( "find_even_success", nFindEvenSuccess )
+ << std::make_pair( "find_even_failed", nFindEvenFailed )
+ << std::make_pair( "find_odd_success", nFindOddSuccess )
+ << std::make_pair( "find_odd_failed", nFindOddFailed );
+ }
+
+ template <class Set>
+ void do_test_extract_with(Set &testSet, size_t pass_count) {
+ typedef Inserter<Set> insert_thread;
+ typedef Deleter<Set> delete_thread;
+ typedef Extractor<typename Set::gc, Set> extract_thread;
+ typedef Observer<Set> observer_thread;
+
+ size_t nInsertSuccess = 0;
+ size_t nInsertFailed = 0;
+ size_t nDeleteSuccess = 0;
+ size_t nDeleteFailed = 0;
+ size_t nExtractSuccess = 0;
+ size_t nExtractFailed = 0;
+ size_t nFindEvenSuccess = 0;
+ size_t nFindEvenFailed = 0;
+ size_t nFindOddSuccess = 0;
+ size_t nFindOddFailed = 0;
+
+ auto reset_stat = [&]() {
+ nInsertSuccess = 0;
+ nInsertFailed = 0;
+ nDeleteSuccess = 0;
+ nDeleteFailed = 0;
+ nExtractSuccess = 0;
+ nExtractFailed = 0;
+ nFindEvenSuccess = 0;
+ nFindEvenFailed = 0;
+ nFindOddSuccess = 0;
+ nFindOddFailed = 0;
+ };
+
+ auto insert_func = [&]() {
+ for (auto el : m_arrData) {
+ if (testSet.insert(key_type(el, 0)))
+ ++nInsertSuccess;
+ else
+ ++nInsertFailed;
+ }
+ };
+
+ auto delete_func = [&]() {
+ for (auto el : m_arrData) {
+ if (el & 3) {
+ if (testSet.erase(key_type(el, 0)))
+ ++nDeleteSuccess;
+ else
+ ++nDeleteFailed;
+ }
+ }
+ };
+
+ auto extract_func = [&]() {
+ for (auto el : m_arrData) {
+ if (el & 3) {
+ auto gp = testSet.extract(key_type(el, 0));
+ if (gp)
+ ++nExtractSuccess;
+ else
+ ++nExtractFailed;
+ gp.release();
+ }
+ }
+ };
+
+ auto find_func = [&]() {
+ for (size_t el : m_arrData) {
+ if (el & 3) {
+ if (testSet.contains(key_thread(el, 0)))
+ ++nFindOddSuccess;
+ else
+ ++nFindOddFailed;
+ } else {
+ // even keys MUST be in the map
+ if (testSet.contains(key_thread(el, 0)))
+ ++nFindEvenSuccess;
+ else
+ ++nFindEvenFailed;
+ }
+ }
+ };
+
+ auto test_func = [&](size_t count, std::function<void()> func) {
+ for (size_t i = 0; i < count; ++i) {
+ func();
+ }
+ };
+
+ size_t const nInitialOddKeys = s_nSetSize * 3 / 4;
+ size_t const nInitialEvenKeys = s_nSetSize / 4;
+ for (size_t nPass = 0; nPass < pass_count; ++nPass) {
+ // Start with an empty set.
+ testSet.clear();
+ reset_stat();
+
+ test_func(s_nInsertPassCount, insert_func);
+ EXPECT_EQ(nInsertSuccess, s_nSetSize);
+ reset_stat();
+
+ test_func(s_nFindPassCount, find_func);
+ EXPECT_EQ(nFindEvenFailed, 0u);
+ EXPECT_EQ(nFindOddFailed, 0u);
+ reset_stat();
+
+ test_func(s_nDeletePassCount, delete_func);
+ EXPECT_EQ(nDeleteSuccess, nInitialOddKeys);
+ reset_stat();
+
+ test_func(s_nInsertPassCount, insert_func);
+ EXPECT_EQ(nInsertSuccess, nInitialOddKeys);
+ reset_stat();
+
+ test_func(s_nDeletePassCount, extract_func);
+ EXPECT_EQ(nExtractSuccess, nInitialOddKeys);
+ reset_stat();
+
+ test_func(s_nFindPassCount, find_func);
+ EXPECT_EQ(nFindEvenFailed, 0u);
+ EXPECT_EQ(nFindOddSuccess, 0u);
+ }
+
+ // std::chrono::duration<double> time_elapsed;
+ // std::chrono::duration<double> time_diff;
+ // std::chrono::time_point<std::chrono::steady_clock>
+ // time_start;
+ // std::chrono::time_point<std::chrono::steady_clock>
+ // time_end;
+ // time_start = std::chrono::steady_clock::now();
+ // time_end = std::chrono::steady_clock::now();
+ // time_diff = time_end - time_start;
+ // time_elapsed = time_diff;
+ // std::cout << "Time elapsed: " << time_elapsed.count() <<
+ // "\n";
+ }
+
+ template <typename Set>
+ void analyze( Set& testSet )
+ {
+ // All even keys must be in the set
+ {
+ for ( size_t n = 0; n < s_nSetSize; n +=4 ) {
+ for ( size_t i = 0; i < s_nInsThreadCount; ++i ) {
+ EXPECT_TRUE( testSet.contains( key_type( n, i ))) << "key=" << n << "/" << i;
+ }
+ }
+ }
+
+ check_before_clear( testSet );
+
+ testSet.clear();
+ EXPECT_TRUE( testSet.empty()) << "set.size=" << testSet.size();
+
+ additional_check( testSet );
+ print_stat( propout(), testSet );
+ additional_cleanup( testSet );
+ }
+
+ template <class Set>
+ void run_test()
+ {
+ static_assert( !Set::c_bExtractSupported, "Set class must not support extract() method" );
+
+ Set testSet( *this );
+ do_test_with( testSet );
+ analyze( testSet );
+ }
+
+ template <class Set>
+ void run_test_extract(size_t pass_count = s_nPassCount)
+ {
+ static_assert( Set::c_bExtractSupported, "Set class must support extract() method" );
+
+ Set testSet( *this );
+ do_test_extract_with( testSet, pass_count);
+ }
+
+ template <class Map>
+ void run_feldman();
+ };
+
+ class Set_Del3_LF: public Set_Del3
+ , public ::testing::WithParamInterface<size_t>
+ {
+ public:
+ template <class Set>
+ void run_test()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Set_Del3::run_test<Set>();
+ }
+
+ template <class Set>
+ void run_test_extract(size_t pass_count = s_nPassCount)
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Set_Del3::run_test_extract<Set>(pass_count);
+ }
+
+ static std::vector<size_t> get_load_factors();
+ };
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_del3.h"
+#include "set_type_cuckoo.h"
+
+namespace set {
+
+ //CDSSTRESS_CuckooSet( Set_Del3, run_test, key_thread, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_del3.h"
+#include "set_type_ellen_bintree.h"
+
+namespace set {
+
+ CDSSTRESS_EllenBinTreeSet( Set_Del3, run_test_extract, key_thread, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_del3.h"
+#include "set_type_feldman_hashset.h"
+
+namespace set {
+
+ template <class Set>
+ void Set_Del3::run_feldman()
+ {
+ typedef typename Set::traits original_traits;
+ struct traits: public original_traits {
+ enum { hash_size = sizeof( uint32_t ) + sizeof( uint16_t ) };
+ };
+ typedef typename Set::template rebind_traits< traits >::result set_type;
+
+ run_test_extract<set_type>(s_nFeldmanPassCount);
+ }
+
+ CDSSTRESS_FeldmanHashSet_fixed( Set_Del3, run_feldman, key_thread, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_del3.h"
+#include "set_type_michael.h"
+
+namespace set {
+
+ CDSSTRESS_MichaelSet( Set_Del3_LF, run_test_extract, key_thread, size_t )
+ CDSSTRESS_MichaelIterableSet( Set_Del3_LF, run_test_extract, key_thread, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_del3.h"
+#include "set_type_skip_list.h"
+
+namespace set {
+
+ CDSSTRESS_SkipListSet( Set_Del3, run_test_extract, key_thread, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_del3.h"
+#include "set_type_split_list.h"
+
+namespace set {
+
+ CDSSTRESS_SplitListSet( Set_Del3_LF, run_test_extract, key_thread, size_t )
+ CDSSTRESS_SplitListIterableSet( Set_Del3_LF, run_test_extract, key_thread, size_t )
+
+
+} // namespace set
--- /dev/null
+set(PACKAGE_NAME stress-sequential-set-delodd)
+
+set(CDSSTRESS_SET_DELODD_SOURCES
+ ../../../main.cpp
+ set_delodd.cpp
+ set_delodd_cuckoo.cpp
+ set_delodd_ellentree.cpp
+ set_delodd_feldman_hashset.cpp
+ set_delodd_michael.cpp
+ set_delodd_skip.cpp
+ set_delodd_split.cpp
+)
+
+include_directories(
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/..
+)
+
+add_executable(${PACKAGE_NAME} ${CDSSTRESS_SET_DELODD_SOURCES})
+target_link_libraries(${PACKAGE_NAME} ${CDS_TEST_LIBRARIES} ${CDSSTRESS_FRAMEWORK_LIBRARY})
+
+add_test(NAME ${PACKAGE_NAME} COMMAND ${PACKAGE_NAME} WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_delodd.h"
+
+namespace set {
+
+ size_t Set_DelOdd::s_nSetSize = 1000000;
+ size_t Set_DelOdd::s_nInsThreadCount = 4;
+ size_t Set_DelOdd::s_nDelThreadCount = 4;
+ size_t Set_DelOdd::s_nExtractThreadCount = 4;
+ size_t Set_DelOdd::s_nFindThreadCount = 2;
+ size_t Set_DelOdd::s_nMaxLoadFactor = 8;
+ size_t Set_DelOdd::s_nInsertPassCount = 100;
+
+ size_t Set_DelOdd::s_nCuckooInitialSize = 1024;
+ size_t Set_DelOdd::s_nCuckooProbesetSize = 16;
+ size_t Set_DelOdd::s_nCuckooProbesetThreshold = 0;
+
+ size_t Set_DelOdd::s_nFeldmanSet_HeadBits = 10;
+ size_t Set_DelOdd::s_nFeldmanSet_ArrayBits = 4;
+
+
+ size_t Set_DelOdd::s_nLoadFactor = 1;
+ std::vector<size_t> Set_DelOdd::m_arrData;
+
+ void Set_DelOdd::SetUpTestCase()
+ {
+ cds_test::config const& cfg = get_config( "map_delodd" );
+
+ s_nSetSize = cfg.get_size_t( "MapSize", s_nSetSize );
+ if ( s_nSetSize < 1000 )
+ s_nSetSize = 1000;
+
+ s_nInsThreadCount = cfg.get_size_t( "InsThreadCount", s_nInsThreadCount );
+ if ( s_nInsThreadCount == 0 )
+ s_nInsThreadCount = 1;
+
+ s_nDelThreadCount = cfg.get_size_t( "DelThreadCount", s_nDelThreadCount );
+ s_nExtractThreadCount = cfg.get_size_t( "ExtractThreadCount", s_nExtractThreadCount );
+ s_nFindThreadCount = cfg.get_size_t( "FindThreadCount", s_nFindThreadCount );
+
+ s_nMaxLoadFactor = cfg.get_size_t( "MaxLoadFactor", s_nMaxLoadFactor );
+ if ( s_nMaxLoadFactor == 0 )
+ s_nMaxLoadFactor = 1;
+
+ s_nInsertPassCount = cfg.get_size_t( "PassCount", s_nInsertPassCount );
+ if ( s_nInsertPassCount == 0 )
+ s_nInsertPassCount = 100;
+
+ s_nCuckooInitialSize = cfg.get_size_t( "CuckooInitialSize", s_nCuckooInitialSize );
+ if ( s_nCuckooInitialSize < 256 )
+ s_nCuckooInitialSize = 256;
+
+ s_nCuckooProbesetSize = cfg.get_size_t( "CuckooProbesetSize", s_nCuckooProbesetSize );
+ if ( s_nCuckooProbesetSize < 8 )
+ s_nCuckooProbesetSize = 8;
+
+ s_nCuckooProbesetThreshold = cfg.get_size_t( "CuckooProbesetThreshold", s_nCuckooProbesetThreshold );
+
+ s_nFeldmanSet_HeadBits = cfg.get_size_t( "FeldmanMapHeadBits", s_nFeldmanSet_HeadBits );
+ if ( s_nFeldmanSet_HeadBits == 0 )
+ s_nFeldmanSet_HeadBits = 2;
+
+ s_nFeldmanSet_ArrayBits = cfg.get_size_t( "FeldmanMapArrayBits", s_nFeldmanSet_ArrayBits );
+ if ( s_nFeldmanSet_ArrayBits == 0 )
+ s_nFeldmanSet_ArrayBits = 2;
+
+ m_arrData.resize( s_nSetSize );
+ for ( size_t i = 0; i < s_nSetSize; ++i )
+ m_arrData[i] = i;
+ shuffle( m_arrData.begin(), m_arrData.end());
+ }
+
+ void Set_DelOdd::TearDownTestCase()
+ {
+ m_arrData.clear();
+ }
+
+ std::vector<size_t> Set_DelOdd_LF::get_load_factors()
+ {
+ cds_test::config const& cfg = get_config( "map_delodd" );
+
+ s_nMaxLoadFactor = cfg.get_size_t( "MaxLoadFactor", s_nMaxLoadFactor );
+ if ( s_nMaxLoadFactor == 0 )
+ s_nMaxLoadFactor = 1;
+
+ std::vector<size_t> lf;
+ for ( size_t n = 1; n <= s_nMaxLoadFactor; n *= 2 )
+ lf.push_back( n );
+
+ return lf;
+ }
+
+#ifdef CDSTEST_GTEST_INSTANTIATE_TEST_CASE_P_HAS_4TH_ARG
+ static std::string get_test_parameter_name( testing::TestParamInfo<size_t> const& p )
+ {
+ return std::to_string( p.param );
+ }
+ INSTANTIATE_TEST_CASE_P( a, Set_DelOdd_LF, ::testing::ValuesIn( Set_DelOdd_LF::get_load_factors()), get_test_parameter_name );
+#else
+ INSTANTIATE_TEST_CASE_P( a, Set_DelOdd_LF, ::testing::ValuesIn( Set_DelOdd_LF::get_load_factors()));
+#endif
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_type.h"
+#include <cds/os/topology.h>
+
+namespace set {
+
+ struct key_thread
+ {
+ uint32_t nKey;
+ uint16_t nThread;
+
+ key_thread( size_t key, size_t threadNo )
+ : nKey( static_cast<uint32_t>(key))
+ , nThread( static_cast<uint16_t>(threadNo))
+ {}
+
+ key_thread()
+ : nKey()
+ , nThread()
+ {}
+ };
+
+ static_assert(sizeof( key_thread ) % 8 == 0, "Key type size mismatch");
+
+ typedef set_type_base<key_thread, size_t>::key_val key_value_pair;
+
+ template <>
+ struct cmp<key_thread> {
+ int operator ()(key_thread const& k1, key_thread const& k2) const
+ {
+ if ( k1.nKey < k2.nKey )
+ return -1;
+ if ( k1.nKey > k2.nKey )
+ return 1;
+ if ( k1.nThread < k2.nThread )
+ return -1;
+ if ( k1.nThread > k2.nThread )
+ return 1;
+ return 0;
+ }
+ int operator ()(key_thread const& k1, size_t k2) const
+ {
+ if ( k1.nKey < k2 )
+ return -1;
+ if ( k1.nKey > k2 )
+ return 1;
+ return 0;
+ }
+ int operator ()(size_t k1, key_thread const& k2) const
+ {
+ if ( k1 < k2.nKey )
+ return -1;
+ if ( k1 > k2.nKey )
+ return 1;
+ return 0;
+ }
+ };
+
+ template <>
+ struct less<set::key_thread>
+ {
+ bool operator()( set::key_thread const& k1, set::key_thread const& k2 ) const
+ {
+ if ( k1.nKey <= k2.nKey )
+ return k1.nKey < k2.nKey || k1.nThread < k2.nThread;
+ return false;
+ }
+ };
+
+ template <>
+ struct hash<set::key_thread>
+ {
+ typedef size_t result_type;
+ typedef set::key_thread argument_type;
+
+ size_t operator()( set::key_thread const& k ) const
+ {
+ return std::hash<size_t>()(k.nKey);
+ }
+
+ size_t operator()( size_t k ) const
+ {
+ return std::hash<size_t>()(k);
+ }
+ };
+
+
+ class Set_DelOdd: public cds_test::stress_fixture
+ {
+ public:
+ static size_t s_nSetSize; // max set size
+ static size_t s_nInsThreadCount; // insert thread count
+ static size_t s_nDelThreadCount; // delete thread count
+ static size_t s_nExtractThreadCount; // extract thread count
+ static size_t s_nMaxLoadFactor; // maximum load factor
+ static size_t s_nInsertPassCount;
+ static size_t s_nFindThreadCount; // find thread count
+
+ static size_t s_nCuckooInitialSize; // initial size for CuckooSet
+ static size_t s_nCuckooProbesetSize; // CuckooSet probeset size (only for list-based probeset)
+ static size_t s_nCuckooProbesetThreshold; // CUckooSet probeset threshold (0 - use default)
+
+ static size_t s_nFeldmanSet_HeadBits;
+ static size_t s_nFeldmanSet_ArrayBits;
+
+ static size_t s_nLoadFactor;
+
+ static std::vector<size_t> m_arrData;
+
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+
+ template <typename Pred>
+ static void prepare_array( std::vector<size_t>& arr, Pred pred )
+ {
+ arr.reserve( m_arrData.size());
+ for ( auto el : m_arrData ) {
+ if ( pred( el ))
+ arr.push_back( el );
+ }
+ arr.resize( arr.size());
+ shuffle( arr.begin(), arr.end());
+ }
+
+ protected:
+ typedef key_thread key_type;
+ typedef size_t value_type;
+
+ atomics::atomic<size_t> m_nInsThreadCount;
+
+ enum {
+ inserter_thread,
+ deleter_thread,
+ extractor_thread,
+ find_thread
+ };
+
+
+ // Inserts keys from [0..N)
+ template <class Set>
+ class Inserter: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Set& m_Set;
+
+ struct update_functor
+ {
+ template <typename Q>
+ void operator()( bool /*bNew*/, key_value_pair const&, Q const& ) const
+ {}
+
+ void operator()(key_value_pair& /*cur*/, key_value_pair * /*prev*/) const
+ {}
+ };
+
+ void init_data()
+ {
+ prepare_array( m_arr, []( size_t ) -> bool { return true; } );
+ for ( size_t i = 0; i < m_arr.size(); ++i ) {
+ if ( m_Set.insert( key_type( m_arr[i], id())))
+ ++m_nInsertInitSuccess;
+ else
+ ++m_nInsertInitFailed;
+ }
+ }
+
+ public:
+ size_t m_nInsertSuccess = 0;
+ size_t m_nInsertFailed = 0;
+ size_t m_nInsertInitSuccess = 0;
+ size_t m_nInsertInitFailed = 0;
+
+ std::vector<size_t> m_arr;
+
+ public:
+ Inserter( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, inserter_thread )
+ , m_Set( set )
+ {
+ init_data();
+ }
+
+ Inserter( Inserter& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {
+ init_data();
+ }
+
+ virtual thread * clone()
+ {
+ return new Inserter( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+ Set_DelOdd& fixture = pool().template fixture<Set_DelOdd>();
+
+ for ( size_t nPass = 0; nPass < s_nInsertPassCount; ++nPass ) {
+ if ( nPass & 1 ) {
+ // insert pass
+ for ( auto el : m_arr ) {
+ if ( el & 1 ) {
+ if ( rSet.insert( key_type( el, id())))
+ ++m_nInsertSuccess;
+ else
+ ++m_nInsertFailed;
+ }
+ }
+ }
+ else {
+ // update pass
+ for ( auto el : m_arr ) {
+ if ( el & 1 ) {
+ bool success;
+ bool inserted;
+ std::tie( success, inserted ) = rSet.update( key_type( el, id()), update_functor());
+ if ( success && inserted )
+ ++m_nInsertSuccess;
+ else
+ ++m_nInsertFailed;
+ }
+ }
+ }
+ }
+
+ fixture.m_nInsThreadCount.fetch_sub( 1, atomics::memory_order_release );
+ m_arr.resize( 0 );
+ }
+ };
+
+ struct key_equal {
+ bool operator()( key_type const& k1, key_type const& k2 ) const
+ {
+ return k1.nKey == k2.nKey;
+ }
+ bool operator()( size_t k1, key_type const& k2 ) const
+ {
+ return k1 == k2.nKey;
+ }
+ bool operator()( key_type const& k1, size_t k2 ) const
+ {
+ return k1.nKey == k2;
+ }
+ bool operator ()( key_value_pair const& k1, key_value_pair const& k2 ) const
+ {
+ return operator()( k1.key, k2.key );
+ }
+ bool operator ()( key_value_pair const& k1, key_type const& k2 ) const
+ {
+ return operator()( k1.key, k2 );
+ }
+ bool operator ()( key_type const& k1, key_value_pair const& k2 ) const
+ {
+ return operator()( k1, k2.key );
+ }
+ bool operator ()( key_value_pair const& k1, size_t k2 ) const
+ {
+ return operator()( k1.key, k2 );
+ }
+ bool operator ()( size_t k1, key_value_pair const& k2 ) const
+ {
+ return operator()( k1, k2.key );
+ }
+ };
+
+ struct key_less {
+ bool operator()( key_type const& k1, key_type const& k2 ) const
+ {
+ return k1.nKey < k2.nKey;
+ }
+ bool operator()( size_t k1, key_type const& k2 ) const
+ {
+ return k1 < k2.nKey;
+ }
+ bool operator()( key_type const& k1, size_t k2 ) const
+ {
+ return k1.nKey < k2;
+ }
+ bool operator ()( key_value_pair const& k1, key_value_pair const& k2 ) const
+ {
+ return operator()( k1.key, k2.key );
+ }
+ bool operator ()( key_value_pair const& k1, key_type const& k2 ) const
+ {
+ return operator()( k1.key, k2 );
+ }
+ bool operator ()( key_type const& k1, key_value_pair const& k2 ) const
+ {
+ return operator()( k1, k2.key );
+ }
+ bool operator ()( key_value_pair const& k1, size_t k2 ) const
+ {
+ return operator()( k1.key, k2 );
+ }
+ bool operator ()( size_t k1, key_value_pair const& k2 ) const
+ {
+ return operator()( k1, k2.key );
+ }
+
+ typedef key_equal equal_to;
+ };
+
+ // Deletes odd keys from [0..N)
+ template <class Set>
+ class Deleter: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Set& m_Set;
+
+ void init_data()
+ {
+ prepare_array( m_arr, []( size_t el ) ->bool { return ( el & 1 ) != 0; } );
+ }
+
+ public:
+ size_t m_nDeleteSuccess = 0;
+ size_t m_nDeleteFailed = 0;
+
+ std::vector<size_t> m_arr;
+
+ public:
+ Deleter( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, deleter_thread )
+ , m_Set( set )
+ {
+ init_data();
+ }
+ Deleter( Deleter& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {
+ init_data();
+ }
+
+ virtual thread * clone()
+ {
+ return new Deleter( *this );
+ }
+
+ template <typename SetType, bool>
+ struct eraser {
+ static bool erase( SetType& s, size_t key, size_t /*thread*/)
+ {
+ return s.erase_with( key, key_less());
+ }
+ };
+
+ template <typename SetType>
+ struct eraser<SetType, true> {
+ static bool erase(SetType& s, size_t key, size_t thread)
+ {
+ return s.erase( key_type(key, thread));
+ }
+ };
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+
+ size_t const nInsThreadCount = s_nInsThreadCount;
+ Set_DelOdd& fixture = pool().template fixture<Set_DelOdd>();
+
+ do {
+ if ( id() & 1 ) {
+ for ( auto el : m_arr ) {
+ for ( size_t k = 0; k < nInsThreadCount; ++k ) {
+ if ( rSet.erase( key_type( el, k )))
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ }
+ }
+ }
+ else {
+ for ( size_t k = 0; k < nInsThreadCount; ++k ) {
+ for ( auto el : m_arr ) {
+ if ( rSet.erase( key_type( el, k )))
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ }
+ }
+ }
+ } while ( fixture.m_nInsThreadCount.load( atomics::memory_order_acquire ) != 0 );
+
+ m_arr.resize( 0 );
+ }
+ };
+
+ // Extracts odd keys from [0..N)
+ template <typename GC, class Set>
+ class Extractor: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Set& m_Set;
+
+ std::vector<size_t> m_arr;
+
+ void init_data()
+ {
+ prepare_array( m_arr, []( size_t el ) ->bool { return ( el & 1 ) != 0; } );
+ }
+
+ public:
+ size_t m_nExtractSuccess = 0;
+ size_t m_nExtractFailed = 0;
+
+ public:
+ Extractor( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, extractor_thread )
+ , m_Set( set )
+ {
+ init_data();
+ }
+
+ Extractor( Extractor& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {
+ init_data();
+ }
+
+ virtual thread * clone()
+ {
+ return new Extractor( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+ typename Set::guarded_ptr gp;
+
+ Set_DelOdd& fixture = pool().template fixture<Set_DelOdd>();
+ size_t const nInsThreadCount = s_nInsThreadCount;
+
+ do {
+ if ( id() & 1 ) {
+ for ( auto el : m_arr ) {
+ for ( size_t k = 0; k < nInsThreadCount; ++k ) {
+ gp = rSet.extract( key_type( el, k ));
+ if ( gp )
+ ++m_nExtractSuccess;
+ else
+ ++m_nExtractFailed;
+ gp.release();
+ }
+ }
+ }
+ else {
+ for ( size_t k = 0; k < nInsThreadCount; ++k ) {
+ for ( auto el : m_arr ) {
+ gp = rSet.extract( key_type( el, k ));
+ if ( gp )
+ ++m_nExtractSuccess;
+ else
+ ++m_nExtractFailed;
+ gp.release();
+ }
+ }
+ }
+ } while ( fixture.m_nInsThreadCount.load( atomics::memory_order_acquire ) != 0 );
+
+ m_arr.resize( 0 );
+ }
+ };
+
+ template <typename RCU, class Set>
+ class Extractor< cds::urcu::gc<RCU>, Set >: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Set& m_Set;
+ std::vector<size_t> m_arr;
+
+ void init_data()
+ {
+ prepare_array( m_arr, []( size_t el ) -> bool { return ( el & 1 ) != 0; } );
+ }
+
+ public:
+ size_t m_nExtractSuccess = 0;
+ size_t m_nExtractFailed = 0;
+
+ public:
+ Extractor( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, extractor_thread )
+ , m_Set( set )
+ {
+ init_data();
+ }
+
+ Extractor( Extractor& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {
+ init_data();
+ }
+
+ virtual thread * clone()
+ {
+ return new Extractor( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+ typename Set::exempt_ptr xp;
+
+ Set_DelOdd& fixture = pool().template fixture<Set_DelOdd>();
+ size_t const nInsThreadCount = fixture.s_nInsThreadCount;
+
+ do {
+ if ( id() & 1 ) {
+ for ( size_t k = 0; k < nInsThreadCount; ++k ) {
+ for ( auto el : m_arr ) {
+ if ( Set::c_bExtractLockExternal ) {
+ typename Set::rcu_lock l;
+ xp = rSet.extract( key_type( el, k ));
+ if ( xp )
+ ++m_nExtractSuccess;
+ else
+ ++m_nExtractFailed;
+ }
+ else {
+ xp = rSet.extract( key_type( el, k ));
+ if ( xp )
+ ++m_nExtractSuccess;
+ else
+ ++m_nExtractFailed;
+ }
+ xp.release();
+ }
+ }
+ }
+ else {
+ for ( auto el : m_arr ) {
+ for ( size_t k = 0; k < nInsThreadCount; ++k ) {
+ if ( Set::c_bExtractLockExternal ) {
+ typename Set::rcu_lock l;
+ xp = rSet.extract( key_type( el, k ));
+ if ( xp )
+ ++m_nExtractSuccess;
+ else
+ ++m_nExtractFailed;
+ }
+ else {
+ xp = rSet.extract( key_type( el, k ));
+ if ( xp )
+ ++m_nExtractSuccess;
+ else
+ ++m_nExtractFailed;
+ }
+ xp.release();
+ }
+ }
+ }
+ } while ( fixture.m_nInsThreadCount.load( atomics::memory_order_acquire ) != 0 );
+
+ m_arr.resize( 0 );
+ }
+ };
+
+ // Finds keys
+ template <class Set>
+ class Observer: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Set& m_Set;
+
+ public:
+ size_t m_nFindEvenSuccess = 0;
+ size_t m_nFindEvenFailed = 0;
+ size_t m_nFindOddSuccess = 0;
+ size_t m_nFindOddFailed = 0;
+
+ public:
+ Observer( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, find_thread )
+ , m_Set( set )
+ {}
+
+ Observer( Observer& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Observer( *this );
+ }
+
+ virtual void test()
+ {
+ Set& set = m_Set;
+ Set_DelOdd& fixture = pool().template fixture<Set_DelOdd>();
+ std::vector<size_t> const& arr = m_arrData;
+ size_t const nInsThreadCount = s_nInsThreadCount;
+
+ do {
+ for ( size_t key : arr ) {
+ if ( key & 1 ) {
+ for ( size_t k = 0; k < nInsThreadCount; ++k ) {
+ if ( set.contains( key_thread( key, k )))
+ ++m_nFindOddSuccess;
+ else
+ ++m_nFindOddFailed;
+ }
+ }
+ else {
+ // even keys MUST be in the map
+ for ( size_t k = 0; k < nInsThreadCount; ++k ) {
+ if ( set.contains( key_thread( key, k )))
+ ++m_nFindEvenSuccess;
+ else
+ ++m_nFindEvenFailed;
+ }
+ }
+ }
+ } while ( fixture.m_nInsThreadCount.load( atomics::memory_order_acquire ) != 0 );
+ }
+ };
+
+ protected:
+ template <class Set>
+ void do_test_with( Set& testSet )
+ {
+ typedef Inserter<Set> insert_thread;
+ typedef Deleter<Set> delete_thread;
+ typedef Observer<Set> observer_thread;
+
+ m_nInsThreadCount.store( s_nInsThreadCount, atomics::memory_order_release );
+
+ cds_test::thread_pool& pool = get_pool();
+ pool.add( new insert_thread( pool, testSet ), s_nInsThreadCount );
+ pool.add( new delete_thread( pool, testSet ), s_nDelThreadCount ? s_nDelThreadCount : cds::OS::topology::processor_count());
+ if ( s_nFindThreadCount )
+ pool.add( new observer_thread( pool, testSet ), s_nFindThreadCount );
+
+ propout() << std::make_pair( "insert_thread_count", s_nInsThreadCount )
+ << std::make_pair( "delete_thread_count", s_nDelThreadCount )
+ << std::make_pair( "find_thread_count", s_nFindThreadCount )
+ << std::make_pair( "set_size", s_nSetSize )
+ << std::make_pair( "pass_count", s_nInsertPassCount );
+
+ std::chrono::milliseconds duration = pool.run();
+
+ propout() << std::make_pair( "duration", duration );
+
+ size_t nInsertInitFailed = 0;
+ size_t nInsertInitSuccess = 0;
+ size_t nInsertSuccess = 0;
+ size_t nInsertFailed = 0;
+ size_t nDeleteSuccess = 0;
+ size_t nDeleteFailed = 0;
+
+ size_t nFindEvenSuccess = 0;
+ size_t nFindEvenFailed = 0;
+ size_t nFindOddSuccess = 0;
+ size_t nFindOddFailed = 0;
+
+ for ( size_t i = 0; i < pool.size(); ++i ) {
+ cds_test::thread& thr = pool.get( i );
+ switch ( thr.type()) {
+ case inserter_thread:
+ {
+ insert_thread& inserter = static_cast<insert_thread&>(thr);
+ nInsertSuccess += inserter.m_nInsertSuccess;
+ nInsertFailed += inserter.m_nInsertFailed;
+ nInsertInitSuccess += inserter.m_nInsertInitSuccess;
+ nInsertInitFailed += inserter.m_nInsertInitFailed;
+ }
+ break;
+ case deleter_thread:
+ {
+ delete_thread& deleter = static_cast<delete_thread&>(thr);
+ nDeleteSuccess += deleter.m_nDeleteSuccess;
+ nDeleteFailed += deleter.m_nDeleteFailed;
+ }
+ break;
+ case find_thread:
+ {
+ observer_thread& observer = static_cast<observer_thread&>( thr );
+ nFindEvenSuccess = observer.m_nFindEvenSuccess;
+ nFindEvenFailed = observer.m_nFindEvenFailed;
+ nFindOddSuccess = observer.m_nFindOddSuccess;
+ nFindOddFailed = observer.m_nFindOddFailed;
+ }
+ break;
+ default:
+ assert( false );
+ }
+ }
+
+ size_t const nInitialOddKeys = ( s_nSetSize * s_nInsThreadCount ) / 2;
+
+ EXPECT_EQ( nInsertInitFailed, 0u );
+ EXPECT_EQ( nInsertInitSuccess, s_nSetSize * s_nInsThreadCount );
+ EXPECT_EQ( nFindEvenFailed, 0u );
+ EXPECT_GE( nInsertSuccess + nInitialOddKeys, nDeleteSuccess );
+ EXPECT_LE( nInsertSuccess, nDeleteSuccess );
+
+ propout()
+ << std::make_pair( "insert_init_success", nInsertInitSuccess )
+ << std::make_pair( "insert_init_failed", nInsertInitFailed )
+ << std::make_pair( "insert_success", nInsertSuccess )
+ << std::make_pair( "insert_failed", nInsertFailed )
+ << std::make_pair( "delete_success", nDeleteSuccess )
+ << std::make_pair( "delete_failed", nDeleteFailed )
+ << std::make_pair( "find_even_success", nFindEvenSuccess )
+ << std::make_pair( "find_even_failed", nFindEvenFailed )
+ << std::make_pair( "find_odd_success", nFindOddSuccess )
+ << std::make_pair( "find_odd_failed", nFindOddFailed );
+ }
+
+ template <class Set>
+ void do_test_extract_with( Set& testSet )
+ {
+ typedef Inserter<Set> insert_thread;
+ typedef Deleter<Set> delete_thread;
+ typedef Extractor< typename Set::gc, Set > extract_thread;
+ typedef Observer<Set> observer_thread;
+
+ m_nInsThreadCount.store( s_nInsThreadCount, atomics::memory_order_release );
+
+ cds_test::thread_pool& pool = get_pool();
+ pool.add( new insert_thread( pool, testSet ), s_nInsThreadCount );
+ if ( s_nDelThreadCount )
+ pool.add( new delete_thread( pool, testSet ), s_nDelThreadCount );
+ if ( s_nExtractThreadCount )
+ pool.add( new extract_thread( pool, testSet ), s_nExtractThreadCount );
+ if ( s_nFindThreadCount )
+ pool.add( new observer_thread( pool, testSet ), s_nFindThreadCount );
+
+ propout() << std::make_pair( "insert_thread_count", s_nInsThreadCount )
+ << std::make_pair( "delete_thread_count", s_nDelThreadCount )
+ << std::make_pair( "extract_thread_count", s_nExtractThreadCount )
+ << std::make_pair( "find_thread_count", s_nFindThreadCount )
+ << std::make_pair( "set_size", s_nSetSize )
+ << std::make_pair( "pass_count", s_nInsertPassCount );
+
+ std::chrono::milliseconds duration = pool.run();
+
+ propout() << std::make_pair( "duration", duration );
+
+ size_t nInsertInitFailed = 0;
+ size_t nInsertInitSuccess = 0;
+ size_t nInsertSuccess = 0;
+ size_t nInsertFailed = 0;
+ size_t nDeleteSuccess = 0;
+ size_t nDeleteFailed = 0;
+ size_t nExtractSuccess = 0;
+ size_t nExtractFailed = 0;
+
+ size_t nFindEvenSuccess = 0;
+ size_t nFindEvenFailed = 0;
+ size_t nFindOddSuccess = 0;
+ size_t nFindOddFailed = 0;
+
+ for ( size_t i = 0; i < pool.size(); ++i ) {
+ cds_test::thread& thr = pool.get( i );
+ switch ( thr.type()) {
+ case inserter_thread:
+ {
+ insert_thread& inserter = static_cast<insert_thread&>( thr );
+ nInsertSuccess += inserter.m_nInsertSuccess;
+ nInsertFailed += inserter.m_nInsertFailed;
+ nInsertInitSuccess += inserter.m_nInsertInitSuccess;
+ nInsertInitFailed += inserter.m_nInsertInitFailed;
+ }
+ break;
+ case deleter_thread:
+ {
+ delete_thread& deleter = static_cast<delete_thread&>(thr);
+ nDeleteSuccess += deleter.m_nDeleteSuccess;
+ nDeleteFailed += deleter.m_nDeleteFailed;
+ }
+ break;
+ case extractor_thread:
+ {
+ extract_thread& extractor = static_cast<extract_thread&>(thr);
+ nExtractSuccess += extractor.m_nExtractSuccess;
+ nExtractFailed += extractor.m_nExtractFailed;
+ }
+ break;
+ case find_thread:
+ {
+ observer_thread& observer = static_cast<observer_thread&>( thr );
+ nFindEvenSuccess = observer.m_nFindEvenSuccess;
+ nFindEvenFailed = observer.m_nFindEvenFailed;
+ nFindOddSuccess = observer.m_nFindOddSuccess;
+ nFindOddFailed = observer.m_nFindOddFailed;
+ }
+ break;
+ default:
+ assert( false );
+ }
+ }
+
+ size_t const nInitialOddKeys = ( s_nSetSize * s_nInsThreadCount ) / 2;
+
+ EXPECT_EQ( nInsertInitFailed, 0u );
+ EXPECT_EQ( nInsertInitSuccess, s_nSetSize * s_nInsThreadCount );
+ EXPECT_EQ( nFindEvenFailed, 0u );
+ EXPECT_GE( nInsertSuccess + nInitialOddKeys, nDeleteSuccess + nExtractSuccess );
+ EXPECT_LE( nInsertSuccess, nDeleteSuccess + nExtractSuccess );
+
+ propout()
+ << std::make_pair( "insert_init_success", nInsertInitSuccess )
+ << std::make_pair( "insert_init_failed", nInsertInitFailed )
+ << std::make_pair( "insert_success", nInsertSuccess )
+ << std::make_pair( "insert_failed", nInsertFailed )
+ << std::make_pair( "delete_success", nDeleteSuccess )
+ << std::make_pair( "delete_failed", nDeleteFailed )
+ << std::make_pair( "extract_success", nExtractSuccess )
+ << std::make_pair( "extract_failed", nExtractFailed )
+ << std::make_pair( "find_even_success", nFindEvenSuccess )
+ << std::make_pair( "find_even_failed", nFindEvenFailed )
+ << std::make_pair( "find_odd_success", nFindOddSuccess )
+ << std::make_pair( "find_odd_failed", nFindOddFailed );
+ }
+
+ template <typename Set>
+ void analyze( Set& testSet )
+ {
+ // All even keys must be in the set
+ {
+ for ( size_t n = 0; n < s_nSetSize; n +=2 ) {
+ for ( size_t i = 0; i < s_nInsThreadCount; ++i ) {
+ EXPECT_TRUE( testSet.contains( key_type( n, i ))) << "key=" << n << "/" << i;
+ }
+ }
+ }
+
+ check_before_clear( testSet );
+
+ testSet.clear();
+ EXPECT_TRUE( testSet.empty()) << "set.size=" << testSet.size();
+
+ additional_check( testSet );
+ print_stat( propout(), testSet );
+ additional_cleanup( testSet );
+ }
+
+ template <class Set>
+ void run_test()
+ {
+ static_assert( !Set::c_bExtractSupported, "Set class must not support extract() method" );
+
+ Set testSet( *this );
+ do_test_with( testSet );
+ analyze( testSet );
+ }
+
+ template <class Set>
+ void run_test_extract()
+ {
+ static_assert( Set::c_bExtractSupported, "Set class must support extract() method" );
+
+ Set testSet( *this );
+ do_test_extract_with( testSet );
+ analyze( testSet );
+ }
+
+ template <class Map>
+ void run_feldman();
+ };
+
+ class Set_DelOdd_LF: public Set_DelOdd
+ , public ::testing::WithParamInterface<size_t>
+ {
+ public:
+ template <class Set>
+ void run_test()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Set_DelOdd::run_test<Set>();
+ }
+
+ template <class Set>
+ void run_test_extract()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Set_DelOdd::run_test_extract<Set>();
+ }
+
+ static std::vector<size_t> get_load_factors();
+ };
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_delodd.h"
+#include "set_type_cuckoo.h"
+
+namespace set {
+
+ //CDSSTRESS_CuckooSet( Set_DelOdd, run_test, key_thread, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_delodd.h"
+#include "set_type_ellen_bintree.h"
+
+namespace set {
+
+ CDSSTRESS_EllenBinTreeSet( Set_DelOdd, run_test_extract, key_thread, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_delodd.h"
+#include "set_type_feldman_hashset.h"
+
+namespace set {
+
+ template <class Set>
+ void Set_DelOdd::run_feldman()
+ {
+ typedef typename Set::traits original_traits;
+ struct traits: public original_traits {
+ enum { hash_size = sizeof( uint32_t ) + sizeof( uint16_t ) };
+ };
+ typedef typename Set::template rebind_traits< traits >::result set_type;
+
+ run_test_extract<set_type>();
+ }
+
+ CDSSTRESS_FeldmanHashSet_fixed( Set_DelOdd, run_feldman, key_thread, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_delodd.h"
+#include "set_type_michael.h"
+
+namespace set {
+
+ CDSSTRESS_MichaelSet( Set_DelOdd_LF, run_test_extract, key_thread, size_t )
+ CDSSTRESS_MichaelIterableSet( Set_DelOdd_LF, run_test_extract, key_thread, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_delodd.h"
+#include "set_type_skip_list.h"
+
+namespace set {
+
+ CDSSTRESS_SkipListSet( Set_DelOdd, run_test_extract, key_thread, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_delodd.h"
+#include "set_type_split_list.h"
+
+namespace set {
+
+ CDSSTRESS_SplitListSet( Set_DelOdd_LF, run_test_extract, key_thread, size_t )
+ CDSSTRESS_SplitListIterableSet( Set_DelOdd_LF, run_test_extract, key_thread, size_t )
+
+
+} // namespace set
--- /dev/null
+set(EXE_SET_INSDELFIND_HP stress-sequential-set-insdelfind-hp)
+set(EXE_SET_INSDELFIND_RCU stress-sequential-set-insdelfind-rcu)
+set(EXE_SET_INSDELFIND_LOCK stress-sequential-set-insdelfind-lock)
+
+set(CDSSTRESS_SET_INSDELFIND_HP_SOURCES
+ ../../../main.cpp
+ set_insdelfind.cpp
+ set_insdelfind_ellentree_hp.cpp
+ set_insdelfind_feldman_hashset_hp.cpp
+ set_insdelfind_michael_hp.cpp
+ set_insdelfind_skip_hp.cpp
+ set_insdelfind_split_hp.cpp
+)
+
+set(CDSSTRESS_SET_INSDELFIND_RCU_SOURCES
+ ../../../main.cpp
+ set_insdelfind.cpp
+ set_insdelfind_ellentree_rcu.cpp
+ set_insdelfind_feldman_hashset_rcu.cpp
+ set_insdelfind_michael_rcu.cpp
+ set_insdelfind_skip_rcu.cpp
+ set_insdelfind_split_rcu.cpp
+)
+
+set(CDSSTRESS_SET_INSDELFIND_LOCK_SOURCES
+ ../../../main.cpp
+ set_insdelfind.cpp
+ set_insdelfind_cuckoo.cpp
+ set_insdelfind_std.cpp
+ set_insdelfind_striped.cpp
+)
+
+include_directories(
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/..
+)
+
+add_executable(${EXE_SET_INSDELFIND_HP} ${CDSSTRESS_SET_INSDELFIND_HP_SOURCES})
+target_link_libraries(${EXE_SET_INSDELFIND_HP} ${CDS_TEST_LIBRARIES} ${CDSSTRESS_FRAMEWORK_LIBRARY})
+add_test(NAME ${EXE_SET_INSDELFIND_HP} COMMAND ${EXE_SET_INSDELFIND_HP} WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
+
+add_executable(${EXE_SET_INSDELFIND_RCU} ${CDSSTRESS_SET_INSDELFIND_RCU_SOURCES})
+target_link_libraries(${EXE_SET_INSDELFIND_RCU} ${CDS_TEST_LIBRARIES} ${CDSSTRESS_FRAMEWORK_LIBRARY})
+add_test(NAME ${EXE_SET_INSDELFIND_RCU} COMMAND ${EXE_SET_INSDELFIND_RCU} WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
+
+add_executable(${EXE_SET_INSDELFIND_LOCK} ${CDSSTRESS_SET_INSDELFIND_LOCK_SOURCES})
+target_link_libraries(${EXE_SET_INSDELFIND_LOCK} ${CDS_TEST_LIBRARIES} ${CDSSTRESS_FRAMEWORK_LIBRARY})
+add_test(NAME ${EXE_SET_INSDELFIND_LOCK} COMMAND ${EXE_SET_INSDELFIND_LOCK} WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
+
+add_custom_target( stress-sequential-set-insdelfind
+ DEPENDS
+ stress-sequential-set-insdelfind-hp
+ stress-sequential-set-insdelfind-rcu
+ stress-sequential-set-insdelfind-lock
+)
+
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdelfind.h"
+
+namespace set {
+
+ size_t Set_InsDelFind::s_nSetSize = 500000; // initial set size
+ size_t Set_InsDelFind::s_nThreadCount = 8; // thread count
+ size_t Set_InsDelFind::s_nMaxLoadFactor = 8; // maximum load factor
+ unsigned int Set_InsDelFind::s_nInsertPercentage = 5;
+ unsigned int Set_InsDelFind::s_nDeletePercentage = 5;
+ unsigned int Set_InsDelFind::s_nDuration = 30; // test duration, seconds
+
+ size_t Set_InsDelFind::s_nCuckooInitialSize = 1024;// initial size for CuckooSet
+ size_t Set_InsDelFind::s_nCuckooProbesetSize = 16; // CuckooSet probeset size (only for list-based probeset)
+ size_t Set_InsDelFind::s_nCuckooProbesetThreshold = 0; // CUckooSet probeset threshold (0 - use default)
+
+ size_t Set_InsDelFind::s_nFeldmanSet_HeadBits = 10;
+ size_t Set_InsDelFind::s_nFeldmanSet_ArrayBits = 4;
+
+ size_t Set_InsDelFind::s_nLoadFactor = 2;
+ Set_InsDelFind::actions Set_InsDelFind::s_arrShuffle[Set_InsDelFind::c_nShuffleSize];
+
+ void Set_InsDelFind::SetUpTestCase()
+ {
+ cds_test::config const& cfg = get_config( "map_insdelfind" );
+
+ s_nSetSize = cfg.get_size_t( "InitialMapSize", s_nSetSize );
+ if ( s_nSetSize < 1000 )
+ s_nSetSize = 1000;
+
+ s_nThreadCount = cfg.get_size_t( "ThreadCount", s_nThreadCount );
+ if ( s_nThreadCount == 0 )
+ s_nThreadCount = 2;
+
+ s_nMaxLoadFactor = cfg.get_size_t( "MaxLoadFactor", s_nMaxLoadFactor );
+ if ( s_nMaxLoadFactor == 0 )
+ s_nMaxLoadFactor = 1;
+
+ s_nInsertPercentage = cfg.get_uint( "InsertPercentage", s_nInsertPercentage );
+ if ( s_nInsertPercentage == 0 || s_nInsertPercentage > 90 )
+ s_nInsertPercentage = 5;
+
+ s_nDeletePercentage = cfg.get_uint( "DeletePercentage", s_nDeletePercentage );
+ if ( s_nDeletePercentage == 0 || s_nDeletePercentage > 90 )
+ s_nDeletePercentage = 5;
+
+ s_nDuration = cfg.get_uint( "Duration", s_nDuration );
+ if ( s_nDuration == 0 )
+ s_nDuration = 5;
+
+ s_nCuckooInitialSize = cfg.get_size_t( "CuckooInitialSize", s_nCuckooInitialSize );
+ if ( s_nCuckooInitialSize < 256 )
+ s_nCuckooInitialSize = 256;
+
+ s_nCuckooProbesetSize = cfg.get_size_t( "CuckooProbesetSize", s_nCuckooProbesetSize );
+ if ( s_nCuckooProbesetSize < 8 )
+ s_nCuckooProbesetSize = 8;
+
+ s_nCuckooProbesetThreshold = cfg.get_size_t( "CuckooProbesetThreshold", s_nCuckooProbesetThreshold );
+
+ s_nFeldmanSet_HeadBits = cfg.get_size_t( "FeldmanMapHeadBits", s_nFeldmanSet_HeadBits );
+ if ( s_nFeldmanSet_HeadBits == 0 )
+ s_nFeldmanSet_HeadBits = 2;
+
+ s_nFeldmanSet_ArrayBits = cfg.get_size_t( "FeldmanMapArrayBits", s_nFeldmanSet_ArrayBits );
+ if ( s_nFeldmanSet_ArrayBits == 0 )
+ s_nFeldmanSet_ArrayBits = 2;
+
+ actions * pFirst = s_arrShuffle;
+ actions * pLast = s_arrShuffle + s_nInsertPercentage;
+ std::fill( pFirst, pLast, do_insert );
+ pFirst = pLast;
+ pLast += s_nDeletePercentage;
+ std::fill( pFirst, pLast, do_delete );
+ pFirst = pLast;
+ pLast = s_arrShuffle + sizeof( s_arrShuffle ) / sizeof( s_arrShuffle[0] );
+ if ( pFirst < pLast )
+ std::fill( pFirst, pLast, do_find );
+ shuffle( s_arrShuffle, pLast );
+ }
+
+ std::vector<size_t> Set_InsDelFind_LF::get_load_factors()
+ {
+ cds_test::config const& cfg = get_config( "map_delodd" );
+
+ s_nMaxLoadFactor = cfg.get_size_t( "MaxLoadFactor", s_nMaxLoadFactor );
+ if ( s_nMaxLoadFactor == 0 )
+ s_nMaxLoadFactor = 1;
+
+ std::vector<size_t> lf;
+ for ( size_t n = 1; n <= s_nMaxLoadFactor; n *= 2 )
+ lf.push_back( n );
+
+ return lf;
+ }
+
+#ifdef CDSTEST_GTEST_INSTANTIATE_TEST_CASE_P_HAS_4TH_ARG
+ static std::string get_test_parameter_name( testing::TestParamInfo<size_t> const& p )
+ {
+ return std::to_string( p.param );
+ }
+ INSTANTIATE_TEST_CASE_P( a, Set_InsDelFind_LF, ::testing::ValuesIn( Set_InsDelFind_LF::get_load_factors()), get_test_parameter_name );
+#else
+ INSTANTIATE_TEST_CASE_P( a, Set_InsDelFind_LF, ::testing::ValuesIn( Set_InsDelFind_LF::get_load_factors()));
+#endif
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_type.h"
+
+namespace set {
+
+ class Set_InsDelFind: public cds_test::stress_fixture
+ {
+ public:
+ static size_t s_nSetSize; // initial set size
+ static size_t s_nThreadCount; // thread count
+ static size_t s_nMaxLoadFactor; // maximum load factor
+ static unsigned int s_nInsertPercentage;
+ static unsigned int s_nDeletePercentage;
+ static unsigned int s_nDuration; // test duration, seconds
+
+ static size_t s_nCuckooInitialSize; // initial size for CuckooSet
+ static size_t s_nCuckooProbesetSize; // CuckooSet probeset size (only for list-based probeset)
+ static size_t s_nCuckooProbesetThreshold; // CUckooSet probeset threshold (0 - use default)
+
+ static size_t s_nFeldmanSet_HeadBits;
+ static size_t s_nFeldmanSet_ArrayBits;
+
+ static size_t s_nLoadFactor;
+
+ static void SetUpTestCase();
+ //static void TearDownTestCase();
+
+ public:
+ enum actions
+ {
+ do_find,
+ do_insert,
+ do_delete
+ };
+ static const unsigned int c_nShuffleSize = 100;
+ static actions s_arrShuffle[c_nShuffleSize];
+
+ protected:
+ typedef size_t key_type;
+ typedef size_t value_type;
+
+ template <class Set>
+ class Worker: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Set& m_Set;
+
+ public:
+ size_t m_nInsertSuccess = 0;
+ size_t m_nInsertFailed = 0;
+ size_t m_nDeleteSuccess = 0;
+ size_t m_nDeleteFailed = 0;
+ size_t m_nFindSuccess = 0;
+ size_t m_nFindFailed = 0;
+
+ public:
+ Worker( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool )
+ , m_Set( set )
+ {}
+
+ Worker( Worker& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Worker( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+ Set_InsDelFind& fixture = pool().template fixture<Set_InsDelFind>();
+
+ unsigned int i = 0;
+ size_t const nNormalize = size_t(-1) / ( fixture.s_nSetSize * 2);
+
+ size_t nRand = 0;
+ while ( !time_elapsed()) {
+ nRand = cds::bitop::RandXorShift(nRand);
+ size_t n = nRand / nNormalize;
+ switch ( s_arrShuffle[i] ) {
+ case do_find:
+ if ( rSet.contains( n ))
+ ++m_nFindSuccess;
+ else
+ ++m_nFindFailed;
+ break;
+ case do_insert:
+ if ( rSet.insert( n ))
+ ++m_nInsertSuccess;
+ else
+ ++m_nInsertFailed;
+ break;
+ case do_delete:
+ if ( rSet.erase( n ))
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ break;
+ }
+
+ if ( ++i >= c_nShuffleSize )
+ i = 0;
+ }
+ }
+ };
+
+ protected:
+ template <class Set>
+ void do_test( Set& testSet )
+ {
+ typedef Worker<Set> work_thread;
+
+ // fill map - only odd number
+ {
+ size_t * pInitArr = new size_t[ s_nSetSize ];
+ size_t * pEnd = pInitArr + s_nSetSize;
+ for ( size_t i = 0; i < s_nSetSize; ++i )
+ pInitArr[i] = i * 2 + 1;
+ shuffle( pInitArr, pEnd );
+ for ( size_t * p = pInitArr; p < pEnd; ++p )
+ testSet.insert( typename Set::value_type( *p, *p ));
+ delete [] pInitArr;
+ }
+
+ cds_test::thread_pool& pool = get_pool();
+ pool.add( new work_thread( pool, testSet ), s_nThreadCount );
+
+ propout() << std::make_pair( "thread_count", s_nThreadCount )
+ << std::make_pair( "set_size", s_nSetSize )
+ << std::make_pair( "insert_percentage", s_nInsertPercentage )
+ << std::make_pair( "delete_percentage", s_nDeletePercentage )
+ << std::make_pair( "total_duration", s_nDuration );
+
+ std::chrono::milliseconds duration = pool.run( std::chrono::seconds( s_nDuration ));
+
+ propout() << std::make_pair( "duration", duration );
+
+ size_t nInsertSuccess = 0;
+ size_t nInsertFailed = 0;
+ size_t nDeleteSuccess = 0;
+ size_t nDeleteFailed = 0;
+ size_t nFindSuccess = 0;
+ size_t nFindFailed = 0;
+ for ( size_t i = 0; i < pool.size(); ++i ) {
+ work_thread& thr = static_cast<work_thread&>( pool.get( i ));
+ nInsertSuccess += thr.m_nInsertSuccess;
+ nInsertFailed += thr.m_nInsertFailed;
+ nDeleteSuccess += thr.m_nDeleteSuccess;
+ nDeleteFailed += thr.m_nDeleteFailed;
+ nFindSuccess += thr.m_nFindSuccess;
+ nFindFailed += thr.m_nFindFailed;
+ }
+
+ propout()
+ << std::make_pair( "insert_success", nInsertSuccess )
+ << std::make_pair( "insert_failed", nInsertFailed )
+ << std::make_pair( "delete_success", nDeleteSuccess )
+ << std::make_pair( "delete_failed", nDeleteFailed )
+ << std::make_pair( "find_success", nFindSuccess )
+ << std::make_pair( "find_failed", nFindFailed );
+
+ {
+ ASSERT_TRUE( std::chrono::duration_cast<std::chrono::seconds>(duration).count() > 0 );
+ size_t nTotalOps = nInsertSuccess + nInsertFailed + nDeleteSuccess + nDeleteFailed + nFindSuccess + nFindFailed;
+ propout() << std::make_pair( "avg_speed", nTotalOps / std::chrono::duration_cast<std::chrono::seconds>(duration).count());
+ }
+
+
+ testSet.clear();
+ EXPECT_TRUE( testSet.empty()) << "set size=" << testSet.size();
+
+ additional_check( testSet );
+ print_stat( propout(), testSet );
+ additional_cleanup( testSet );
+ }
+
+ template <class Set>
+ void run_test()
+ {
+ Set s( *this );
+ do_test( s );
+ }
+ };
+
+ class Set_InsDelFind_LF: public Set_InsDelFind
+ , public ::testing::WithParamInterface<size_t>
+ {
+ public:
+ template <class Set>
+ void run_test()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Set_InsDelFind::run_test<Set>();
+ }
+
+ static std::vector<size_t> get_load_factors();
+ };
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdelfind.h"
+#include "set_type_cuckoo.h"
+
+namespace set {
+
+ //CDSSTRESS_CuckooSet( Set_InsDelFind, run_test, size_t, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdelfind.h"
+#include "set_type_ellen_bintree.h"
+
+namespace set {
+
+ CDSSTRESS_EllenBinTreeSet_HP( Set_InsDelFind, run_test, size_t, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdelfind.h"
+#include "set_type_ellen_bintree.h"
+
+namespace set {
+
+ CDSSTRESS_EllenBinTreeSet_RCU( Set_InsDelFind, run_test, size_t, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdelfind.h"
+#include "set_type_feldman_hashset.h"
+
+namespace set {
+
+ CDSSTRESS_FeldmanHashSet_fixed_HP( Set_InsDelFind, run_test, size_t, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdelfind.h"
+#include "set_type_feldman_hashset.h"
+
+namespace set {
+
+ CDSSTRESS_FeldmanHashSet_fixed_RCU( Set_InsDelFind, run_test, size_t, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdelfind.h"
+#include "set_type_michael.h"
+
+namespace set {
+
+ CDSSTRESS_MichaelSet_HP( Set_InsDelFind_LF, run_test, size_t, size_t )
+ CDSSTRESS_MichaelIterableSet( Set_InsDelFind_LF, run_test, size_t, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdelfind.h"
+#include "set_type_michael.h"
+
+namespace set {
+
+ CDSSTRESS_MichaelSet_RCU( Set_InsDelFind_LF, run_test, size_t, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdelfind.h"
+#include "set_type_skip_list.h"
+
+namespace set {
+
+ CDSSTRESS_SkipListSet_HP( Set_InsDelFind, run_test, size_t, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdelfind.h"
+#include "set_type_skip_list.h"
+
+namespace set {
+
+ CDSSTRESS_SkipListSet_RCU( Set_InsDelFind, run_test, size_t, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdelfind.h"
+#include "set_type_split_list.h"
+
+namespace set {
+
+ CDSSTRESS_SplitListSet_HP( Set_InsDelFind_LF, run_test, size_t, size_t )
+ CDSSTRESS_SplitListIterableSet( Set_InsDelFind_LF, run_test, size_t, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdelfind.h"
+#include "set_type_split_list.h"
+
+namespace set {
+
+ CDSSTRESS_SplitListSet_RCU( Set_InsDelFind_LF, run_test, size_t, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdelfind.h"
+#include "set_type_std.h"
+
+namespace set {
+ //CDSSTRESS_StdSet( Set_InsDelFind, run_test, size_t, size_t )
+} // namespace set
+
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdelfind.h"
+#include "set_type_striped.h"
+
+namespace set {
+
+ //CDSSTRESS_StripedSet( Set_InsDelFind_LF, run_test, size_t, size_t )
+
+} // namespace set
+
--- /dev/null
+set(PACKAGE_NAME stress-sequential-set-insdel-func)
+
+set(CDSSTRESS_SET_INSDEL_FUNC_SOURCES
+ ../../../main.cpp
+ set_insdel_func.cpp
+ set_insdel_func_cuckoo.cpp
+ set_insdel_func_ellentree.cpp
+ set_insdel_func_feldman_hashset.cpp
+ set_insdel_func_michael.cpp
+ set_insdel_func_skip.cpp
+ set_insdel_func_split.cpp
+ set_insdel_func_striped.cpp
+)
+
+include_directories(
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/..
+)
+
+add_executable(${PACKAGE_NAME} ${CDSSTRESS_SET_INSDEL_FUNC_SOURCES})
+target_link_libraries(${PACKAGE_NAME} ${CDS_TEST_LIBRARIES} ${CDSSTRESS_FRAMEWORK_LIBRARY})
+
+add_test(NAME ${PACKAGE_NAME} COMMAND ${PACKAGE_NAME} WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdel_func.h"
+
+namespace set {
+
+ size_t Set_InsDel_func::s_nSetSize = 1000000; // set size
+ size_t Set_InsDel_func::s_nInsertThreadCount = 4; // count of insertion thread
+ size_t Set_InsDel_func::s_nDeleteThreadCount = 4; // count of deletion thread
+ size_t Set_InsDel_func::s_nUpdateThreadCount = 4; // count of ensure thread
+ size_t Set_InsDel_func::s_nThreadPassCount = 4; // pass count for each thread
+ size_t Set_InsDel_func::s_nMaxLoadFactor = 8; // maximum load factor
+
+ size_t Set_InsDel_func::s_nCuckooInitialSize = 1024;// initial size for CuckooSet
+ size_t Set_InsDel_func::s_nCuckooProbesetSize = 16; // CuckooSet probeset size (only for list-based probeset)
+ size_t Set_InsDel_func::s_nCuckooProbesetThreshold = 0; // CUckooSet probeset threshold (0 - use default)
+
+ size_t Set_InsDel_func::s_nFeldmanSet_HeadBits = 10;
+ size_t Set_InsDel_func::s_nFeldmanSet_ArrayBits = 4;
+
+ size_t Set_InsDel_func::s_nLoadFactor = 1;
+
+ void Set_InsDel_func::SetUpTestCase()
+ {
+ cds_test::config const& cfg = get_config( "map_insdel_func" );
+
+ s_nSetSize = cfg.get_size_t( "MapSize", s_nSetSize );
+ if ( s_nSetSize < 1000 )
+ s_nSetSize = 1000;
+
+ s_nInsertThreadCount = cfg.get_size_t( "InsertThreadCount", s_nInsertThreadCount );
+ if ( s_nInsertThreadCount == 0 )
+ s_nInsertThreadCount = 2;
+
+ s_nDeleteThreadCount = cfg.get_size_t( "DeleteThreadCount", s_nDeleteThreadCount );
+ if ( s_nDeleteThreadCount == 0 )
+ s_nDeleteThreadCount = 2;
+
+ s_nUpdateThreadCount = cfg.get_size_t( "UpdateThreadCount", s_nUpdateThreadCount );
+ if ( s_nUpdateThreadCount == 0 )
+ s_nUpdateThreadCount = 2;
+
+ s_nThreadPassCount = cfg.get_size_t( "ThreadPassCount", s_nThreadPassCount );
+ if ( s_nThreadPassCount == 0 )
+ s_nThreadPassCount = 4;
+
+ s_nMaxLoadFactor = cfg.get_size_t( "MaxLoadFactor", s_nMaxLoadFactor );
+ if ( s_nMaxLoadFactor == 0 )
+ s_nMaxLoadFactor = 1;
+
+ s_nCuckooInitialSize = cfg.get_size_t( "CuckooInitialSize", s_nCuckooInitialSize );
+ if ( s_nCuckooInitialSize < 256 )
+ s_nCuckooInitialSize = 256;
+
+ s_nCuckooProbesetSize = cfg.get_size_t( "CuckooProbesetSize", s_nCuckooProbesetSize );
+ if ( s_nCuckooProbesetSize < 8 )
+ s_nCuckooProbesetSize = 8;
+
+ s_nCuckooProbesetThreshold = cfg.get_size_t( "CuckooProbesetThreshold", s_nCuckooProbesetThreshold );
+
+ s_nFeldmanSet_HeadBits = cfg.get_size_t( "FeldmanMapHeadBits", s_nFeldmanSet_HeadBits );
+ if ( s_nFeldmanSet_HeadBits == 0 )
+ s_nFeldmanSet_HeadBits = 2;
+
+ s_nFeldmanSet_ArrayBits = cfg.get_size_t( "FeldmanMapArrayBits", s_nFeldmanSet_ArrayBits );
+ if ( s_nFeldmanSet_ArrayBits == 0 )
+ s_nFeldmanSet_ArrayBits = 2;
+ }
+
+ std::vector<size_t> Set_InsDel_func_LF::get_load_factors()
+ {
+ cds_test::config const& cfg = get_config( "map_insdel_func" );
+
+ s_nMaxLoadFactor = cfg.get_size_t( "MaxLoadFactor", s_nMaxLoadFactor );
+ if ( s_nMaxLoadFactor == 0 )
+ s_nMaxLoadFactor = 1;
+
+ std::vector<size_t> lf;
+ for ( size_t n = 1; n <= s_nMaxLoadFactor; n *= 2 )
+ lf.push_back( n );
+
+ return lf;
+ }
+
+#ifdef CDSTEST_GTEST_INSTANTIATE_TEST_CASE_P_HAS_4TH_ARG
+ static std::string get_test_parameter_name( testing::TestParamInfo<size_t> const& p )
+ {
+ return std::to_string( p.param );
+ }
+ INSTANTIATE_TEST_CASE_P( a, Set_InsDel_func_LF, ::testing::ValuesIn( Set_InsDel_func_LF::get_load_factors()), get_test_parameter_name );
+#else
+ INSTANTIATE_TEST_CASE_P( a, Set_InsDel_func_LF, ::testing::ValuesIn( Set_InsDel_func_LF::get_load_factors()));
+#endif
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_type.h"
+
+namespace set {
+
+ class Set_InsDel_func: public cds_test::stress_fixture
+ {
+ public:
+ static size_t s_nSetSize; // set size
+ static size_t s_nInsertThreadCount; // count of insertion thread
+ static size_t s_nDeleteThreadCount; // count of deletion thread
+ static size_t s_nUpdateThreadCount; // count of updating thread
+ static size_t s_nThreadPassCount; // pass count for each thread
+ static size_t s_nMaxLoadFactor; // maximum load factor
+
+ static size_t s_nCuckooInitialSize; // initial size for CuckooSet
+ static size_t s_nCuckooProbesetSize; // CuckooSet probeset size (only for list-based probeset)
+ static size_t s_nCuckooProbesetThreshold; // CUckooSet probeset threshold (0 - use default)
+
+ static size_t s_nFeldmanSet_HeadBits;
+ static size_t s_nFeldmanSet_ArrayBits;
+
+ static size_t s_nLoadFactor;
+
+ static void SetUpTestCase();
+ //static void TearDownTestCase();
+
+ public:
+ typedef size_t key_type;
+
+ struct value {
+ size_t nKey;
+ size_t nData;
+ atomics::atomic<size_t> nUpdateCall;
+ bool volatile bInitialized;
+ cds::OS::ThreadId threadId; // insert thread id
+
+ typedef cds::sync::spin_lock< cds::backoff::pause > lock_type;
+ mutable lock_type m_access;
+
+ value()
+ : nKey(0)
+ , nData(0)
+ , nUpdateCall(0)
+ , bInitialized( false )
+ , threadId( cds::OS::get_current_thread_id())
+ {}
+
+ value( value const& s )
+ : nKey(s.nKey)
+ , nData(s.nData)
+ , nUpdateCall(s.nUpdateCall.load(atomics::memory_order_relaxed))
+ , bInitialized( s.bInitialized )
+ , threadId( cds::OS::get_current_thread_id())
+ , m_access()
+ {}
+
+ // boost::container::flat_map requires operator =
+ // cppcheck-suppress operatorEqVarError
+ value& operator=( value const& v )
+ {
+ nKey = v.nKey;
+ nData = v.nData;
+ threadId = v.threadId;
+ nUpdateCall.store( v.nUpdateCall.load(atomics::memory_order_relaxed), atomics::memory_order_relaxed );
+ bInitialized = v.bInitialized;
+
+ return *this;
+ }
+ };
+
+ size_t * m_pKeyFirst;
+ size_t * m_pKeyLast;
+ std::unique_ptr< size_t[] > m_pKeyArr;
+
+ enum {
+ insert_thread,
+ update_thread,
+ delete_thread
+ };
+
+ template <class Set>
+ class Inserter: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+
+ Set& m_Set;
+ typedef typename Set::value_type keyval_type;
+
+ struct insert_functor {
+ size_t nTestFunctorRef;
+
+ insert_functor()
+ : nTestFunctorRef(0)
+ {}
+ insert_functor( insert_functor const& ) = delete;
+
+ void operator()( keyval_type& val )
+ {
+ std::unique_lock< typename value::lock_type> ac( val.val.m_access );
+
+ val.val.nKey = val.key;
+ val.val.nData = val.key * 8;
+
+ ++nTestFunctorRef;
+ val.val.bInitialized = true;
+ }
+ };
+
+ public:
+ size_t m_nInsertSuccess = 0;
+ size_t m_nInsertFailed = 0;
+ size_t m_nTestFunctorRef = 0;
+
+ public:
+ Inserter( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, insert_thread )
+ , m_Set( set )
+ {}
+
+ Inserter( Inserter& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Inserter( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+ Set_InsDel_func& fixture = pool().template fixture<Set_InsDel_func>();
+
+ size_t * pKeyFirst = fixture.m_pKeyFirst;
+ size_t * pKeyLast = fixture.m_pKeyLast;
+ size_t const nPassCount = fixture.s_nThreadPassCount;
+
+ // func is passed by reference
+ insert_functor func;
+
+ if ( id() & 1 ) {
+ for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) {
+ for ( size_t * p = pKeyFirst; p < pKeyLast; ++p ) {
+ if ( rSet.insert( *p, std::ref( func )))
+ ++m_nInsertSuccess;
+ else
+ ++m_nInsertFailed;
+ }
+ }
+ }
+ else {
+ for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) {
+ for ( size_t * p = pKeyLast - 1; p >= pKeyFirst; --p ) {
+ if ( rSet.insert( *p, std::ref( func )))
+ ++m_nInsertSuccess;
+ else
+ ++m_nInsertFailed;
+ }
+ }
+ }
+
+ m_nTestFunctorRef = func.nTestFunctorRef;
+ }
+ };
+
+ template <class Set>
+ class Updater: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+
+ Set& m_Set;
+ typedef typename Set::value_type keyval_type;
+
+ struct update_functor {
+ size_t nCreated = 0;
+ size_t nModified = 0;
+
+ update_functor() {}
+ update_functor( const update_functor& ) = delete;
+
+ void operator()( bool bNew, keyval_type& val, size_t /*nKey*/ )
+ {
+ std::unique_lock<typename value::lock_type> ac( val.val.m_access );
+ if ( !val.val.bInitialized )
+ {
+ val.val.nKey = val.key;
+ val.val.nData = val.key * 8;
+ val.val.bInitialized = true;
+ }
+
+ if ( bNew ) {
+ ++nCreated;
+ }
+ else {
+ val.val.nUpdateCall.fetch_add( 1, atomics::memory_order_relaxed );
+ ++nModified;
+ }
+ }
+
+ void operator()( keyval_type& cur, keyval_type * old )
+ {
+ operator()( old == nullptr, cur, 0 );
+ }
+ };
+
+ public:
+ size_t m_nUpdateFailed = 0;
+ size_t m_nUpdateCreated = 0;
+ size_t m_nUpdateExisted = 0;
+ size_t m_nFunctorCreated = 0;
+ size_t m_nFunctorModified = 0;
+
+ public:
+ Updater( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, update_thread )
+ , m_Set( set )
+ {}
+
+ Updater( Updater& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Updater( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+
+ Set_InsDel_func& fixture = pool().template fixture<Set_InsDel_func>();
+ size_t * pKeyFirst = fixture.m_pKeyFirst;
+ size_t * pKeyLast = fixture.m_pKeyLast;
+ size_t const nPassCount = fixture.s_nThreadPassCount;
+
+ update_functor func;
+
+ if ( id() & 1 ) {
+ for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) {
+ for ( size_t * p = pKeyFirst; p < pKeyLast; ++p ) {
+ std::pair<bool, bool> ret = rSet.update( *p, std::ref( func ), true );
+ if ( ret.first ) {
+ if ( ret.second )
+ ++m_nUpdateCreated;
+ else
+ ++m_nUpdateExisted;
+ }
+ else
+ ++m_nUpdateFailed;
+ }
+ }
+ }
+ else {
+ for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) {
+ for ( size_t * p = pKeyLast - 1 ; p >= pKeyFirst; --p ) {
+ std::pair<bool, bool> ret = rSet.update( *p, std::ref( func ), true );
+ if ( ret.first ) {
+ if ( ret.second )
+ ++m_nUpdateCreated;
+ else
+ ++m_nUpdateExisted;
+ }
+ else
+ ++m_nUpdateFailed;
+ }
+ }
+ }
+
+ m_nFunctorCreated = func.nCreated;
+ m_nFunctorModified = func.nModified;
+ }
+ };
+
+ template <class Set>
+ class Deleter: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+
+ Set& m_Set;
+ typedef typename Set::value_type keyval_type;
+
+ struct value_container
+ {
+ size_t nKeyExpected;
+
+ size_t nSuccessItem = 0;
+ size_t nFailedItem = 0;
+ };
+
+ struct erase_functor {
+ value_container m_cnt;
+
+ void operator ()( keyval_type const& itm )
+ {
+ keyval_type& item = const_cast<keyval_type&>(itm);
+ while ( true ) {
+ bool bBkoff = false;
+ {
+ std::unique_lock< typename value::lock_type> ac( item.val.m_access );
+ if ( item.val.bInitialized ) {
+ if ( m_cnt.nKeyExpected == item.val.nKey && m_cnt.nKeyExpected * 8 == item.val.nData )
+ ++m_cnt.nSuccessItem;
+ else
+ ++m_cnt.nFailedItem;
+ item.val.nData++;
+ item.val.nKey = 0;
+ break;
+ }
+ else
+ bBkoff = true;
+ }
+ if ( bBkoff )
+ cds::backoff::yield()();
+ }
+ }
+ };
+
+ public:
+ size_t m_nDeleteSuccess = 0;
+ size_t m_nDeleteFailed = 0;
+ size_t m_nValueSuccess = 0;
+ size_t m_nValueFailed = 0;
+
+ public:
+ Deleter( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, delete_thread )
+ , m_Set( set )
+ {}
+
+ Deleter( Deleter& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Deleter( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+
+ Set_InsDel_func& fixture = pool().template fixture<Set_InsDel_func>();
+ size_t * pKeyFirst = fixture.m_pKeyFirst;
+ size_t * pKeyLast = fixture.m_pKeyLast;
+ size_t const nPassCount = fixture.s_nThreadPassCount;
+
+ erase_functor func;
+
+ if ( id() & 1 ) {
+ for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) {
+ for ( size_t * p = pKeyFirst; p < pKeyLast; ++p ) {
+ func.m_cnt.nKeyExpected = *p;
+ if ( rSet.erase( *p, std::ref( func )))
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ }
+ }
+ }
+ else {
+ for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) {
+ for ( size_t * p = pKeyLast - 1; p >= pKeyFirst; --p ) {
+ func.m_cnt.nKeyExpected = *p;
+ if ( rSet.erase( *p, std::ref( func )))
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ }
+ }
+ }
+
+ m_nValueSuccess = func.m_cnt.nSuccessItem;
+ m_nValueFailed = func.m_cnt.nFailedItem;
+ }
+ };
+
+ protected:
+
+ template <class Set>
+ void run_test( Set& testSet )
+ {
+ typedef Inserter<Set> InserterThread;
+ typedef Deleter<Set> DeleterThread;
+ typedef Updater<Set> UpdaterThread;
+
+ m_pKeyArr.reset( new size_t[ s_nSetSize ] );
+ m_pKeyFirst = m_pKeyArr.get();
+ m_pKeyLast = m_pKeyFirst + s_nSetSize;
+ for ( size_t i = 0; i < s_nSetSize; ++i )
+ m_pKeyArr[i] = i;
+ shuffle( m_pKeyFirst, m_pKeyLast );
+
+ cds_test::thread_pool& pool = get_pool();
+ pool.add( new InserterThread( pool, testSet ), s_nInsertThreadCount );
+ pool.add( new DeleterThread( pool, testSet ), s_nDeleteThreadCount );
+ pool.add( new UpdaterThread( pool, testSet ), s_nUpdateThreadCount );
+
+ propout() << std::make_pair( "insert_thread_count", s_nInsertThreadCount )
+ << std::make_pair( "update_thread_count", s_nUpdateThreadCount )
+ << std::make_pair( "delete_thread_count", s_nDeleteThreadCount )
+ << std::make_pair( "thread_pass_count", s_nThreadPassCount )
+ << std::make_pair( "set_size", s_nSetSize );
+
+ std::chrono::milliseconds duration = pool.run();
+
+ propout() << std::make_pair( "duration", duration );
+
+ size_t nInsertSuccess = 0;
+ size_t nInsertFailed = 0;
+ size_t nDeleteSuccess = 0;
+ size_t nDeleteFailed = 0;
+ size_t nDelValueSuccess = 0;
+ size_t nDelValueFailed = 0;
+ size_t nUpdateFailed = 0;
+ size_t nUpdateCreated = 0;
+ size_t nUpdateModified = 0;
+ size_t nEnsFuncCreated = 0;
+ size_t nEnsFuncModified = 0;
+ size_t nTestFunctorRef = 0;
+
+ for ( size_t i = 0; i < pool.size(); ++i ) {
+ cds_test::thread& thr = pool.get( i );
+ switch ( thr.type()) {
+ case insert_thread:
+ {
+ InserterThread& inserter = static_cast<InserterThread&>( thr );
+ nInsertSuccess += inserter.m_nInsertSuccess;
+ nInsertFailed += inserter.m_nInsertFailed;
+ nTestFunctorRef += inserter.m_nTestFunctorRef;
+ }
+ break;
+ case update_thread:
+ {
+ UpdaterThread& updater = static_cast<UpdaterThread&>(thr);
+ nUpdateCreated += updater.m_nUpdateCreated;
+ nUpdateModified += updater.m_nUpdateExisted;
+ nUpdateFailed += updater.m_nUpdateFailed;
+ nEnsFuncCreated += updater.m_nFunctorCreated;
+ nEnsFuncModified += updater.m_nFunctorModified;
+ }
+ break;
+ case delete_thread:
+ {
+ DeleterThread& deleter = static_cast<DeleterThread&>(thr);
+ nDeleteSuccess += deleter.m_nDeleteSuccess;
+ nDeleteFailed += deleter.m_nDeleteFailed;
+ nDelValueSuccess += deleter.m_nValueSuccess;
+ nDelValueFailed += deleter.m_nValueFailed;
+ }
+ break;
+ }
+ }
+
+ propout()
+ << std::make_pair( "insert_success", nInsertSuccess )
+ << std::make_pair( "delete_success", nDeleteSuccess )
+ << std::make_pair( "insert_failed", nInsertFailed )
+ << std::make_pair( "delete_failed", nDeleteFailed )
+ << std::make_pair( "update_created", nUpdateCreated )
+ << std::make_pair( "update_modified", nUpdateModified )
+ << std::make_pair( "update_failed", nUpdateFailed )
+ << std::make_pair( "final_set_size", testSet.size());
+
+
+ EXPECT_EQ( nDelValueFailed, 0u );
+ EXPECT_EQ( nDelValueSuccess, nDeleteSuccess );
+
+ EXPECT_EQ( nUpdateFailed, 0u );
+ EXPECT_EQ( nUpdateCreated, nEnsFuncCreated );
+ EXPECT_EQ( nUpdateModified, nEnsFuncModified );
+
+ // nTestFunctorRef is call count of insert functor
+ EXPECT_EQ( nTestFunctorRef, nInsertSuccess );
+
+ //testSet.clear();
+ for ( size_t * p = m_pKeyFirst; p != m_pKeyLast; ++p )
+ testSet.erase( *p );
+
+ EXPECT_TRUE( testSet.empty());
+ EXPECT_EQ( testSet.size(), 0u );
+
+ additional_check( testSet );
+ print_stat( propout(), testSet );
+
+ additional_cleanup( testSet );
+ }
+
+ template <class Set>
+ void run_test()
+ {
+ Set s( *this );
+ run_test( s );
+ }
+
+ template <class Set>
+ void run_test2()
+ {
+ Set s( *this );
+ run_test( s );
+
+ for ( auto it = s.begin(); it != s.end(); ++it )
+ std::cout << "key=" << it->key << std::endl;
+ }
+ };
+
+ class Set_InsDel_func_LF: public Set_InsDel_func
+ , public ::testing::WithParamInterface<size_t>
+ {
+ public:
+ template <class Set>
+ void run_test()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Set_InsDel_func::run_test<Set>();
+ }
+
+ template <class Set>
+ void run_test2()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Set_InsDel_func::run_test2<Set>();
+ }
+
+ static std::vector<size_t> get_load_factors();
+ };
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdel_func.h"
+#include "set_type_cuckoo.h"
+
+namespace set {
+
+ //CDSSTRESS_CuckooSet( Set_InsDel_func, run_test, size_t, value )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdel_func.h"
+#include "set_type_ellen_bintree.h"
+
+namespace set {
+
+ CDSSTRESS_EllenBinTreeSet( Set_InsDel_func, run_test, size_t, value )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdel_func.h"
+#include "set_type_feldman_hashset.h"
+
+namespace set {
+
+ CDSSTRESS_FeldmanHashSet_fixed( Set_InsDel_func, run_test, size_t, value )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdel_func.h"
+#include "set_type_michael.h"
+
+namespace set {
+
+ CDSSTRESS_MichaelSet( Set_InsDel_func_LF, run_test2, size_t, value )
+ CDSSTRESS_MichaelIterableSet( Set_InsDel_func_LF, run_test2, size_t, value )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdel_func.h"
+#include "set_type_skip_list.h"
+
+namespace set {
+
+ CDSSTRESS_SkipListSet( Set_InsDel_func, run_test, size_t, value )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdel_func.h"
+#include "set_type_split_list.h"
+
+namespace set {
+
+ CDSSTRESS_SplitListSet( Set_InsDel_func_LF, run_test, size_t, value )
+ CDSSTRESS_SplitListIterableSet( Set_InsDel_func_LF, run_test, size_t, value )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdel_func.h"
+#include "set_type_striped.h"
+
+namespace set {
+
+ //CDSSTRESS_StripedSet( Set_InsDel_func_LF, run_test, size_t, value )
+
+} // namespace set
+
--- /dev/null
+set(PACKAGE_NAME stress-sequential-set-insdel-string)
+
+set(CDSSTRESS_SET_INSDEL_STRING_SOURCES
+ ../../../main.cpp
+ set_insdel_string.cpp
+ set_insdel_string_cuckoo.cpp
+ set_insdel_string_ellentree.cpp
+ set_insdel_string_feldman_hashset.cpp
+ set_insdel_string_michael.cpp
+ set_insdel_string_skip.cpp
+ set_insdel_string_split.cpp
+ set_insdel_string_std.cpp
+ set_insdel_string_striped.cpp
+)
+
+include_directories(
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/..
+)
+
+add_executable(${PACKAGE_NAME} ${CDSSTRESS_SET_INSDEL_STRING_SOURCES})
+target_link_libraries(${PACKAGE_NAME} ${CDS_TEST_LIBRARIES} ${CDSSTRESS_FRAMEWORK_LIBRARY})
+
+add_test(NAME ${PACKAGE_NAME} COMMAND ${PACKAGE_NAME} WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdel_string.h"
+
+namespace set {
+
+ size_t Set_InsDel_string::s_nSetSize = 1000000; // set size
+ size_t Set_InsDel_string::s_nInsertThreadCount = 4; // count of insertion thread
+ size_t Set_InsDel_string::s_nDeleteThreadCount = 4; // count of deletion thread
+ size_t Set_InsDel_string::s_nThreadPassCount = 4; // pass count for each thread
+ size_t Set_InsDel_string::s_nMaxLoadFactor = 8; // maximum load factor
+
+ size_t Set_InsDel_string::s_nCuckooInitialSize = 1024;// initial size for CuckooSet
+ size_t Set_InsDel_string::s_nCuckooProbesetSize = 16; // CuckooSet probeset size (only for list-based probeset)
+ size_t Set_InsDel_string::s_nCuckooProbesetThreshold = 0; // CUckooSet probeset threshold (0 - use default)
+
+ size_t Set_InsDel_string::s_nFeldmanSet_HeadBits = 10;
+ size_t Set_InsDel_string::s_nFeldmanSet_ArrayBits = 4;
+
+ size_t Set_InsDel_string::s_nLoadFactor = 1;
+ std::vector<std::string> Set_InsDel_string::m_arrString;
+
+ void Set_InsDel_string::SetUpTestCase()
+ {
+ cds_test::config const& cfg = get_config( "map_insdel_string" );
+
+ s_nSetSize = cfg.get_size_t( "MapSize", s_nSetSize );
+ if ( s_nSetSize < 1000 )
+ s_nSetSize = 1000;
+
+ s_nInsertThreadCount = cfg.get_size_t( "InsertThreadCount", s_nInsertThreadCount );
+ if ( s_nInsertThreadCount == 0 )
+ s_nInsertThreadCount = 2;
+
+ s_nDeleteThreadCount = cfg.get_size_t( "DeleteThreadCount", s_nDeleteThreadCount );
+ if ( s_nDeleteThreadCount == 0 )
+ s_nDeleteThreadCount = 2;
+
+ s_nThreadPassCount = cfg.get_size_t( "ThreadPassCount", s_nThreadPassCount );
+ if ( s_nThreadPassCount == 0 )
+ s_nThreadPassCount = 4;
+
+ s_nMaxLoadFactor = cfg.get_size_t( "MaxLoadFactor", s_nMaxLoadFactor );
+ if ( s_nMaxLoadFactor == 0 )
+ s_nMaxLoadFactor = 1;
+
+ s_nCuckooInitialSize = cfg.get_size_t( "CuckooInitialSize", s_nCuckooInitialSize );
+ if ( s_nCuckooInitialSize < 256 )
+ s_nCuckooInitialSize = 256;
+
+ s_nCuckooProbesetSize = cfg.get_size_t( "CuckooProbesetSize", s_nCuckooProbesetSize );
+ if ( s_nCuckooProbesetSize < 8 )
+ s_nCuckooProbesetSize = 8;
+
+ s_nCuckooProbesetThreshold = cfg.get_size_t( "CuckooProbesetThreshold", s_nCuckooProbesetThreshold );
+
+ s_nFeldmanSet_HeadBits = cfg.get_size_t( "FeldmanMapHeadBits", s_nFeldmanSet_HeadBits );
+ if ( s_nFeldmanSet_HeadBits == 0 )
+ s_nFeldmanSet_HeadBits = 2;
+
+ s_nFeldmanSet_ArrayBits = cfg.get_size_t( "FeldmanMapArrayBits", s_nFeldmanSet_ArrayBits );
+ if ( s_nFeldmanSet_ArrayBits == 0 )
+ s_nFeldmanSet_ArrayBits = 2;
+
+ // Load string dictionary
+ m_arrString = load_dictionary();
+ }
+
+ void Set_InsDel_string::TearDownTestCase()
+ {
+ m_arrString.clear();
+ }
+
+ std::vector<size_t> Set_InsDel_string_LF::get_load_factors()
+ {
+ cds_test::config const& cfg = get_config( "map_insdel_string" );
+
+ s_nMaxLoadFactor = cfg.get_size_t( "MaxLoadFactor", s_nMaxLoadFactor );
+ if ( s_nMaxLoadFactor == 0 )
+ s_nMaxLoadFactor = 1;
+
+ std::vector<size_t> lf;
+ for ( size_t n = 1; n <= s_nMaxLoadFactor; n *= 2 )
+ lf.push_back( n );
+
+ return lf;
+ }
+
+#ifdef CDSTEST_GTEST_INSTANTIATE_TEST_CASE_P_HAS_4TH_ARG
+ static std::string get_test_parameter_name( testing::TestParamInfo<size_t> const& p )
+ {
+ return std::to_string( p.param );
+ }
+ INSTANTIATE_TEST_CASE_P( a, Set_InsDel_string_LF, ::testing::ValuesIn( Set_InsDel_string_LF::get_load_factors()), get_test_parameter_name );
+#else
+ INSTANTIATE_TEST_CASE_P( a, Set_InsDel_string_LF, ::testing::ValuesIn( Set_InsDel_string_LF::get_load_factors()));
+#endif
+
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_type.h"
+
+namespace set {
+
+#define TEST_CASE(TAG, X) void X();
+
+ class Set_InsDel_string: public cds_test::stress_fixture
+ {
+ public:
+ static size_t s_nSetSize; // set size
+ static size_t s_nInsertThreadCount; // count of insertion thread
+ static size_t s_nDeleteThreadCount; // count of deletion thread
+ static size_t s_nThreadPassCount; // pass count for each thread
+ static size_t s_nMaxLoadFactor; // maximum load factor
+
+ static size_t s_nCuckooInitialSize; // initial size for CuckooSet
+ static size_t s_nCuckooProbesetSize; // CuckooSet probeset size (only for list-based probeset)
+ static size_t s_nCuckooProbesetThreshold; // CUckooSet probeset threshold (0 - use default)
+
+ static size_t s_nFeldmanSet_HeadBits;
+ static size_t s_nFeldmanSet_ArrayBits;
+
+ static size_t s_nLoadFactor;
+ static std::vector<std::string> m_arrString;
+
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+
+ private:
+ typedef std::string key_type;
+ typedef size_t value_type;
+
+ enum {
+ insert_thread,
+ delete_thread,
+ extract_thread
+ };
+
+ template <class Set>
+ class Inserter: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+
+ Set& m_Set;
+ typedef typename Set::value_type keyval_type;
+
+ public:
+ size_t m_nInsertSuccess = 0;
+ size_t m_nInsertFailed = 0;
+
+ public:
+ Inserter( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, insert_thread )
+ , m_Set( set )
+ {}
+
+ Inserter( Inserter& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Inserter( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+
+ Set_InsDel_string& fixture = pool().template fixture<Set_InsDel_string>();
+ size_t nArrSize = m_arrString.size();
+ size_t const nSetSize = fixture.s_nSetSize;
+ size_t const nPassCount = fixture.s_nThreadPassCount;
+
+ if ( id() & 1 ) {
+ for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) {
+ for ( size_t nItem = 0; nItem < nSetSize; ++nItem ) {
+ if ( rSet.insert( keyval_type( m_arrString[nItem % nArrSize], nItem * 8 )))
+ ++m_nInsertSuccess;
+ else
+ ++m_nInsertFailed;
+ }
+ }
+ }
+ else {
+ for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) {
+ for ( size_t nItem = nSetSize; nItem > 0; --nItem ) {
+ if ( rSet.insert( keyval_type( m_arrString[nItem % nArrSize], nItem * 8 )))
+ ++m_nInsertSuccess;
+ else
+ ++m_nInsertFailed;
+ }
+ }
+ }
+ }
+ };
+
+ template <class Set>
+ class Deleter: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+
+ Set& m_Set;
+ public:
+ size_t m_nDeleteSuccess = 0;
+ size_t m_nDeleteFailed = 0;
+
+ public:
+ Deleter( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, delete_thread )
+ , m_Set( set )
+ {}
+
+ Deleter( Deleter& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Deleter( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+
+ Set_InsDel_string& fixture = pool().template fixture<Set_InsDel_string>();
+ size_t nArrSize = m_arrString.size();
+ size_t const nSetSize = fixture.s_nSetSize;
+ size_t const nPassCount = fixture.s_nThreadPassCount;
+
+ if ( id() & 1 ) {
+ for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) {
+ for ( size_t nItem = 0; nItem < nSetSize; ++nItem ) {
+ if ( rSet.erase( m_arrString[nItem % nArrSize] ))
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ }
+ }
+ }
+ else {
+ for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) {
+ for ( size_t nItem = nSetSize; nItem > 0; --nItem ) {
+ if ( rSet.erase( m_arrString[nItem % nArrSize] ))
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ }
+ }
+ }
+ }
+ };
+
+ template <typename GC, class Set>
+ class Extractor: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Set& m_Set;
+
+ public:
+ size_t m_nDeleteSuccess = 0;
+ size_t m_nDeleteFailed = 0;
+
+ public:
+ Extractor( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, extract_thread )
+ , m_Set( set )
+ {}
+
+ Extractor( Extractor& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Extractor( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+
+ typename Set::guarded_ptr gp;
+
+ Set_InsDel_string& fixture = pool().template fixture<Set_InsDel_string>();
+ size_t nArrSize = m_arrString.size();
+ size_t const nSetSize = fixture.s_nSetSize;
+ size_t const nPassCount = fixture.s_nThreadPassCount;
+
+ if ( id() & 1 ) {
+ for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) {
+ for ( size_t nItem = 0; nItem < nSetSize; ++nItem ) {
+ gp = rSet.extract( m_arrString[nItem % nArrSize] );
+ if ( gp )
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ gp.release();
+ }
+ }
+ }
+ else {
+ for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) {
+ for ( size_t nItem = nSetSize; nItem > 0; --nItem ) {
+ gp = rSet.extract( m_arrString[nItem % nArrSize] );
+ if ( gp )
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ gp.release();
+ }
+ }
+ }
+ }
+ };
+
+ template <typename RCU, class Set>
+ class Extractor<cds::urcu::gc<RCU>, Set >: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Set& m_Set;
+
+ public:
+ size_t m_nDeleteSuccess = 0;
+ size_t m_nDeleteFailed = 0;
+
+ public:
+ Extractor( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, extract_thread )
+ , m_Set( set )
+ {}
+
+ Extractor( Extractor& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Extractor( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+
+ typename Set::exempt_ptr xp;
+
+ Set_InsDel_string& fixture = pool().template fixture<Set_InsDel_string>();
+ size_t nArrSize = m_arrString.size();
+ size_t const nSetSize = fixture.s_nSetSize;
+ size_t const nPassCount = fixture.s_nThreadPassCount;
+
+ if ( id() & 1 ) {
+ for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) {
+ for ( size_t nItem = 0; nItem < nSetSize; ++nItem ) {
+ if ( Set::c_bExtractLockExternal ) {
+ typename Set::rcu_lock l;
+ xp = rSet.extract( m_arrString[nItem % nArrSize] );
+ if ( xp )
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ }
+ else {
+ xp = rSet.extract( m_arrString[nItem % nArrSize] );
+ if ( xp )
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ }
+ xp.release();
+ }
+ }
+ }
+ else {
+ for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) {
+ for ( size_t nItem = nSetSize; nItem > 0; --nItem ) {
+ if ( Set::c_bExtractLockExternal ) {
+ typename Set::rcu_lock l;
+ xp = rSet.extract( m_arrString[nItem % nArrSize] );
+ if ( xp )
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ }
+ else {
+ xp = rSet.extract( m_arrString[nItem % nArrSize] );
+ if ( xp )
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ }
+ xp.release();
+ }
+ }
+ }
+ }
+ };
+
+ protected:
+ template <class Set>
+ void do_test( Set& testSet )
+ {
+ typedef Inserter<Set> InserterThread;
+ typedef Deleter<Set> DeleterThread;
+
+ cds_test::thread_pool& pool = get_pool();
+ pool.add( new InserterThread( pool, testSet ), s_nInsertThreadCount );
+ pool.add( new DeleterThread( pool, testSet ), s_nDeleteThreadCount );
+
+ propout() << std::make_pair( "insert_thread_count", s_nInsertThreadCount )
+ << std::make_pair( "delete_thread_count", s_nDeleteThreadCount )
+ << std::make_pair( "thread_pass_count", s_nThreadPassCount )
+ << std::make_pair( "set_size", s_nSetSize );
+
+ std::chrono::milliseconds duration = pool.run();
+
+ propout() << std::make_pair( "duration", duration );
+
+ size_t nInsertSuccess = 0;
+ size_t nInsertFailed = 0;
+ size_t nDeleteSuccess = 0;
+ size_t nDeleteFailed = 0;
+ for ( size_t i = 0; i < pool.size(); ++i ) {
+ cds_test::thread& thr = pool.get( i );
+ switch ( thr.type()) {
+ case insert_thread:
+ {
+ InserterThread& inserter = static_cast<InserterThread&>( thr );
+ nInsertSuccess += inserter.m_nInsertSuccess;
+ nInsertFailed += inserter.m_nInsertFailed;
+ }
+ break;
+ case delete_thread:
+ {
+ DeleterThread& deleter = static_cast<DeleterThread&>(thr);
+ nDeleteSuccess += deleter.m_nDeleteSuccess;
+ nDeleteFailed += deleter.m_nDeleteFailed;
+ }
+ break;
+ default:
+ assert( false ); // Forgot anything?..
+ }
+ }
+
+ propout()
+ << std::make_pair( "insert_success", nInsertSuccess )
+ << std::make_pair( "delete_success", nDeleteSuccess )
+ << std::make_pair( "insert_failed", nInsertFailed )
+ << std::make_pair( "delete_failed", nDeleteFailed )
+ << std::make_pair( "final_set_size", testSet.size());
+
+ //testSet.clear();
+ for (auto const& str: m_arrString )
+ testSet.erase( str );
+ EXPECT_TRUE( testSet.empty());
+ EXPECT_EQ( testSet.size(), 0u );
+
+ additional_check( testSet );
+ print_stat( propout(), testSet );
+ additional_cleanup( testSet );
+ }
+
+ template <class Set>
+ void do_test_extract( Set& testSet )
+ {
+ typedef Inserter<Set> InserterThread;
+ typedef Deleter<Set> DeleterThread;
+ typedef Extractor<typename Set::gc, Set> ExtractThread;
+
+ size_t const nDelThreadCount = s_nDeleteThreadCount / 2;
+ size_t const nExtractThreadCount = s_nDeleteThreadCount - nDelThreadCount;
+
+ cds_test::thread_pool& pool = get_pool();
+ pool.add( new InserterThread( pool, testSet ), s_nInsertThreadCount );
+ pool.add( new DeleterThread( pool, testSet ), nDelThreadCount );
+ pool.add( new ExtractThread( pool, testSet ), nExtractThreadCount );
+
+ propout() << std::make_pair( "insert_thread_count", s_nInsertThreadCount )
+ << std::make_pair( "delete_thread_count", nDelThreadCount )
+ << std::make_pair( "extract_thread_count", nExtractThreadCount )
+ << std::make_pair( "thread_pass_count", s_nThreadPassCount )
+ << std::make_pair( "set_size", s_nSetSize );
+
+ std::chrono::milliseconds duration = pool.run();
+
+ propout() << std::make_pair( "duration", duration );
+
+ size_t nInsertSuccess = 0;
+ size_t nInsertFailed = 0;
+ size_t nDeleteSuccess = 0;
+ size_t nDeleteFailed = 0;
+ size_t nExtractSuccess = 0;
+ size_t nExtractFailed = 0;
+ for ( size_t i = 0; i < pool.size(); ++i ) {
+ cds_test::thread& thr = pool.get( i );
+ switch ( thr.type()) {
+ case insert_thread:
+ {
+ InserterThread& inserter = static_cast<InserterThread&>(thr);
+ nInsertSuccess += inserter.m_nInsertSuccess;
+ nInsertFailed += inserter.m_nInsertFailed;
+ }
+ break;
+ case delete_thread:
+ {
+ DeleterThread& deleter = static_cast<DeleterThread&>(thr);
+ nDeleteSuccess += deleter.m_nDeleteSuccess;
+ nDeleteFailed += deleter.m_nDeleteFailed;
+ }
+ break;
+ case extract_thread:
+ {
+ ExtractThread& extractor = static_cast<ExtractThread&>(thr);
+ nExtractSuccess += extractor.m_nDeleteSuccess;
+ nExtractFailed += extractor.m_nDeleteFailed;
+ }
+ break;
+ default:
+ assert( false ); // Forgot anything?..
+ }
+ }
+
+ propout()
+ << std::make_pair( "insert_success", nInsertSuccess )
+ << std::make_pair( "delete_success", nDeleteSuccess )
+ << std::make_pair( "extract_success", nExtractSuccess )
+ << std::make_pair( "insert_failed", nInsertFailed )
+ << std::make_pair( "delete_failed", nDeleteFailed )
+ << std::make_pair( "extract_failed", nExtractFailed )
+ << std::make_pair( "final_set_size", testSet.size());
+
+ //testSet.clear();
+ for ( auto const& str : m_arrString )
+ testSet.erase( str );
+ EXPECT_TRUE( testSet.empty());
+ EXPECT_EQ( testSet.size(), 0u );
+
+ additional_check( testSet );
+ print_stat( propout(), testSet );
+ additional_cleanup( testSet );
+ }
+
+ template <class Set>
+ void run_test()
+ {
+ ASSERT_TRUE( m_arrString.size() > 0 );
+
+ Set s( *this );
+ do_test( s );
+ }
+
+ template <class Set>
+ void run_test_extract()
+ {
+ ASSERT_TRUE( m_arrString.size() > 0 );
+
+ Set s( *this );
+ do_test_extract( s );
+ }
+ };
+
+ class Set_InsDel_string_LF: public Set_InsDel_string
+ , public ::testing::WithParamInterface<size_t>
+ {
+ public:
+ template <class Set>
+ void run_test()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Set_InsDel_string::run_test<Set>();
+ }
+
+ template <class Set>
+ void run_test_extract()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Set_InsDel_string::run_test_extract<Set>();
+ }
+
+ static std::vector<size_t> get_load_factors();
+ };
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdel_string.h"
+#include "set_type_cuckoo.h"
+
+namespace set {
+
+ //CDSSTRESS_CuckooSet( Set_InsDel_string, run_test, std::string, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdel_string.h"
+#include "set_type_ellen_bintree.h"
+
+namespace set {
+
+ CDSSTRESS_EllenBinTreeSet( Set_InsDel_string, run_test_extract, std::string, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdel_string.h"
+#include "set_type_feldman_hashset.h"
+
+namespace set {
+
+ CDSSTRESS_FeldmanHashSet_stdhash( Set_InsDel_string, run_test_extract, std::string, size_t )
+ CDSSTRESS_FeldmanHashSet_city( Set_InsDel_string, run_test_extract, std::string, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdel_string.h"
+#include "set_type_michael.h"
+
+namespace set {
+
+ CDSSTRESS_MichaelSet( Set_InsDel_string_LF, run_test_extract, std::string, size_t )
+ CDSSTRESS_MichaelIterableSet( Set_InsDel_string_LF, run_test_extract, std::string, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdel_string.h"
+#include "set_type_skip_list.h"
+
+namespace set {
+
+ CDSSTRESS_SkipListSet( Set_InsDel_string, run_test_extract, std::string, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdel_string.h"
+#include "set_type_split_list.h"
+
+namespace set {
+
+ CDSSTRESS_SplitListSet( Set_InsDel_string_LF, run_test_extract, std::string, size_t )
+ CDSSTRESS_SplitListIterableSet( Set_InsDel_string_LF, run_test_extract, std::string, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdel_string.h"
+#include "set_type_std.h"
+
+namespace set {
+ //CDSSTRESS_StdSet( Set_InsDel_string, run_test, std::string, size_t )
+} // namespace set
+
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_insdel_string.h"
+#include "set_type_striped.h"
+
+namespace set {
+
+ //CDSSTRESS_StripedSet( Set_InsDel_string_LF, run_test, std::string, size_t )
+
+} // namespace set
+
--- /dev/null
+set(PACKAGE_NAME stress-sequential-set-iter-erase)
+
+set(CDSSTRESS_SET_ITER_ERASE_SOURCES
+ ../../../main.cpp
+ set_iter_erase.cpp
+ set_iter_erase_feldman_hashset.cpp
+ set_iter_erase_michael.cpp
+ set_iter_erase_split.cpp
+)
+
+include_directories(
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/..
+)
+
+add_executable(${PACKAGE_NAME} ${CDSSTRESS_SET_ITER_ERASE_SOURCES})
+target_link_libraries(${PACKAGE_NAME} ${CDS_TEST_LIBRARIES} ${CDSSTRESS_FRAMEWORK_LIBRARY})
+
+add_test(NAME ${PACKAGE_NAME} COMMAND ${PACKAGE_NAME} WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_iter_erase.h"
+
+namespace set {
+
+ size_t Set_Iter_Del3::s_nSetSize = 5000;
+ size_t Set_Iter_Del3::s_nInsThreadCount = 4;
+ size_t Set_Iter_Del3::s_nDelThreadCount = 4;
+ size_t Set_Iter_Del3::s_nExtractThreadCount = 4;
+ size_t Set_Iter_Del3::s_nFindThreadCount = 2;
+ size_t Set_Iter_Del3::s_nMaxLoadFactor = 4;
+ size_t Set_Iter_Del3::s_nInsertPassCount = 1000;
+
+ size_t Set_Iter_Del3::s_nFeldmanSet_HeadBits = 8;
+ size_t Set_Iter_Del3::s_nFeldmanSet_ArrayBits = 8;
+
+ size_t Set_Iter_Del3::s_nLoadFactor = 1;
+ std::vector<size_t> Set_Iter_Del3::m_arrData;
+
+ void Set_Iter_Del3::SetUpTestCase()
+ {
+ cds_test::config const& cfg = get_config( "map_iter_erase" );
+
+ s_nSetSize = cfg.get_size_t( "MapSize", s_nSetSize );
+ if ( s_nSetSize < 1000 )
+ s_nSetSize = 1000;
+
+ s_nInsThreadCount = cfg.get_size_t( "InsThreadCount", s_nInsThreadCount );
+ if ( s_nInsThreadCount == 0 )
+ s_nInsThreadCount = 1;
+
+ s_nDelThreadCount = cfg.get_size_t( "DelThreadCount", s_nDelThreadCount );
+ s_nExtractThreadCount = cfg.get_size_t( "ExtractThreadCount", s_nExtractThreadCount );
+ s_nFindThreadCount = cfg.get_size_t( "FindThreadCount", s_nFindThreadCount );
+
+ s_nMaxLoadFactor = cfg.get_size_t( "MaxLoadFactor", s_nMaxLoadFactor );
+ if ( s_nMaxLoadFactor == 0 )
+ s_nMaxLoadFactor = 1;
+
+ s_nInsertPassCount = cfg.get_size_t( "PassCount", s_nInsertPassCount );
+ if ( s_nInsertPassCount == 0 )
+ s_nInsertPassCount = 1000;
+
+ s_nFeldmanSet_HeadBits = cfg.get_size_t( "FeldmanMapHeadBits", s_nFeldmanSet_HeadBits );
+ if ( s_nFeldmanSet_HeadBits == 0 )
+ s_nFeldmanSet_HeadBits = 8;
+
+ s_nFeldmanSet_ArrayBits = cfg.get_size_t( "FeldmanMapArrayBits", s_nFeldmanSet_ArrayBits );
+ if ( s_nFeldmanSet_ArrayBits == 0 )
+ s_nFeldmanSet_ArrayBits = 8;
+
+ m_arrData.resize( s_nSetSize );
+ for ( size_t i = 0; i < s_nSetSize; ++i )
+ m_arrData[i] = i;
+ shuffle( m_arrData.begin(), m_arrData.end());
+ }
+
+ void Set_Iter_Del3::TearDownTestCase()
+ {
+ m_arrData.clear();
+ }
+
+ std::vector<size_t> Set_Iter_Del3_LF::get_load_factors()
+ {
+ cds_test::config const& cfg = get_config( "map_iter_erase" );
+
+ s_nMaxLoadFactor = cfg.get_size_t( "MaxLoadFactor", s_nMaxLoadFactor );
+ if ( s_nMaxLoadFactor == 0 )
+ s_nMaxLoadFactor = 1;
+
+ std::vector<size_t> lf;
+ for ( size_t n = 1; n <= s_nMaxLoadFactor; n *= 2 )
+ lf.push_back( n );
+
+ return lf;
+ }
+
+#ifdef CDSTEST_GTEST_INSTANTIATE_TEST_CASE_P_HAS_4TH_ARG
+ static std::string get_test_parameter_name( testing::TestParamInfo<size_t> const& p )
+ {
+ return std::to_string( p.param );
+ }
+ INSTANTIATE_TEST_CASE_P( a, Set_Iter_Del3_LF, ::testing::ValuesIn( Set_Iter_Del3_LF::get_load_factors()), get_test_parameter_name );
+#else
+ INSTANTIATE_TEST_CASE_P( a, Set_Iter_Del3_LF, ::testing::ValuesIn( Set_Iter_Del3_LF::get_load_factors()));
+#endif
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_type.h"
+#include <cds/os/topology.h>
+
+namespace set {
+
+ struct key_thread
+ {
+ uint32_t nKey;
+ uint16_t nThread;
+
+ key_thread( size_t key, size_t threadNo )
+ : nKey( static_cast<uint32_t>(key))
+ , nThread( static_cast<uint16_t>(threadNo))
+ {}
+
+ key_thread()
+ : nKey()
+ , nThread()
+ {}
+ };
+
+ static_assert(sizeof( key_thread ) % 8 == 0, "Key type size mismatch");
+
+ typedef set_type_base<key_thread, size_t>::key_val key_value_pair;
+
+ template <>
+ struct cmp<key_thread> {
+ int operator ()(key_thread const& k1, key_thread const& k2) const
+ {
+ if ( k1.nKey < k2.nKey )
+ return -1;
+ if ( k1.nKey > k2.nKey )
+ return 1;
+ if ( k1.nThread < k2.nThread )
+ return -1;
+ if ( k1.nThread > k2.nThread )
+ return 1;
+ return 0;
+ }
+ int operator ()(key_thread const& k1, size_t k2) const
+ {
+ if ( k1.nKey < k2 )
+ return -1;
+ if ( k1.nKey > k2 )
+ return 1;
+ return 0;
+ }
+ int operator ()(size_t k1, key_thread const& k2) const
+ {
+ if ( k1 < k2.nKey )
+ return -1;
+ if ( k1 > k2.nKey )
+ return 1;
+ return 0;
+ }
+ };
+
+ template <>
+ struct less<set::key_thread>
+ {
+ bool operator()( set::key_thread const& k1, set::key_thread const& k2 ) const
+ {
+ if ( k1.nKey <= k2.nKey )
+ return k1.nKey < k2.nKey || k1.nThread < k2.nThread;
+ return false;
+ }
+ };
+
+ template <>
+ struct hash<set::key_thread>
+ {
+ typedef size_t result_type;
+ typedef set::key_thread argument_type;
+
+ size_t operator()( set::key_thread const& k ) const
+ {
+ return std::hash<size_t>()(k.nKey);
+ }
+
+ size_t operator()( size_t k ) const
+ {
+ return std::hash<size_t>()(k);
+ }
+ };
+
+
+ class Set_Iter_Del3: public cds_test::stress_fixture
+ {
+ public:
+ static size_t s_nSetSize; // max set size
+ static size_t s_nInsThreadCount; // insert thread count
+ static size_t s_nDelThreadCount; // delete thread count
+ static size_t s_nExtractThreadCount; // extract thread count
+ static size_t s_nMaxLoadFactor; // maximum load factor
+ static size_t s_nInsertPassCount;
+ static size_t s_nFindThreadCount; // find thread count
+
+ static size_t s_nFeldmanSet_HeadBits;
+ static size_t s_nFeldmanSet_ArrayBits;
+
+ static size_t s_nLoadFactor;
+
+ static std::vector<size_t> m_arrData;
+
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+
+ template <typename Pred>
+ static void prepare_array( std::vector<size_t>& arr, Pred pred )
+ {
+ arr.reserve( m_arrData.size());
+ for ( auto el : m_arrData ) {
+ if ( pred( el ))
+ arr.push_back( el );
+ }
+ arr.resize( arr.size());
+ shuffle( arr.begin(), arr.end());
+ }
+
+ protected:
+ typedef key_thread key_type;
+ typedef size_t value_type;
+
+ atomics::atomic<size_t> m_nInsThreadCount;
+
+ enum {
+ inserter_thread,
+ deleter_thread,
+ extractor_thread,
+ find_thread
+ };
+
+
+ // Inserts keys from [0..N)
+ template <class Set>
+ class Inserter: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Set& m_Set;
+
+ struct update_functor
+ {
+ template <typename Q>
+ void operator()( bool /*bNew*/, key_value_pair const&, Q const& ) const
+ {}
+
+ void operator()(key_value_pair& /*cur*/, key_value_pair * /*prev*/) const
+ {}
+ };
+
+ void init_data()
+ {
+ prepare_array( m_arr, []( size_t ) -> bool { return true; } );
+ for ( size_t i = 0; i < m_arr.size(); ++i ) {
+ if ( m_Set.insert( key_type( m_arr[i], id())))
+ ++m_nInsertInitSuccess;
+ else
+ ++m_nInsertInitFailed;
+ }
+ }
+
+ public:
+ size_t m_nInsertSuccess = 0;
+ size_t m_nInsertFailed = 0;
+ size_t m_nInsertInitSuccess = 0;
+ size_t m_nInsertInitFailed = 0;
+
+ std::vector<size_t> m_arr;
+
+ public:
+ Inserter( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, inserter_thread )
+ , m_Set( set )
+ {
+ init_data();
+ }
+
+ Inserter( Inserter& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {
+ init_data();
+ }
+
+ virtual thread * clone()
+ {
+ return new Inserter( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+ Set_Iter_Del3& fixture = pool().template fixture<Set_Iter_Del3>();
+
+ for ( size_t nPass = 0; nPass < s_nInsertPassCount; ++nPass ) {
+ if ( nPass & 1 ) {
+ // insert pass
+ for ( auto el : m_arr ) {
+ if ( el & 3 ) {
+ if ( rSet.insert( key_type( el, id())))
+ ++m_nInsertSuccess;
+ else
+ ++m_nInsertFailed;
+ }
+ }
+ }
+ else {
+ // update pass
+ for ( auto el : m_arr ) {
+ if ( el & 3 ) {
+ bool success;
+ bool inserted;
+ std::tie( success, inserted ) = rSet.update( key_type( el, id()), update_functor());
+ if ( success && inserted )
+ ++m_nInsertSuccess;
+ else
+ ++m_nInsertFailed;
+ }
+ }
+ }
+ }
+
+ fixture.m_nInsThreadCount.fetch_sub( 1, atomics::memory_order_release );
+ m_arr.resize( 0 );
+ }
+ };
+
+ struct key_equal {
+ bool operator()( key_type const& k1, key_type const& k2 ) const
+ {
+ return k1.nKey == k2.nKey;
+ }
+ bool operator()( size_t k1, key_type const& k2 ) const
+ {
+ return k1 == k2.nKey;
+ }
+ bool operator()( key_type const& k1, size_t k2 ) const
+ {
+ return k1.nKey == k2;
+ }
+ bool operator ()( key_value_pair const& k1, key_value_pair const& k2 ) const
+ {
+ return operator()( k1.key, k2.key );
+ }
+ bool operator ()( key_value_pair const& k1, key_type const& k2 ) const
+ {
+ return operator()( k1.key, k2 );
+ }
+ bool operator ()( key_type const& k1, key_value_pair const& k2 ) const
+ {
+ return operator()( k1, k2.key );
+ }
+ bool operator ()( key_value_pair const& k1, size_t k2 ) const
+ {
+ return operator()( k1.key, k2 );
+ }
+ bool operator ()( size_t k1, key_value_pair const& k2 ) const
+ {
+ return operator()( k1, k2.key );
+ }
+ };
+
+ struct key_less {
+ bool operator()( key_type const& k1, key_type const& k2 ) const
+ {
+ return k1.nKey < k2.nKey;
+ }
+ bool operator()( size_t k1, key_type const& k2 ) const
+ {
+ return k1 < k2.nKey;
+ }
+ bool operator()( key_type const& k1, size_t k2 ) const
+ {
+ return k1.nKey < k2;
+ }
+ bool operator ()( key_value_pair const& k1, key_value_pair const& k2 ) const
+ {
+ return operator()( k1.key, k2.key );
+ }
+ bool operator ()( key_value_pair const& k1, key_type const& k2 ) const
+ {
+ return operator()( k1.key, k2 );
+ }
+ bool operator ()( key_type const& k1, key_value_pair const& k2 ) const
+ {
+ return operator()( k1, k2.key );
+ }
+ bool operator ()( key_value_pair const& k1, size_t k2 ) const
+ {
+ return operator()( k1.key, k2 );
+ }
+ bool operator ()( size_t k1, key_value_pair const& k2 ) const
+ {
+ return operator()( k1, k2.key );
+ }
+
+ typedef key_equal equal_to;
+ };
+
+ // Deletes keys from [0..N)
+ template <class Set, typename Iterator>
+ class Deleter: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Set& m_Set;
+
+ public:
+ size_t m_nDeleteSuccess = 0;
+ size_t m_nDeleteFailed = 0;
+
+ public:
+ Deleter( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, deleter_thread )
+ , m_Set( set )
+ {}
+
+ Deleter( Deleter& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Deleter( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+
+ Set_Iter_Del3& fixture = pool().template fixture<Set_Iter_Del3>();
+
+ do {
+ auto itEnd = rSet.template get_end<Iterator>();
+ for ( auto it = rSet.template get_begin<Iterator>(); it != itEnd; ++it ) {
+ if ( it->key.nKey & 3 ) {
+ if ( rSet.erase_at( it ))
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ }
+ }
+ } while ( fixture.m_nInsThreadCount.load( atomics::memory_order_acquire ) != 0 );
+ }
+ };
+
+ // Extracts keys from [0..N)
+ template <typename GC, class Set>
+ class Extractor: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Set& m_Set;
+
+ std::vector<size_t> m_arr;
+
+ void init_data()
+ {
+ prepare_array( m_arr, []( size_t el ) ->bool { return ( el & 3 ) != 0; } );
+ }
+
+ public:
+ size_t m_nExtractSuccess = 0;
+ size_t m_nExtractFailed = 0;
+
+ public:
+ Extractor( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, extractor_thread )
+ , m_Set( set )
+ {
+ init_data();
+ }
+
+ Extractor( Extractor& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {
+ init_data();
+ }
+
+ virtual thread * clone()
+ {
+ return new Extractor( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+ typename Set::guarded_ptr gp;
+
+ Set_Iter_Del3& fixture = pool().template fixture<Set_Iter_Del3>();
+ size_t const nInsThreadCount = s_nInsThreadCount;
+
+ do {
+ if ( id() & 1 ) {
+ for ( auto el : m_arr ) {
+ for ( size_t k = 0; k < nInsThreadCount; ++k ) {
+ gp = rSet.extract( key_type( el, k ));
+ if ( gp )
+ ++m_nExtractSuccess;
+ else
+ ++m_nExtractFailed;
+ gp.release();
+ }
+ }
+ }
+ else {
+ for ( size_t k = 0; k < nInsThreadCount; ++k ) {
+ for ( auto el : m_arr ) {
+ gp = rSet.extract( key_type( el, k ));
+ if ( gp )
+ ++m_nExtractSuccess;
+ else
+ ++m_nExtractFailed;
+ gp.release();
+ }
+ }
+ }
+ } while ( fixture.m_nInsThreadCount.load( atomics::memory_order_acquire ) != 0 );
+
+ m_arr.resize( 0 );
+ }
+ };
+
+ template <typename RCU, class Set>
+ class Extractor< cds::urcu::gc<RCU>, Set >: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Set& m_Set;
+ std::vector<size_t> m_arr;
+
+ void init_data()
+ {
+ prepare_array( m_arr, []( size_t el ) -> bool { return ( el & 3 ) != 0; } );
+ }
+
+ public:
+ size_t m_nExtractSuccess = 0;
+ size_t m_nExtractFailed = 0;
+
+ public:
+ Extractor( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, extractor_thread )
+ , m_Set( set )
+ {
+ init_data();
+ }
+
+ Extractor( Extractor& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {
+ init_data();
+ }
+
+ virtual thread * clone()
+ {
+ return new Extractor( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+ typename Set::exempt_ptr xp;
+
+ Set_Iter_Del3& fixture = pool().template fixture<Set_Iter_Del3>();
+ size_t const nInsThreadCount = fixture.s_nInsThreadCount;
+
+ do {
+ if ( id() & 1 ) {
+ for ( size_t k = 0; k < nInsThreadCount; ++k ) {
+ for ( auto el : m_arr ) {
+ if ( Set::c_bExtractLockExternal ) {
+ typename Set::rcu_lock l;
+ xp = rSet.extract( key_type( el, k ));
+ if ( xp )
+ ++m_nExtractSuccess;
+ else
+ ++m_nExtractFailed;
+ }
+ else {
+ xp = rSet.extract( key_type( el, k ));
+ if ( xp )
+ ++m_nExtractSuccess;
+ else
+ ++m_nExtractFailed;
+ }
+ xp.release();
+ }
+ }
+ }
+ else {
+ for ( auto el : m_arr ) {
+ for ( size_t k = 0; k < nInsThreadCount; ++k ) {
+ if ( Set::c_bExtractLockExternal ) {
+ typename Set::rcu_lock l;
+ xp = rSet.extract( key_type( el, k ));
+ if ( xp )
+ ++m_nExtractSuccess;
+ else
+ ++m_nExtractFailed;
+ }
+ else {
+ xp = rSet.extract( key_type( el, k ));
+ if ( xp )
+ ++m_nExtractSuccess;
+ else
+ ++m_nExtractFailed;
+ }
+ xp.release();
+ }
+ }
+ }
+ } while ( fixture.m_nInsThreadCount.load( atomics::memory_order_acquire ) != 0 );
+
+ m_arr.resize( 0 );
+ }
+ };
+
+ // Finds keys
+ template <class Set>
+ class Observer: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Set& m_Set;
+
+ public:
+ size_t m_nFindEvenSuccess = 0;
+ size_t m_nFindEvenFailed = 0;
+ size_t m_nFindOddSuccess = 0;
+ size_t m_nFindOddFailed = 0;
+
+ public:
+ Observer( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, find_thread )
+ , m_Set( set )
+ {}
+
+ Observer( Observer& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Observer( *this );
+ }
+
+ virtual void test()
+ {
+ Set& set = m_Set;
+ Set_Iter_Del3& fixture = pool().template fixture<Set_Iter_Del3>();
+ std::vector<size_t> const& arr = m_arrData;
+ size_t const nInsThreadCount = s_nInsThreadCount;
+
+ do {
+ for ( size_t key : arr ) {
+ if ( key & 3 ) {
+ for ( size_t k = 0; k < nInsThreadCount; ++k ) {
+ if ( set.contains( key_thread( key, k )))
+ ++m_nFindOddSuccess;
+ else
+ ++m_nFindOddFailed;
+ }
+ }
+ else {
+ // that keys MUST be in the map
+ for ( size_t k = 0; k < nInsThreadCount; ++k ) {
+ if ( set.contains( key_thread( key, k )))
+ ++m_nFindEvenSuccess;
+ else
+ ++m_nFindEvenFailed;
+ }
+ }
+ }
+ } while ( fixture.m_nInsThreadCount.load( atomics::memory_order_acquire ) != 0 );
+ }
+ };
+
+ protected:
+ template <typename Iterator, class Set>
+ void do_test_with( Set& testSet )
+ {
+ typedef Inserter<Set> insert_thread;
+ typedef Deleter<Set, Iterator> delete_thread;
+ typedef Observer<Set> observer_thread;
+
+ m_nInsThreadCount.store( s_nInsThreadCount, atomics::memory_order_release );
+
+ cds_test::thread_pool& pool = get_pool();
+ pool.add( new insert_thread( pool, testSet ), s_nInsThreadCount );
+ pool.add( new delete_thread( pool, testSet ), s_nDelThreadCount ? s_nDelThreadCount : cds::OS::topology::processor_count());
+ if ( s_nFindThreadCount )
+ pool.add( new observer_thread( pool, testSet ), s_nFindThreadCount );
+
+ propout() << std::make_pair( "insert_thread_count", s_nInsThreadCount )
+ << std::make_pair( "delete_thread_count", s_nDelThreadCount )
+ << std::make_pair( "find_thread_count", s_nFindThreadCount )
+ << std::make_pair( "set_size", s_nSetSize )
+ << std::make_pair( "pass_count", s_nInsertPassCount );
+
+ std::chrono::milliseconds duration = pool.run();
+
+ propout() << std::make_pair( "duration", duration );
+
+ size_t nInsertInitFailed = 0;
+ size_t nInsertInitSuccess = 0;
+ size_t nInsertSuccess = 0;
+ size_t nInsertFailed = 0;
+ size_t nDeleteSuccess = 0;
+ size_t nDeleteFailed = 0;
+
+ size_t nFindEvenSuccess = 0;
+ size_t nFindEvenFailed = 0;
+ size_t nFindOddSuccess = 0;
+ size_t nFindOddFailed = 0;
+
+ for ( size_t i = 0; i < pool.size(); ++i ) {
+ cds_test::thread& thr = pool.get( i );
+ switch ( thr.type()) {
+ case inserter_thread:
+ {
+ insert_thread& inserter = static_cast<insert_thread&>(thr);
+ nInsertSuccess += inserter.m_nInsertSuccess;
+ nInsertFailed += inserter.m_nInsertFailed;
+ nInsertInitSuccess += inserter.m_nInsertInitSuccess;
+ nInsertInitFailed += inserter.m_nInsertInitFailed;
+ }
+ break;
+ case deleter_thread:
+ {
+ delete_thread& deleter = static_cast<delete_thread&>(thr);
+ nDeleteSuccess += deleter.m_nDeleteSuccess;
+ nDeleteFailed += deleter.m_nDeleteFailed;
+ }
+ break;
+ case find_thread:
+ {
+ observer_thread& observer = static_cast<observer_thread&>( thr );
+ nFindEvenSuccess = observer.m_nFindEvenSuccess;
+ nFindEvenFailed = observer.m_nFindEvenFailed;
+ nFindOddSuccess = observer.m_nFindOddSuccess;
+ nFindOddFailed = observer.m_nFindOddFailed;
+ }
+ break;
+ default:
+ assert( false );
+ }
+ }
+
+ size_t const nInitialOddKeys = ( s_nSetSize * s_nInsThreadCount ) * 3 / 4;
+
+ EXPECT_EQ( nInsertInitFailed, 0u );
+ EXPECT_EQ( nInsertInitSuccess, s_nSetSize * s_nInsThreadCount );
+ EXPECT_EQ( nFindEvenFailed, 0u );
+ EXPECT_GE( nInsertSuccess + nInitialOddKeys, nDeleteSuccess );
+ EXPECT_LE( nInsertSuccess, nDeleteSuccess );
+
+ propout()
+ << std::make_pair( "insert_init_success", nInsertInitSuccess )
+ << std::make_pair( "insert_init_failed", nInsertInitFailed )
+ << std::make_pair( "insert_success", nInsertSuccess )
+ << std::make_pair( "insert_failed", nInsertFailed )
+ << std::make_pair( "delete_success", nDeleteSuccess )
+ << std::make_pair( "delete_failed", nDeleteFailed )
+ << std::make_pair( "find_even_success", nFindEvenSuccess )
+ << std::make_pair( "find_even_failed", nFindEvenFailed )
+ << std::make_pair( "find_odd_success", nFindOddSuccess )
+ << std::make_pair( "find_odd_failed", nFindOddFailed );
+ }
+
+ template <typename Iterator, class Set>
+ void do_test_extract_with( Set& testSet )
+ {
+ typedef Inserter<Set> insert_thread;
+ typedef Deleter<Set, Iterator> delete_thread;
+ typedef Extractor< typename Set::gc, Set > extract_thread;
+ typedef Observer<Set> observer_thread;
+
+ m_nInsThreadCount.store( s_nInsThreadCount, atomics::memory_order_release );
+
+ cds_test::thread_pool& pool = get_pool();
+ pool.add( new insert_thread( pool, testSet ), s_nInsThreadCount );
+ if ( s_nDelThreadCount )
+ pool.add( new delete_thread( pool, testSet ), s_nDelThreadCount );
+ if ( s_nExtractThreadCount )
+ pool.add( new extract_thread( pool, testSet ), s_nExtractThreadCount );
+ if ( s_nFindThreadCount )
+ pool.add( new observer_thread( pool, testSet ), s_nFindThreadCount );
+
+ propout() << std::make_pair( "insert_thread_count", s_nInsThreadCount )
+ << std::make_pair( "delete_thread_count", s_nDelThreadCount )
+ << std::make_pair( "extract_thread_count", s_nExtractThreadCount )
+ << std::make_pair( "find_thread_count", s_nFindThreadCount )
+ << std::make_pair( "set_size", s_nSetSize )
+ << std::make_pair( "pass_count", s_nInsertPassCount );
+
+ std::chrono::milliseconds duration = pool.run();
+
+ propout() << std::make_pair( "duration", duration );
+
+ size_t nInsertInitFailed = 0;
+ size_t nInsertInitSuccess = 0;
+ size_t nInsertSuccess = 0;
+ size_t nInsertFailed = 0;
+ size_t nDeleteSuccess = 0;
+ size_t nDeleteFailed = 0;
+ size_t nExtractSuccess = 0;
+ size_t nExtractFailed = 0;
+
+ size_t nFindEvenSuccess = 0;
+ size_t nFindEvenFailed = 0;
+ size_t nFindOddSuccess = 0;
+ size_t nFindOddFailed = 0;
+
+ for ( size_t i = 0; i < pool.size(); ++i ) {
+ cds_test::thread& thr = pool.get( i );
+ switch ( thr.type()) {
+ case inserter_thread:
+ {
+ insert_thread& inserter = static_cast<insert_thread&>( thr );
+ nInsertSuccess += inserter.m_nInsertSuccess;
+ nInsertFailed += inserter.m_nInsertFailed;
+ nInsertInitSuccess += inserter.m_nInsertInitSuccess;
+ nInsertInitFailed += inserter.m_nInsertInitFailed;
+ }
+ break;
+ case deleter_thread:
+ {
+ delete_thread& deleter = static_cast<delete_thread&>(thr);
+ nDeleteSuccess += deleter.m_nDeleteSuccess;
+ nDeleteFailed += deleter.m_nDeleteFailed;
+ }
+ break;
+ case extractor_thread:
+ {
+ extract_thread& extractor = static_cast<extract_thread&>(thr);
+ nExtractSuccess += extractor.m_nExtractSuccess;
+ nExtractFailed += extractor.m_nExtractFailed;
+ }
+ break;
+ case find_thread:
+ {
+ observer_thread& observer = static_cast<observer_thread&>( thr );
+ nFindEvenSuccess = observer.m_nFindEvenSuccess;
+ nFindEvenFailed = observer.m_nFindEvenFailed;
+ nFindOddSuccess = observer.m_nFindOddSuccess;
+ nFindOddFailed = observer.m_nFindOddFailed;
+ }
+ break;
+ default:
+ assert( false );
+ }
+ }
+
+ size_t const nInitialOddKeys = ( s_nSetSize * s_nInsThreadCount ) * 3 / 4;
+
+ EXPECT_EQ( nInsertInitFailed, 0u );
+ EXPECT_EQ( nInsertInitSuccess, s_nSetSize * s_nInsThreadCount );
+ EXPECT_EQ( nFindEvenFailed, 0u );
+ EXPECT_GE( nInsertSuccess + nInitialOddKeys, nDeleteSuccess + nExtractSuccess );
+ EXPECT_LE( nInsertSuccess, nDeleteSuccess + nExtractSuccess );
+
+ propout()
+ << std::make_pair( "insert_init_success", nInsertInitSuccess )
+ << std::make_pair( "insert_init_failed", nInsertInitFailed )
+ << std::make_pair( "insert_success", nInsertSuccess )
+ << std::make_pair( "insert_failed", nInsertFailed )
+ << std::make_pair( "delete_success", nDeleteSuccess )
+ << std::make_pair( "delete_failed", nDeleteFailed )
+ << std::make_pair( "extract_success", nExtractSuccess )
+ << std::make_pair( "extract_failed", nExtractFailed )
+ << std::make_pair( "find_even_success", nFindEvenSuccess )
+ << std::make_pair( "find_even_failed", nFindEvenFailed )
+ << std::make_pair( "find_odd_success", nFindOddSuccess )
+ << std::make_pair( "find_odd_failed", nFindOddFailed );
+ }
+
+ template <typename Set>
+ void analyze( Set& testSet )
+ {
+ // All even keys must be in the set
+ {
+ for ( size_t n = 0; n < s_nSetSize; n +=4 ) {
+ for ( size_t i = 0; i < s_nInsThreadCount; ++i ) {
+ EXPECT_TRUE( testSet.contains( key_type( n, i ))) << "key=" << n << "/" << i;
+ }
+ }
+ }
+
+ check_before_clear( testSet );
+
+ testSet.clear();
+ EXPECT_TRUE( testSet.empty()) << "set.size=" << testSet.size();
+
+ additional_check( testSet );
+ print_stat( propout(), testSet );
+ additional_cleanup( testSet );
+ }
+
+ template <class Set, typename Iterator=typename Set::iterator>
+ void run_test()
+ {
+ static_assert( !Set::c_bExtractSupported, "Set class must not support extract() method" );
+
+ Set testSet( *this );
+ do_test_with<Iterator>( testSet );
+ analyze( testSet );
+ }
+
+ template <class Set, typename Iterator=typename Set::iterator>
+ void run_test_extract()
+ {
+ static_assert( Set::c_bExtractSupported, "Set class must support extract() method" );
+
+ Set testSet( *this );
+ do_test_extract_with<Iterator>( testSet );
+ analyze( testSet );
+ }
+
+ template <class Set>
+ void run_feldman();
+ };
+
+ class Set_Iter_Del3_reverse: public Set_Iter_Del3
+ {
+ public:
+ template <class Set>
+ void run_feldman();
+ };
+
+
+ class Set_Iter_Del3_LF: public Set_Iter_Del3
+ , public ::testing::WithParamInterface<size_t>
+ {
+ public:
+ template <class Set>
+ void run_test()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Set_Iter_Del3::run_test<Set>();
+ }
+
+ template <class Set>
+ void run_test_extract()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Set_Iter_Del3::run_test_extract<Set>();
+ }
+
+ static std::vector<size_t> get_load_factors();
+ };
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_iter_erase.h"
+#include "set_type_feldman_hashset.h"
+
+namespace set {
+
+ template <class Set>
+ void Set_Iter_Del3::run_feldman()
+ {
+ typedef typename Set::traits original_traits;
+ struct traits: public original_traits {
+ enum { hash_size = sizeof( uint32_t ) + sizeof( uint16_t ) };
+ };
+ typedef typename Set::template rebind_traits< traits >::result set_type;
+
+ run_test_extract<set_type>();
+ }
+
+ template <class Set>
+ void Set_Iter_Del3_reverse::run_feldman()
+ {
+ typedef typename Set::traits original_traits;
+ struct traits: public original_traits {
+ enum { hash_size = sizeof( uint32_t ) + sizeof( uint16_t ) };
+ };
+ typedef typename Set::template rebind_traits< traits >::result set_type;
+
+ run_test_extract<set_type, typename set_type::reverse_iterator>();
+ }
+
+ //TODO: add erase_at() to FeldmanHashSet<RCU>
+ CDSSTRESS_FeldmanHashSet_fixed_HP( Set_Iter_Del3, run_feldman, key_thread, size_t )
+ CDSSTRESS_FeldmanHashSet_fixed_HP( Set_Iter_Del3_reverse, run_feldman, key_thread, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_iter_erase.h"
+#include "set_type_michael.h"
+
+namespace set {
+
+ // Test is too long
+ //CDSSTRESS_MichaelIterableSet( Set_Iter_Del3_LF, run_test_extract, key_thread, size_t )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_iter_erase.h"
+#include "set_type_split_list.h"
+
+namespace set {
+ // Too long
+ //CDSSTRESS_SplitListIterableSet( Set_Iter_Del3_LF, run_test_extract, key_thread, size_t )
+
+} // namespace set
--- /dev/null
+set(PACKAGE_NAME stress-sequential-set-iteration)
+
+set(CDSSTRESS_SET_ITERATION_SOURCES
+ ../../../main.cpp
+ set_iteration.cpp
+ set_iteration_feldman_hashset.cpp
+ set_iteration_michael.cpp
+)
+
+include_directories(
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/..
+)
+
+add_executable(${PACKAGE_NAME} ${CDSSTRESS_SET_ITERATION_SOURCES})
+target_link_libraries(${PACKAGE_NAME} ${CDS_TEST_LIBRARIES} ${CDSSTRESS_FRAMEWORK_LIBRARY})
+
+add_test(NAME ${PACKAGE_NAME} COMMAND ${PACKAGE_NAME} WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_iteration.h"
+
+namespace set {
+
+ size_t Set_Iteration::s_nSetSize = 1000000; // set size
+ size_t Set_Iteration::s_nInsertThreadCount = 4; // count of insertion thread
+ size_t Set_Iteration::s_nDeleteThreadCount = 4; // count of deletion thread
+ size_t Set_Iteration::s_nThreadPassCount = 4; // pass count for each thread
+ size_t Set_Iteration::s_nMaxLoadFactor = 8; // maximum load factor
+
+ size_t Set_Iteration::s_nCuckooInitialSize = 1024;// initial size for CuckooSet
+ size_t Set_Iteration::s_nCuckooProbesetSize = 16; // CuckooSet probeset size (only for list-based probeset)
+ size_t Set_Iteration::s_nCuckooProbesetThreshold = 0; // CUckooSet probeset threshold (0 - use default)
+
+ size_t Set_Iteration::s_nFeldmanSet_HeadBits = 10;
+ size_t Set_Iteration::s_nFeldmanSet_ArrayBits = 4;
+
+ size_t Set_Iteration::s_nLoadFactor = 1;
+ std::vector<std::string> Set_Iteration::m_arrString;
+
+ void Set_Iteration::SetUpTestCase()
+ {
+ cds_test::config const& cfg = get_config( "map_insdel_string" );
+
+ s_nSetSize = cfg.get_size_t( "MapSize", s_nSetSize );
+ if ( s_nSetSize < 1000 )
+ s_nSetSize = 1000;
+
+ s_nInsertThreadCount = cfg.get_size_t( "InsertThreadCount", s_nInsertThreadCount );
+ if ( s_nInsertThreadCount == 0 )
+ s_nInsertThreadCount = 2;
+
+ s_nDeleteThreadCount = cfg.get_size_t( "DeleteThreadCount", s_nDeleteThreadCount );
+ if ( s_nDeleteThreadCount == 0 )
+ s_nDeleteThreadCount = 2;
+
+ s_nThreadPassCount = cfg.get_size_t( "ThreadPassCount", s_nThreadPassCount );
+ if ( s_nThreadPassCount == 0 )
+ s_nThreadPassCount = 4;
+
+ s_nMaxLoadFactor = cfg.get_size_t( "MaxLoadFactor", s_nMaxLoadFactor );
+ if ( s_nMaxLoadFactor == 0 )
+ s_nMaxLoadFactor = 1;
+
+ s_nCuckooInitialSize = cfg.get_size_t( "CuckooInitialSize", s_nCuckooInitialSize );
+ if ( s_nCuckooInitialSize < 256 )
+ s_nCuckooInitialSize = 256;
+
+ s_nCuckooProbesetSize = cfg.get_size_t( "CuckooProbesetSize", s_nCuckooProbesetSize );
+ if ( s_nCuckooProbesetSize < 8 )
+ s_nCuckooProbesetSize = 8;
+
+ s_nCuckooProbesetThreshold = cfg.get_size_t( "CuckooProbesetThreshold", s_nCuckooProbesetThreshold );
+
+ s_nFeldmanSet_HeadBits = cfg.get_size_t( "FeldmanMapHeadBits", s_nFeldmanSet_HeadBits );
+ if ( s_nFeldmanSet_HeadBits == 0 )
+ s_nFeldmanSet_HeadBits = 2;
+
+ s_nFeldmanSet_ArrayBits = cfg.get_size_t( "FeldmanMapArrayBits", s_nFeldmanSet_ArrayBits );
+ if ( s_nFeldmanSet_ArrayBits == 0 )
+ s_nFeldmanSet_ArrayBits = 2;
+
+ // Load string dictionary
+ m_arrString = load_dictionary();
+ }
+
+ void Set_Iteration::TearDownTestCase()
+ {
+ m_arrString.clear();
+ }
+
+ std::vector<size_t> Set_Iteration_LF::get_load_factors()
+ {
+ cds_test::config const& cfg = get_config( "map_insdel_string" );
+
+ s_nMaxLoadFactor = cfg.get_size_t( "MaxLoadFactor", s_nMaxLoadFactor );
+ if ( s_nMaxLoadFactor == 0 )
+ s_nMaxLoadFactor = 1;
+
+ std::vector<size_t> lf;
+ for ( size_t n = 1; n <= s_nMaxLoadFactor; n *= 2 )
+ lf.push_back( n );
+
+ return lf;
+ }
+
+#ifdef CDSTEST_GTEST_INSTANTIATE_TEST_CASE_P_HAS_4TH_ARG
+ static std::string get_test_parameter_name( testing::TestParamInfo<size_t> const& p )
+ {
+ return std::to_string( p.param );
+ }
+ INSTANTIATE_TEST_CASE_P( a, Set_Iteration_LF, ::testing::ValuesIn( Set_Iteration_LF::get_load_factors()), get_test_parameter_name );
+#else
+ INSTANTIATE_TEST_CASE_P( a, Set_Iteration_LF, ::testing::ValuesIn( Set_Iteration_LF::get_load_factors()));
+#endif
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_type.h"
+#include <cds_test/city.h>
+
+namespace set {
+
+// Test for set's thread-safe iterator:
+// Several thread inserts/erases elemets from the set.
+// Dedicated Iterator thread iterates over the set, calculates CityHash for each element
+// and stores it in the element.
+// Test goal: no crash
+
+#define TEST_CASE(TAG, X) void X();
+
+ class Set_Iteration: public cds_test::stress_fixture
+ {
+ public:
+ static size_t s_nSetSize; // set size
+ static size_t s_nInsertThreadCount; // count of insertion thread
+ static size_t s_nDeleteThreadCount; // count of deletion thread
+ static size_t s_nThreadPassCount; // pass count for each thread
+ static size_t s_nMaxLoadFactor; // maximum load factor
+
+ static size_t s_nCuckooInitialSize; // initial size for CuckooSet
+ static size_t s_nCuckooProbesetSize; // CuckooSet probeset size (only for list-based probeset)
+ static size_t s_nCuckooProbesetThreshold; // CUckooSet probeset threshold (0 - use default)
+
+ static size_t s_nFeldmanSet_HeadBits;
+ static size_t s_nFeldmanSet_ArrayBits;
+
+ static size_t s_nLoadFactor;
+ static std::vector<std::string> m_arrString;
+
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+
+ void on_modifier_done()
+ {
+ m_nModifierCount.fetch_sub( 1, atomics::memory_order_relaxed );
+ }
+
+ bool all_modifiers_done() const
+ {
+ return m_nModifierCount.load( atomics::memory_order_relaxed ) == 0;
+ }
+
+ typedef std::string key_type;
+
+ struct value_type
+ {
+ size_t val;
+ uint64_t hash;
+
+ explicit value_type( size_t v )
+ : val(v)
+ , hash(0)
+ {}
+ };
+
+ private:
+ enum {
+ insert_thread,
+ delete_thread,
+ extract_thread,
+ iterator_thread
+ };
+
+ atomics::atomic<size_t> m_nModifierCount;
+
+ template <class Set>
+ class Inserter: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+
+ Set& m_Set;
+ typedef typename Set::value_type keyval_type;
+
+ public:
+ size_t m_nInsertSuccess = 0;
+ size_t m_nInsertFailed = 0;
+
+ public:
+ Inserter( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, insert_thread )
+ , m_Set( set )
+ {}
+
+ Inserter( Inserter& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Inserter( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+
+ Set_Iteration& fixture = pool().template fixture<Set_Iteration>();
+ size_t nArrSize = m_arrString.size();
+ size_t const nSetSize = fixture.s_nSetSize;
+ size_t const nPassCount = fixture.s_nThreadPassCount;
+
+ if ( id() & 1 ) {
+ for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) {
+ for ( size_t nItem = 0; nItem < nSetSize; ++nItem ) {
+ if ( rSet.insert( keyval_type( m_arrString[nItem % nArrSize], nItem * 8 )))
+ ++m_nInsertSuccess;
+ else
+ ++m_nInsertFailed;
+ }
+ }
+ }
+ else {
+ for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) {
+ for ( size_t nItem = nSetSize; nItem > 0; --nItem ) {
+ if ( rSet.insert( keyval_type( m_arrString[nItem % nArrSize], nItem * 8 )))
+ ++m_nInsertSuccess;
+ else
+ ++m_nInsertFailed;
+ }
+ }
+ }
+
+ fixture.on_modifier_done();
+ }
+ };
+
+ template <class Set>
+ class Deleter: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+
+ Set& m_Set;
+ public:
+ size_t m_nDeleteSuccess = 0;
+ size_t m_nDeleteFailed = 0;
+
+ public:
+ Deleter( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, delete_thread )
+ , m_Set( set )
+ {}
+
+ Deleter( Deleter& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Deleter( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+
+ Set_Iteration& fixture = pool().template fixture<Set_Iteration>();
+ size_t nArrSize = m_arrString.size();
+ size_t const nSetSize = fixture.s_nSetSize;
+ size_t const nPassCount = fixture.s_nThreadPassCount;
+
+ if ( id() & 1 ) {
+ for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) {
+ for ( size_t nItem = 0; nItem < nSetSize; ++nItem ) {
+ if ( rSet.erase( m_arrString[nItem % nArrSize] ))
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ }
+ }
+ }
+ else {
+ for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) {
+ for ( size_t nItem = nSetSize; nItem > 0; --nItem ) {
+ if ( rSet.erase( m_arrString[nItem % nArrSize] ))
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ }
+ }
+ }
+
+ fixture.on_modifier_done();
+ }
+ };
+
+ template <typename GC, class Set>
+ class Extractor: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Set& m_Set;
+
+ public:
+ size_t m_nDeleteSuccess = 0;
+ size_t m_nDeleteFailed = 0;
+
+ public:
+ Extractor( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, extract_thread )
+ , m_Set( set )
+ {}
+
+ Extractor( Extractor& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Extractor( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+
+ typename Set::guarded_ptr gp;
+
+ Set_Iteration& fixture = pool().template fixture<Set_Iteration>();
+ size_t nArrSize = m_arrString.size();
+ size_t const nSetSize = fixture.s_nSetSize;
+ size_t const nPassCount = fixture.s_nThreadPassCount;
+
+ if ( id() & 1 ) {
+ for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) {
+ for ( size_t nItem = 0; nItem < nSetSize; ++nItem ) {
+ gp = rSet.extract( m_arrString[nItem % nArrSize] );
+ if ( gp )
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ gp.release();
+ }
+ }
+ }
+ else {
+ for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) {
+ for ( size_t nItem = nSetSize; nItem > 0; --nItem ) {
+ gp = rSet.extract( m_arrString[nItem % nArrSize] );
+ if ( gp )
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ gp.release();
+ }
+ }
+ }
+
+ fixture.on_modifier_done();
+ }
+ };
+
+ template <typename RCU, class Set>
+ class Extractor<cds::urcu::gc<RCU>, Set >: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Set& m_Set;
+
+ public:
+ size_t m_nDeleteSuccess = 0;
+ size_t m_nDeleteFailed = 0;
+
+ public:
+ Extractor( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, extract_thread )
+ , m_Set( set )
+ {}
+
+ Extractor( Extractor& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Extractor( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+
+ typename Set::exempt_ptr xp;
+
+ Set_Iteration& fixture = pool().template fixture<Set_Iteration>();
+ size_t nArrSize = m_arrString.size();
+ size_t const nSetSize = fixture.s_nSetSize;
+ size_t const nPassCount = fixture.s_nThreadPassCount;
+
+ if ( id() & 1 ) {
+ for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) {
+ for ( size_t nItem = 0; nItem < nSetSize; ++nItem ) {
+ if ( Set::c_bExtractLockExternal ) {
+ typename Set::rcu_lock l;
+ xp = rSet.extract( m_arrString[nItem % nArrSize] );
+ if ( xp )
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ }
+ else {
+ xp = rSet.extract( m_arrString[nItem % nArrSize] );
+ if ( xp )
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ }
+ xp.release();
+ }
+ }
+ }
+ else {
+ for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) {
+ for ( size_t nItem = nSetSize; nItem > 0; --nItem ) {
+ if ( Set::c_bExtractLockExternal ) {
+ typename Set::rcu_lock l;
+ xp = rSet.extract( m_arrString[nItem % nArrSize] );
+ if ( xp )
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ }
+ else {
+ xp = rSet.extract( m_arrString[nItem % nArrSize] );
+ if ( xp )
+ ++m_nDeleteSuccess;
+ else
+ ++m_nDeleteFailed;
+ }
+ xp.release();
+ }
+ }
+ }
+
+ fixture.on_modifier_done();
+ }
+ };
+
+ template <typename GC, class Set>
+ class Iterator: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+
+ Set& m_Set;
+ typedef typename Set::value_type keyval_type;
+
+ public:
+ size_t m_nPassCount = 0;
+ size_t m_nVisitCount = 0; // how many items the iterator visited
+
+ public:
+ Iterator( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, iterator_thread )
+ , m_Set( set )
+ {}
+
+ Iterator( Iterator& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Iterator( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+
+ Set_Iteration& fixture = pool().template fixture<Set_Iteration>();
+ while ( !fixture.all_modifiers_done()) {
+ ++m_nPassCount;
+ typename Set::iterator it;
+ typename Set::iterator itEnd;
+ itEnd = rSet.end();
+ for ( it = rSet.begin(); it != itEnd; ++it ) {
+#if CDS_BUILD_BITS == 64
+ it->val.hash = CityHash64( it->key.c_str(), it->key.length());
+#else
+ it->val.hash = std::hash<std::string>()( it->key );
+#endif
+ ++m_nVisitCount;
+ }
+ }
+ }
+ };
+
+ template <typename RCU, class Set>
+ class Iterator<cds::urcu::gc<RCU>, Set>: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+
+ Set& m_Set;
+ typedef typename Set::value_type keyval_type;
+
+ public:
+ size_t m_nPassCount = 0;
+ size_t m_nVisitCount = 0; // how many items the iterator visited
+
+ public:
+ Iterator( cds_test::thread_pool& pool, Set& set )
+ : base_class( pool, iterator_thread )
+ , m_Set( set )
+ {}
+
+ Iterator( Iterator& src )
+ : base_class( src )
+ , m_Set( src.m_Set )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Iterator( *this );
+ }
+
+ virtual void test()
+ {
+ Set& rSet = m_Set;
+
+ Set_Iteration& fixture = pool().template fixture<Set_Iteration>();
+ while ( !fixture.all_modifiers_done()) {
+ ++m_nPassCount;
+ typename Set::rcu_lock l;
+ for ( auto it = rSet.begin(); it != rSet.end(); ++it ) {
+#if CDS_BUILD_BITS == 64
+ it->val.hash = CityHash64( it->key.c_str(), it->key.length());
+#else
+ it->val.hash = std::hash<std::string>()(it->key);
+#endif
+ ++m_nVisitCount;
+ }
+ }
+ }
+ };
+
+ protected:
+ template <class Set>
+ void do_test( Set& testSet )
+ {
+ typedef Inserter<Set> InserterThread;
+ typedef Deleter<Set> DeleterThread;
+ typedef Iterator<typename Set::gc, Set> IteratorThread;
+
+ cds_test::thread_pool& pool = get_pool();
+ pool.add( new InserterThread( pool, testSet ), s_nInsertThreadCount );
+ pool.add( new DeleterThread( pool, testSet ), s_nDeleteThreadCount );
+
+ m_nModifierCount.store( pool.size(), atomics::memory_order_relaxed );
+ pool.add( new IteratorThread( pool, testSet ), 1 );
+
+ propout() << std::make_pair( "insert_thread_count", s_nInsertThreadCount )
+ << std::make_pair( "delete_thread_count", s_nDeleteThreadCount )
+ << std::make_pair( "thread_pass_count", s_nThreadPassCount )
+ << std::make_pair( "set_size", s_nSetSize );
+
+ std::chrono::milliseconds duration = pool.run();
+
+ propout() << std::make_pair( "duration", duration );
+
+ size_t nInsertSuccess = 0;
+ size_t nInsertFailed = 0;
+ size_t nDeleteSuccess = 0;
+ size_t nDeleteFailed = 0;
+ size_t nIteratorPassCount = 0;
+ size_t nIteratorVisitCount = 0;
+ for ( size_t i = 0; i < pool.size(); ++i ) {
+ cds_test::thread& thr = pool.get( i );
+ switch ( thr.type()) {
+ case insert_thread:
+ {
+ InserterThread& inserter = static_cast<InserterThread&>( thr );
+ nInsertSuccess += inserter.m_nInsertSuccess;
+ nInsertFailed += inserter.m_nInsertFailed;
+ }
+ break;
+ case delete_thread:
+ {
+ DeleterThread& deleter = static_cast<DeleterThread&>(thr);
+ nDeleteSuccess += deleter.m_nDeleteSuccess;
+ nDeleteFailed += deleter.m_nDeleteFailed;
+ }
+ break;
+ case iterator_thread:
+ {
+ IteratorThread& iter = static_cast<IteratorThread&>(thr);
+ nIteratorPassCount += iter.m_nPassCount;
+ nIteratorVisitCount += iter.m_nVisitCount;
+ }
+ break;
+ default:
+ assert( false ); // Forgot anything?..
+ }
+ }
+
+ propout()
+ << std::make_pair( "insert_success", nInsertSuccess )
+ << std::make_pair( "delete_success", nDeleteSuccess )
+ << std::make_pair( "insert_failed", nInsertFailed )
+ << std::make_pair( "delete_failed", nDeleteFailed )
+ << std::make_pair( "iterator_pass_count", nIteratorPassCount )
+ << std::make_pair( "iterator_visit_count", nIteratorVisitCount )
+ << std::make_pair( "final_set_size", testSet.size());
+
+ testSet.clear();
+ EXPECT_TRUE( testSet.empty());
+
+ additional_check( testSet );
+ print_stat( propout(), testSet );
+ additional_cleanup( testSet );
+ }
+
+ template <class Set>
+ void do_test_extract( Set& testSet )
+ {
+ typedef Inserter<Set> InserterThread;
+ typedef Deleter<Set> DeleterThread;
+ typedef Extractor<typename Set::gc, Set> ExtractThread;
+ typedef Iterator<typename Set::gc, Set> IteratorThread;
+
+ size_t const nDelThreadCount = s_nDeleteThreadCount / 2;
+ size_t const nExtractThreadCount = s_nDeleteThreadCount - nDelThreadCount;
+
+ cds_test::thread_pool& pool = get_pool();
+ pool.add( new InserterThread( pool, testSet ), s_nInsertThreadCount );
+ pool.add( new DeleterThread( pool, testSet ), nDelThreadCount );
+ pool.add( new ExtractThread( pool, testSet ), nExtractThreadCount );
+
+ m_nModifierCount.store( pool.size(), atomics::memory_order_relaxed );
+ pool.add( new IteratorThread( pool, testSet ), 1 );
+
+ propout() << std::make_pair( "insert_thread_count", s_nInsertThreadCount )
+ << std::make_pair( "delete_thread_count", nDelThreadCount )
+ << std::make_pair( "extract_thread_count", nExtractThreadCount )
+ << std::make_pair( "thread_pass_count", s_nThreadPassCount )
+ << std::make_pair( "set_size", s_nSetSize );
+
+ std::chrono::milliseconds duration = pool.run();
+
+ propout() << std::make_pair( "duration", duration );
+
+ size_t nInsertSuccess = 0;
+ size_t nInsertFailed = 0;
+ size_t nDeleteSuccess = 0;
+ size_t nDeleteFailed = 0;
+ size_t nExtractSuccess = 0;
+ size_t nExtractFailed = 0;
+ size_t nIteratorPassCount = 0;
+ size_t nIteratorVisitCount = 0;
+ for ( size_t i = 0; i < pool.size(); ++i ) {
+ cds_test::thread& thr = pool.get( i );
+ switch ( thr.type()) {
+ case insert_thread:
+ {
+ InserterThread& inserter = static_cast<InserterThread&>(thr);
+ nInsertSuccess += inserter.m_nInsertSuccess;
+ nInsertFailed += inserter.m_nInsertFailed;
+ }
+ break;
+ case delete_thread:
+ {
+ DeleterThread& deleter = static_cast<DeleterThread&>(thr);
+ nDeleteSuccess += deleter.m_nDeleteSuccess;
+ nDeleteFailed += deleter.m_nDeleteFailed;
+ }
+ break;
+ case extract_thread:
+ {
+ ExtractThread& extractor = static_cast<ExtractThread&>(thr);
+ nExtractSuccess += extractor.m_nDeleteSuccess;
+ nExtractFailed += extractor.m_nDeleteFailed;
+ }
+ break;
+ case iterator_thread:
+ {
+ IteratorThread& iter = static_cast<IteratorThread&>(thr);
+ nIteratorPassCount += iter.m_nPassCount;
+ nIteratorVisitCount += iter.m_nVisitCount;
+ }
+ break;
+ default:
+ assert( false ); // Forgot anything?..
+ }
+ }
+
+ propout()
+ << std::make_pair( "insert_success", nInsertSuccess )
+ << std::make_pair( "delete_success", nDeleteSuccess )
+ << std::make_pair( "extract_success", nExtractSuccess )
+ << std::make_pair( "insert_failed", nInsertFailed )
+ << std::make_pair( "delete_failed", nDeleteFailed )
+ << std::make_pair( "extract_failed", nExtractFailed )
+ << std::make_pair( "iterator_pass_count", nIteratorPassCount )
+ << std::make_pair( "iterator_visit_count", nIteratorVisitCount )
+ << std::make_pair( "final_set_size", testSet.size());
+
+ testSet.clear();
+ EXPECT_TRUE( testSet.empty());
+
+ additional_check( testSet );
+ print_stat( propout(), testSet );
+ additional_cleanup( testSet );
+ }
+
+ template <class Set>
+ void run_test()
+ {
+ ASSERT_TRUE( m_arrString.size() > 0 );
+
+ Set s( *this );
+ do_test( s );
+ }
+
+ template <class Set>
+ void run_test_extract()
+ {
+ ASSERT_TRUE( m_arrString.size() > 0 );
+
+ Set s( *this );
+ do_test_extract( s );
+ }
+ };
+
+ class Set_Iteration_LF: public Set_Iteration
+ , public ::testing::WithParamInterface<size_t>
+ {
+ public:
+ template <class Set>
+ void run_test()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Set_Iteration::run_test<Set>();
+ }
+
+ template <class Set>
+ void run_test_extract()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Set_Iteration::run_test_extract<Set>();
+ }
+
+ static std::vector<size_t> get_load_factors();
+ };
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_iteration.h"
+#include "set_type_feldman_hashset.h"
+
+namespace set {
+
+ CDSSTRESS_FeldmanHashSet_stdhash( Set_Iteration, run_test_extract, std::string, Set_Iteration::value_type )
+ CDSSTRESS_FeldmanHashSet_city( Set_Iteration, run_test_extract, std::string, Set_Iteration::value_type )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_iteration.h"
+#include "set_type_michael.h"
+
+namespace set {
+
+ CDSSTRESS_MichaelIterableSet( Set_Iteration_LF, run_test_extract, std::string, Set_Iteration::value_type )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "set_iteration.h"
+#include "set_type_split_list.h"
+
+namespace set {
+
+ CDSSTRESS_SplitListIterableSet( Set_Iteration_LF, run_test_extract, std::string, Set_Iteration::value_type )
+
+} // namespace set
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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.
+*/
+
+#ifndef CDSUNIT_SET_TYPE_H
+#define CDSUNIT_SET_TYPE_H
+
+#include <cds/urcu/general_instant.h>
+#include <cds/urcu/general_buffered.h>
+#include <cds/urcu/general_threaded.h>
+#include <cds/urcu/signal_buffered.h>
+
+#include <cds/opt/hash.h>
+#include <cds/sync/spinlock.h>
+
+#include <cds_test/stress_test.h>
+
+namespace set {
+ namespace cc = cds::container;
+ namespace co = cds::opt;
+
+ typedef cds::urcu::gc< cds::urcu::general_instant_stripped > rcu_gpi;
+ typedef cds::urcu::gc< cds::urcu::general_buffered_stripped > rcu_gpb;
+ typedef cds::urcu::gc< cds::urcu::general_threaded_stripped > rcu_gpt;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef cds::urcu::gc< cds::urcu::signal_buffered_stripped > rcu_shb;
+#endif
+
+ template <typename Key>
+ struct less;
+
+ template <typename Key>
+ struct cmp
+ {
+ int operator ()(Key const& k1, Key const& k2) const
+ {
+ if ( less<Key>( k1, k2 ))
+ return -1;
+ return less<Key>( k2, k1 ) ? 1 : 0;
+ }
+ };
+
+ template <typename Key>
+ struct hash;
+
+#define CDSUNIT_INT_COMPARE(t) template <> struct cmp<t> { int operator()( t k1, t k2 ){ return (int)(k1 - k2); } }
+ CDSUNIT_INT_COMPARE(char);
+ CDSUNIT_INT_COMPARE(unsigned char);
+ CDSUNIT_INT_COMPARE(int);
+ CDSUNIT_INT_COMPARE(unsigned int);
+ CDSUNIT_INT_COMPARE(long);
+ CDSUNIT_INT_COMPARE(unsigned long);
+ CDSUNIT_INT_COMPARE(long long);
+ CDSUNIT_INT_COMPARE(unsigned long long);
+#undef CDSUNIT_INT_COMPARE
+
+#define CDSUNIT_INT_LESS(t) template <> struct less<t> { bool operator()( t k1, t k2 ){ return k1 < k2; } }
+ CDSUNIT_INT_LESS( char );
+ CDSUNIT_INT_LESS( unsigned char );
+ CDSUNIT_INT_LESS( int );
+ CDSUNIT_INT_LESS( unsigned int );
+ CDSUNIT_INT_LESS( long );
+ CDSUNIT_INT_LESS( unsigned long );
+ CDSUNIT_INT_LESS( long long );
+ CDSUNIT_INT_LESS( unsigned long long );
+#undef CDSUNIT_INT_LESS
+
+ template <>
+ struct cmp<std::string>
+ {
+ int operator()(std::string const& s1, std::string const& s2)
+ {
+ return s1.compare( s2 );
+ }
+ int operator()(std::string const& s1, char const * s2)
+ {
+ return s1.compare( s2 );
+ }
+ int operator()(char const * s1, std::string const& s2)
+ {
+ return -s2.compare( s1 );
+ }
+ };
+
+ template <>
+ struct less<std::string>
+ {
+ bool operator ()( std::string const& k1, std::string const& k2 ) const
+ {
+ return cmp<std::string>()( k1, k2 ) < 0;
+ }
+ bool operator ()( std::string const& k1, char const* k2 ) const
+ {
+ return cmp<std::string>()( k1, k2 ) < 0;
+ }
+ bool operator ()( char const* k1, std::string const& k2 ) const
+ {
+ return cmp<std::string>()( k1, k2 ) < 0;
+ }
+ };
+
+ template <typename T>
+ struct hash
+ {
+ typedef size_t result_type;
+ typedef T argument_type;
+
+ size_t operator()( T const& k ) const
+ {
+ return std::hash<size_t>()(k.nKey);
+ }
+
+ size_t operator()( size_t k ) const
+ {
+ return std::hash<size_t>()(k);
+ }
+ };
+
+ template <>
+ struct hash<size_t>
+ {
+ typedef size_t result_type;
+ typedef size_t argument_type;
+
+ size_t operator()( size_t k ) const
+ {
+ return std::hash<size_t>()(k);
+ }
+ };
+
+ template <>
+ struct hash<std::string>
+ {
+ typedef size_t result_type;
+ typedef std::string argument_type;
+
+ size_t operator()( std::string const& k ) const
+ {
+ return std::hash<std::string>()(k);
+ }
+ };
+
+ // forward
+ template <typename ImplSelector, typename Key, typename Value>
+ struct set_type;
+
+ template <typename Key, typename Value>
+ struct set_type_base
+ {
+ typedef Key key_type;
+ typedef Value value_type;
+
+ struct key_val {
+ key_type key;
+ value_type val;
+
+ explicit key_val( key_type const& k ): key(k), val() {}
+ key_val( key_type const& k, value_type const& v ): key(k), val(v) {}
+
+ template <typename K>
+ explicit key_val( K const& k ): key(k) {}
+
+ template <typename K, typename T>
+ key_val( K const& k, T const& v ): key(k), val(v) {}
+ };
+
+ typedef set::hash<key_type> key_hash;
+ typedef set::less<key_type> key_less;
+ typedef set::cmp<key_type> key_compare;
+
+ struct less {
+ bool operator()( key_val const& k1, key_val const& k2 ) const
+ {
+ return key_less()( k1.key, k2.key );
+ }
+ bool operator()( key_type const& k1, key_val const& k2 ) const
+ {
+ return key_less()( k1, k2.key );
+ }
+ bool operator()( key_val const& k1, key_type const& k2 ) const
+ {
+ return key_less()( k1.key, k2 );
+ }
+ };
+
+ struct compare {
+ int operator()( key_val const& k1, key_val const& k2 ) const
+ {
+ return key_compare()( k1.key, k2.key );
+ }
+ int operator()( key_type const& k1, key_val const& k2 ) const
+ {
+ return key_compare()( k1, k2.key );
+ }
+ int operator()( key_val const& k1, key_type const& k2 ) const
+ {
+ return key_compare()( k1.key, k2 );
+ }
+ };
+
+ struct equal_to {
+ bool operator()( key_val const& k1, key_val const& k2 ) const
+ {
+ return key_compare()( k1.key, k2.key ) == 0;
+ }
+ bool operator()( key_type const& k1, key_val const& k2 ) const
+ {
+ return key_compare()( k1, k2.key ) == 0;
+ }
+ bool operator()( key_val const& k1, key_type const& k2 ) const
+ {
+ return key_compare()( k1.key, k2 ) == 0;
+ }
+ };
+
+
+ struct hash: public key_hash
+ {
+ size_t operator()( key_val const& v ) const
+ {
+ return key_hash::operator()( v.key );
+ }
+ size_t operator()( key_type const& key ) const
+ {
+ return key_hash::operator()( key );
+ }
+ template <typename Q>
+ size_t operator()( Q const& k ) const
+ {
+ return key_hash::operator()( k );
+ }
+ };
+
+ struct hash2: public hash
+ {
+ size_t operator()( key_val const& k ) const
+ {
+ size_t h = hash::operator ()( k.key );
+ size_t seed = ~h;
+ seed ^= h + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+ return seed;
+ }
+ size_t operator()( key_type const& k ) const
+ {
+ size_t h = hash::operator ()( k );
+ size_t seed = ~h;
+ seed ^= h + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+ return seed;
+ }
+ template <typename Q>
+ size_t operator()( Q const& k ) const
+ {
+ return key_hash::operator()( k );
+ }
+ };
+ };
+
+
+ // *************************************************
+ // print_stat
+ // *************************************************
+
+ struct empty_stat {};
+ static inline cds_test::property_stream& operator <<( cds_test::property_stream& o, empty_stat const& )
+ {
+ return o;
+ }
+
+ template <typename Set>
+ static inline void print_stat( cds_test::property_stream& o, Set const& s )
+ {
+ o << s.statistics();
+ }
+
+
+ //*******************************************************
+ // additional_check
+ //*******************************************************
+
+ template <typename Set>
+ static inline void additional_check( Set& /*set*/ )
+ {}
+
+ template <typename Set>
+ static inline void additional_cleanup( Set& /*set*/ )
+ {}
+
+ //*******************************************************
+ // check_before_clear
+ //*******************************************************
+
+ template <typename Set>
+ static inline void check_before_clear( Set& /*s*/ )
+ {}
+
+} // namespace set
+
+
+#endif // ifndef CDSUNIT_SET_TYPE_H
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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.
+*/
+
+#ifndef CDSUNIT_SET_TYPE_CUCKOO_H
+#define CDSUNIT_SET_TYPE_CUCKOO_H
+
+#include "set/set_type.h"
+
+#include <cds/container/cuckoo_set.h>
+#include <cds_test/stat_cuckoo_out.h>
+
+namespace set {
+
+ template <typename V, typename Traits>
+ class CuckooSet : public cc::CuckooSet< V, Traits >
+ {
+ public:
+ typedef cc::CuckooSet< V, Traits > cuckoo_base_class;
+
+ public:
+ template <typename Config>
+ CuckooSet( Config const& cfg )
+ : cuckoo_base_class(
+ cfg.s_nCuckooInitialSize,
+ static_cast<unsigned int>( cfg.s_nCuckooProbesetSize ),
+ static_cast<unsigned int>( cfg.s_nCuckooProbesetThreshold )
+ )
+ {}
+
+ template <typename Q, typename Pred>
+ bool erase_with( Q const& key, Pred /*pred*/ )
+ {
+ return cuckoo_base_class::erase_with( key, typename std::conditional< cuckoo_base_class::c_isSorted, Pred, typename Pred::equal_to>::type());
+ }
+
+ // for testing
+ static CDS_CONSTEXPR bool const c_bExtractSupported = false;
+ static CDS_CONSTEXPR bool const c_bLoadFactorDepended = false;
+ static CDS_CONSTEXPR bool const c_bEraseExactKey = false;
+ };
+
+ struct tag_CuckooSet;
+
+ template <typename Key, typename Val>
+ struct set_type< tag_CuckooSet, Key, Val >: public set_type_base< Key, Val >
+ {
+ typedef set_type_base< Key, Val > base_class;
+ typedef typename base_class::key_val key_val;
+ typedef typename base_class::compare compare;
+ typedef typename base_class::equal_to equal_to;
+ typedef typename base_class::less less;
+ typedef typename base_class::hash hash;
+ typedef typename base_class::hash2 hash2;
+
+ // ***************************************************************************
+ // CuckooSet
+
+ template <typename Traits>
+ struct traits_CuckooStripedSet : public Traits
+ {
+ typedef cc::cuckoo::striping<> mutex_policy;
+ };
+ template <typename Traits>
+ struct traits_CuckooRefinableSet : public Traits
+ {
+ typedef cc::cuckoo::refinable<> mutex_policy;
+ };
+
+ struct traits_CuckooSet_list_unord :
+ public cc::cuckoo::make_traits <
+ cc::cuckoo::probeset_type< cc::cuckoo::list >
+ , co::equal_to< equal_to >
+ , co::hash< std::tuple< hash, hash2 > >
+ > ::type
+ {};
+ typedef CuckooSet< key_val, traits_CuckooStripedSet<traits_CuckooSet_list_unord>> CuckooStripedSet_list_unord;
+ typedef CuckooSet< key_val, traits_CuckooRefinableSet<traits_CuckooSet_list_unord>> CuckooRefinableSet_list_unord;
+
+ struct traits_CuckooSet_list_unord_stat : public traits_CuckooSet_list_unord
+ {
+ typedef cc::cuckoo::stat stat;
+ };
+ typedef CuckooSet< key_val, traits_CuckooStripedSet<traits_CuckooSet_list_unord_stat>> CuckooStripedSet_list_unord_stat;
+ typedef CuckooSet< key_val, traits_CuckooRefinableSet<traits_CuckooSet_list_unord_stat>> CuckooRefinableSet_list_unord_stat;
+
+ struct traits_CuckooSet_list_unord_storehash : public traits_CuckooSet_list_unord
+ {
+ static CDS_CONSTEXPR const bool store_hash = true;
+ };
+ typedef CuckooSet< key_val, traits_CuckooStripedSet<traits_CuckooSet_list_unord_storehash>> CuckooStripedSet_list_unord_storehash;
+ typedef CuckooSet< key_val, traits_CuckooRefinableSet<traits_CuckooSet_list_unord_storehash>> CuckooRefinableSet_list_unord_storehash;
+
+ struct traits_CuckooSet_list_ord :
+ public cc::cuckoo::make_traits <
+ cc::cuckoo::probeset_type< cc::cuckoo::list >
+ , co::compare< compare >
+ , co::hash< std::tuple< hash, hash2 > >
+ > ::type
+ {};
+ typedef CuckooSet< key_val, traits_CuckooStripedSet<traits_CuckooSet_list_ord>> CuckooStripedSet_list_ord;
+ typedef CuckooSet< key_val, traits_CuckooRefinableSet<traits_CuckooSet_list_ord>> CuckooRefinableSet_list_ord;
+
+ struct traits_CuckooSet_list_ord_stat : public traits_CuckooSet_list_ord
+ {
+ typedef cc::cuckoo::stat stat;
+ };
+ typedef CuckooSet< key_val, traits_CuckooStripedSet<traits_CuckooSet_list_ord_stat>> CuckooStripedSet_list_ord_stat;
+ typedef CuckooSet< key_val, traits_CuckooRefinableSet<traits_CuckooSet_list_ord_stat>> CuckooRefinableSet_list_ord_stat;
+
+ struct traits_CuckooSet_list_ord_storehash : public traits_CuckooSet_list_ord
+ {
+ static CDS_CONSTEXPR const bool store_hash = true;
+ };
+ typedef CuckooSet< key_val, traits_CuckooStripedSet<traits_CuckooSet_list_ord_storehash>> CuckooStripedSet_list_ord_storehash;
+ typedef CuckooSet< key_val, traits_CuckooRefinableSet<traits_CuckooSet_list_ord_storehash>> CuckooRefinableSet_list_ord_storehash;
+
+
+ struct traits_CuckooSet_vector_unord :
+ public cc::cuckoo::make_traits <
+ cc::cuckoo::probeset_type< cc::cuckoo::vector<4> >
+ , co::equal_to< equal_to >
+ , co::hash< std::tuple< hash, hash2 > >
+ > ::type
+ {};
+ typedef CuckooSet< key_val, traits_CuckooStripedSet<traits_CuckooSet_vector_unord>> CuckooStripedSet_vector_unord;
+ typedef CuckooSet< key_val, traits_CuckooRefinableSet<traits_CuckooSet_vector_unord>> CuckooRefinableSet_vector_unord;
+
+ struct traits_CuckooSet_vector_unord_stat : public traits_CuckooSet_vector_unord
+ {
+ typedef cc::cuckoo::stat stat;
+ };
+ typedef CuckooSet< key_val, traits_CuckooStripedSet<traits_CuckooSet_vector_unord_stat>> CuckooStripedSet_vector_unord_stat;
+ typedef CuckooSet< key_val, traits_CuckooRefinableSet<traits_CuckooSet_vector_unord_stat>> CuckooRefinableSet_vector_unord_stat;
+
+ struct traits_CuckooSet_vector_unord_storehash : public traits_CuckooSet_vector_unord
+ {
+ static CDS_CONSTEXPR const bool store_hash = true;
+ };
+ typedef CuckooSet< key_val, traits_CuckooStripedSet<traits_CuckooSet_vector_unord_storehash>> CuckooStripedSet_vector_unord_storehash;
+ typedef CuckooSet< key_val, traits_CuckooRefinableSet<traits_CuckooSet_vector_unord_storehash>> CuckooRefinableSet_vector_unord_storehash;
+
+ struct traits_CuckooSet_vector_ord :
+ public cc::cuckoo::make_traits <
+ cc::cuckoo::probeset_type< cc::cuckoo::vector<4> >
+ , co::compare< compare >
+ , co::hash< std::tuple< hash, hash2 > >
+ > ::type
+ {};
+ typedef CuckooSet< key_val, traits_CuckooStripedSet<traits_CuckooSet_vector_ord>> CuckooStripedSet_vector_ord;
+ typedef CuckooSet< key_val, traits_CuckooRefinableSet<traits_CuckooSet_vector_ord>> CuckooRefinableSet_vector_ord;
+
+ struct traits_CuckooSet_vector_ord_stat : public traits_CuckooSet_vector_ord
+ {
+ typedef cc::cuckoo::stat stat;
+ };
+ typedef CuckooSet< key_val, traits_CuckooStripedSet<traits_CuckooSet_vector_ord_stat>> CuckooStripedSet_vector_ord_stat;
+ typedef CuckooSet< key_val, traits_CuckooRefinableSet<traits_CuckooSet_vector_ord_stat>> CuckooRefinableSet_vector_ord_stat;
+
+ struct traits_CuckooSet_vector_ord_storehash : public traits_CuckooSet_vector_ord
+ {
+ static CDS_CONSTEXPR const bool store_hash = true;
+ };
+ typedef CuckooSet< key_val, traits_CuckooStripedSet<traits_CuckooSet_vector_ord_storehash>> CuckooStripedSet_vector_ord_storehash;
+ typedef CuckooSet< key_val, traits_CuckooRefinableSet<traits_CuckooSet_vector_ord_storehash>> CuckooRefinableSet_vector_ord_storehash;
+
+ };
+
+ template <typename T, typename Traits >
+ static inline void print_stat( cds_test::property_stream& o, cc::CuckooSet< T, Traits > const& s )
+ {
+ o << s.statistics() << s.mutex_policy_statistics();
+ }
+
+ template <typename V, typename Traits>
+ static inline void print_stat( cds_test::property_stream& o, CuckooSet< V, Traits > const& s )
+ {
+ typedef CuckooSet< V, Traits > set_type;
+ print_stat( o, static_cast<typename set_type::cuckoo_base_class const&>(s));
+ }
+
+} // namespace set
+
+#define CDSSTRESS_CuckooSet_case( fixture, test_case, cuckoo_set_type, key_type, value_type ) \
+ TEST_F( fixture, cuckoo_set_type ) \
+ { \
+ typedef set::set_type< tag_CuckooSet, key_type, value_type >::cuckoo_set_type set_type; \
+ test_case<set_type>(); \
+ }
+
+#define CDSSTRESS_CuckooSet( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooStripedSet_list_unord, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooRefinableSet_list_unord, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooStripedSet_list_unord_stat, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooRefinableSet_list_unord_stat, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooStripedSet_list_unord_storehash, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooRefinableSet_list_unord_storehash, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooStripedSet_list_ord, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooRefinableSet_list_ord, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooStripedSet_list_ord_stat, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooRefinableSet_list_ord_stat, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooStripedSet_list_ord_storehash, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooRefinableSet_list_ord_storehash, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooStripedSet_vector_unord, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooRefinableSet_vector_unord, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooStripedSet_vector_unord_stat, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooRefinableSet_vector_unord_stat, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooStripedSet_vector_unord_storehash, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooRefinableSet_vector_unord_storehash, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooStripedSet_vector_ord, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooRefinableSet_vector_ord, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooStripedSet_vector_ord_stat, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooRefinableSet_vector_ord_stat, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooStripedSet_vector_ord_storehash, key_type, value_type ) \
+ CDSSTRESS_CuckooSet_case( fixture, test_case, CuckooRefinableSet_vector_ord_storehash, key_type, value_type ) \
+
+
+#endif // #ifndef CDSUNIT_SET_TYPE_CUCKOO_H
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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.
+*/
+
+#ifndef CDSUNIT_SET_TYPE_ELLEN_BINTREE_H
+#define CDSUNIT_SET_TYPE_ELLEN_BINTREE_H
+
+#include "set_type.h"
+
+#include <cds/container/ellen_bintree_set_rcu.h>
+#include <cds/container/ellen_bintree_set_hp.h>
+#include <cds/container/ellen_bintree_set_dhp.h>
+
+#include <cds_test/stat_ellenbintree_out.h>
+#include "framework/ellen_bintree_update_desc_pool.h"
+
+namespace set {
+
+ template <class GC, typename Key, typename T, typename Traits = cc::ellen_bintree::traits >
+ class EllenBinTreeSet : public cc::EllenBinTreeSet< GC, Key, T, Traits >
+ {
+ typedef cc::EllenBinTreeSet< GC, Key, T, Traits > base_class;
+ public:
+ template <typename Config>
+ EllenBinTreeSet( Config const& /*cfg*/ )
+ {}
+
+ // for testing
+ static CDS_CONSTEXPR bool const c_bExtractSupported = true;
+ static CDS_CONSTEXPR bool const c_bLoadFactorDepended = false;
+ static CDS_CONSTEXPR bool const c_bEraseExactKey = false;
+ };
+
+ struct tag_EllenBinTreeSet;
+
+ template <typename Key, typename Val>
+ struct set_type< tag_EllenBinTreeSet, Key, Val >: public set_type_base< Key, Val >
+ {
+ typedef set_type_base< Key, Val > base_class;
+ typedef typename base_class::key_type key_type;
+ typedef typename base_class::key_val key_val;
+ typedef typename base_class::compare compare;
+ typedef typename base_class::less less;
+ typedef typename base_class::key_less key_less;
+
+ struct ellen_bintree_props {
+ struct key_extractor {
+ void operator()( key_type& dest, key_val const& src ) const
+ {
+ dest = src.key;
+ }
+ };
+
+ struct less {
+ bool operator()( key_val const& v1, key_val const& v2 ) const
+ {
+ return key_less()( v1.key, v2.key );
+ }
+ bool operator()( key_type const& k, key_val const& v ) const
+ {
+ return key_less()( k, v.key );
+ }
+ bool operator()( key_val const& v, key_type const& k ) const
+ {
+ return key_less()( v.key, k );
+ }
+ bool operator()( key_type const& k1, key_type const& k2 ) const
+ {
+ return key_less()( k1, k2 );
+ }
+ };
+
+ struct hp_gc {
+ typedef cc::ellen_bintree::node<cds::gc::HP, key_val> leaf_node;
+ typedef cc::ellen_bintree::internal_node< key_type, leaf_node > internal_node;
+ typedef cc::ellen_bintree::update_desc< leaf_node, internal_node > update_desc;
+ };
+
+ struct dhp_gc {
+ typedef cc::ellen_bintree::node<cds::gc::DHP, key_val> leaf_node;
+ typedef cc::ellen_bintree::internal_node< key_type, leaf_node > internal_node;
+ typedef cc::ellen_bintree::update_desc< leaf_node, internal_node > update_desc;
+ };
+
+ struct gpi {
+ typedef cc::ellen_bintree::node<rcu_gpi, key_val> leaf_node;
+ typedef cc::ellen_bintree::internal_node< key_type, leaf_node > internal_node;
+ typedef cc::ellen_bintree::update_desc< leaf_node, internal_node > update_desc;
+ };
+ struct gpb {
+ typedef cc::ellen_bintree::node<rcu_gpb, key_val> leaf_node;
+ typedef cc::ellen_bintree::internal_node< key_type, leaf_node > internal_node;
+ typedef cc::ellen_bintree::update_desc< leaf_node, internal_node > update_desc;
+ };
+ struct gpt {
+ typedef cc::ellen_bintree::node<rcu_gpt, key_val> leaf_node;
+ typedef cc::ellen_bintree::internal_node< key_type, leaf_node > internal_node;
+ typedef cc::ellen_bintree::update_desc< leaf_node, internal_node > update_desc;
+ };
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ struct shb {
+ typedef cc::ellen_bintree::node<rcu_shb, key_val> leaf_node;
+ typedef cc::ellen_bintree::internal_node< key_type, leaf_node > internal_node;
+ typedef cc::ellen_bintree::update_desc< leaf_node, internal_node > update_desc;
+ };
+#endif
+ };
+
+ struct traits_EllenBinTreeSet: public cc::ellen_bintree::make_set_traits<
+ cc::ellen_bintree::key_extractor< typename ellen_bintree_props::key_extractor >
+ ,co::less< typename ellen_bintree_props::less >
+ ,co::node_allocator< ellen_bintree_pool::internal_node_allocator< int > >
+ ,co::item_counter<cds::atomicity::cache_friendly_item_counter >
+ >::type
+ {};
+
+ struct traits_EllenBinTreeSet_hp : public traits_EllenBinTreeSet
+ {
+ typedef cds::memory::pool_allocator< typename ellen_bintree_props::hp_gc::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator;
+ };
+ typedef EllenBinTreeSet< cds::gc::HP, key_type, key_val, traits_EllenBinTreeSet_hp > EllenBinTreeSet_hp;
+
+ struct traits_EllenBinTreeSet_dhp : public traits_EllenBinTreeSet
+ {
+ typedef cds::memory::pool_allocator< typename ellen_bintree_props::dhp_gc::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator;
+ };
+ typedef EllenBinTreeSet< cds::gc::DHP, key_type, key_val, traits_EllenBinTreeSet_dhp > EllenBinTreeSet_dhp;
+
+ struct traits_EllenBinTreeSet_gpi : public traits_EllenBinTreeSet
+ {
+ typedef cds::memory::pool_allocator< typename ellen_bintree_props::gpi::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator;
+ };
+ typedef EllenBinTreeSet< rcu_gpi, key_type, key_val, traits_EllenBinTreeSet_gpi > EllenBinTreeSet_rcu_gpi;
+
+ struct traits_EllenBinTreeSet_gpb : public traits_EllenBinTreeSet
+ {
+ typedef cds::memory::pool_allocator< typename ellen_bintree_props::gpb::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator;
+ };
+ typedef EllenBinTreeSet< rcu_gpb, key_type, key_val, traits_EllenBinTreeSet_gpb > EllenBinTreeSet_rcu_gpb;
+
+ struct traits_EllenBinTreeSet_gpt : public traits_EllenBinTreeSet
+ {
+ typedef cds::memory::pool_allocator< typename ellen_bintree_props::gpt::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator;
+ };
+ typedef EllenBinTreeSet< rcu_gpt, key_type, key_val, traits_EllenBinTreeSet_gpt > EllenBinTreeSet_rcu_gpt;
+
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ struct traits_EllenBinTreeSet_shb : public traits_EllenBinTreeSet
+ {
+ typedef cds::memory::pool_allocator< typename ellen_bintree_props::shb::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator;
+ };
+ typedef EllenBinTreeSet< rcu_shb, key_type, key_val, traits_EllenBinTreeSet_shb > EllenBinTreeSet_rcu_shb;
+#endif
+
+ //
+ struct traits_EllenBinTreeSet_yield : public traits_EllenBinTreeSet
+ {
+ typedef cds::backoff::yield back_off;
+ };
+
+ struct traits_EllenBinTreeSet_yield_hp : public traits_EllenBinTreeSet_yield
+ {
+ typedef cds::memory::pool_allocator< typename ellen_bintree_props::hp_gc::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator;
+ };
+ typedef EllenBinTreeSet< cds::gc::HP, key_type, key_val, traits_EllenBinTreeSet_yield_hp > EllenBinTreeSet_yield_hp;
+
+ struct traits_EllenBinTreeSet_yield_dhp : public traits_EllenBinTreeSet_yield
+ {
+ typedef cds::memory::pool_allocator< typename ellen_bintree_props::dhp_gc::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator;
+ };
+ typedef EllenBinTreeSet< cds::gc::DHP, key_type, key_val, traits_EllenBinTreeSet_yield_dhp > EllenBinTreeSet_yield_dhp;
+
+
+ struct traits_EllenBinTreeSet_yield_gpb : public traits_EllenBinTreeSet_yield
+ {
+ typedef cds::memory::pool_allocator< typename ellen_bintree_props::gpb::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator;
+ };
+ typedef EllenBinTreeSet< rcu_gpb, key_type, key_val, traits_EllenBinTreeSet_yield_gpb > EllenBinTreeSet_yield_rcu_gpb;
+
+
+ struct traits_EllenBinTreeSet_stat: public cc::ellen_bintree::make_set_traits<
+ cc::ellen_bintree::key_extractor< typename ellen_bintree_props::key_extractor >
+ ,co::less< typename ellen_bintree_props::less >
+ ,co::node_allocator< ellen_bintree_pool::internal_node_allocator< int > >
+ ,co::stat< cc::ellen_bintree::stat<> >
+ ,co::item_counter<cds::atomicity::cache_friendly_item_counter >
+ >::type
+ {};
+
+ struct traits_EllenBinTreeSet_stat_hp : public traits_EllenBinTreeSet_stat
+ {
+ typedef cds::memory::pool_allocator< typename ellen_bintree_props::hp_gc::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator;
+ };
+ typedef EllenBinTreeSet< cds::gc::HP, key_type, key_val, traits_EllenBinTreeSet_stat_hp > EllenBinTreeSet_hp_stat;
+
+ struct traits_EllenBinTreeSet_stat_dhp : public traits_EllenBinTreeSet_stat
+ {
+ typedef cds::memory::pool_allocator< typename ellen_bintree_props::dhp_gc::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator;
+ };
+ typedef EllenBinTreeSet< cds::gc::DHP, key_type, key_val, traits_EllenBinTreeSet_stat_dhp > EllenBinTreeSet_dhp_stat;
+
+ struct traits_EllenBinTreeSet_stat_gpi : public traits_EllenBinTreeSet_stat
+ {
+ typedef cds::memory::pool_allocator< typename ellen_bintree_props::gpi::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator;
+ };
+ typedef EllenBinTreeSet< rcu_gpi, key_type, key_val, traits_EllenBinTreeSet_stat_gpi > EllenBinTreeSet_rcu_gpi_stat;
+
+ struct traits_EllenBinTreeSet_stat_gpb : public traits_EllenBinTreeSet_stat
+ {
+ typedef cds::memory::pool_allocator< typename ellen_bintree_props::gpb::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator;
+ };
+ typedef EllenBinTreeSet< rcu_gpb, key_type, key_val, traits_EllenBinTreeSet_stat_gpb > EllenBinTreeSet_rcu_gpb_stat;
+
+ struct traits_EllenBinTreeSet_stat_gpt : public traits_EllenBinTreeSet_stat
+ {
+ typedef cds::memory::pool_allocator< typename ellen_bintree_props::gpt::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator;
+ };
+ typedef EllenBinTreeSet< rcu_gpt, key_type, key_val, traits_EllenBinTreeSet_stat_gpt > EllenBinTreeSet_rcu_gpt_stat;
+
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ struct traits_EllenBinTreeSet_stat_shb : public traits_EllenBinTreeSet_stat
+ {
+ typedef cds::memory::pool_allocator< typename ellen_bintree_props::shb::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator;
+ };
+ typedef EllenBinTreeSet< rcu_shb, key_type, key_val, traits_EllenBinTreeSet_stat_shb > EllenBinTreeSet_rcu_shb_stat;
+#endif
+
+ };
+
+ template <typename GC, typename Key, typename T, typename Traits>
+ static inline void print_stat( cds_test::property_stream& o, EllenBinTreeSet<GC, Key, T, Traits> const& s )
+ {
+ o << s.statistics();
+ }
+
+ namespace ellen_bintree_check {
+ static inline void check_stat( cds::intrusive::ellen_bintree::empty_stat const& /*s*/ )
+ {
+ // Not true for threaded RCU
+ /*
+ EXPECT_EQ( ellen_bintree_pool::internal_node_counter::m_nAlloc.get(), ellen_bintree_pool::internal_node_counter::m_nFree.get());
+ */
+ }
+ static inline void check_stat( cds::intrusive::ellen_bintree::stat<> const& stat )
+ {
+ EXPECT_EQ( stat.m_nInternalNodeCreated, stat.m_nInternalNodeDeleted );
+ EXPECT_EQ( stat.m_nUpdateDescCreated, stat.m_nUpdateDescDeleted );
+ //EXPECT_EQ( ellen_bintree_pool::internal_node_counter::m_nAlloc.get(), ellen_bintree_pool::internal_node_counter::m_nFree.get());
+ EXPECT_EQ( ellen_bintree_pool::internal_node_counter::m_nAlloc.get(), stat.m_nInternalNodeCreated );
+ // true if RCU is not threaded
+ //EXPECT_EQ( stat.m_nInternalNodeDeleted, ellen_bintree_pool::internal_node_counter::m_nFree.get());
+ }
+ } // namespace ellen_bintree_check
+
+ template <typename GC, typename Key, typename T, typename Traits>
+ static inline void additional_check( EllenBinTreeSet<GC, Key, T, Traits>& s )
+ {
+ //typedef EllenBinTreeSet<GC, Key, T, Traits> set_type;
+ GC::force_dispose();
+ ellen_bintree_check::check_stat( s.statistics());
+ }
+
+ template <typename GC, typename Key, typename T, typename Traits>
+ static inline void additional_cleanup( EllenBinTreeSet<GC, Key, T, Traits>& /*s*/ )
+ {
+ ellen_bintree_pool::internal_node_counter::reset();
+ }
+
+ template <typename GC, typename Key, typename T, typename Traits>
+ static inline void check_before_clear( cds::container::EllenBinTreeSet<GC, Key, T, Traits>& s )
+ {
+ EXPECT_TRUE( s.check_consistency());
+ }
+} // namespace set
+
+#define CDSSTRESS_EllenBinTreeSet_case( fixture, test_case, ellen_set_type, key_type, value_type ) \
+ TEST_F( fixture, ellen_set_type ) \
+ { \
+ typedef set::set_type< tag_EllenBinTreeSet, key_type, value_type >::ellen_set_type set_type; \
+ test_case<set_type>(); \
+ }
+
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+# define CDSSTRESS_EllenBinTreeSet_SHRCU( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_EllenBinTreeSet_case( fixture, test_case, EllenBinTreeSet_rcu_shb, key_type, value_type ) \
+
+#else
+# define CDSSTRESS_EllenBinTreeSet_SHRCU( fixture, test_case, key_type, value_type )
+#endif
+
+
+#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL > 0
+# define CDSSTRESS_EllenBinTreeSet_HP_1( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_EllenBinTreeSet_case( fixture, test_case, EllenBinTreeSet_yield_hp, key_type, value_type ) \
+ CDSSTRESS_EllenBinTreeSet_case( fixture, test_case, EllenBinTreeSet_yield_dhp, key_type, value_type ) \
+ CDSSTRESS_EllenBinTreeSet_case( fixture, test_case, EllenBinTreeSet_yield_rcu_gpb, key_type, value_type ) \
+
+# define CDSSTRESS_EllenBinTreeSet_RCU_1( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_EllenBinTreeSet_case( fixture, test_case, EllenBinTreeSet_rcu_gpi, key_type, value_type ) \
+ CDSSTRESS_EllenBinTreeSet_SHRCU( fixture, test_case, key_type, value_type )
+
+#else
+# define CDSSTRESS_EllenBinTreeSet_HP_1( fixture, test_case, key_type, value_type )
+# define CDSSTRESS_EllenBinTreeSet_RCU_1( fixture, test_case, key_type, value_type )
+#endif
+
+#define CDSSTRESS_EllenBinTreeSet_HP( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_EllenBinTreeSet_case( fixture, test_case, EllenBinTreeSet_hp, key_type, value_type ) \
+ CDSSTRESS_EllenBinTreeSet_case( fixture, test_case, EllenBinTreeSet_dhp, key_type, value_type ) \
+ CDSSTRESS_EllenBinTreeSet_HP_1( fixture, test_case, key_type, value_type ) \
+
+#define CDSSTRESS_EllenBinTreeSet_RCU( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_EllenBinTreeSet_case( fixture, test_case, EllenBinTreeSet_rcu_gpb, key_type, value_type ) \
+ CDSSTRESS_EllenBinTreeSet_case( fixture, test_case, EllenBinTreeSet_rcu_gpt, key_type, value_type ) \
+ CDSSTRESS_EllenBinTreeSet_RCU_1( fixture, test_case, key_type, value_type ) \
+
+#define CDSSTRESS_EllenBinTreeSet( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_EllenBinTreeSet_HP( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_EllenBinTreeSet_RCU( fixture, test_case, key_type, value_type ) \
+
+#endif // #ifndef CDSUNIT_SET_TYPE_ELLEN_BINTREE_H
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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.
+*/
+
+#ifndef CDSUNIT_SET_TYPE_FELDMAN_HASHSET_H
+#define CDSUNIT_SET_TYPE_FELDMAN_HASHSET_H
+
+#include "set/set_type.h"
+
+#include <cds/container/feldman_hashset_hp.h>
+#include <cds/container/feldman_hashset_dhp.h>
+#include <cds/container/feldman_hashset_rcu.h>
+
+#include <cds_test/stat_feldman_hashset_out.h>
+#include <cds_test/hash_func.h>
+
+namespace set {
+
+ template <class GC, typename T, typename Traits = cc::feldman_hashset::traits>
+ class FeldmanHashSet : public cc::FeldmanHashSet< GC, T, Traits >
+ {
+ typedef cc::FeldmanHashSet< GC, T, Traits > base_class;
+
+
+ template <typename GC2>
+ struct get_extracted_ptr
+ {
+ typedef typename base_class::guarded_ptr extracted_ptr;
+ };
+
+ template <typename RCU>
+ struct get_extracted_ptr<cds::urcu::gc<RCU>>
+ {
+ typedef typename base_class::exempt_ptr extracted_ptr;
+ };
+
+ public:
+ typedef typename T::hasher hasher;
+ typedef typename get_extracted_ptr<GC>::extracted_ptr extracted_ptr;
+
+ template <typename OtherTraits>
+ struct rebind_traits {
+ typedef FeldmanHashSet<GC, T, OtherTraits > result;
+ };
+
+ template <class Config>
+ FeldmanHashSet( Config const& cfg )
+ : base_class( cfg.s_nFeldmanSet_HeadBits, cfg.s_nFeldmanSet_ArrayBits )
+ {}
+
+ template <typename Q>
+ bool erase( Q const& key )
+ {
+ return base_class::erase( hasher()( key ));
+ }
+
+ template <typename Q, typename Func>
+ bool erase( Q const& key, Func f )
+ {
+ return base_class::erase( hasher()( key ), f );
+ }
+
+ template <typename Q>
+ extracted_ptr extract(Q const& key)
+ {
+ return base_class::extract( hasher()(key));
+ }
+
+ template <typename Q>
+ bool contains( Q const& key )
+ {
+ return base_class::contains( hasher()(key));
+ }
+
+ template <typename Iterator>
+ typename std::enable_if< std::is_same< Iterator, typename base_class::iterator>::value, Iterator>::type
+ get_begin()
+ {
+ return base_class::begin();
+ }
+
+ template <typename Iterator>
+ typename std::enable_if< std::is_same< Iterator, typename base_class::iterator>::value, Iterator>::type
+ get_end()
+ {
+ return base_class::end();
+ }
+
+ template <typename Iterator>
+ typename std::enable_if< std::is_same< Iterator, typename base_class::reverse_iterator>::value, Iterator>::type
+ get_begin()
+ {
+ return base_class::rbegin();
+ }
+
+ template <typename Iterator>
+ typename std::enable_if< std::is_same< Iterator, typename base_class::reverse_iterator>::value, Iterator>::type
+ get_end()
+ {
+ return base_class::rend();
+ }
+
+ // for testing
+ static CDS_CONSTEXPR bool const c_bExtractSupported = true;
+ static CDS_CONSTEXPR bool const c_bLoadFactorDepended = false;
+ static CDS_CONSTEXPR bool const c_bEraseExactKey = true;
+ };
+
+ struct tag_FeldmanHashSet;
+
+ template <typename Key, typename Val>
+ struct set_type< tag_FeldmanHashSet, Key, Val >: public set_type_base< Key, Val >
+ {
+ typedef set_type_base< Key, Val > base_class;
+ typedef typename base_class::compare compare;
+ typedef typename base_class::less less;
+ typedef typename base_class::hash hash;
+ typedef typename base_class::key_type key_type;
+ typedef typename base_class::value_type value_type;
+
+ template <typename Hasher>
+ struct hash_type
+ {
+ typedef Hasher hasher;
+ typedef typename hasher::hash_type type;
+ };
+
+ template <typename TH>
+ struct hash_type<std::hash<TH>>
+ {
+ typedef std::hash<TH> hasher;
+ typedef size_t type;
+ };
+
+ template <typename Hasher>
+ struct key_val: base_class::key_val
+ {
+ typedef typename base_class::key_val base;
+ typedef Hasher hasher;
+ typedef typename hash_type<hasher>::type hash_type;
+
+ hash_type hash;
+
+ explicit key_val( key_type const& k ): base(k), hash( hasher()( k )) {}
+ key_val( key_type const& k, value_type const& v ): base(k, v), hash( hasher()( k )) {}
+
+ template <typename K>
+ explicit key_val( K const& k ): base(k), hash( hasher()( k )) {}
+
+ template <typename K, typename T>
+ key_val( K const& k, T const& v ): base(k, v), hash( hasher()( k )) {}
+ };
+
+ struct default_traits : public cc::feldman_hashset::traits
+ {
+ struct hash_accessor {
+ template <typename Hasher>
+ typename key_val<Hasher>::hash_type const& operator()( key_val<Hasher> const& kv )
+ {
+ return kv.hash;
+ }
+ };
+ typedef cds::atomicity::cache_friendly_item_counter item_counter;
+ };
+
+ typedef FeldmanHashSet< cds::gc::HP, key_val<std::hash<key_type>>, default_traits > FeldmanHashSet_hp_stdhash;
+ typedef FeldmanHashSet< cds::gc::DHP, key_val<std::hash<key_type>>, default_traits > FeldmanHashSet_dhp_stdhash;
+ typedef FeldmanHashSet< rcu_gpi, key_val<std::hash<key_type>>, default_traits > FeldmanHashSet_rcu_gpi_stdhash;
+ typedef FeldmanHashSet< rcu_gpb, key_val<std::hash<key_type>>, default_traits > FeldmanHashSet_rcu_gpb_stdhash;
+ typedef FeldmanHashSet< rcu_gpt, key_val<std::hash<key_type>>, default_traits > FeldmanHashSet_rcu_gpt_stdhash;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef FeldmanHashSet< rcu_shb, key_val<std::hash<key_type>>, default_traits > FeldmanHashSet_rcu_shb_stdhash;
+#endif
+
+ struct traits_FeldmanHashSet_stat: public cc::feldman_hashset::make_traits<
+ co::type_traits< default_traits >,
+ co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ {};
+
+ typedef FeldmanHashSet< cds::gc::HP, key_val<std::hash<key_type>>, traits_FeldmanHashSet_stat > FeldmanHashSet_hp_stdhash_stat;
+ typedef FeldmanHashSet< cds::gc::DHP, key_val<std::hash<key_type>>, traits_FeldmanHashSet_stat > FeldmanHashSet_dhp_stdhash_stat;
+ typedef FeldmanHashSet< rcu_gpi, key_val<std::hash<key_type>>, traits_FeldmanHashSet_stat > FeldmanHashSet_rcu_gpi_stdhash_stat;
+ typedef FeldmanHashSet< rcu_gpb, key_val<std::hash<key_type>>, traits_FeldmanHashSet_stat > FeldmanHashSet_rcu_gpb_stdhash_stat;
+ typedef FeldmanHashSet< rcu_gpt, key_val<std::hash<key_type>>, traits_FeldmanHashSet_stat > FeldmanHashSet_rcu_gpt_stdhash_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef FeldmanHashSet< rcu_shb, key_val<std::hash<key_type>>, traits_FeldmanHashSet_stat > FeldmanHashSet_rcu_shb_stdhash_stat;
+#endif
+
+ // CityHash
+#if CDS_BUILD_BITS == 64
+ struct traits_FeldmanHashSet_city64 : public default_traits
+ {
+ typedef ::cds_test::city64::less less;
+ };
+ typedef FeldmanHashSet< cds::gc::HP, key_val<::cds_test::city64>, traits_FeldmanHashSet_city64 > FeldmanHashSet_hp_city64;
+ typedef FeldmanHashSet< cds::gc::DHP, key_val<::cds_test::city64>, traits_FeldmanHashSet_city64 > FeldmanHashSet_dhp_city64;
+ typedef FeldmanHashSet< rcu_gpi, key_val<::cds_test::city64>, traits_FeldmanHashSet_city64 > FeldmanHashSet_rcu_gpi_city64;
+ typedef FeldmanHashSet< rcu_gpb, key_val<::cds_test::city64>, traits_FeldmanHashSet_city64 > FeldmanHashSet_rcu_gpb_city64;
+ typedef FeldmanHashSet< rcu_gpt, key_val<::cds_test::city64>, traits_FeldmanHashSet_city64 > FeldmanHashSet_rcu_gpt_city64;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef FeldmanHashSet< rcu_shb, key_val<::cds_test::city64>, traits_FeldmanHashSet_city64 > FeldmanHashSet_rcu_shb_city64;
+#endif
+
+ struct traits_FeldmanHashSet_city64_stat : public traits_FeldmanHashSet_city64
+ {
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef FeldmanHashSet< cds::gc::HP, key_val<::cds_test::city64>, traits_FeldmanHashSet_city64_stat > FeldmanHashSet_hp_city64_stat;
+ typedef FeldmanHashSet< cds::gc::DHP, key_val<::cds_test::city64>, traits_FeldmanHashSet_city64_stat > FeldmanHashSet_dhp_city64_stat;
+ typedef FeldmanHashSet< rcu_gpi, key_val<::cds_test::city64>, traits_FeldmanHashSet_city64_stat > FeldmanHashSet_rcu_gpi_city64_stat;
+ typedef FeldmanHashSet< rcu_gpb, key_val<::cds_test::city64>, traits_FeldmanHashSet_city64_stat > FeldmanHashSet_rcu_gpb_city64_stat;
+ typedef FeldmanHashSet< rcu_gpt, key_val<::cds_test::city64>, traits_FeldmanHashSet_city64_stat > FeldmanHashSet_rcu_gpt_city64_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef FeldmanHashSet< rcu_shb, key_val<::cds_test::city64>, traits_FeldmanHashSet_city64_stat > FeldmanHashSet_rcu_shb_city64_stat;
+#endif
+
+ struct traits_FeldmanHashSet_city128 : public default_traits
+ {
+ typedef ::cds_test::city128::less less;
+ };
+ typedef FeldmanHashSet< cds::gc::HP, key_val<::cds_test::city128>, traits_FeldmanHashSet_city128 > FeldmanHashSet_hp_city128;
+ typedef FeldmanHashSet< cds::gc::DHP, key_val<::cds_test::city128>, traits_FeldmanHashSet_city128 > FeldmanHashSet_dhp_city128;
+ typedef FeldmanHashSet< rcu_gpi, key_val<::cds_test::city128>, traits_FeldmanHashSet_city128 > FeldmanHashSet_rcu_gpi_city128;
+ typedef FeldmanHashSet< rcu_gpb, key_val<::cds_test::city128>, traits_FeldmanHashSet_city128 > FeldmanHashSet_rcu_gpb_city128;
+ typedef FeldmanHashSet< rcu_gpt, key_val<::cds_test::city128>, traits_FeldmanHashSet_city128 > FeldmanHashSet_rcu_gpt_city128;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef FeldmanHashSet< rcu_shb, key_val<::cds_test::city128>, traits_FeldmanHashSet_city128 > FeldmanHashSet_rcu_shb_city128;
+#endif
+
+ struct traits_FeldmanHashSet_city128_stat : public traits_FeldmanHashSet_city128
+ {
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef FeldmanHashSet< cds::gc::HP, key_val<::cds_test::city128>, traits_FeldmanHashSet_city128_stat > FeldmanHashSet_hp_city128_stat;
+ typedef FeldmanHashSet< cds::gc::DHP, key_val<::cds_test::city128>, traits_FeldmanHashSet_city128_stat > FeldmanHashSet_dhp_city128_stat;
+ typedef FeldmanHashSet< rcu_gpi, key_val<::cds_test::city128>, traits_FeldmanHashSet_city128_stat > FeldmanHashSet_rcu_gpi_city128_stat;
+ typedef FeldmanHashSet< rcu_gpb, key_val<::cds_test::city128>, traits_FeldmanHashSet_city128_stat > FeldmanHashSet_rcu_gpb_city128_stat;
+ typedef FeldmanHashSet< rcu_gpt, key_val<::cds_test::city128>, traits_FeldmanHashSet_city128_stat > FeldmanHashSet_rcu_gpt_city128_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef FeldmanHashSet< rcu_shb, key_val<::cds_test::city128>, traits_FeldmanHashSet_city128_stat > FeldmanHashSet_rcu_shb_city128_stat;
+#endif
+
+#endif // #if CDS_BUILD_BITS == 64
+
+
+ // for fixed-sized key
+ // No hash function is necessary
+
+ struct fixed_sized_key
+ {
+ typedef typename set_type_base< Key, Val >::key_type key_type;
+ struct key_val : public set_type_base< Key, Val >::key_val
+ {
+ typedef typename set_type_base< Key, Val >::key_val base_class;
+
+ explicit key_val(key_type const& k) : base_class(k) {}
+ key_val(key_type const& k, value_type const& v) : base_class(k, v) {}
+
+ template <typename K>
+ explicit key_val(K const& k) : base_class(k) {}
+
+ template <typename K, typename T>
+ key_val(K const& k, T const& v) : base_class(k, v) {}
+
+ // mock hasher
+ struct hasher {
+ template <typename Q>
+ key_type operator()( Q const& k ) const
+ {
+ return key_type( k );
+ }
+
+ key_type const& operator()( key_val const& kv ) const
+ {
+ return kv.key;
+ }
+
+ key_type const& operator()( key_type const& k ) const
+ {
+ return k;
+ }
+ };
+ };
+
+ struct traits : public cc::feldman_hashset::traits
+ {
+ struct hash_accessor {
+ key_type const& operator()( key_val const& kv ) const
+ {
+ return kv.key;
+ }
+
+ key_type const& operator()( key_type const& k ) const
+ {
+ return k;
+ }
+ };
+
+ typedef set::cmp<Key> compare;
+ typedef cds::atomicity::cache_friendly_item_counter item_counter;
+ };
+
+ struct traits_stat : public traits
+ {
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ };
+
+ typedef FeldmanHashSet< cds::gc::HP, typename fixed_sized_key::key_val, typename fixed_sized_key::traits > FeldmanHashSet_hp_fixed;
+ typedef FeldmanHashSet< cds::gc::DHP, typename fixed_sized_key::key_val, typename fixed_sized_key::traits > FeldmanHashSet_dhp_fixed;
+ typedef FeldmanHashSet< rcu_gpi, typename fixed_sized_key::key_val, typename fixed_sized_key::traits > FeldmanHashSet_rcu_gpi_fixed;
+ typedef FeldmanHashSet< rcu_gpb, typename fixed_sized_key::key_val, typename fixed_sized_key::traits > FeldmanHashSet_rcu_gpb_fixed;
+ typedef FeldmanHashSet< rcu_gpt, typename fixed_sized_key::key_val, typename fixed_sized_key::traits > FeldmanHashSet_rcu_gpt_fixed;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef FeldmanHashSet< rcu_shb, typename fixed_sized_key::key_val, typename fixed_sized_key::traits > FeldmanHashSet_rcu_shb_fixed;
+#endif
+
+ typedef FeldmanHashSet< cds::gc::HP, typename fixed_sized_key::key_val, typename fixed_sized_key::traits_stat > FeldmanHashSet_hp_fixed_stat;
+ typedef FeldmanHashSet< cds::gc::DHP, typename fixed_sized_key::key_val, typename fixed_sized_key::traits_stat > FeldmanHashSet_dhp_fixed_stat;
+ typedef FeldmanHashSet< rcu_gpi, typename fixed_sized_key::key_val, typename fixed_sized_key::traits_stat > FeldmanHashSet_rcu_gpi_fixed_stat;
+ typedef FeldmanHashSet< rcu_gpb, typename fixed_sized_key::key_val, typename fixed_sized_key::traits_stat > FeldmanHashSet_rcu_gpb_fixed_stat;
+ typedef FeldmanHashSet< rcu_gpt, typename fixed_sized_key::key_val, typename fixed_sized_key::traits_stat > FeldmanHashSet_rcu_gpt_fixed_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef FeldmanHashSet< rcu_shb, typename fixed_sized_key::key_val, typename fixed_sized_key::traits_stat > FeldmanHashSet_rcu_shb_fixed_stat;
+#endif
+
+ };
+
+ template <typename GC, typename T, typename Traits >
+ static inline void print_stat( cds_test::property_stream& o, FeldmanHashSet< GC, T, Traits > const& s )
+ {
+ std::vector< cds::intrusive::feldman_hashset::level_statistics > level_stat;
+ s.get_level_statistics( level_stat );
+
+ o << s.statistics()
+ << level_stat;
+ }
+} // namespace set
+
+#define CDSSTRESS_FeldmanHashSet_case( fixture, test_case, feldman_set_type, key_type, value_type ) \
+ TEST_F( fixture, feldman_set_type ) \
+ { \
+ typedef set::set_type< tag_FeldmanHashSet, key_type, value_type >::feldman_set_type set_type; \
+ test_case<set_type>(); \
+ }
+
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+# define CDSSTRESS_FeldmanHashSet_fixed_SHRCU( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_rcu_shb_fixed, key_type, value_type ) \
+
+# define CDSSTRESS_FeldmanHashSet_stdhash_SHRCU( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_rcu_shb_stdhash, key_type, value_type ) \
+
+# if CDS_BUILD_BITS == 64
+# define CDSSTRESS_FeldmanHashSet_city_SHRCU( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_rcu_shb_city64, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_rcu_shb_city128, key_type, value_type ) \
+
+# else
+# define CDSSTRESS_FeldmanHashSet_city_SHRCU( fixture, test_case, key_type, value_type )
+# endif
+
+#else
+# define CDSSTRESS_FeldmanHashSet_fixed_SHRCU( fixture, test_case, key_type, value_type )
+# define CDSSTRESS_FeldmanHashSet_stdhash_SHRCU( fixture, test_case, key_type, value_type )
+# define CDSSTRESS_FeldmanHashSet_city_SHRCU( fixture, test_case, key_type, value_type )
+#endif
+
+
+#define CDSSTRESS_FeldmanHashSet_fixed_RCU( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_rcu_gpi_fixed, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_rcu_gpb_fixed, key_type, value_type ) \
+ //CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_rcu_gpt_fixed, key_type, value_type ) \
+
+ //CDSSTRESS_FeldmanHashSet_fixed_SHRCU( fixture, test_case, key_type, value_type )
+
+#define CDSSTRESS_FeldmanHashSet_fixed_HP( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_hp_fixed, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_dhp_fixed, key_type, value_type ) \
+
+#define CDSSTRESS_FeldmanHashSet_fixed( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_fixed_HP( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_fixed_RCU( fixture, test_case, key_type, value_type ) \
+
+#define CDSSTRESS_FeldmanHashSet_stdhash_rcu_gpi( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_rcu_gpi_stdhash, key_type, value_type ) \
+
+#define CDSSTRESS_FeldmanHashSet_stdhash_HP( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_hp_stdhash, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_dhp_stdhash, key_type, value_type ) \
+
+#define CDSSTRESS_FeldmanHashSet_stdhash_RCU( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_rcu_gpb_stdhash, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_rcu_gpt_stdhash, key_type, value_type ) \
+
+ //CDSSTRESS_FeldmanHashSet_stdhash_SHRCU( fixture, test_case, key_type, value_type )
+
+#define CDSSTRESS_FeldmanHashSet_stdhash( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_stdhash_HP( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_stdhash_RCU( fixture, test_case, key_type, value_type ) \
+
+#if CDS_BUILD_BITS == 64
+# define CDSSTRESS_FeldmanHashSet_city_rcu_gpi( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_rcu_gpi_city64, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_rcu_gpi_city128, key_type, value_type ) \
+
+# define CDSSTRESS_FeldmanHashSet_city_HP( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_hp_city64, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_dhp_city64, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_hp_city128, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_dhp_city128, key_type, value_type ) \
+
+# define CDSSTRESS_FeldmanHashSet_city_RCU( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_rcu_gpb_city64, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_rcu_gpt_city64, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_rcu_gpb_city128, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_case( fixture, test_case, FeldmanHashSet_rcu_gpt_city128, key_type, value_type ) \
+
+ //CDSSTRESS_FeldmanHashSet_city_SHRCU( fixture, test_case, key_type, value_type )
+
+# define CDSSTRESS_FeldmanHashSet_city( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_city_HP( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_FeldmanHashSet_city_RCU( fixture, test_case, key_type, value_type ) \
+
+
+#else
+# define CDSSTRESS_FeldmanHashSet_city_rcu_gpi( fixture, test_case, key_type, value_type )
+# define CDSSTRESS_FeldmanHashSet_city_HP( fixture, test_case, key_type, value_type )
+# define CDSSTRESS_FeldmanHashSet_city_RCU( fixture, test_case, key_type, value_type )
+# define CDSSTRESS_FeldmanHashSet_city( fixture, test_case, key_type, value_type )
+#endif
+
+#endif // #ifndef CDSUNIT_SET_TYPE_FELDMAN_HASHSET_H
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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.
+*/
+
+#ifndef CDSUNIT_SET_TYPE_ITRERABLE_LIST_H
+#define CDSUNIT_SET_TYPE_ITRERABLE_LIST_H
+
+#include "set_type.h"
+
+#include <cds/container/iterable_list_hp.h>
+#include <cds/container/iterable_list_dhp.h>
+//#include <cds/container/michael_list_rcu.h>
+
+namespace set {
+
+ template <typename Key, typename Val>
+ struct iterable_list_type
+ {
+ typedef typename set_type_base< Key, Val >::key_val key_val;
+ typedef typename set_type_base< Key, Val >::compare compare;
+ typedef typename set_type_base< Key, Val >::less less;
+
+ struct traits_IterableList_cmp:
+ public cc::iterable_list::make_traits<
+ co::compare< compare >
+ >::type
+ {};
+ typedef cc::IterableList< cds::gc::HP, key_val, traits_IterableList_cmp > IterableList_HP_cmp;
+ typedef cc::IterableList< cds::gc::DHP, key_val, traits_IterableList_cmp > IterableList_DHP_cmp;
+
+ struct traits_IterableList_cmp_stat: public traits_IterableList_cmp
+ {
+ typedef cc::iterable_list::stat<> stat;
+ };
+ typedef cc::IterableList< cds::gc::HP, key_val, traits_IterableList_cmp_stat > IterableList_HP_cmp_stat;
+ typedef cc::IterableList< cds::gc::DHP, key_val, traits_IterableList_cmp_stat > IterableList_DHP_cmp_stat;
+
+ struct traits_IterableList_cmp_seqcst : public traits_IterableList_cmp
+ {
+ typedef co::v::sequential_consistent memory_model;
+ };
+ typedef cc::IterableList< cds::gc::HP, key_val, traits_IterableList_cmp_seqcst > IterableList_HP_cmp_seqcst;
+ typedef cc::IterableList< cds::gc::DHP, key_val, traits_IterableList_cmp_seqcst > IterableList_DHP_cmp_seqcst;
+
+ struct traits_IterableList_less :
+ public cc::iterable_list::make_traits<
+ co::less< less >
+ >::type
+ {};
+ typedef cc::IterableList< cds::gc::HP, key_val, traits_IterableList_less > IterableList_HP_less;
+ typedef cc::IterableList< cds::gc::DHP, key_val, traits_IterableList_less > IterableList_DHP_less;
+
+ struct traits_IterableList_less_stat : public traits_IterableList_less
+ {
+ typedef cc::iterable_list::stat<> stat;
+ };
+ typedef cc::IterableList< cds::gc::HP, key_val, traits_IterableList_less_stat > IterableList_HP_less_stat;
+ typedef cc::IterableList< cds::gc::DHP, key_val, traits_IterableList_less_stat > IterableList_DHP_less_stat;
+
+ struct traits_IterableList_less_seqcst :
+ public cc::iterable_list::make_traits<
+ co::less< less >
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ {};
+ typedef cc::IterableList< cds::gc::HP, key_val, traits_IterableList_less_seqcst > IterableList_HP_less_seqcst;
+ typedef cc::IterableList< cds::gc::DHP, key_val, traits_IterableList_less_seqcst > IterableList_DHP_less_seqcst;
+
+ };
+
+} // namespace set
+
+#endif // #ifndef CDSUNIT_SET_TYPE_ITRERABLE_LIST_H
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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.
+*/
+
+#ifndef CDSUNIT_SET_TYPE_LAZY_LIST_H
+#define CDSUNIT_SET_TYPE_LAZY_LIST_H
+
+#include "set_type.h"
+
+#include <cds/container/lazy_list_hp.h>
+#include <cds/container/lazy_list_dhp.h>
+#include <cds/container/lazy_list_rcu.h>
+
+namespace set {
+
+ template <typename Key, typename Val>
+ struct lazy_list_type
+ {
+ typedef typename set_type_base< Key, Val >::key_val key_val;
+ typedef typename set_type_base< Key, Val >::compare compare;
+ typedef typename set_type_base< Key, Val >::less less;
+
+ struct traits_LazyList_cmp :
+ public cc::lazy_list::make_traits<
+ co::compare< compare >
+ >::type
+ {};
+ typedef cc::LazyList< cds::gc::HP, key_val, traits_LazyList_cmp > LazyList_HP_cmp;
+ typedef cc::LazyList< cds::gc::DHP, key_val, traits_LazyList_cmp > LazyList_DHP_cmp;
+ typedef cc::LazyList< rcu_gpi, key_val, traits_LazyList_cmp > LazyList_RCU_GPI_cmp;
+ typedef cc::LazyList< rcu_gpb, key_val, traits_LazyList_cmp > LazyList_RCU_GPB_cmp;
+ typedef cc::LazyList< rcu_gpt, key_val, traits_LazyList_cmp > LazyList_RCU_GPT_cmp;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef cc::LazyList< rcu_shb, key_val, traits_LazyList_cmp > LazyList_RCU_SHB_cmp;
+#endif
+
+ struct traits_LazyList_cmp_stat : public traits_LazyList_cmp
+ {
+ typedef cc::lazy_list::stat<> stat;
+ };
+ typedef cc::LazyList< cds::gc::HP, key_val, traits_LazyList_cmp_stat > LazyList_HP_cmp_stat;
+ typedef cc::LazyList< cds::gc::DHP, key_val, traits_LazyList_cmp_stat > LazyList_DHP_cmp_stat;
+ typedef cc::LazyList< rcu_gpi, key_val, traits_LazyList_cmp_stat > LazyList_RCU_GPI_cmp_stat;
+ typedef cc::LazyList< rcu_gpb, key_val, traits_LazyList_cmp_stat > LazyList_RCU_GPB_cmp_stat;
+ typedef cc::LazyList< rcu_gpt, key_val, traits_LazyList_cmp_stat > LazyList_RCU_GPT_cmp_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef cc::LazyList< rcu_shb, key_val, traits_LazyList_cmp_stat > LazyList_RCU_SHB_cmp_stat;
+#endif
+
+ struct traits_LazyList_cmp_seqcst :
+ public cc::lazy_list::make_traits<
+ co::compare< compare >
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ {};
+ typedef cc::LazyList< cds::gc::HP, key_val, traits_LazyList_cmp_seqcst > LazyList_HP_cmp_seqcst;
+ typedef cc::LazyList< cds::gc::DHP, key_val, traits_LazyList_cmp_seqcst > LazyList_DHP_cmp_seqcst;
+ typedef cc::LazyList< rcu_gpi, key_val, traits_LazyList_cmp_seqcst > LazyList_RCU_GPI_cmp_seqcst;
+ typedef cc::LazyList< rcu_gpb, key_val, traits_LazyList_cmp_seqcst > LazyList_RCU_GPB_cmp_seqcst;
+ typedef cc::LazyList< rcu_gpt, key_val, traits_LazyList_cmp_seqcst > LazyList_RCU_GPT_cmp_seqcst;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef cc::LazyList< rcu_shb, key_val, traits_LazyList_cmp_seqcst > LazyList_RCU_SHB_cmp_seqcst;
+#endif
+
+ struct traits_LazyList_less:
+ public cc::lazy_list::make_traits<
+ co::less< less >
+ >::type
+ {};
+ typedef cc::LazyList< cds::gc::HP, key_val, traits_LazyList_less > LazyList_HP_less;
+ typedef cc::LazyList< cds::gc::DHP, key_val, traits_LazyList_less > LazyList_DHP_less;
+ typedef cc::LazyList< rcu_gpi, key_val, traits_LazyList_less > LazyList_RCU_GPI_less;
+ typedef cc::LazyList< rcu_gpb, key_val, traits_LazyList_less > LazyList_RCU_GPB_less;
+ typedef cc::LazyList< rcu_gpt, key_val, traits_LazyList_less > LazyList_RCU_GPT_less;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef cc::LazyList< rcu_shb, key_val, traits_LazyList_less > LazyList_RCU_SHB_less;
+#endif
+
+ struct traits_LazyList_less_stat: public traits_LazyList_less
+ {
+ typedef cc::lazy_list::stat<> stat;
+ };
+ typedef cc::LazyList< cds::gc::HP, key_val, traits_LazyList_less_stat > LazyList_HP_less_stat;
+ typedef cc::LazyList< cds::gc::DHP, key_val, traits_LazyList_less_stat > LazyList_DHP_less_stat;
+ typedef cc::LazyList< rcu_gpi, key_val, traits_LazyList_less_stat > LazyList_RCU_GPI_less_stat;
+ typedef cc::LazyList< rcu_gpb, key_val, traits_LazyList_less_stat > LazyList_RCU_GPB_less_stat;
+ typedef cc::LazyList< rcu_gpt, key_val, traits_LazyList_less_stat > LazyList_RCU_GPT_less_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef cc::LazyList< rcu_shb, key_val, traits_LazyList_less_stat > LazyList_RCU_SHB_less_stat;
+#endif
+
+ struct traits_LazyList_less_seqcst :
+ public cc::lazy_list::make_traits<
+ co::less< less >
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ {};
+ typedef cc::LazyList< cds::gc::HP, key_val, traits_LazyList_less_seqcst > LazyList_HP_less_seqcst;
+ typedef cc::LazyList< cds::gc::DHP, key_val, traits_LazyList_less_seqcst > LazyList_DHP_less_seqcst;
+ typedef cc::LazyList< rcu_gpi, key_val, traits_LazyList_less_seqcst > LazyList_RCU_GPI_less_seqcst;
+ typedef cc::LazyList< rcu_gpb, key_val, traits_LazyList_less_seqcst > LazyList_RCU_GPB_less_seqcst;
+ typedef cc::LazyList< rcu_gpt, key_val, traits_LazyList_less_seqcst > LazyList_RCU_GPT_less_seqcst;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef cc::LazyList< rcu_shb, key_val, traits_LazyList_less_seqcst > LazyList_RCU_SHB_less_seqcst;
+#endif
+
+ };
+
+} // namespace set
+
+#endif // #ifndef CDSUNIT_SET_TYPE_LAZY_LIST_H
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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.
+*/
+
+#ifndef CDSUNIT_SET_TYPE_MICHAEL_H
+#define CDSUNIT_SET_TYPE_MICHAEL_H
+
+#include "set_type_michael_list.h"
+#include "set_type_lazy_list.h"
+#include "set_type_iterable_list.h"
+
+#include <cds/container/michael_set.h>
+#include <cds/container/michael_set_rcu.h>
+
+#include <cds_test/stat_michael_list_out.h>
+#include <cds_test/stat_lazy_list_out.h>
+#include <cds_test/stat_iterable_list_out.h>
+
+namespace set {
+
+ template <class GC, typename List, typename Traits = cc::michael_set::traits>
+ class MichaelHashSet : public cc::MichaelHashSet< GC, List, Traits >
+ {
+ typedef cc::MichaelHashSet< GC, List, Traits > base_class;
+ public:
+ template <class Config>
+ MichaelHashSet( Config const& cfg )
+ : base_class( cfg.s_nSetSize, cfg.s_nLoadFactor )
+ {}
+
+ template <typename Iterator>
+ typename std::enable_if< std::is_same< Iterator, typename base_class::iterator>::value, Iterator>::type
+ get_begin()
+ {
+ return base_class::begin();
+ }
+
+ template <typename Iterator>
+ typename std::enable_if< std::is_same< Iterator, typename base_class::iterator>::value, Iterator>::type
+ get_end()
+ {
+ return base_class::end();
+ }
+
+ // for testing
+ static CDS_CONSTEXPR bool const c_bExtractSupported = true;
+ static CDS_CONSTEXPR bool const c_bLoadFactorDepended = true;
+ static CDS_CONSTEXPR bool const c_bEraseExactKey = false;
+ };
+
+ struct tag_MichaelHashSet;
+
+ template <typename Key, typename Val>
+ struct set_type< tag_MichaelHashSet, Key, Val >: public set_type_base< Key, Val >
+ {
+ typedef set_type_base< Key, Val > base_class;
+ typedef typename base_class::key_val key_val;
+ typedef typename base_class::compare compare;
+ typedef typename base_class::less less;
+ typedef typename base_class::hash hash;
+
+ // ***************************************************************************
+ // MichaelHashSet based on MichaelList
+
+ typedef michael_list_type< Key, Val > ml;
+
+ struct traits_MichaelSet :
+ public cc::michael_set::make_traits<
+ co::hash< hash >
+ ,co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ >::type
+ {};
+ typedef MichaelHashSet< cds::gc::HP, typename ml::MichaelList_HP_cmp, traits_MichaelSet > MichaelSet_HP_cmp;
+ typedef MichaelHashSet< cds::gc::DHP, typename ml::MichaelList_DHP_cmp, traits_MichaelSet > MichaelSet_DHP_cmp;
+ typedef MichaelHashSet< rcu_gpi, typename ml::MichaelList_RCU_GPI_cmp, traits_MichaelSet > MichaelSet_RCU_GPI_cmp;
+ typedef MichaelHashSet< rcu_gpb, typename ml::MichaelList_RCU_GPB_cmp, traits_MichaelSet > MichaelSet_RCU_GPB_cmp;
+ typedef MichaelHashSet< rcu_gpt, typename ml::MichaelList_RCU_GPT_cmp, traits_MichaelSet > MichaelSet_RCU_GPT_cmp;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef MichaelHashSet< rcu_shb, typename ml::MichaelList_RCU_SHB_cmp, traits_MichaelSet > MichaelSet_RCU_SHB_cmp;
+#endif
+
+ typedef MichaelHashSet< cds::gc::HP, typename ml::MichaelList_HP_cmp_stat, traits_MichaelSet > MichaelSet_HP_cmp_stat;
+ typedef MichaelHashSet< cds::gc::DHP, typename ml::MichaelList_DHP_cmp_stat, traits_MichaelSet > MichaelSet_DHP_cmp_stat;
+ typedef MichaelHashSet< rcu_gpi, typename ml::MichaelList_RCU_GPI_cmp_stat, traits_MichaelSet > MichaelSet_RCU_GPI_cmp_stat;
+ typedef MichaelHashSet< rcu_gpb, typename ml::MichaelList_RCU_GPB_cmp_stat, traits_MichaelSet > MichaelSet_RCU_GPB_cmp_stat;
+ typedef MichaelHashSet< rcu_gpt, typename ml::MichaelList_RCU_GPT_cmp_stat, traits_MichaelSet > MichaelSet_RCU_GPT_cmp_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef MichaelHashSet< rcu_shb, typename ml::MichaelList_RCU_SHB_cmp_stat, traits_MichaelSet > MichaelSet_RCU_SHB_cmp_stat;
+#endif
+
+ typedef MichaelHashSet< cds::gc::HP, typename ml::MichaelList_HP_less, traits_MichaelSet > MichaelSet_HP_less;
+ typedef MichaelHashSet< cds::gc::DHP, typename ml::MichaelList_DHP_less, traits_MichaelSet > MichaelSet_DHP_less;
+ typedef MichaelHashSet< rcu_gpi, typename ml::MichaelList_RCU_GPI_less, traits_MichaelSet > MichaelSet_RCU_GPI_less;
+ typedef MichaelHashSet< rcu_gpb, typename ml::MichaelList_RCU_GPB_less, traits_MichaelSet > MichaelSet_RCU_GPB_less;
+ typedef MichaelHashSet< rcu_gpt, typename ml::MichaelList_RCU_GPT_less, traits_MichaelSet > MichaelSet_RCU_GPT_less;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef MichaelHashSet< rcu_shb, typename ml::MichaelList_RCU_SHB_less, traits_MichaelSet > MichaelSet_RCU_SHB_less;
+#endif
+
+ typedef MichaelHashSet< cds::gc::HP, typename ml::MichaelList_HP_less_stat, traits_MichaelSet > MichaelSet_HP_less_stat;
+ typedef MichaelHashSet< cds::gc::DHP, typename ml::MichaelList_DHP_less_stat, traits_MichaelSet > MichaelSet_DHP_less_stat;
+ typedef MichaelHashSet< rcu_gpi, typename ml::MichaelList_RCU_GPI_less_stat, traits_MichaelSet > MichaelSet_RCU_GPI_less_stat;
+ typedef MichaelHashSet< rcu_gpb, typename ml::MichaelList_RCU_GPB_less_stat, traits_MichaelSet > MichaelSet_RCU_GPB_less_stat;
+ typedef MichaelHashSet< rcu_gpt, typename ml::MichaelList_RCU_GPT_less_stat, traits_MichaelSet > MichaelSet_RCU_GPT_less_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef MichaelHashSet< rcu_shb, typename ml::MichaelList_RCU_SHB_less_stat, traits_MichaelSet > MichaelSet_RCU_SHB_less_stat;
+#endif
+
+ typedef MichaelHashSet< cds::gc::HP, typename ml::MichaelList_HP_less_seqcst, traits_MichaelSet > MichaelSet_HP_less_seqcst;
+ typedef MichaelHashSet< cds::gc::DHP, typename ml::MichaelList_DHP_less_seqcst, traits_MichaelSet > MichaelSet_DHP_less_seqcst;
+ typedef MichaelHashSet< rcu_gpi, typename ml::MichaelList_RCU_GPI_less_seqcst, traits_MichaelSet > MichaelSet_RCU_GPI_less_seqcst;
+ typedef MichaelHashSet< rcu_gpb, typename ml::MichaelList_RCU_GPB_less_seqcst, traits_MichaelSet > MichaelSet_RCU_GPB_less_seqcst;
+ typedef MichaelHashSet< rcu_gpt, typename ml::MichaelList_RCU_GPT_less_seqcst, traits_MichaelSet > MichaelSet_RCU_GPT_less_seqcst;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef MichaelHashSet< rcu_shb, typename ml::MichaelList_RCU_SHB_less_seqcst, traits_MichaelSet > MichaelSet_RCU_SHB_less_seqcst;
+#endif
+
+
+ // ***************************************************************************
+ // MichaelHashSet based on LazyList
+
+ typedef lazy_list_type< Key, Val > ll;
+
+ typedef MichaelHashSet< cds::gc::HP, typename ll::LazyList_HP_cmp, traits_MichaelSet > MichaelSet_Lazy_HP_cmp;
+ typedef MichaelHashSet< cds::gc::DHP, typename ll::LazyList_DHP_cmp, traits_MichaelSet > MichaelSet_Lazy_DHP_cmp;
+ typedef MichaelHashSet< rcu_gpi, typename ll::LazyList_RCU_GPI_cmp, traits_MichaelSet > MichaelSet_Lazy_RCU_GPI_cmp;
+ typedef MichaelHashSet< rcu_gpb, typename ll::LazyList_RCU_GPB_cmp, traits_MichaelSet > MichaelSet_Lazy_RCU_GPB_cmp;
+ typedef MichaelHashSet< rcu_gpt, typename ll::LazyList_RCU_GPT_cmp, traits_MichaelSet > MichaelSet_Lazy_RCU_GPT_cmp;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef MichaelHashSet< rcu_shb, typename ll::LazyList_RCU_SHB_cmp, traits_MichaelSet > MichaelSet_Lazy_RCU_SHB_cmp;
+#endif
+
+ typedef MichaelHashSet< cds::gc::HP, typename ll::LazyList_HP_cmp_stat, traits_MichaelSet > MichaelSet_Lazy_HP_cmp_stat;
+ typedef MichaelHashSet< cds::gc::DHP, typename ll::LazyList_DHP_cmp_stat, traits_MichaelSet > MichaelSet_Lazy_DHP_cmp_stat;
+ typedef MichaelHashSet< rcu_gpi, typename ll::LazyList_RCU_GPI_cmp_stat, traits_MichaelSet > MichaelSet_Lazy_RCU_GPI_cmp_stat;
+ typedef MichaelHashSet< rcu_gpb, typename ll::LazyList_RCU_GPB_cmp_stat, traits_MichaelSet > MichaelSet_Lazy_RCU_GPB_cmp_stat;
+ typedef MichaelHashSet< rcu_gpt, typename ll::LazyList_RCU_GPT_cmp_stat, traits_MichaelSet > MichaelSet_Lazy_RCU_GPT_cmp_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef MichaelHashSet< rcu_shb, typename ll::LazyList_RCU_SHB_cmp_stat, traits_MichaelSet > MichaelSet_Lazy_RCU_SHB_cmp_stat;
+#endif
+
+ typedef MichaelHashSet< cds::gc::HP, typename ll::LazyList_HP_less, traits_MichaelSet > MichaelSet_Lazy_HP_less;
+ typedef MichaelHashSet< cds::gc::DHP, typename ll::LazyList_DHP_less, traits_MichaelSet > MichaelSet_Lazy_DHP_less;
+ typedef MichaelHashSet< rcu_gpi, typename ll::LazyList_RCU_GPI_less, traits_MichaelSet > MichaelSet_Lazy_RCU_GPI_less;
+ typedef MichaelHashSet< rcu_gpb, typename ll::LazyList_RCU_GPB_less, traits_MichaelSet > MichaelSet_Lazy_RCU_GPB_less;
+ typedef MichaelHashSet< rcu_gpt, typename ll::LazyList_RCU_GPT_less, traits_MichaelSet > MichaelSet_Lazy_RCU_GPT_less;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef MichaelHashSet< rcu_shb, typename ll::LazyList_RCU_SHB_less, traits_MichaelSet > MichaelSet_Lazy_RCU_SHB_less;
+#endif
+
+ typedef MichaelHashSet< cds::gc::HP, typename ll::LazyList_HP_less_stat, traits_MichaelSet > MichaelSet_Lazy_HP_less_stat;
+ typedef MichaelHashSet< cds::gc::DHP, typename ll::LazyList_DHP_less_stat, traits_MichaelSet > MichaelSet_Lazy_DHP_less_stat;
+ typedef MichaelHashSet< rcu_gpi, typename ll::LazyList_RCU_GPI_less_stat, traits_MichaelSet > MichaelSet_Lazy_RCU_GPI_less_stat;
+ typedef MichaelHashSet< rcu_gpb, typename ll::LazyList_RCU_GPB_less_stat, traits_MichaelSet > MichaelSet_Lazy_RCU_GPB_less_stat;
+ typedef MichaelHashSet< rcu_gpt, typename ll::LazyList_RCU_GPT_less_stat, traits_MichaelSet > MichaelSet_Lazy_RCU_GPT_less_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef MichaelHashSet< rcu_shb, typename ll::LazyList_RCU_SHB_less_stat, traits_MichaelSet > MichaelSet_Lazy_RCU_SHB_less_stat;
+#endif
+
+ typedef MichaelHashSet< cds::gc::HP, typename ll::LazyList_HP_less_seqcst, traits_MichaelSet > MichaelSet_Lazy_HP_less_seqcst;
+ typedef MichaelHashSet< cds::gc::DHP, typename ll::LazyList_DHP_less_seqcst, traits_MichaelSet > MichaelSet_Lazy_DHP_less_seqcst;
+ typedef MichaelHashSet< rcu_gpi, typename ll::LazyList_RCU_GPI_less_seqcst, traits_MichaelSet > MichaelSet_Lazy_RCU_GPI_less_seqcst;
+ typedef MichaelHashSet< rcu_gpb, typename ll::LazyList_RCU_GPB_less_seqcst, traits_MichaelSet > MichaelSet_Lazy_RCU_GPB_less_seqcst;
+ typedef MichaelHashSet< rcu_gpt, typename ll::LazyList_RCU_GPT_less_seqcst, traits_MichaelSet > MichaelSet_Lazy_RCU_GPT_less_seqcst;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef MichaelHashSet< rcu_shb, typename ll::LazyList_RCU_SHB_less_seqcst, traits_MichaelSet > MichaelSet_Lazy_RCU_SHB_less_seqcst;
+#endif
+
+
+ // ***************************************************************************
+ // MichaelHashSet based on IterableList
+
+ typedef iterable_list_type< Key, Val > il;
+
+ typedef MichaelHashSet< cds::gc::HP, typename il::IterableList_HP_cmp, traits_MichaelSet > MichaelSet_Iterable_HP_cmp;
+ typedef MichaelHashSet< cds::gc::DHP, typename il::IterableList_DHP_cmp, traits_MichaelSet > MichaelSet_Iterable_DHP_cmp;
+
+ typedef MichaelHashSet< cds::gc::HP, typename il::IterableList_HP_cmp_stat, traits_MichaelSet > MichaelSet_Iterable_HP_cmp_stat;
+ typedef MichaelHashSet< cds::gc::DHP, typename il::IterableList_DHP_cmp_stat, traits_MichaelSet > MichaelSet_Iterable_DHP_cmp_stat;
+
+ typedef MichaelHashSet< cds::gc::HP, typename il::IterableList_HP_less, traits_MichaelSet > MichaelSet_Iterable_HP_less;
+ typedef MichaelHashSet< cds::gc::DHP, typename il::IterableList_DHP_less, traits_MichaelSet > MichaelSet_Iterable_DHP_less;
+
+ typedef MichaelHashSet< cds::gc::HP, typename il::IterableList_HP_less_stat, traits_MichaelSet > MichaelSet_Iterable_HP_less_stat;
+ typedef MichaelHashSet< cds::gc::DHP, typename il::IterableList_DHP_less_stat, traits_MichaelSet > MichaelSet_Iterable_DHP_less_stat;
+
+ typedef MichaelHashSet< cds::gc::HP, typename il::IterableList_HP_less_seqcst, traits_MichaelSet > MichaelSet_Iterable_HP_less_seqcst;
+ typedef MichaelHashSet< cds::gc::DHP, typename il::IterableList_DHP_less_seqcst, traits_MichaelSet > MichaelSet_Iterable_DHP_less_seqcst;
+
+ };
+
+ template <typename GC, typename T, typename Traits>
+ static inline void print_stat( cds_test::property_stream& o, MichaelHashSet<GC, T, Traits> const& s )
+ {
+ o << s.statistics();
+ }
+
+} // namespace set
+
+
+#define CDSSTRESS_MichaelSet_case( fixture, test_case, michael_set_type, key_type, value_type ) \
+ TEST_P( fixture, michael_set_type ) \
+ { \
+ typedef set::set_type< tag_MichaelHashSet, key_type, value_type >::michael_set_type set_type; \
+ test_case<set_type>(); \
+ }
+
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+
+#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL > 0
+# define CDSSTRESS_MichaelSet_SHRCU_1( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_RCU_SHT_cmp, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_RCU_SHB_less, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_Lazy_RCU_SHT_cmp, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_Lazy_RCU_SHB_less, key_type, value_type ) \
+
+# define CDSSTRESS_MichaelIterableSet_SHRCU_1( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_Iterable_RCU_SHT_cmp, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_Iterable_RCU_SHB_less, key_type, value_type ) \
+
+#else
+# define CDSSTRESS_MichaelSet_SHRCU_1( fixture, test_case, key_type, value_type )
+# define CDSSTRESS_MichaelIterableSet_SHRCU_1( fixture, test_case, key_type, value_type )
+#endif
+
+# define CDSSTRESS_MichaelSet_SHRCU( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_RCU_SHB_cmp, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_RCU_SHT_less, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_Lazy_RCU_SHB_cmp, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_Lazy_RCU_SHT_less, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_SHRCU_1( fixture, test_case, key_type, value_type ) \
+
+# define CDSSTRESS_MichaelIterableSet_SHRCU( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_Iterable_RCU_SHB_cmp, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_Iterable_RCU_SHT_less, key_type, value_type ) \
+ CDSSTRESS_MichaelIterableSet_SHRCU_1( fixture, test_case, key_type, value_type ) \
+
+#else
+# define CDSSTRESS_MichaelSet_SHRCU( fixture, test_case, key_type, value_type )
+# define CDSSTRESS_MichaelIterableSet_SHRCU( fixture, test_case, key_type, value_type )
+#endif
+
+#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL > 0
+# define CDSSTRESS_MichaelSet_HP_1( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_DHP_cmp, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_HP_less, key_type, value_type ) \
+ \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_Lazy_DHP_cmp, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_Lazy_HP_less, key_type, value_type ) \
+
+# define CDSSTRESS_MichaelSet_RCU_1( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_RCU_GPB_cmp, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_RCU_GPI_less, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_RCU_GPT_less, key_type, value_type ) \
+ \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_Lazy_RCU_GPB_cmp, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_Lazy_RCU_GPI_less, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_Lazy_RCU_GPT_less, key_type, value_type ) \
+ \
+ CDSSTRESS_MichaelSet_SHRCU( fixture, test_case, key_type, value_type ) \
+
+# define CDSSTRESS_MichaelIterableSet_1( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_Iterable_DHP_cmp, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_Iterable_HP_less, key_type, value_type ) \
+
+
+#else
+# define CDSSTRESS_MichaelSet_HP_1( fixture, test_case, key_type, value_type )
+# define CDSSTRESS_MichaelSet_RCU_1( fixture, test_case, key_type, value_type )
+# define CDSSTRESS_MichaelIterableSet_1( fixture, test_case, key_type, value_type )
+#endif
+
+
+#define CDSSTRESS_MichaelSet_HP( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_HP_cmp, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_DHP_less, key_type, value_type ) \
+ \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_Lazy_HP_cmp, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_Lazy_DHP_less, key_type, value_type ) \
+ \
+ CDSSTRESS_MichaelSet_HP_1( fixture, test_case, key_type, value_type ) \
+
+#define CDSSTRESS_MichaelSet_RCU( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_RCU_GPI_cmp, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_RCU_GPT_cmp, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_RCU_GPB_less, key_type, value_type ) \
+ \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_Lazy_RCU_GPI_cmp, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_Lazy_RCU_GPT_cmp, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_Lazy_RCU_GPB_less, key_type, value_type ) \
+ \
+ CDSSTRESS_MichaelSet_RCU_1( fixture, test_case, key_type, value_type ) \
+
+#define CDSSTRESS_MichaelSet( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_HP( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_RCU( fixture, test_case, key_type, value_type ) \
+
+#define CDSSTRESS_MichaelIterableSet( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_Iterable_HP_cmp, key_type, value_type ) \
+ CDSSTRESS_MichaelSet_case( fixture, test_case, MichaelSet_Iterable_DHP_less, key_type, value_type ) \
+ CDSSTRESS_MichaelIterableSet_1( fixture, test_case, key_type, value_type ) \
+
+#endif // #ifndef CDSUNIT_SET_TYPE_MICHAEL_H
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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.
+*/
+
+#ifndef CDSUNIT_SET_TYPE_MICHAEL_LIST_H
+#define CDSUNIT_SET_TYPE_MICHAEL_LIST_H
+
+#include "set_type.h"
+
+#include <cds/container/michael_list_hp.h>
+#include <cds/container/michael_list_dhp.h>
+#include <cds/container/michael_list_rcu.h>
+
+namespace set {
+
+ template <typename Key, typename Val>
+ struct michael_list_type
+ {
+ typedef typename set_type_base< Key, Val >::key_val key_val;
+ typedef typename set_type_base< Key, Val >::compare compare;
+ typedef typename set_type_base< Key, Val >::less less;
+
+ struct traits_MichaelList_cmp:
+ public cc::michael_list::make_traits<
+ co::compare< compare >
+ >::type
+ {};
+ typedef cc::MichaelList< cds::gc::HP, key_val, traits_MichaelList_cmp > MichaelList_HP_cmp;
+ typedef cc::MichaelList< cds::gc::DHP, key_val, traits_MichaelList_cmp > MichaelList_DHP_cmp;
+ typedef cc::MichaelList< rcu_gpi, key_val, traits_MichaelList_cmp > MichaelList_RCU_GPI_cmp;
+ typedef cc::MichaelList< rcu_gpb, key_val, traits_MichaelList_cmp > MichaelList_RCU_GPB_cmp;
+ typedef cc::MichaelList< rcu_gpt, key_val, traits_MichaelList_cmp > MichaelList_RCU_GPT_cmp;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef cc::MichaelList< rcu_shb, key_val, traits_MichaelList_cmp > MichaelList_RCU_SHB_cmp;
+#endif
+
+ struct traits_MichaelList_cmp_stat: public traits_MichaelList_cmp
+ {
+ typedef cc::michael_list::stat<> stat;
+ };
+ typedef cc::MichaelList< cds::gc::HP, key_val, traits_MichaelList_cmp_stat > MichaelList_HP_cmp_stat;
+ typedef cc::MichaelList< cds::gc::DHP, key_val, traits_MichaelList_cmp_stat > MichaelList_DHP_cmp_stat;
+ typedef cc::MichaelList< rcu_gpi, key_val, traits_MichaelList_cmp_stat > MichaelList_RCU_GPI_cmp_stat;
+ typedef cc::MichaelList< rcu_gpb, key_val, traits_MichaelList_cmp_stat > MichaelList_RCU_GPB_cmp_stat;
+ typedef cc::MichaelList< rcu_gpt, key_val, traits_MichaelList_cmp_stat > MichaelList_RCU_GPT_cmp_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef cc::MichaelList< rcu_shb, key_val, traits_MichaelList_cmp_stat > MichaelList_RCU_SHB_cmp_stat;
+#endif
+
+ struct traits_MichaelList_cmp_seqcst : public traits_MichaelList_cmp
+ {
+ typedef co::v::sequential_consistent memory_model;
+ };
+ typedef cc::MichaelList< cds::gc::HP, key_val, traits_MichaelList_cmp_seqcst > MichaelList_HP_cmp_seqcst;
+ typedef cc::MichaelList< cds::gc::DHP, key_val, traits_MichaelList_cmp_seqcst > MichaelList_DHP_cmp_seqcst;
+ typedef cc::MichaelList< rcu_gpi, key_val, traits_MichaelList_cmp_seqcst > MichaelList_RCU_GPI_cmp_seqcst;
+ typedef cc::MichaelList< rcu_gpb, key_val, traits_MichaelList_cmp_seqcst > MichaelList_RCU_GPB_cmp_seqcst;
+ typedef cc::MichaelList< rcu_gpt, key_val, traits_MichaelList_cmp_seqcst > MichaelList_RCU_GPT_cmp_seqcst;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef cc::MichaelList< rcu_shb, key_val, traits_MichaelList_cmp_seqcst > MichaelList_RCU_SHB_cmp_seqcst;
+#endif
+
+ struct traits_MichaelList_less :
+ public cc::michael_list::make_traits<
+ co::less< less >
+ >::type
+ {};
+ typedef cc::MichaelList< cds::gc::HP, key_val, traits_MichaelList_less > MichaelList_HP_less;
+ typedef cc::MichaelList< cds::gc::DHP, key_val, traits_MichaelList_less > MichaelList_DHP_less;
+ typedef cc::MichaelList< rcu_gpi, key_val, traits_MichaelList_less > MichaelList_RCU_GPI_less;
+ typedef cc::MichaelList< rcu_gpb, key_val, traits_MichaelList_less > MichaelList_RCU_GPB_less;
+ typedef cc::MichaelList< rcu_gpt, key_val, traits_MichaelList_less > MichaelList_RCU_GPT_less;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef cc::MichaelList< rcu_shb, key_val, traits_MichaelList_less > MichaelList_RCU_SHB_less;
+#endif
+
+ struct traits_MichaelList_less_stat : public traits_MichaelList_less
+ {
+ typedef cc::michael_list::stat<> stat;
+ };
+ typedef cc::MichaelList< cds::gc::HP, key_val, traits_MichaelList_less_stat > MichaelList_HP_less_stat;
+ typedef cc::MichaelList< cds::gc::DHP, key_val, traits_MichaelList_less_stat > MichaelList_DHP_less_stat;
+ typedef cc::MichaelList< rcu_gpi, key_val, traits_MichaelList_less_stat > MichaelList_RCU_GPI_less_stat;
+ typedef cc::MichaelList< rcu_gpb, key_val, traits_MichaelList_less_stat > MichaelList_RCU_GPB_less_stat;
+ typedef cc::MichaelList< rcu_gpt, key_val, traits_MichaelList_less_stat > MichaelList_RCU_GPT_less_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef cc::MichaelList< rcu_shb, key_val, traits_MichaelList_less_stat > MichaelList_RCU_SHB_less_stat;
+#endif
+
+ struct traits_MichaelList_less_seqcst :
+ public cc::michael_list::make_traits<
+ co::less< less >
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ {};
+ typedef cc::MichaelList< cds::gc::HP, key_val, traits_MichaelList_less_seqcst > MichaelList_HP_less_seqcst;
+ typedef cc::MichaelList< cds::gc::DHP, key_val, traits_MichaelList_less_seqcst > MichaelList_DHP_less_seqcst;
+ typedef cc::MichaelList< rcu_gpi, key_val, traits_MichaelList_less_seqcst > MichaelList_RCU_GPI_less_seqcst;
+ typedef cc::MichaelList< rcu_gpb, key_val, traits_MichaelList_less_seqcst > MichaelList_RCU_GPB_less_seqcst;
+ typedef cc::MichaelList< rcu_gpt, key_val, traits_MichaelList_less_seqcst > MichaelList_RCU_GPT_less_seqcst;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef cc::MichaelList< rcu_shb, key_val, traits_MichaelList_less_seqcst > MichaelList_RCU_SHB_less_seqcst;
+#endif
+
+ };
+
+} // namespace set
+
+#endif // #ifndef CDSUNIT_SET_TYPE_MICHAEL_LIST_H
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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.
+*/
+
+#ifndef CDSUNIT_SET_TYPE_SKIP_LIST_H
+#define CDSUNIT_SET_TYPE_SKIP_LIST_H
+
+#include "set_type.h"
+
+#include <cds/container/skip_list_set_hp.h>
+#include <cds/container/skip_list_set_dhp.h>
+#include <cds/container/skip_list_set_rcu.h>
+
+#include <cds_test/stat_skiplist_out.h>
+
+namespace set {
+
+ template <typename GC, typename T, typename Traits = cc::skip_list::traits >
+ class SkipListSet : public cc::SkipListSet<GC, T, Traits>
+ {
+ typedef cc::SkipListSet<GC, T, Traits> base_class;
+ public:
+ template <typename Config>
+ SkipListSet( Config const& /*cfg*/ )
+ {}
+
+ // for testing
+ static CDS_CONSTEXPR bool const c_bExtractSupported = true;
+ static CDS_CONSTEXPR bool const c_bLoadFactorDepended = false;
+ static CDS_CONSTEXPR bool const c_bEraseExactKey = false;
+ };
+
+ struct tag_SkipListSet;
+
+ template <typename Key, typename Val>
+ struct set_type< tag_SkipListSet, Key, Val >: public set_type_base< Key, Val >
+ {
+ typedef set_type_base< Key, Val > base_class;
+ typedef typename base_class::key_val key_val;
+ typedef typename base_class::compare compare;
+ typedef typename base_class::less less;
+ typedef typename base_class::hash hash;
+
+ class traits_SkipListSet_less_turbo32: public cc::skip_list::make_traits <
+ co::less< less >
+ ,cc::skip_list::random_level_generator< cc::skip_list::turbo32 >
+ ,co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ >::type
+ {};
+ typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_turbo32 > SkipListSet_hp_less_turbo32;
+ typedef SkipListSet< cds::gc::DHP, key_val, traits_SkipListSet_less_turbo32 > SkipListSet_dhp_less_turbo32;
+ typedef SkipListSet< rcu_gpi, key_val, traits_SkipListSet_less_turbo32 > SkipListSet_rcu_gpi_less_turbo32;
+ typedef SkipListSet< rcu_gpb, key_val, traits_SkipListSet_less_turbo32 > SkipListSet_rcu_gpb_less_turbo32;
+ typedef SkipListSet< rcu_gpt, key_val, traits_SkipListSet_less_turbo32 > SkipListSet_rcu_gpt_less_turbo32;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SkipListSet< rcu_shb, key_val, traits_SkipListSet_less_turbo32 > SkipListSet_rcu_shb_less_turbo32;
+#endif
+
+ class traits_SkipListSet_less_turbo24: public cc::skip_list::make_traits <
+ co::less< less >
+ ,cc::skip_list::random_level_generator< cc::skip_list::turbo24 >
+ ,co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ >::type
+ {};
+ typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_turbo24 > SkipListSet_hp_less_turbo24;
+ typedef SkipListSet< cds::gc::DHP, key_val, traits_SkipListSet_less_turbo24 > SkipListSet_dhp_less_turbo24;
+ typedef SkipListSet< rcu_gpi, key_val, traits_SkipListSet_less_turbo24 > SkipListSet_rcu_gpi_less_turbo24;
+ typedef SkipListSet< rcu_gpb, key_val, traits_SkipListSet_less_turbo24 > SkipListSet_rcu_gpb_less_turbo24;
+ typedef SkipListSet< rcu_gpt, key_val, traits_SkipListSet_less_turbo24 > SkipListSet_rcu_gpt_less_turbo24;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SkipListSet< rcu_shb, key_val, traits_SkipListSet_less_turbo24 > SkipListSet_rcu_shb_less_turbo24;
+#endif
+
+ class traits_SkipListSet_less_turbo16: public cc::skip_list::make_traits <
+ co::less< less >
+ ,cc::skip_list::random_level_generator< cc::skip_list::turbo16 >
+ ,co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ >::type
+ {};
+ typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_turbo16 > SkipListSet_hp_less_turbo16;
+ typedef SkipListSet< cds::gc::DHP, key_val, traits_SkipListSet_less_turbo16 > SkipListSet_dhp_less_turbo16;
+ typedef SkipListSet< rcu_gpi, key_val, traits_SkipListSet_less_turbo16 > SkipListSet_rcu_gpi_less_turbo16;
+ typedef SkipListSet< rcu_gpb, key_val, traits_SkipListSet_less_turbo16 > SkipListSet_rcu_gpb_less_turbo16;
+ typedef SkipListSet< rcu_gpt, key_val, traits_SkipListSet_less_turbo16 > SkipListSet_rcu_gpt_less_turbo16;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SkipListSet< rcu_shb, key_val, traits_SkipListSet_less_turbo16 > SkipListSet_rcu_shb_less_turbo16;
+#endif
+
+ class traits_SkipListSet_less_turbo32_seqcst: public cc::skip_list::make_traits <
+ co::less< less >
+ ,cc::skip_list::random_level_generator< cc::skip_list::turbo32 >
+ ,co::memory_model< co::v::sequential_consistent >
+ ,co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ >::type
+ {};
+ typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_turbo32_seqcst > SkipListSet_hp_less_turbo32_seqcst;
+ typedef SkipListSet< cds::gc::DHP, key_val, traits_SkipListSet_less_turbo32_seqcst > SkipListSet_dhp_less_turbo32_seqcst;
+ typedef SkipListSet< rcu_gpi, key_val, traits_SkipListSet_less_turbo32_seqcst > SkipListSet_rcu_gpi_less_turbo32_seqcst;
+ typedef SkipListSet< rcu_gpb, key_val, traits_SkipListSet_less_turbo32_seqcst > SkipListSet_rcu_gpb_less_turbo32_seqcst;
+ typedef SkipListSet< rcu_gpt, key_val, traits_SkipListSet_less_turbo32_seqcst > SkipListSet_rcu_gpt_less_turbo32_seqcst;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SkipListSet< rcu_shb, key_val, traits_SkipListSet_less_turbo32_seqcst > SkipListSet_rcu_shb_less_turbo32_seqcst;
+#endif
+
+ class traits_SkipListSet_less_turbo32_stat: public cc::skip_list::make_traits <
+ co::less< less >
+ ,cc::skip_list::random_level_generator< cc::skip_list::turbo32 >
+ ,co::stat< cc::skip_list::stat<> >
+ ,co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ >::type
+ {};
+ typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_turbo32_stat > SkipListSet_hp_less_turbo32_stat;
+ typedef SkipListSet< cds::gc::DHP, key_val, traits_SkipListSet_less_turbo32_stat > SkipListSet_dhp_less_turbo32_stat;
+ typedef SkipListSet< rcu_gpi, key_val, traits_SkipListSet_less_turbo32_stat > SkipListSet_rcu_gpi_less_turbo32_stat;
+ typedef SkipListSet< rcu_gpb, key_val, traits_SkipListSet_less_turbo32_stat > SkipListSet_rcu_gpb_less_turbo32_stat;
+ typedef SkipListSet< rcu_gpt, key_val, traits_SkipListSet_less_turbo32_stat > SkipListSet_rcu_gpt_less_turbo32_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SkipListSet< rcu_shb, key_val, traits_SkipListSet_less_turbo32_stat > SkipListSet_rcu_shb_less_turbo32_stat;
+#endif
+
+ class traits_SkipListSet_less_turbo24_stat: public cc::skip_list::make_traits <
+ co::less< less >
+ ,cc::skip_list::random_level_generator< cc::skip_list::turbo24 >
+ ,co::stat< cc::skip_list::stat<> >
+ ,co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ >::type
+ {};
+ typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_turbo24_stat > SkipListSet_hp_less_turbo24_stat;
+ typedef SkipListSet< cds::gc::DHP, key_val, traits_SkipListSet_less_turbo24_stat > SkipListSet_dhp_less_turbo24_stat;
+ typedef SkipListSet< rcu_gpi, key_val, traits_SkipListSet_less_turbo24_stat > SkipListSet_rcu_gpi_less_turbo24_stat;
+ typedef SkipListSet< rcu_gpb, key_val, traits_SkipListSet_less_turbo24_stat > SkipListSet_rcu_gpb_less_turbo24_stat;
+ typedef SkipListSet< rcu_gpt, key_val, traits_SkipListSet_less_turbo24_stat > SkipListSet_rcu_gpt_less_turbo24_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SkipListSet< rcu_shb, key_val, traits_SkipListSet_less_turbo24_stat > SkipListSet_rcu_shb_less_turbo24_stat;
+#endif
+
+ class traits_SkipListSet_less_turbo16_stat: public cc::skip_list::make_traits <
+ co::less< less >
+ ,cc::skip_list::random_level_generator< cc::skip_list::turbo16 >
+ ,co::stat< cc::skip_list::stat<> >
+ ,co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ >::type
+ {};
+ typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_turbo16_stat > SkipListSet_hp_less_turbo16_stat;
+ typedef SkipListSet< cds::gc::DHP, key_val, traits_SkipListSet_less_turbo16_stat > SkipListSet_dhp_less_turbo16_stat;
+ typedef SkipListSet< rcu_gpi, key_val, traits_SkipListSet_less_turbo16_stat > SkipListSet_rcu_gpi_less_turbo16_stat;
+ typedef SkipListSet< rcu_gpb, key_val, traits_SkipListSet_less_turbo16_stat > SkipListSet_rcu_gpb_less_turbo16_stat;
+ typedef SkipListSet< rcu_gpt, key_val, traits_SkipListSet_less_turbo16_stat > SkipListSet_rcu_gpt_less_turbo16_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SkipListSet< rcu_shb, key_val, traits_SkipListSet_less_turbo16_stat > SkipListSet_rcu_shb_less_turbo16_stat;
+#endif
+
+ class traits_SkipListSet_cmp_turbo32: public cc::skip_list::make_traits <
+ co::compare< compare >
+ ,cc::skip_list::random_level_generator< cc::skip_list::turbo32 >
+ ,co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ >::type
+ {};
+ typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_cmp_turbo32 > SkipListSet_hp_cmp_turbo32;
+ typedef SkipListSet< cds::gc::DHP, key_val, traits_SkipListSet_cmp_turbo32 > SkipListSet_dhp_cmp_turbo32;
+ typedef SkipListSet< rcu_gpi, key_val, traits_SkipListSet_cmp_turbo32 > SkipListSet_rcu_gpi_cmp_turbo32;
+ typedef SkipListSet< rcu_gpb, key_val, traits_SkipListSet_cmp_turbo32 > SkipListSet_rcu_gpb_cmp_turbo32;
+ typedef SkipListSet< rcu_gpt, key_val, traits_SkipListSet_cmp_turbo32 > SkipListSet_rcu_gpt_cmp_turbo32;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SkipListSet< rcu_shb, key_val, traits_SkipListSet_cmp_turbo32 > SkipListSet_rcu_shb_cmp_turbo32;
+#endif
+
+ class traits_SkipListSet_cmp_turbo32_stat: public cc::skip_list::make_traits <
+ co::compare< compare >
+ ,cc::skip_list::random_level_generator< cc::skip_list::turbo32 >
+ ,co::stat< cc::skip_list::stat<> >
+ ,co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ >::type
+ {};
+ typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_cmp_turbo32_stat > SkipListSet_hp_cmp_turbo32_stat;
+ typedef SkipListSet< cds::gc::DHP, key_val, traits_SkipListSet_cmp_turbo32_stat > SkipListSet_dhp_cmp_turbo32_stat;
+ typedef SkipListSet< rcu_gpi, key_val, traits_SkipListSet_cmp_turbo32_stat > SkipListSet_rcu_gpi_cmp_turbo32_stat;
+ typedef SkipListSet< rcu_gpb, key_val, traits_SkipListSet_cmp_turbo32_stat > SkipListSet_rcu_gpb_cmp_turbo32_stat;
+ typedef SkipListSet< rcu_gpt, key_val, traits_SkipListSet_cmp_turbo32_stat > SkipListSet_rcu_gpt_cmp_turbo32_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SkipListSet< rcu_shb, key_val, traits_SkipListSet_cmp_turbo32_stat > SkipListSet_rcu_shb_cmp_turbo32_stat;
+#endif
+
+ class traits_SkipListSet_less_xorshift32: public cc::skip_list::make_traits <
+ co::less< less >
+ ,cc::skip_list::random_level_generator< cc::skip_list::xorshift32 >
+ ,co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ >::type
+ {};
+ typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_xorshift32 > SkipListSet_hp_less_xorshift32;
+ typedef SkipListSet< cds::gc::DHP, key_val, traits_SkipListSet_less_xorshift32 > SkipListSet_dhp_less_xorshift32;
+ typedef SkipListSet< rcu_gpi, key_val, traits_SkipListSet_less_xorshift32 > SkipListSet_rcu_gpi_less_xorshift32;
+ typedef SkipListSet< rcu_gpb, key_val, traits_SkipListSet_less_xorshift32 > SkipListSet_rcu_gpb_less_xorshift32;
+ typedef SkipListSet< rcu_gpt, key_val, traits_SkipListSet_less_xorshift32 > SkipListSet_rcu_gpt_less_xorshift32;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SkipListSet< rcu_shb, key_val, traits_SkipListSet_less_xorshift32 > SkipListSet_rcu_shb_less_xorshift32;
+#endif
+
+ class traits_SkipListSet_less_xorshift24: public cc::skip_list::make_traits <
+ co::less< less >
+ ,cc::skip_list::random_level_generator< cc::skip_list::xorshift24 >
+ ,co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ >::type
+ {};
+ typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_xorshift24 > SkipListSet_hp_less_xorshift24;
+ typedef SkipListSet< cds::gc::DHP, key_val, traits_SkipListSet_less_xorshift24 > SkipListSet_dhp_less_xorshift24;
+ typedef SkipListSet< rcu_gpi, key_val, traits_SkipListSet_less_xorshift24 > SkipListSet_rcu_gpi_less_xorshift24;
+ typedef SkipListSet< rcu_gpb, key_val, traits_SkipListSet_less_xorshift24 > SkipListSet_rcu_gpb_less_xorshift24;
+ typedef SkipListSet< rcu_gpt, key_val, traits_SkipListSet_less_xorshift24 > SkipListSet_rcu_gpt_less_xorshift24;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SkipListSet< rcu_shb, key_val, traits_SkipListSet_less_xorshift24 > SkipListSet_rcu_shb_less_xorshift24;
+#endif
+
+ class traits_SkipListSet_less_xorshift16: public cc::skip_list::make_traits <
+ co::less< less >
+ , cc::skip_list::random_level_generator< cc::skip_list::xorshift16 >
+ , co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ >::type
+ {};
+ typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_xorshift16 > SkipListSet_hp_less_xorshift16;
+ typedef SkipListSet< cds::gc::DHP, key_val, traits_SkipListSet_less_xorshift16 > SkipListSet_dhp_less_xorshift16;
+ typedef SkipListSet< rcu_gpi, key_val, traits_SkipListSet_less_xorshift16 > SkipListSet_rcu_gpi_less_xorshift16;
+ typedef SkipListSet< rcu_gpb, key_val, traits_SkipListSet_less_xorshift16 > SkipListSet_rcu_gpb_less_xorshift16;
+ typedef SkipListSet< rcu_gpt, key_val, traits_SkipListSet_less_xorshift16 > SkipListSet_rcu_gpt_less_xorshift16;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SkipListSet< rcu_shb, key_val, traits_SkipListSet_less_xorshift16 > SkipListSet_rcu_shb_less_xorshift16;
+#endif
+
+ class traits_SkipListSet_less_xorshift32_stat: public cc::skip_list::make_traits <
+ co::less< less >
+ ,cc::skip_list::random_level_generator< cc::skip_list::xorshift32 >
+ ,co::stat< cc::skip_list::stat<> >
+ ,co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ >::type
+ {};
+ typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_xorshift32_stat > SkipListSet_hp_less_xorshift32_stat;
+ typedef SkipListSet< cds::gc::DHP, key_val, traits_SkipListSet_less_xorshift32_stat > SkipListSet_dhp_less_xorshift32_stat;
+ typedef SkipListSet< rcu_gpi, key_val, traits_SkipListSet_less_xorshift32_stat > SkipListSet_rcu_gpi_less_xorshift32_stat;
+ typedef SkipListSet< rcu_gpb, key_val, traits_SkipListSet_less_xorshift32_stat > SkipListSet_rcu_gpb_less_xorshift32_stat;
+ typedef SkipListSet< rcu_gpt, key_val, traits_SkipListSet_less_xorshift32_stat > SkipListSet_rcu_gpt_less_xorshift32_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SkipListSet< rcu_shb, key_val, traits_SkipListSet_less_xorshift32_stat > SkipListSet_rcu_shb_less_xorshift32_stat;
+#endif
+
+ class traits_SkipListSet_less_xorshift24_stat: public cc::skip_list::make_traits <
+ co::less< less >
+ , cc::skip_list::random_level_generator< cc::skip_list::xorshift24 >
+ , co::stat< cc::skip_list::stat<> >
+ , co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ >::type
+ {};
+ typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_xorshift24_stat > SkipListSet_hp_less_xorshift24_stat;
+ typedef SkipListSet< cds::gc::DHP, key_val, traits_SkipListSet_less_xorshift24_stat > SkipListSet_dhp_less_xorshift24_stat;
+ typedef SkipListSet< rcu_gpi, key_val, traits_SkipListSet_less_xorshift24_stat > SkipListSet_rcu_gpi_less_xorshift24_stat;
+ typedef SkipListSet< rcu_gpb, key_val, traits_SkipListSet_less_xorshift24_stat > SkipListSet_rcu_gpb_less_xorshift24_stat;
+ typedef SkipListSet< rcu_gpt, key_val, traits_SkipListSet_less_xorshift24_stat > SkipListSet_rcu_gpt_less_xorshift24_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SkipListSet< rcu_shb, key_val, traits_SkipListSet_less_xorshift24_stat > SkipListSet_rcu_shb_less_xorshift24_stat;
+#endif
+
+ class traits_SkipListSet_less_xorshift16_stat: public cc::skip_list::make_traits <
+ co::less< less >
+ , cc::skip_list::random_level_generator< cc::skip_list::xorshift16 >
+ , co::stat< cc::skip_list::stat<> >
+ , co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ >::type
+ {};
+ typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_xorshift16_stat > SkipListSet_hp_less_xorshift16_stat;
+ typedef SkipListSet< cds::gc::DHP, key_val, traits_SkipListSet_less_xorshift16_stat > SkipListSet_dhp_less_xorshift16_stat;
+ typedef SkipListSet< rcu_gpi, key_val, traits_SkipListSet_less_xorshift16_stat > SkipListSet_rcu_gpi_less_xorshift16_stat;
+ typedef SkipListSet< rcu_gpb, key_val, traits_SkipListSet_less_xorshift16_stat > SkipListSet_rcu_gpb_less_xorshift16_stat;
+ typedef SkipListSet< rcu_gpt, key_val, traits_SkipListSet_less_xorshift16_stat > SkipListSet_rcu_gpt_less_xorshift16_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SkipListSet< rcu_shb, key_val, traits_SkipListSet_less_xorshift16_stat > SkipListSet_rcu_shb_less_xorshift16_stat;
+#endif
+
+ class traits_SkipListSet_cmp_xorshift32: public cc::skip_list::make_traits <
+ co::compare< compare >
+ ,cc::skip_list::random_level_generator< cc::skip_list::xorshift32 >
+ ,co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ >::type
+ {};
+ typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_cmp_xorshift32 > SkipListSet_hp_cmp_xorshift32;
+ typedef SkipListSet< cds::gc::DHP, key_val, traits_SkipListSet_cmp_xorshift32 > SkipListSet_dhp_cmp_xorshift32;
+ typedef SkipListSet< rcu_gpi, key_val, traits_SkipListSet_cmp_xorshift32 > SkipListSet_rcu_gpi_cmp_xorshift32;
+ typedef SkipListSet< rcu_gpb, key_val, traits_SkipListSet_cmp_xorshift32 > SkipListSet_rcu_gpb_cmp_xorshift32;
+ typedef SkipListSet< rcu_gpt, key_val, traits_SkipListSet_cmp_xorshift32 > SkipListSet_rcu_gpt_cmp_xorshift32;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SkipListSet< rcu_shb, key_val, traits_SkipListSet_cmp_xorshift32 > SkipListSet_rcu_shb_cmp_xorshift32;
+#endif
+
+ class traits_SkipListSet_cmp_xorshift32_stat: public cc::skip_list::make_traits <
+ co::compare< compare >
+ ,cc::skip_list::random_level_generator< cc::skip_list::xorshift32 >
+ ,co::stat< cc::skip_list::stat<> >
+ ,co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ >::type
+ {};
+ typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_cmp_xorshift32_stat > SkipListSet_hp_cmp_xorshift32_stat;
+ typedef SkipListSet< cds::gc::DHP, key_val, traits_SkipListSet_cmp_xorshift32_stat > SkipListSet_dhp_cmp_xorshift32_stat;
+ typedef SkipListSet< rcu_gpi, key_val, traits_SkipListSet_cmp_xorshift32_stat > SkipListSet_rcu_gpi_cmp_xorshift32_stat;
+ typedef SkipListSet< rcu_gpb, key_val, traits_SkipListSet_cmp_xorshift32_stat > SkipListSet_rcu_gpb_cmp_xorshift32_stat;
+ typedef SkipListSet< rcu_gpt, key_val, traits_SkipListSet_cmp_xorshift32_stat > SkipListSet_rcu_gpt_cmp_xorshift32_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SkipListSet< rcu_shb, key_val, traits_SkipListSet_cmp_xorshift32_stat > SkipListSet_rcu_shb_cmp_xorshift32_stat;
+#endif
+ };
+
+ template <typename GC, typename T, typename Traits>
+ static inline void print_stat( cds_test::property_stream& o, SkipListSet<GC, T, Traits> const& s )
+ {
+ o << s.statistics();
+ }
+
+} // namespace set
+
+#define CDSSTRESS_SkipListSet_case( fixture, test_case, skiplist_set_type, key_type, value_type ) \
+ TEST_F( fixture, skiplist_set_type ) \
+ { \
+ typedef set::set_type< tag_SkipListSet, key_type, value_type >::skiplist_set_type set_type; \
+ test_case<set_type>(); \
+ }
+
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+
+#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL > 1
+# define CDSSTRESS_SkipListSet_SHRCU_2( fixture, test_case, key_type, value_type ) \
+
+#else
+# define CDSSTRESS_SkipListSet_SHRCU_2( fixture, test_case, key_type, value_type )
+#endif
+
+#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL == 1
+# define CDSSTRESS_SkipListSet_SHRCU_1( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_rcu_shb_cmp_turbo32, key_type, value_type) \
+
+#else
+# define CDSSTRESS_SkipListSet_SHRCU_1( fixture, test_case, key_type, value_type )
+#endif
+
+
+# define CDSSTRESS_SkipListSet_SHRCU( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_rcu_shb_less_turbo32, key_type, value_type) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_rcu_shb_less_xorshift32, key_type, value_type) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_rcu_shb_cmp_xorshift32, key_type, value_type) \
+ CDSSTRESS_SkipListSet_SHRCU_1( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_SHRCU_2( fixture, test_case, key_type, value_type ) \
+
+#else
+# define CDSSTRESS_SkipListSet_SHRCU( fixture, test_case, key_type, value_type )
+#endif
+
+#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL > 1
+# define CDSSTRESS_SkipListSet_HP_2( fixture, test_case, key_type, value_type ) \
+
+# define CDSSTRESS_SkipListSet_RCU_2( fixture, test_case, key_type, value_type ) \
+
+#else
+# define CDSSTRESS_SkipListSet_HP_2( fixture, test_case, key_type, value_type )
+# define CDSSTRESS_SkipListSet_RCU_2( fixture, test_case, key_type, value_type )
+#endif
+
+#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL == 1
+# define CDSSTRESS_SkipListSet_HP_1( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_dhp_less_turbo32, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_hp_cmp_turbo32, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_dhp_less_xorshift32, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_hp_cmp_xorshift32, key_type, value_type ) \
+
+# define CDSSTRESS_SkipListSet_RCU_1( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_rcu_gpb_less_turbo32, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_rcu_gpi_cmp_turbo32, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_rcu_gpt_cmp_turbo32, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_rcu_gpb_less_xorshift32, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_rcu_gpi_cmp_xorshift32, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_rcu_gpt_cmp_xorshift32, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_SHRCU( fixture, test_case, key_type, value_type ) \
+
+#else
+# define CDSSTRESS_SkipListSet_HP_1( fixture, test_case, key_type, value_type )
+# define CDSSTRESS_SkipListSet_RCU_1( fixture, test_case, key_type, value_type )
+#endif
+
+
+#define CDSSTRESS_SkipListSet_HP( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_hp_less_turbo32, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_hp_less_turbo24, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_hp_less_turbo16, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_dhp_cmp_turbo32, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_hp_less_xorshift32, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_hp_less_xorshift24, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_hp_less_xorshift16, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_dhp_cmp_xorshift32, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_HP_1( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_HP_2( fixture, test_case, key_type, value_type ) \
+
+#define CDSSTRESS_SkipListSet_RCU( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_rcu_gpi_less_turbo32, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_rcu_gpt_less_turbo32, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_rcu_gpb_cmp_turbo32, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_rcu_gpi_less_xorshift32, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_rcu_gpt_less_xorshift32, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_case( fixture, test_case, SkipListSet_rcu_gpb_cmp_xorshift32, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_RCU_1( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_RCU_2( fixture, test_case, key_type, value_type ) \
+
+#define CDSSTRESS_SkipListSet( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_HP( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SkipListSet_RCU( fixture, test_case, key_type, value_type ) \
+
+#endif // #ifndef CDSUNIT_SET_TYPE_SKIP_LIST_H
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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.
+*/
+
+#ifndef CDSUNIT_SET_TYPE_SPLIT_LIST_H
+#define CDSUNIT_SET_TYPE_SPLIT_LIST_H
+
+#include "set_type.h"
+
+#include <cds/container/michael_list_hp.h>
+#include <cds/container/michael_list_dhp.h>
+#include <cds/container/michael_list_rcu.h>
+#include <cds/container/lazy_list_hp.h>
+#include <cds/container/lazy_list_dhp.h>
+#include <cds/container/lazy_list_rcu.h>
+#include <cds/container/iterable_list_hp.h>
+#include <cds/container/iterable_list_dhp.h>
+
+#include <cds/container/split_list_set.h>
+#include <cds/container/split_list_set_rcu.h>
+
+#include <cds_test/stat_splitlist_out.h>
+#include <cds_test/stat_michael_list_out.h>
+#include <cds_test/stat_lazy_list_out.h>
+#include <cds_test/stat_iterable_list_out.h>
+
+namespace set {
+
+ template <typename GC, typename T, typename Traits = cc::split_list::traits>
+ class SplitListSet : public cc::SplitListSet< GC, T, Traits >
+ {
+ typedef cc::SplitListSet< GC, T, Traits > base_class;
+ public:
+ template <typename Config>
+ SplitListSet( Config const& cfg )
+ : base_class( cfg.s_nSetSize, cfg.s_nLoadFactor )
+ {}
+
+ template <typename Iterator>
+ typename std::enable_if< std::is_same< Iterator, typename base_class::iterator>::value, Iterator>::type
+ get_begin()
+ {
+ return base_class::begin();
+ }
+
+ template <typename Iterator>
+ typename std::enable_if< std::is_same< Iterator, typename base_class::iterator>::value, Iterator>::type
+ get_end()
+ {
+ return base_class::end();
+ }
+
+ // for testing
+ static CDS_CONSTEXPR bool const c_bExtractSupported = true;
+ static CDS_CONSTEXPR bool const c_bLoadFactorDepended = true;
+ static CDS_CONSTEXPR bool const c_bEraseExactKey = false;
+ };
+
+ struct tag_SplitListSet;
+
+ template <typename Key, typename Val>
+ struct set_type< tag_SplitListSet, Key, Val >: public set_type_base< Key, Val >
+ {
+ typedef set_type_base< Key, Val > base_class;
+ typedef typename base_class::key_val key_val;
+ typedef typename base_class::compare compare;
+ typedef typename base_class::less less;
+ typedef typename base_class::hash hash;
+
+ // ***************************************************************************
+ // SplitListSet based on MichaelList
+
+ struct traits_SplitList_Michael_dyn_cmp :
+ public cc::split_list::make_traits<
+ cc::split_list::ordered_list<cc::michael_list_tag>
+ ,co::hash< hash >
+ ,co::item_counter<cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::michael_list::make_traits<
+ co::compare< compare >
+ >::type
+ >
+ >::type
+ {};
+ typedef SplitListSet< cds::gc::HP, key_val, traits_SplitList_Michael_dyn_cmp > SplitList_Michael_HP_dyn_cmp;
+ typedef SplitListSet< cds::gc::DHP, key_val, traits_SplitList_Michael_dyn_cmp > SplitList_Michael_DHP_dyn_cmp;
+ typedef SplitListSet< rcu_gpi, key_val, traits_SplitList_Michael_dyn_cmp > SplitList_Michael_RCU_GPI_dyn_cmp;
+ typedef SplitListSet< rcu_gpb, key_val, traits_SplitList_Michael_dyn_cmp > SplitList_Michael_RCU_GPB_dyn_cmp;
+ typedef SplitListSet< rcu_gpt, key_val, traits_SplitList_Michael_dyn_cmp > SplitList_Michael_RCU_GPT_dyn_cmp;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SplitListSet< rcu_shb, key_val, traits_SplitList_Michael_dyn_cmp > SplitList_Michael_RCU_SHB_dyn_cmp;
+#endif
+
+ struct traits_SplitList_Michael_dyn_cmp_swar: public traits_SplitList_Michael_dyn_cmp
+ {
+ typedef cds::algo::bit_reversal::swar bit_reversal;
+ };
+ typedef SplitListSet< cds::gc::HP, key_val, traits_SplitList_Michael_dyn_cmp_swar > SplitList_Michael_HP_dyn_cmp_swar;
+ typedef SplitListSet< cds::gc::DHP, key_val, traits_SplitList_Michael_dyn_cmp_swar > SplitList_Michael_DHP_dyn_cmp_swar;
+ typedef SplitListSet< rcu_gpi, key_val, traits_SplitList_Michael_dyn_cmp_swar > SplitList_Michael_RCU_GPI_dyn_cmp_swar;
+ typedef SplitListSet< rcu_gpb, key_val, traits_SplitList_Michael_dyn_cmp_swar > SplitList_Michael_RCU_GPB_dyn_cmp_swar;
+ typedef SplitListSet< rcu_gpt, key_val, traits_SplitList_Michael_dyn_cmp_swar > SplitList_Michael_RCU_GPT_dyn_cmp_swar;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SplitListSet< rcu_shb, key_val, traits_SplitList_Michael_dyn_cmp_swar > SplitList_Michael_RCU_SHB_dyn_cmp_swar;
+#endif
+
+ struct traits_SplitList_Michael_dyn_cmp_stat :
+ public cc::split_list::make_traits<
+ cc::split_list::ordered_list<cc::michael_list_tag>
+ ,co::hash< hash >
+ , co::item_counter<cds::atomicity::cache_friendly_item_counter >
+ ,co::stat< cc::split_list::stat<> >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::michael_list::make_traits<
+ co::compare< compare >
+ ,co::stat< cc::michael_list::stat<>>
+ >::type
+ >
+ >::type
+ {};
+ typedef SplitListSet< cds::gc::HP, key_val, traits_SplitList_Michael_dyn_cmp_stat > SplitList_Michael_HP_dyn_cmp_stat;
+ typedef SplitListSet< cds::gc::DHP, key_val, traits_SplitList_Michael_dyn_cmp_stat > SplitList_Michael_DHP_dyn_cmp_stat;
+ typedef SplitListSet< rcu_gpi, key_val, traits_SplitList_Michael_dyn_cmp_stat > SplitList_Michael_RCU_GPI_dyn_cmp_stat;
+ typedef SplitListSet< rcu_gpb, key_val, traits_SplitList_Michael_dyn_cmp_stat > SplitList_Michael_RCU_GPB_dyn_cmp_stat;
+ typedef SplitListSet< rcu_gpt, key_val, traits_SplitList_Michael_dyn_cmp_stat > SplitList_Michael_RCU_GPT_dyn_cmp_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SplitListSet< rcu_shb, key_val, traits_SplitList_Michael_dyn_cmp_stat > SplitList_Michael_RCU_SHB_dyn_cmp_stat;
+#endif
+
+ struct traits_SplitList_Michael_dyn_cmp_seqcst :
+ public cc::split_list::make_traits<
+ cc::split_list::ordered_list<cc::michael_list_tag>
+ ,co::hash< hash >
+ ,co::item_counter<cds::atomicity::cache_friendly_item_counter >
+ ,co::memory_model< co::v::sequential_consistent >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::michael_list::make_traits<
+ co::compare< compare >
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ >
+ >::type
+ {};
+ typedef SplitListSet< cds::gc::HP, key_val, traits_SplitList_Michael_dyn_cmp_seqcst > SplitList_Michael_HP_dyn_cmp_seqcst;
+ typedef SplitListSet< cds::gc::DHP, key_val, traits_SplitList_Michael_dyn_cmp_seqcst > SplitList_Michael_DHP_dyn_cmp_seqcst;
+ typedef SplitListSet< rcu_gpi, key_val, traits_SplitList_Michael_dyn_cmp_seqcst > SplitList_Michael_RCU_GPI_dyn_cmp_seqcst;
+ typedef SplitListSet< rcu_gpb, key_val, traits_SplitList_Michael_dyn_cmp_seqcst > SplitList_Michael_RCU_GPB_dyn_cmp_seqcst;
+ typedef SplitListSet< rcu_gpt, key_val, traits_SplitList_Michael_dyn_cmp_seqcst > SplitList_Michael_RCU_GPT_dyn_cmp_seqcst;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SplitListSet< rcu_shb, key_val, traits_SplitList_Michael_dyn_cmp_seqcst > SplitList_Michael_RCU_SHB_dyn_cmp_seqcst;
+#endif
+
+ struct traits_SplitList_Michael_st_cmp :
+ public cc::split_list::make_traits<
+ cc::split_list::ordered_list<cc::michael_list_tag>
+ ,cc::split_list::dynamic_bucket_table< false >
+ ,co::hash< hash >
+ ,co::item_counter<cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::michael_list::make_traits<
+ co::compare< compare >
+ >::type
+ >
+ >::type
+ {};
+ typedef SplitListSet< cds::gc::HP, key_val, traits_SplitList_Michael_st_cmp > SplitList_Michael_HP_st_cmp;
+ typedef SplitListSet< cds::gc::DHP, key_val, traits_SplitList_Michael_st_cmp > SplitList_Michael_DHP_st_cmp;
+ typedef SplitListSet< rcu_gpi, key_val, traits_SplitList_Michael_st_cmp > SplitList_Michael_RCU_GPI_st_cmp;
+ typedef SplitListSet< rcu_gpb, key_val, traits_SplitList_Michael_st_cmp > SplitList_Michael_RCU_GPB_st_cmp;
+ typedef SplitListSet< rcu_gpt, key_val, traits_SplitList_Michael_st_cmp > SplitList_Michael_RCU_GPT_st_cmp;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SplitListSet< rcu_shb, key_val, traits_SplitList_Michael_st_cmp > SplitList_Michael_RCU_SHB_st_cmp;
+#endif
+
+ //HP + less
+ struct traits_SplitList_Michael_dyn_less :
+ public cc::split_list::make_traits<
+ cc::split_list::ordered_list<cc::michael_list_tag>
+ ,co::hash< hash >
+ , co::item_counter<cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::michael_list::make_traits<
+ co::less< less >
+ >::type
+ >
+ >::type
+ {};
+ typedef SplitListSet< cds::gc::HP, key_val, traits_SplitList_Michael_dyn_less > SplitList_Michael_HP_dyn_less;
+ typedef SplitListSet< cds::gc::DHP, key_val, traits_SplitList_Michael_dyn_less > SplitList_Michael_DHP_dyn_less;
+ typedef SplitListSet< rcu_gpi, key_val, traits_SplitList_Michael_dyn_less > SplitList_Michael_RCU_GPI_dyn_less;
+ typedef SplitListSet< rcu_gpb, key_val, traits_SplitList_Michael_dyn_less > SplitList_Michael_RCU_GPB_dyn_less;
+ typedef SplitListSet< rcu_gpt, key_val, traits_SplitList_Michael_dyn_less > SplitList_Michael_RCU_GPT_dyn_less;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SplitListSet< rcu_shb, key_val, traits_SplitList_Michael_dyn_less > SplitList_Michael_RCU_SHB_dyn_less;
+#endif
+
+ struct traits_SplitList_Michael_st_less :
+ public cc::split_list::make_traits<
+ cc::split_list::ordered_list<cc::michael_list_tag>
+ ,cc::split_list::dynamic_bucket_table< false >
+ ,co::hash< hash >
+ , co::item_counter<cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::michael_list::make_traits<
+ co::less< less >
+ >::type
+ >
+ >::type
+ {};
+ typedef SplitListSet< cds::gc::HP, key_val, traits_SplitList_Michael_st_less > SplitList_Michael_HP_st_less;
+ typedef SplitListSet< cds::gc::DHP, key_val, traits_SplitList_Michael_st_less > SplitList_Michael_DHP_st_less;
+ typedef SplitListSet< rcu_gpi, key_val, traits_SplitList_Michael_st_less > SplitList_Michael_RCU_GPI_st_less;
+ typedef SplitListSet< rcu_gpb, key_val, traits_SplitList_Michael_st_less > SplitList_Michael_RCU_GPB_st_less;
+ typedef SplitListSet< rcu_gpt, key_val, traits_SplitList_Michael_st_less > SplitList_Michael_RCU_GPT_st_less;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SplitListSet< rcu_shb, key_val, traits_SplitList_Michael_st_less > SplitList_Michael_RCU_SHB_st_less;
+#endif
+
+ struct traits_SplitList_Michael_st_less_stat :
+ public cc::split_list::make_traits<
+ cc::split_list::ordered_list<cc::michael_list_tag>
+ ,cc::split_list::dynamic_bucket_table< false >
+ ,co::hash< hash >
+ , co::item_counter<cds::atomicity::cache_friendly_item_counter >
+ ,co::stat< cc::split_list::stat<>>
+ ,cc::split_list::ordered_list_traits<
+ typename cc::michael_list::make_traits<
+ co::less< less >
+ ,co::stat< cc::michael_list::stat<>>
+ >::type
+ >
+ >::type
+ {};
+ typedef SplitListSet< cds::gc::HP, key_val, traits_SplitList_Michael_st_less_stat > SplitList_Michael_HP_st_less_stat;
+ typedef SplitListSet< cds::gc::DHP, key_val, traits_SplitList_Michael_st_less_stat > SplitList_Michael_DHP_st_less_stat;
+ typedef SplitListSet< rcu_gpi, key_val, traits_SplitList_Michael_st_less_stat > SplitList_Michael_RCU_GPI_st_less_stat;
+ typedef SplitListSet< rcu_gpb, key_val, traits_SplitList_Michael_st_less_stat > SplitList_Michael_RCU_GPB_st_less_stat;
+ typedef SplitListSet< rcu_gpt, key_val, traits_SplitList_Michael_st_less_stat > SplitList_Michael_RCU_GPT_st_less_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SplitListSet< rcu_shb, key_val, traits_SplitList_Michael_st_less_stat > SplitList_Michael_RCU_SHB_st_less_stat;
+#endif
+
+ // ***************************************************************************
+ // SplitListSet based on LazyList
+
+ struct traits_SplitList_Lazy_dyn_cmp :
+ public cc::split_list::make_traits<
+ cc::split_list::ordered_list<cc::lazy_list_tag>
+ ,co::hash< hash >
+ , co::item_counter<cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::lazy_list::make_traits<
+ co::compare< compare >
+ >::type
+ >
+ >::type
+ {};
+ typedef SplitListSet< cds::gc::HP, key_val, traits_SplitList_Lazy_dyn_cmp > SplitList_Lazy_HP_dyn_cmp;
+ typedef SplitListSet< cds::gc::DHP, key_val, traits_SplitList_Lazy_dyn_cmp > SplitList_Lazy_DHP_dyn_cmp;
+ typedef SplitListSet< rcu_gpi, key_val, traits_SplitList_Lazy_dyn_cmp > SplitList_Lazy_RCU_GPI_dyn_cmp;
+ typedef SplitListSet< rcu_gpb, key_val, traits_SplitList_Lazy_dyn_cmp > SplitList_Lazy_RCU_GPB_dyn_cmp;
+ typedef SplitListSet< rcu_gpt, key_val, traits_SplitList_Lazy_dyn_cmp > SplitList_Lazy_RCU_GPT_dyn_cmp;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SplitListSet< rcu_shb, key_val, traits_SplitList_Lazy_dyn_cmp > SplitList_Lazy_RCU_SHB_dyn_cmp;
+#endif
+
+ struct traits_SplitList_Lazy_dyn_cmp_stat : public traits_SplitList_Lazy_dyn_cmp
+ {
+ typedef cc::split_list::stat<> stat;
+ typedef typename cc::lazy_list::make_traits<
+ co::compare< compare >
+ , co::stat< cc::lazy_list::stat<>>
+ >::type ordered_list_traits;
+ };
+ typedef SplitListSet< cds::gc::HP, key_val, traits_SplitList_Lazy_dyn_cmp_stat > SplitList_Lazy_HP_dyn_cmp_stat;
+ typedef SplitListSet< cds::gc::DHP, key_val, traits_SplitList_Lazy_dyn_cmp_stat > SplitList_Lazy_DHP_dyn_cmp_stat;
+ typedef SplitListSet< rcu_gpi, key_val, traits_SplitList_Lazy_dyn_cmp_stat > SplitList_Lazy_RCU_GPI_dyn_cmp_stat;
+ typedef SplitListSet< rcu_gpb, key_val, traits_SplitList_Lazy_dyn_cmp_stat > SplitList_Lazy_RCU_GPB_dyn_cmp_stat;
+ typedef SplitListSet< rcu_gpt, key_val, traits_SplitList_Lazy_dyn_cmp_stat > SplitList_Lazy_RCU_GPT_dyn_cmp_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SplitListSet< rcu_shb, key_val, traits_SplitList_Lazy_dyn_cmp > SplitList_Lazy_RCU_SHB_dyn_cmp_stat;
+#endif
+
+ struct traits_SplitList_Lazy_dyn_cmp_seqcst :
+ public cc::split_list::make_traits<
+ cc::split_list::ordered_list<cc::lazy_list_tag>
+ ,co::hash< hash >
+ , co::item_counter<cds::atomicity::cache_friendly_item_counter >
+ ,co::memory_model< co::v::sequential_consistent >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::lazy_list::make_traits<
+ co::compare< compare >
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ >
+ >::type
+ {};
+ typedef SplitListSet< cds::gc::HP, key_val, traits_SplitList_Lazy_dyn_cmp_seqcst > SplitList_Lazy_HP_dyn_cmp_seqcst;
+ typedef SplitListSet< cds::gc::DHP, key_val, traits_SplitList_Lazy_dyn_cmp_seqcst > SplitList_Lazy_DHP_dyn_cmp_seqcst;
+ typedef SplitListSet< rcu_gpi, key_val, traits_SplitList_Lazy_dyn_cmp_seqcst > SplitList_Lazy_RCU_GPI_dyn_cmp_seqcst;
+ typedef SplitListSet< rcu_gpb, key_val, traits_SplitList_Lazy_dyn_cmp_seqcst > SplitList_Lazy_RCU_GPB_dyn_cmp_seqcst;
+ typedef SplitListSet< rcu_gpt, key_val, traits_SplitList_Lazy_dyn_cmp_seqcst > SplitList_Lazy_RCU_GPT_dyn_cmp_seqcst;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SplitListSet< rcu_shb, key_val, traits_SplitList_Lazy_dyn_cmp_seqcst > SplitList_Lazy_RCU_SHB_dyn_cmp_seqcst;
+#endif
+
+ struct traits_SplitList_Lazy_st_cmp :
+ public cc::split_list::make_traits<
+ cc::split_list::ordered_list<cc::lazy_list_tag>
+ ,cc::split_list::dynamic_bucket_table< false >
+ ,co::hash< hash >
+ , co::item_counter<cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::lazy_list::make_traits<
+ co::compare< compare >
+ >::type
+ >
+ >::type
+ {};
+ typedef SplitListSet< cds::gc::HP, key_val, traits_SplitList_Lazy_st_cmp > SplitList_Lazy_HP_st_cmp;
+ typedef SplitListSet< cds::gc::DHP, key_val, traits_SplitList_Lazy_st_cmp > SplitList_Lazy_DHP_st_cmp;
+ typedef SplitListSet< rcu_gpi, key_val, traits_SplitList_Lazy_st_cmp > SplitList_Lazy_RCU_GPI_st_cmp;
+ typedef SplitListSet< rcu_gpb, key_val, traits_SplitList_Lazy_st_cmp > SplitList_Lazy_RCU_GPB_st_cmp;
+ typedef SplitListSet< rcu_gpt, key_val, traits_SplitList_Lazy_st_cmp > SplitList_Lazy_RCU_GPT_st_cmp;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SplitListSet< rcu_shb, key_val, traits_SplitList_Lazy_st_cmp > SplitList_Lazy_RCU_SHB_st_cmp;
+#endif
+
+ struct traits_SplitList_Lazy_dyn_less :
+ public cc::split_list::make_traits<
+ cc::split_list::ordered_list<cc::lazy_list_tag>
+ ,co::hash< hash >
+ , co::item_counter<cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::lazy_list::make_traits<
+ co::less< less >
+ >::type
+ >
+ >::type
+ {};
+ typedef SplitListSet< cds::gc::HP, key_val, traits_SplitList_Lazy_dyn_less > SplitList_Lazy_HP_dyn_less;
+ typedef SplitListSet< cds::gc::DHP, key_val, traits_SplitList_Lazy_dyn_less > SplitList_Lazy_DHP_dyn_less;
+ typedef SplitListSet< rcu_gpi, key_val, traits_SplitList_Lazy_dyn_less > SplitList_Lazy_RCU_GPI_dyn_less;
+ typedef SplitListSet< rcu_gpb, key_val, traits_SplitList_Lazy_dyn_less > SplitList_Lazy_RCU_GPB_dyn_less;
+ typedef SplitListSet< rcu_gpt, key_val, traits_SplitList_Lazy_dyn_less > SplitList_Lazy_RCU_GPT_dyn_less;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SplitListSet< rcu_shb, key_val, traits_SplitList_Lazy_dyn_less > SplitList_Lazy_RCU_SHB_dyn_less;
+#endif
+
+ struct traits_SplitList_Lazy_st_less :
+ public cc::split_list::make_traits<
+ cc::split_list::ordered_list<cc::lazy_list_tag>
+ ,cc::split_list::dynamic_bucket_table< false >
+ ,co::hash< hash >
+ , co::item_counter<cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::lazy_list::make_traits<
+ co::less< less >
+ >::type
+ >
+ >::type
+ {};
+ typedef SplitListSet< cds::gc::HP, key_val, traits_SplitList_Lazy_st_less > SplitList_Lazy_HP_st_less;
+ typedef SplitListSet< cds::gc::DHP, key_val, traits_SplitList_Lazy_st_less > SplitList_Lazy_DHP_st_less;
+ typedef SplitListSet< rcu_gpi, key_val, traits_SplitList_Lazy_st_less > SplitList_Lazy_RCU_GPI_st_less;
+ typedef SplitListSet< rcu_gpb, key_val, traits_SplitList_Lazy_st_less > SplitList_Lazy_RCU_GPB_st_less;
+ typedef SplitListSet< rcu_gpt, key_val, traits_SplitList_Lazy_st_less > SplitList_Lazy_RCU_GPT_st_less;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SplitListSet< rcu_shb, key_val, traits_SplitList_Lazy_st_less > SplitList_Lazy_RCU_SHB_st_less;
+#endif
+
+ struct traits_SplitList_Lazy_st_less_stat : public traits_SplitList_Lazy_st_less
+ {
+ typedef cc::split_list::stat<> stat;
+ typedef typename cc::lazy_list::make_traits<
+ co::less< less >
+ , co::stat< cc::lazy_list::stat<>>
+ >::type ordered_list_traits;
+ };
+ typedef SplitListSet< cds::gc::HP, key_val, traits_SplitList_Lazy_st_less_stat > SplitList_Lazy_HP_st_less_stat;
+ typedef SplitListSet< cds::gc::DHP, key_val, traits_SplitList_Lazy_st_less_stat > SplitList_Lazy_DHP_st_less_stat;
+ typedef SplitListSet< rcu_gpi, key_val, traits_SplitList_Lazy_st_less_stat > SplitList_Lazy_RCU_GPI_st_less_stat;
+ typedef SplitListSet< rcu_gpb, key_val, traits_SplitList_Lazy_st_less_stat > SplitList_Lazy_RCU_GPB_st_less_stat;
+ typedef SplitListSet< rcu_gpt, key_val, traits_SplitList_Lazy_st_less_stat > SplitList_Lazy_RCU_GPT_st_less_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef SplitListSet< rcu_shb, key_val, traits_SplitList_Lazy_st_less_stat > SplitList_Lazy_RCU_SHB_st_less_stat;
+#endif
+
+ // ***************************************************************************
+ // SplitListSet based on IterableList
+
+ struct traits_SplitList_Iterable_dyn_cmp :
+ public cc::split_list::make_traits<
+ cc::split_list::ordered_list<cc::iterable_list_tag>
+ ,co::hash< hash >
+ , co::item_counter<cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::iterable_list::make_traits<
+ co::compare< compare >
+ >::type
+ >
+ >::type
+ {};
+ typedef SplitListSet< cds::gc::HP, key_val, traits_SplitList_Iterable_dyn_cmp > SplitList_Iterable_HP_dyn_cmp;
+ typedef SplitListSet< cds::gc::DHP, key_val, traits_SplitList_Iterable_dyn_cmp > SplitList_Iterable_DHP_dyn_cmp;
+
+ struct traits_SplitList_Iterable_dyn_cmp_stat:
+ public cc::split_list::make_traits<
+ cc::split_list::ordered_list<cc::iterable_list_tag>
+ ,co::hash< hash >
+ , co::item_counter<cds::atomicity::cache_friendly_item_counter >
+ ,co::stat< cc::split_list::stat<> >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::iterable_list::make_traits<
+ co::compare< compare >
+ ,co::stat< cc::iterable_list::stat<>>
+ >::type
+ >
+ >::type
+ {};
+ typedef SplitListSet< cds::gc::HP, key_val, traits_SplitList_Iterable_dyn_cmp_stat > SplitList_Iterable_HP_dyn_cmp_stat;
+ typedef SplitListSet< cds::gc::DHP, key_val, traits_SplitList_Iterable_dyn_cmp_stat > SplitList_Iterable_DHP_dyn_cmp_stat;
+
+ struct traits_SplitList_Iterable_dyn_cmp_seqcst :
+ public cc::split_list::make_traits<
+ cc::split_list::ordered_list<cc::iterable_list_tag>
+ ,co::hash< hash >
+ , co::item_counter<cds::atomicity::cache_friendly_item_counter >
+ ,co::memory_model< co::v::sequential_consistent >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::iterable_list::make_traits<
+ co::compare< compare >
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ >
+ >::type
+ {};
+ typedef SplitListSet< cds::gc::HP, key_val, traits_SplitList_Iterable_dyn_cmp_seqcst > SplitList_Iterable_HP_dyn_cmp_seqcst;
+ typedef SplitListSet< cds::gc::DHP, key_val, traits_SplitList_Iterable_dyn_cmp_seqcst > SplitList_Iterable_DHP_dyn_cmp_seqcst;
+
+ struct traits_SplitList_Iterable_st_cmp :
+ public cc::split_list::make_traits<
+ cc::split_list::ordered_list<cc::iterable_list_tag>
+ ,cc::split_list::dynamic_bucket_table< false >
+ ,co::hash< hash >
+ , co::item_counter<cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::iterable_list::make_traits<
+ co::compare< compare >
+ >::type
+ >
+ >::type
+ {};
+ typedef SplitListSet< cds::gc::HP, key_val, traits_SplitList_Iterable_st_cmp > SplitList_Iterable_HP_st_cmp;
+ typedef SplitListSet< cds::gc::DHP, key_val, traits_SplitList_Iterable_st_cmp > SplitList_Iterable_DHP_st_cmp;
+
+ //HP + less
+ struct traits_SplitList_Iterable_dyn_less :
+ public cc::split_list::make_traits<
+ cc::split_list::ordered_list<cc::iterable_list_tag>
+ ,co::hash< hash >
+ , co::item_counter<cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::iterable_list::make_traits<
+ co::less< less >
+ >::type
+ >
+ >::type
+ {};
+ typedef SplitListSet< cds::gc::HP, key_val, traits_SplitList_Iterable_dyn_less > SplitList_Iterable_HP_dyn_less;
+ typedef SplitListSet< cds::gc::DHP, key_val, traits_SplitList_Iterable_dyn_less > SplitList_Iterable_DHP_dyn_less;
+
+ struct traits_SplitList_Iterable_st_less :
+ public cc::split_list::make_traits<
+ cc::split_list::ordered_list<cc::iterable_list_tag>
+ ,cc::split_list::dynamic_bucket_table< false >
+ ,co::hash< hash >
+ , co::item_counter<cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::iterable_list::make_traits<
+ co::less< less >
+ >::type
+ >
+ >::type
+ {};
+ typedef SplitListSet< cds::gc::HP, key_val, traits_SplitList_Iterable_st_less > SplitList_Iterable_HP_st_less;
+ typedef SplitListSet< cds::gc::DHP, key_val, traits_SplitList_Iterable_st_less > SplitList_Iterable_DHP_st_less;
+
+ struct traits_SplitList_Iterable_st_less_stat :
+ public cc::split_list::make_traits<
+ cc::split_list::ordered_list<cc::iterable_list_tag>
+ ,cc::split_list::dynamic_bucket_table< false >
+ ,co::hash< hash >
+ , co::item_counter<cds::atomicity::cache_friendly_item_counter >
+ ,co::stat< cc::split_list::stat<>>
+ ,cc::split_list::ordered_list_traits<
+ typename cc::iterable_list::make_traits<
+ co::less< less >
+ ,co::stat< cc::iterable_list::stat<>>
+ >::type
+ >
+ >::type
+ {};
+ typedef SplitListSet< cds::gc::HP, key_val, traits_SplitList_Iterable_st_less_stat > SplitList_Iterable_HP_st_less_stat;
+ typedef SplitListSet< cds::gc::DHP, key_val, traits_SplitList_Iterable_st_less_stat > SplitList_Iterable_DHP_st_less_stat;
+
+ };
+
+ template <typename GC, typename T, typename Traits>
+ static inline void print_stat( cds_test::property_stream& o, SplitListSet<GC, T, Traits> const& s )
+ {
+ o << s.statistics()
+ << cds_test::stat_prefix( "list_stat" )
+ << s.list_statistics()
+ << cds_test::stat_prefix( "" );
+ }
+
+} // namespace set
+
+
+#define CDSSTRESS_SplitListSet_case( fixture, test_case, splitlist_set_type, key_type, value_type ) \
+ TEST_P( fixture, splitlist_set_type ) \
+ { \
+ typedef set::set_type< tag_SplitListSet, key_type, value_type >::splitlist_set_type set_type; \
+ test_case<set_type>(); \
+ }
+
+
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+
+#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL > 1
+# define CDSSTRESS_SplitListSet_SHRCU_2( fixture, test_case, key_type, value_type ) \
+
+#else
+# define CDSSTRESS_SplitListSet_SHRCU_2( fixture, test_case, key_type, value_type )
+#endif
+
+#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL == 1
+# define CDSSTRESS_SplitListSet_SHRCU_1( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_RCU_SHT_dyn_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_RCU_SHB_st_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_RCU_SHB_dyn_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_RCU_SHB_st_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_RCU_SHT_dyn_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_RCU_SHT_st_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_RCU_SHB_dyn_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_RCU_SHT_st_less, key_type, value_type ) \
+
+#else
+# define CDSSTRESS_SplitListSet_SHRCU_1( fixture, test_case, key_type, value_type )
+#endif
+
+
+# define CDSSTRESS_SplitListSet_SHRCU( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_RCU_SHB_dyn_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_RCU_SHT_st_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_RCU_SHT_dyn_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_RCU_SHT_st_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_RCU_SHB_dyn_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_RCU_SHB_st_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_RCU_SHT_dyn_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_RCU_SHB_st_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_SHRCU_1( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_SHRCU_2( fixture, test_case, key_type, value_type ) \
+
+#else
+# define CDSSTRESS_SplitListSet_SHRCU( fixture, test_case, key_type, value_type )
+#endif
+
+#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL > 1
+# define CDSSTRESS_SplitListSet_HP_2( fixture, test_case, key_type, value_type ) \
+
+# define CDSSTRESS_SplitListSet_RCU_2( fixture, test_case, key_type, value_type ) \
+
+#else
+# define CDSSTRESS_SplitListSet_HP_2( fixture, test_case, key_type, value_type )
+# define CDSSTRESS_SplitListSet_RCU_2( fixture, test_case, key_type, value_type )
+#endif
+
+#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL == 1
+# define CDSSTRESS_SplitListSet_HP_1( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_DHP_dyn_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_DHP_dyn_cmp_swar, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_HP_st_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_DHP_dyn_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_HP_st_less, key_type, value_type ) \
+ \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_DHP_dyn_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_DHP_st_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_HP_dyn_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_DHP_st_less, key_type, value_type ) \
+
+# define CDSSTRESS_SplitListSet_RCU_1( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_RCU_GPT_dyn_cmp_swar, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_RCU_GPI_st_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_RCU_GPT_st_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_RCU_GPB_dyn_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_RCU_GPI_st_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_RCU_GPT_st_less, key_type, value_type ) \
+ \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_RCU_GPB_dyn_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_RCU_GPB_st_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_RCU_GPI_dyn_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_RCU_GPT_dyn_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_RCU_GPB_st_less, key_type, value_type ) \
+ \
+ CDSSTRESS_SplitListSet_SHRCU( fixture, test_case, key_type, value_type )
+
+
+#else
+# define CDSSTRESS_SplitListSet_HP_1( fixture, test_case, key_type, value_type )
+# define CDSSTRESS_SplitListSet_RCU_1( fixture, test_case, key_type, value_type )
+#endif
+
+#define CDSSTRESS_SplitListSet_HP( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_HP_dyn_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_HP_dyn_cmp_swar, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_DHP_st_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_HP_dyn_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_DHP_st_less, key_type, value_type ) \
+ \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_HP_dyn_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_HP_st_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_DHP_dyn_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_HP_st_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_HP_1( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_HP_2( fixture, test_case, key_type, value_type ) \
+
+#define CDSSTRESS_SplitListSet_RCU( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_RCU_GPI_dyn_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_RCU_GPB_dyn_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_RCU_GPB_dyn_cmp_swar, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_RCU_GPT_dyn_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_RCU_GPB_st_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_RCU_GPI_dyn_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_RCU_GPT_dyn_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Michael_RCU_GPB_st_less, key_type, value_type ) \
+ \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_RCU_GPI_dyn_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_RCU_GPT_dyn_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_RCU_GPI_st_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_RCU_GPT_st_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_RCU_GPB_dyn_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_RCU_GPI_st_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Lazy_RCU_GPT_st_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_RCU_1( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_RCU_2( fixture, test_case, key_type, value_type ) \
+
+#define CDSSTRESS_SplitListSet( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_HP( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_RCU( fixture, test_case, key_type, value_type ) \
+
+#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL > 0
+# define CDSSTRESS_SplitListIterableSet_1( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Iterable_DHP_dyn_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Iterable_HP_st_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Iterable_DHP_dyn_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Iterable_HP_st_less, key_type, value_type ) \
+
+#else
+# define CDSSTRESS_SplitListIterableSet_1( fixture, test_case, key_type, value_type )
+#endif
+
+#define CDSSTRESS_SplitListIterableSet( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Iterable_HP_dyn_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Iterable_DHP_st_cmp, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Iterable_HP_dyn_less, key_type, value_type ) \
+ CDSSTRESS_SplitListSet_case( fixture, test_case, SplitList_Iterable_DHP_st_less, key_type, value_type ) \
+ CDSSTRESS_SplitListIterableSet_1( fixture, test_case, key_type, value_type )
+
+#endif // #ifndef CDSUNIT_SET_TYPE_SPLIT_LIST_H
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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.
+*/
+
+#ifndef CDSUNIT_SET_TYPE_STD_H
+#define CDSUNIT_SET_TYPE_STD_H
+
+#include <unordered_set>
+#include <set>
+#include <mutex> //unique_lock
+
+#include "set_type.h"
+
+namespace set {
+
+ struct tag_StdSet;
+
+ template <typename Value, typename Hash, typename Less, typename EqualTo, typename Lock,
+ class Alloc = typename CDS_DEFAULT_ALLOCATOR::template rebind<Value>::other
+ >
+ class StdHashSet
+ : public std::unordered_set<
+ Value
+ , Hash
+ , EqualTo
+ , Alloc
+ >
+ {
+ public:
+ Lock m_lock;
+ typedef std::unique_lock<Lock> scoped_lock;
+ typedef std::unordered_set<
+ Value
+ , Hash
+ , EqualTo
+ , Alloc
+ > base_class;
+
+ public:
+ typedef typename base_class::value_type value_type;
+
+ template <class Config>
+ StdHashSet( Config const& )
+ {}
+
+ template <typename Key>
+ bool contains( const Key& key )
+ {
+ scoped_lock al( m_lock );
+ return base_class::find( value_type(key)) != base_class::end();
+ }
+
+ template <typename Key>
+ bool insert( Key const& key )
+ {
+ scoped_lock al( m_lock );
+ std::pair<typename base_class::iterator, bool> pRet = base_class::insert( value_type( key ));
+ return pRet.second;
+ }
+
+ template <typename Key, typename Func>
+ bool insert( Key const& key, Func func )
+ {
+ scoped_lock al( m_lock );
+ std::pair<typename base_class::iterator, bool> pRet = base_class::insert( value_type( key ));
+ if ( pRet.second ) {
+ func( *pRet.first );
+ return true;
+ }
+ return false;
+ }
+
+ template <typename T, typename Func>
+ std::pair<bool, bool> ensure( const T& key, Func func )
+ {
+ scoped_lock al( m_lock );
+ std::pair<typename base_class::iterator, bool> pRet = base_class::insert( value_type( key ));
+ if ( pRet.second ) {
+ func( true, *pRet.first, key );
+ return std::make_pair( true, true );
+ }
+ else {
+ func( false, *pRet.first, key );
+ return std::make_pair( true, false );
+ }
+ }
+
+ template <typename Key>
+ bool erase( const Key& key )
+ {
+ scoped_lock al( m_lock );
+ return base_class::erase( value_type(key)) != 0;
+ }
+
+ template <typename T, typename Func>
+ bool erase( const T& key, Func func )
+ {
+ scoped_lock al( m_lock );
+ typename base_class::iterator it = base_class::find( value_type(key));
+ if ( it != base_class::end()) {
+ func( *it );
+ return base_class::erase( it ) != base_class::end();
+ }
+ return false;
+ }
+
+ empty_stat statistics() const
+ {
+ return empty_stat();
+ }
+
+ // for testing
+ static CDS_CONSTEXPR bool const c_bExtractSupported = false;
+ static CDS_CONSTEXPR bool const c_bLoadFactorDepended = false;
+ static CDS_CONSTEXPR bool const c_bEraseExactKey = true;
+ };
+
+ template <typename Value, typename Less, typename Lock,
+ class Alloc = typename CDS_DEFAULT_ALLOCATOR::template rebind<Value>::other
+ >
+ class StdSet: public std::set<Value, Less, Alloc>
+ {
+ Lock m_lock;
+ typedef std::unique_lock<Lock> scoped_lock;
+ typedef std::set<Value, Less, Alloc> base_class;
+ public:
+ typedef typename base_class::key_type value_type;
+
+ template <class Config>
+ StdSet( Config const& )
+ {}
+
+ template <typename Key>
+ bool contains( const Key& key )
+ {
+ value_type v( key );
+ scoped_lock al( m_lock );
+ return base_class::find( v ) != base_class::end();
+ }
+
+ template <typename Key>
+ bool insert( Key const& k )
+ {
+ scoped_lock al( m_lock );
+ return base_class::insert( value_type( k )).second;
+ }
+
+ template <typename Key, typename Func>
+ bool insert( Key const& key, Func func )
+ {
+ scoped_lock al( m_lock );
+ std::pair<typename base_class::iterator, bool> pRet = base_class::insert( value_type( key ));
+ if ( pRet.second ) {
+ func( *pRet.first );
+ return true;
+ }
+ return false;
+ }
+
+ template <typename T, typename Func>
+ std::pair<bool, bool> ensure( const T& key, Func func )
+ {
+ scoped_lock al( m_lock );
+ std::pair<typename base_class::iterator, bool> pRet = base_class::insert( value_type( key ));
+ if ( pRet.second ) {
+ func( true, *pRet.first, key );
+ return std::make_pair( true, true );
+ }
+ else {
+ func( false, *pRet.first, key );
+ return std::make_pair( true, false );
+ }
+ }
+
+ template <typename Key>
+ bool erase( const Key& key )
+ {
+ scoped_lock al( m_lock );
+ return base_class::erase( value_type(key)) != 0;
+ }
+
+ template <typename T, typename Func>
+ bool erase( const T& key, Func func )
+ {
+ scoped_lock al( m_lock );
+ typename base_class::iterator it = base_class::find( value_type(key));
+ if ( it != base_class::end()) {
+ func( *it );
+
+ base_class::erase( it );
+ return true;
+ }
+ return false;
+ }
+
+ empty_stat statistics() const
+ {
+ return empty_stat();
+ }
+
+ // for testing
+ static CDS_CONSTEXPR bool const c_bExtractSupported = false;
+ static CDS_CONSTEXPR bool const c_bLoadFactorDepended = false;
+ };
+
+ template <typename Key, typename Val>
+ struct set_type< tag_StdSet, Key, Val >: public set_type_base< Key, Val >
+ {
+ typedef set_type_base< Key, Val > base_class;
+ typedef typename base_class::key_val key_val;
+ typedef typename base_class::less less;
+ typedef typename base_class::hash hash;
+ typedef typename base_class::equal_to equal_to;
+
+ typedef StdSet< key_val, less, cds::sync::spin > StdSet_Spin;
+ typedef StdSet< key_val, less, std::mutex > StdSet_Mutex;
+ //typedef StdSet< key_val, less, lock::NoLock> StdSet_NoLock;
+
+ typedef StdHashSet< key_val, hash, less, equal_to, cds::sync::spin > StdHashSet_Spin;
+ typedef StdHashSet< key_val, hash, less, equal_to, std::mutex > StdHashSet_Mutex;
+ //typedef StdHashSet< key_val, hash, less, equal_to, lock::NoLock > StdHashSet_NoLock;
+ };
+
+} // namespace set
+
+#define CDSSTRESS_StdSet_case( fixture, test_case, std_set_type, key_type, value_type ) \
+ TEST_F( fixture, std_set_type ) \
+ { \
+ typedef set::set_type< tag_StdSet, key_type, value_type >::std_set_type set_type; \
+ test_case<set_type>(); \
+ }
+
+#define CDSSTRESS_StdSet( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_StdSet_case( fixture, test_case, StdSet_Spin, key_type, value_type ) \
+ CDSSTRESS_StdSet_case( fixture, test_case, StdHashSet_Spin, key_type, value_type ) \
+
+#endif // #ifndef CDSUNIT_SET_TYPE_STD_H
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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.
+*/
+
+#ifndef CDSUNIT_SET_TYPE_STRIPED_H
+#define CDSUNIT_SET_TYPE_STRIPED_H
+
+#include "set_type.h"
+
+#include <cds/container/striped_set/std_list.h>
+#include <cds/container/striped_set/std_vector.h>
+#include <cds/container/striped_set/std_set.h>
+#include <cds/container/striped_set/std_hash_set.h>
+#include <cds/container/striped_set/boost_unordered_set.h>
+
+#include <boost/version.hpp>
+#if BOOST_VERSION >= 104800
+# include <cds/container/striped_set/boost_slist.h>
+# include <cds/container/striped_set/boost_list.h>
+# include <cds/container/striped_set/boost_vector.h>
+# include <cds/container/striped_set/boost_stable_vector.h>
+# include <cds/container/striped_set/boost_set.h>
+# include <cds/container/striped_set/boost_flat_set.h>
+#endif
+#include <cds/container/striped_set.h>
+
+namespace set {
+
+ struct tag_StripedSet;
+
+ template <typename Key, typename Val>
+ struct set_type< tag_StripedSet, Key, Val >: public set_type_base< Key, Val >
+ {
+ typedef set_type_base< Key, Val > base_class;
+ typedef typename base_class::key_val key_val;
+ typedef typename base_class::compare compare;
+ typedef typename base_class::less less;
+ typedef typename base_class::equal_to equal_to;
+ typedef typename base_class::hash hash;
+ typedef typename base_class::hash2 hash2;
+
+
+ // ***************************************************************************
+ // StripedSet
+
+ // for sequential containers
+ template <class BucketEntry, typename... Options>
+ class StripedHashSet_seq:
+ public cc::StripedSet< BucketEntry,
+ co::mutex_policy< cc::striped_set::striping<> >
+ ,co::resizing_policy<cc::striped_set::load_factor_resizing<0> >
+ , Options...
+ >
+ {
+ typedef cc::StripedSet< BucketEntry,
+ co::mutex_policy< cc::striped_set::striping<> >
+ ,co::resizing_policy<cc::striped_set::load_factor_resizing<0> >
+ , Options...
+ > base_class;
+ typedef typename base_class::resizing_policy resizing_policy_t;
+
+ resizing_policy_t m_placeHolder;
+ public:
+ template <class Config>
+ StripedHashSet_seq( Config const& cfg )
+ : base_class( cfg.s_nSetSize / cfg.s_nLoadFactor / 16, *(new(&m_placeHolder) resizing_policy_t( cfg.s_nLoadFactor )))
+ {}
+
+ empty_stat statistics() const
+ {
+ return empty_stat();
+ }
+
+ /*
+ template <typename Q, typename Less>
+ bool erase_with( Q const& v, Less pred )
+ {
+ return base_class::erase( v );
+ }
+ */
+
+ // for testing
+ static CDS_CONSTEXPR bool const c_bExtractSupported = false;
+ static CDS_CONSTEXPR bool const c_bLoadFactorDepended = true;
+ static CDS_CONSTEXPR bool const c_bEraseExactKey = false;
+ };
+
+ template <class BucketEntry, typename... Options>
+ class StripedHashSet_seq_rational:
+ public cc::StripedSet< BucketEntry,
+ co::mutex_policy< cc::striped_set::striping<> >
+ ,co::resizing_policy<cc::striped_set::rational_load_factor_resizing<0> >
+ , Options...
+ >
+ {
+ typedef cc::StripedSet< BucketEntry,
+ co::mutex_policy< cc::striped_set::striping<> >
+ ,co::resizing_policy<cc::striped_set::rational_load_factor_resizing<0> >
+ , Options...
+ > base_class;
+ typedef typename base_class::resizing_policy resizing_policy_t;
+
+ resizing_policy_t m_placeHolder;
+ public:
+ template <class Config>
+ StripedHashSet_seq_rational( Config const& cfg ) // LoadFactor = 1 / nDenominator
+ : base_class( cfg.s_nSetSize / cfg.s_nLoadFactor / 16, *(new(&m_placeHolder) resizing_policy_t( 1, cfg.s_nLoadFactor )))
+ {}
+
+ empty_stat statistics() const
+ {
+ return empty_stat();
+ }
+
+ /*
+ template <typename Q, typename Less>
+ bool erase_with( Q const& v, Less pred )
+ {
+ return base_class::erase( v );
+ }
+ */
+
+ // for testing
+ static CDS_CONSTEXPR bool const c_bExtractSupported = false;
+ static CDS_CONSTEXPR bool const c_bLoadFactorDepended = true;
+ static CDS_CONSTEXPR bool const c_bEraseExactKey = false;
+ };
+
+ // for non-sequential ordered containers
+ template <class BucketEntry, typename... Options>
+ class StripedHashSet_ord:
+ public cc::StripedSet< BucketEntry,
+ co::resizing_policy<cc::striped_set::load_factor_resizing<0> >
+ ,co::mutex_policy< cc::striped_set::striping<> >
+ , Options...
+ >
+ {
+ typedef cc::StripedSet< BucketEntry,
+ co::resizing_policy<cc::striped_set::load_factor_resizing<0> >
+ ,co::mutex_policy< cc::striped_set::striping<> >
+ , Options...
+ > base_class;
+ typedef typename base_class::resizing_policy resizing_policy_t;
+
+ resizing_policy_t m_placeHolder;
+ public:
+ template <class Config>
+ StripedHashSet_ord( Config const& cfg )
+ : base_class( 0, *(new(&m_placeHolder) resizing_policy_t( cfg.s_nMaxLoadFactor * 1024 )))
+ {}
+
+ empty_stat statistics() const
+ {
+ return empty_stat();
+ }
+
+ // for testing
+ static CDS_CONSTEXPR bool const c_bExtractSupported = false;
+ static CDS_CONSTEXPR bool const c_bLoadFactorDepended = false;
+ static CDS_CONSTEXPR bool const c_bEraseExactKey = false;
+ };
+
+ template <class BucketEntry, typename... Options>
+ class StripedHashSet_ord_rational:
+ public cc::StripedSet< BucketEntry,
+ co::resizing_policy<cc::striped_set::rational_load_factor_resizing<0> >
+ ,co::mutex_policy< cc::striped_set::striping<> >
+ , Options...
+ >
+ {
+ typedef cc::StripedSet< BucketEntry,
+ co::resizing_policy<cc::striped_set::rational_load_factor_resizing<0> >
+ ,co::mutex_policy< cc::striped_set::striping<> >
+ , Options...
+ > base_class;
+ typedef typename base_class::resizing_policy resizing_policy_t;
+
+ resizing_policy_t m_placeHolder;
+ public:
+ template <class Config>
+ StripedHashSet_ord_rational( Config const& cfg ) // LoadFactor = 1 / nDenominator
+ : base_class( 0, *(new(&m_placeHolder) resizing_policy_t( 1024, cfg.s_nLoadFactor )))
+ {}
+
+ empty_stat statistics() const
+ {
+ return empty_stat();
+ }
+
+ // for testing
+ static CDS_CONSTEXPR bool const c_bExtractSupported = false;
+ static CDS_CONSTEXPR bool const c_bLoadFactorDepended = true;
+ static CDS_CONSTEXPR bool const c_bEraseExactKey = false;
+ };
+
+ typedef StripedHashSet_seq<
+ std::list< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > StripedSet_list;
+
+ typedef StripedHashSet_seq_rational<
+ std::list< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > StripedSet_rational_list;
+
+ typedef StripedHashSet_seq<
+ std::vector< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > StripedSet_vector;
+
+ typedef StripedHashSet_seq_rational<
+ std::vector< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > StripedSet_rational_vector;
+
+#if BOOST_VERSION >= 104800
+ typedef StripedHashSet_seq<
+ boost::container::slist< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > StripedSet_boost_slist;
+
+ typedef StripedHashSet_seq_rational<
+ boost::container::slist< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > StripedSet_rational_boost_slist;
+
+ typedef StripedHashSet_seq<
+ boost::container::list< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > StripedSet_boost_list;
+
+ typedef StripedHashSet_seq_rational<
+ boost::container::list< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > StripedSet_rational_boost_list;
+
+ typedef StripedHashSet_seq<
+ boost::container::vector< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > StripedSet_boost_vector;
+
+ typedef StripedHashSet_seq_rational<
+ boost::container::vector< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > StripedSet_rational_boost_vector;
+
+ typedef StripedHashSet_seq<
+ boost::container::stable_vector< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > StripedSet_boost_stable_vector;
+
+ typedef StripedHashSet_seq_rational<
+ boost::container::stable_vector< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > StripedSet_rational_boost_stable_vector;
+#endif
+
+ typedef StripedHashSet_ord<
+ std::set< key_val, less >
+ , co::hash< hash2 >
+ > StripedSet_set;
+
+ typedef StripedHashSet_ord_rational<
+ std::set< key_val, less >
+ , co::hash< hash2 >
+ > StripedSet_rational_set;
+
+ typedef StripedHashSet_ord<
+ std::unordered_set< key_val, hash, equal_to >
+ , co::hash< hash2 >
+ > StripedSet_hashset;
+
+ typedef StripedHashSet_ord_rational<
+ std::unordered_set< key_val, hash, equal_to >
+ , co::hash< hash2 >
+ > StripedSet_rational_hashset;
+
+#if BOOST_VERSION >= 104800
+ typedef StripedHashSet_ord<
+ boost::container::set< key_val, less >
+ , co::hash< hash2 >
+ > StripedSet_boost_set;
+
+ typedef StripedHashSet_ord_rational<
+ boost::container::set< key_val, less >
+ , co::hash< hash2 >
+ > StripedSet_rational_boost_set;
+
+ typedef StripedHashSet_ord<
+ boost::container::flat_set< key_val, less >
+ , co::hash< hash2 >
+ > StripedSet_boost_flat_set;
+
+ typedef StripedHashSet_ord_rational<
+ boost::container::flat_set< key_val, less >
+ , co::hash< hash2 >
+ > StripedSet_rational_boost_flat_set;
+#endif
+
+ typedef StripedHashSet_ord<
+ boost::unordered_set< key_val, hash, equal_to >
+ , co::hash< hash2 >
+ > StripedSet_boost_unordered_set;
+
+ typedef StripedHashSet_ord_rational<
+ boost::unordered_set< key_val, hash, equal_to >
+ , co::hash< hash2 >
+ > StripedSet_rational_boost_unordered_set;
+
+
+ // ***************************************************************************
+ // RefinableSet
+
+ // for sequential containers
+ template <class BucketEntry, typename... Options>
+ class RefinableHashSet_seq:
+ public cc::StripedSet< BucketEntry,
+ co::mutex_policy< cc::striped_set::refinable<> >
+ ,co::resizing_policy<cc::striped_set::load_factor_resizing<0> >
+ , Options...
+ >
+ {
+ typedef cc::StripedSet< BucketEntry,
+ co::mutex_policy< cc::striped_set::refinable<> >
+ ,co::resizing_policy<cc::striped_set::load_factor_resizing<0> >
+ , Options...
+ > base_class;
+ typedef typename base_class::resizing_policy resizing_policy_t;
+
+ resizing_policy_t m_placeHolder;
+ public:
+ template <class Config>
+ RefinableHashSet_seq( Config const& cfg )
+ : base_class( cfg.s_nSetSize / cfg.s_nLoadFactor / 16, *(new(&m_placeHolder) resizing_policy_t( cfg.s_nLoadFactor )))
+ {}
+
+ empty_stat statistics() const
+ {
+ return empty_stat();
+ }
+
+ /*
+ template <typename Q, typename Less>
+ bool erase_with( Q const& v, Less pred )
+ {
+ return base_class::erase( v );
+ }
+ */
+
+ // for testing
+ static CDS_CONSTEXPR bool const c_bExtractSupported = false;
+ static CDS_CONSTEXPR bool const c_bLoadFactorDepended = true;
+ };
+
+ template <class BucketEntry, typename... Options>
+ class RefinableHashSet_seq_rational:
+ public cc::StripedSet< BucketEntry,
+ co::mutex_policy< cc::striped_set::refinable<> >
+ ,co::resizing_policy<cc::striped_set::rational_load_factor_resizing<0> >
+ , Options...
+ >
+ {
+ typedef cc::StripedSet< BucketEntry,
+ co::mutex_policy< cc::striped_set::refinable<> >
+ ,co::resizing_policy<cc::striped_set::rational_load_factor_resizing<0> >
+ , Options...
+ > base_class;
+ typedef typename base_class::resizing_policy resizing_policy_t;
+
+ resizing_policy_t m_placeHolder;
+ public:
+ template <class Config>
+ RefinableHashSet_seq_rational( Config const& cfg ) // LoadFactor = 1 / nDenominator
+ : base_class( cfg.s_nSetSize / cfg.s_nLoadFactor / 16, *(new(&m_placeHolder) resizing_policy_t( 1, cfg.s_nLoadFactor )))
+ {}
+
+ empty_stat statistics() const
+ {
+ return empty_stat();
+ }
+
+ // for testing
+ static CDS_CONSTEXPR bool const c_bExtractSupported = false;
+ static CDS_CONSTEXPR bool const c_bLoadFactorDepended = true;
+ };
+
+ // for non-sequential ordered containers
+ template <class BucketEntry, typename... Options>
+ class RefinableHashSet_ord:
+ public cc::StripedSet< BucketEntry,
+ co::resizing_policy<cc::striped_set::load_factor_resizing<0> >
+ ,co::mutex_policy< cc::striped_set::refinable<> >
+ , Options...
+ >
+ {
+ typedef cc::StripedSet< BucketEntry,
+ co::resizing_policy<cc::striped_set::load_factor_resizing<0> >
+ ,co::mutex_policy< cc::striped_set::refinable<> >
+ , Options...
+ > base_class;
+ typedef typename base_class::resizing_policy resizing_policy_t;
+
+ resizing_policy_t m_placeHolder;
+ public:
+ template <class Config>
+ RefinableHashSet_ord( Config const& cfg )
+ : base_class( 0, *(new(&m_placeHolder) resizing_policy_t( cfg.s_nMaxLoadFactor * 1024 )))
+ {}
+
+ empty_stat statistics() const
+ {
+ return empty_stat();
+ }
+
+ // for testing
+ static CDS_CONSTEXPR bool const c_bExtractSupported = false;
+ static CDS_CONSTEXPR bool const c_bLoadFactorDepended = false;
+ };
+
+ template <class BucketEntry, typename... Options>
+ class RefinableHashSet_ord_rational:
+ public cc::StripedSet< BucketEntry,
+ co::resizing_policy<cc::striped_set::rational_load_factor_resizing<0> >
+ ,co::mutex_policy< cc::striped_set::refinable<> >
+ , Options...
+ >
+ {
+ typedef cc::StripedSet< BucketEntry,
+ co::resizing_policy<cc::striped_set::rational_load_factor_resizing<0> >
+ ,co::mutex_policy< cc::striped_set::refinable<> >
+ , Options...
+ > base_class;
+ typedef typename base_class::resizing_policy resizing_policy_t;
+
+ resizing_policy_t m_placeHolder;
+ public:
+ template <class Config>
+ RefinableHashSet_ord_rational( Config const& cfg ) // LoadFactor = 1 / nDenominator
+ : base_class( 0, *(new(&m_placeHolder) resizing_policy_t( 1024, cfg.s_nLoadFactor )))
+ {}
+
+ empty_stat statistics() const
+ {
+ return empty_stat();
+ }
+
+ // for testing
+ static CDS_CONSTEXPR bool const c_bExtractSupported = false;
+ static CDS_CONSTEXPR bool const c_bLoadFactorDepended = true;
+ };
+
+ typedef RefinableHashSet_seq<
+ std::list< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > RefinableSet_list;
+
+ typedef RefinableHashSet_seq_rational<
+ std::list< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > RefinableSet_rational_list;
+
+ typedef RefinableHashSet_seq<
+ std::vector< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > RefinableSet_vector;
+
+ typedef RefinableHashSet_seq_rational<
+ std::vector< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > RefinableSet_rational_vector;
+
+#if BOOST_VERSION >= 104800
+ typedef RefinableHashSet_seq<
+ boost::container::slist< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > RefinableSet_boost_slist;
+
+ typedef RefinableHashSet_seq_rational<
+ boost::container::slist< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > RefinableSet_rational_boost_slist;
+
+ typedef RefinableHashSet_seq<
+ boost::container::list< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > RefinableSet_boost_list;
+
+ typedef RefinableHashSet_seq_rational<
+ boost::container::list< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > RefinableSet_rational_boost_list;
+
+ typedef RefinableHashSet_seq<
+ boost::container::vector< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > RefinableSet_boost_vector;
+
+ typedef RefinableHashSet_seq_rational<
+ boost::container::vector< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > RefinableSet_rational_boost_vector;
+
+ typedef RefinableHashSet_seq<
+ boost::container::stable_vector< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > RefinableSet_boost_stable_vector;
+
+ typedef RefinableHashSet_seq_rational<
+ boost::container::stable_vector< key_val >
+ , co::hash< hash2 >
+ , co::less< less >
+ > RefinableSet_rational_boost_stable_vector;
+#endif
+
+ typedef RefinableHashSet_ord<
+ std::set< key_val, less >
+ , co::hash< hash2 >
+ > RefinableSet_set;
+
+ typedef RefinableHashSet_ord_rational<
+ std::set< key_val, less >
+ , co::hash< hash2 >
+ > RefinableSet_rational_set;
+
+ typedef RefinableHashSet_ord<
+ std::unordered_set< key_val, hash, equal_to >
+ , co::hash< hash2 >
+ > RefinableSet_hashset;
+
+ typedef RefinableHashSet_ord_rational<
+ std::unordered_set< key_val, hash, equal_to >
+ , co::hash< hash2 >
+ > RefinableSet_rational_hashset;
+
+#if BOOST_VERSION >= 104800
+ typedef RefinableHashSet_ord<
+ boost::container::set< key_val, less >
+ , co::hash< hash2 >
+ > RefinableSet_boost_set;
+
+ typedef RefinableHashSet_ord_rational<
+ boost::container::set< key_val, less >
+ , co::hash< hash2 >
+ > RefinableSet_rational_boost_set;
+
+ typedef RefinableHashSet_ord<
+ boost::container::flat_set< key_val, less >
+ , co::hash< hash2 >
+ > RefinableSet_boost_flat_set;
+
+ typedef RefinableHashSet_ord_rational<
+ boost::container::flat_set< key_val, less >
+ , co::hash< hash2 >
+ > RefinableSet_rational_boost_flat_set;
+#endif
+
+ typedef RefinableHashSet_ord<
+ boost::unordered_set< key_val, hash, equal_to >
+ , co::hash< hash2 >
+ > RefinableSet_boost_unordered_set;
+
+ typedef RefinableHashSet_ord_rational<
+ boost::unordered_set< key_val, hash, equal_to >
+ , co::hash< hash2 >
+ > RefinableSet_rational_boost_unordered_set;
+ };
+
+} // namespace set
+
+#define CDSSTRESS_StripedSet_case( fixture, test_case, striped_set_type, key_type, value_type ) \
+ TEST_P( fixture, striped_set_type ) \
+ { \
+ typedef set::set_type< tag_StripedSet, key_type, value_type >::striped_set_type set_type; \
+ test_case<set_type>(); \
+ }
+
+#define CDSSTRESS_StripedSet( fixture, test_case, key_type, value_type ) \
+ CDSSTRESS_StripedSet_case( fixture, test_case, StripedSet_list, key_type, value_type ) \
+ CDSSTRESS_StripedSet_case( fixture, test_case, StripedSet_rational_list, key_type, value_type ) \
+ CDSSTRESS_StripedSet_case( fixture, test_case, StripedSet_vector, key_type, value_type ) \
+ CDSSTRESS_StripedSet_case( fixture, test_case, StripedSet_rational_vector, key_type, value_type ) \
+ CDSSTRESS_StripedSet_case( fixture, test_case, StripedSet_set, key_type, value_type ) \
+ CDSSTRESS_StripedSet_case( fixture, test_case, StripedSet_rational_set, key_type, value_type ) \
+ CDSSTRESS_StripedSet_case( fixture, test_case, StripedSet_hashset, key_type, value_type ) \
+ CDSSTRESS_StripedSet_case( fixture, test_case, StripedSet_rational_hashset, key_type, value_type ) \
+ CDSSTRESS_StripedSet_case( fixture, test_case, RefinableSet_list, key_type, value_type ) \
+ CDSSTRESS_StripedSet_case( fixture, test_case, RefinableSet_rational_list, key_type, value_type ) \
+ CDSSTRESS_StripedSet_case( fixture, test_case, RefinableSet_vector, key_type, value_type ) \
+ CDSSTRESS_StripedSet_case( fixture, test_case, RefinableSet_rational_vector, key_type, value_type ) \
+ CDSSTRESS_StripedSet_case( fixture, test_case, RefinableSet_set, key_type, value_type ) \
+ CDSSTRESS_StripedSet_case( fixture, test_case, RefinableSet_rational_set, key_type, value_type ) \
+ CDSSTRESS_StripedSet_case( fixture, test_case, RefinableSet_hashset, key_type, value_type ) \
+ CDSSTRESS_StripedSet_case( fixture, test_case, RefinableSet_rational_hashset, key_type, value_type )
+
+#endif // #ifndef CDSUNIT_SET_TYPE_STRIPED_H
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 <cds_test/stress_test.h>
+
+#include <cds/intrusive/free_list.h>
+#include <cds/intrusive/free_list_cached.h>
+#ifdef CDS_DCAS_SUPPORT
+# include <cds/intrusive/free_list_tagged.h>
+#endif
+
+namespace {
+ class put_get: public cds_test::stress_fixture
+ {
+ protected:
+ static size_t s_nThreadCount;
+ static size_t s_nPassCount;
+ static size_t const c_nArraySize = 100;
+
+ template <typename FreeList >
+ struct value_type: public FreeList::node
+ {
+ size_t counter;
+
+ value_type()
+ : counter(0)
+ {}
+ };
+
+ template <class FreeList>
+ class Worker: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ public:
+ FreeList& m_FreeList;
+ size_t m_nSuccess = 0;
+
+ public:
+ Worker( cds_test::thread_pool& pool, FreeList& s )
+ : base_class( pool )
+ , m_FreeList( s )
+ {}
+
+ Worker( Worker& src )
+ : base_class( src )
+ , m_FreeList( src.m_FreeList )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Worker( *this );
+ }
+
+ virtual void test()
+ {
+ typedef value_type<FreeList> item_type;
+ item_type* arr[ c_nArraySize ];
+
+ for ( size_t pass = 0; pass < s_nPassCount; ++pass ) {
+ size_t n = 0;
+ item_type* p;
+
+ while ( (p = static_cast<item_type*>( m_FreeList.get())) != nullptr ) {
+ CDS_TSAN_ANNOTATE_IGNORE_RW_BEGIN;
+ p->counter++;
+ CDS_TSAN_ANNOTATE_IGNORE_RW_END;
+ arr[n] = p;
+ ++m_nSuccess;
+ ++n;
+ }
+
+ for ( size_t i = 0; i < n; ++i )
+ m_FreeList.put( arr[i] );
+ }
+ }
+ };
+
+ public:
+ static void SetUpTestCase()
+ {
+ cds_test::config const& cfg = get_config( "SequentialFreeList" );
+
+ s_nPassCount = cfg.get_size_t( "PassCount", s_nPassCount );
+
+ s_nThreadCount = 1;
+ if ( s_nPassCount == 0 )
+ s_nPassCount = 1000;
+ }
+ //static void TearDownTestCase();
+
+ protected:
+
+ template <typename FreeList>
+ void test( FreeList& list )
+ {
+ cds_test::thread_pool& pool = get_pool();
+
+ value_type<FreeList> arr[c_nArraySize];
+
+ for ( auto& i : arr )
+ list.put( &i );
+
+ pool.add( new Worker<FreeList>( pool, list ), s_nThreadCount );
+
+ propout() << std::make_pair( "work_thread", s_nThreadCount )
+ << std::make_pair( "pass_count", s_nPassCount );
+
+ std::chrono::milliseconds duration = pool.run();
+
+ propout() << std::make_pair( "duration", duration );
+
+ // analyze result
+ size_t nTotal = 0;
+ for ( auto const& i : arr )
+ nTotal += i.counter;
+
+ size_t nSuccess = 0;
+ for ( size_t threadNo = 0; threadNo < pool.size(); ++threadNo )
+ nSuccess += static_cast<Worker<FreeList>&>( pool.get( threadNo )).m_nSuccess;
+
+ EXPECT_EQ( nSuccess, nTotal );
+
+ list.clear( []( typename FreeList::node* ) {} );
+ }
+ };
+
+ size_t put_get::s_nThreadCount = 1;
+ size_t put_get::s_nPassCount = 100000;
+
+#define CDSSTRESS_FREELIST_F( name, freelist_type ) \
+ TEST_F( put_get, name ) \
+ { \
+ freelist_type fl; \
+ test( fl ); \
+ }
+
+ CDSSTRESS_FREELIST_F( FreeList, cds::intrusive::FreeList )
+
+ typedef cds::intrusive::CachedFreeList<cds::intrusive::FreeList> cached_free_list;
+ CDSSTRESS_FREELIST_F( CachedFreeList, cached_free_list )
+
+#ifdef CDS_DCAS_SUPPORT
+ TEST_F( put_get, TaggetFreeList )
+ {
+ struct tagged_ptr {
+ void* p;
+ uintptr_t tag;
+ };
+
+ atomics::atomic<tagged_ptr> tp;
+ if ( tp.is_lock_free()) {
+ cds::intrusive::TaggedFreeList fl;
+ test( fl );
+ }
+ else
+ std::cout << "Double-width CAS is not supported\n";
+ }
+#endif
+
+} // namespace
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 <cds_test/stress_test.h>
+
+#include <cds/intrusive/free_list.h>
+#include <cds/intrusive/free_list_cached.h>
+#ifdef CDS_DCAS_SUPPORT
+# include <cds/intrusive/free_list_tagged.h>
+#endif
+
+namespace {
+ class put_get_single: public cds_test::stress_fixture
+ {
+ protected:
+ static size_t s_nThreadCount;
+ static size_t s_nPassCount;
+
+ template <typename FreeList >
+ struct value_type: public FreeList::node
+ {
+ atomics::atomic<size_t> counter;
+
+ value_type()
+ : counter(0)
+ {}
+ };
+
+ template <class FreeList>
+ class Worker: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ public:
+ FreeList& m_FreeList;
+ size_t m_nSuccess = 0;
+
+ public:
+ Worker( cds_test::thread_pool& pool, FreeList& s )
+ : base_class( pool )
+ , m_FreeList( s )
+ {}
+
+ Worker( Worker& src )
+ : base_class( src )
+ , m_FreeList( src.m_FreeList )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Worker( *this );
+ }
+
+ virtual void test()
+ {
+ typedef value_type<FreeList> item_type;
+
+ for ( size_t pass = 0; pass < s_nPassCount; ++pass ) {
+ item_type* p;
+ while ( (p = static_cast<item_type*>( m_FreeList.get())) == nullptr );
+ p->counter.fetch_add( 1, atomics::memory_order_relaxed );
+ m_FreeList.put( p );
+ }
+ }
+ };
+
+ public:
+ static void SetUpTestCase()
+ {
+ cds_test::config const& cfg = get_config( "SequentialFreeList" );
+
+ s_nPassCount = cfg.get_size_t( "SinglePassCount", s_nPassCount );
+
+ s_nThreadCount = 1;
+ if ( s_nPassCount == 0 )
+ s_nPassCount = 1000;
+ }
+ //static void TearDownTestCase();
+
+ protected:
+
+ template <typename FreeList>
+ void test( FreeList& list )
+ {
+ cds_test::thread_pool& pool = get_pool();
+
+ value_type<FreeList> item;;
+ list.put( &item );
+
+ pool.add( new Worker<FreeList>( pool, list ), s_nThreadCount );
+
+ propout() << std::make_pair( "work_thread", s_nThreadCount )
+ << std::make_pair( "pass_count", s_nPassCount );
+
+ std::chrono::milliseconds duration = pool.run();
+
+ propout() << std::make_pair( "duration", duration );
+
+ // analyze result
+ EXPECT_EQ( item.counter.load( atomics::memory_order_relaxed ), s_nPassCount * s_nThreadCount );
+
+ list.clear( []( typename FreeList::node* ) {} );
+ }
+ };
+
+ size_t put_get_single::s_nThreadCount = 1;
+ size_t put_get_single::s_nPassCount = 100000;
+
+#define CDSSTRESS_FREELIST_F( name, freelist_type ) \
+ TEST_F( put_get_single, name ) \
+ { \
+ freelist_type fl; \
+ test( fl ); \
+ }
+
+ CDSSTRESS_FREELIST_F( FreeList, cds::intrusive::FreeList )
+
+ typedef cds::intrusive::CachedFreeList<cds::intrusive::FreeList> cached_free_list;
+ CDSSTRESS_FREELIST_F( CachedFreeList, cached_free_list )
+
+#ifdef CDS_DCAS_SUPPORT
+ TEST_F( put_get_single, TaggetFreeList )
+ {
+ struct tagged_ptr {
+ void* p;
+ uintptr_t tag;
+ };
+
+ atomics::atomic<tagged_ptr> tp;
+ if ( tp.is_lock_free()) {
+ cds::intrusive::TaggedFreeList fl;
+ test( fl );
+ }
+ else
+ std::cout << "Double-width CAS is not supported\n";
+ }
+#endif
+
+} // namespace
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "../misc/common.h"
+#include "../queue/queue_type.h"
+
+#include <algorithm>
+#include <type_traits>
+#include <vector>
+
+// Sequential queue push/pop test
+namespace {
+
+static size_t s_nEnqueueCount = 4000000;
+// Call 's_nEnqueueStride' number of enqueue before dequeue.
+static size_t s_nEnqueueStride = 10000;
+static size_t s_nQueueSize = 100000;
+static size_t s_nVyukovQueuePushCount = 300000;
+
+struct old_value {
+ size_t nNo;
+};
+
+template <class Value = old_value>
+class sequential_queue : public cds_test::stress_fixture {
+protected:
+ using value_type = Value;
+
+ template <typename Queue>
+ void test(Queue &q, size_t enqueue_count = s_nEnqueueCount) {
+ value_type v;
+ v.nNo = 0;
+ size_t push_failure = 0;
+ size_t pop_sum = 0;
+
+ while (v.nNo < enqueue_count) {
+ size_t curr_push_count =
+ std::min(enqueue_count - v.nNo, s_nEnqueueStride);
+ for (size_t i = 0; i < curr_push_count; i++) {
+ if (q.push(v))
+ ++v.nNo;
+ else
+ ++push_failure;
+ }
+
+ value_type res;
+ while (q.pop(res)) {
+ pop_sum += res.nNo;
+ }
+ }
+
+ if (push_failure) {
+ std::cout << "Sequential queue push error count: " << push_failure
+ << "\n";
+ }
+ size_t supposed_sum = enqueue_count * (enqueue_count - 1) / 2;
+ if (pop_sum != supposed_sum) {
+ std::cout << "Sequential queue pop sum: " << pop_sum
+ << " != " << supposed_sum << "\n";
+ }
+ }
+
+public:
+ static void SetUpTestCase() {
+ cds_test::config const &cfg = get_config("SequentialQueue");
+ GetConfig(EnqueueCount);
+ GetConfig(EnqueueStride);
+ GetConfig(QueueSize);
+ GetConfig(VyukovQueuePushCount);
+ }
+};
+
+using simple_sequential_queue = sequential_queue<>;
+
+#define CDSSTRESS_Sequential_Queue_F(test_fixture, type_name) \
+ TEST_F(test_fixture, type_name) { \
+ typedef queue::Types<value_type>::type_name queue_type; \
+ queue_type queue(s_nQueueSize); \
+ test(queue, s_nVyukovQueuePushCount); \
+ }
+
+#define CDSSTRESS_Sequential_VyukovQueue(test_fixture) \
+ CDSSTRESS_Sequential_Queue_F(test_fixture, VyukovMPMCCycleQueue_dyn); \
+ CDSSTRESS_Sequential_Queue_F(test_fixture, VyukovMPMCCycleQueue_dyn_ic);
+
+CDSSTRESS_Sequential_VyukovQueue(simple_sequential_queue);
+
+#undef CDSSTRESS_Sequential_Queue_F
+#define CDSSTRESS_Sequential_Queue_F(test_fixture, type_name) \
+ TEST_F(test_fixture, type_name) { \
+ typedef queue::Types<value_type>::type_name queue_type; \
+ queue_type queue; \
+ test(queue); \
+ }
+
+#define CDSSTRESS_Sequential_MSQueue(test_fixture) \
+ CDSSTRESS_Sequential_Queue_F(test_fixture, MSQueue_HP); \
+ CDSSTRESS_Sequential_Queue_F(test_fixture, MSQueue_DHP);
+
+#define CDSSTRESS_Sequential_MoirQueue(test_fixture) \
+ CDSSTRESS_Sequential_Queue_F(test_fixture, MoirQueue_HP); \
+ CDSSTRESS_Sequential_Queue_F(test_fixture, MoirQueue_DHP);
+
+#define CDSSTRESS_Sequential_OptimsticQueue(test_fixture) \
+ CDSSTRESS_Sequential_Queue_F(test_fixture, OptimisticQueue_HP); \
+ CDSSTRESS_Sequential_Queue_F(test_fixture, OptimisticQueue_DHP);
+
+#define CDSSTRESS_Sequential_BasketQueue(test_fixture) \
+ CDSSTRESS_Sequential_Queue_F(test_fixture, BasketQueue_HP); \
+ CDSSTRESS_Sequential_Queue_F(test_fixture, BasketQueue_DHP);
+
+#define CDSSTRESS_Sequential_RWQueue(test_fixture) \
+ CDSSTRESS_Sequential_Queue_F(test_fixture, RWQueue_Spin);
+
+#define CDSSTRESS_Sequential_WeakRingBuffer(test_fixture) \
+ CDSSTRESS_Sequential_Queue_F(test_fixture, WeakRingBuffer_dyn);
+
+CDSSTRESS_Sequential_MSQueue(simple_sequential_queue);
+CDSSTRESS_Sequential_MoirQueue(simple_sequential_queue);
+CDSSTRESS_Sequential_BasketQueue(simple_sequential_queue);
+CDSSTRESS_Sequential_OptimsticQueue(simple_sequential_queue);
+CDSSTRESS_Sequential_RWQueue(simple_sequential_queue);
+CDSSTRESS_Sequential_WeakRingBuffer(simple_sequential_queue);
+
+// ********************************************************************
+// SegmentedQueue test
+
+class sequential_segmented_queue
+ : public sequential_queue<>,
+ public ::testing::WithParamInterface<size_t> {
+ typedef sequential_queue<> base_class;
+
+protected:
+ template <typename Queue> void test() {
+ size_t quasi_factor = GetParam();
+ Queue q(quasi_factor);
+ base_class::test(q);
+ }
+
+public:
+ static std::vector<size_t> get_test_parameters() {
+ cds_test::config const &cfg =
+ cds_test::stress_fixture::get_config("SequentialQueue");
+ bool bIterative = cfg.get_bool("SegmentedQueue_Iterate", false);
+ size_t quasi_factor = cfg.get_size_t("SegmentedQueue_SegmentSize", 256);
+
+ std::vector<size_t> args;
+ if (bIterative && quasi_factor > 4) {
+ for (size_t qf = 4; qf <= quasi_factor; qf *= 2)
+ args.push_back(qf);
+ } else {
+ if (quasi_factor > 2)
+ args.push_back(quasi_factor);
+ else
+ args.push_back(2);
+ }
+
+ return args;
+ }
+};
+
+#undef CDSSTRESS_Sequential_Queue_F
+#define CDSSTRESS_Sequential_Queue_F(test_fixture, type_name) \
+ TEST_P(test_fixture, type_name) { \
+ typedef typename queue::Types<value_type>::type_name queue_type; \
+ test<queue_type>(); \
+ }
+
+#define CDSSTRESS_Sequential_SegmentedQueue(test_fixture) \
+ CDSSTRESS_Sequential_Queue_F(test_fixture, SegmentedQueue_HP_spin); \
+ CDSSTRESS_Sequential_Queue_F(test_fixture, SegmentedQueue_HP_spin_padding); \
+ CDSSTRESS_Sequential_Queue_F(test_fixture, SegmentedQueue_DHP_spin);
+
+CDSSTRESS_Sequential_SegmentedQueue(sequential_segmented_queue)
+
+#ifdef CDSTEST_GTEST_INSTANTIATE_TEST_CASE_P_HAS_4TH_ARG
+ static std::string
+ get_test_parameter_name(testing::TestParamInfo<size_t> const &p) {
+ return std::to_string(p.param);
+}
+INSTANTIATE_TEST_CASE_P(
+ SQ, sequential_segmented_queue,
+ ::testing::ValuesIn(sequential_segmented_queue::get_test_parameters()),
+ get_test_parameter_name);
+#else
+ INSTANTIATE_TEST_CASE_P(
+ SQ, sequential_segmented_queue,
+ ::testing::ValuesIn(sequential_segmented_queue::get_test_parameters()));
+#endif
+
+// ********************************************************************
+// SPSC WeakRingBuffer
+static size_t s_nBufferSize = 1024 * 1024;
+static size_t s_nPushCount = 1000000;
+
+class sequential_weak_ring_buffer : public cds_test::stress_fixture {
+protected:
+ typedef size_t value_type;
+
+ template <typename Queue> void test(Queue &m_Queue) {
+ size_t const nPushCount = s_nPushCount;
+ size_t m_nPushed = 0;
+ size_t m_nPushFailed = 0;
+ size_t m_nPopped = 0;
+ size_t m_nBadValue = 0;
+ size_t m_nPopFrontFailed = 0;
+ size_t m_nPopEmpty = 0;
+
+ for (size_t i = 0; i < nPushCount; ++i) {
+ size_t len = rand(1024) + 64;
+ void *buf = m_Queue.back(len);
+ if (buf) {
+ memset(buf, len % 256, len);
+ m_Queue.push_back();
+ m_nPushed += len;
+ } else
+ ++m_nPushFailed;
+ }
+
+ while (true) {
+ auto buf = m_Queue.front();
+ if (buf.first) {
+ m_nPopped += buf.second;
+
+ uint8_t val = static_cast<uint8_t>(buf.second % 256);
+ uint8_t const *p = reinterpret_cast<uint8_t *>(buf.first);
+ for (uint8_t const *pEnd = p + buf.second; p < pEnd; ++p) {
+ if (*p != val) {
+ ++m_nBadValue;
+ break;
+ }
+ }
+
+ if (!m_Queue.pop_front())
+ ++m_nPopFrontFailed;
+ } else {
+ ++m_nPopEmpty;
+ if (m_Queue.empty())
+ break;
+ }
+ }
+ }
+
+public:
+ static void SetUpTestCase() {
+ cds_test::config const &cfg = get_config("SequentialRingBuffer");
+
+ s_nBufferSize = cfg.get_size_t("BufferSize", s_nBufferSize);
+ s_nPushCount = cfg.get_size_t("PushCount", s_nPushCount);
+
+ if (s_nBufferSize < 1024 * 64)
+ s_nBufferSize = 1024 * 64;
+ if (s_nPushCount == 0u)
+ s_nPushCount = 1024;
+ }
+};
+
+#undef CDSSTRESS_Sequential_Queue_F
+#define CDSSTRESS_Sequential_Queue_F(test_fixture, type_name) \
+ TEST_F(test_fixture, type_name) { \
+ typedef queue::Types<value_type>::type_name queue_type; \
+ queue_type queue(s_nBufferSize); \
+ test(queue); \
+ }
+
+CDSSTRESS_WeakRingBuffer_void(sequential_weak_ring_buffer)
+
+#undef CDSSTRESS_Queue_F
+
+} // namespace
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ 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 "../misc/common.h"
+#include "../stack/stack_type.h"
+
+namespace {
+
+#define CDSSTRESS_SequentialTreiberStack_F(test_fixture, type_name) \
+ TEST_F(test_fixture, type_name) { \
+ typedef stack::Types<value_type>::type_name stack_type; \
+ stack_type stack; \
+ test(stack); \
+ }
+
+#define CDSSTRESS_SequentialEliminationStack_F(test_fixture, type_name) \
+ TEST_F(test_fixture, type_name) { \
+ typedef stack::Types<value_type>::type_name stack_type; \
+ stack_type stack(s_nSequentialEliminationSize); \
+ test(stack); \
+ }
+
+#define CDSSTRESS_SequentialTreiberStack(test_fixture) \
+ CDSSTRESS_SequentialTreiberStack_F(test_fixture, Treiber_HP); \
+ CDSSTRESS_SequentialTreiberStack_F(test_fixture, Treiber_DHP); \
+
+#define CDSSTRESS_SequentialEliminationStack(test_fixture) \
+ CDSSTRESS_SequentialEliminationStack_F(test_fixture, Elimination_HP); \
+ CDSSTRESS_SequentialEliminationStack_F(test_fixture, Elimination_HP_dyn); \
+ CDSSTRESS_SequentialEliminationStack_F(test_fixture, Elimination_DHP); \
+ CDSSTRESS_SequentialEliminationStack_F(test_fixture, Elimination_DHP_dyn)
+
+static size_t s_nSequentialStackPushCount = 100000;
+static size_t s_nSequentialEliminationSize = 4;
+
+class sequential_stack : public cds_test::stress_fixture {
+protected:
+ struct value_type {
+ size_t nNo;
+ size_t nThread;
+
+ value_type() : nNo(0), nThread(0) {}
+ value_type(size_t n) : nNo(n), nThread(0) {}
+ };
+
+protected:
+ static void SetUpTestCase() {
+ cds_test::config const &cfg = get_config("SequentialStack");
+ GetConfig(SequentialStackPushCount);
+ GetConfig(SequentialEliminationSize);
+ }
+
+ template <typename Stack> void test(Stack &stack) {
+ size_t push_error_cnt = 0;
+ size_t pop_sum = 0;
+ value_type v;
+ size_t m_nStartItem = 0;
+ size_t m_nEndItem = s_nSequentialStackPushCount;
+ for (v.nNo = m_nStartItem; v.nNo < m_nEndItem; ++v.nNo) {
+ if (!stack.push(v))
+ ++push_error_cnt;
+ }
+
+ while (stack.pop(v)) {
+ pop_sum += v.nNo;
+ }
+
+ if (push_error_cnt) {
+ std::cout << "Sequential stack push error count: " << push_error_cnt
+ << "\n";
+ }
+ size_t supposed_sum =
+ (m_nStartItem + m_nEndItem - 1) * (m_nEndItem - m_nStartItem) / 2;
+ if (pop_sum != supposed_sum) {
+ std::cout << "Sequential stack pop sum: " << pop_sum
+ << " != " << supposed_sum << "\n";
+ }
+ }
+};
+
+CDSSTRESS_SequentialTreiberStack(sequential_stack)
+ CDSSTRESS_SequentialEliminationStack(sequential_stack)
+
+} // namespace