From 2304d657c11732b1a4a01838354135215a32b987 Mon Sep 17 00:00:00 2001 From: khizmax Date: Fri, 5 Aug 2016 22:52:41 +0300 Subject: [PATCH] Added stress test for thread-safe iterable sets --- projects/Win/vc14/cds.sln | 16 + projects/Win/vc14/stress-framework.vcxproj | 1 + .../Win/vc14/stress-framework.vcxproj.filters | 3 + .../Win/vc14/stress-set-iteration.vcxproj | 252 +++++++ .../vc14/stress-set-iteration.vcxproj.filters | 39 ++ test/stress/set/CMakeLists.txt | 2 + .../set/insdel_string/set_insdel_string.cpp | 6 +- test/stress/set/iteration/CMakeLists.txt | 24 + test/stress/set/iteration/set_iteration.cpp | 118 ++++ test/stress/set/iteration/set_iteration.h | 626 ++++++++++++++++++ .../set_iteration_feldman_hashset.cpp | 39 ++ .../set/iteration/set_iteration_michael.cpp | 38 ++ 12 files changed, 1161 insertions(+), 3 deletions(-) create mode 100644 projects/Win/vc14/stress-set-iteration.vcxproj create mode 100644 projects/Win/vc14/stress-set-iteration.vcxproj.filters create mode 100644 test/stress/set/iteration/CMakeLists.txt create mode 100644 test/stress/set/iteration/set_iteration.cpp create mode 100644 test/stress/set/iteration/set_iteration.h create mode 100644 test/stress/set/iteration/set_iteration_feldman_hashset.cpp create mode 100644 test/stress/set/iteration/set_iteration_michael.cpp diff --git a/projects/Win/vc14/cds.sln b/projects/Win/vc14/cds.sln index 727f5cff..deb30067 100644 --- a/projects/Win/vc14/cds.sln +++ b/projects/Win/vc14/cds.sln @@ -17,6 +17,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "cds_test", "cds_test", "{3A510E45-180B-4ADC-AFCD-D75774B68580}" ProjectSection(SolutionItems) = preProject ..\..\..\test\include\cds_test\check_size.h = ..\..\..\test\include\cds_test\check_size.h + ..\..\..\test\include\cds_test\city.h = ..\..\..\test\include\cds_test\city.h ..\..\..\test\include\cds_test\fixture.h = ..\..\..\test\include\cds_test\fixture.h ..\..\..\test\include\cds_test\hash_func.h = ..\..\..\test\include\cds_test\hash_func.h ..\..\..\test\include\cds_test\stat_bronson_avltree_out.h = ..\..\..\test\include\cds_test\stat_bronson_avltree_out.h @@ -225,6 +226,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stress-map-insfind-int", "s {408FE9BC-44F0-4E6A-89FA-D6F952584239} = {408FE9BC-44F0-4E6A-89FA-D6F952584239} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stress-set-iteration", "stress-set-iteration.vcxproj", "{31952FA8-A303-4A0B-94C4-ABA5A8A6DBCE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -595,6 +598,18 @@ Global {24DF3B87-387E-4EFC-BDE0-8DAD279FE19A}.Release|Win32.Build.0 = Release|Win32 {24DF3B87-387E-4EFC-BDE0-8DAD279FE19A}.Release|x64.ActiveCfg = Release|x64 {24DF3B87-387E-4EFC-BDE0-8DAD279FE19A}.Release|x64.Build.0 = Release|x64 + {31952FA8-A303-4A0B-94C4-ABA5A8A6DBCE}.Debug|Win32.ActiveCfg = Debug|Win32 + {31952FA8-A303-4A0B-94C4-ABA5A8A6DBCE}.Debug|Win32.Build.0 = Debug|Win32 + {31952FA8-A303-4A0B-94C4-ABA5A8A6DBCE}.Debug|x64.ActiveCfg = Debug|x64 + {31952FA8-A303-4A0B-94C4-ABA5A8A6DBCE}.Debug|x64.Build.0 = Debug|x64 + {31952FA8-A303-4A0B-94C4-ABA5A8A6DBCE}.DebugVLD|Win32.ActiveCfg = DebugVLD|Win32 + {31952FA8-A303-4A0B-94C4-ABA5A8A6DBCE}.DebugVLD|Win32.Build.0 = DebugVLD|Win32 + {31952FA8-A303-4A0B-94C4-ABA5A8A6DBCE}.DebugVLD|x64.ActiveCfg = DebugVLD|x64 + {31952FA8-A303-4A0B-94C4-ABA5A8A6DBCE}.DebugVLD|x64.Build.0 = DebugVLD|x64 + {31952FA8-A303-4A0B-94C4-ABA5A8A6DBCE}.Release|Win32.ActiveCfg = Release|Win32 + {31952FA8-A303-4A0B-94C4-ABA5A8A6DBCE}.Release|Win32.Build.0 = Release|Win32 + {31952FA8-A303-4A0B-94C4-ABA5A8A6DBCE}.Release|x64.ActiveCfg = Release|x64 + {31952FA8-A303-4A0B-94C4-ABA5A8A6DBCE}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -633,6 +648,7 @@ Global {50387CA5-F5B2-4C40-ACFD-FC3C9EE2CD6B} = {7D3EE35B-185D-40B5-88C2-7F9933426978} {1BB746AC-7856-4E59-9430-51177621DC35} = {7D3EE35B-185D-40B5-88C2-7F9933426978} {24DF3B87-387E-4EFC-BDE0-8DAD279FE19A} = {7D3EE35B-185D-40B5-88C2-7F9933426978} + {31952FA8-A303-4A0B-94C4-ABA5A8A6DBCE} = {0D83E8C7-97D1-4BA1-928A-6846E7089652} EndGlobalSection GlobalSection(DPCodeReviewSolutionGUID) = preSolution DPCodeReviewSolutionGUID = {00000000-0000-0000-0000-000000000000} diff --git a/projects/Win/vc14/stress-framework.vcxproj b/projects/Win/vc14/stress-framework.vcxproj index 9288eaae..1bb5e312 100644 --- a/projects/Win/vc14/stress-framework.vcxproj +++ b/projects/Win/vc14/stress-framework.vcxproj @@ -28,6 +28,7 @@ + diff --git a/projects/Win/vc14/stress-framework.vcxproj.filters b/projects/Win/vc14/stress-framework.vcxproj.filters index a757333f..9599b06f 100644 --- a/projects/Win/vc14/stress-framework.vcxproj.filters +++ b/projects/Win/vc14/stress-framework.vcxproj.filters @@ -24,6 +24,9 @@ Header Files + + Header Files + diff --git a/projects/Win/vc14/stress-set-iteration.vcxproj b/projects/Win/vc14/stress-set-iteration.vcxproj new file mode 100644 index 00000000..bb410bd5 --- /dev/null +++ b/projects/Win/vc14/stress-set-iteration.vcxproj @@ -0,0 +1,252 @@ + + + + + DebugVLD + Win32 + + + DebugVLD + x64 + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + {31952FA8-A303-4A0B-94C4-ABA5A8A6DBCE} + Win32Proj + stress_set_iteration + 8.1 + stress-set-iteration + + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)..\..\..\bin\vc.$(PlatformToolset)\$(Platform)\ + $(SolutionDir)..\..\..\obj\vc.$(PlatformToolset)\$(Platform)\$(ProjectName)\$(Configuration)\ + $(ProjectName)_d + + + true + $(SolutionDir)..\..\..\bin\vc.$(PlatformToolset)\$(Platform)\ + $(SolutionDir)..\..\..\obj\vc.$(PlatformToolset)\$(Platform)\$(ProjectName)\$(Configuration)\ + $(ProjectName)_d + + + true + $(SolutionDir)..\..\..\bin\vc.$(PlatformToolset)\$(Platform)\ + $(SolutionDir)..\..\..\obj\vc.$(PlatformToolset)\$(Platform)\$(ProjectName)\$(Configuration)\ + $(ProjectName)_d + + + true + $(SolutionDir)..\..\..\bin\vc.$(PlatformToolset)\$(Platform)\ + $(SolutionDir)..\..\..\obj\vc.$(PlatformToolset)\$(Platform)\$(ProjectName)\$(Configuration)\ + $(ProjectName)_d + + + false + $(SolutionDir)..\..\..\bin\vc.$(PlatformToolset)\$(Platform)-release\ + $(SolutionDir)..\..\..\obj\vc.$(PlatformToolset)\$(Platform)\$(ProjectName)\$(Configuration)\ + + + false + $(SolutionDir)..\..\..\bin\vc.$(PlatformToolset)\$(Platform)-release\ + $(SolutionDir)..\..\..\obj\vc.$(PlatformToolset)\$(Platform)\$(ProjectName)\$(Configuration)\ + + + + NotUsing + Level3 + Disabled + _ENABLE_ATOMIC_ALIGNMENT_FIX;CDSUNIT_USE_URCU;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(SolutionDir)..\..\..;$(GTEST_ROOT)/include;$(SolutionDir)..\..\..\test\include;$(SolutionDir)..\..\..\test\stress\set;$(SolutionDir)..\..\..\test\stress\;$(BOOST_PATH);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + + + Console + true + $(GTEST_LIB32);$(GTEST_ROOT)/lib/x86;$(BOOST_PATH)/stage32/lib;$(BOOST_PATH)/stage/lib;$(BOOST_PATH)/bin;%(AdditionalLibraryDirectories);$(OutDir) + gtestd.lib;stress-framework_d.lib;%(AdditionalDependencies) + + + + + NotUsing + Level3 + Disabled + _ENABLE_ATOMIC_ALIGNMENT_FIX;CDSUNIT_USE_URCU;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(SolutionDir)..\..\..;$(GTEST_ROOT)/include;$(SolutionDir)..\..\..\test\include;$(SolutionDir)..\..\..\test\stress\set;$(SolutionDir)..\..\..\test\stress\;$(BOOST_PATH);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + + + Console + true + $(GTEST_LIB32);$(GTEST_ROOT)/lib/x86;$(BOOST_PATH)/stage32/lib;$(BOOST_PATH)/stage/lib;$(BOOST_PATH)/bin;%(AdditionalLibraryDirectories);$(OutDir) + gtestd.lib;stress-framework_d.lib;%(AdditionalDependencies) + + + + + NotUsing + Level3 + Disabled + _ENABLE_ATOMIC_ALIGNMENT_FIX;CDSUNIT_USE_URCU;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(SolutionDir)..\..\..;$(GTEST_ROOT)/include;$(SolutionDir)..\..\..\test\include;$(SolutionDir)..\..\..\test\stress\set;$(SolutionDir)..\..\..\test\stress\;$(BOOST_PATH);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + + + Console + true + $(GTEST_LIB64);$(GTEST_ROOT)/lib/x64;$(BOOST_PATH)/stage64/lib;$(BOOST_PATH)/bin;%(AdditionalLibraryDirectories);$(OutDir) + gtestd.lib;stress-framework_d.lib;%(AdditionalDependencies) + + + + + NotUsing + Level3 + Disabled + _ENABLE_ATOMIC_ALIGNMENT_FIX;CDSUNIT_USE_URCU;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(SolutionDir)..\..\..;$(GTEST_ROOT)/include;$(SolutionDir)..\..\..\test\include;$(SolutionDir)..\..\..\test\stress\set;$(SolutionDir)..\..\..\test\stress\;$(BOOST_PATH);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + + + Console + true + $(GTEST_LIB64);$(GTEST_ROOT)/lib/x64;$(BOOST_PATH)/stage64/lib;$(BOOST_PATH)/bin;%(AdditionalLibraryDirectories);$(OutDir) + gtestd.lib;stress-framework_d.lib;%(AdditionalDependencies) + + + + + Level3 + NotUsing + MaxSpeed + true + true + _ENABLE_ATOMIC_ALIGNMENT_FIX;CDSUNIT_USE_URCU;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(SolutionDir)..\..\..;$(GTEST_ROOT)/include;$(SolutionDir)..\..\..\test\include;$(SolutionDir)..\..\..\test\stress\set;$(SolutionDir)..\..\..\test\stress\;$(BOOST_PATH);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + + + Console + true + true + true + $(GTEST_LIB32);$(GTEST_ROOT)/lib/x86;$(BOOST_PATH)/stage32/lib;$(BOOST_PATH)/stage/lib;$(BOOST_PATH)/bin;%(AdditionalLibraryDirectories);$(OutDir) + gtest.lib;stress-framework.lib;%(AdditionalDependencies) + + + + + Level3 + NotUsing + MaxSpeed + true + true + _ENABLE_ATOMIC_ALIGNMENT_FIX;CDSUNIT_USE_URCU;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(SolutionDir)..\..\..;$(GTEST_ROOT)/include;$(SolutionDir)..\..\..\test\include;$(SolutionDir)..\..\..\test\stress\set;$(SolutionDir)..\..\..\test\stress\;$(BOOST_PATH);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + + + Console + true + true + true + $(GTEST_LIB64);$(GTEST_ROOT)/lib/x64;$(BOOST_PATH)/stage64/lib;$(BOOST_PATH)/bin;%(AdditionalLibraryDirectories);$(OutDir) + gtest.lib;stress-framework.lib;%(AdditionalDependencies) + + + + + + \ No newline at end of file diff --git a/projects/Win/vc14/stress-set-iteration.vcxproj.filters b/projects/Win/vc14/stress-set-iteration.vcxproj.filters new file mode 100644 index 00000000..f13d03a9 --- /dev/null +++ b/projects/Win/vc14/stress-set-iteration.vcxproj.filters @@ -0,0 +1,39 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + + + + \ No newline at end of file diff --git a/test/stress/set/CMakeLists.txt b/test/stress/set/CMakeLists.txt index 473f4e5b..f689f08d 100644 --- a/test/stress/set/CMakeLists.txt +++ b/test/stress/set/CMakeLists.txt @@ -5,6 +5,7 @@ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/delodd) 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_custom_target( stress-set DEPENDS @@ -12,4 +13,5 @@ add_custom_target( stress-set stress-set-insdelfind stress-set-insdel-func stress-set-insdel-string + stress-set-iteration ) diff --git a/test/stress/set/insdel_string/set_insdel_string.cpp b/test/stress/set/insdel_string/set_insdel_string.cpp index eeb9fbc3..a15bea3f 100644 --- a/test/stress/set/insdel_string/set_insdel_string.cpp +++ b/test/stress/set/insdel_string/set_insdel_string.cpp @@ -25,7 +25,7 @@ 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. + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "set_insdel_string.h" @@ -50,7 +50,7 @@ namespace set { void Set_InsDel_string::SetUpTestCase() { - cds_test::config const& cfg = get_config( "map_insdel_func" ); + cds_test::config const& cfg = get_config( "map_insdel_string" ); s_nSetSize = cfg.get_size_t( "MapSize", s_nSetSize ); if ( s_nSetSize < 1000 ) @@ -101,7 +101,7 @@ namespace set { std::vector Set_InsDel_string_LF::get_load_factors() { - cds_test::config const& cfg = get_config( "map_insdel_func" ); + cds_test::config const& cfg = get_config( "map_insdel_string" ); s_nMaxLoadFactor = cfg.get_size_t( "MaxLoadFactor", s_nMaxLoadFactor ); if ( s_nMaxLoadFactor == 0 ) diff --git a/test/stress/set/iteration/CMakeLists.txt b/test/stress/set/iteration/CMakeLists.txt new file mode 100644 index 00000000..e17c6084 --- /dev/null +++ b/test/stress/set/iteration/CMakeLists.txt @@ -0,0 +1,24 @@ +set(PACKAGE_NAME stress-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_SHARED_LIBRARY} + ${GTEST_LIBRARY} + ${Boost_THREAD_LIBRARY} + ${Boost_SYSTEM_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT} +) + +add_test(NAME ${PACKAGE_NAME} COMMAND ${PACKAGE_NAME} WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) \ No newline at end of file diff --git a/test/stress/set/iteration/set_iteration.cpp b/test/stress/set/iteration/set_iteration.cpp new file mode 100644 index 00000000..b72792e5 --- /dev/null +++ b/test/stress/set/iteration/set_iteration.cpp @@ -0,0 +1,118 @@ +/* + This file is a part of libcds - Concurrent Data Structures library + + (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016 + + Source code repo: http://github.com/khizmax/libcds/ + Download: http://sourceforge.net/projects/libcds/files/ + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "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; + } + + INSTANTIATE_TEST_CASE_P( a, Set_Iteration_LF, ::testing::ValuesIn( Set_Iteration_LF::get_load_factors())); +} // namespace set diff --git a/test/stress/set/iteration/set_iteration.h b/test/stress/set/iteration/set_iteration.h new file mode 100644 index 00000000..b8ea3b3c --- /dev/null +++ b/test/stress/set/iteration/set_iteration.h @@ -0,0 +1,626 @@ +/* + This file is a part of libcds - Concurrent Data Structures library + + (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016 + + Source code repo: http://github.com/khizmax/libcds/ + Download: http://sourceforge.net/projects/libcds/files/ + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "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; + for ( auto it = rSet.begin(); it != rSet.end(); ++it ) { + it->val.hash = CityHash64( it->key.c_str(), it->key.length()); + ++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/set/iteration/set_iteration_feldman_hashset.cpp b/test/stress/set/iteration/set_iteration_feldman_hashset.cpp new file mode 100644 index 00000000..805c5640 --- /dev/null +++ b/test/stress/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-2016 + + Source code repo: http://github.com/khizmax/libcds/ + Download: http://sourceforge.net/projects/libcds/files/ + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "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/set/iteration/set_iteration_michael.cpp b/test/stress/set/iteration/set_iteration_michael.cpp new file mode 100644 index 00000000..fbb2d3bc --- /dev/null +++ b/test/stress/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-2016 + + Source code repo: http://github.com/khizmax/libcds/ + Download: http://sourceforge.net/projects/libcds/files/ + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "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 -- 2.34.1