From 59cb651402874a22500cab3ec586565b48f76059 Mon Sep 17 00:00:00 2001 From: Peizhao Ou Date: Fri, 15 Dec 2017 14:03:28 -0800 Subject: [PATCH] Adds a few single-threaded test cases for queue, stack, and set --- test/stress/CMakeLists.txt | 1 + test/stress/misc/common.h | 11 +- test/stress/sequential/CMakeLists.txt | 26 + .../sequential/sequential-set/CMakeLists.txt | 21 + .../sequential-set/del3/CMakeLists.txt | 22 + .../sequential-set/del3/set_del3.cpp | 155 +++ .../sequential/sequential-set/del3/set_del3.h | 868 +++++++++++++++++ .../sequential-set/del3/set_del3_cuckoo.cpp | 38 + .../del3/set_del3_ellentree.cpp | 38 + .../del3/set_del3_feldman_hashset.cpp | 50 + .../sequential-set/del3/set_del3_michael.cpp | 39 + .../sequential-set/del3/set_del3_skip.cpp | 38 + .../sequential-set/del3/set_del3_split.cpp | 40 + .../sequential-set/delodd/CMakeLists.txt | 22 + .../sequential-set/delodd/set_delodd.cpp | 131 +++ .../sequential-set/delodd/set_delodd.h | 921 ++++++++++++++++++ .../delodd/set_delodd_cuckoo.cpp | 38 + .../delodd/set_delodd_ellentree.cpp | 38 + .../delodd/set_delodd_feldman_hashset.cpp | 50 + .../delodd/set_delodd_michael.cpp | 39 + .../sequential-set/delodd/set_delodd_skip.cpp | 38 + .../delodd/set_delodd_split.cpp | 40 + .../sequential-set/insdel_find/CMakeLists.txt | 56 ++ .../insdel_find/set_insdelfind.cpp | 136 +++ .../insdel_find/set_insdelfind.h | 233 +++++ .../insdel_find/set_insdelfind_cuckoo.cpp | 38 + .../set_insdelfind_ellentree_hp.cpp | 38 + .../set_insdelfind_ellentree_rcu.cpp | 38 + .../set_insdelfind_feldman_hashset_hp.cpp | 38 + .../set_insdelfind_feldman_hashset_rcu.cpp | 38 + .../insdel_find/set_insdelfind_michael_hp.cpp | 39 + .../set_insdelfind_michael_rcu.cpp | 38 + .../insdel_find/set_insdelfind_skip_hp.cpp | 38 + .../insdel_find/set_insdelfind_skip_rcu.cpp | 38 + .../insdel_find/set_insdelfind_split_hp.cpp | 39 + .../insdel_find/set_insdelfind_split_rcu.cpp | 38 + .../insdel_find/set_insdelfind_std.cpp | 37 + .../insdel_find/set_insdelfind_striped.cpp | 39 + .../sequential-set/insdel_func/CMakeLists.txt | 23 + .../insdel_func/set_insdel_func.cpp | 122 +++ .../insdel_func/set_insdel_func.h | 564 +++++++++++ .../insdel_func/set_insdel_func_cuckoo.cpp | 38 + .../insdel_func/set_insdel_func_ellentree.cpp | 38 + .../set_insdel_func_feldman_hashset.cpp | 38 + .../insdel_func/set_insdel_func_michael.cpp | 39 + .../insdel_func/set_insdel_func_skip.cpp | 38 + .../insdel_func/set_insdel_func_split.cpp | 39 + .../insdel_func/set_insdel_func_striped.cpp | 39 + .../insdel_string/CMakeLists.txt | 24 + .../insdel_string/set_insdel_string.cpp | 128 +++ .../insdel_string/set_insdel_string.h | 521 ++++++++++ .../set_insdel_string_cuckoo.cpp | 38 + .../set_insdel_string_ellentree.cpp | 38 + .../set_insdel_string_feldman_hashset.cpp | 39 + .../set_insdel_string_michael.cpp | 39 + .../insdel_string/set_insdel_string_skip.cpp | 38 + .../insdel_string/set_insdel_string_split.cpp | 39 + .../insdel_string/set_insdel_string_std.cpp | 37 + .../set_insdel_string_striped.cpp | 39 + .../sequential-set/iter_erase/CMakeLists.txt | 19 + .../iter_erase/set_iter_erase.cpp | 116 +++ .../iter_erase/set_iter_erase.h | 885 +++++++++++++++++ .../set_iter_erase_feldman_hashset.cpp | 64 ++ .../iter_erase/set_iter_erase_michael.cpp | 39 + .../iter_erase/set_iter_erase_split.cpp | 38 + .../sequential-set/iteration/CMakeLists.txt | 18 + .../iteration/set_iteration.cpp | 126 +++ .../sequential-set/iteration/set_iteration.h | 681 +++++++++++++ .../set_iteration_feldman_hashset.cpp | 39 + .../iteration/set_iteration_michael.cpp | 38 + .../iteration/set_iteration_split.cpp | 38 + .../sequential/sequential-set/set_type.h | 325 ++++++ .../sequential-set/set_type_cuckoo.h | 244 +++++ .../sequential-set/set_type_ellen_bintree.h | 347 +++++++ .../sequential-set/set_type_feldman_hashset.h | 460 +++++++++ .../sequential-set/set_type_iterable_list.h | 99 ++ .../sequential-set/set_type_lazy_list.h | 137 +++ .../sequential-set/set_type_michael.h | 329 +++++++ .../sequential-set/set_type_michael_list.h | 135 +++ .../sequential-set/set_type_skip_list.h | 437 +++++++++ .../sequential-set/set_type_split_list.h | 697 +++++++++++++ .../sequential/sequential-set/set_type_std.h | 263 +++++ .../sequential-set/set_type_striped.h | 644 ++++++++++++ .../sequential_freelist_put_get.cpp | 187 ++++ .../sequential_freelist_put_get_single.cpp | 165 ++++ test/stress/sequential/sequential_queue.cpp | 301 ++++++ test/stress/sequential/sequential_stack.cpp | 115 +++ 87 files changed, 12527 insertions(+), 2 deletions(-) create mode 100644 test/stress/sequential/CMakeLists.txt create mode 100644 test/stress/sequential/sequential-set/CMakeLists.txt create mode 100644 test/stress/sequential/sequential-set/del3/CMakeLists.txt create mode 100644 test/stress/sequential/sequential-set/del3/set_del3.cpp create mode 100644 test/stress/sequential/sequential-set/del3/set_del3.h create mode 100644 test/stress/sequential/sequential-set/del3/set_del3_cuckoo.cpp create mode 100644 test/stress/sequential/sequential-set/del3/set_del3_ellentree.cpp create mode 100644 test/stress/sequential/sequential-set/del3/set_del3_feldman_hashset.cpp create mode 100644 test/stress/sequential/sequential-set/del3/set_del3_michael.cpp create mode 100644 test/stress/sequential/sequential-set/del3/set_del3_skip.cpp create mode 100644 test/stress/sequential/sequential-set/del3/set_del3_split.cpp create mode 100644 test/stress/sequential/sequential-set/delodd/CMakeLists.txt create mode 100644 test/stress/sequential/sequential-set/delodd/set_delodd.cpp create mode 100644 test/stress/sequential/sequential-set/delodd/set_delodd.h create mode 100644 test/stress/sequential/sequential-set/delodd/set_delodd_cuckoo.cpp create mode 100644 test/stress/sequential/sequential-set/delodd/set_delodd_ellentree.cpp create mode 100644 test/stress/sequential/sequential-set/delodd/set_delodd_feldman_hashset.cpp create mode 100644 test/stress/sequential/sequential-set/delodd/set_delodd_michael.cpp create mode 100644 test/stress/sequential/sequential-set/delodd/set_delodd_skip.cpp create mode 100644 test/stress/sequential/sequential-set/delodd/set_delodd_split.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_find/CMakeLists.txt create mode 100644 test/stress/sequential/sequential-set/insdel_find/set_insdelfind.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_find/set_insdelfind.h create mode 100644 test/stress/sequential/sequential-set/insdel_find/set_insdelfind_cuckoo.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_find/set_insdelfind_ellentree_hp.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_find/set_insdelfind_ellentree_rcu.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_find/set_insdelfind_feldman_hashset_hp.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_find/set_insdelfind_feldman_hashset_rcu.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_find/set_insdelfind_michael_hp.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_find/set_insdelfind_michael_rcu.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_find/set_insdelfind_skip_hp.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_find/set_insdelfind_skip_rcu.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_find/set_insdelfind_split_hp.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_find/set_insdelfind_split_rcu.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_find/set_insdelfind_std.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_find/set_insdelfind_striped.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_func/CMakeLists.txt create mode 100644 test/stress/sequential/sequential-set/insdel_func/set_insdel_func.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_func/set_insdel_func.h create mode 100644 test/stress/sequential/sequential-set/insdel_func/set_insdel_func_cuckoo.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_func/set_insdel_func_ellentree.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_func/set_insdel_func_feldman_hashset.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_func/set_insdel_func_michael.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_func/set_insdel_func_skip.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_func/set_insdel_func_split.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_func/set_insdel_func_striped.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_string/CMakeLists.txt create mode 100644 test/stress/sequential/sequential-set/insdel_string/set_insdel_string.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_string/set_insdel_string.h create mode 100644 test/stress/sequential/sequential-set/insdel_string/set_insdel_string_cuckoo.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_string/set_insdel_string_ellentree.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_string/set_insdel_string_feldman_hashset.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_string/set_insdel_string_michael.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_string/set_insdel_string_skip.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_string/set_insdel_string_split.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_string/set_insdel_string_std.cpp create mode 100644 test/stress/sequential/sequential-set/insdel_string/set_insdel_string_striped.cpp create mode 100644 test/stress/sequential/sequential-set/iter_erase/CMakeLists.txt create mode 100644 test/stress/sequential/sequential-set/iter_erase/set_iter_erase.cpp create mode 100644 test/stress/sequential/sequential-set/iter_erase/set_iter_erase.h create mode 100644 test/stress/sequential/sequential-set/iter_erase/set_iter_erase_feldman_hashset.cpp create mode 100644 test/stress/sequential/sequential-set/iter_erase/set_iter_erase_michael.cpp create mode 100644 test/stress/sequential/sequential-set/iter_erase/set_iter_erase_split.cpp create mode 100644 test/stress/sequential/sequential-set/iteration/CMakeLists.txt create mode 100644 test/stress/sequential/sequential-set/iteration/set_iteration.cpp create mode 100644 test/stress/sequential/sequential-set/iteration/set_iteration.h create mode 100644 test/stress/sequential/sequential-set/iteration/set_iteration_feldman_hashset.cpp create mode 100644 test/stress/sequential/sequential-set/iteration/set_iteration_michael.cpp create mode 100644 test/stress/sequential/sequential-set/iteration/set_iteration_split.cpp create mode 100644 test/stress/sequential/sequential-set/set_type.h create mode 100644 test/stress/sequential/sequential-set/set_type_cuckoo.h create mode 100644 test/stress/sequential/sequential-set/set_type_ellen_bintree.h create mode 100644 test/stress/sequential/sequential-set/set_type_feldman_hashset.h create mode 100644 test/stress/sequential/sequential-set/set_type_iterable_list.h create mode 100644 test/stress/sequential/sequential-set/set_type_lazy_list.h create mode 100644 test/stress/sequential/sequential-set/set_type_michael.h create mode 100644 test/stress/sequential/sequential-set/set_type_michael_list.h create mode 100644 test/stress/sequential/sequential-set/set_type_skip_list.h create mode 100644 test/stress/sequential/sequential-set/set_type_split_list.h create mode 100644 test/stress/sequential/sequential-set/set_type_std.h create mode 100644 test/stress/sequential/sequential-set/set_type_striped.h create mode 100644 test/stress/sequential/sequential_freelist_put_get.cpp create mode 100644 test/stress/sequential/sequential_freelist_put_get_single.cpp create mode 100644 test/stress/sequential/sequential_queue.cpp create mode 100644 test/stress/sequential/sequential_stack.cpp diff --git a/test/stress/CMakeLists.txt b/test/stress/CMakeLists.txt index b7336370..99d5dc18 100644 --- a/test/stress/CMakeLists.txt +++ b/test/stress/CMakeLists.txt @@ -21,6 +21,7 @@ include_directories( ${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) diff --git a/test/stress/misc/common.h b/test/stress/misc/common.h index 09878f6d..e297f166 100644 --- a/test/stress/misc/common.h +++ b/test/stress/misc/common.h @@ -1,5 +1,5 @@ -#ifndef _COMMON_H -#define _COMMON_H +#ifndef _CDS_STRESS_TEST_COMMON_H +#define _CDS_STRESS_TEST_COMMON_H #include @@ -7,4 +7,11 @@ typedef unsigned long long ullong; #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 diff --git a/test/stress/sequential/CMakeLists.txt b/test/stress/sequential/CMakeLists.txt new file mode 100644 index 00000000..3d090780 --- /dev/null +++ b/test/stress/sequential/CMakeLists.txt @@ -0,0 +1,26 @@ +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 +) diff --git a/test/stress/sequential/sequential-set/CMakeLists.txt b/test/stress/sequential/sequential-set/CMakeLists.txt new file mode 100644 index 00000000..b3ac996e --- /dev/null +++ b/test/stress/sequential/sequential-set/CMakeLists.txt @@ -0,0 +1,21 @@ + +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 +) diff --git a/test/stress/sequential/sequential-set/del3/CMakeLists.txt b/test/stress/sequential/sequential-set/del3/CMakeLists.txt new file mode 100644 index 00000000..c27c42b8 --- /dev/null +++ b/test/stress/sequential/sequential-set/del3/CMakeLists.txt @@ -0,0 +1,22 @@ +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}) diff --git a/test/stress/sequential/sequential-set/del3/set_del3.cpp b/test/stress/sequential/sequential-set/del3/set_del3.cpp new file mode 100644 index 00000000..4376fde7 --- /dev/null +++ b/test/stress/sequential/sequential-set/del3/set_del3.cpp @@ -0,0 +1,155 @@ +/* + 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 + +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 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 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 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 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 diff --git a/test/stress/sequential/sequential-set/del3/set_del3.h b/test/stress/sequential/sequential-set/del3/set_del3.h new file mode 100644 index 00000000..8a89c962 --- /dev/null +++ b/test/stress/sequential/sequential-set/del3/set_del3.h @@ -0,0 +1,868 @@ +/* + 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 +#include + +namespace set { + + struct key_thread + { + uint32_t nKey; + uint16_t nThread; + + key_thread( size_t key, size_t threadNo ) + : nKey( static_cast(key)) + , nThread( static_cast(threadNo)) + {} + + key_thread() + : nKey() + , nThread() + {} + }; + + static_assert(sizeof( key_thread ) % 8 == 0, "Key type size mismatch"); + + typedef set_type_base::key_val key_value_pair; + + template <> + struct cmp { + 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 + { + 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 + { + typedef size_t result_type; + typedef set::key_thread argument_type; + + size_t operator()( set::key_thread const& k ) const + { + return std::hash()(k.nKey); + } + + size_t operator()( size_t k ) const + { + return std::hash()(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 m_arrData; + + static void SetUpTestCase(); + static void TearDownTestCase(); + + template + static void prepare_array( std::vector& 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 Inserter: public cds_test::thread + { + typedef cds_test::thread base_class; + Set& m_Set; + + struct update_functor + { + template + 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 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 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 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 + struct eraser { + static bool erase( SetType& s, size_t key, size_t /*thread*/) + { + return s.erase_with( key, key_less()); + } + }; + + template + struct eraser { + 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 + class Extractor: public cds_test::thread + { + typedef cds_test::thread base_class; + Set& m_Set; + + std::vector 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 + class Extractor< cds::urcu::gc, Set >: public cds_test::thread + { + typedef cds_test::thread base_class; + Set& m_Set; + std::vector 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(); + 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 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 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 + void do_test_with( Set& testSet ) + { + typedef Inserter insert_thread; + typedef Deleter delete_thread; + typedef Observer 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(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(thr); + nDeleteSuccess += deleter.m_nDeleteSuccess; + nDeleteFailed += deleter.m_nDeleteFailed; + } + break; + case find_thread: + { + observer_thread& observer = static_cast( 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 + void do_test_extract_with(Set &testSet, size_t pass_count) { + typedef Inserter insert_thread; + typedef Deleter delete_thread; + typedef Extractor extract_thread; + typedef Observer 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 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 time_elapsed; + // std::chrono::duration time_diff; + // std::chrono::time_point + // time_start; + // std::chrono::time_point + // 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 + 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 + 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 + 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 + void run_feldman(); + }; + + class Set_Del3_LF: public Set_Del3 + , public ::testing::WithParamInterface + { + public: + template + void run_test() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Set_Del3::run_test(); + } + + template + 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(pass_count); + } + + static std::vector get_load_factors(); + }; + +} // namespace set diff --git a/test/stress/sequential/sequential-set/del3/set_del3_cuckoo.cpp b/test/stress/sequential/sequential-set/del3/set_del3_cuckoo.cpp new file mode 100644 index 00000000..4e9fb831 --- /dev/null +++ b/test/stress/sequential/sequential-set/del3/set_del3_cuckoo.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/del3/set_del3_ellentree.cpp b/test/stress/sequential/sequential-set/del3/set_del3_ellentree.cpp new file mode 100644 index 00000000..53e4f66d --- /dev/null +++ b/test/stress/sequential/sequential-set/del3/set_del3_ellentree.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/del3/set_del3_feldman_hashset.cpp b/test/stress/sequential/sequential-set/del3/set_del3_feldman_hashset.cpp new file mode 100644 index 00000000..1b05171e --- /dev/null +++ b/test/stress/sequential/sequential-set/del3/set_del3_feldman_hashset.cpp @@ -0,0 +1,50 @@ +/* + 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 + 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(s_nFeldmanPassCount); + } + + CDSSTRESS_FeldmanHashSet_fixed( Set_Del3, run_feldman, key_thread, size_t ) + +} // namespace set diff --git a/test/stress/sequential/sequential-set/del3/set_del3_michael.cpp b/test/stress/sequential/sequential-set/del3/set_del3_michael.cpp new file mode 100644 index 00000000..d7e64a02 --- /dev/null +++ b/test/stress/sequential/sequential-set/del3/set_del3_michael.cpp @@ -0,0 +1,39 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/del3/set_del3_skip.cpp b/test/stress/sequential/sequential-set/del3/set_del3_skip.cpp new file mode 100644 index 00000000..9767eebc --- /dev/null +++ b/test/stress/sequential/sequential-set/del3/set_del3_skip.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/del3/set_del3_split.cpp b/test/stress/sequential/sequential-set/del3/set_del3_split.cpp new file mode 100644 index 00000000..73e68330 --- /dev/null +++ b/test/stress/sequential/sequential-set/del3/set_del3_split.cpp @@ -0,0 +1,40 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/delodd/CMakeLists.txt b/test/stress/sequential/sequential-set/delodd/CMakeLists.txt new file mode 100644 index 00000000..06259bb9 --- /dev/null +++ b/test/stress/sequential/sequential-set/delodd/CMakeLists.txt @@ -0,0 +1,22 @@ +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}) diff --git a/test/stress/sequential/sequential-set/delodd/set_delodd.cpp b/test/stress/sequential/sequential-set/delodd/set_delodd.cpp new file mode 100644 index 00000000..f454f127 --- /dev/null +++ b/test/stress/sequential/sequential-set/delodd/set_delodd.cpp @@ -0,0 +1,131 @@ +/* + 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 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 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 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 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 diff --git a/test/stress/sequential/sequential-set/delodd/set_delodd.h b/test/stress/sequential/sequential-set/delodd/set_delodd.h new file mode 100644 index 00000000..45302cd9 --- /dev/null +++ b/test/stress/sequential/sequential-set/delodd/set_delodd.h @@ -0,0 +1,921 @@ +/* + 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 + +namespace set { + + struct key_thread + { + uint32_t nKey; + uint16_t nThread; + + key_thread( size_t key, size_t threadNo ) + : nKey( static_cast(key)) + , nThread( static_cast(threadNo)) + {} + + key_thread() + : nKey() + , nThread() + {} + }; + + static_assert(sizeof( key_thread ) % 8 == 0, "Key type size mismatch"); + + typedef set_type_base::key_val key_value_pair; + + template <> + struct cmp { + 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 + { + 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 + { + typedef size_t result_type; + typedef set::key_thread argument_type; + + size_t operator()( set::key_thread const& k ) const + { + return std::hash()(k.nKey); + } + + size_t operator()( size_t k ) const + { + return std::hash()(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 m_arrData; + + static void SetUpTestCase(); + static void TearDownTestCase(); + + template + static void prepare_array( std::vector& 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 m_nInsThreadCount; + + enum { + inserter_thread, + deleter_thread, + extractor_thread, + find_thread + }; + + + // Inserts keys from [0..N) + template + class Inserter: public cds_test::thread + { + typedef cds_test::thread base_class; + Set& m_Set; + + struct update_functor + { + template + 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 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(); + + 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 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 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 + struct eraser { + static bool erase( SetType& s, size_t key, size_t /*thread*/) + { + return s.erase_with( key, key_less()); + } + }; + + template + struct eraser { + 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(); + + 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 + class Extractor: public cds_test::thread + { + typedef cds_test::thread base_class; + Set& m_Set; + + std::vector 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(); + 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 + class Extractor< cds::urcu::gc, Set >: public cds_test::thread + { + typedef cds_test::thread base_class; + Set& m_Set; + std::vector 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(); + 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 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(); + std::vector 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 + void do_test_with( Set& testSet ) + { + typedef Inserter insert_thread; + typedef Deleter delete_thread; + typedef Observer 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(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(thr); + nDeleteSuccess += deleter.m_nDeleteSuccess; + nDeleteFailed += deleter.m_nDeleteFailed; + } + break; + case find_thread: + { + observer_thread& observer = static_cast( 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 + void do_test_extract_with( Set& testSet ) + { + typedef Inserter insert_thread; + typedef Deleter delete_thread; + typedef Extractor< typename Set::gc, Set > extract_thread; + typedef Observer 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( 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(thr); + nDeleteSuccess += deleter.m_nDeleteSuccess; + nDeleteFailed += deleter.m_nDeleteFailed; + } + break; + case extractor_thread: + { + extract_thread& extractor = static_cast(thr); + nExtractSuccess += extractor.m_nExtractSuccess; + nExtractFailed += extractor.m_nExtractFailed; + } + break; + case find_thread: + { + observer_thread& observer = static_cast( 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 + 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 + 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 + 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 + void run_feldman(); + }; + + class Set_DelOdd_LF: public Set_DelOdd + , public ::testing::WithParamInterface + { + public: + template + void run_test() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Set_DelOdd::run_test(); + } + + template + void run_test_extract() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Set_DelOdd::run_test_extract(); + } + + static std::vector get_load_factors(); + }; + +} // namespace set diff --git a/test/stress/sequential/sequential-set/delodd/set_delodd_cuckoo.cpp b/test/stress/sequential/sequential-set/delodd/set_delodd_cuckoo.cpp new file mode 100644 index 00000000..ceefac62 --- /dev/null +++ b/test/stress/sequential/sequential-set/delodd/set_delodd_cuckoo.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/delodd/set_delodd_ellentree.cpp b/test/stress/sequential/sequential-set/delodd/set_delodd_ellentree.cpp new file mode 100644 index 00000000..49dbfff9 --- /dev/null +++ b/test/stress/sequential/sequential-set/delodd/set_delodd_ellentree.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/delodd/set_delodd_feldman_hashset.cpp b/test/stress/sequential/sequential-set/delodd/set_delodd_feldman_hashset.cpp new file mode 100644 index 00000000..41a2dd4e --- /dev/null +++ b/test/stress/sequential/sequential-set/delodd/set_delodd_feldman_hashset.cpp @@ -0,0 +1,50 @@ +/* + 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 + 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(); + } + + CDSSTRESS_FeldmanHashSet_fixed( Set_DelOdd, run_feldman, key_thread, size_t ) + +} // namespace set diff --git a/test/stress/sequential/sequential-set/delodd/set_delodd_michael.cpp b/test/stress/sequential/sequential-set/delodd/set_delodd_michael.cpp new file mode 100644 index 00000000..f41c0157 --- /dev/null +++ b/test/stress/sequential/sequential-set/delodd/set_delodd_michael.cpp @@ -0,0 +1,39 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/delodd/set_delodd_skip.cpp b/test/stress/sequential/sequential-set/delodd/set_delodd_skip.cpp new file mode 100644 index 00000000..f5014ef3 --- /dev/null +++ b/test/stress/sequential/sequential-set/delodd/set_delodd_skip.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/delodd/set_delodd_split.cpp b/test/stress/sequential/sequential-set/delodd/set_delodd_split.cpp new file mode 100644 index 00000000..ce08ba4e --- /dev/null +++ b/test/stress/sequential/sequential-set/delodd/set_delodd_split.cpp @@ -0,0 +1,40 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_find/CMakeLists.txt b/test/stress/sequential/sequential-set/insdel_find/CMakeLists.txt new file mode 100644 index 00000000..eb3ef457 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_find/CMakeLists.txt @@ -0,0 +1,56 @@ +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 +) + diff --git a/test/stress/sequential/sequential-set/insdel_find/set_insdelfind.cpp b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind.cpp new file mode 100644 index 00000000..afcff02c --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind.cpp @@ -0,0 +1,136 @@ +/* + 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 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 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 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 diff --git a/test/stress/sequential/sequential-set/insdel_find/set_insdelfind.h b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind.h new file mode 100644 index 00000000..c28ab90a --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind.h @@ -0,0 +1,233 @@ +/* + 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 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(); + + 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 + void do_test( Set& testSet ) + { + typedef Worker 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( 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(duration).count() > 0 ); + size_t nTotalOps = nInsertSuccess + nInsertFailed + nDeleteSuccess + nDeleteFailed + nFindSuccess + nFindFailed; + propout() << std::make_pair( "avg_speed", nTotalOps / std::chrono::duration_cast(duration).count()); + } + + + testSet.clear(); + EXPECT_TRUE( testSet.empty()) << "set size=" << testSet.size(); + + additional_check( testSet ); + print_stat( propout(), testSet ); + additional_cleanup( testSet ); + } + + template + void run_test() + { + Set s( *this ); + do_test( s ); + } + }; + + class Set_InsDelFind_LF: public Set_InsDelFind + , public ::testing::WithParamInterface + { + public: + template + void run_test() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Set_InsDelFind::run_test(); + } + + static std::vector get_load_factors(); + }; + +} // namespace set diff --git a/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_cuckoo.cpp b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_cuckoo.cpp new file mode 100644 index 00000000..fc00355f --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_cuckoo.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_ellentree_hp.cpp b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_ellentree_hp.cpp new file mode 100644 index 00000000..adfd5920 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_ellentree_hp.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_ellentree_rcu.cpp b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_ellentree_rcu.cpp new file mode 100644 index 00000000..11906ea5 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_ellentree_rcu.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_feldman_hashset_hp.cpp b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_feldman_hashset_hp.cpp new file mode 100644 index 00000000..7e6a68e3 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_feldman_hashset_hp.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_feldman_hashset_rcu.cpp b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_feldman_hashset_rcu.cpp new file mode 100644 index 00000000..423cfdde --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_feldman_hashset_rcu.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_michael_hp.cpp b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_michael_hp.cpp new file mode 100644 index 00000000..d43ae5d1 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_michael_hp.cpp @@ -0,0 +1,39 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_michael_rcu.cpp b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_michael_rcu.cpp new file mode 100644 index 00000000..0006b831 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_michael_rcu.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_skip_hp.cpp b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_skip_hp.cpp new file mode 100644 index 00000000..539d0d99 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_skip_hp.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_skip_rcu.cpp b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_skip_rcu.cpp new file mode 100644 index 00000000..9ecaceb4 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_skip_rcu.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_split_hp.cpp b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_split_hp.cpp new file mode 100644 index 00000000..35a3ca6b --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_split_hp.cpp @@ -0,0 +1,39 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_split_rcu.cpp b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_split_rcu.cpp new file mode 100644 index 00000000..d0f98b7d --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_split_rcu.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_std.cpp b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_std.cpp new file mode 100644 index 00000000..75d6fa52 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_std.cpp @@ -0,0 +1,37 @@ +/* + 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 + diff --git a/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_striped.cpp b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_striped.cpp new file mode 100644 index 00000000..7f89f64a --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_find/set_insdelfind_striped.cpp @@ -0,0 +1,39 @@ +/* + 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 + diff --git a/test/stress/sequential/sequential-set/insdel_func/CMakeLists.txt b/test/stress/sequential/sequential-set/insdel_func/CMakeLists.txt new file mode 100644 index 00000000..555b7a10 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_func/CMakeLists.txt @@ -0,0 +1,23 @@ +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}) diff --git a/test/stress/sequential/sequential-set/insdel_func/set_insdel_func.cpp b/test/stress/sequential/sequential-set/insdel_func/set_insdel_func.cpp new file mode 100644 index 00000000..9ce8d9a5 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_func/set_insdel_func.cpp @@ -0,0 +1,122 @@ +/* + 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 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 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 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 diff --git a/test/stress/sequential/sequential-set/insdel_func/set_insdel_func.h b/test/stress/sequential/sequential-set/insdel_func/set_insdel_func.h new file mode 100644 index 00000000..d7b4439c --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_func/set_insdel_func.h @@ -0,0 +1,564 @@ +/* + 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 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 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(); + + 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 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 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(); + 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 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 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 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(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(); + 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 + void run_test( Set& testSet ) + { + typedef Inserter InserterThread; + typedef Deleter DeleterThread; + typedef Updater 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( thr ); + nInsertSuccess += inserter.m_nInsertSuccess; + nInsertFailed += inserter.m_nInsertFailed; + nTestFunctorRef += inserter.m_nTestFunctorRef; + } + break; + case update_thread: + { + UpdaterThread& updater = static_cast(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(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 + void run_test() + { + Set s( *this ); + run_test( s ); + } + + template + 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 + { + public: + template + void run_test() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Set_InsDel_func::run_test(); + } + + template + void run_test2() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Set_InsDel_func::run_test2(); + } + + static std::vector get_load_factors(); + }; + +} // namespace set diff --git a/test/stress/sequential/sequential-set/insdel_func/set_insdel_func_cuckoo.cpp b/test/stress/sequential/sequential-set/insdel_func/set_insdel_func_cuckoo.cpp new file mode 100644 index 00000000..865ae347 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_func/set_insdel_func_cuckoo.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_func/set_insdel_func_ellentree.cpp b/test/stress/sequential/sequential-set/insdel_func/set_insdel_func_ellentree.cpp new file mode 100644 index 00000000..42235d53 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_func/set_insdel_func_ellentree.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_func/set_insdel_func_feldman_hashset.cpp b/test/stress/sequential/sequential-set/insdel_func/set_insdel_func_feldman_hashset.cpp new file mode 100644 index 00000000..b918eb2b --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_func/set_insdel_func_feldman_hashset.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_func/set_insdel_func_michael.cpp b/test/stress/sequential/sequential-set/insdel_func/set_insdel_func_michael.cpp new file mode 100644 index 00000000..bef62825 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_func/set_insdel_func_michael.cpp @@ -0,0 +1,39 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_func/set_insdel_func_skip.cpp b/test/stress/sequential/sequential-set/insdel_func/set_insdel_func_skip.cpp new file mode 100644 index 00000000..10272191 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_func/set_insdel_func_skip.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_func/set_insdel_func_split.cpp b/test/stress/sequential/sequential-set/insdel_func/set_insdel_func_split.cpp new file mode 100644 index 00000000..a752c4d2 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_func/set_insdel_func_split.cpp @@ -0,0 +1,39 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_func/set_insdel_func_striped.cpp b/test/stress/sequential/sequential-set/insdel_func/set_insdel_func_striped.cpp new file mode 100644 index 00000000..9fdbdf63 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_func/set_insdel_func_striped.cpp @@ -0,0 +1,39 @@ +/* + 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 + diff --git a/test/stress/sequential/sequential-set/insdel_string/CMakeLists.txt b/test/stress/sequential/sequential-set/insdel_string/CMakeLists.txt new file mode 100644 index 00000000..4b780b46 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_string/CMakeLists.txt @@ -0,0 +1,24 @@ +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}) diff --git a/test/stress/sequential/sequential-set/insdel_string/set_insdel_string.cpp b/test/stress/sequential/sequential-set/insdel_string/set_insdel_string.cpp new file mode 100644 index 00000000..40f066e4 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_string/set_insdel_string.cpp @@ -0,0 +1,128 @@ +/* + 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 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 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 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 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 diff --git a/test/stress/sequential/sequential-set/insdel_string/set_insdel_string.h b/test/stress/sequential/sequential-set/insdel_string/set_insdel_string.h new file mode 100644 index 00000000..ad1a1b63 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_string/set_insdel_string.h @@ -0,0 +1,521 @@ +/* + 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 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 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(); + 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 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(); + 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 + 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(); + 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 + class Extractor, 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(); + 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 + void do_test( Set& testSet ) + { + typedef Inserter InserterThread; + typedef Deleter 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( thr ); + nInsertSuccess += inserter.m_nInsertSuccess; + nInsertFailed += inserter.m_nInsertFailed; + } + break; + case delete_thread: + { + DeleterThread& deleter = static_cast(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 + void do_test_extract( Set& testSet ) + { + typedef Inserter InserterThread; + typedef Deleter DeleterThread; + typedef Extractor 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(thr); + nInsertSuccess += inserter.m_nInsertSuccess; + nInsertFailed += inserter.m_nInsertFailed; + } + break; + case delete_thread: + { + DeleterThread& deleter = static_cast(thr); + nDeleteSuccess += deleter.m_nDeleteSuccess; + nDeleteFailed += deleter.m_nDeleteFailed; + } + break; + case extract_thread: + { + ExtractThread& extractor = static_cast(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 + void run_test() + { + ASSERT_TRUE( m_arrString.size() > 0 ); + + Set s( *this ); + do_test( s ); + } + + template + 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 + { + public: + template + void run_test() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Set_InsDel_string::run_test(); + } + + template + void run_test_extract() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Set_InsDel_string::run_test_extract(); + } + + static std::vector get_load_factors(); + }; + +} // namespace set diff --git a/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_cuckoo.cpp b/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_cuckoo.cpp new file mode 100644 index 00000000..83892c3c --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_cuckoo.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_ellentree.cpp b/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_ellentree.cpp new file mode 100644 index 00000000..13c9e043 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_ellentree.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_feldman_hashset.cpp b/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_feldman_hashset.cpp new file mode 100644 index 00000000..94f1d6d5 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_feldman_hashset.cpp @@ -0,0 +1,39 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_michael.cpp b/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_michael.cpp new file mode 100644 index 00000000..d0c181b0 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_michael.cpp @@ -0,0 +1,39 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_skip.cpp b/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_skip.cpp new file mode 100644 index 00000000..1b6a7241 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_skip.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_split.cpp b/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_split.cpp new file mode 100644 index 00000000..8d9ff713 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_split.cpp @@ -0,0 +1,39 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_std.cpp b/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_std.cpp new file mode 100644 index 00000000..b81f90b5 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_std.cpp @@ -0,0 +1,37 @@ +/* + 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 + diff --git a/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_striped.cpp b/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_striped.cpp new file mode 100644 index 00000000..b1baa873 --- /dev/null +++ b/test/stress/sequential/sequential-set/insdel_string/set_insdel_string_striped.cpp @@ -0,0 +1,39 @@ +/* + 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 + diff --git a/test/stress/sequential/sequential-set/iter_erase/CMakeLists.txt b/test/stress/sequential/sequential-set/iter_erase/CMakeLists.txt new file mode 100644 index 00000000..0c683177 --- /dev/null +++ b/test/stress/sequential/sequential-set/iter_erase/CMakeLists.txt @@ -0,0 +1,19 @@ +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}) diff --git a/test/stress/sequential/sequential-set/iter_erase/set_iter_erase.cpp b/test/stress/sequential/sequential-set/iter_erase/set_iter_erase.cpp new file mode 100644 index 00000000..e52a4c89 --- /dev/null +++ b/test/stress/sequential/sequential-set/iter_erase/set_iter_erase.cpp @@ -0,0 +1,116 @@ +/* + 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 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 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 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 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 diff --git a/test/stress/sequential/sequential-set/iter_erase/set_iter_erase.h b/test/stress/sequential/sequential-set/iter_erase/set_iter_erase.h new file mode 100644 index 00000000..1615311d --- /dev/null +++ b/test/stress/sequential/sequential-set/iter_erase/set_iter_erase.h @@ -0,0 +1,885 @@ +/* + 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 + +namespace set { + + struct key_thread + { + uint32_t nKey; + uint16_t nThread; + + key_thread( size_t key, size_t threadNo ) + : nKey( static_cast(key)) + , nThread( static_cast(threadNo)) + {} + + key_thread() + : nKey() + , nThread() + {} + }; + + static_assert(sizeof( key_thread ) % 8 == 0, "Key type size mismatch"); + + typedef set_type_base::key_val key_value_pair; + + template <> + struct cmp { + 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 + { + 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 + { + typedef size_t result_type; + typedef set::key_thread argument_type; + + size_t operator()( set::key_thread const& k ) const + { + return std::hash()(k.nKey); + } + + size_t operator()( size_t k ) const + { + return std::hash()(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 m_arrData; + + static void SetUpTestCase(); + static void TearDownTestCase(); + + template + static void prepare_array( std::vector& 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 m_nInsThreadCount; + + enum { + inserter_thread, + deleter_thread, + extractor_thread, + find_thread + }; + + + // Inserts keys from [0..N) + template + class Inserter: public cds_test::thread + { + typedef cds_test::thread base_class; + Set& m_Set; + + struct update_functor + { + template + 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 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(); + + 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 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(); + + do { + auto itEnd = rSet.template get_end(); + for ( auto it = rSet.template get_begin(); 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 + class Extractor: public cds_test::thread + { + typedef cds_test::thread base_class; + Set& m_Set; + + std::vector 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(); + 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 + class Extractor< cds::urcu::gc, Set >: public cds_test::thread + { + typedef cds_test::thread base_class; + Set& m_Set; + std::vector 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(); + 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 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(); + std::vector 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 + void do_test_with( Set& testSet ) + { + typedef Inserter insert_thread; + typedef Deleter delete_thread; + typedef Observer 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(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(thr); + nDeleteSuccess += deleter.m_nDeleteSuccess; + nDeleteFailed += deleter.m_nDeleteFailed; + } + break; + case find_thread: + { + observer_thread& observer = static_cast( 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 + void do_test_extract_with( Set& testSet ) + { + typedef Inserter insert_thread; + typedef Deleter delete_thread; + typedef Extractor< typename Set::gc, Set > extract_thread; + typedef Observer 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( 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(thr); + nDeleteSuccess += deleter.m_nDeleteSuccess; + nDeleteFailed += deleter.m_nDeleteFailed; + } + break; + case extractor_thread: + { + extract_thread& extractor = static_cast(thr); + nExtractSuccess += extractor.m_nExtractSuccess; + nExtractFailed += extractor.m_nExtractFailed; + } + break; + case find_thread: + { + observer_thread& observer = static_cast( 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 + 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 + 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 + 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 + void run_feldman(); + }; + + class Set_Iter_Del3_reverse: public Set_Iter_Del3 + { + public: + template + void run_feldman(); + }; + + + class Set_Iter_Del3_LF: public Set_Iter_Del3 + , public ::testing::WithParamInterface + { + public: + template + void run_test() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Set_Iter_Del3::run_test(); + } + + template + void run_test_extract() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Set_Iter_Del3::run_test_extract(); + } + + static std::vector get_load_factors(); + }; + +} // namespace set diff --git a/test/stress/sequential/sequential-set/iter_erase/set_iter_erase_feldman_hashset.cpp b/test/stress/sequential/sequential-set/iter_erase/set_iter_erase_feldman_hashset.cpp new file mode 100644 index 00000000..5dfb1295 --- /dev/null +++ b/test/stress/sequential/sequential-set/iter_erase/set_iter_erase_feldman_hashset.cpp @@ -0,0 +1,64 @@ +/* + 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 + 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(); + } + + template + 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(); + } + + //TODO: add erase_at() to FeldmanHashSet + 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 diff --git a/test/stress/sequential/sequential-set/iter_erase/set_iter_erase_michael.cpp b/test/stress/sequential/sequential-set/iter_erase/set_iter_erase_michael.cpp new file mode 100644 index 00000000..3a69c963 --- /dev/null +++ b/test/stress/sequential/sequential-set/iter_erase/set_iter_erase_michael.cpp @@ -0,0 +1,39 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/iter_erase/set_iter_erase_split.cpp b/test/stress/sequential/sequential-set/iter_erase/set_iter_erase_split.cpp new file mode 100644 index 00000000..235a02cf --- /dev/null +++ b/test/stress/sequential/sequential-set/iter_erase/set_iter_erase_split.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/iteration/CMakeLists.txt b/test/stress/sequential/sequential-set/iteration/CMakeLists.txt new file mode 100644 index 00000000..0adcbd55 --- /dev/null +++ b/test/stress/sequential/sequential-set/iteration/CMakeLists.txt @@ -0,0 +1,18 @@ +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}) diff --git a/test/stress/sequential/sequential-set/iteration/set_iteration.cpp b/test/stress/sequential/sequential-set/iteration/set_iteration.cpp new file mode 100644 index 00000000..8012b263 --- /dev/null +++ b/test/stress/sequential/sequential-set/iteration/set_iteration.cpp @@ -0,0 +1,126 @@ +/* + 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 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 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 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 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 diff --git a/test/stress/sequential/sequential-set/iteration/set_iteration.h b/test/stress/sequential/sequential-set/iteration/set_iteration.h new file mode 100644 index 00000000..2be247d3 --- /dev/null +++ b/test/stress/sequential/sequential-set/iteration/set_iteration.h @@ -0,0 +1,681 @@ +/* + 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 + +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 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 m_nModifierCount; + + template + 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(); + 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 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(); + 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 + 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(); + 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 + class Extractor, 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(); + 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 + 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(); + 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()( it->key ); +#endif + ++m_nVisitCount; + } + } + } + }; + + template + class Iterator, 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(); + 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()(it->key); +#endif + ++m_nVisitCount; + } + } + } + }; + + protected: + template + void do_test( Set& testSet ) + { + typedef Inserter InserterThread; + typedef Deleter DeleterThread; + typedef Iterator 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( thr ); + nInsertSuccess += inserter.m_nInsertSuccess; + nInsertFailed += inserter.m_nInsertFailed; + } + break; + case delete_thread: + { + DeleterThread& deleter = static_cast(thr); + nDeleteSuccess += deleter.m_nDeleteSuccess; + nDeleteFailed += deleter.m_nDeleteFailed; + } + break; + case iterator_thread: + { + IteratorThread& iter = static_cast(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 + void do_test_extract( Set& testSet ) + { + typedef Inserter InserterThread; + typedef Deleter DeleterThread; + typedef Extractor ExtractThread; + typedef Iterator 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(thr); + nInsertSuccess += inserter.m_nInsertSuccess; + nInsertFailed += inserter.m_nInsertFailed; + } + break; + case delete_thread: + { + DeleterThread& deleter = static_cast(thr); + nDeleteSuccess += deleter.m_nDeleteSuccess; + nDeleteFailed += deleter.m_nDeleteFailed; + } + break; + case extract_thread: + { + ExtractThread& extractor = static_cast(thr); + nExtractSuccess += extractor.m_nDeleteSuccess; + nExtractFailed += extractor.m_nDeleteFailed; + } + break; + case iterator_thread: + { + IteratorThread& iter = static_cast(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 + void run_test() + { + ASSERT_TRUE( m_arrString.size() > 0 ); + + Set s( *this ); + do_test( s ); + } + + template + 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 + { + public: + template + void run_test() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Set_Iteration::run_test(); + } + + template + void run_test_extract() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Set_Iteration::run_test_extract(); + } + + static std::vector get_load_factors(); + }; + +} // namespace set diff --git a/test/stress/sequential/sequential-set/iteration/set_iteration_feldman_hashset.cpp b/test/stress/sequential/sequential-set/iteration/set_iteration_feldman_hashset.cpp new file mode 100644 index 00000000..3371dd9a --- /dev/null +++ b/test/stress/sequential/sequential-set/iteration/set_iteration_feldman_hashset.cpp @@ -0,0 +1,39 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/iteration/set_iteration_michael.cpp b/test/stress/sequential/sequential-set/iteration/set_iteration_michael.cpp new file mode 100644 index 00000000..f603e70b --- /dev/null +++ b/test/stress/sequential/sequential-set/iteration/set_iteration_michael.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/iteration/set_iteration_split.cpp b/test/stress/sequential/sequential-set/iteration/set_iteration_split.cpp new file mode 100644 index 00000000..d9b7b776 --- /dev/null +++ b/test/stress/sequential/sequential-set/iteration/set_iteration_split.cpp @@ -0,0 +1,38 @@ +/* + 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 diff --git a/test/stress/sequential/sequential-set/set_type.h b/test/stress/sequential/sequential-set/set_type.h new file mode 100644 index 00000000..14d365cc --- /dev/null +++ b/test/stress/sequential/sequential-set/set_type.h @@ -0,0 +1,325 @@ +/* + 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 +#include +#include +#include + +#include +#include + +#include + +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 + struct less; + + template + struct cmp + { + int operator ()(Key const& k1, Key const& k2) const + { + if ( less( k1, k2 )) + return -1; + return less( k2, k1 ) ? 1 : 0; + } + }; + + template + struct hash; + +#define CDSUNIT_INT_COMPARE(t) template <> struct cmp { 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 { 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 + { + 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 + { + bool operator ()( std::string const& k1, std::string const& k2 ) const + { + return cmp()( k1, k2 ) < 0; + } + bool operator ()( std::string const& k1, char const* k2 ) const + { + return cmp()( k1, k2 ) < 0; + } + bool operator ()( char const* k1, std::string const& k2 ) const + { + return cmp()( k1, k2 ) < 0; + } + }; + + template + struct hash + { + typedef size_t result_type; + typedef T argument_type; + + size_t operator()( T const& k ) const + { + return std::hash()(k.nKey); + } + + size_t operator()( size_t k ) const + { + return std::hash()(k); + } + }; + + template <> + struct hash + { + typedef size_t result_type; + typedef size_t argument_type; + + size_t operator()( size_t k ) const + { + return std::hash()(k); + } + }; + + template <> + struct hash + { + typedef size_t result_type; + typedef std::string argument_type; + + size_t operator()( std::string const& k ) const + { + return std::hash()(k); + } + }; + + // forward + template + struct set_type; + + template + 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 + explicit key_val( K const& k ): key(k) {} + + template + key_val( K const& k, T const& v ): key(k), val(v) {} + }; + + typedef set::hash key_hash; + typedef set::less key_less; + typedef set::cmp 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 + 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 + 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 + static inline void print_stat( cds_test::property_stream& o, Set const& s ) + { + o << s.statistics(); + } + + + //******************************************************* + // additional_check + //******************************************************* + + template + static inline void additional_check( Set& /*set*/ ) + {} + + template + static inline void additional_cleanup( Set& /*set*/ ) + {} + + //******************************************************* + // check_before_clear + //******************************************************* + + template + static inline void check_before_clear( Set& /*s*/ ) + {} + +} // namespace set + + +#endif // ifndef CDSUNIT_SET_TYPE_H diff --git a/test/stress/sequential/sequential-set/set_type_cuckoo.h b/test/stress/sequential/sequential-set/set_type_cuckoo.h new file mode 100644 index 00000000..9592b195 --- /dev/null +++ b/test/stress/sequential/sequential-set/set_type_cuckoo.h @@ -0,0 +1,244 @@ +/* + 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 +#include + +namespace set { + + template + class CuckooSet : public cc::CuckooSet< V, Traits > + { + public: + typedef cc::CuckooSet< V, Traits > cuckoo_base_class; + + public: + template + CuckooSet( Config const& cfg ) + : cuckoo_base_class( + cfg.s_nCuckooInitialSize, + static_cast( cfg.s_nCuckooProbesetSize ), + static_cast( cfg.s_nCuckooProbesetThreshold ) + ) + {} + + template + 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 + 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 + struct traits_CuckooStripedSet : public Traits + { + typedef cc::cuckoo::striping<> mutex_policy; + }; + template + 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> CuckooStripedSet_list_unord; + typedef CuckooSet< key_val, traits_CuckooRefinableSet> 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> CuckooStripedSet_list_unord_stat; + typedef CuckooSet< key_val, traits_CuckooRefinableSet> 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> CuckooStripedSet_list_unord_storehash; + typedef CuckooSet< key_val, traits_CuckooRefinableSet> 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> CuckooStripedSet_list_ord; + typedef CuckooSet< key_val, traits_CuckooRefinableSet> 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> CuckooStripedSet_list_ord_stat; + typedef CuckooSet< key_val, traits_CuckooRefinableSet> 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> CuckooStripedSet_list_ord_storehash; + typedef CuckooSet< key_val, traits_CuckooRefinableSet> 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> CuckooStripedSet_vector_unord; + typedef CuckooSet< key_val, traits_CuckooRefinableSet> 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> CuckooStripedSet_vector_unord_stat; + typedef CuckooSet< key_val, traits_CuckooRefinableSet> 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> CuckooStripedSet_vector_unord_storehash; + typedef CuckooSet< key_val, traits_CuckooRefinableSet> 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> CuckooStripedSet_vector_ord; + typedef CuckooSet< key_val, traits_CuckooRefinableSet> 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> CuckooStripedSet_vector_ord_stat; + typedef CuckooSet< key_val, traits_CuckooRefinableSet> 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> CuckooStripedSet_vector_ord_storehash; + typedef CuckooSet< key_val, traits_CuckooRefinableSet> CuckooRefinableSet_vector_ord_storehash; + + }; + + template + static inline void print_stat( cds_test::property_stream& o, cc::CuckooSet< T, Traits > const& s ) + { + o << s.statistics() << s.mutex_policy_statistics(); + } + + template + 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(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(); \ + } + +#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 diff --git a/test/stress/sequential/sequential-set/set_type_ellen_bintree.h b/test/stress/sequential/sequential-set/set_type_ellen_bintree.h new file mode 100644 index 00000000..fa5af50e --- /dev/null +++ b/test/stress/sequential/sequential-set/set_type_ellen_bintree.h @@ -0,0 +1,347 @@ +/* + 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 +#include +#include + +#include +#include "framework/ellen_bintree_update_desc_pool.h" + +namespace set { + + template + class EllenBinTreeSet : public cc::EllenBinTreeSet< GC, Key, T, Traits > + { + typedef cc::EllenBinTreeSet< GC, Key, T, Traits > base_class; + public: + template + 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 + 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 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 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 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 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 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 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 + >::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 + >::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 + static inline void print_stat( cds_test::property_stream& o, EllenBinTreeSet 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 + static inline void additional_check( EllenBinTreeSet& s ) + { + //typedef EllenBinTreeSet set_type; + GC::force_dispose(); + ellen_bintree_check::check_stat( s.statistics()); + } + + template + static inline void additional_cleanup( EllenBinTreeSet& /*s*/ ) + { + ellen_bintree_pool::internal_node_counter::reset(); + } + + template + static inline void check_before_clear( cds::container::EllenBinTreeSet& 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(); \ + } + +#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 diff --git a/test/stress/sequential/sequential-set/set_type_feldman_hashset.h b/test/stress/sequential/sequential-set/set_type_feldman_hashset.h new file mode 100644 index 00000000..0573fbc3 --- /dev/null +++ b/test/stress/sequential/sequential-set/set_type_feldman_hashset.h @@ -0,0 +1,460 @@ +/* + 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 +#include +#include + +#include +#include + +namespace set { + + template + class FeldmanHashSet : public cc::FeldmanHashSet< GC, T, Traits > + { + typedef cc::FeldmanHashSet< GC, T, Traits > base_class; + + + template + struct get_extracted_ptr + { + typedef typename base_class::guarded_ptr extracted_ptr; + }; + + template + struct get_extracted_ptr> + { + typedef typename base_class::exempt_ptr extracted_ptr; + }; + + public: + typedef typename T::hasher hasher; + typedef typename get_extracted_ptr::extracted_ptr extracted_ptr; + + template + struct rebind_traits { + typedef FeldmanHashSet result; + }; + + template + FeldmanHashSet( Config const& cfg ) + : base_class( cfg.s_nFeldmanSet_HeadBits, cfg.s_nFeldmanSet_ArrayBits ) + {} + + template + bool erase( Q const& key ) + { + return base_class::erase( hasher()( key )); + } + + template + bool erase( Q const& key, Func f ) + { + return base_class::erase( hasher()( key ), f ); + } + + template + extracted_ptr extract(Q const& key) + { + return base_class::extract( hasher()(key)); + } + + template + bool contains( Q const& key ) + { + return base_class::contains( hasher()(key)); + } + + template + typename std::enable_if< std::is_same< Iterator, typename base_class::iterator>::value, Iterator>::type + get_begin() + { + return base_class::begin(); + } + + template + typename std::enable_if< std::is_same< Iterator, typename base_class::iterator>::value, Iterator>::type + get_end() + { + return base_class::end(); + } + + template + typename std::enable_if< std::is_same< Iterator, typename base_class::reverse_iterator>::value, Iterator>::type + get_begin() + { + return base_class::rbegin(); + } + + template + 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 + 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 + struct hash_type + { + typedef Hasher hasher; + typedef typename hasher::hash_type type; + }; + + template + struct hash_type> + { + typedef std::hash hasher; + typedef size_t type; + }; + + template + struct key_val: base_class::key_val + { + typedef typename base_class::key_val base; + typedef Hasher hasher; + typedef typename hash_type::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 + explicit key_val( K const& k ): base(k), hash( hasher()( k )) {} + + template + 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 key_val::hash_type const& operator()( key_val const& kv ) + { + return kv.hash; + } + }; + typedef cds::atomicity::cache_friendly_item_counter item_counter; + }; + + typedef FeldmanHashSet< cds::gc::HP, key_val>, default_traits > FeldmanHashSet_hp_stdhash; + typedef FeldmanHashSet< cds::gc::DHP, key_val>, default_traits > FeldmanHashSet_dhp_stdhash; + typedef FeldmanHashSet< rcu_gpi, key_val>, default_traits > FeldmanHashSet_rcu_gpi_stdhash; + typedef FeldmanHashSet< rcu_gpb, key_val>, default_traits > FeldmanHashSet_rcu_gpb_stdhash; + typedef FeldmanHashSet< rcu_gpt, key_val>, default_traits > FeldmanHashSet_rcu_gpt_stdhash; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashSet< rcu_shb, key_val>, 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>, traits_FeldmanHashSet_stat > FeldmanHashSet_hp_stdhash_stat; + typedef FeldmanHashSet< cds::gc::DHP, key_val>, traits_FeldmanHashSet_stat > FeldmanHashSet_dhp_stdhash_stat; + typedef FeldmanHashSet< rcu_gpi, key_val>, traits_FeldmanHashSet_stat > FeldmanHashSet_rcu_gpi_stdhash_stat; + typedef FeldmanHashSet< rcu_gpb, key_val>, traits_FeldmanHashSet_stat > FeldmanHashSet_rcu_gpb_stdhash_stat; + typedef FeldmanHashSet< rcu_gpt, key_val>, traits_FeldmanHashSet_stat > FeldmanHashSet_rcu_gpt_stdhash_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashSet< rcu_shb, key_val>, 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 + explicit key_val(K const& k) : base_class(k) {} + + template + key_val(K const& k, T const& v) : base_class(k, v) {} + + // mock hasher + struct hasher { + template + 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 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 + 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(); \ + } + +#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 diff --git a/test/stress/sequential/sequential-set/set_type_iterable_list.h b/test/stress/sequential/sequential-set/set_type_iterable_list.h new file mode 100644 index 00000000..df316ac8 --- /dev/null +++ b/test/stress/sequential/sequential-set/set_type_iterable_list.h @@ -0,0 +1,99 @@ +/* + 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 +#include +//#include + +namespace set { + + template + 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 diff --git a/test/stress/sequential/sequential-set/set_type_lazy_list.h b/test/stress/sequential/sequential-set/set_type_lazy_list.h new file mode 100644 index 00000000..e00c9faf --- /dev/null +++ b/test/stress/sequential/sequential-set/set_type_lazy_list.h @@ -0,0 +1,137 @@ +/* + 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 +#include +#include + +namespace set { + + template + 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 diff --git a/test/stress/sequential/sequential-set/set_type_michael.h b/test/stress/sequential/sequential-set/set_type_michael.h new file mode 100644 index 00000000..2682511f --- /dev/null +++ b/test/stress/sequential/sequential-set/set_type_michael.h @@ -0,0 +1,329 @@ +/* + 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 +#include + +#include +#include +#include + +namespace set { + + template + class MichaelHashSet : public cc::MichaelHashSet< GC, List, Traits > + { + typedef cc::MichaelHashSet< GC, List, Traits > base_class; + public: + template + MichaelHashSet( Config const& cfg ) + : base_class( cfg.s_nSetSize, cfg.s_nLoadFactor ) + {} + + template + typename std::enable_if< std::is_same< Iterator, typename base_class::iterator>::value, Iterator>::type + get_begin() + { + return base_class::begin(); + } + + template + 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 + 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 + static inline void print_stat( cds_test::property_stream& o, MichaelHashSet 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(); \ + } + +#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 diff --git a/test/stress/sequential/sequential-set/set_type_michael_list.h b/test/stress/sequential/sequential-set/set_type_michael_list.h new file mode 100644 index 00000000..1ce5268c --- /dev/null +++ b/test/stress/sequential/sequential-set/set_type_michael_list.h @@ -0,0 +1,135 @@ +/* + 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 +#include +#include + +namespace set { + + template + 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 diff --git a/test/stress/sequential/sequential-set/set_type_skip_list.h b/test/stress/sequential/sequential-set/set_type_skip_list.h new file mode 100644 index 00000000..922c544e --- /dev/null +++ b/test/stress/sequential/sequential-set/set_type_skip_list.h @@ -0,0 +1,437 @@ +/* + 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 +#include +#include + +#include + +namespace set { + + template + class SkipListSet : public cc::SkipListSet + { + typedef cc::SkipListSet base_class; + public: + template + 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 + 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 + static inline void print_stat( cds_test::property_stream& o, SkipListSet 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(); \ + } + +#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 diff --git a/test/stress/sequential/sequential-set/set_type_split_list.h b/test/stress/sequential/sequential-set/set_type_split_list.h new file mode 100644 index 00000000..0e7621f3 --- /dev/null +++ b/test/stress/sequential/sequential-set/set_type_split_list.h @@ -0,0 +1,697 @@ +/* + 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +namespace set { + + template + class SplitListSet : public cc::SplitListSet< GC, T, Traits > + { + typedef cc::SplitListSet< GC, T, Traits > base_class; + public: + template + SplitListSet( Config const& cfg ) + : base_class( cfg.s_nSetSize, cfg.s_nLoadFactor ) + {} + + template + typename std::enable_if< std::is_same< Iterator, typename base_class::iterator>::value, Iterator>::type + get_begin() + { + return base_class::begin(); + } + + template + 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 + 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 + ,co::hash< hash > + ,co::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 + ,co::hash< hash > + , co::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 + ,co::hash< hash > + ,co::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::split_list::dynamic_bucket_table< false > + ,co::hash< hash > + ,co::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 + ,co::hash< hash > + , co::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::split_list::dynamic_bucket_table< false > + ,co::hash< hash > + , co::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::split_list::dynamic_bucket_table< false > + ,co::hash< hash > + , co::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 + ,co::hash< hash > + , co::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 + ,co::hash< hash > + , co::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::split_list::dynamic_bucket_table< false > + ,co::hash< hash > + , co::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 + ,co::hash< hash > + , co::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::split_list::dynamic_bucket_table< false > + ,co::hash< hash > + , co::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 + ,co::hash< hash > + , co::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 + ,co::hash< hash > + , co::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 + ,co::hash< hash > + , co::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::split_list::dynamic_bucket_table< false > + ,co::hash< hash > + , co::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 + ,co::hash< hash > + , co::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::split_list::dynamic_bucket_table< false > + ,co::hash< hash > + , co::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::split_list::dynamic_bucket_table< false > + ,co::hash< hash > + , co::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 + static inline void print_stat( cds_test::property_stream& o, SplitListSet 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(); \ + } + + +#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 diff --git a/test/stress/sequential/sequential-set/set_type_std.h b/test/stress/sequential/sequential-set/set_type_std.h new file mode 100644 index 00000000..20b9db80 --- /dev/null +++ b/test/stress/sequential/sequential-set/set_type_std.h @@ -0,0 +1,263 @@ +/* + 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 +#include +#include //unique_lock + +#include "set_type.h" + +namespace set { + + struct tag_StdSet; + + template ::other + > + class StdHashSet + : public std::unordered_set< + Value + , Hash + , EqualTo + , Alloc + > + { + public: + Lock m_lock; + typedef std::unique_lock scoped_lock; + typedef std::unordered_set< + Value + , Hash + , EqualTo + , Alloc + > base_class; + + public: + typedef typename base_class::value_type value_type; + + template + StdHashSet( Config const& ) + {} + + template + bool contains( const Key& key ) + { + scoped_lock al( m_lock ); + return base_class::find( value_type(key)) != base_class::end(); + } + + template + bool insert( Key const& key ) + { + scoped_lock al( m_lock ); + std::pair pRet = base_class::insert( value_type( key )); + return pRet.second; + } + + template + bool insert( Key const& key, Func func ) + { + scoped_lock al( m_lock ); + std::pair pRet = base_class::insert( value_type( key )); + if ( pRet.second ) { + func( *pRet.first ); + return true; + } + return false; + } + + template + std::pair ensure( const T& key, Func func ) + { + scoped_lock al( m_lock ); + std::pair 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 + bool erase( const Key& key ) + { + scoped_lock al( m_lock ); + return base_class::erase( value_type(key)) != 0; + } + + template + 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 ::other + > + class StdSet: public std::set + { + Lock m_lock; + typedef std::unique_lock scoped_lock; + typedef std::set base_class; + public: + typedef typename base_class::key_type value_type; + + template + StdSet( Config const& ) + {} + + template + bool contains( const Key& key ) + { + value_type v( key ); + scoped_lock al( m_lock ); + return base_class::find( v ) != base_class::end(); + } + + template + bool insert( Key const& k ) + { + scoped_lock al( m_lock ); + return base_class::insert( value_type( k )).second; + } + + template + bool insert( Key const& key, Func func ) + { + scoped_lock al( m_lock ); + std::pair pRet = base_class::insert( value_type( key )); + if ( pRet.second ) { + func( *pRet.first ); + return true; + } + return false; + } + + template + std::pair ensure( const T& key, Func func ) + { + scoped_lock al( m_lock ); + std::pair 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 + bool erase( const Key& key ) + { + scoped_lock al( m_lock ); + return base_class::erase( value_type(key)) != 0; + } + + template + 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 + 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(); \ + } + +#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 diff --git a/test/stress/sequential/sequential-set/set_type_striped.h b/test/stress/sequential/sequential-set/set_type_striped.h new file mode 100644 index 00000000..a67a20bc --- /dev/null +++ b/test/stress/sequential/sequential-set/set_type_striped.h @@ -0,0 +1,644 @@ +/* + 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 +#include +#include +#include +#include + +#include +#if BOOST_VERSION >= 104800 +# include +# include +# include +# include +# include +# include +#endif +#include + +namespace set { + + struct tag_StripedSet; + + template + 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 StripedHashSet_seq: + public cc::StripedSet< BucketEntry, + co::mutex_policy< cc::striped_set::striping<> > + ,co::resizing_policy > + , Options... + > + { + typedef cc::StripedSet< BucketEntry, + co::mutex_policy< cc::striped_set::striping<> > + ,co::resizing_policy > + , Options... + > base_class; + typedef typename base_class::resizing_policy resizing_policy_t; + + resizing_policy_t m_placeHolder; + public: + template + 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 + 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 StripedHashSet_seq_rational: + public cc::StripedSet< BucketEntry, + co::mutex_policy< cc::striped_set::striping<> > + ,co::resizing_policy > + , Options... + > + { + typedef cc::StripedSet< BucketEntry, + co::mutex_policy< cc::striped_set::striping<> > + ,co::resizing_policy > + , Options... + > base_class; + typedef typename base_class::resizing_policy resizing_policy_t; + + resizing_policy_t m_placeHolder; + public: + template + 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 + 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 StripedHashSet_ord: + public cc::StripedSet< BucketEntry, + co::resizing_policy > + ,co::mutex_policy< cc::striped_set::striping<> > + , Options... + > + { + typedef cc::StripedSet< BucketEntry, + co::resizing_policy > + ,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 + 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 StripedHashSet_ord_rational: + public cc::StripedSet< BucketEntry, + co::resizing_policy > + ,co::mutex_policy< cc::striped_set::striping<> > + , Options... + > + { + typedef cc::StripedSet< BucketEntry, + co::resizing_policy > + ,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 + 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 RefinableHashSet_seq: + public cc::StripedSet< BucketEntry, + co::mutex_policy< cc::striped_set::refinable<> > + ,co::resizing_policy > + , Options... + > + { + typedef cc::StripedSet< BucketEntry, + co::mutex_policy< cc::striped_set::refinable<> > + ,co::resizing_policy > + , Options... + > base_class; + typedef typename base_class::resizing_policy resizing_policy_t; + + resizing_policy_t m_placeHolder; + public: + template + 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 + 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 RefinableHashSet_seq_rational: + public cc::StripedSet< BucketEntry, + co::mutex_policy< cc::striped_set::refinable<> > + ,co::resizing_policy > + , Options... + > + { + typedef cc::StripedSet< BucketEntry, + co::mutex_policy< cc::striped_set::refinable<> > + ,co::resizing_policy > + , Options... + > base_class; + typedef typename base_class::resizing_policy resizing_policy_t; + + resizing_policy_t m_placeHolder; + public: + template + 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 RefinableHashSet_ord: + public cc::StripedSet< BucketEntry, + co::resizing_policy > + ,co::mutex_policy< cc::striped_set::refinable<> > + , Options... + > + { + typedef cc::StripedSet< BucketEntry, + co::resizing_policy > + ,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 + 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 RefinableHashSet_ord_rational: + public cc::StripedSet< BucketEntry, + co::resizing_policy > + ,co::mutex_policy< cc::striped_set::refinable<> > + , Options... + > + { + typedef cc::StripedSet< BucketEntry, + co::resizing_policy > + ,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 + 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(); \ + } + +#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 diff --git a/test/stress/sequential/sequential_freelist_put_get.cpp b/test/stress/sequential/sequential_freelist_put_get.cpp new file mode 100644 index 00000000..0767d754 --- /dev/null +++ b/test/stress/sequential/sequential_freelist_put_get.cpp @@ -0,0 +1,187 @@ +/* + 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 + +#include +#include +#ifdef CDS_DCAS_SUPPORT +# include +#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 + struct value_type: public FreeList::node + { + size_t counter; + + value_type() + : counter(0) + {} + }; + + template + 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 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( 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 + void test( FreeList& list ) + { + cds_test::thread_pool& pool = get_pool(); + + value_type arr[c_nArraySize]; + + for ( auto& i : arr ) + list.put( &i ); + + pool.add( new Worker( 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&>( 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 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 tp; + if ( tp.is_lock_free()) { + cds::intrusive::TaggedFreeList fl; + test( fl ); + } + else + std::cout << "Double-width CAS is not supported\n"; + } +#endif + +} // namespace diff --git a/test/stress/sequential/sequential_freelist_put_get_single.cpp b/test/stress/sequential/sequential_freelist_put_get_single.cpp new file mode 100644 index 00000000..9b7f68a2 --- /dev/null +++ b/test/stress/sequential/sequential_freelist_put_get_single.cpp @@ -0,0 +1,165 @@ +/* + 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 + +#include +#include +#ifdef CDS_DCAS_SUPPORT +# include +#endif + +namespace { + class put_get_single: public cds_test::stress_fixture + { + protected: + static size_t s_nThreadCount; + static size_t s_nPassCount; + + template + struct value_type: public FreeList::node + { + atomics::atomic counter; + + value_type() + : counter(0) + {} + }; + + template + 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 item_type; + + for ( size_t pass = 0; pass < s_nPassCount; ++pass ) { + item_type* p; + while ( (p = static_cast( 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 + void test( FreeList& list ) + { + cds_test::thread_pool& pool = get_pool(); + + value_type item;; + list.put( &item ); + + pool.add( new Worker( 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 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 tp; + if ( tp.is_lock_free()) { + cds::intrusive::TaggedFreeList fl; + test( fl ); + } + else + std::cout << "Double-width CAS is not supported\n"; + } +#endif + +} // namespace diff --git a/test/stress/sequential/sequential_queue.cpp b/test/stress/sequential/sequential_queue.cpp new file mode 100644 index 00000000..1a537dd6 --- /dev/null +++ b/test/stress/sequential/sequential_queue.cpp @@ -0,0 +1,301 @@ +/* + 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 +#include +#include + +// 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 sequential_queue : public cds_test::stress_fixture { +protected: + using value_type = Value; + + template + 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::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::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 { + typedef sequential_queue<> base_class; + +protected: + template void test() { + size_t quasi_factor = GetParam(); + Queue q(quasi_factor); + base_class::test(q); + } + +public: + static std::vector 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 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::type_name queue_type; \ + test(); \ + } + +#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 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 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(buf.second % 256); + uint8_t const *p = reinterpret_cast(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::type_name queue_type; \ + queue_type queue(s_nBufferSize); \ + test(queue); \ + } + +CDSSTRESS_WeakRingBuffer_void(sequential_weak_ring_buffer) + +#undef CDSSTRESS_Queue_F + +} // namespace diff --git a/test/stress/sequential/sequential_stack.cpp b/test/stress/sequential/sequential_stack.cpp new file mode 100644 index 00000000..48287ef8 --- /dev/null +++ b/test/stress/sequential/sequential_stack.cpp @@ -0,0 +1,115 @@ +/* + 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::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::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 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 -- 2.34.1