From: Peizhao Ou Date: Thu, 8 Feb 2018 20:49:43 +0000 (-0800) Subject: Adds parallel test organization (actual test cases are still sequential) X-Git-Url: http://plrg.eecs.uci.edu/git/?p=libcds.git;a=commitdiff_plain;h=f7b18ec599eadb55ea2e8757ba12fcab12e9f708 Adds parallel test organization (actual test cases are still sequential) --- diff --git a/test/stress/CMakeLists.txt b/test/stress/CMakeLists.txt index 089f81e8..a11751da 100644 --- a/test/stress/CMakeLists.txt +++ b/test/stress/CMakeLists.txt @@ -22,6 +22,7 @@ include_directories( ) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/sequential) +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/parallel) #add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/misc) #add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/freelist) #add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/map) @@ -33,6 +34,7 @@ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/sequential) add_custom_target( stress-all DEPENDS stress-sequential-all + stress-parallel-all #stress-misc #stress-freelist #stress-map diff --git a/test/stress/parallel/CMakeLists.txt b/test/stress/parallel/CMakeLists.txt new file mode 100644 index 00000000..fff34f13 --- /dev/null +++ b/test/stress/parallel/CMakeLists.txt @@ -0,0 +1,32 @@ +set(PACKAGE_NAME stress-parallel) + +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/parallel-misc) +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/parallel-map) + +set(CDSSTRESS_STACK_SOURCES + ../main.cpp + parallel_queue.cpp + parallel_freelist_put_get_single.cpp + parallel_freelist_put_get.cpp + parallel_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_executable(mytest test.cpp ../main.cpp) +#add_executable(mytest test.cpp ) +#target_link_libraries(mytest ${CDS_TEST_LIBRARIES} ${CDSSTRESS_FRAMEWORK_LIBRARY}) + +add_test(NAME ${PACKAGE_NAME} COMMAND ${PACKAGE_NAME} WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) + +add_custom_target( stress-parallel-all + DEPENDS + stress-parallel + stress-parallel-map + stress-parallel-misc +) diff --git a/test/stress/parallel/parallel-map/CMakeLists.txt b/test/stress/parallel/parallel-map/CMakeLists.txt new file mode 100644 index 00000000..d41efd30 --- /dev/null +++ b/test/stress/parallel/parallel-map/CMakeLists.txt @@ -0,0 +1,17 @@ + +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}/find_string) +#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/insdel_func) +#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/insdel_string) +#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/insdel_item_int) +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/insdelfind) +#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/minmax) +#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/iter_erase) + +add_custom_target( stress-parallel-map + DEPENDS + stress-parallel-map-insdelfind +) diff --git a/test/stress/parallel/parallel-map/del3/CMakeLists.txt b/test/stress/parallel/parallel-map/del3/CMakeLists.txt new file mode 100644 index 00000000..1098f447 --- /dev/null +++ b/test/stress/parallel/parallel-map/del3/CMakeLists.txt @@ -0,0 +1,23 @@ +set(PACKAGE_NAME stress-sequential-map-del3) + +set(CDSSTRESS_MAP_DEL3_SOURCES + ../../../main.cpp + map_del3.cpp + map_del3_bronsonavltree.cpp + map_del3_cuckoo.cpp + map_del3_ellentree.cpp + map_del3_feldman_hashmap.cpp + map_del3_michael.cpp + map_del3_skip.cpp + map_del3_split.cpp +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. +) + +add_executable(${PACKAGE_NAME} ${CDSSTRESS_MAP_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/parallel/parallel-map/del3/map_del3.cpp b/test/stress/parallel/parallel-map/del3/map_del3.cpp new file mode 100644 index 00000000..6332394e --- /dev/null +++ b/test/stress/parallel/parallel-map/del3/map_del3.cpp @@ -0,0 +1,167 @@ +/* + 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 "map_del3.h" + +namespace map { + + size_t Map_Del3::s_nMapSize = 10000; + size_t Map_Del3::s_nInsThreadCount = 4; + size_t Map_Del3::s_nDelThreadCount = 4; + size_t Map_Del3::s_nExtractThreadCount = 4; + size_t Map_Del3::s_nFindThreadCount = 2; + size_t Map_Del3::s_nMaxLoadFactor = 8; + size_t Map_Del3::s_nInsertPassCount = 100; + size_t Map_Del3::s_nOriginalPassCount = 100; + size_t Map_Del3::s_nPassCount = 100; + size_t Map_Del3::s_nFeldmanPassCount = 100; + size_t Map_Del3::s_nBronsonAVLTreeMapPassCount = 100; + size_t Map_Del3::s_nEllenBinTreeMapPassCount= 100; + size_t Map_Del3::s_nMichaelMapPassCount= 100; + size_t Map_Del3::s_nSkipListMapPassCount= 100; + + size_t Map_Del3::s_nCuckooInitialSize = 1024; + size_t Map_Del3::s_nCuckooProbesetSize = 16; + size_t Map_Del3::s_nCuckooProbesetThreshold = 0; + + size_t Map_Del3::s_nFeldmanMap_HeadBits = 10; + size_t Map_Del3::s_nFeldmanMap_ArrayBits = 4; + + size_t Map_Del3::s_nLoadFactor = 1; + std::vector Map_Del3::m_arrElements; + + void Map_Del3::SetUpTestCase() + { + cds_test::config const& cfg = get_config( "sequential_real_map_delodd" ); + + s_nMapSize = cfg.get_size_t( "MapSize", s_nMapSize ); + if ( s_nMapSize < 1000 ) + s_nMapSize = 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( "InsertPassCount", s_nInsertPassCount ); + if ( s_nInsertPassCount == 0 ) + s_nInsertPassCount = 100; + + s_nPassCount = cfg.get_size_t("PassCount", s_nPassCount); + if (s_nPassCount == 0) + s_nPassCount = 100; + s_nOriginalPassCount = s_nPassCount; + + s_nFeldmanPassCount = + cfg.get_size_t("FeldmanPassCount", s_nFeldmanPassCount); + if (s_nFeldmanPassCount == 0) + s_nFeldmanPassCount = 500; + + s_nBronsonAVLTreeMapPassCount = cfg.get_size_t( + "BronsonAVLTreeMapPassCount", s_nBronsonAVLTreeMapPassCount); + if (s_nBronsonAVLTreeMapPassCount == 0) + s_nBronsonAVLTreeMapPassCount = 500; + + s_nEllenBinTreeMapPassCount = cfg.get_size_t( + "EllenBinTreeMapPassCount", s_nEllenBinTreeMapPassCount); + if (s_nEllenBinTreeMapPassCount == 0) + s_nEllenBinTreeMapPassCount = 500; + + s_nMichaelMapPassCount = + cfg.get_size_t("MichaelMapPassCount", s_nMichaelMapPassCount); + if (s_nMichaelMapPassCount == 0) + s_nMichaelMapPassCount = 500; + + s_nSkipListMapPassCount = + cfg.get_size_t("SkipListMapPassCount", s_nSkipListMapPassCount); + if (s_nSkipListMapPassCount == 0) + s_nSkipListMapPassCount = 500; + + 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_nFeldmanMap_HeadBits = cfg.get_size_t( "FeldmanMapHeadBits", s_nFeldmanMap_HeadBits ); + if ( s_nFeldmanMap_HeadBits == 0 ) + s_nFeldmanMap_HeadBits = 2; + + s_nFeldmanMap_ArrayBits = cfg.get_size_t( "FeldmanMapArrayBits", s_nFeldmanMap_ArrayBits ); + if ( s_nFeldmanMap_ArrayBits == 0 ) + s_nFeldmanMap_ArrayBits = 2; + + m_arrElements.resize( s_nMapSize ); + for ( size_t i = 0; i < s_nMapSize; ++i ) + m_arrElements[i] = i;; + shuffle( m_arrElements.begin(), m_arrElements.end()); + } + + void Map_Del3::TearDownTestCase() + { + m_arrElements.clear(); + } + + std::vector Map_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, Map_Del3_LF, ::testing::ValuesIn( Map_Del3_LF::get_load_factors()), get_test_parameter_name ); +#else + INSTANTIATE_TEST_CASE_P( a, Map_Del3_LF, ::testing::ValuesIn( Map_Del3_LF::get_load_factors())); +#endif +} // namespace map diff --git a/test/stress/parallel/parallel-map/del3/map_del3.h b/test/stress/parallel/parallel-map/del3/map_del3.h new file mode 100644 index 00000000..38cc8722 --- /dev/null +++ b/test/stress/parallel/parallel-map/del3/map_del3.h @@ -0,0 +1,739 @@ +/* + 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 "map_type.h" +#include + +namespace map { + + namespace { + 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 size mismatch!!!"); + } // namespace + + 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()( key_thread const& k1, 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 key_thread argument_type; + + size_t operator()( key_thread const& k ) const + { + return std::hash()(k.nKey); + } + size_t operator()( size_t k ) const + { + return std::hash()(k); + } + }; + + class Map_Del3: public cds_test::stress_fixture + { + public: + 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_nMapSize; // max map size + static size_t s_nMaxLoadFactor; // maximum load factor + static size_t s_nInsertPassCount; + static size_t s_nOriginalPassCount; + static size_t s_nPassCount; + static size_t s_nBronsonAVLTreeMapPassCount; + static size_t s_nEllenBinTreeMapPassCount; + static size_t s_nFeldmanPassCount; + static size_t s_nMichaelMapPassCount; + static size_t s_nSkipListMapPassCount; + + static size_t s_nFindThreadCount; // find thread count + + static size_t s_nCuckooInitialSize; // initial size for CuckooMap + static size_t s_nCuckooProbesetSize; // CuckooMap probeset size (only for list-based probeset) + static size_t s_nCuckooProbesetThreshold; // CuckooMap probeset threshold (0 - use default) + + static size_t s_nFeldmanMap_HeadBits; + static size_t s_nFeldmanMap_ArrayBits; + + static size_t s_nLoadFactor; // current load factor + + static std::vector m_arrElements; + + static void SetUpTestCase(); + static void TearDownTestCase(); + + template + static void prepare_array( std::vector& arr, Pred pred ) + { + arr.reserve( m_arrElements.size()); + for ( auto el : m_arrElements ) { + 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; + typedef std::pair pair_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; + Map& m_Map; + + struct update_func + { + template + void operator()( bool /*bNew*/, Q const& ) const + {} + + template + void operator()( bool /*bNew*/, Q const&, V& ) const + {} + + // FeldmanHashMap + template + void operator()( Q&, Q*) 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_Map.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, Map& map ) + : base_class( pool, inserter_thread ) + , m_Map( map ) + { + init_data(); + } + + Inserter( Inserter& src ) + : base_class( src ) + , m_Map( src.m_Map ) + { + init_data(); + } + + virtual thread * clone() + { + return new Inserter( *this ); + } + + virtual void test() + { + Map& rMap = m_Map; + Map_Del3& fixture = pool().template fixture(); + + update_func f; + + for (auto el : m_arr) { + if (el & 3) { + if (rMap.insert(key_type(el, id()))) + ++m_nInsertSuccess; + else + ++m_nInsertFailed; + } + } + 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; + } + }; + + 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; + } + + typedef key_equal equal_to; + }; + + // Deletes odd keys from [0..N) + template + class Deleter: public cds_test::thread + { + typedef cds_test::thread base_class; + Map& m_Map; + + 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, Map& map ) + : base_class( pool, deleter_thread ) + , m_Map( map ) + { + init_data(); + } + + Deleter( Deleter& src ) + : base_class( src ) + , m_Map( src.m_Map ) + { + init_data(); + } + + virtual thread * clone() + { + return new Deleter( *this ); + } + + virtual void test() + { + Map& rMap = m_Map; + + Map_Del3& fixture = pool().template fixture(); + size_t const nInsThreadCount = s_nInsThreadCount; + + for (auto el : m_arr) { + for (size_t k = 0; k < nInsThreadCount; ++k) { + if (rMap.erase(key_type(el, k))) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + } + } + m_arr.resize( 0 ); + } + }; + + // Deletes odd keys from [0..N) + template + class Extractor: public cds_test::thread + { + typedef cds_test::thread base_class; + Map& m_Map; + + 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: + Extractor( cds_test::thread_pool& pool, Map& map ) + : base_class( pool, extractor_thread ) + , m_Map( map ) + { + init_data(); + } + + Extractor( Extractor& src ) + : base_class( src ) + , m_Map( src.m_Map ) + { + init_data(); + } + + virtual thread * clone() + { + return new Extractor( *this ); + } + + virtual void test() + { + Map& rMap = m_Map; + + typename Map::guarded_ptr gp; + Map_Del3& fixture = pool().template fixture(); + size_t const nInsThreadCount = s_nInsThreadCount; + + for (auto el : m_arr) { + for (size_t k = 0; k < nInsThreadCount; ++k) { + gp = rMap.extract(key_type(el, k)); + if (gp) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + gp.release(); + } + } + m_arr.resize( 0 ); + } + }; + + template + class Extractor< cds::urcu::gc, Map > : public cds_test::thread + { + typedef cds_test::thread base_class; + Map& m_Map; + + 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: + Extractor( cds_test::thread_pool& pool, Map& map ) + : base_class( pool, extractor_thread ) + , m_Map( map ) + { + init_data(); + } + + Extractor( Extractor& src ) + : base_class( src ) + , m_Map( src.m_Map ) + { + init_data(); + } + + virtual thread * clone() + { + return new Extractor( *this ); + } + + virtual void test() + { + Map& rMap = m_Map; + Map_Del3& fixture = pool().template fixture(); + + typename Map::exempt_ptr xp; + size_t const nInsThreadCount = s_nInsThreadCount; + + for (size_t k = 0; k < nInsThreadCount; ++k) { + for (auto el : m_arr) { + if (Map::c_bExtractLockExternal) { + typename Map::rcu_lock l; + xp = rMap.extract(key_type(el, k)); + if (xp) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + } else { + xp = rMap.extract(key_type(el, k)); + if (xp) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + } + xp.release(); + } + } + m_arr.resize(0); + } + }; + + // Finds keys + template + class Observer: public cds_test::thread + { + typedef cds_test::thread base_class; + Map& m_Map; + + 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, Map& map ) + : base_class( pool, find_thread ) + , m_Map( map ) + {} + + Observer( Observer& src ) + : base_class( src ) + , m_Map( src.m_Map ) + {} + + virtual thread * clone() + { + return new Observer( *this ); + } + + virtual void test() + { + Map& map = m_Map; + Map_Del3& fixture = pool().template fixture(); + std::vector const& arr = m_arrElements; + size_t const nInsThreadCount = s_nInsThreadCount; + + for (size_t key : arr) { + if (key & 3) { + for (size_t k = 0; k < nInsThreadCount; ++k) { + if (map.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 (map.contains(key_thread(key, k))) + ++m_nFindEvenSuccess; + else + ++m_nFindEvenFailed; + } + } + } + } + }; + + protected: + template + void do_test( Map& testMap ) + { + 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, testMap ), s_nInsThreadCount ); + pool.add( new delete_thread( pool, testMap ), s_nDelThreadCount ? s_nDelThreadCount : cds::OS::topology::processor_count()); + if ( s_nFindThreadCount ) + pool.add( new observer_thread( pool, testMap ), 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( "map_size", s_nMapSize ) + << 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; + } + } + + size_t const nInitialOddKeys = ( s_nMapSize * s_nInsThreadCount ) * 3 / 4; + + EXPECT_EQ( nInsertInitFailed, 0u ); + EXPECT_EQ( nInsertInitSuccess, s_nMapSize * 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 ); + + analyze( testMap ); + } + + template + void do_test_extract( Map& testMap ) + { + typedef Inserter insert_thread; + typedef Deleter delete_thread; + typedef Extractor< typename Map::gc, Map > extract_thread; + typedef Observer observer_thread; + + cds_test::thread_pool &pool = get_pool(); + std::unique_ptr inserter( + new insert_thread(pool, testMap)); + std::unique_ptr deleter( + new delete_thread(pool, testMap)); + std::unique_ptr extractor( + new extract_thread(pool, testMap)); + std::unique_ptr observer( + new observer_thread(pool, testMap)); + + for (size_t nPass = 0; nPass < s_nPassCount; ++nPass) { + testMap.clear(); + inserter->test(); + observer->test(); + deleter->test(); + observer->test(); + testMap.clear(); + inserter->test(); + extractor->test(); + observer->test(); + } + } + + template + void analyze( Map& testMap ) + { + // All even keys must be in the map + { + for ( size_t n = 0; n < s_nMapSize; n +=4 ) { + for ( size_t i = 0; i < s_nInsThreadCount; ++i ) { + EXPECT_TRUE( testMap.contains( key_type( n, i ))) << "key=" << n << "/" << i; + } + } + } + + print_stat( propout(), testMap ); + + check_before_cleanup( testMap ); + testMap.clear(); + EXPECT_TRUE( testMap.empty()) << "map.size=" << testMap.size(); + + additional_check( testMap ); + additional_cleanup( testMap ); + } + + template + void run_test_extract() + { + static_assert( Map::c_bExtractSupported, "Map class must support extract() method" ); + + size_t nMapSize = s_nMapSize; + s_nMapSize *= s_nInsThreadCount; + + Map testMap( *this ); + + s_nMapSize = nMapSize; + do_test_extract( testMap ); + } + + template + void run_test() + { + size_t nMapSize = s_nMapSize; + s_nMapSize *= s_nInsThreadCount; + + Map testMap( *this ); + + s_nMapSize = nMapSize; + do_test( testMap ); + } + + template + void run_feldman(); + + template + void run_bronson_avl_tree(); + + template + void run_ellen_bin_tree(); + + template + void run_skip_list(); + + template + void run_michael(); + }; + + class Map_Del3_LF: public Map_Del3 + , public ::testing::WithParamInterface + { + public: + template + void run_test() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Map_Del3::run_test(); + } + + template + void run_test_extract() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Map_Del3::run_test_extract(); + } + + static std::vector get_load_factors(); + }; + +} // namespace map diff --git a/test/stress/parallel/parallel-map/del3/map_del3_bronsonavltree.cpp b/test/stress/parallel/parallel-map/del3/map_del3_bronsonavltree.cpp new file mode 100644 index 00000000..d7b3435b --- /dev/null +++ b/test/stress/parallel/parallel-map/del3/map_del3_bronsonavltree.cpp @@ -0,0 +1,45 @@ +/* + 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 "map_del3.h" +#include "map_type_bronson_avltree.h" + +namespace map { + + template + void Map_Del3::run_bronson_avl_tree() + { + Map_Del3::s_nPassCount = Map_Del3::s_nBronsonAVLTreeMapPassCount; + run_test_extract(); + } + + CDSSTRESS_BronsonAVLTreeMap( Map_Del3, run_bronson_avl_tree, key_thread, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/del3/map_del3_cuckoo.cpp b/test/stress/parallel/parallel-map/del3/map_del3_cuckoo.cpp new file mode 100644 index 00000000..4c1266bb --- /dev/null +++ b/test/stress/parallel/parallel-map/del3/map_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 "map_del3.h" +#include "map_type_cuckoo.h" + +namespace map { + +// CDSSTRESS_CuckooMap( Map_Del3, run_test, key_thread, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/del3/map_del3_ellentree.cpp b/test/stress/parallel/parallel-map/del3/map_del3_ellentree.cpp new file mode 100644 index 00000000..21c292c2 --- /dev/null +++ b/test/stress/parallel/parallel-map/del3/map_del3_ellentree.cpp @@ -0,0 +1,45 @@ +/* + 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 "map_del3.h" +#include "map_type_ellen_bintree.h" + +namespace map { + + template + void Map_Del3::run_ellen_bin_tree() + { + Map_Del3::s_nPassCount = Map_Del3::s_nEllenBinTreeMapPassCount; + run_test_extract(); + } + + CDSSTRESS_EllenBinTreeMap( Map_Del3, run_ellen_bin_tree, key_thread, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/del3/map_del3_feldman_hashmap.cpp b/test/stress/parallel/parallel-map/del3/map_del3_feldman_hashmap.cpp new file mode 100644 index 00000000..4bfa673f --- /dev/null +++ b/test/stress/parallel/parallel-map/del3/map_del3_feldman_hashmap.cpp @@ -0,0 +1,51 @@ +/* + 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 "map_del3.h" +#include "map_type_feldman_hashmap.h" + +namespace map { + + template + void Map_Del3::run_feldman() + { + typedef typename Map::traits original_traits; + struct traits: public original_traits { + enum { hash_size = sizeof( uint32_t ) + sizeof( uint16_t ) }; + }; + typedef typename Map::template rebind_traits< traits >::result map_type; + + Map_Del3::s_nPassCount = Map_Del3::s_nFeldmanPassCount; + run_test_extract(); + } + + CDSSTRESS_FeldmanHashMap_fixed( Map_Del3, run_feldman, key_thread, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/del3/map_del3_michael.cpp b/test/stress/parallel/parallel-map/del3/map_del3_michael.cpp new file mode 100644 index 00000000..e428408d --- /dev/null +++ b/test/stress/parallel/parallel-map/del3/map_del3_michael.cpp @@ -0,0 +1,45 @@ +/* + 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 "map_del3.h" +#include "map_type_michael.h" + +namespace map { + + template + void Map_Del3::run_michael() + { + Map_Del3::s_nPassCount = Map_Del3::s_nMichaelMapPassCount; + run_test_extract(); + } + + CDSSTRESS_MichaelMap( Map_Del3_LF, run_michael, key_thread, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/del3/map_del3_skip.cpp b/test/stress/parallel/parallel-map/del3/map_del3_skip.cpp new file mode 100644 index 00000000..4b02361b --- /dev/null +++ b/test/stress/parallel/parallel-map/del3/map_del3_skip.cpp @@ -0,0 +1,45 @@ +/* + 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 "map_del3.h" +#include "map_type_skip_list.h" + +namespace map { + + template + void Map_Del3::run_skip_list() + { + Map_Del3::s_nPassCount = Map_Del3::s_nSkipListMapPassCount; + run_test_extract(); + } + + CDSSTRESS_SkipListMap( Map_Del3, run_skip_list, key_thread, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/del3/map_del3_split.cpp b/test/stress/parallel/parallel-map/del3/map_del3_split.cpp new file mode 100644 index 00000000..a64ec5a9 --- /dev/null +++ b/test/stress/parallel/parallel-map/del3/map_del3_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 "map_del3.h" +#include "map_type_split_list.h" + +namespace map { + + CDSSTRESS_SplitListMap( Map_Del3_LF, run_test_extract, key_thread, size_t ) + CDSSTRESS_SplitListIterableMap( Map_Del3_LF, run_test_extract, key_thread, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/delodd/CMakeLists.txt b/test/stress/parallel/parallel-map/delodd/CMakeLists.txt new file mode 100644 index 00000000..3b7a92b2 --- /dev/null +++ b/test/stress/parallel/parallel-map/delodd/CMakeLists.txt @@ -0,0 +1,23 @@ +set(PACKAGE_NAME stress-sequential-map-delodd) + +set(CDSSTRESS_MAP_DELODD_SOURCES + ../../../main.cpp + map_delodd.cpp + map_delodd_bronsonavltree.cpp + map_delodd_cuckoo.cpp + map_delodd_ellentree.cpp + map_delodd_feldman_hashmap.cpp + map_delodd_michael.cpp + map_delodd_skip.cpp + map_delodd_split.cpp +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. +) + +add_executable(${PACKAGE_NAME} ${CDSSTRESS_MAP_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/parallel/parallel-map/delodd/map_delodd.cpp b/test/stress/parallel/parallel-map/delodd/map_delodd.cpp new file mode 100644 index 00000000..410327fe --- /dev/null +++ b/test/stress/parallel/parallel-map/delodd/map_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 "map_delodd.h" + +namespace map { + + size_t Map_DelOdd::s_nMapSize = 10000; + size_t Map_DelOdd::s_nInsThreadCount = 4; + size_t Map_DelOdd::s_nDelThreadCount = 4; + size_t Map_DelOdd::s_nExtractThreadCount = 4; + size_t Map_DelOdd::s_nFindThreadCount = 2; + size_t Map_DelOdd::s_nMaxLoadFactor = 8; + size_t Map_DelOdd::s_nInsertPassCount = 100; + + size_t Map_DelOdd::s_nCuckooInitialSize = 1024; + size_t Map_DelOdd::s_nCuckooProbesetSize = 16; + size_t Map_DelOdd::s_nCuckooProbesetThreshold = 0; + + size_t Map_DelOdd::s_nFeldmanMap_HeadBits = 10; + size_t Map_DelOdd::s_nFeldmanMap_ArrayBits = 4; + + size_t Map_DelOdd::s_nLoadFactor = 1; + std::vector Map_DelOdd::m_arrElements; + + void Map_DelOdd::SetUpTestCase() + { + cds_test::config const& cfg = get_config( "map_delodd" ); + + s_nMapSize = cfg.get_size_t( "MapSize", s_nMapSize ); + if ( s_nMapSize < 1000 ) + s_nMapSize = 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_nFeldmanMap_HeadBits = cfg.get_size_t( "FeldmanMapHeadBits", s_nFeldmanMap_HeadBits ); + if ( s_nFeldmanMap_HeadBits == 0 ) + s_nFeldmanMap_HeadBits = 2; + + s_nFeldmanMap_ArrayBits = cfg.get_size_t( "FeldmanMapArrayBits", s_nFeldmanMap_ArrayBits ); + if ( s_nFeldmanMap_ArrayBits == 0 ) + s_nFeldmanMap_ArrayBits = 2; + + m_arrElements.resize( s_nMapSize ); + for ( size_t i = 0; i < s_nMapSize; ++i ) + m_arrElements[i] = i;; + shuffle( m_arrElements.begin(), m_arrElements.end()); + } + + void Map_DelOdd::TearDownTestCase() + { + m_arrElements.clear(); + } + + std::vector Map_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, Map_DelOdd_LF, ::testing::ValuesIn( Map_DelOdd_LF::get_load_factors()), get_test_parameter_name ); +#else + INSTANTIATE_TEST_CASE_P( a, Map_DelOdd_LF, ::testing::ValuesIn( Map_DelOdd_LF::get_load_factors())); +#endif + +} // namespace map diff --git a/test/stress/parallel/parallel-map/delodd/map_delodd.h b/test/stress/parallel/parallel-map/delodd/map_delodd.h new file mode 100644 index 00000000..f4db078d --- /dev/null +++ b/test/stress/parallel/parallel-map/delodd/map_delodd.h @@ -0,0 +1,881 @@ +/* + 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 "map_type.h" +#include + +namespace map { + + namespace { + 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 size mismatch!!!"); + } // namespace + + 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()( key_thread const& k1, 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 key_thread argument_type; + + size_t operator()( key_thread const& k ) const + { + return std::hash()(k.nKey); + } + size_t operator()( size_t k ) const + { + return std::hash()(k); + } + }; + + class Map_DelOdd: public cds_test::stress_fixture + { + public: + 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_nMapSize; // max map size + 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 CuckooMap + static size_t s_nCuckooProbesetSize; // CuckooMap probeset size (only for list-based probeset) + static size_t s_nCuckooProbesetThreshold; // CuckooMap probeset threshold (0 - use default) + + static size_t s_nFeldmanMap_HeadBits; + static size_t s_nFeldmanMap_ArrayBits; + + static size_t s_nLoadFactor; // current load factor + + static std::vector m_arrElements; + + static void SetUpTestCase(); + static void TearDownTestCase(); + + template + static void prepare_array( std::vector& arr, Pred pred ) + { + arr.reserve( m_arrElements.size()); + for ( auto el : m_arrElements ) { + 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; + typedef std::pair pair_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; + Map& m_Map; + + struct update_func + { + template + void operator()( bool /*bNew*/, Q const& ) const + {} + + template + void operator()( bool /*bNew*/, Q const&, V& ) const + {} + + // FeldmanHashMap + template + void operator()( Q&, Q*) 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_Map.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, Map& map ) + : base_class( pool, inserter_thread ) + , m_Map( map ) + { + init_data(); + } + + Inserter( Inserter& src ) + : base_class( src ) + , m_Map( src.m_Map ) + { + init_data(); + } + + virtual thread * clone() + { + return new Inserter( *this ); + } + + virtual void test() + { + Map& rMap = m_Map; + Map_DelOdd& fixture = pool().template fixture(); + + update_func f; + + for ( size_t nPass = 0; nPass < s_nInsertPassCount; ++nPass ) { + if ( nPass & 1 ) { + // insert pass + for ( auto el : m_arr ) { + if ( el & 1 ) { + if ( rMap.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 ) = rMap.update( key_type( el, id()), f ); + 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; + } + }; + + 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; + } + + typedef key_equal equal_to; + }; + + // Deletes odd keys from [0..N) + template + class Deleter: public cds_test::thread + { + typedef cds_test::thread base_class; + Map& m_Map; + + 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, Map& map ) + : base_class( pool, deleter_thread ) + , m_Map( map ) + { + init_data(); + } + + Deleter( Deleter& src ) + : base_class( src ) + , m_Map( src.m_Map ) + { + init_data(); + } + + virtual thread * clone() + { + return new Deleter( *this ); + } + + virtual void test() + { + Map& rMap = m_Map; + + Map_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 ) { + if ( rMap.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 ( rMap.erase( key_type( el, k ))) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + } + } + } + } while ( fixture.m_nInsThreadCount.load( atomics::memory_order_acquire ) != 0 ); + + m_arr.resize( 0 ); + } + }; + + // Deletes odd keys from [0..N) + template + class Extractor: public cds_test::thread + { + typedef cds_test::thread base_class; + Map& m_Map; + + 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: + Extractor( cds_test::thread_pool& pool, Map& map ) + : base_class( pool, extractor_thread ) + , m_Map( map ) + { + init_data(); + } + + Extractor( Extractor& src ) + : base_class( src ) + , m_Map( src.m_Map ) + { + init_data(); + } + + virtual thread * clone() + { + return new Extractor( *this ); + } + + virtual void test() + { + Map& rMap = m_Map; + + typename Map::guarded_ptr gp; + Map_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 = rMap.extract( key_type( el, k )); + if ( gp ) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + gp.release(); + } + } + } + else { + for ( size_t k = 0; k < nInsThreadCount; ++k ) { + for ( auto el: m_arr ) { + gp = rMap.extract( key_type( el, k )); + if ( gp ) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + gp.release(); + } + } + } + } while ( fixture.m_nInsThreadCount.load( atomics::memory_order_acquire ) != 0 ); + + m_arr.resize( 0 ); + } + }; + + template + class Extractor< cds::urcu::gc, Map > : public cds_test::thread + { + typedef cds_test::thread base_class; + Map& m_Map; + + 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: + Extractor( cds_test::thread_pool& pool, Map& map ) + : base_class( pool, extractor_thread ) + , m_Map( map ) + { + init_data(); + } + + Extractor( Extractor& src ) + : base_class( src ) + , m_Map( src.m_Map ) + { + init_data(); + } + + virtual thread * clone() + { + return new Extractor( *this ); + } + + virtual void test() + { + Map& rMap = m_Map; + Map_DelOdd& fixture = pool().template fixture(); + + typename Map::exempt_ptr xp; + size_t const nInsThreadCount = s_nInsThreadCount; + + do { + if ( id() & 1 ) { + for ( size_t k = 0; k < nInsThreadCount; ++k ) { + for ( auto el: m_arr ) { + if ( Map::c_bExtractLockExternal ) { + typename Map::rcu_lock l; + xp = rMap.extract( key_type( el, k )); + if ( xp ) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + } + else { + xp = rMap.extract( key_type( el, k )); + if ( xp ) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + } + xp.release(); + } + } + } + else { + for ( auto el : m_arr ) { + for ( size_t k = 0; k < nInsThreadCount; ++k ) { + if ( Map::c_bExtractLockExternal ) { + typename Map::rcu_lock l; + xp = rMap.extract( key_type( el, k )); + if ( xp ) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + } + else { + xp = rMap.extract( key_type( el, k )); + if ( xp ) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + } + 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; + Map& m_Map; + + 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, Map& map ) + : base_class( pool, find_thread ) + , m_Map( map ) + {} + + Observer( Observer& src ) + : base_class( src ) + , m_Map( src.m_Map ) + {} + + virtual thread * clone() + { + return new Observer( *this ); + } + + virtual void test() + { + Map& map = m_Map; + Map_DelOdd& fixture = pool().template fixture(); + std::vector const& arr = m_arrElements; + size_t const nInsThreadCount = s_nInsThreadCount; + + do { + for ( size_t key : arr ) { + if ( key & 1 ) { + for ( size_t k = 0; k < nInsThreadCount; ++k ) { + if ( map.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 ( map.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( Map& testMap ) + { + 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, testMap ), s_nInsThreadCount ); + pool.add( new delete_thread( pool, testMap ), s_nDelThreadCount ? s_nDelThreadCount : cds::OS::topology::processor_count()); + if ( s_nFindThreadCount ) + pool.add( new observer_thread( pool, testMap ), 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( "map_size", s_nMapSize ) + << 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; + } + } + + size_t const nInitialOddKeys = ( s_nMapSize * s_nInsThreadCount ) / 2; + + EXPECT_EQ( nInsertInitFailed, 0u ); + EXPECT_EQ( nInsertInitSuccess, s_nMapSize * 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 ); + + analyze( testMap ); + } + + template + void do_test_extract( Map& testMap ) + { + typedef Inserter insert_thread; + typedef Deleter delete_thread; + typedef Extractor< typename Map::gc, Map > 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, testMap ), s_nInsThreadCount ); + if ( s_nDelThreadCount ) + pool.add( new delete_thread( pool, testMap ), s_nDelThreadCount ); + if ( s_nExtractThreadCount ) + pool.add( new extract_thread( pool, testMap ), s_nExtractThreadCount ); + if ( s_nFindThreadCount ) + pool.add( new observer_thread( pool, testMap ), 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( "map_size", s_nMapSize ) + << 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_nDeleteSuccess; + nExtractFailed += extractor.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_nMapSize * s_nInsThreadCount ) / 2; + + EXPECT_EQ( nInsertInitFailed, 0u ); + EXPECT_EQ( nInsertInitSuccess, s_nMapSize * 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 ); + + analyze( testMap ); + } + + template + void analyze( Map& testMap ) + { + // All even keys must be in the map + { + for ( size_t n = 0; n < s_nMapSize; n +=2 ) { + for ( size_t i = 0; i < s_nInsThreadCount; ++i ) { + EXPECT_TRUE( testMap.contains( key_type( n, i ))) << "key=" << n << "/" << i; + } + } + } + + print_stat( propout(), testMap ); + + check_before_cleanup( testMap ); + testMap.clear(); + EXPECT_TRUE( testMap.empty()) << "map.size=" << testMap.size(); + + additional_check( testMap ); + additional_cleanup( testMap ); + } + + template + void run_test_extract() + { + static_assert( Map::c_bExtractSupported, "Map class must support extract() method" ); + + size_t nMapSize = s_nMapSize; + s_nMapSize *= s_nInsThreadCount; + + Map testMap( *this ); + + s_nMapSize = nMapSize; + do_test_extract( testMap ); + } + + template + void run_test() + { + size_t nMapSize = s_nMapSize; + s_nMapSize *= s_nInsThreadCount; + + Map testMap( *this ); + + s_nMapSize = nMapSize; + do_test( testMap ); + } + + template + void run_feldman(); + }; + + class Map_DelOdd_LF: public Map_DelOdd + , public ::testing::WithParamInterface + { + public: + template + void run_test() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Map_DelOdd::run_test(); + } + + template + void run_test_extract() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Map_DelOdd::run_test_extract(); + } + + static std::vector get_load_factors(); + }; + +} // namespace map diff --git a/test/stress/parallel/parallel-map/delodd/map_delodd_bronsonavltree.cpp b/test/stress/parallel/parallel-map/delodd/map_delodd_bronsonavltree.cpp new file mode 100644 index 00000000..ec1ffe03 --- /dev/null +++ b/test/stress/parallel/parallel-map/delodd/map_delodd_bronsonavltree.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 "map_delodd.h" +#include "map_type_bronson_avltree.h" + +namespace map { + + CDSSTRESS_BronsonAVLTreeMap( Map_DelOdd, run_test_extract, key_thread, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/delodd/map_delodd_cuckoo.cpp b/test/stress/parallel/parallel-map/delodd/map_delodd_cuckoo.cpp new file mode 100644 index 00000000..f9b1b400 --- /dev/null +++ b/test/stress/parallel/parallel-map/delodd/map_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 "map_delodd.h" +#include "map_type_cuckoo.h" + +namespace map { + +// CDSSTRESS_CuckooMap( Map_DelOdd, run_test, key_thread, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/delodd/map_delodd_ellentree.cpp b/test/stress/parallel/parallel-map/delodd/map_delodd_ellentree.cpp new file mode 100644 index 00000000..91707858 --- /dev/null +++ b/test/stress/parallel/parallel-map/delodd/map_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 "map_delodd.h" +#include "map_type_ellen_bintree.h" + +namespace map { + + CDSSTRESS_EllenBinTreeMap( Map_DelOdd, run_test_extract, key_thread, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/delodd/map_delodd_feldman_hashmap.cpp b/test/stress/parallel/parallel-map/delodd/map_delodd_feldman_hashmap.cpp new file mode 100644 index 00000000..aa2a5fac --- /dev/null +++ b/test/stress/parallel/parallel-map/delodd/map_delodd_feldman_hashmap.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 "map_delodd.h" +#include "map_type_feldman_hashmap.h" + +namespace map { + + template + void Map_DelOdd::run_feldman() + { + typedef typename Map::traits original_traits; + struct traits: public original_traits { + enum { hash_size = sizeof( uint32_t ) + sizeof( uint16_t ) }; + }; + typedef typename Map::template rebind_traits< traits >::result map_type; + + run_test_extract(); + } + + CDSSTRESS_FeldmanHashMap_fixed( Map_DelOdd, run_feldman, key_thread, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/delodd/map_delodd_michael.cpp b/test/stress/parallel/parallel-map/delodd/map_delodd_michael.cpp new file mode 100644 index 00000000..49d3f435 --- /dev/null +++ b/test/stress/parallel/parallel-map/delodd/map_delodd_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 "map_delodd.h" +#include "map_type_michael.h" + +namespace map { + + CDSSTRESS_MichaelMap( Map_DelOdd_LF, run_test_extract, key_thread, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/delodd/map_delodd_skip.cpp b/test/stress/parallel/parallel-map/delodd/map_delodd_skip.cpp new file mode 100644 index 00000000..139dc366 --- /dev/null +++ b/test/stress/parallel/parallel-map/delodd/map_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 "map_delodd.h" +#include "map_type_skip_list.h" + +namespace map { + + CDSSTRESS_SkipListMap( Map_DelOdd, run_test_extract, key_thread, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/delodd/map_delodd_split.cpp b/test/stress/parallel/parallel-map/delodd/map_delodd_split.cpp new file mode 100644 index 00000000..8553b279 --- /dev/null +++ b/test/stress/parallel/parallel-map/delodd/map_delodd_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 "map_delodd.h" +#include "map_type_split_list.h" + +namespace map { + + CDSSTRESS_SplitListMap( Map_DelOdd_LF, run_test_extract, key_thread, size_t ) + CDSSTRESS_SplitListIterableMap( Map_DelOdd_LF, run_test_extract, key_thread, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/find_string/CMakeLists.txt b/test/stress/parallel/parallel-map/find_string/CMakeLists.txt new file mode 100644 index 00000000..610b997a --- /dev/null +++ b/test/stress/parallel/parallel-map/find_string/CMakeLists.txt @@ -0,0 +1,25 @@ +set(PACKAGE_NAME stress-sequential-map-find-string) + +set(CDSSTRESS_MAP_FIND_STRING_SOURCES + ../../../main.cpp + map_find_string.cpp + #map_find_string_cuckoo.cpp + map_find_string_split.cpp + map_find_string_bronsonavltree.cpp + map_find_string_ellentree.cpp + map_find_string_feldman_hashset.cpp + map_find_string_michael.cpp + map_find_string_skip.cpp + #map_find_string_std.cpp + #map_find_string_striped.cpp +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. +) + +add_executable(${PACKAGE_NAME} ${CDSSTRESS_MAP_FIND_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/parallel/parallel-map/find_string/map_find_string.cpp b/test/stress/parallel/parallel-map/find_string/map_find_string.cpp new file mode 100644 index 00000000..5a1a9876 --- /dev/null +++ b/test/stress/parallel/parallel-map/find_string/map_find_string.cpp @@ -0,0 +1,255 @@ +/* + 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 "map_find_string.h" +#include + +namespace map { + + size_t Map_find_string::s_nThreadCount = 8; + size_t Map_find_string::s_nMapSize = 10000000; + size_t Map_find_string::s_nMaxLoadFactor = 8; + size_t Map_find_string::s_nPercentExists = 50; + size_t Map_find_string::s_nPassCount = 2; + size_t Map_find_string::s_nFeldmanPassCount = 100; + size_t Map_find_string::s_nBronsonAVLTreeMapPassCount = 100; + size_t Map_find_string::s_nEllenBinTreeMapPassCount = 100; + size_t Map_find_string::s_nMichaelMapPassCount = 100; + size_t Map_find_string::s_nSkipListMapPassCount = 100; + size_t Map_find_string::s_nSplitListMapPassCount = 100; + + size_t Map_find_string::s_nCuckooInitialSize = 1024; + size_t Map_find_string::s_nCuckooProbesetSize = 16; + size_t Map_find_string::s_nCuckooProbesetThreshold = 0; + + size_t Map_find_string::s_nFeldmanMap_HeadBits = 10; + size_t Map_find_string::s_nFeldmanMap_ArrayBits = 4; + + + size_t Map_find_string::s_nLoadFactor = 1; + Map_find_string::value_vector Map_find_string::s_Data; + std::vector Map_find_string::s_arrString; + + void Map_find_string::setup_test_case() + { + cds_test::config const &cfg = + get_config("sequential_real_map_find_string"); + + s_nMapSize = cfg.get_size_t("MapSize", s_nMapSize); + if (s_nMapSize < 1000) + s_nMapSize = 1000; + + s_nThreadCount = cfg.get_size_t("ThreadCount", s_nThreadCount); + if (s_nThreadCount == 0) + s_nThreadCount = 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_nBronsonAVLTreeMapPassCount = cfg.get_size_t( + "BronsonAVLTreeMapPassCount", s_nBronsonAVLTreeMapPassCount); + if (s_nBronsonAVLTreeMapPassCount == 0) + s_nBronsonAVLTreeMapPassCount = 500; + + s_nEllenBinTreeMapPassCount = cfg.get_size_t("EllenBinTreeMapPassCount", + s_nEllenBinTreeMapPassCount); + if (s_nEllenBinTreeMapPassCount == 0) + s_nEllenBinTreeMapPassCount = 500; + + s_nMichaelMapPassCount = + cfg.get_size_t("MichaelMapPassCount", s_nMichaelMapPassCount); + if (s_nMichaelMapPassCount == 0) + s_nMichaelMapPassCount = 500; + + s_nSkipListMapPassCount = + cfg.get_size_t("SkipListMapPassCount", s_nSkipListMapPassCount); + if (s_nSkipListMapPassCount == 0) + s_nSkipListMapPassCount = 500; + + s_nSplitListMapPassCount = + cfg.get_size_t("SplitListMapPassCount", s_nSplitListMapPassCount); + if (s_nSplitListMapPassCount == 0) + s_nSplitListMapPassCount = 500; + + s_nPercentExists = cfg.get_size_t("PercentExists", s_nPercentExists); + if (s_nPercentExists > 100) + s_nPercentExists = 100; + else if (s_nPercentExists < 1) + s_nPercentExists = 1; + + 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_nFeldmanMap_HeadBits = + cfg.get_size_t("FeldmanMapHeadBits", s_nFeldmanMap_HeadBits); + if (s_nFeldmanMap_HeadBits == 0) + s_nFeldmanMap_HeadBits = 2; + + s_nFeldmanMap_ArrayBits = + cfg.get_size_t("FeldmanMapArrayBits", s_nFeldmanMap_ArrayBits); + if (s_nFeldmanMap_ArrayBits == 0) + s_nFeldmanMap_ArrayBits = 2; + + s_arrString = load_dictionary(); + } + + void Map_find_string::TearDownTestCase() + { + s_arrString.clear(); + s_Data.clear(); + } + + void Map_find_string::SetUpTestCase() + { + setup_test_case(); + + s_Data.clear(); + + size_t nSize = s_arrString.size(); + if ( nSize > s_nMapSize ) + nSize = s_nMapSize; + s_Data.reserve( nSize ); + + size_t nActualSize = 0; + for ( size_t i = 0; i < nSize; ++i ) { + bool bExists = rand( 100 ) <= s_nPercentExists; + if ( bExists ) + ++nActualSize; + s_Data.push_back( { &s_arrString.at( i ), bExists } ); + } + s_nMapSize = nActualSize; + } + + template + void Map_find_string::fill_string_array() + { + typedef Hash hasher; + typedef typename hasher::result_type hash_type; + + std::map mapHash; + s_Data.clear(); + + size_t nSize = s_arrString.size(); + if ( nSize > s_nMapSize ) + nSize = s_nMapSize; + s_Data.reserve( nSize ); + + size_t nActualSize = 0; + size_t nDiffHash = 0; + hasher h; + for ( size_t i = 0; i < s_arrString.size(); ++i ) { + hash_type hash = h( s_arrString.at( i )); + if ( mapHash.insert( std::make_pair( hash, i )).second ) { + if ( ++nDiffHash >= nSize ) + break; + bool bExists = rand( 100 ) <= s_nPercentExists; + if ( bExists ) + ++nActualSize; + s_Data.push_back( { &s_arrString.at( i ), bExists } ); + } + } + s_nMapSize = nActualSize; + + } + + void Map_find_string_stdhash::SetUpTestCase() + { + setup_test_case(); + fill_string_array>(); + } + +#if CDS_BUILD_BITS == 64 + void Map_find_string_city32::SetUpTestCase() + { + setup_test_case(); + fill_string_array(); + } + + void Map_find_string_city64::SetUpTestCase() + { + setup_test_case(); + fill_string_array(); + } + + void Map_find_string_city128::SetUpTestCase() + { + setup_test_case(); + fill_string_array(); + } + +#endif + + std::vector Map_find_string::get_load_factors() + { + cds_test::config const& cfg = get_config( "map_find_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, Map_find_string_LF, ::testing::ValuesIn( Map_find_string::get_load_factors()), get_test_parameter_name ); +#else + INSTANTIATE_TEST_CASE_P( a, Map_find_string_LF, ::testing::ValuesIn( Map_find_string::get_load_factors())); +#endif + + +} // namespace map diff --git a/test/stress/parallel/parallel-map/find_string/map_find_string.h b/test/stress/parallel/parallel-map/find_string/map_find_string.h new file mode 100644 index 00000000..61eb2199 --- /dev/null +++ b/test/stress/parallel/parallel-map/find_string/map_find_string.h @@ -0,0 +1,289 @@ +/* + 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 "map_type.h" + +namespace map { + + class Map_find_string: public cds_test::stress_fixture + { + public: + static size_t s_nThreadCount; // thread count + static size_t s_nMapSize; // map size (count of searching item) + static size_t s_nPercentExists; // percent of existing keys in searching sequence + static size_t s_nPassCount; + static size_t s_nBronsonAVLTreeMapPassCount; + static size_t s_nEllenBinTreeMapPassCount; + static size_t s_nFeldmanPassCount; + static size_t s_nMichaelMapPassCount; + static size_t s_nSkipListMapPassCount; + static size_t s_nSplitListMapPassCount; + + static size_t s_nMaxLoadFactor; // maximum load factor + + static size_t s_nCuckooInitialSize; // initial size for CuckooMap + static size_t s_nCuckooProbesetSize; // CuckooMap probeset size (only for list-based probeset) + static size_t s_nCuckooProbesetThreshold; // CUckooMap probeset threshold (o - use default) + + static size_t s_nFeldmanMap_HeadBits; + static size_t s_nFeldmanMap_ArrayBits; + + static size_t s_nLoadFactor; // current load factor + + typedef std::string key_type; + struct value_type { + std::string const* pKey; + bool bExists ; // true - key in map, false - key not in map + }; + + typedef std::vector value_vector; + static std::vector s_arrString; + static value_vector s_Data; + + static void SetUpTestCase(); + static void TearDownTestCase(); + + static void setup_test_case(); + static std::vector get_load_factors(); + + private: + template + static bool check_result( Iterator const& it, Map const& map ) + { + return it != map.end(); + } + template + static bool check_result( bool b, Map const& ) + { + return b; + } + + template + class Worker: public cds_test::thread + { + typedef cds_test::thread base_class; + Map& m_Map; + + public: + struct Stat { + size_t nSuccess = 0; + size_t nFailed = 0; + }; + + Stat m_KeyExists; + Stat m_KeyNotExists; + + public: + Worker( cds_test::thread_pool& pool, Map& map ) + : base_class( pool ) + , m_Map( map ) + , m_KeyExists() + , m_KeyNotExists() + {} + + Worker( Worker& src ) + : base_class( src ) + , m_Map( src.m_Map ) + , m_KeyExists() + , m_KeyNotExists() + {} + + virtual thread * clone() + { + return new Worker( *this ); + } + virtual void test() + { + size_t const nPassCount = s_nPassCount; + + Map& rMap = m_Map; + for (size_t nPass = 0; nPass < nPassCount; ++nPass) { + auto itEnd = s_Data.cend(); + for (auto it = s_Data.cbegin(); it != itEnd; ++it) { + auto bFound = rMap.contains(*(it->pKey)); + if (it->bExists) { + if (check_result(bFound, rMap)) + ++m_KeyExists.nSuccess; + else + ++m_KeyExists.nFailed; + } else { + if (check_result(bFound, rMap)) + ++m_KeyNotExists.nFailed; + else + ++m_KeyNotExists.nSuccess; + } + } + } + } + }; + + protected: + template + static void fill_string_array(); + + template + void test( Map& testMap ) + { + typedef Worker worker; + + // Fill the map + for ( size_t i = 0; i < s_Data.size(); ++i ) { + // All keys in arrData are unique, insert() must be successful + if ( s_Data[i].bExists ) { + EXPECT_TRUE( check_result( testMap.insert( *(s_Data[i].pKey), s_Data[i] ), testMap )); + } + } + + cds_test::thread_pool &pool = get_pool(); + std::unique_ptr worker_thread(new worker(pool, testMap)); + worker_thread->test(); + + testMap.clear(); + additional_cleanup(testMap); + } + + template + void run_test() + { + ASSERT_GT( s_Data.size(), 0u ); + + Map testMap( *this ); + test( testMap ); + } + + template + void run_bronson_avl_tree() { + Map_find_string::s_nPassCount = + Map_find_string::s_nBronsonAVLTreeMapPassCount; + run_test(); + } + + template + void run_ellen_bin_tree() { + Map_find_string::s_nPassCount = + Map_find_string::s_nEllenBinTreeMapPassCount; + run_test(); + } + + template + void run_feldman() { + Map_find_string::s_nPassCount = + Map_find_string::s_nFeldmanPassCount; + run_test(); + } + + template + void run_michael() { + Map_find_string::s_nPassCount = + Map_find_string::s_nMichaelMapPassCount; + run_test(); + } + + template + void run_skip_list() { + Map_find_string::s_nPassCount = + Map_find_string::s_nSkipListMapPassCount; + run_test(); + } + + template + void run_split_list() { + Map_find_string::s_nPassCount = + Map_find_string::s_nSplitListMapPassCount; + run_test(); + } + + }; + + class Map_find_string_stdhash: public Map_find_string + { + public: + static void SetUpTestCase(); + + template + void run_test() + { + Map_find_string::run_test(); + } + }; + +#if CDS_BUILD_BITS == 64 + class Map_find_string_city32: public Map_find_string + { + public: + static void SetUpTestCase(); + + template + void run_test() + { + Map_find_string::run_test(); + } + }; + + class Map_find_string_city64: public Map_find_string + { + public: + static void SetUpTestCase(); + + template + void run_test() + { + Map_find_string::run_test(); + } + }; + + class Map_find_string_city128: public Map_find_string + { + public: + static void SetUpTestCase(); + + template + void run_test() + { + Map_find_string::run_test(); + } + }; + +#endif // #if CDS_BUILD_BITS == 64 + + class Map_find_string_LF: public Map_find_string + , public ::testing::WithParamInterface + { + public: + template + void run_test() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Map_find_string::run_test(); + } + }; + +} // namespace map diff --git a/test/stress/parallel/parallel-map/find_string/map_find_string_bronsonavltree.cpp b/test/stress/parallel/parallel-map/find_string/map_find_string_bronsonavltree.cpp new file mode 100644 index 00000000..4f97a46a --- /dev/null +++ b/test/stress/parallel/parallel-map/find_string/map_find_string_bronsonavltree.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 "map_find_string.h" +#include "map_type_bronson_avltree.h" + +namespace map { + + CDSSTRESS_BronsonAVLTreeMap( Map_find_string, run_bronson_avl_tree, std::string, Map_find_string::value_type ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/find_string/map_find_string_cuckoo.cpp b/test/stress/parallel/parallel-map/find_string/map_find_string_cuckoo.cpp new file mode 100644 index 00000000..4e4bb1db --- /dev/null +++ b/test/stress/parallel/parallel-map/find_string/map_find_string_cuckoo.cpp @@ -0,0 +1,41 @@ +/* + 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 "map_find_string.h" +#include "map_type_cuckoo.h" + +namespace map { + +// CDSSTRESS_CuckooMap( Map_find_string, run_test, std::string, Map_find_string::value_type ) +#if CDS_BUILD_BITS == 64 +// CDSSTRESS_CuckooMap_city64( Map_find_string, run_test, std::string, Map_find_string::value_type ) +#endif + +} // namespace map diff --git a/test/stress/parallel/parallel-map/find_string/map_find_string_ellentree.cpp b/test/stress/parallel/parallel-map/find_string/map_find_string_ellentree.cpp new file mode 100644 index 00000000..7b1453d5 --- /dev/null +++ b/test/stress/parallel/parallel-map/find_string/map_find_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 "map_find_string.h" +#include "map_type_ellen_bintree.h" + +namespace map { + + CDSSTRESS_EllenBinTreeMap( Map_find_string, run_ellen_bin_tree, std::string, Map_find_string::value_type ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/find_string/map_find_string_feldman_hashset.cpp b/test/stress/parallel/parallel-map/find_string/map_find_string_feldman_hashset.cpp new file mode 100644 index 00000000..dcb0c70e --- /dev/null +++ b/test/stress/parallel/parallel-map/find_string/map_find_string_feldman_hashset.cpp @@ -0,0 +1,42 @@ +/* + 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 "map_find_string.h" +#include "map_type_feldman_hashmap.h" + +namespace map { + + CDSSTRESS_FeldmanHashMap_stdhash( Map_find_string_stdhash, run_feldman, std::string, Map_find_string::value_type ) +#if CDS_BUILD_BITS == 64 + CDSSTRESS_FeldmanHashMap_city64( Map_find_string_city64, run_feldman, std::string, Map_find_string::value_type ) + CDSSTRESS_FeldmanHashMap_city128( Map_find_string_city128, run_feldman, std::string, Map_find_string::value_type ) +#endif + +} // namespace map diff --git a/test/stress/parallel/parallel-map/find_string/map_find_string_michael.cpp b/test/stress/parallel/parallel-map/find_string/map_find_string_michael.cpp new file mode 100644 index 00000000..e6325c2a --- /dev/null +++ b/test/stress/parallel/parallel-map/find_string/map_find_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 "map_find_string.h" +#include "map_type_michael.h" + +namespace map { + + CDSSTRESS_MichaelMap( Map_find_string_LF, run_michael, std::string, Map_find_string::value_type ) + CDSSTRESS_MichaelMap_nogc( Map_find_string_LF, run_michael, std::string, Map_find_string::value_type ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/find_string/map_find_string_skip.cpp b/test/stress/parallel/parallel-map/find_string/map_find_string_skip.cpp new file mode 100644 index 00000000..0e947bf0 --- /dev/null +++ b/test/stress/parallel/parallel-map/find_string/map_find_string_skip.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 "map_find_string.h" +#include "map_type_skip_list.h" + +namespace map { + + CDSSTRESS_SkipListMap( Map_find_string, run_skip_list, std::string, Map_find_string::value_type ) + CDSSTRESS_SkipListMap_nogc( Map_find_string, run_skip_list, std::string, Map_find_string::value_type ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/find_string/map_find_string_split.cpp b/test/stress/parallel/parallel-map/find_string/map_find_string_split.cpp new file mode 100644 index 00000000..6e33e01a --- /dev/null +++ b/test/stress/parallel/parallel-map/find_string/map_find_string_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 "map_find_string.h" +#include "map_type_split_list.h" + +namespace map { + + CDSSTRESS_SplitListMap( Map_find_string_LF, run_split_list, std::string, Map_find_string::value_type ) + CDSSTRESS_SplitListIterableMap( Map_find_string_LF, run_split_list, std::string, Map_find_string::value_type ) + CDSSTRESS_SplitListMap_nogc( Map_find_string_LF, run_split_list, std::string, Map_find_string::value_type ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/find_string/map_find_string_std.cpp b/test/stress/parallel/parallel-map/find_string/map_find_string_std.cpp new file mode 100644 index 00000000..0f1081fb --- /dev/null +++ b/test/stress/parallel/parallel-map/find_string/map_find_string_std.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 "map_find_string.h" +#include "map_type_std.h" + +namespace map { + +// CDSSTRESS_StdMap( Map_find_string, run_test, std::string, Map_find_string::value_type ) +// CDSSTRESS_StdMap_nolock( Map_find_string, run_test, std::string, Map_find_string::value_type ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/find_string/map_find_string_striped.cpp b/test/stress/parallel/parallel-map/find_string/map_find_string_striped.cpp new file mode 100644 index 00000000..aefd6386 --- /dev/null +++ b/test/stress/parallel/parallel-map/find_string/map_find_string_striped.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 "map_find_string.h" +#include "map_type_striped.h" + +namespace map { + +// CDSSTRESS_StripedMap( Map_find_string_LF, run_test, std::string, Map_find_string::value_type ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_func/CMakeLists.txt b/test/stress/parallel/parallel-map/insdel_func/CMakeLists.txt new file mode 100644 index 00000000..8a0846f9 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_func/CMakeLists.txt @@ -0,0 +1,24 @@ +set(PACKAGE_NAME stress-sequential-map-insdel-func) + +set(CDSSTRESS_MAP_INSDEL_FUNC_SOURCES + ../../../main.cpp + map_insdel_func.cpp + map_insdel_func_bronsonavltree.cpp + map_insdel_func_cuckoo.cpp + map_insdel_func_ellentree.cpp + map_insdel_func_feldman_hashset.cpp + map_insdel_func_michael.cpp + map_insdel_func_skip.cpp + map_insdel_func_split.cpp + map_insdel_func_striped.cpp +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. +) + +add_executable(${PACKAGE_NAME} ${CDSSTRESS_MAP_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/parallel/parallel-map/insdel_func/map_insdel_func.cpp b/test/stress/parallel/parallel-map/insdel_func/map_insdel_func.cpp new file mode 100644 index 00000000..a5245f3d --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_func/map_insdel_func.cpp @@ -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. +*/ + +#include "map_insdel_func.h" + +namespace map { + + size_t Map_InsDel_func::s_nMapSize = 1000000; // map size + size_t Map_InsDel_func::s_nInsertThreadCount = 4; // count of insertion thread + size_t Map_InsDel_func::s_nDeleteThreadCount = 4; // count of deletion thread + size_t Map_InsDel_func::s_nUpdateThreadCount = 4; // count of ensure thread + size_t Map_InsDel_func::s_nThreadPassCount = 4; // pass count for each thread + size_t Map_InsDel_func::s_nMaxLoadFactor = 8; // maximum load factor + + size_t Map_InsDel_func::s_nCuckooInitialSize = 1024;// initial size for CuckooSet + size_t Map_InsDel_func::s_nCuckooProbesetSize = 16; // CuckooSet probeset size (only for list-based probeset) + size_t Map_InsDel_func::s_nCuckooProbesetThreshold = 0; // CUckooSet probeset threshold (0 - use default) + + size_t Map_InsDel_func::s_nFeldmanMap_HeadBits = 10; + size_t Map_InsDel_func::s_nFeldmanMap_ArrayBits = 4; + + size_t Map_InsDel_func::s_nLoadFactor = 1; + Map_InsDel_func::key_array Map_InsDel_func::s_arrKeys; + + void Map_InsDel_func::SetUpTestCase() + { + cds_test::config const& cfg = get_config( "map_insdel_func" ); + + s_nMapSize = cfg.get_size_t( "MapSize", s_nMapSize ); + if ( s_nMapSize < 1000 ) + s_nMapSize = 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_nFeldmanMap_HeadBits = cfg.get_size_t( "FeldmanMapHeadBits", s_nFeldmanMap_HeadBits ); + if ( s_nFeldmanMap_HeadBits == 0 ) + s_nFeldmanMap_HeadBits = 2; + + s_nFeldmanMap_ArrayBits = cfg.get_size_t( "FeldmanMapArrayBits", s_nFeldmanMap_ArrayBits ); + if ( s_nFeldmanMap_ArrayBits == 0 ) + s_nFeldmanMap_ArrayBits = 2; + + s_arrKeys.clear(); + s_arrKeys.reserve( s_nMapSize ); + for ( size_t i = 0; i < s_nMapSize; ++i ) + s_arrKeys.push_back( i ); + shuffle( s_arrKeys.begin(), s_arrKeys.end()); + } + + void Map_InsDel_func::TearDownTestCase() + { + s_arrKeys.clear(); + } + + std::vector Map_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, Map_InsDel_func_LF, ::testing::ValuesIn( Map_InsDel_func_LF::get_load_factors()), get_test_parameter_name ); +#else + INSTANTIATE_TEST_CASE_P( a, Map_InsDel_func_LF, ::testing::ValuesIn( Map_InsDel_func_LF::get_load_factors())); +#endif + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_func/map_insdel_func.h b/test/stress/parallel/parallel-map/insdel_func/map_insdel_func.h new file mode 100644 index 00000000..b2605ca5 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_func/map_insdel_func.h @@ -0,0 +1,572 @@ +/* + 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 "map_type.h" + +namespace map { + + class Map_InsDel_func: public cds_test::stress_fixture + { + public: + static size_t s_nMapSize; // map 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 CuckooMap + static size_t s_nCuckooProbesetSize; // CuckooMap probeset size (only for list-based probeset) + static size_t s_nCuckooProbesetThreshold; // CuckooMap probeset threshold (o - use default) + + static size_t s_nFeldmanMap_HeadBits; + static size_t s_nFeldmanMap_ArrayBits; + + static size_t s_nLoadFactor; // current load factor + + static void SetUpTestCase(); + static void TearDownTestCase(); + + typedef size_t key_type; + struct value_type { + size_t nKey; + size_t nData; + size_t nUpdateCall; + atomics::atomic bInitialized; + cds::OS::ThreadId threadId; // inserter thread id + + typedef cds::sync::spin_lock< cds::backoff::pause > lock_type; + mutable lock_type m_access; + + value_type() + : nKey(0) + , nData(0) + , nUpdateCall(0) + , bInitialized( false ) + , threadId( cds::OS::get_current_thread_id()) + {} + + value_type( value_type const& s ) + : nKey(s.nKey) + , nData(s.nData) + , nUpdateCall( s.nUpdateCall ) + , bInitialized( s.bInitialized.load(atomics::memory_order_relaxed)) + , threadId( cds::OS::get_current_thread_id()) + , m_access() + {} + + // boost::container::flat_map requires operator = + // cppcheck-suppress operatorEqVarError + value_type& operator=( value_type const& v ) + { + nKey = v.nKey; + nData = v.nData; + nUpdateCall = v.nUpdateCall; + threadId = v.threadId; + bInitialized.store(v.bInitialized.load(atomics::memory_order_relaxed), atomics::memory_order_relaxed); + + return *this; + } + }; + + typedef std::vector key_array; + static key_array s_arrKeys; + + protected: + enum { + insert_thread, + delete_thread, + update_thread + }; + + template + class Inserter: public cds_test::thread + { + typedef cds_test::thread base_class; + Map& m_Map; + + struct insert_functor { + size_t nTestFunctorRef; + + insert_functor() + : nTestFunctorRef(0) + {} + + template + void operator()( Pair& val ) + { + operator()( val.first, val.second ); + } + + template + void operator()( Key const& key, Val& v ) + { + std::unique_lock< typename value_type::lock_type> ac( v.m_access ); + + v.nKey = key; + v.nData = key * 8; + + ++nTestFunctorRef; + v.bInitialized.store( true, atomics::memory_order_relaxed); + } + }; + + public: + size_t m_nInsertSuccess = 0; + size_t m_nInsertFailed = 0; + + size_t m_nTestFunctorRef = 0; + + public: + Inserter( cds_test::thread_pool& pool, Map& map ) + : base_class( pool, insert_thread ) + , m_Map( map ) + {} + + Inserter( Inserter& src ) + : base_class( src ) + , m_Map( src.m_Map ) + {} + + virtual thread * clone() + { + return new Inserter( *this ); + } + + virtual void test() + { + Map& rMap = m_Map; + + // func is passed by reference + insert_functor func; + size_t const nPassCount = s_nThreadPassCount; + + if ( id() & 1 ) { + for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) { + for ( key_array::const_iterator it = s_arrKeys.begin(), itEnd = s_arrKeys.end(); it != itEnd; ++it ) { + if ( rMap.insert_with( *it, std::ref(func))) + ++m_nInsertSuccess; + else + ++m_nInsertFailed; + } + } + } + else { + for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) { + for ( key_array::const_reverse_iterator it = s_arrKeys.rbegin(), itEnd = s_arrKeys.rend(); it != itEnd; ++it ) { + if ( rMap.insert_with( *it, 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; + Map& m_Map; + + struct update_functor { + size_t nCreated = 0; + size_t nModified = 0; + + update_functor() = default; + + template + void operator()( bool /*bNew*/, Key const& key, Val& v ) + { + std::unique_lock ac( v.m_access ); + if ( !v.bInitialized.load( atomics::memory_order_acquire )) { + ++nCreated; + v.nKey = key; + v.nData = key * 8; + v.bInitialized.store( true, atomics::memory_order_relaxed); + } + else { + ++v.nUpdateCall; + ++nModified; + } + } + + template + void operator()( bool bNew, Pair& val ) + { + operator()( bNew, val.first, val.second ); + } + + // For FeldmanHashMap, IterableList + template + void operator()( Val& cur, Val * old ) + { + if ( old ) { + // If a key exists, FeldmanHashMap creates a new node too + // We should manually copy important values from old to cur + std::unique_lock ac( cur.second.m_access ); + cur.second.nKey = cur.first; + cur.second.nData = cur.first * 8; + cur.second.bInitialized.store( true, atomics::memory_order_release ); + } + operator()( old == nullptr, cur.first, cur.second ); + } + + private: + update_functor(const update_functor& ) = delete; + }; + + 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, Map& map ) + : base_class( pool, update_thread ) + , m_Map( map ) + {} + + Updater( Updater& src ) + : base_class( src ) + , m_Map( src.m_Map ) + {} + + virtual thread * clone() + { + return new Updater( *this ); + } + + virtual void test() + { + Map& rMap = m_Map; + + update_functor func; + size_t const nPassCount = s_nThreadPassCount; + + if ( id() & 1 ) { + for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) { + for ( key_array::const_iterator it = s_arrKeys.begin(), itEnd = s_arrKeys.end(); it != itEnd; ++it ) { + std::pair ret = rMap.update( *it, std::ref( func )); + if ( ret.first ) { + if ( ret.second ) + ++m_nUpdateCreated; + else + ++m_nUpdateExisted; + } + else + ++m_nUpdateFailed; + } + } + } + else { + for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) { + for ( key_array::const_reverse_iterator it = s_arrKeys.rbegin(), itEnd = s_arrKeys.rend(); it != itEnd; ++it ) { + std::pair ret = rMap.update( *it, std::ref( func )); + 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 + { + Map& m_Map; + typedef cds_test::thread base_class; + typedef typename Map::mapped_type value_type; + + struct value_container + { + size_t nKeyExpected; + + size_t nSuccessItem; + size_t nFailedItem; + + value_container() + : nKeyExpected() + , nSuccessItem(0) + , nFailedItem(0) + {} + }; + + struct erase_functor { + value_container m_cnt; + + template + void operator()( Key const& /*key*/, Val& v ) + { + while ( true ) { + if ( v.bInitialized.load( atomics::memory_order_relaxed )) { + std::unique_lock< typename value_type::lock_type> ac( v.m_access ); + + if ( m_cnt.nKeyExpected == v.nKey && m_cnt.nKeyExpected * 8 == v.nData ) + ++m_cnt.nSuccessItem; + else + ++m_cnt.nFailedItem; + v.nData++; + v.nKey = 0; + break; + } + else + cds::backoff::yield()(); + } + } + + template + void operator ()( Pair& item ) + { + operator()( item.first, item.second ); + } + }; + + 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, Map& map ) + : base_class( pool, delete_thread ) + , m_Map( map ) + {} + + Deleter( Deleter& src ) + : base_class( src ) + , m_Map( src.m_Map ) + {} + + virtual thread * clone() + { + return new Deleter( *this ); + } + + virtual void test() + { + Map& rMap = m_Map; + + erase_functor func; + size_t const nPassCount = s_nThreadPassCount; + + if ( id() & 1 ) { + for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) { + for ( key_array::const_iterator it = s_arrKeys.cbegin(), itEnd = s_arrKeys.cend(); it != itEnd; ++it ) { + func.m_cnt.nKeyExpected = *it; + if ( rMap.erase( *it, std::ref(func))) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + } + } + } + else { + for ( size_t nPass = 0; nPass < nPassCount; ++nPass ) { + for ( key_array::const_reverse_iterator it = s_arrKeys.crbegin(), itEnd = s_arrKeys.crend(); it != itEnd; ++it ) { + func.m_cnt.nKeyExpected = *it; + if ( rMap.erase( *it, std::ref(func))) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + } + } + } + + m_nValueSuccess = func.m_cnt.nSuccessItem; + m_nValueFailed = func.m_cnt.nFailedItem; + } + }; + + protected: + + template + void do_test( Map& testMap ) + { + typedef Inserter inserter; + typedef Deleter deleter; + typedef Updater updater; + + cds_test::thread_pool& pool = get_pool(); + pool.add( new inserter( pool, testMap ), s_nInsertThreadCount ); + pool.add( new deleter( pool, testMap ), s_nDeleteThreadCount ); + if ( s_nUpdateThreadCount ) + pool.add( new updater( pool, testMap ), s_nUpdateThreadCount ); + + propout() << std::make_pair( "insert_thread_count", s_nInsertThreadCount ) + << std::make_pair( "delete_thread_count", s_nDeleteThreadCount ) + << std::make_pair( "update_thread_count", s_nUpdateThreadCount ) + << std::make_pair( "pass_count", s_nThreadPassCount ) + << std::make_pair( "map_size", s_nMapSize ); + + 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 nInsFuncCalled = 0; + + for ( size_t i = 0; i < pool.size(); ++i ) { + cds_test::thread& thr = pool.get( i ); + switch ( thr.type()) { + case insert_thread: + { + inserter& t = static_cast( thr ); + nInsertSuccess += t.m_nInsertSuccess; + nInsertFailed += t.m_nInsertFailed; + nInsFuncCalled += t.m_nTestFunctorRef; + } + break; + case delete_thread: + { + deleter& t = static_cast(thr); + nDeleteSuccess += t.m_nDeleteSuccess; + nDeleteFailed += t.m_nDeleteFailed; + nDelValueSuccess += t.m_nValueSuccess; + nDelValueFailed += t.m_nValueFailed; + } + break; + case update_thread: + { + updater& t = static_cast(thr); + nUpdateCreated += t.m_nUpdateCreated; + nUpdateModified += t.m_nUpdateExisted; + nUpdateFailed += t.m_nUpdateFailed; + nEnsFuncCreated += t.m_nFunctorCreated; + nEnsFuncModified += t.m_nFunctorModified; + } + break; + default: + assert( false ); + } + } + + 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( "update_success", nUpdateCreated + nUpdateModified ) + << std::make_pair( "update_failed", nUpdateFailed ) + << std::make_pair( "update_functor_create", nEnsFuncCreated ) + << std::make_pair( "update_functor_modify", nEnsFuncModified ) + << std::make_pair( "finish_map_size", testMap.size()); + + EXPECT_EQ( nDelValueFailed, 0u ); + EXPECT_EQ( nDelValueSuccess, nDeleteSuccess ); + EXPECT_EQ( nUpdateFailed, 0u ); + EXPECT_EQ( nUpdateCreated + nUpdateModified, nEnsFuncCreated + nEnsFuncModified ); + + // nInsFuncCalled is call count of insert functor + EXPECT_EQ( nInsFuncCalled, nInsertSuccess ); + + check_before_cleanup( testMap ); + + for ( size_t nItem = 0; nItem < s_nMapSize; ++nItem ) + testMap.erase( nItem ); + + EXPECT_TRUE( testMap.empty()); + EXPECT_EQ( testMap.size(), 0u ); + + additional_check( testMap ); + print_stat( propout(), testMap ); + additional_cleanup( testMap ); + } + + template + void run_test() + { + Map testMap( *this ); + do_test( testMap ); + } + + template + void run_test2() + { + Map testMap( *this ); + do_test( testMap ); + + if ( testMap.size() != 0 ) { + for ( auto it = testMap.begin(); it != testMap.end(); ++it ) { + std::cout << "key=" << it->first << std::endl; + } + } + } + }; + + class Map_InsDel_func_LF: public Map_InsDel_func + , public ::testing::WithParamInterface + { + public: + template + void run_test() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Map_InsDel_func::run_test(); + } + + template + void run_test2() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Map_InsDel_func::run_test2(); + } + + static std::vector get_load_factors(); + }; + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_func/map_insdel_func_bronsonavltree.cpp b/test/stress/parallel/parallel-map/insdel_func/map_insdel_func_bronsonavltree.cpp new file mode 100644 index 00000000..6643b99c --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_func/map_insdel_func_bronsonavltree.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 "map_insdel_func.h" +#include "map_type_bronson_avltree.h" + +namespace map { + + CDSSTRESS_BronsonAVLTreeMap( Map_InsDel_func, run_test, size_t, Map_InsDel_func::value_type ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_func/map_insdel_func_cuckoo.cpp b/test/stress/parallel/parallel-map/insdel_func/map_insdel_func_cuckoo.cpp new file mode 100644 index 00000000..e2c6ab4d --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_func/map_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 "map_insdel_func.h" +#include "map_type_cuckoo.h" + +namespace map { + +// CDSSTRESS_CuckooMap( Map_InsDel_func, run_test, size_t, Map_InsDel_func::value_type ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_func/map_insdel_func_ellentree.cpp b/test/stress/parallel/parallel-map/insdel_func/map_insdel_func_ellentree.cpp new file mode 100644 index 00000000..b2047bc3 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_func/map_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 "map_insdel_func.h" +#include "map_type_ellen_bintree.h" + +namespace map { + + CDSSTRESS_EllenBinTreeMap( Map_InsDel_func, run_test, size_t, Map_InsDel_func::value_type ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_func/map_insdel_func_feldman_hashset.cpp b/test/stress/parallel/parallel-map/insdel_func/map_insdel_func_feldman_hashset.cpp new file mode 100644 index 00000000..d5ed79cc --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_func/map_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 "map_insdel_func.h" +#include "map_type_feldman_hashmap.h" + +namespace map { + + CDSSTRESS_FeldmanHashMap_fixed( Map_InsDel_func, run_test, size_t, Map_InsDel_func::value_type ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_func/map_insdel_func_michael.cpp b/test/stress/parallel/parallel-map/insdel_func/map_insdel_func_michael.cpp new file mode 100644 index 00000000..a425fa39 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_func/map_insdel_func_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 "map_insdel_func.h" +#include "map_type_michael.h" + +namespace map { + + CDSSTRESS_MichaelMap( Map_InsDel_func_LF, run_test2, size_t, Map_InsDel_func::value_type ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_func/map_insdel_func_skip.cpp b/test/stress/parallel/parallel-map/insdel_func/map_insdel_func_skip.cpp new file mode 100644 index 00000000..fe49cc95 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_func/map_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 "map_insdel_func.h" +#include "map_type_skip_list.h" + +namespace map { + + CDSSTRESS_SkipListMap( Map_InsDel_func, run_test, size_t, Map_InsDel_func::value_type ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_func/map_insdel_func_split.cpp b/test/stress/parallel/parallel-map/insdel_func/map_insdel_func_split.cpp new file mode 100644 index 00000000..a4d68357 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_func/map_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 "map_insdel_func.h" +#include "map_type_split_list.h" + +namespace map { + + CDSSTRESS_SplitListMap( Map_InsDel_func_LF, run_test, size_t, Map_InsDel_func::value_type ) + CDSSTRESS_SplitListIterableMap( Map_InsDel_func_LF, run_test, size_t, Map_InsDel_func::value_type ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_func/map_insdel_func_striped.cpp b/test/stress/parallel/parallel-map/insdel_func/map_insdel_func_striped.cpp new file mode 100644 index 00000000..4d5b283c --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_func/map_insdel_func_striped.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 "map_insdel_func.h" +#include "map_type_striped.h" + +namespace map { + +// CDSSTRESS_StripedMap( Map_InsDel_func_LF, run_test, size_t, Map_InsDel_func::value_type ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_item_int/CMakeLists.txt b/test/stress/parallel/parallel-map/insdel_item_int/CMakeLists.txt new file mode 100644 index 00000000..2091f333 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_item_int/CMakeLists.txt @@ -0,0 +1,24 @@ +set(PACKAGE_NAME stress-sequential-map-insdel-item-int) + +set(CDSSTRESS_MAP_INSDEL_ITEM_INT_SOURCES + ../../../main.cpp + map_insdel_item_int.cpp + map_insdel_item_int_bronsonavltree.cpp + map_insdel_item_int_cuckoo.cpp + map_insdel_item_int_ellentree.cpp + map_insdel_item_int_feldman_hashset.cpp + map_insdel_item_int_michael.cpp + map_insdel_item_int_skip.cpp + map_insdel_item_int_split.cpp + map_insdel_item_int_striped.cpp +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. +) + +add_executable(${PACKAGE_NAME} ${CDSSTRESS_MAP_INSDEL_ITEM_INT_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/parallel/parallel-map/insdel_item_int/map_insdel_item_int.cpp b/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int.cpp new file mode 100644 index 00000000..9dc75aa5 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int.cpp @@ -0,0 +1,120 @@ +/* + 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 "map_insdel_item_int.h" + +namespace map { + + size_t Map_InsDel_item_int::s_nMapSize = 10000; // map size + size_t Map_InsDel_item_int::s_nInsertThreadCount = 4; // count of insertion thread + size_t Map_InsDel_item_int::s_nDeleteThreadCount = 4; // count of deletion thread + size_t Map_InsDel_item_int::s_nMaxLoadFactor = 8; // maximum load factor + + size_t Map_InsDel_item_int::s_nAttemptCount = 2000; // count of SUCCESS insert/delete for each thread + size_t Map_InsDel_item_int::s_nGoalItem = 5000; + + size_t Map_InsDel_item_int::s_nCuckooInitialSize = 1024;// initial size for CuckooSet + size_t Map_InsDel_item_int::s_nCuckooProbesetSize = 16; // CuckooSet probeset size (only for list-based probeset) + size_t Map_InsDel_item_int::s_nCuckooProbesetThreshold = 0; // CUckooSet probeset threshold (0 - use default) + + size_t Map_InsDel_item_int::s_nFeldmanMap_HeadBits = 10; + size_t Map_InsDel_item_int::s_nFeldmanMap_ArrayBits = 4; + + size_t Map_InsDel_item_int::s_nLoadFactor = 1; + + void Map_InsDel_item_int::SetUpTestCase() + { + cds_test::config const& cfg = get_config( "map_insdel_item_int" ); + + s_nMapSize = cfg.get_size_t( "MapSize", s_nMapSize ); + if ( s_nMapSize < 1000 ) + s_nMapSize = 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_nGoalItem = cfg.get_size_t( "GoalItem", s_nGoalItem ); + if ( s_nGoalItem >= s_nMapSize ) + s_nGoalItem = s_nMapSize / 2; + + s_nAttemptCount = cfg.get_size_t( "AttemptCount", s_nAttemptCount ); + if ( s_nAttemptCount == 0 ) + s_nAttemptCount = 1000; + + 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_nFeldmanMap_HeadBits = cfg.get_size_t( "FeldmanMapHeadBits", s_nFeldmanMap_HeadBits ); + if ( s_nFeldmanMap_HeadBits == 0 ) + s_nFeldmanMap_HeadBits = 2; + + s_nFeldmanMap_ArrayBits = cfg.get_size_t( "FeldmanMapArrayBits", s_nFeldmanMap_ArrayBits ); + if ( s_nFeldmanMap_ArrayBits == 0 ) + s_nFeldmanMap_ArrayBits = 2; + } + + std::vector Map_InsDel_item_int_LF::get_load_factors() + { + cds_test::config const& cfg = get_config( "map_insdel_item_int" ); + + 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, Map_InsDel_item_int_LF, ::testing::ValuesIn( Map_InsDel_item_int_LF::get_load_factors()), get_test_parameter_name ); +#else + INSTANTIATE_TEST_CASE_P( a, Map_InsDel_item_int_LF, ::testing::ValuesIn( Map_InsDel_item_int_LF::get_load_factors())); +#endif + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int.h b/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int.h new file mode 100644 index 00000000..26da8034 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int.h @@ -0,0 +1,303 @@ +/* + 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 "map_type.h" + +namespace map { + + class Map_InsDel_item_int: public cds_test::stress_fixture + { + public: + static size_t s_nMapSize; // map size + static size_t s_nInsertThreadCount; // count of insertion thread + static size_t s_nDeleteThreadCount; // count of deletion thread + static size_t s_nMaxLoadFactor; // maximum load factor + + static size_t s_nAttemptCount; // count of SUCCESS insert/delete for each thread + static size_t s_nGoalItem; + + static size_t s_nCuckooInitialSize; // initial size for CuckooMap + static size_t s_nCuckooProbesetSize; // CuckooMap probeset size (only for list-based probeset) + static size_t s_nCuckooProbesetThreshold; // CuckooMap probeset threshold (o - use default) + + static size_t s_nFeldmanMap_HeadBits; + static size_t s_nFeldmanMap_ArrayBits; + + static size_t s_nLoadFactor; // current load factor + + static void SetUpTestCase(); + //static void TearDownTestCase(); + + typedef size_t key_type; + typedef size_t value_type; + + protected: + enum { + insert_thread, + delete_thread + }; + + template + class Inserter: public cds_test::thread + { + typedef cds_test::thread base_class; + Map& m_Map; + + struct update_func + { + void operator()( bool bNew, std::pair& item ) const + { + if ( bNew ) + item.second = item.first; + } + + // for boost::container::flat_map + void operator()( bool bNew, std::pair& item ) const + { + if ( bNew ) + item.second = item.first; + } + + // for BronsonAVLTreeMap + void operator()( bool bNew, key_type key, value_type& val ) const + { + if ( bNew ) + val = key; + } + + // for FeldmanHashMap + void operator()( std::pair& item, std::pair* pOld ) const + { + if ( !pOld ) + item.second = item.first; + } + }; + + public: + size_t m_nInsertSuccess = 0; + size_t m_nInsertFailed = 0; + + public: + Inserter( cds_test::thread_pool& pool, Map& map ) + : base_class( pool, insert_thread ) + , m_Map( map ) + {} + + Inserter( Inserter& src ) + : base_class( src ) + , m_Map( src.m_Map ) + {} + + virtual thread * clone() + { + return new Inserter( *this ); + } + + virtual void test() + { + Map& rMap = m_Map; + + size_t const nGoalItem = s_nGoalItem; + size_t const nAttemptCount = s_nAttemptCount; + + for ( size_t nAttempt = 0; nAttempt < nAttemptCount; ) { + if ( nAttempt % 2 == 0 ) { + if ( rMap.insert( nGoalItem, nGoalItem )) { + ++m_nInsertSuccess; + ++nAttempt; + } + else + ++m_nInsertFailed; + } + else { + std::pair updateResult = rMap.update( nGoalItem, update_func(), true ); + if ( updateResult.second ) { + ++m_nInsertSuccess; + ++nAttempt; + } + else + ++m_nInsertFailed; + } + } + } + }; + + template + class Deleter: public cds_test::thread + { + typedef cds_test::thread base_class; + Map& m_Map; + + public: + size_t m_nDeleteSuccess = 0; + size_t m_nDeleteFailed = 0; + + public: + Deleter( cds_test::thread_pool& pool, Map& map ) + : base_class( pool, delete_thread ) + , m_Map( map ) + {} + + Deleter( Deleter& src ) + : base_class( src ) + , m_Map( src.m_Map ) + {} + + virtual thread * clone() + { + return new Deleter( *this ); + } + + virtual void test() + { + Map& rMap = m_Map; + + size_t const nGoalItem = s_nGoalItem; + size_t const nAttemptCount = s_nAttemptCount; + for ( size_t nAttempt = 0; nAttempt < nAttemptCount; ) { + if ( rMap.erase( nGoalItem )) { + ++m_nDeleteSuccess; + ++nAttempt; + } + else + ++m_nDeleteFailed; + } + } + }; + + protected: + + template + void do_test( Map& testMap ) + { + typedef Inserter inserter; + typedef Deleter deleter; + + // Fill the map + { + std::vector v; + v.reserve( s_nMapSize ); + for ( size_t i = 0; i < s_nMapSize; ++i ) + v.push_back( i ); + shuffle( v.begin(), v.end()); + for ( auto i: v ) + EXPECT_TRUE( testMap.insert( i, i )); + } + + cds_test::thread_pool& pool = get_pool(); + pool.add( new inserter( pool, testMap ), s_nInsertThreadCount ); + pool.add( new deleter( pool, testMap ), s_nDeleteThreadCount ); + + propout() << std::make_pair( "insert_thread_count", s_nInsertThreadCount ) + << std::make_pair( "delete_thread_count", s_nDeleteThreadCount ) + << std::make_pair( "map_size", s_nMapSize ) + << std::make_pair( "goal_item", s_nGoalItem ) + << std::make_pair( "attempt_count", s_nAttemptCount ); + + + 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: + { + inserter& t = static_cast(thr); + EXPECT_EQ( t.m_nInsertSuccess, s_nAttemptCount ) << "thread=" << t.id(); + nInsertSuccess += t.m_nInsertSuccess; + nInsertFailed += t.m_nInsertFailed; + } + break; + case delete_thread: + { + deleter& t = static_cast(thr); + EXPECT_EQ( t.m_nDeleteSuccess, s_nAttemptCount ) << "thread=" << t.id(); + nDeleteSuccess += t.m_nDeleteSuccess; + nDeleteFailed += t.m_nDeleteFailed; + } + break; + default: + assert( false ); + } + } + + EXPECT_EQ( nInsertSuccess, nDeleteSuccess ); + EXPECT_TRUE( testMap.contains( s_nGoalItem )); + EXPECT_CONTAINER_SIZE( testMap, s_nMapSize ); + + 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 ); + + // Check if the map contains all items + for ( size_t i = 0; i < s_nMapSize; ++i ) + EXPECT_TRUE( testMap.contains( i )) << "key=" << i; + + check_before_cleanup( testMap ); + + testMap.clear(); + additional_check( testMap ); + print_stat( propout(), testMap ); + additional_cleanup( testMap ); + } + + template + void run_test() + { + Map testMap( *this ); + do_test( testMap ); + } + }; + + class Map_InsDel_item_int_LF: public Map_InsDel_item_int + , public ::testing::WithParamInterface + { + public: + template + void run_test() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Map_InsDel_item_int::run_test(); + } + + static std::vector get_load_factors(); + }; + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_bronsonavltree.cpp b/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_bronsonavltree.cpp new file mode 100644 index 00000000..f4feb938 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_bronsonavltree.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 "map_insdel_item_int.h" +#include "map_type_bronson_avltree.h" + +namespace map { + + CDSSTRESS_BronsonAVLTreeMap( Map_InsDel_item_int, run_test, size_t, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_cuckoo.cpp b/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_cuckoo.cpp new file mode 100644 index 00000000..2f7fbf41 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_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 "map_insdel_item_int.h" +#include "map_type_cuckoo.h" + +namespace map { + +// CDSSTRESS_CuckooMap( Map_InsDel_item_int, run_test, size_t, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_ellentree.cpp b/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_ellentree.cpp new file mode 100644 index 00000000..66571e25 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_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 "map_insdel_item_int.h" +#include "map_type_ellen_bintree.h" + +namespace map { + + CDSSTRESS_EllenBinTreeMap( Map_InsDel_item_int, run_test, size_t, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_feldman_hashset.cpp b/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_feldman_hashset.cpp new file mode 100644 index 00000000..b07bbb5e --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_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 "map_insdel_item_int.h" +#include "map_type_feldman_hashmap.h" + +namespace map { + + CDSSTRESS_FeldmanHashMap_fixed( Map_InsDel_item_int, run_test, size_t, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_michael.cpp b/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_michael.cpp new file mode 100644 index 00000000..87ed4232 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_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 "map_insdel_item_int.h" +#include "map_type_michael.h" + +namespace map { + + CDSSTRESS_MichaelMap( Map_InsDel_item_int_LF, run_test, size_t, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_skip.cpp b/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_skip.cpp new file mode 100644 index 00000000..f6a17a6a --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_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 "map_insdel_item_int.h" +#include "map_type_skip_list.h" + +namespace map { + + CDSSTRESS_SkipListMap( Map_InsDel_item_int, run_test, size_t, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_split.cpp b/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_split.cpp new file mode 100644 index 00000000..5acacc91 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_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 "map_insdel_item_int.h" +#include "map_type_split_list.h" + +namespace map { + + CDSSTRESS_SplitListMap( Map_InsDel_item_int_LF, run_test, size_t, size_t ) + CDSSTRESS_SplitListIterableMap( Map_InsDel_item_int_LF, run_test, size_t, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_striped.cpp b/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_striped.cpp new file mode 100644 index 00000000..54c7d3a7 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_item_int/map_insdel_item_int_striped.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 "map_insdel_item_int.h" +#include "map_type_striped.h" + +namespace map { + +// CDSSTRESS_StripedMap( Map_InsDel_item_int_LF, run_test, size_t, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_string/CMakeLists.txt b/test/stress/parallel/parallel-map/insdel_string/CMakeLists.txt new file mode 100644 index 00000000..726631bd --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_string/CMakeLists.txt @@ -0,0 +1,25 @@ +set(PACKAGE_NAME stress-sequential-map-insdel-string) + +set(CDSSTRESS_MAP_INSDEL_STRING_SOURCES + ../../../main.cpp + map_insdel_string.cpp + map_insdel_string_bronsonavltree.cpp + #map_insdel_string_cuckoo.cpp + map_insdel_string_ellentree.cpp + map_insdel_string_feldman_hashset.cpp + map_insdel_string_michael.cpp + map_insdel_string_skip.cpp + map_insdel_string_split.cpp + #map_insdel_string_std.cpp + #map_insdel_string_striped.cpp +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. +) + +add_executable(${PACKAGE_NAME} ${CDSSTRESS_MAP_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/parallel/parallel-map/insdel_string/map_insdel_string.cpp b/test/stress/parallel/parallel-map/insdel_string/map_insdel_string.cpp new file mode 100644 index 00000000..22373a99 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_string/map_insdel_string.cpp @@ -0,0 +1,228 @@ +/* + 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 "map_insdel_string.h" +#include + +namespace map { + + size_t Map_InsDel_string::s_nMapSize = 1000000; // map size + size_t Map_InsDel_string::s_nInsertThreadCount = 4; // count of insertion thread + size_t Map_InsDel_string::s_nDeleteThreadCount = 4; // count of deletion thread + size_t Map_InsDel_string::s_nThreadPassCount = 4; // pass count for each thread + size_t Map_InsDel_string::s_nFeldmanPassCount = 100; + size_t Map_InsDel_string::s_nBronsonAVLTreeMapPassCount = 100; + size_t Map_InsDel_string::s_nEllenBinTreeMapPassCount = 100; + size_t Map_InsDel_string::s_nMichaelMapPassCount = 100; + size_t Map_InsDel_string::s_nSkipListMapPassCount = 100; + size_t Map_InsDel_string::s_nSplitListMapPassCount = 100; + + size_t Map_InsDel_string::s_nMaxLoadFactor = 8; // maximum load factor + + size_t Map_InsDel_string::s_nCuckooInitialSize = 1024;// initial size for CuckooSet + size_t Map_InsDel_string::s_nCuckooProbesetSize = 16; // CuckooSet probeset size (only for list-based probeset) + size_t Map_InsDel_string::s_nCuckooProbesetThreshold = 0; // CuckooSet probeset threshold (0 - use default) + + size_t Map_InsDel_string::s_nFeldmanMap_HeadBits = 10; + size_t Map_InsDel_string::s_nFeldmanMap_ArrayBits = 4; + + size_t Map_InsDel_string::s_nLoadFactor = 1; + std::vector Map_InsDel_string::s_arrKeys; + + void Map_InsDel_string::setup_test_case() + { + cds_test::config const& cfg = get_config( "sequential_real_map_insdel_string" ); + + s_nMapSize = cfg.get_size_t( "MapSize", s_nMapSize ); + if ( s_nMapSize < 1000 ) + s_nMapSize = 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_nFeldmanPassCount = + cfg.get_size_t("FeldmanPassCount", s_nFeldmanPassCount); + if (s_nFeldmanPassCount == 0) + s_nFeldmanPassCount = 500; + + s_nBronsonAVLTreeMapPassCount = cfg.get_size_t( + "BronsonAVLTreeMapPassCount", s_nBronsonAVLTreeMapPassCount); + if (s_nBronsonAVLTreeMapPassCount == 0) + s_nBronsonAVLTreeMapPassCount = 500; + + s_nEllenBinTreeMapPassCount = cfg.get_size_t( + "EllenBinTreeMapPassCount", s_nEllenBinTreeMapPassCount); + if (s_nEllenBinTreeMapPassCount == 0) + s_nEllenBinTreeMapPassCount = 500; + + s_nMichaelMapPassCount = + cfg.get_size_t("MichaelMapPassCount", s_nMichaelMapPassCount); + if (s_nMichaelMapPassCount == 0) + s_nMichaelMapPassCount = 500; + + s_nSkipListMapPassCount = + cfg.get_size_t("SkipListMapPassCount", s_nSkipListMapPassCount); + if (s_nSkipListMapPassCount == 0) + s_nSkipListMapPassCount = 500; + + s_nSplitListMapPassCount = + cfg.get_size_t("SplitListMapPassCount", s_nSplitListMapPassCount); + if (s_nSplitListMapPassCount == 0) + s_nSplitListMapPassCount = 500; + + 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_nFeldmanMap_HeadBits = cfg.get_size_t( "FeldmanMapHeadBits", s_nFeldmanMap_HeadBits ); + if ( s_nFeldmanMap_HeadBits == 0 ) + s_nFeldmanMap_HeadBits = 2; + + s_nFeldmanMap_ArrayBits = cfg.get_size_t( "FeldmanMapArrayBits", s_nFeldmanMap_ArrayBits ); + if ( s_nFeldmanMap_ArrayBits == 0 ) + s_nFeldmanMap_ArrayBits = 2; + } + + void Map_InsDel_string::SetUpTestCase() + { + setup_test_case(); + + s_arrKeys.clear(); + s_arrKeys.reserve( s_nMapSize ); + std::vector dict = load_dictionary(); + for ( size_t i = 0; i < s_nMapSize; ++i ) + s_arrKeys.push_back( std::move( dict.at(i))); + } + + void Map_InsDel_string::TearDownTestCase() + { + s_arrKeys.clear(); + } + + std::vector Map_InsDel_string::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; + } + + template + void Map_InsDel_string::fill_string_array() + { + typedef Hash hasher; + typedef typename hasher::result_type hash_type; + + std::map mapHash; + s_arrKeys.clear(); + std::vector dict = load_dictionary(); + + size_t nSize = dict.size(); + if ( nSize > s_nMapSize ) + nSize = s_nMapSize; + s_arrKeys.reserve( nSize ); + + size_t nDiffHash = 0; + hasher h; + for ( size_t i = 0; i < dict.size(); ++i ) { + hash_type hash = h( dict.at( i )); + if ( mapHash.insert( std::make_pair( hash, i )).second ) { + if ( ++nDiffHash >= nSize ) + break; + s_arrKeys.push_back( std::move( dict.at( i ))); + } + } + s_nMapSize = dict.size(); + } + + void Map_InsDel_string_stdhash::SetUpTestCase() + { + setup_test_case(); + fill_string_array>(); + } + +#if CDS_BUILD_BITS == 64 + void Map_InsDel_string_city32::SetUpTestCase() + { + setup_test_case(); + fill_string_array(); + } + + void Map_InsDel_string_city64::SetUpTestCase() + { + setup_test_case(); + fill_string_array(); + } + + void Map_InsDel_string_city128::SetUpTestCase() + { + setup_test_case(); + fill_string_array(); + } + +#endif + +#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, Map_InsDel_string_LF, ::testing::ValuesIn( Map_InsDel_string::get_load_factors()), get_test_parameter_name ); +#else + INSTANTIATE_TEST_CASE_P( a, Map_InsDel_string_LF, ::testing::ValuesIn( Map_InsDel_string::get_load_factors())); +#endif + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_string/map_insdel_string.h b/test/stress/parallel/parallel-map/insdel_string/map_insdel_string.h new file mode 100644 index 00000000..050025a0 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_string/map_insdel_string.h @@ -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 "map_type.h" + +namespace map { + +#define TEST_CASE(TAG, X) void X(); + + class Map_InsDel_string: public cds_test::stress_fixture + { + public: + static size_t s_nMapSize; // map 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_nBronsonAVLTreeMapPassCount; + static size_t s_nEllenBinTreeMapPassCount; + static size_t s_nFeldmanPassCount; + static size_t s_nMichaelMapPassCount; + static size_t s_nSkipListMapPassCount; + static size_t s_nSplitListMapPassCount; + + static size_t s_nMaxLoadFactor; // maximum load factor + + static size_t s_nCuckooInitialSize; // initial size for CuckooMap + static size_t s_nCuckooProbesetSize; // CuckooMap probeset size (only for list-based probeset) + static size_t s_nCuckooProbesetThreshold; // CuckooMap probeset threshold (o - use default) + + static size_t s_nFeldmanMap_HeadBits; + static size_t s_nFeldmanMap_ArrayBits; + + static size_t s_nLoadFactor; // current load factor + + static void SetUpTestCase(); + static void TearDownTestCase(); + + static void setup_test_case(); + static std::vector get_load_factors(); + + typedef std::string key_type; + typedef size_t value_type; + + static std::vector s_arrKeys; + + protected: + enum { + insert_thread, + delete_thread + }; + + template + class Inserter: public cds_test::thread + { + typedef cds_test::thread base_class; + Map& m_Map; + + public: + size_t m_nInsertSuccess = 0; + size_t m_nInsertFailed = 0; + + public: + Inserter( cds_test::thread_pool& pool, Map& map ) + : base_class( pool, insert_thread ) + , m_Map( map ) + {} + + Inserter( Inserter& src ) + : base_class( src ) + , m_Map( src.m_Map ) + {} + + virtual thread * clone() + { + return new Inserter( *this ); + } + + virtual void test() + { + Map& rMap = m_Map; + + for (auto it = s_arrKeys.cbegin(), itEnd = s_arrKeys.cend(); + it != itEnd; ++it) { + if (rMap.insert(*it, 0)) + ++m_nInsertSuccess; + else + ++m_nInsertFailed; + } + } + }; + + template + class Deleter: public cds_test::thread + { + typedef cds_test::thread base_class; + Map& m_Map; + + public: + size_t m_nDeleteSuccess = 0; + size_t m_nDeleteFailed = 0; + + public: + Deleter( cds_test::thread_pool& pool, Map& map ) + : base_class( pool, delete_thread ) + , m_Map( map ) + {} + + Deleter( Deleter& src ) + : base_class( src ) + , m_Map( src.m_Map ) + {} + + virtual thread * clone() + { + return new Deleter( *this ); + } + + virtual void test() + { + Map& rMap = m_Map; + + for (auto it = s_arrKeys.cbegin(), itEnd = s_arrKeys.cend(); + it != itEnd; ++it) { + if (rMap.erase(*it)) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + } + } + }; + + protected: + template + static void fill_string_array(); + + template + void do_test( Map& testMap ) + { + typedef Inserter inserter; + typedef Deleter deleter; + + cds_test::thread_pool& pool = get_pool(); + std::unique_ptr inserter_thrd( + new inserter(pool, testMap)); + std::unique_ptr deleter_thrd( + new deleter(pool, testMap)); + for (size_t nPass = 0; nPass < s_nThreadPassCount; ++nPass) { + inserter_thrd->test(); + deleter_thrd->test(); + } + + // testMap.clear(); + for ( auto const& str: s_arrKeys ) + testMap.erase( str ); + EXPECT_TRUE( testMap.empty()); + EXPECT_EQ( testMap.size(), 0u ); + additional_cleanup( testMap ); + } + + template + void run_test() + { + Map testMap( *this ); + do_test( testMap ); + } + + template + void run_bronson_avl_tree() { + Map_InsDel_string::s_nThreadPassCount = + Map_InsDel_string::s_nBronsonAVLTreeMapPassCount; + run_test(); + } + + template + void run_ellen_bin_tree() { + Map_InsDel_string::s_nThreadPassCount = + Map_InsDel_string::s_nEllenBinTreeMapPassCount; + run_test(); + } + + template + void run_feldman() { + Map_InsDel_string::s_nThreadPassCount = + Map_InsDel_string::s_nFeldmanPassCount; + run_test(); + } + + template + void run_michael() { + Map_InsDel_string::s_nThreadPassCount = + Map_InsDel_string::s_nMichaelMapPassCount; + run_test(); + } + + template + void run_skip_list() { + Map_InsDel_string::s_nThreadPassCount = + Map_InsDel_string::s_nSkipListMapPassCount; + run_test(); + } + + template + void run_split_list() { + Map_InsDel_string::s_nThreadPassCount = + Map_InsDel_string::s_nSplitListMapPassCount; + run_test(); + } + }; + + class Map_InsDel_string_stdhash: public Map_InsDel_string + { + public: + static void SetUpTestCase(); + + template + void run_test() + { + Map_InsDel_string::run_test(); + } + }; + +#if CDS_BUILD_BITS == 64 + class Map_InsDel_string_city32: public Map_InsDel_string + { + public: + static void SetUpTestCase(); + + template + void run_test() + { + Map_InsDel_string::run_test(); + } + }; + + class Map_InsDel_string_city64: public Map_InsDel_string + { + public: + static void SetUpTestCase(); + + template + void run_test() + { + Map_InsDel_string::run_test(); + } + }; + + class Map_InsDel_string_city128: public Map_InsDel_string + { + public: + static void SetUpTestCase(); + + template + void run_test() + { + Map_InsDel_string::run_test(); + } + }; + +#endif // #if CDS_BUILD_BITS == 64 + + class Map_InsDel_string_LF: public Map_InsDel_string + , public ::testing::WithParamInterface + { + public: + template + void run_test() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Map_InsDel_string::run_test(); + } + }; + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_bronsonavltree.cpp b/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_bronsonavltree.cpp new file mode 100644 index 00000000..737950e7 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_bronsonavltree.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 "map_insdel_string.h" +#include "map_type_bronson_avltree.h" + +namespace map { + + CDSSTRESS_BronsonAVLTreeMap( Map_InsDel_string, run_bronson_avl_tree, std::string, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_cuckoo.cpp b/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_cuckoo.cpp new file mode 100644 index 00000000..6b9f41ec --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_string/map_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 "map_insdel_string.h" +#include "map_type_cuckoo.h" + +namespace map { + +// CDSSTRESS_CuckooMap( Map_InsDel_string, run_test, std::string, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_ellentree.cpp b/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_ellentree.cpp new file mode 100644 index 00000000..4e7c8eed --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_string/map_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 "map_insdel_string.h" +#include "map_type_ellen_bintree.h" + +namespace map { + + CDSSTRESS_EllenBinTreeMap( Map_InsDel_string, run_ellen_bin_tree, std::string, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_feldman_hashset.cpp b/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_feldman_hashset.cpp new file mode 100644 index 00000000..0c5666e9 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_feldman_hashset.cpp @@ -0,0 +1,42 @@ +/* + 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 "map_insdel_string.h" +#include "map_type_feldman_hashmap.h" + +namespace map { + + CDSSTRESS_FeldmanHashMap_stdhash( Map_InsDel_string_stdhash, run_feldman, std::string, size_t ) +#if CDS_BUILD_BITS == 64 + CDSSTRESS_FeldmanHashMap_city64( Map_InsDel_string_city64, run_feldman, std::string, size_t ) + CDSSTRESS_FeldmanHashMap_city128( Map_InsDel_string_city128, run_feldman, std::string, size_t ) +#endif + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_michael.cpp b/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_michael.cpp new file mode 100644 index 00000000..3bcf3963 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_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 "map_insdel_string.h" +#include "map_type_michael.h" + +namespace map { + + CDSSTRESS_MichaelMap( Map_InsDel_string_LF, run_michael, std::string, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_skip.cpp b/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_skip.cpp new file mode 100644 index 00000000..20065081 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_string/map_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 "map_insdel_string.h" +#include "map_type_skip_list.h" + +namespace map { + + CDSSTRESS_SkipListMap( Map_InsDel_string, run_skip_list, std::string, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_split.cpp b/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_split.cpp new file mode 100644 index 00000000..16018633 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_string/map_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 "map_insdel_string.h" +#include "map_type_split_list.h" + +namespace map { + + CDSSTRESS_SplitListMap( Map_InsDel_string_LF, run_split_list, std::string, size_t ) + CDSSTRESS_SplitListIterableMap( Map_InsDel_string_LF, run_split_list, std::string, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_std.cpp b/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_std.cpp new file mode 100644 index 00000000..c9c94d14 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_std.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 "map_insdel_string.h" +#include "map_type_std.h" + +namespace map { + +// CDSSTRESS_StdMap( Map_InsDel_string, run_test, std::string, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_striped.cpp b/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_striped.cpp new file mode 100644 index 00000000..182c0204 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdel_string/map_insdel_string_striped.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 "map_insdel_string.h" +#include "map_type_striped.h" + +namespace map { + +// CDSSTRESS_StripedMap( Map_InsDel_string_LF, run_test, std::string, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdelfind/CMakeLists.txt b/test/stress/parallel/parallel-map/insdelfind/CMakeLists.txt new file mode 100644 index 00000000..c759b429 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdelfind/CMakeLists.txt @@ -0,0 +1,45 @@ +set(MAP_INSDELFIND_HP stress-parallel-map-insdelfind-hp) +set(MAP_INSDELFIND_RCU stress-parallel-map-insdelfind-rcu) + +set(CDSSTRESS_MAP_INSDELFIND_HP_SOURCES + ../../../main.cpp + map_insdelfind.cpp + #map_insdelfind_cuckoo.cpp + map_insdelfind_ellentree_hp.cpp + map_insdelfind_feldman_hashset_hp.cpp + map_insdelfind_michael_hp.cpp + map_insdelfind_skip_hp.cpp + map_insdelfind_split_hp.cpp + #map_insdelfind_std.cpp + #map_insdelfind_striped.cpp +) + +set(CDSSTRESS_MAP_INSDELFIND_RCU_SOURCES + ../../../main.cpp + map_insdelfind.cpp + #map_insdelfind_bronsonavltree.cpp + map_insdelfind_ellentree_rcu.cpp + map_insdelfind_feldman_hashset_rcu.cpp + map_insdelfind_michael_rcu.cpp + map_insdelfind_skip_rcu.cpp + map_insdelfind_split_rcu.cpp +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. +) + +add_executable(${MAP_INSDELFIND_HP} ${CDSSTRESS_MAP_INSDELFIND_HP_SOURCES}) +target_link_libraries(${MAP_INSDELFIND_HP} ${CDS_TEST_LIBRARIES} ${CDSSTRESS_FRAMEWORK_LIBRARY}) +add_test(NAME ${MAP_INSDELFIND_HP} COMMAND ${MAP_INSDELFIND_HP} WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) + +add_executable(${MAP_INSDELFIND_RCU} ${CDSSTRESS_MAP_INSDELFIND_RCU_SOURCES}) +target_link_libraries(${MAP_INSDELFIND_RCU} ${CDS_TEST_LIBRARIES} ${CDSSTRESS_FRAMEWORK_LIBRARY}) +add_test(NAME ${MAP_INSDELFIND_RCU} COMMAND ${MAP_INSDELFIND_RCU} WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) + +add_custom_target( stress-parallel-map-insdelfind + DEPENDS + stress-parallel-map-insdelfind-hp + stress-parallel-map-insdelfind-rcu +) diff --git a/test/stress/parallel/parallel-map/insdelfind/map_insdelfind.cpp b/test/stress/parallel/parallel-map/insdelfind/map_insdelfind.cpp new file mode 100644 index 00000000..2e2cd7c9 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdelfind/map_insdelfind.cpp @@ -0,0 +1,221 @@ +/* + 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 "map_insdelfind.h" + +namespace map { + + size_t Map_InsDelFind::s_nMapSize = 500000; + size_t Map_InsDelFind::s_nThreadCount = 8; + + size_t Map_InsDelFind::s_nPassCount = 100; + size_t Map_InsDelFind::s_nBronsonAVLTreeMapPassCount = 100; + + size_t Map_InsDelFind::s_nHpFeldmanPassCount = 100; + size_t Map_InsDelFind::s_nHpEllenBinTreeMapPassCount = 100; + size_t Map_InsDelFind::s_nHpMichaelMapPassCount = 100; + size_t Map_InsDelFind::s_nHpSkipListMapPassCount = 100; + size_t Map_InsDelFind::s_nHpSplitListMapPassCount = 100; + + size_t Map_InsDelFind::s_nRcuFeldmanPassCount = 100; + size_t Map_InsDelFind::s_nRcuEllenBinTreeMapPassCount = 100; + size_t Map_InsDelFind::s_nRcuMichaelMapPassCount = 100; + size_t Map_InsDelFind::s_nRcuSkipListMapPassCount = 100; + size_t Map_InsDelFind::s_nRcuSplitListMapPassCount = 100; + + size_t Map_InsDelFind::s_nMaxLoadFactor = 8; + unsigned int Map_InsDelFind::s_nInsertPercentage = 5; + unsigned int Map_InsDelFind::s_nDeletePercentage = 5; + unsigned int Map_InsDelFind::s_nDuration = 30; + + + size_t Map_InsDelFind::s_nCuckooInitialSize = 1024;// initial size for CuckooSet + size_t Map_InsDelFind::s_nCuckooProbesetSize = 16; // CuckooSet probeset size (only for list-based probeset) + size_t Map_InsDelFind::s_nCuckooProbesetThreshold = 0; // CUckooSet probeset threshold (0 - use default) + + size_t Map_InsDelFind::s_nFeldmanMap_HeadBits = 10; + size_t Map_InsDelFind::s_nFeldmanMap_ArrayBits = 4; + + size_t Map_InsDelFind::s_nLoadFactor = 1; + Map_InsDelFind::actions Map_InsDelFind::s_arrShuffle[Map_InsDelFind::c_nShuffleSize]; + + void Map_InsDelFind::SetUpTestCase() + { + cds_test::config const& cfg = get_config( "sequential_real_map_insdelfind" ); + + s_nMapSize = cfg.get_size_t( "InitialMapSize", s_nMapSize ); + if ( s_nMapSize < 1000 ) + s_nMapSize = 1000; + + s_nThreadCount = cfg.get_size_t( "ThreadCount", s_nThreadCount ); + if ( s_nThreadCount == 0 ) + s_nThreadCount = std::min( 16u, std::thread::hardware_concurrency() * 2 ); + + s_nPassCount = + cfg.get_size_t("PassCount", s_nPassCount); + if (s_nPassCount == 0) + s_nPassCount = 500; + + s_nBronsonAVLTreeMapPassCount = cfg.get_size_t( + "BronsonAVLTreeMapPassCount", s_nBronsonAVLTreeMapPassCount); + if (s_nBronsonAVLTreeMapPassCount == 0) + s_nBronsonAVLTreeMapPassCount = 500; + + s_nHpFeldmanPassCount = + cfg.get_size_t("HpFeldmanPassCount", s_nHpFeldmanPassCount); + if (s_nHpFeldmanPassCount == 0) + s_nHpFeldmanPassCount = 500; + + s_nRcuFeldmanPassCount = + cfg.get_size_t("RcuFeldmanPassCount", s_nRcuFeldmanPassCount); + if (s_nRcuFeldmanPassCount == 0) + s_nRcuFeldmanPassCount = 500; + + s_nHpEllenBinTreeMapPassCount = cfg.get_size_t( + "HpEllenBinTreeMapPassCount", s_nHpEllenBinTreeMapPassCount); + if (s_nHpEllenBinTreeMapPassCount == 0) + s_nHpEllenBinTreeMapPassCount = 500; + + s_nRcuEllenBinTreeMapPassCount = cfg.get_size_t( + "RcuEllenBinTreeMapPassCount", s_nRcuEllenBinTreeMapPassCount); + if (s_nRcuEllenBinTreeMapPassCount == 0) + s_nRcuEllenBinTreeMapPassCount = 500; + + s_nHpMichaelMapPassCount = + cfg.get_size_t("HpMichaelMapPassCount", s_nHpMichaelMapPassCount); + if (s_nHpMichaelMapPassCount == 0) + s_nHpMichaelMapPassCount = 500; + + s_nRcuMichaelMapPassCount = + cfg.get_size_t("RcuMichaelMapPassCount", s_nRcuMichaelMapPassCount); + if (s_nRcuMichaelMapPassCount == 0) + s_nRcuMichaelMapPassCount = 500; + + s_nHpSkipListMapPassCount = + cfg.get_size_t("HpSkipListMapPassCount", s_nHpSkipListMapPassCount); + if (s_nHpSkipListMapPassCount == 0) + s_nHpSkipListMapPassCount = 500; + + s_nRcuSkipListMapPassCount = + cfg.get_size_t("RcuSkipListMapPassCount", s_nRcuSkipListMapPassCount); + if (s_nRcuSkipListMapPassCount == 0) + s_nRcuSkipListMapPassCount = 500; + + s_nHpSplitListMapPassCount = + cfg.get_size_t("HpSplitListMapPassCount", s_nHpSplitListMapPassCount); + if (s_nHpSplitListMapPassCount == 0) + s_nHpSplitListMapPassCount = 500; + + s_nRcuSplitListMapPassCount = + cfg.get_size_t("RcuSplitListMapPassCount", s_nRcuSplitListMapPassCount); + if (s_nRcuSplitListMapPassCount == 0) + s_nRcuSplitListMapPassCount = 500; + + 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 >= 100 ) + s_nInsertPercentage = 99; + + s_nDeletePercentage = cfg.get_uint( "DeletePercentage", s_nDeletePercentage ); + if ( s_nDeletePercentage >= 100 ) + s_nDeletePercentage = 99; + + if ( s_nInsertPercentage + s_nDeletePercentage > 100 ) { + unsigned int total = s_nInsertPercentage + s_nDeletePercentage; + s_nInsertPercentage = s_nInsertPercentage * 100 / total; + s_nDeletePercentage = s_nDeletePercentage * 100 / total; + } + + s_nDuration = cfg.get_uint( "Duration", s_nDuration ); + if ( s_nDuration < 5 ) + 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_nFeldmanMap_HeadBits = cfg.get_size_t( "FeldmanMapHeadBits", s_nFeldmanMap_HeadBits ); + if ( s_nFeldmanMap_HeadBits == 0 ) + s_nFeldmanMap_HeadBits = 2; + + s_nFeldmanMap_ArrayBits = cfg.get_size_t( "FeldmanMapArrayBits", s_nFeldmanMap_ArrayBits ); + if ( s_nFeldmanMap_ArrayBits == 0 ) + s_nFeldmanMap_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 Map_InsDelFind_LF::get_load_factors() + { + cds_test::config const &cfg = + get_config("sequential_real_map_insdelfind"); + + s_nMaxLoadFactor = cfg.get_size_t("MaxLoadFactor", s_nMaxLoadFactor); + if (s_nMaxLoadFactor == 0) + s_nMaxLoadFactor = 1; + + // Only test with max load factor. + std::vector lf = {s_nMaxLoadFactor}; +// 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, Map_InsDelFind_LF, ::testing::ValuesIn( Map_InsDelFind_LF::get_load_factors()), get_test_parameter_name ); +#else + INSTANTIATE_TEST_CASE_P( a, Map_InsDelFind_LF, ::testing::ValuesIn( Map_InsDelFind_LF::get_load_factors())); +#endif + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdelfind/map_insdelfind.h b/test/stress/parallel/parallel-map/insdelfind/map_insdelfind.h new file mode 100644 index 00000000..4a830534 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdelfind/map_insdelfind.h @@ -0,0 +1,307 @@ +/* + 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 "map_type.h" + +namespace map { + + + class Map_InsDelFind: public cds_test::stress_fixture + { + public: + static size_t s_nMapSize; // initial map size + + static size_t s_nPassCount; + static size_t s_nBronsonAVLTreeMapPassCount; + + static size_t s_nHpEllenBinTreeMapPassCount; + static size_t s_nHpFeldmanPassCount; + static size_t s_nHpMichaelMapPassCount; + static size_t s_nHpSkipListMapPassCount; + static size_t s_nHpSplitListMapPassCount; + + static size_t s_nRcuEllenBinTreeMapPassCount; + static size_t s_nRcuFeldmanPassCount; + static size_t s_nRcuMichaelMapPassCount; + static size_t s_nRcuSkipListMapPassCount; + static size_t s_nRcuSplitListMapPassCount; + + + 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 CuckooMap + static size_t s_nCuckooProbesetSize; // CuckooMap probeset size (only for list-based probeset) + static size_t s_nCuckooProbesetThreshold; // CuckooMap probeset threshold (o - use default) + + static size_t s_nFeldmanMap_HeadBits; + static size_t s_nFeldmanMap_ArrayBits; + + static size_t s_nLoadFactor; // current load factor + + 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; + Map& m_Map; + + 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, Map& map ) + : base_class( pool ) + , m_Map( map ) + {} + + Worker( Worker& src ) + : base_class( src ) + , m_Map( src.m_Map ) + {} + + virtual thread * clone() + { + return new Worker( *this ); + } + + typedef std::pair< key_type const, value_type > map_value_type; + + struct update_functor { + template + void operator()( bool /*bNew*/, map_value_type& /*cur*/, Q const& /*val*/ ) const + {} + + // FeldmanHashMap + void operator()( map_value_type& /*cur*/, map_value_type* /*old*/) const + {} + + // MichaelMap + void operator()( bool /*bNew*/, map_value_type& /*cur*/ ) const + {} + + // BronsonAVLTreeMap + void operator()( bool /*bNew*/, key_type /*key*/, value_type& /*val*/ ) const + {} + }; + + virtual void test() + { + Map& rMap = m_Map; + size_t pass_count = Map_InsDelFind::s_nPassCount; + + size_t nInsertedNum = 0; + size_t nUninsertedNum = 0; + for (size_t count = 0; count < pass_count; count++) { + bool shouldUpdate = true; + for (size_t i = 0; i < s_nMapSize; ++i) { + // The number to operate on the map. + size_t n = i; + // Insert + if (i % s_nInsertPercentage == 1) { + nInsertedNum++; + if (!shouldUpdate) { + if (rMap.insert(n, n)) + ++m_nInsertSuccess; + else + ++m_nInsertFailed; + shouldUpdate = true; + } else { + if (rMap.update(n, update_functor(), true).first) + ++m_nInsertSuccess; + else + ++m_nInsertFailed; + shouldUpdate = false; + } + } else { + nUninsertedNum++; + } + // Find + if (rMap.contains(n)) + ++m_nFindSuccess; + else + ++m_nFindFailed; + // Delete + if (i % s_nInsertPercentage == 1) { + + if (rMap.erase(n)) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + break; + } + } + } + EXPECT_EQ(nInsertedNum, m_nFindSuccess); + EXPECT_EQ(nUninsertedNum, m_nFindFailed); + EXPECT_EQ(m_nDeleteSuccess, nInsertedNum); + EXPECT_EQ(m_nDeleteFailed, 0); + } + }; + + protected: + template + void do_test( Map& testMap ) + { + typedef Worker worker; + cds_test::thread_pool& pool = get_pool(); + std::unique_ptr worker_thrd(new worker(pool, testMap)); + worker_thrd->test(); + + testMap.clear(); + EXPECT_TRUE( testMap.empty()); + additional_cleanup( testMap ); + } + + template + void run_test() + { + std::unique_ptr testMap(new Map(*this)); + do_test(*testMap); + } + + template + void run_bronson_avl_tree() { + Map_InsDelFind::s_nPassCount = + Map_InsDelFind::s_nBronsonAVLTreeMapPassCount; + run_test(); + } + + template + void run_ellen_bin_tree_hp() { + Map_InsDelFind::s_nPassCount = + Map_InsDelFind::s_nHpEllenBinTreeMapPassCount; + run_test(); + } + + template + void run_skip_list_hp() { + Map_InsDelFind::s_nPassCount = + Map_InsDelFind::s_nHpSkipListMapPassCount; + run_test(); + } + + template + void run_feldman_hp() { + Map_InsDelFind::s_nPassCount = + Map_InsDelFind::s_nHpFeldmanPassCount; + run_test(); + } + + template + void run_ellen_bin_tree_rcu() { + Map_InsDelFind::s_nPassCount = + Map_InsDelFind::s_nRcuEllenBinTreeMapPassCount; + run_test(); + } + + template + void run_skip_list_rcu() { + Map_InsDelFind::s_nPassCount = + Map_InsDelFind::s_nRcuSkipListMapPassCount; + run_test(); + } + + template + void run_feldman_rcu() { + Map_InsDelFind::s_nPassCount = + Map_InsDelFind::s_nRcuFeldmanPassCount; + run_test(); + } + }; + + class Map_InsDelFind_LF: public Map_InsDelFind + , public ::testing::WithParamInterface + { + public: + template + void run_test() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Map_InsDelFind::run_test(); + } + + template + void run_michael_hp() { + Map_InsDelFind::s_nPassCount = + Map_InsDelFind::s_nHpMichaelMapPassCount; + Map_InsDelFind_LF::run_test(); + } + + template + void run_split_list_hp() { + Map_InsDelFind::s_nPassCount = + Map_InsDelFind::s_nHpSplitListMapPassCount; + Map_InsDelFind_LF::run_test(); + } + + template + void run_michael_rcu() { + Map_InsDelFind::s_nPassCount = + Map_InsDelFind::s_nRcuMichaelMapPassCount; + Map_InsDelFind_LF::run_test(); + } + + template + void run_split_list_rcu() { + Map_InsDelFind::s_nPassCount = + Map_InsDelFind::s_nRcuSplitListMapPassCount; + Map_InsDelFind_LF::run_test(); + } + + static std::vector get_load_factors(); + }; + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_bronsonavltree.cpp b/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_bronsonavltree.cpp new file mode 100644 index 00000000..68071541 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_bronsonavltree.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 "map_insdelfind.h" +#include "map_type_bronson_avltree.h" + +namespace map { + + CDSSTRESS_BronsonAVLTreeMap( Map_InsDelFind, run_bronson_avl_tree, size_t, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_cuckoo.cpp b/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_cuckoo.cpp new file mode 100644 index 00000000..ca7e84f6 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdelfind/map_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 "map_insdelfind.h" +#include "map_type_cuckoo.h" + +namespace map { + +// CDSSTRESS_CuckooMap( Map_InsDelFind, run_test, size_t, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_ellentree_hp.cpp b/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_ellentree_hp.cpp new file mode 100644 index 00000000..88ba4d67 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdelfind/map_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 "map_insdelfind.h" +#include "map_type_ellen_bintree.h" + +namespace map { + + CDSSTRESS_EllenBinTreeMap_HP( Map_InsDelFind, run_ellen_bin_tree_hp, size_t, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_ellentree_rcu.cpp b/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_ellentree_rcu.cpp new file mode 100644 index 00000000..43306b5b --- /dev/null +++ b/test/stress/parallel/parallel-map/insdelfind/map_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 "map_insdelfind.h" +#include "map_type_ellen_bintree.h" + +namespace map { + + CDSSTRESS_EllenBinTreeMap_RCU( Map_InsDelFind, run_ellen_bin_tree_rcu, size_t, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_feldman_hashset_hp.cpp b/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_feldman_hashset_hp.cpp new file mode 100644 index 00000000..0787b0cb --- /dev/null +++ b/test/stress/parallel/parallel-map/insdelfind/map_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 "map_insdelfind.h" +#include "map_type_feldman_hashmap.h" + +namespace map { + + CDSSTRESS_FeldmanHashMap_fixed_HP( Map_InsDelFind, run_feldman_hp, size_t, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_feldman_hashset_rcu.cpp b/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_feldman_hashset_rcu.cpp new file mode 100644 index 00000000..2e6ecfe5 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdelfind/map_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 "map_insdelfind.h" +#include "map_type_feldman_hashmap.h" + +namespace map { + + CDSSTRESS_FeldmanHashMap_fixed_RCU( Map_InsDelFind, run_feldman_rcu, size_t, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_michael_hp.cpp b/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_michael_hp.cpp new file mode 100644 index 00000000..61b8bd2d --- /dev/null +++ b/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_michael_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 "map_insdelfind.h" +#include "map_type_michael.h" + +namespace map { + + CDSSTRESS_MichaelMap_HP( Map_InsDelFind_LF, run_michael_hp, size_t, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_michael_rcu.cpp b/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_michael_rcu.cpp new file mode 100644 index 00000000..309c1e04 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdelfind/map_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 "map_insdelfind.h" +#include "map_type_michael.h" + +namespace map { + + CDSSTRESS_MichaelMap_RCU( Map_InsDelFind_LF, run_michael_rcu, size_t, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_skip_hp.cpp b/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_skip_hp.cpp new file mode 100644 index 00000000..329a773d --- /dev/null +++ b/test/stress/parallel/parallel-map/insdelfind/map_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 "map_insdelfind.h" +#include "map_type_skip_list.h" + +namespace map { + + CDSSTRESS_SkipListMap_HP( Map_InsDelFind, run_skip_list_hp, size_t, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_skip_rcu.cpp b/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_skip_rcu.cpp new file mode 100644 index 00000000..19d10850 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdelfind/map_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 "map_insdelfind.h" +#include "map_type_skip_list.h" + +namespace map { + + CDSSTRESS_SkipListMap_RCU( Map_InsDelFind, run_skip_list_rcu, size_t, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_split_hp.cpp b/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_split_hp.cpp new file mode 100644 index 00000000..0c501bc9 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdelfind/map_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 "map_insdelfind.h" +#include "map_type_split_list.h" + +namespace map { + + CDSSTRESS_SplitListMap_HP( Map_InsDelFind_LF, run_split_list_hp, size_t, size_t ) + CDSSTRESS_SplitListIterableMap( Map_InsDelFind_LF, run_split_list_hp, size_t, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_split_rcu.cpp b/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_split_rcu.cpp new file mode 100644 index 00000000..9da9c8a9 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdelfind/map_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 "map_insdelfind.h" +#include "map_type_split_list.h" + +namespace map { + + CDSSTRESS_SplitListMap_RCU( Map_InsDelFind_LF, run_split_list_rcu, size_t, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_std.cpp b/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_std.cpp new file mode 100644 index 00000000..5d09f152 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_std.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 "map_insdelfind.h" +#include "map_type_std.h" + +namespace map { + +// CDSSTRESS_StdMap( Map_InsDelFind, run_test, size_t, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_striped.cpp b/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_striped.cpp new file mode 100644 index 00000000..96458ac3 --- /dev/null +++ b/test/stress/parallel/parallel-map/insdelfind/map_insdelfind_striped.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 "map_insdelfind.h" +#include "map_type_striped.h" + +namespace map { + +// CDSSTRESS_StripedMap( Map_InsDelFind_LF, run_test, size_t, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/iter_erase/CMakeLists.txt b/test/stress/parallel/parallel-map/iter_erase/CMakeLists.txt new file mode 100644 index 00000000..42358af3 --- /dev/null +++ b/test/stress/parallel/parallel-map/iter_erase/CMakeLists.txt @@ -0,0 +1,19 @@ +set(PACKAGE_NAME stress-sequential-map-iter-erase) + +set(CDSSTRESS_MAP_ITER_ERASE_SOURCES + ../../../main.cpp + map_iter_erase.cpp + map_iter_erase_feldman_hashmap.cpp + map_iter_erase_michael.cpp + map_iter_erase_split.cpp +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. +) + +add_executable(${PACKAGE_NAME} ${CDSSTRESS_MAP_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/parallel/parallel-map/iter_erase/map_iter_erase.cpp b/test/stress/parallel/parallel-map/iter_erase/map_iter_erase.cpp new file mode 100644 index 00000000..ac04e53d --- /dev/null +++ b/test/stress/parallel/parallel-map/iter_erase/map_iter_erase.cpp @@ -0,0 +1,117 @@ +/* + 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 "map_iter_erase.h" + +namespace map { + + size_t Map_Iter_Del3::s_nMapSize = 5000; + size_t Map_Iter_Del3::s_nInsThreadCount = 4; + size_t Map_Iter_Del3::s_nDelThreadCount = 4; + size_t Map_Iter_Del3::s_nExtractThreadCount = 4; + size_t Map_Iter_Del3::s_nFindThreadCount = 2; + size_t Map_Iter_Del3::s_nMaxLoadFactor = 4; + size_t Map_Iter_Del3::s_nInsertPassCount = 1000; + + size_t Map_Iter_Del3::s_nFeldmanMap_HeadBits = 10; + size_t Map_Iter_Del3::s_nFeldmanMap_ArrayBits = 4; + + size_t Map_Iter_Del3::s_nLoadFactor = 1; + std::vector Map_Iter_Del3::m_arrElements; + + void Map_Iter_Del3::SetUpTestCase() + { + cds_test::config const& cfg = get_config( "map_iter_erase" ); + + s_nMapSize = cfg.get_size_t( "MapSize", s_nMapSize ); + if ( s_nMapSize < 1000 ) + s_nMapSize = 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_nFeldmanMap_HeadBits = cfg.get_size_t( "FeldmanMapHeadBits", s_nFeldmanMap_HeadBits ); + if ( s_nFeldmanMap_HeadBits == 0 ) + s_nFeldmanMap_HeadBits = 2; + + s_nFeldmanMap_ArrayBits = cfg.get_size_t( "FeldmanMapArrayBits", s_nFeldmanMap_ArrayBits ); + if ( s_nFeldmanMap_ArrayBits == 0 ) + s_nFeldmanMap_ArrayBits = 2; + + m_arrElements.resize( s_nMapSize ); + for ( size_t i = 0; i < s_nMapSize; ++i ) + m_arrElements[i] = i;; + shuffle( m_arrElements.begin(), m_arrElements.end()); + } + + void Map_Iter_Del3::TearDownTestCase() + { + m_arrElements.clear(); + } + + std::vector Map_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, Map_Iter_Del3_LF, ::testing::ValuesIn( Map_Iter_Del3_LF::get_load_factors()), get_test_parameter_name ); +#else + INSTANTIATE_TEST_CASE_P( a, Map_Iter_Del3_LF, ::testing::ValuesIn( Map_Iter_Del3_LF::get_load_factors())); +#endif + +} // namespace map diff --git a/test/stress/parallel/parallel-map/iter_erase/map_iter_erase.h b/test/stress/parallel/parallel-map/iter_erase/map_iter_erase.h new file mode 100644 index 00000000..cceb3585 --- /dev/null +++ b/test/stress/parallel/parallel-map/iter_erase/map_iter_erase.h @@ -0,0 +1,871 @@ +/* + 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 "map_type.h" +#include + +namespace map { + + namespace { + 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 size mismatch!!!"); + } // namespace + + 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()( key_thread const& k1, 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 key_thread argument_type; + + size_t operator()( key_thread const& k ) const + { + return std::hash()(k.nKey); + } + size_t operator()( size_t k ) const + { + return std::hash()(k); + } + }; + + class Map_Iter_Del3: public cds_test::stress_fixture + { + public: + 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_nMapSize; // max map size + 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_nFeldmanMap_HeadBits; + static size_t s_nFeldmanMap_ArrayBits; + + static size_t s_nLoadFactor; // current load factor + + static std::vector m_arrElements; + + static void SetUpTestCase(); + static void TearDownTestCase(); + + template + static void prepare_array( std::vector& arr, Pred pred ) + { + arr.reserve( m_arrElements.size()); + for ( auto el : m_arrElements ) { + 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; + typedef std::pair pair_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; + Map& m_Map; + + struct update_func + { + template + void operator()( bool /*bNew*/, Q const& ) const + {} + + template + void operator()( bool /*bNew*/, Q const&, V& ) const + {} + + // FeldmanHashMap + template + void operator()( Q&, Q*) 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_Map.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, Map& map ) + : base_class( pool, inserter_thread ) + , m_Map( map ) + { + init_data(); + } + + Inserter( Inserter& src ) + : base_class( src ) + , m_Map( src.m_Map ) + { + init_data(); + } + + virtual thread * clone() + { + return new Inserter( *this ); + } + + virtual void test() + { + Map& rMap = m_Map; + Map_Iter_Del3& fixture = pool().template fixture(); + + update_func f; + + for ( size_t nPass = 0; nPass < s_nInsertPassCount; ++nPass ) { + if ( nPass & 1 ) { + // insert pass + for ( auto el : m_arr ) { + if ( el & 3 ) { + if ( rMap.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 ) = rMap.update( key_type( el, id()), f ); + 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; + } + }; + + 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; + } + + typedef key_equal equal_to; + }; + + // Deletes odd keys from [0..N) + template + class Deleter: public cds_test::thread + { + typedef cds_test::thread base_class; + Map& m_Map; + + 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, Map& map ) + : base_class( pool, deleter_thread ) + , m_Map( map ) + { + init_data(); + } + + Deleter( Deleter& src ) + : base_class( src ) + , m_Map( src.m_Map ) + { + init_data(); + } + + virtual thread * clone() + { + return new Deleter( *this ); + } + + virtual void test() + { + Map& rMap = m_Map; + + Map_Iter_Del3& fixture = pool().template fixture(); + + do { + auto itEnd = rMap.template get_end(); + for ( auto it = rMap.template get_begin(); it != itEnd; ++it ) { + if ( it->first.nKey & 3 ) { + if ( rMap.erase_at( it )) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + } + } + } while ( fixture.m_nInsThreadCount.load( atomics::memory_order_acquire ) != 0 ); + } + }; + + // Deletes odd keys from [0..N) + template + class Extractor: public cds_test::thread + { + typedef cds_test::thread base_class; + Map& m_Map; + + 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: + Extractor( cds_test::thread_pool& pool, Map& map ) + : base_class( pool, extractor_thread ) + , m_Map( map ) + { + init_data(); + } + + Extractor( Extractor& src ) + : base_class( src ) + , m_Map( src.m_Map ) + { + init_data(); + } + + virtual thread * clone() + { + return new Extractor( *this ); + } + + virtual void test() + { + Map& rMap = m_Map; + + typename Map::guarded_ptr gp; + Map_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 = rMap.extract( key_type( el, k )); + if ( gp ) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + gp.release(); + } + } + } + else { + for ( size_t k = 0; k < nInsThreadCount; ++k ) { + for ( auto el: m_arr ) { + gp = rMap.extract( key_type( el, k )); + if ( gp ) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + gp.release(); + } + } + } + } while ( fixture.m_nInsThreadCount.load( atomics::memory_order_acquire ) != 0 ); + + m_arr.resize( 0 ); + } + }; + + template + class Extractor< cds::urcu::gc, Map > : public cds_test::thread + { + typedef cds_test::thread base_class; + Map& m_Map; + + 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: + Extractor( cds_test::thread_pool& pool, Map& map ) + : base_class( pool, extractor_thread ) + , m_Map( map ) + { + init_data(); + } + + Extractor( Extractor& src ) + : base_class( src ) + , m_Map( src.m_Map ) + { + init_data(); + } + + virtual thread * clone() + { + return new Extractor( *this ); + } + + virtual void test() + { + Map& rMap = m_Map; + Map_Iter_Del3& fixture = pool().template fixture(); + + typename Map::exempt_ptr xp; + size_t const nInsThreadCount = s_nInsThreadCount; + + do { + if ( id() & 1 ) { + for ( size_t k = 0; k < nInsThreadCount; ++k ) { + for ( auto el: m_arr ) { + if ( Map::c_bExtractLockExternal ) { + typename Map::rcu_lock l; + xp = rMap.extract( key_type( el, k )); + if ( xp ) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + } + else { + xp = rMap.extract( key_type( el, k )); + if ( xp ) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + } + xp.release(); + } + } + } + else { + for ( auto el : m_arr ) { + for ( size_t k = 0; k < nInsThreadCount; ++k ) { + if ( Map::c_bExtractLockExternal ) { + typename Map::rcu_lock l; + xp = rMap.extract( key_type( el, k )); + if ( xp ) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + } + else { + xp = rMap.extract( key_type( el, k )); + if ( xp ) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + } + 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; + Map& m_Map; + + 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, Map& map ) + : base_class( pool, find_thread ) + , m_Map( map ) + {} + + Observer( Observer& src ) + : base_class( src ) + , m_Map( src.m_Map ) + {} + + virtual thread * clone() + { + return new Observer( *this ); + } + + virtual void test() + { + Map& map = m_Map; + Map_Iter_Del3& fixture = pool().template fixture(); + std::vector const& arr = m_arrElements; + size_t const nInsThreadCount = s_nInsThreadCount; + + do { + for ( size_t key : arr ) { + if ( key & 3 ) { + for ( size_t k = 0; k < nInsThreadCount; ++k ) { + if ( map.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 ( map.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( Map& testMap ) + { + 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, testMap ), s_nInsThreadCount ); + pool.add( new delete_thread( pool, testMap ), s_nDelThreadCount ? s_nDelThreadCount : cds::OS::topology::processor_count()); + if ( s_nFindThreadCount ) + pool.add( new observer_thread( pool, testMap ), 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( "map_size", s_nMapSize ) + << 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; + } + } + + size_t const nInitialOddKeys = ( s_nMapSize * s_nInsThreadCount ) * 3 / 4; + + EXPECT_EQ( nInsertInitFailed, 0u ); + EXPECT_EQ( nInsertInitSuccess, s_nMapSize * 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 ); + + analyze( testMap ); + } + + template + void do_test_extract( Map& testMap ) + { + typedef Inserter insert_thread; + typedef Deleter delete_thread; + typedef Extractor< typename Map::gc, Map > 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, testMap ), s_nInsThreadCount ); + if ( s_nDelThreadCount ) + pool.add( new delete_thread( pool, testMap ), s_nDelThreadCount ); + if ( s_nExtractThreadCount ) + pool.add( new extract_thread( pool, testMap ), s_nExtractThreadCount ); + if ( s_nFindThreadCount ) + pool.add( new observer_thread( pool, testMap ), 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( "map_size", s_nMapSize ) + << 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_nDeleteSuccess; + nExtractFailed += extractor.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_nMapSize * s_nInsThreadCount ) * 3 / 4; + + EXPECT_EQ( nInsertInitFailed, 0u ); + EXPECT_EQ( nInsertInitSuccess, s_nMapSize * 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 ); + + analyze( testMap ); + } + + template + void analyze( Map& testMap ) + { + // All even keys must be in the map + { + for ( size_t n = 0; n < s_nMapSize; n +=4 ) { + for ( size_t i = 0; i < s_nInsThreadCount; ++i ) { + EXPECT_TRUE( testMap.contains( key_type( n, i ))) << "key=" << n << "/" << i; + } + } + } + + print_stat( propout(), testMap ); + + check_before_cleanup( testMap ); + testMap.clear(); + EXPECT_TRUE( testMap.empty()) << "map.size=" << testMap.size(); + + additional_check( testMap ); + additional_cleanup( testMap ); + } + + template + void run_test_extract() + { + static_assert( Map::c_bExtractSupported, "Map class must support extract() method" ); + + size_t nMapSize = s_nMapSize; + s_nMapSize *= s_nInsThreadCount; + + Map testMap( *this ); + + s_nMapSize = nMapSize; + do_test_extract( testMap ); + } + + template + void run_test() + { + size_t nMapSize = s_nMapSize; + s_nMapSize *= s_nInsThreadCount; + + Map testMap( *this ); + + s_nMapSize = nMapSize; + do_test( testMap ); + } + + template + void run_feldman(); + }; + + class Map_Iter_Del3_reverse: public Map_Iter_Del3 + { + public: + template + void run_feldman(); + }; + + + class Map_Iter_Del3_LF: public Map_Iter_Del3 + , public ::testing::WithParamInterface + { + public: + template + void run_test() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Map_Iter_Del3::run_test(); + } + + template + void run_test_extract() + { + s_nLoadFactor = GetParam(); + propout() << std::make_pair( "load_factor", s_nLoadFactor ); + Map_Iter_Del3::run_test_extract(); + } + + static std::vector get_load_factors(); + }; + +} // namespace map diff --git a/test/stress/parallel/parallel-map/iter_erase/map_iter_erase_feldman_hashmap.cpp b/test/stress/parallel/parallel-map/iter_erase/map_iter_erase_feldman_hashmap.cpp new file mode 100644 index 00000000..23522ca0 --- /dev/null +++ b/test/stress/parallel/parallel-map/iter_erase/map_iter_erase_feldman_hashmap.cpp @@ -0,0 +1,63 @@ +/* + 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 "map_iter_erase.h" +#include "map_type_feldman_hashmap.h" + +namespace map { + + template + void Map_Iter_Del3::run_feldman() + { + typedef typename Map::traits original_traits; + struct traits: public original_traits { + enum { hash_size = sizeof( uint32_t ) + sizeof( uint16_t ) }; + }; + typedef typename Map::template rebind_traits< traits >::result map_type; + + run_test_extract(); + } + + template + void Map_Iter_Del3_reverse::run_feldman() + { + typedef typename Map::traits original_traits; + struct traits: public original_traits { + enum { hash_size = sizeof( uint32_t ) + sizeof( uint16_t ) }; + }; + typedef typename Map::template rebind_traits< traits >::result map_type; + + run_test_extract(); + } + + CDSSTRESS_FeldmanHashMap_fixed_HP( Map_Iter_Del3, run_feldman, key_thread, size_t ) + CDSSTRESS_FeldmanHashMap_fixed_HP( Map_Iter_Del3_reverse, run_feldman, key_thread, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/iter_erase/map_iter_erase_michael.cpp b/test/stress/parallel/parallel-map/iter_erase/map_iter_erase_michael.cpp new file mode 100644 index 00000000..66b21475 --- /dev/null +++ b/test/stress/parallel/parallel-map/iter_erase/map_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 "map_iter_erase.h" +#include "map_type_michael.h" + +namespace map { + + // Test is too long + // CDSSTRESS_MichaelMap_Iterable( Map_Iter_Del3_LF, run_test_extract, key_thread, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/iter_erase/map_iter_erase_split.cpp b/test/stress/parallel/parallel-map/iter_erase/map_iter_erase_split.cpp new file mode 100644 index 00000000..840be70a --- /dev/null +++ b/test/stress/parallel/parallel-map/iter_erase/map_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 "map_iter_erase.h" +#include "map_type_split_list.h" + +namespace map { + // Too long + //CDSSTRESS_SplitListIterableMap( Map_Iter_Del3_LF, run_test_extract, key_thread, size_t ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/map_type.h b/test/stress/parallel/parallel-map/map_type.h new file mode 100644 index 00000000..dae3f81e --- /dev/null +++ b/test/stress/parallel/parallel-map/map_type.h @@ -0,0 +1,235 @@ +/* + 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_MAP_TYPE_H +#define CDSUNIT_MAP_TYPE_H + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +namespace map { + 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 ) const { 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 ) const { 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 map_type; + + template + struct map_type_base + { + typedef map::hash key_hash; + typedef map::less key_less; + typedef cmp key_compare; + + struct equal_to { + bool operator()( Key const& k1, Key const& k2 ) const + { + return key_compare()( k1, k2 ) == 0; + } + }; + + struct hash2: public key_hash + { + size_t operator()( Key const& k ) const + { + size_t h = key_hash::operator ()( k ); + size_t seed = ~h; + seed ^= h + 0x9e3779b9 + (seed << 6) + (seed >> 2); + return seed; + } + template + size_t operator()( Q const& k ) const + { + size_t h = key_hash::operator ()( k ); + size_t seed = ~h; + seed ^= h + 0x9e3779b9 + (seed << 6) + (seed >> 2); + return seed; + } + }; + }; + + 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, Map const& m ) + { + o << m.statistics(); + } + + + template + static inline void check_before_cleanup( Map& /*m*/ ) + {} + + template + static inline void additional_cleanup( Map& /*m*/ ) + {} + + template + static inline void additional_check( Map& /*m*/ ) + {} + +} // namespace map + +#endif // ifndef CDSUNIT_MAP_TYPE_H diff --git a/test/stress/parallel/parallel-map/map_type_bronson_avltree.h b/test/stress/parallel/parallel-map/map_type_bronson_avltree.h new file mode 100644 index 00000000..87f7cd9b --- /dev/null +++ b/test/stress/parallel/parallel-map/map_type_bronson_avltree.h @@ -0,0 +1,243 @@ +/* + 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_MAP_TYPE_BRONSON_AVLTREE_H +#define CDSUNIT_MAP_TYPE_BRONSON_AVLTREE_H + +#include "map_type.h" + +#include +#include +#include + +#include +#include + +namespace map { + + template + class BronsonAVLTreeMap : public cc::BronsonAVLTreeMap< GC, Key, T, Traits > + { + typedef cc::BronsonAVLTreeMap< GC, Key, T, Traits > base_class; + public: + template + BronsonAVLTreeMap( Config const& /*cfg*/ ) + : base_class() + {} + + std::pair extract_min_key() + { + Key key; + typename base_class::exempt_ptr xp = base_class::extract_min( [&key]( Key const& k ) { key = k; } ); + if ( xp ) + return std::make_pair( key, true ); + return std::make_pair( key, false ); + } + + std::pair extract_max_key() + { + Key key; + typename base_class::exempt_ptr xp = base_class::extract_max( [&key]( Key const& k ) { key = k; } ); + if ( xp ) + return std::make_pair( key, true ); + return std::make_pair( key, false ); + } + + // 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_BronsonAVLTreeMap; + + template + struct map_type< tag_BronsonAVLTreeMap, Key, Value >: public map_type_base< Key, Value > + { + typedef map_type_base< Key, Value > base_class; + typedef typename base_class::key_compare compare; + typedef typename base_class::key_less less; + + typedef cds::memory::vyukov_queue_pool< std::mutex > BronsonAVLTreeMap_simple_pool; + typedef cds::memory::lazy_vyukov_queue_pool< std::mutex > BronsonAVLTreeMap_lazy_pool; + typedef cds::memory::bounded_vyukov_queue_pool< std::mutex > BronsonAVLTreeMap_bounded_pool; + + struct BronsonAVLTreeMap_less: public + cc::bronson_avltree::make_traits< + co::less< less > + ,cc::bronson_avltree::relaxed_insert< false > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > + >::type + {}; + typedef BronsonAVLTreeMap< rcu_gpi, Key, Value, BronsonAVLTreeMap_less > BronsonAVLTreeMap_rcu_gpi_less; + typedef BronsonAVLTreeMap< rcu_gpb, Key, Value, BronsonAVLTreeMap_less > BronsonAVLTreeMap_rcu_gpb_less; + typedef BronsonAVLTreeMap< rcu_gpt, Key, Value, BronsonAVLTreeMap_less > BronsonAVLTreeMap_rcu_gpt_less; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef BronsonAVLTreeMap< rcu_shb, Key, Value, BronsonAVLTreeMap_less > BronsonAVLTreeMap_rcu_shb_less; +#endif + struct BronsonAVLTreeMap_cmp_stat: public + cc::bronson_avltree::make_traits< + co::compare< compare > + ,cc::bronson_avltree::relaxed_insert< false > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > + ,co::stat< cc::bronson_avltree::stat<>> + >::type + {}; + typedef BronsonAVLTreeMap< rcu_gpi, Key, Value, BronsonAVLTreeMap_cmp_stat > BronsonAVLTreeMap_rcu_gpi_cmp_stat; + typedef BronsonAVLTreeMap< rcu_gpb, Key, Value, BronsonAVLTreeMap_cmp_stat > BronsonAVLTreeMap_rcu_gpb_cmp_stat; + typedef BronsonAVLTreeMap< rcu_gpt, Key, Value, BronsonAVLTreeMap_cmp_stat > BronsonAVLTreeMap_rcu_gpt_cmp_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef BronsonAVLTreeMap< rcu_shb, Key, Value, BronsonAVLTreeMap_cmp_stat > BronsonAVLTreeMap_rcu_shb_cmp_stat; +#endif + + struct BronsonAVLTreeMap_less_pool_simple: public BronsonAVLTreeMap_less + { + typedef cds::sync::pool_monitor sync_monitor; + }; + typedef BronsonAVLTreeMap< rcu_gpi, Key, Value, BronsonAVLTreeMap_less_pool_simple > BronsonAVLTreeMap_rcu_gpi_less_pool_simple; + typedef BronsonAVLTreeMap< rcu_gpb, Key, Value, BronsonAVLTreeMap_less_pool_simple > BronsonAVLTreeMap_rcu_gpb_less_pool_simple; + typedef BronsonAVLTreeMap< rcu_gpt, Key, Value, BronsonAVLTreeMap_less_pool_simple > BronsonAVLTreeMap_rcu_gpt_less_pool_simple; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef BronsonAVLTreeMap< rcu_shb, Key, Value, BronsonAVLTreeMap_less_pool_simple > BronsonAVLTreeMap_rcu_shb_less_pool_simple; +#endif + struct BronsonAVLTreeMap_less_pool_simple_stat : public BronsonAVLTreeMap_less + { + typedef cc::bronson_avltree::stat<> stat; + typedef cds::sync::pool_monitor sync_monitor; + }; + typedef BronsonAVLTreeMap< rcu_gpi, Key, Value, BronsonAVLTreeMap_less_pool_simple_stat > BronsonAVLTreeMap_rcu_gpi_less_pool_simple_stat; + typedef BronsonAVLTreeMap< rcu_gpb, Key, Value, BronsonAVLTreeMap_less_pool_simple_stat > BronsonAVLTreeMap_rcu_gpb_less_pool_simple_stat; + typedef BronsonAVLTreeMap< rcu_gpt, Key, Value, BronsonAVLTreeMap_less_pool_simple_stat > BronsonAVLTreeMap_rcu_gpt_less_pool_simple_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef BronsonAVLTreeMap< rcu_shb, Key, Value, BronsonAVLTreeMap_less_pool_simple_stat > BronsonAVLTreeMap_rcu_shb_less_pool_simple_stat; +#endif + struct BronsonAVLTreeMap_less_pool_lazy: public BronsonAVLTreeMap_less + { + typedef cds::sync::pool_monitor sync_monitor; + static CDS_CONSTEXPR bool const relaxed_insert = false; // relaxed insert can lead to test assert triggering + }; + typedef BronsonAVLTreeMap< rcu_gpi, Key, Value, BronsonAVLTreeMap_less_pool_lazy > BronsonAVLTreeMap_rcu_gpi_less_pool_lazy; + typedef BronsonAVLTreeMap< rcu_gpb, Key, Value, BronsonAVLTreeMap_less_pool_lazy > BronsonAVLTreeMap_rcu_gpb_less_pool_lazy; + typedef BronsonAVLTreeMap< rcu_gpt, Key, Value, BronsonAVLTreeMap_less_pool_lazy > BronsonAVLTreeMap_rcu_gpt_less_pool_lazy; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef BronsonAVLTreeMap< rcu_shb, Key, Value, BronsonAVLTreeMap_less_pool_lazy > BronsonAVLTreeMap_rcu_shb_less_pool_lazy; +#endif + struct BronsonAVLTreeMap_less_pool_lazy_stat : public BronsonAVLTreeMap_less + { + typedef cc::bronson_avltree::stat<> stat; + typedef cds::sync::pool_monitor sync_monitor; + static CDS_CONSTEXPR bool const relaxed_insert = false; // relaxed insert can lead to test assert triggering + }; + typedef BronsonAVLTreeMap< rcu_gpi, Key, Value, BronsonAVLTreeMap_less_pool_lazy_stat > BronsonAVLTreeMap_rcu_gpi_less_pool_lazy_stat; + typedef BronsonAVLTreeMap< rcu_gpb, Key, Value, BronsonAVLTreeMap_less_pool_lazy_stat > BronsonAVLTreeMap_rcu_gpb_less_pool_lazy_stat; + typedef BronsonAVLTreeMap< rcu_gpt, Key, Value, BronsonAVLTreeMap_less_pool_lazy_stat > BronsonAVLTreeMap_rcu_gpt_less_pool_lazy_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef BronsonAVLTreeMap< rcu_shb, Key, Value, BronsonAVLTreeMap_less_pool_lazy_stat > BronsonAVLTreeMap_rcu_shb_less_pool_lazy_stat; +#endif + struct BronsonAVLTreeMap_less_pool_bounded: public BronsonAVLTreeMap_less + { + typedef cds::sync::pool_monitor sync_monitor; + static CDS_CONSTEXPR bool const relaxed_insert = false; // relaxed insert can lead to test assert triggering + }; + typedef BronsonAVLTreeMap< rcu_gpi, Key, Value, BronsonAVLTreeMap_less_pool_bounded > BronsonAVLTreeMap_rcu_gpi_less_pool_bounded; + typedef BronsonAVLTreeMap< rcu_gpb, Key, Value, BronsonAVLTreeMap_less_pool_bounded > BronsonAVLTreeMap_rcu_gpb_less_pool_bounded; + typedef BronsonAVLTreeMap< rcu_gpt, Key, Value, BronsonAVLTreeMap_less_pool_bounded > BronsonAVLTreeMap_rcu_gpt_less_pool_bounded; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef BronsonAVLTreeMap< rcu_shb, Key, Value, BronsonAVLTreeMap_less_pool_bounded > BronsonAVLTreeMap_rcu_shb_less_pool_bounded; +#endif + struct BronsonAVLTreeMap_less_pool_bounded_stat : public BronsonAVLTreeMap_less + { + typedef cc::bronson_avltree::stat<> stat; + typedef cds::sync::pool_monitor sync_monitor; + static CDS_CONSTEXPR bool const relaxed_insert = false; // relaxed insert can lead to test assert triggering + }; + typedef BronsonAVLTreeMap< rcu_gpi, Key, Value, BronsonAVLTreeMap_less_pool_bounded_stat > BronsonAVLTreeMap_rcu_gpi_less_pool_bounded_stat; + typedef BronsonAVLTreeMap< rcu_gpb, Key, Value, BronsonAVLTreeMap_less_pool_bounded_stat > BronsonAVLTreeMap_rcu_gpb_less_pool_bounded_stat; + typedef BronsonAVLTreeMap< rcu_gpt, Key, Value, BronsonAVLTreeMap_less_pool_bounded_stat > BronsonAVLTreeMap_rcu_gpt_less_pool_bounded_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef BronsonAVLTreeMap< rcu_shb, Key, Value, BronsonAVLTreeMap_less_pool_bounded_stat > BronsonAVLTreeMap_rcu_shb_less_pool_bounded_stat; +#endif + }; + + template + static inline void print_stat( cds_test::property_stream& o, BronsonAVLTreeMap const& m ) + { + o << m.statistics() + << m.monitor().statistics(); + } + + template + static inline void check_before_cleanup( BronsonAVLTreeMap& m ) + { + bool check_consistency_result = m.check_consistency([]( size_t nLevel, size_t hLeft, size_t hRight ) + { + EXPECT_TRUE( false ) << "Tree violation on level=" << nLevel << ": hLeft=" << hLeft << ", hRight=" << hRight; + }); + EXPECT_TRUE( check_consistency_result ) << "Internal tree structure violation"; + } + + +#define CDSSTRESS_BronsonAVLTreeMap_case( fixture, test_case, bronson_map_type, key_type, value_type ) \ + TEST_F( fixture, bronson_map_type ) \ + { \ + typedef map::map_type< tag_BronsonAVLTreeMap, key_type, value_type >::bronson_map_type map_type; \ + test_case(); \ + } + +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED +# define CDSSTRESS_BronsonAVLTreeMap_SHRCU( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_BronsonAVLTreeMap_case( fixture, test_case, BronsonAVLTreeMap_rcu_shb_less, key_type, value_type ) \ + CDSSTRESS_BronsonAVLTreeMap_case( fixture, test_case, BronsonAVLTreeMap_rcu_shb_less_pool_simple, key_type, value_type ) \ + CDSSTRESS_BronsonAVLTreeMap_case( fixture, test_case, BronsonAVLTreeMap_rcu_shb_less_pool_lazy, key_type, value_type ) \ + +#else +# define CDSSTRESS_BronsonAVLTreeMap_SHRCU( fixture, test_case, key_type, value_type ) +#endif + +#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL > 0 +# define CDSSTRESS_BronsonAVLTreeMap_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_BronsonAVLTreeMap_case( fixture, test_case, BronsonAVLTreeMap_rcu_gpi_less_pool_simple, key_type, value_type ) \ + CDSSTRESS_BronsonAVLTreeMap_case( fixture, test_case, BronsonAVLTreeMap_rcu_gpi_less_pool_lazy, key_type, value_type ) \ + CDSSTRESS_BronsonAVLTreeMap_case( fixture, test_case, BronsonAVLTreeMap_rcu_gpb_less_pool_lazy, key_type, value_type ) \ + CDSSTRESS_BronsonAVLTreeMap_SHRCU( fixture, test_case, key_type, value_type ) + +#else +# define CDSSTRESS_BronsonAVLTreeMap_1( fixture, test_case, key_type, value_type ) +#endif + +#define CDSSTRESS_BronsonAVLTreeMap( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_BronsonAVLTreeMap_case( fixture, test_case, BronsonAVLTreeMap_rcu_gpi_less, key_type, value_type ) \ + CDSSTRESS_BronsonAVLTreeMap_case( fixture, test_case, BronsonAVLTreeMap_rcu_gpb_less, key_type, value_type ) \ + CDSSTRESS_BronsonAVLTreeMap_case( fixture, test_case, BronsonAVLTreeMap_rcu_gpb_less_pool_simple, key_type, value_type ) \ + CDSSTRESS_BronsonAVLTreeMap_1( fixture, test_case, key_type, value_type ) \ + +} // namespace map + +#endif // ifndef CDSUNIT_MAP_TYPE_BRONSON_AVLTREE_H diff --git a/test/stress/parallel/parallel-map/map_type_cuckoo.h b/test/stress/parallel/parallel-map/map_type_cuckoo.h new file mode 100644 index 00000000..2ef88925 --- /dev/null +++ b/test/stress/parallel/parallel-map/map_type_cuckoo.h @@ -0,0 +1,364 @@ +/* + 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_MAP_TYPE_CUCKOO_H +#define CDSUNIT_MAP_TYPE_CUCKOO_H + +#include "map_type.h" +#include +#include +#include + +namespace map { + + template + class CuckooMap: public cc::CuckooMap< K, V, Traits > + { + public: + typedef cc::CuckooMap< K, V, Traits > base_class; + + public: + template + CuckooMap( Config const& cfg ) + : 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 base_class::erase_with( key, typename std::conditional< 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_CuckooMap; + + template + struct map_type< tag_CuckooMap, Key, Value >: public map_type_base< Key, Value > + { + typedef map_type_base< Key, Value > base_class; + typedef typename base_class::key_compare compare; + typedef typename base_class::key_less less; + typedef typename base_class::equal_to equal_to; + typedef typename base_class::key_hash hash; + typedef typename base_class::hash2 hash2; + + template + struct traits_CuckooStripedMap: public Traits + { + typedef cc::cuckoo::striping<> mutex_policy; + }; + template + struct traits_CuckooRefinableMap : public Traits + { + typedef cc::cuckoo::refinable<> mutex_policy; + }; + + struct traits_CuckooMap_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 CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_list_unord; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_list_unord; + + struct traits_CuckooMap_list_unord_stat : public traits_CuckooMap_list_unord + { + typedef cc::cuckoo::stat stat; + }; + typedef CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_list_unord_stat; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_list_unord_stat; + + struct traits_CuckooMap_list_unord_storehash : public traits_CuckooMap_list_unord + { + static CDS_CONSTEXPR const bool store_hash = true; + }; + typedef CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_list_unord_storehash; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_list_unord_storehash; + + struct traits_CuckooMap_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 CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_list_ord; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_list_ord; + + struct traits_CuckooMap_list_ord_stat : public traits_CuckooMap_list_ord + { + typedef cc::cuckoo::stat stat; + }; + typedef CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_list_ord_stat; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_list_ord_stat; + + struct traits_CuckooMap_list_ord_storehash : public traits_CuckooMap_list_ord + { + static CDS_CONSTEXPR const bool store_hash = true; + }; + typedef CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_list_ord_storehash; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_list_ord_storehash; + + struct traits_CuckooMap_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 CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_vector_unord; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_vector_unord; + + struct traits_CuckooMap_vector_unord_stat : public traits_CuckooMap_vector_unord + { + typedef cc::cuckoo::stat stat; + }; + typedef CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_vector_unord_stat; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_vector_unord_stat; + + struct traits_CuckooMap_vector_unord_storehash : public traits_CuckooMap_vector_unord + { + static CDS_CONSTEXPR const bool store_hash = true; + }; + typedef CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_vector_unord_storehash; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_vector_unord_storehash; + + struct traits_CuckooMap_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 CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_vector_ord; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_vector_ord; + + struct traits_CuckooMap_vector_ord_stat : public traits_CuckooMap_vector_ord + { + typedef cc::cuckoo::stat stat; + }; + typedef CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_vector_ord_stat; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_vector_ord_stat; + + struct traits_CuckooMap_vector_ord_storehash : public traits_CuckooMap_vector_ord + { + static CDS_CONSTEXPR const bool store_hash = true; + }; + typedef CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_vector_ord_storehash; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_vector_ord_storehash; + +#if CDS_BUILD_BITS == 64 + + struct traits_CuckooMap_list_unord_city64: + public cc::cuckoo::make_traits < + cc::cuckoo::probeset_type< cc::cuckoo::list > + , co::equal_to< equal_to > + , co::hash< std::tuple< cds_test::city64, hash2 > > + > ::type + {}; + typedef CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_list_unord_city64; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_list_unord_city64; + + struct traits_CuckooMap_list_unord_city64_stat: public traits_CuckooMap_list_unord_city64 + { + typedef cc::cuckoo::stat stat; + }; + typedef CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_list_unord_city64_stat; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_list_unord_city64_stat; + + struct traits_CuckooMap_list_unord_city64_storehash: public traits_CuckooMap_list_unord_city64 + { + static CDS_CONSTEXPR const bool store_hash = true; + }; + typedef CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_list_unord_city64_storehash; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_list_unord_city64_storehash; + + struct traits_CuckooMap_list_ord_city64: + public cc::cuckoo::make_traits < + cc::cuckoo::probeset_type< cc::cuckoo::list > + , co::compare< compare > + , co::hash< std::tuple< cds_test::city64, hash2 > > + >::type + {}; + typedef CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_list_ord_city64; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_list_ord_city64; + + struct traits_CuckooMap_list_ord_city64_stat: public traits_CuckooMap_list_ord_city64 + { + typedef cc::cuckoo::stat stat; + }; + typedef CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_list_ord_city64_stat; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_list_ord_city64_stat; + + struct traits_CuckooMap_list_ord_city64_storehash: public traits_CuckooMap_list_ord_city64 + { + static CDS_CONSTEXPR const bool store_hash = true; + }; + typedef CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_list_ord_city64_storehash; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_list_ord_city64_storehash; + + struct traits_CuckooMap_vector_unord_city64: + public cc::cuckoo::make_traits < + cc::cuckoo::probeset_type< cc::cuckoo::vector<4> > + , co::equal_to< equal_to > + , co::hash< std::tuple< cds_test::city64, hash2 > > + >::type + {}; + typedef CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_vector_unord_city64; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_vector_unord_city64; + + struct traits_CuckooMap_vector_unord_city64_stat: public traits_CuckooMap_vector_unord_city64 + { + typedef cc::cuckoo::stat stat; + }; + typedef CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_vector_unord_city64_stat; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_vector_unord_city64_stat; + + struct traits_CuckooMap_vector_unord_city64_storehash: public traits_CuckooMap_vector_unord_city64 + { + static CDS_CONSTEXPR const bool store_hash = true; + }; + typedef CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_vector_unord_city64_storehash; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_vector_unord_city64_storehash; + + struct traits_CuckooMap_vector_ord_city64: + public cc::cuckoo::make_traits < + cc::cuckoo::probeset_type< cc::cuckoo::vector<4> > + , co::compare< compare > + , co::hash< std::tuple< cds_test::city64, hash2 > > + >::type + {}; + typedef CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_vector_ord_city64; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_vector_ord_city64; + + struct traits_CuckooMap_vector_ord_city64_stat: public traits_CuckooMap_vector_ord_city64 + { + typedef cc::cuckoo::stat stat; + }; + typedef CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_vector_ord_city64_stat; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_vector_ord_city64_stat; + + struct traits_CuckooMap_vector_ord_city64_storehash: public traits_CuckooMap_vector_ord_city64 + { + static CDS_CONSTEXPR const bool store_hash = true; + }; + typedef CuckooMap< Key, Value, traits_CuckooStripedMap> CuckooStripedMap_vector_ord_city64_storehash; + typedef CuckooMap< Key, Value, traits_CuckooRefinableMap> CuckooRefinableMap_vector_ord_city64_storehash; +#endif // CDS_BUILD_BITS == 64 + }; + + template + static inline void print_stat( cds_test::property_stream& o, cc::CuckooMap< Key, T, Traits > const& s ) + { + o << s.statistics() << s.mutex_policy_statistics(); + } + + template + static inline void print_stat( cds_test::property_stream& o, CuckooMap< Key, V, Traits > const& s ) + { + typedef CuckooMap< Key, V, Traits > map_type; + print_stat( o, static_cast(s)); + } + +} // namespace map + + +#define CDSSTRESS_CuckooMap_case( fixture, test_case, cuckoo_map_type, key_type, value_type ) \ + TEST_F( fixture, cuckoo_map_type ) \ + { \ + typedef map::map_type< tag_CuckooMap, key_type, value_type >::cuckoo_map_type map_type; \ + test_case(); \ + } + +#define CDSSTRESS_CuckooMap( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_list_unord, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_list_unord, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_list_unord_stat, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_list_unord_stat, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_list_unord_storehash, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_list_unord_storehash, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_list_ord, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_list_ord, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_list_ord_stat, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_list_ord_stat, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_list_ord_storehash, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_list_ord_storehash, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_vector_unord, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_vector_unord, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_vector_unord_stat, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_vector_unord_stat, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_vector_unord_storehash, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_vector_unord_storehash, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_vector_ord, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_vector_ord, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_vector_ord_stat, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_vector_ord_stat, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_vector_ord_storehash, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_vector_ord_storehash, key_type, value_type ) + +#if CDS_BUILD_BITS == 64 +# define CDSSTRESS_CuckooMap_city64( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_list_unord_city64, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_list_unord_city64, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_list_unord_city64_stat, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_list_unord_city64_stat, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_list_unord_city64_storehash, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_list_unord_city64_storehash, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_list_ord_city64, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_list_ord_city64, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_list_ord_city64_stat, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_list_ord_city64_stat, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_list_ord_city64_storehash, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_list_ord_city64_storehash, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_vector_unord_city64, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_vector_unord_city64, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_vector_unord_city64_stat, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_vector_unord_city64_stat, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_vector_unord_city64_storehash, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_vector_unord_city64_storehash, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_vector_ord_city64, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_vector_ord_city64, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_vector_ord_city64_stat, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_vector_ord_city64_stat, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooStripedMap_vector_ord_city64_storehash, key_type, value_type ) \ + CDSSTRESS_CuckooMap_case( fixture, test_case, CuckooRefinableMap_vector_ord_city64_storehash, key_type, value_type ) +#endif +#endif // ifndef CDSUNIT_MAP_TYPE_CUCKOO_H diff --git a/test/stress/parallel/parallel-map/map_type_ellen_bintree.h b/test/stress/parallel/parallel-map/map_type_ellen_bintree.h new file mode 100644 index 00000000..cfb534e6 --- /dev/null +++ b/test/stress/parallel/parallel-map/map_type_ellen_bintree.h @@ -0,0 +1,317 @@ +/* + 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_MAP_TYPE_ELLEN_BINTREE_H +#define CDSUNIT_MAP_TYPE_ELLEN_BINTREE_H + +#include "map_type.h" + +#include +#include +#include + +#include +#include "framework/ellen_bintree_update_desc_pool.h" + +namespace map { + + template + class EllenBinTreeMap : public cc::EllenBinTreeMap< GC, Key, T, Traits > + { + typedef cc::EllenBinTreeMap< GC, Key, T, Traits > base_class; + public: + template + EllenBinTreeMap( Config const& /*cfg*/) + : base_class() + {} + + std::pair extract_min_key() + { + auto xp = base_class::extract_min(); + if ( xp ) + return std::make_pair( xp->first, true ); + return std::make_pair( Key(), false ); + } + + std::pair extract_max_key() + { + auto xp = base_class::extract_max(); + if ( xp ) + return std::make_pair( xp->first, true ); + return std::make_pair( Key(), false ); + } + + // 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_EllenBinTreeMap; + + template + struct map_type< tag_EllenBinTreeMap, Key, Value >: public map_type_base< Key, Value > + { + typedef map_type_base< Key, Value > base_class; + typedef typename base_class::key_compare compare; + typedef typename base_class::key_less less; + + struct ellen_bintree_props { + struct hp_gc { + typedef cc::ellen_bintree::map_node leaf_node; + typedef cc::ellen_bintree::internal_node< Key, leaf_node > internal_node; + typedef cc::ellen_bintree::update_desc< leaf_node, internal_node > update_desc; + }; + struct dhp_gc { + typedef cc::ellen_bintree::map_node leaf_node; + typedef cc::ellen_bintree::internal_node< Key, leaf_node > internal_node; + typedef cc::ellen_bintree::update_desc< leaf_node, internal_node > update_desc; + }; + struct gpi { + typedef cc::ellen_bintree::map_node leaf_node; + typedef cc::ellen_bintree::internal_node< Key, leaf_node > internal_node; + typedef cc::ellen_bintree::update_desc< leaf_node, internal_node > update_desc; + }; + struct gpb { + typedef cc::ellen_bintree::map_node leaf_node; + typedef cc::ellen_bintree::internal_node< Key, leaf_node > internal_node; + typedef cc::ellen_bintree::update_desc< leaf_node, internal_node > update_desc; + }; + struct gpt { + typedef cc::ellen_bintree::map_node leaf_node; + typedef cc::ellen_bintree::internal_node< Key, 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::map_node leaf_node; + typedef cc::ellen_bintree::internal_node< Key, leaf_node > internal_node; + typedef cc::ellen_bintree::update_desc< leaf_node, internal_node > update_desc; + }; +#endif + }; + + struct traits_EllenBinTreeMap: public cc::ellen_bintree::make_set_traits< + co::less< less > + ,co::node_allocator< ellen_bintree_pool::internal_node_allocator< int > > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > + >::type + {}; + struct traits_EllenBinTreeMap_hp : traits_EllenBinTreeMap { + typedef cds::memory::pool_allocator< typename ellen_bintree_props::hp_gc::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator; + }; + typedef EllenBinTreeMap< cds::gc::HP, Key, Value, traits_EllenBinTreeMap_hp > EllenBinTreeMap_hp; + + struct traits_EllenBinTreeMap_dhp : traits_EllenBinTreeMap { + typedef cds::memory::pool_allocator< typename ellen_bintree_props::dhp_gc::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator; + }; + typedef EllenBinTreeMap< cds::gc::DHP, Key, Value, traits_EllenBinTreeMap_dhp > EllenBinTreeMap_dhp; + + struct traits_EllenBinTreeMap_gpi : traits_EllenBinTreeMap { + typedef cds::memory::pool_allocator< typename ellen_bintree_props::gpi::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator; + }; + typedef EllenBinTreeMap< rcu_gpi, Key, Value, traits_EllenBinTreeMap_gpi > EllenBinTreeMap_rcu_gpi; + + struct traits_EllenBinTreeMap_gpb : traits_EllenBinTreeMap { + typedef cds::memory::pool_allocator< typename ellen_bintree_props::gpb::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator; + }; + typedef EllenBinTreeMap< rcu_gpb, Key, Value, traits_EllenBinTreeMap_gpb > EllenBinTreeMap_rcu_gpb; + + struct traits_EllenBinTreeMap_gpt : traits_EllenBinTreeMap { + typedef cds::memory::pool_allocator< typename ellen_bintree_props::gpt::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator; + }; + typedef EllenBinTreeMap< rcu_gpt, Key, Value, traits_EllenBinTreeMap_gpt > EllenBinTreeMap_rcu_gpt; + +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + struct traits_EllenBinTreeMap_shb : traits_EllenBinTreeMap { + typedef cds::memory::pool_allocator< typename ellen_bintree_props::shb::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator; + }; + typedef EllenBinTreeMap< rcu_shb, Key, Value, traits_EllenBinTreeMap_shb > EllenBinTreeMap_rcu_shb; +#endif + + struct traits_EllenBinTreeMap_yield : public traits_EllenBinTreeMap + { + typedef cds::backoff::yield back_off; + }; + struct traits_EllenBinTreeMap_hp_yield : traits_EllenBinTreeMap_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 EllenBinTreeMap< cds::gc::HP, Key, Value, traits_EllenBinTreeMap_hp_yield > EllenBinTreeMap_hp_yield; + + struct traits_EllenBinTreeMap_dhp_yield : traits_EllenBinTreeMap_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 EllenBinTreeMap< cds::gc::DHP, Key, Value, traits_EllenBinTreeMap_dhp_yield > EllenBinTreeMap_dhp_yield; + + struct traits_EllenBinTreeMap_gpb_yield : traits_EllenBinTreeMap_yield { + typedef cds::memory::pool_allocator< typename ellen_bintree_props::gpb::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator; + }; + typedef EllenBinTreeMap< rcu_gpb, Key, Value, traits_EllenBinTreeMap_gpb_yield > EllenBinTreeMap_rcu_gpb_yield; + + + struct traits_EllenBinTreeMap_stat: public cc::ellen_bintree::make_set_traits< + co::less< less > + ,cc::ellen_bintree::update_desc_allocator< + cds::memory::pool_allocator< typename ellen_bintree_props::hp_gc::update_desc, ellen_bintree_pool::update_desc_pool_accessor > + > + ,co::node_allocator< ellen_bintree_pool::internal_node_allocator< int > > + ,co::stat< cc::ellen_bintree::stat<> > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > + >::type + {}; + + struct traits_EllenBinTreeMap_stat_hp : public traits_EllenBinTreeMap_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 EllenBinTreeMap< cds::gc::HP, Key, Value, traits_EllenBinTreeMap_stat_hp > EllenBinTreeMap_hp_stat; + + struct traits_EllenBinTreeMap_stat_dhp : public traits_EllenBinTreeMap_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 EllenBinTreeMap< cds::gc::HP, Key, Value, traits_EllenBinTreeMap_stat_dhp > EllenBinTreeMap_dhp_stat; + + struct traits_EllenBinTreeMap_stat_gpi : public traits_EllenBinTreeMap_stat + { + typedef cds::memory::pool_allocator< typename ellen_bintree_props::gpi::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator; + }; + typedef EllenBinTreeMap< rcu_gpi, Key, Value, traits_EllenBinTreeMap_stat_gpi > EllenBinTreeMap_rcu_gpi_stat; + + struct traits_EllenBinTreeMap_stat_gpb : public traits_EllenBinTreeMap_stat + { + typedef cds::memory::pool_allocator< typename ellen_bintree_props::gpb::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator; + }; + typedef EllenBinTreeMap< rcu_gpb, Key, Value, traits_EllenBinTreeMap_stat_gpb > EllenBinTreeMap_rcu_gpb_stat; + + struct traits_EllenBinTreeMap_stat_gpt : public traits_EllenBinTreeMap_stat + { + typedef cds::memory::pool_allocator< typename ellen_bintree_props::gpt::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator; + }; + typedef EllenBinTreeMap< rcu_gpt, Key, Value, traits_EllenBinTreeMap_stat_gpt > EllenBinTreeMap_rcu_gpt_stat; + +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + struct traits_EllenBinTreeMap_stat_shb : public traits_EllenBinTreeMap_stat + { + typedef cds::memory::pool_allocator< typename ellen_bintree_props::shb::update_desc, ellen_bintree_pool::update_desc_pool_accessor > update_desc_allocator; + }; + typedef EllenBinTreeMap< rcu_shb, Key, Value, traits_EllenBinTreeMap_stat_shb > EllenBinTreeMap_rcu_shb_stat; +#endif + }; + + template + static inline void print_stat( cds_test::property_stream& o, EllenBinTreeMap const& s ) + { + o << s.statistics(); + } + template + static inline void additional_cleanup( EllenBinTreeMap& /*s*/ ) + { + ellen_bintree_pool::internal_node_counter::reset(); + } + namespace ellen_bintree_check { + static inline void check_stat( cds::intrusive::ellen_bintree::empty_stat const& /*s*/ ) + { + // This check is not valid for thread-based RCU + /* + CPPUNIT_CHECK_CURRENT_EX( ellen_bintree_pool::internal_node_counter::m_nAlloc.get() == ellen_bintree_pool::internal_node_counter::m_nFree.get(), + "m_nAlloc=" << ellen_bintree_pool::internal_node_counter::m_nAlloc.get() + << ", m_nFree=" << 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(), stat.m_nInternalNodeCreated ); + } + } // namespace ellen_bintree_check + template + static inline void additional_check( EllenBinTreeMap& m ) + { + GC::force_dispose(); + ellen_bintree_check::check_stat( m.statistics()); + } + + template + static inline void check_before_cleanup( EllenBinTreeMap& m ) + { + EXPECT_TRUE( m.check_consistency()); + } +} // namespace map + + +#define CDSSTRESS_EllenBinTreeMap_case( fixture, test_case, ellen_map_type, key_type, value_type ) \ + TEST_F( fixture, ellen_map_type ) \ + { \ + typedef map::map_type< tag_EllenBinTreeMap, key_type, value_type >::ellen_map_type map_type; \ + test_case(); \ + } + +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED +# define CDSSTRESS_EllenBinTreeMap_SHRCU( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_EllenBinTreeMap_case( fixture, test_case, EllenBinTreeMap_rcu_shb, key_type, value_type ) \ + +#else +# define CDSSTRESS_EllenBinTreeMap_SHRCU( fixture, test_case, key_type, value_type ) +#endif + +#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL > 0 +# define CDSSTRESS_EllenBinTreeMap_HP_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_EllenBinTreeMap_case( fixture, test_case, EllenBinTreeMap_hp_yield, key_type, value_type ) \ + CDSSTRESS_EllenBinTreeMap_case( fixture, test_case, EllenBinTreeMap_dhp_yield, key_type, value_type ) \ + + +# define CDSSTRESS_EllenBinTreeMap_RCU_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_EllenBinTreeMap_case( fixture, test_case, EllenBinTreeMap_rcu_gpi, key_type, value_type ) \ + CDSSTRESS_EllenBinTreeMap_case( fixture, test_case, EllenBinTreeMap_rcu_gpb_yield, key_type, value_type ) \ + CDSSTRESS_EllenBinTreeMap_SHRCU( fixture, test_case, key_type, value_type ) \ + +#else +# define CDSSTRESS_EllenBinTreeMap_HP_1( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_EllenBinTreeMap_RCU_1( fixture, test_case, key_type, value_type ) +#endif + +#define CDSSTRESS_EllenBinTreeMap_HP( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_EllenBinTreeMap_case( fixture, test_case, EllenBinTreeMap_hp, key_type, value_type ) \ + CDSSTRESS_EllenBinTreeMap_case( fixture, test_case, EllenBinTreeMap_dhp, key_type, value_type ) \ + CDSSTRESS_EllenBinTreeMap_HP_1( fixture, test_case, key_type, value_type ) \ + +#define CDSSTRESS_EllenBinTreeMap_RCU( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_EllenBinTreeMap_case( fixture, test_case, EllenBinTreeMap_rcu_gpb, key_type, value_type ) \ + CDSSTRESS_EllenBinTreeMap_RCU_1( fixture, test_case, key_type, value_type ) \ + +#define CDSSTRESS_EllenBinTreeMap( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_EllenBinTreeMap_HP( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_EllenBinTreeMap_RCU( fixture, test_case, key_type, value_type ) \ + +#endif // ifndef CDSUNIT_MAP_TYPE_ELLEN_BINTREE_H diff --git a/test/stress/parallel/parallel-map/map_type_feldman_hashmap.h b/test/stress/parallel/parallel-map/map_type_feldman_hashmap.h new file mode 100644 index 00000000..0d1a8625 --- /dev/null +++ b/test/stress/parallel/parallel-map/map_type_feldman_hashmap.h @@ -0,0 +1,357 @@ +/* + 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_MAP_TYPE_FELDMAN_HASHMAP_H +#define CDSUNIT_MAP_TYPE_FELDMAN_HASHMAP_H + +#include "map_type.h" + +#include +#include +#include + +#include +#include + +namespace map { + + template + class FeldmanHashMap : public cc::FeldmanHashMap< GC, Key, T, Traits > + { + typedef cc::FeldmanHashMap< GC, Key, T, Traits > base_class; + public: + + template + struct rebind_traits { + typedef FeldmanHashMap result; + }; + + template + FeldmanHashMap( Config const& cfg) + : base_class( cfg.s_nFeldmanMap_HeadBits, cfg.s_nFeldmanMap_ArrayBits ) + {} + + 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_FeldmanHashMap; + + template + struct map_type< tag_FeldmanHashMap, Key, Value >: public map_type_base< Key, Value > + { + typedef map_type_base< Key, Value > base_class; + typedef typename base_class::key_compare compare; + typedef typename base_class::key_less less; + + struct traits_FeldmanHashMap_stdhash : public cc::feldman_hashmap::traits + { + typedef std::hash< Key > hash; + typedef std::less less; + typedef cds::atomicity::cache_friendly_item_counter item_counter; + }; + + typedef FeldmanHashMap< cds::gc::HP, Key, Value, traits_FeldmanHashMap_stdhash > FeldmanHashMap_hp_stdhash; + typedef FeldmanHashMap< cds::gc::DHP, Key, Value, traits_FeldmanHashMap_stdhash > FeldmanHashMap_dhp_stdhash; + typedef FeldmanHashMap< rcu_gpi, Key, Value, traits_FeldmanHashMap_stdhash > FeldmanHashMap_rcu_gpi_stdhash; + typedef FeldmanHashMap< rcu_gpb, Key, Value, traits_FeldmanHashMap_stdhash > FeldmanHashMap_rcu_gpb_stdhash; + typedef FeldmanHashMap< rcu_gpt, Key, Value, traits_FeldmanHashMap_stdhash > FeldmanHashMap_rcu_gpt_stdhash; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashMap< rcu_shb, Key, Value, traits_FeldmanHashMap_stdhash > FeldmanHashMap_rcu_shb_stdhash; +#endif + + struct traits_FeldmanHashMap_stdhash_stat: traits_FeldmanHashMap_stdhash + { + typedef cc::feldman_hashmap::stat<> stat; + typedef std::less less; + }; + + typedef FeldmanHashMap< cds::gc::HP, Key, Value, traits_FeldmanHashMap_stdhash_stat > FeldmanHashMap_hp_stdhash_stat; + typedef FeldmanHashMap< cds::gc::DHP, Key, Value, traits_FeldmanHashMap_stdhash_stat > FeldmanHashMap_dhp_stdhash_stat; + typedef FeldmanHashMap< rcu_gpi, Key, Value, traits_FeldmanHashMap_stdhash_stat > FeldmanHashMap_rcu_gpi_stdhash_stat; + typedef FeldmanHashMap< rcu_gpb, Key, Value, traits_FeldmanHashMap_stdhash_stat > FeldmanHashMap_rcu_gpb_stdhash_stat; + typedef FeldmanHashMap< rcu_gpt, Key, Value, traits_FeldmanHashMap_stdhash_stat > FeldmanHashMap_rcu_gpt_stdhash_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashMap< rcu_shb, Key, Value, traits_FeldmanHashMap_stdhash_stat > FeldmanHashMap_rcu_shb_stdhash_stat; +#endif + + // CityHash +#if CDS_BUILD_BITS == 64 + struct traits_FeldmanHashMap_city64 : public cc::feldman_hashmap::traits + { + typedef ::cds_test::city64 hash; + typedef ::cds_test::city64::less less; + typedef cds::atomicity::cache_friendly_item_counter item_counter; + }; + typedef FeldmanHashMap< cds::gc::HP, Key, Value, traits_FeldmanHashMap_city64 > FeldmanHashMap_hp_city64; + typedef FeldmanHashMap< cds::gc::DHP, Key, Value, traits_FeldmanHashMap_city64 > FeldmanHashMap_dhp_city64; + typedef FeldmanHashMap< rcu_gpi, Key, Value, traits_FeldmanHashMap_city64 > FeldmanHashMap_rcu_gpi_city64; + typedef FeldmanHashMap< rcu_gpb, Key, Value, traits_FeldmanHashMap_city64 > FeldmanHashMap_rcu_gpb_city64; + typedef FeldmanHashMap< rcu_gpt, Key, Value, traits_FeldmanHashMap_city64 > FeldmanHashMap_rcu_gpt_city64; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashMap< rcu_shb, Key, Value, traits_FeldmanHashMap_city64 > FeldmanHashMap_rcu_shb_city64; +#endif + + struct traits_FeldmanHashMap_city64_stat : public traits_FeldmanHashMap_city64 + { + typedef cc::feldman_hashmap::stat<> stat; + }; + typedef FeldmanHashMap< cds::gc::HP, Key, Value, traits_FeldmanHashMap_city64_stat > FeldmanHashMap_hp_city64_stat; + typedef FeldmanHashMap< cds::gc::DHP, Key, Value, traits_FeldmanHashMap_city64_stat > FeldmanHashMap_dhp_city64_stat; + typedef FeldmanHashMap< rcu_gpi, Key, Value, traits_FeldmanHashMap_city64_stat > FeldmanHashMap_rcu_gpi_city64_stat; + typedef FeldmanHashMap< rcu_gpb, Key, Value, traits_FeldmanHashMap_city64_stat > FeldmanHashMap_rcu_gpb_city64_stat; + typedef FeldmanHashMap< rcu_gpt, Key, Value, traits_FeldmanHashMap_city64_stat > FeldmanHashMap_rcu_gpt_city64_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashMap< rcu_shb, Key, Value, traits_FeldmanHashMap_city64_stat > FeldmanHashMap_rcu_shb_city64_stat; +#endif + + struct traits_FeldmanHashMap_city128 : public cc::feldman_hashmap::traits + { + typedef ::cds_test::city128 hash; + typedef ::cds_test::city128::less less; + typedef cds::atomicity::cache_friendly_item_counter item_counter; + }; + typedef FeldmanHashMap< cds::gc::HP, Key, Value, traits_FeldmanHashMap_city128 > FeldmanHashMap_hp_city128; + typedef FeldmanHashMap< cds::gc::DHP, Key, Value, traits_FeldmanHashMap_city128 > FeldmanHashMap_dhp_city128; + typedef FeldmanHashMap< rcu_gpi, Key, Value, traits_FeldmanHashMap_city128 > FeldmanHashMap_rcu_gpi_city128; + typedef FeldmanHashMap< rcu_gpb, Key, Value, traits_FeldmanHashMap_city128 > FeldmanHashMap_rcu_gpb_city128; + typedef FeldmanHashMap< rcu_gpt, Key, Value, traits_FeldmanHashMap_city128 > FeldmanHashMap_rcu_gpt_city128; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashMap< rcu_shb, Key, Value, traits_FeldmanHashMap_city128 > FeldmanHashMap_rcu_shb_city128; +#endif + + struct traits_FeldmanHashMap_city128_stat : public traits_FeldmanHashMap_city128 + { + typedef cc::feldman_hashmap::stat<> stat; + }; + typedef FeldmanHashMap< cds::gc::HP, Key, Value, traits_FeldmanHashMap_city128_stat > FeldmanHashMap_hp_city128_stat; + typedef FeldmanHashMap< cds::gc::DHP, Key, Value, traits_FeldmanHashMap_city128_stat > FeldmanHashMap_dhp_city128_stat; + typedef FeldmanHashMap< rcu_gpi, Key, Value, traits_FeldmanHashMap_city128_stat > FeldmanHashMap_rcu_gpi_city128_stat; + typedef FeldmanHashMap< rcu_gpb, Key, Value, traits_FeldmanHashMap_city128_stat > FeldmanHashMap_rcu_gpb_city128_stat; + typedef FeldmanHashMap< rcu_gpt, Key, Value, traits_FeldmanHashMap_city128_stat > FeldmanHashMap_rcu_gpt_city128_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashMap< rcu_shb, Key, Value, traits_FeldmanHashMap_city128_stat > FeldmanHashMap_rcu_shb_city128_stat; +#endif +#endif // CDS_BUILD_BITS == 64 + + + // for fixed-sized keys - no hash functor required + struct traits_FeldmanHashMap_fixed: public cc::feldman_hashmap::traits + { + typedef map::cmp compare; + typedef cds::atomicity::cache_friendly_item_counter item_counter; + }; + + typedef FeldmanHashMap< cds::gc::HP, Key, Value, traits_FeldmanHashMap_fixed > FeldmanHashMap_hp_fixed; + typedef FeldmanHashMap< cds::gc::DHP, Key, Value, traits_FeldmanHashMap_fixed > FeldmanHashMap_dhp_fixed; + typedef FeldmanHashMap< rcu_gpi, Key, Value, traits_FeldmanHashMap_fixed > FeldmanHashMap_rcu_gpi_fixed; + typedef FeldmanHashMap< rcu_gpb, Key, Value, traits_FeldmanHashMap_fixed > FeldmanHashMap_rcu_gpb_fixed; + typedef FeldmanHashMap< rcu_gpt, Key, Value, traits_FeldmanHashMap_fixed > FeldmanHashMap_rcu_gpt_fixed; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashMap< rcu_shb, Key, Value, traits_FeldmanHashMap_fixed > FeldmanHashMap_rcu_shb_fixed; +#endif + + struct traits_FeldmanHashMap_fixed_stat : public traits_FeldmanHashMap_fixed + { + typedef cc::feldman_hashmap::stat<> stat; + }; + typedef FeldmanHashMap< cds::gc::HP, Key, Value, traits_FeldmanHashMap_fixed_stat > FeldmanHashMap_hp_fixed_stat; + typedef FeldmanHashMap< cds::gc::DHP, Key, Value, traits_FeldmanHashMap_fixed_stat > FeldmanHashMap_dhp_fixed_stat; + typedef FeldmanHashMap< rcu_gpi, Key, Value, traits_FeldmanHashMap_fixed_stat > FeldmanHashMap_rcu_gpi_fixed_stat; + typedef FeldmanHashMap< rcu_gpb, Key, Value, traits_FeldmanHashMap_fixed_stat > FeldmanHashMap_rcu_gpb_fixed_stat; + typedef FeldmanHashMap< rcu_gpt, Key, Value, traits_FeldmanHashMap_fixed_stat > FeldmanHashMap_rcu_gpt_fixed_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashMap< rcu_shb, Key, Value, traits_FeldmanHashMap_fixed_stat > FeldmanHashMap_rcu_shb_fixed_stat; +#endif + + }; + + template + static inline void print_stat( cds_test::property_stream& o, FeldmanHashMap< GC, K, T, Traits > const& m ) + { + std::vector< cds::intrusive::feldman_hashset::level_statistics > level_stat; + m.get_level_statistics( level_stat ); + + o << m.statistics() + << level_stat; + } + +#define CDSSTRESS_FeldmanHashMap_case( fixture, test_case, feldman_map_type, key_type, value_type ) \ + TEST_F( fixture, feldman_map_type ) \ + { \ + typedef map::map_type< tag_FeldmanHashMap, key_type, value_type >::feldman_map_type map_type; \ + test_case(); \ + } + + +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED +# define CDSSTRESS_FeldmanHashMap_fixed_SHRCU( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_case( fixture, test_case, FeldmanHashMap_rcu_shb_fixed, key_type, value_type ) \ + +# define CDSSTRESS_FeldmanHashMap_stdhash_SHRCU( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_case( fixture, test_case, FeldmanHashMap_rcu_shb_stdhash, key_type, value_type ) \ + +# if CDS_BUILD_BITS == 64 +# define CDSSTRESS_FeldmanHashMap_city64_SHRCU( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_case( fixture, test_case, FeldmanHashMap_rcu_shb_city64, key_type, value_type ) \ + +# define CDSSTRESS_FeldmanHashMap_city128_SHRCU( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_case( fixture, test_case, FeldmanHashMap_rcu_shb_city64, key_type, value_type ) \ + +# else +# define CDSSTRESS_FeldmanHashMap_city64_SHRCU( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_FeldmanHashMap_city128_SHRCU( fixture, test_case, key_type, value_type ) +# endif + +#else +# define CDSSTRESS_FeldmanHashMap_fixed_SHRCU( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_FeldmanHashMap_stdhash_SHRCU( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_FeldmanHashMap_city64_SHRCU( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_FeldmanHashMap_city128_SHRCU( fixture, test_case, key_type, value_type ) +#endif + +#define CDSSTRESS_FeldmanHashMap_fixed_HP( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_case( fixture, test_case, FeldmanHashMap_hp_fixed, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_case( fixture, test_case, FeldmanHashMap_dhp_fixed, key_type, value_type ) \ + +#define CDSSTRESS_FeldmanHashMap_fixed_RCU( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_case( fixture, test_case, FeldmanHashMap_rcu_gpi_fixed, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_case( fixture, test_case, FeldmanHashMap_rcu_gpb_fixed, key_type, value_type ) \ + + //CDSSTRESS_FeldmanHashMap_fixed_SHRCU( fixture, test_case, key_type, value_type ) + +#define CDSSTRESS_FeldmanHashMap_fixed( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_fixed_HP( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_fixed_RCU( fixture, test_case, key_type, value_type ) \ + + +#define CDSSTRESS_FeldmanHashMap_stdhash_HP( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_case( fixture, test_case, FeldmanHashMap_hp_stdhash, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_case( fixture, test_case, FeldmanHashMap_dhp_stdhash, key_type, value_type ) \ + +#define CDSSTRESS_FeldmanHashMap_stdhash_RCU( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_case( fixture, test_case, FeldmanHashMap_rcu_gpi_stdhash, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_case( fixture, test_case, FeldmanHashMap_rcu_gpb_stdhash, key_type, value_type ) \ + + //CDSSTRESS_FeldmanHashMap_stdhash_SHRCU( fixture, test_case, key_type, value_type ) + +#define CDSSTRESS_FeldmanHashMap_stdhash( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_stdhash_HP( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_stdhash_RCU( fixture, test_case, key_type, value_type ) \ + + +#if CDS_BUILD_BITS == 64 +# define CDSSTRESS_FeldmanHashMap_city64_HP( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_case( fixture, test_case, FeldmanHashMap_hp_city64, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_case( fixture, test_case, FeldmanHashMap_dhp_city64, key_type, value_type ) \ + +# define CDSSTRESS_FeldmanHashMap_city64_RCU( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_case( fixture, test_case, FeldmanHashMap_rcu_gpi_city64, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_case( fixture, test_case, FeldmanHashMap_rcu_gpb_city64, key_type, value_type ) \ + + //CDSSTRESS_FeldmanHashMap_city64_SHRCU( fixture, test_case, key_type, value_type ) + +# define CDSSTRESS_FeldmanHashMap_city64( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_city64_HP( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_city64_RCU( fixture, test_case, key_type, value_type ) \ + + +# define CDSSTRESS_FeldmanHashMap_city128_HP( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_case( fixture, test_case, FeldmanHashMap_hp_city128, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_case( fixture, test_case, FeldmanHashMap_dhp_city128, key_type, value_type ) \ + +# define CDSSTRESS_FeldmanHashMap_city128_RCU( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_case( fixture, test_case, FeldmanHashMap_rcu_gpi_city128, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_case( fixture, test_case, FeldmanHashMap_rcu_gpb_city128, key_type, value_type ) \ + + //CDSSTRESS_FeldmanHashMap_city128_SHRCU( fixture, test_case, key_type, value_type ) + +# define CDSSTRESS_FeldmanHashMap_city128( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_city128_HP( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_city128_RCU( fixture, test_case, key_type, value_type ) \ + +# define CDSSTRESS_FeldmanHashMap_city_HP( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_city64_HP( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_city128_HP( fixture, test_case, key_type, value_type ) + +# define CDSSTRESS_FeldmanHashMap_city_RCU( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_city64_RCU( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_city128_RCU( fixture, test_case, key_type, value_type ) + +# define CDSSTRESS_FeldmanHashMap_city( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_city_HP( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_FeldmanHashMap_city_RCU( fixture, test_case, key_type, value_type ) + +#else +# define CDSSTRESS_FeldmanHashMap_city64_HP( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_FeldmanHashMap_city64_RCU( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_FeldmanHashMap_city64( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_FeldmanHashMap_city128_HP( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_FeldmanHashMap_city128_RCU( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_FeldmanHashMap_city128( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_FeldmanHashMap_city_HP( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_FeldmanHashMap_city_RCU( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_FeldmanHashMap_city( fixture, test_case, key_type, value_type ) +#endif + + +} // namespace map + +#endif // #ifndef CDSUNIT_MAP_TYPE_FELDMAN_HASHMAP_H diff --git a/test/stress/parallel/parallel-map/map_type_iterable_list.h b/test/stress/parallel/parallel-map/map_type_iterable_list.h new file mode 100644 index 00000000..0ad60fa1 --- /dev/null +++ b/test/stress/parallel/parallel-map/map_type_iterable_list.h @@ -0,0 +1,102 @@ +/* + 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_MAP_TYPE_ITERABLE_LIST_H +#define CDSUNIT_MAP_TYPE_ITERABLE_LIST_H + +#include "map_type.h" + +#include +#include + +#include + +namespace map { + + template + struct iterable_list_type + { + typedef typename map_type_base::key_compare compare; + typedef typename map_type_base::key_less less; + + struct traits_IterableList_cmp : + public cc::iterable_list::make_traits< + co::compare< compare > + >::type + {}; + typedef cc::IterableKVList< cds::gc::HP, Key, Value, traits_IterableList_cmp > IterableList_HP_cmp; + typedef cc::IterableKVList< cds::gc::DHP, Key, Value, traits_IterableList_cmp > IterableList_DHP_cmp; + + struct traits_IterableList_cmp_stat: public traits_IterableList_cmp + { + typedef cc::iterable_list::stat<> stat; + }; + typedef cc::IterableKVList< cds::gc::HP, Key, Value, traits_IterableList_cmp_stat > IterableList_HP_cmp_stat; + typedef cc::IterableKVList< cds::gc::DHP, Key, Value, traits_IterableList_cmp_stat > IterableList_DHP_cmp_stat; + + struct traits_IterableList_cmp_seqcst : + public cc::iterable_list::make_traits< + co::compare< compare > + ,co::memory_model< co::v::sequential_consistent > + >::type + {}; + typedef cc::IterableKVList< cds::gc::HP, Key, Value, traits_IterableList_cmp_seqcst > IterableList_HP_cmp_seqcst; + typedef cc::IterableKVList< cds::gc::DHP, Key, Value, traits_IterableList_cmp_seqcst > IterableList_DHP_cmp_seqcst; + + + struct traits_IterableList_less : + public cc::iterable_list::make_traits< + co::less< less > + >::type + {}; + typedef cc::IterableKVList< cds::gc::HP, Key, Value, traits_IterableList_less > IterableList_HP_less; + typedef cc::IterableKVList< cds::gc::DHP, Key, Value, traits_IterableList_less > IterableList_DHP_less; + + struct traits_IterableList_less_stat: public traits_IterableList_less + { + typedef cc::iterable_list::stat<> stat; + }; + typedef cc::IterableKVList< cds::gc::HP, Key, Value, traits_IterableList_less_stat > IterableList_HP_less_stat; + typedef cc::IterableKVList< cds::gc::DHP, Key, Value, 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::IterableKVList< cds::gc::HP, Key, Value, traits_IterableList_less_seqcst > IterableList_HP_less_seqcst; + typedef cc::IterableKVList< cds::gc::DHP, Key, Value, traits_IterableList_less_seqcst > IterableList_DHP_less_seqcst; + + }; + +} // namespace map + +#endif // ifndef CDSUNIT_MAP_TYPE_ITERABLE_LIST_H diff --git a/test/stress/parallel/parallel-map/map_type_lazy_list.h b/test/stress/parallel/parallel-map/map_type_lazy_list.h new file mode 100644 index 00000000..27675f0d --- /dev/null +++ b/test/stress/parallel/parallel-map/map_type_lazy_list.h @@ -0,0 +1,154 @@ +/* + 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_MAP_TYPE_LAZY_LIST_H +#define CDSUNIT_MAP_TYPE_LAZY_LIST_H + +#include "map_type.h" + +#include +#include +#include +#include + +#include + +namespace map { + + template + struct lazy_list_type + { + typedef typename map_type_base::key_compare compare; + typedef typename map_type_base::key_less less; + typedef typename map_type_base::equal_to equal_to; + + struct traits_LazyList_cmp: + public cc::lazy_list::make_traits< + co::compare< compare > + >::type + {}; + typedef cc::LazyKVList< cds::gc::HP, Key, Value, traits_LazyList_cmp > LazyList_HP_cmp; + typedef cc::LazyKVList< cds::gc::DHP, Key, Value, traits_LazyList_cmp > LazyList_DHP_cmp; + typedef cc::LazyKVList< cds::gc::nogc, Key, Value, traits_LazyList_cmp > LazyList_NOGC_cmp; + typedef cc::LazyKVList< rcu_gpi, Key, Value, traits_LazyList_cmp > LazyList_RCU_GPI_cmp; + typedef cc::LazyKVList< rcu_gpb, Key, Value, traits_LazyList_cmp > LazyList_RCU_GPB_cmp; + typedef cc::LazyKVList< rcu_gpt, Key, Value, traits_LazyList_cmp > LazyList_RCU_GPT_cmp; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef cc::LazyKVList< rcu_shb, Key, Value, 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::LazyKVList< cds::gc::HP, Key, Value, traits_LazyList_cmp_stat > LazyList_HP_cmp_stat; + typedef cc::LazyKVList< cds::gc::DHP, Key, Value, traits_LazyList_cmp_stat > LazyList_DHP_cmp_stat; + typedef cc::LazyKVList< cds::gc::nogc, Key, Value, traits_LazyList_cmp_stat > LazyList_NOGC_cmp_stat; + typedef cc::LazyKVList< rcu_gpi, Key, Value, traits_LazyList_cmp_stat > LazyList_RCU_GPI_cmp_stat; + typedef cc::LazyKVList< rcu_gpb, Key, Value, traits_LazyList_cmp_stat > LazyList_RCU_GPB_cmp_stat; + typedef cc::LazyKVList< rcu_gpt, Key, Value, traits_LazyList_cmp_stat > LazyList_RCU_GPT_cmp_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef cc::LazyKVList< rcu_shb, Key, Value, traits_LazyList_cmp_stat > LazyList_RCU_SHB_cmp_stat; +#endif + + struct traits_LazyList_unord : + public cc::lazy_list::make_traits< + co::equal_to< equal_to > + ,co::sort< false > + >::type + {}; + typedef cc::LazyKVList< cds::gc::nogc, Key, Value, traits_LazyList_unord > LazyList_NOGC_unord; + + struct traits_LazyList_cmp_seqcst : + public cc::lazy_list::make_traits< + co::compare< compare > + ,co::memory_model< co::v::sequential_consistent > + >::type + {}; + typedef cc::LazyKVList< cds::gc::HP, Key, Value, traits_LazyList_cmp_seqcst > LazyList_HP_cmp_seqcst; + typedef cc::LazyKVList< cds::gc::DHP, Key, Value, traits_LazyList_cmp_seqcst > LazyList_DHP_cmp_seqcst; + typedef cc::LazyKVList< cds::gc::nogc, Key, Value, traits_LazyList_cmp_seqcst > LazyList_NOGC_cmp_seqcst; + typedef cc::LazyKVList< rcu_gpi, Key, Value, traits_LazyList_cmp_seqcst > LazyList_RCU_GPI_cmp_seqcst; + typedef cc::LazyKVList< rcu_gpb, Key, Value, traits_LazyList_cmp_seqcst > LazyList_RCU_GPB_cmp_seqcst; + typedef cc::LazyKVList< rcu_gpt, Key, Value, traits_LazyList_cmp_seqcst > LazyList_RCU_GPT_cmp_seqcst; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef cc::LazyKVList< rcu_shb, Key, Value, 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::LazyKVList< cds::gc::HP, Key, Value, traits_LazyList_less > LazyList_HP_less; + typedef cc::LazyKVList< cds::gc::DHP, Key, Value, traits_LazyList_less > LazyList_DHP_less; + typedef cc::LazyKVList< cds::gc::nogc, Key, Value, traits_LazyList_less > LazyList_NOGC_less; + typedef cc::LazyKVList< rcu_gpi, Key, Value, traits_LazyList_less > LazyList_RCU_GPI_less; + typedef cc::LazyKVList< rcu_gpb, Key, Value, traits_LazyList_less > LazyList_RCU_GPB_less; + typedef cc::LazyKVList< rcu_gpt, Key, Value, traits_LazyList_less > LazyList_RCU_GPT_less; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef cc::LazyKVList< rcu_shb, Key, Value, 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::LazyKVList< cds::gc::HP, Key, Value, traits_LazyList_less_stat > LazyList_HP_less_stat; + typedef cc::LazyKVList< cds::gc::DHP, Key, Value, traits_LazyList_less_stat > LazyList_DHP_less_stat; + typedef cc::LazyKVList< cds::gc::nogc, Key, Value, traits_LazyList_less_stat > LazyList_NOGC_less_stat; + typedef cc::LazyKVList< rcu_gpi, Key, Value, traits_LazyList_less_stat > LazyList_RCU_GPI_less_stat; + typedef cc::LazyKVList< rcu_gpb, Key, Value, traits_LazyList_less_stat > LazyList_RCU_GPB_less_stat; + typedef cc::LazyKVList< rcu_gpt, Key, Value, traits_LazyList_less_stat > LazyList_RCU_GPT_less_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef cc::LazyKVList< rcu_shb, Key, Value, 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::LazyKVList< cds::gc::HP, Key, Value, traits_LazyList_less_seqcst > LazyList_HP_less_seqcst; + typedef cc::LazyKVList< cds::gc::DHP, Key, Value, traits_LazyList_less_seqcst > LazyList_DHP_less_seqcst; + typedef cc::LazyKVList< cds::gc::nogc, Key, Value, traits_LazyList_less_seqcst > LazyList_NOGC_less_seqcst; + typedef cc::LazyKVList< rcu_gpi, Key, Value, traits_LazyList_less_seqcst > LazyList_RCU_GPI_less_seqcst; + typedef cc::LazyKVList< rcu_gpb, Key, Value, traits_LazyList_less_seqcst > LazyList_RCU_GPB_less_seqcst; + typedef cc::LazyKVList< rcu_gpt, Key, Value, traits_LazyList_less_seqcst > LazyList_RCU_GPT_less_seqcst; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef cc::LazyKVList< rcu_shb, Key, Value, traits_LazyList_less_seqcst > LazyList_RCU_SHB_less_seqcst; +#endif + + }; + +} // namespace map + +#endif // ifndef CDSUNIT_MAP_TYPE_LAZY_LIST_H diff --git a/test/stress/parallel/parallel-map/map_type_michael.h b/test/stress/parallel/parallel-map/map_type_michael.h new file mode 100644 index 00000000..a07e463b --- /dev/null +++ b/test/stress/parallel/parallel-map/map_type_michael.h @@ -0,0 +1,372 @@ +/* + 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_MAP_TYPE_MICHAEL_H +#define CDSUNIT_MAP_TYPE_MICHAEL_H + +#include "map_type_michael_list.h" +#include "map_type_lazy_list.h" +#include "map_type_iterable_list.h" + +#include +#include +#include + +namespace map { + + template + class MichaelHashMap : public cc::MichaelHashMap< GC, List, Traits > + { + typedef cc::MichaelHashMap< GC, List, Traits > base_class; + public: + template + MichaelHashMap( Config const& cfg) + : base_class( cfg.s_nMapSize, 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_MichaelHashMap; + + template + struct map_type< tag_MichaelHashMap, Key, Value >: public map_type_base< Key, Value > + { + typedef map_type_base< Key, Value > base_class; + typedef typename base_class::key_compare compare; + typedef typename base_class::key_less less; + typedef typename base_class::equal_to equal_to; + typedef typename base_class::key_hash hash; + + struct traits_MichaelMap_hash : + public cc::michael_map::make_traits< + co::hash< hash > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > + >::type + {}; + + // *************************************************************************** + // MichaelHashMap based on MichaelKVList + typedef michael_list_type< Key, Value > ml; + + typedef MichaelHashMap< cds::gc::HP, typename ml::MichaelList_HP_cmp, traits_MichaelMap_hash > MichaelMap_HP_cmp; + typedef MichaelHashMap< cds::gc::DHP, typename ml::MichaelList_DHP_cmp, traits_MichaelMap_hash > MichaelMap_DHP_cmp; + typedef MichaelHashMap< cds::gc::nogc, typename ml::MichaelList_NOGC_cmp, traits_MichaelMap_hash > MichaelMap_NOGC_cmp; + typedef MichaelHashMap< rcu_gpi, typename ml::MichaelList_RCU_GPI_cmp, traits_MichaelMap_hash > MichaelMap_RCU_GPI_cmp; + typedef MichaelHashMap< rcu_gpb, typename ml::MichaelList_RCU_GPB_cmp, traits_MichaelMap_hash > MichaelMap_RCU_GPB_cmp; + typedef MichaelHashMap< rcu_gpt, typename ml::MichaelList_RCU_GPT_cmp, traits_MichaelMap_hash > MichaelMap_RCU_GPT_cmp; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef MichaelHashMap< rcu_shb, typename ml::MichaelList_RCU_SHB_cmp, traits_MichaelMap_hash > MichaelMap_RCU_SHB_cmp; +#endif + + typedef MichaelHashMap< cds::gc::HP, typename ml::MichaelList_HP_cmp_stat, traits_MichaelMap_hash > MichaelMap_HP_cmp_stat; + typedef MichaelHashMap< cds::gc::DHP, typename ml::MichaelList_DHP_cmp_stat, traits_MichaelMap_hash > MichaelMap_DHP_cmp_stat; + typedef MichaelHashMap< cds::gc::nogc, typename ml::MichaelList_NOGC_cmp_stat, traits_MichaelMap_hash > MichaelMap_NOGC_cmp_stat; + typedef MichaelHashMap< rcu_gpi, typename ml::MichaelList_RCU_GPI_cmp_stat, traits_MichaelMap_hash > MichaelMap_RCU_GPI_cmp_stat; + typedef MichaelHashMap< rcu_gpb, typename ml::MichaelList_RCU_GPB_cmp_stat, traits_MichaelMap_hash > MichaelMap_RCU_GPB_cmp_stat; + typedef MichaelHashMap< rcu_gpt, typename ml::MichaelList_RCU_GPT_cmp_stat, traits_MichaelMap_hash > MichaelMap_RCU_GPT_cmp_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef MichaelHashMap< rcu_shb, typename ml::MichaelList_RCU_SHB_cmp_stat, traits_MichaelMap_hash > MichaelMap_RCU_SHB_cmp_stat; +#endif + + typedef MichaelHashMap< cds::gc::HP, typename ml::MichaelList_HP_less, traits_MichaelMap_hash > MichaelMap_HP_less; + typedef MichaelHashMap< cds::gc::DHP, typename ml::MichaelList_DHP_less, traits_MichaelMap_hash > MichaelMap_DHP_less; + typedef MichaelHashMap< cds::gc::nogc, typename ml::MichaelList_NOGC_less, traits_MichaelMap_hash > MichaelMap_NOGC_less; + typedef MichaelHashMap< rcu_gpi, typename ml::MichaelList_RCU_GPI_less, traits_MichaelMap_hash > MichaelMap_RCU_GPI_less; + typedef MichaelHashMap< rcu_gpb, typename ml::MichaelList_RCU_GPB_less, traits_MichaelMap_hash > MichaelMap_RCU_GPB_less; + typedef MichaelHashMap< rcu_gpt, typename ml::MichaelList_RCU_GPT_less, traits_MichaelMap_hash > MichaelMap_RCU_GPT_less; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef MichaelHashMap< rcu_shb, typename ml::MichaelList_RCU_SHB_less, traits_MichaelMap_hash > MichaelMap_RCU_SHB_less; +#endif + + typedef MichaelHashMap< cds::gc::HP, typename ml::MichaelList_HP_less_stat, traits_MichaelMap_hash > MichaelMap_HP_less_stat; + typedef MichaelHashMap< cds::gc::DHP, typename ml::MichaelList_DHP_less_stat, traits_MichaelMap_hash > MichaelMap_DHP_less_stat; + typedef MichaelHashMap< cds::gc::nogc, typename ml::MichaelList_NOGC_less_stat, traits_MichaelMap_hash > MichaelMap_NOGC_less_stat; + typedef MichaelHashMap< rcu_gpi, typename ml::MichaelList_RCU_GPI_less_stat, traits_MichaelMap_hash > MichaelMap_RCU_GPI_less_stat; + typedef MichaelHashMap< rcu_gpb, typename ml::MichaelList_RCU_GPB_less_stat, traits_MichaelMap_hash > MichaelMap_RCU_GPB_less_stat; + typedef MichaelHashMap< rcu_gpt, typename ml::MichaelList_RCU_GPT_less_stat, traits_MichaelMap_hash > MichaelMap_RCU_GPT_less_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef MichaelHashMap< rcu_shb, typename ml::MichaelList_RCU_SHB_less_stat, traits_MichaelMap_hash > MichaelMap_RCU_SHB_less_stat; +#endif + + typedef MichaelHashMap< cds::gc::HP, typename ml::MichaelList_HP_cmp_seqcst, traits_MichaelMap_hash > MichaelMap_HP_cmp_seqcst; + typedef MichaelHashMap< cds::gc::DHP, typename ml::MichaelList_DHP_cmp_seqcst, traits_MichaelMap_hash > MichaelMap_DHP_cmp_seqcst; + typedef MichaelHashMap< cds::gc::nogc, typename ml::MichaelList_NOGC_cmp_seqcst, traits_MichaelMap_hash > MichaelMap_NOGC_cmp_seqcst; + typedef MichaelHashMap< rcu_gpi, typename ml::MichaelList_RCU_GPI_cmp_seqcst, traits_MichaelMap_hash > MichaelMap_RCU_GPI_cmp_seqcst; + typedef MichaelHashMap< rcu_gpb, typename ml::MichaelList_RCU_GPB_cmp_seqcst, traits_MichaelMap_hash > MichaelMap_RCU_GPB_cmp_seqcst; + typedef MichaelHashMap< rcu_gpt, typename ml::MichaelList_RCU_GPT_cmp_seqcst, traits_MichaelMap_hash > MichaelMap_RCU_GPT_cmp_seqcst; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef MichaelHashMap< rcu_shb, typename ml::MichaelList_RCU_SHB_cmp_seqcst, traits_MichaelMap_hash > MichaelMap_RCU_SHB_cmp_seqcst; +#endif + + typedef MichaelHashMap< cds::gc::HP, typename ml::MichaelList_HP_less_seqcst, traits_MichaelMap_hash > MichaelMap_HP_less_seqcst; + typedef MichaelHashMap< cds::gc::DHP, typename ml::MichaelList_DHP_less_seqcst, traits_MichaelMap_hash > MichaelMap_DHP_less_seqcst; + typedef MichaelHashMap< cds::gc::nogc, typename ml::MichaelList_NOGC_less_seqcst, traits_MichaelMap_hash > MichaelMap_NOGC_less_seqcst; + typedef MichaelHashMap< rcu_gpi, typename ml::MichaelList_RCU_GPI_less_seqcst, traits_MichaelMap_hash > MichaelMap_RCU_GPI_less_seqcst; + typedef MichaelHashMap< rcu_gpb, typename ml::MichaelList_RCU_GPB_less_seqcst, traits_MichaelMap_hash > MichaelMap_RCU_GPB_less_seqcst; + typedef MichaelHashMap< rcu_gpt, typename ml::MichaelList_RCU_GPT_less_seqcst, traits_MichaelMap_hash > MichaelMap_RCU_GPT_less_seqcst; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef MichaelHashMap< rcu_shb, typename ml::MichaelList_RCU_SHB_less_seqcst, traits_MichaelMap_hash > MichaelMap_RCU_SHB_less_seqcst; +#endif + + + // *************************************************************************** + // MichaelHashMap based on LazyKVList + typedef lazy_list_type< Key, Value > ll; + + typedef MichaelHashMap< cds::gc::HP, typename ll::LazyList_HP_cmp, traits_MichaelMap_hash > MichaelMap_Lazy_HP_cmp; + typedef MichaelHashMap< cds::gc::DHP, typename ll::LazyList_DHP_cmp, traits_MichaelMap_hash > MichaelMap_Lazy_DHP_cmp; + typedef MichaelHashMap< cds::gc::nogc, typename ll::LazyList_NOGC_cmp, traits_MichaelMap_hash > MichaelMap_Lazy_NOGC_cmp; + typedef MichaelHashMap< rcu_gpi, typename ll::LazyList_RCU_GPI_cmp, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_GPI_cmp; + typedef MichaelHashMap< rcu_gpb, typename ll::LazyList_RCU_GPB_cmp, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_GPB_cmp; + typedef MichaelHashMap< rcu_gpt, typename ll::LazyList_RCU_GPT_cmp, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_GPT_cmp; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef MichaelHashMap< rcu_shb, typename ll::LazyList_RCU_SHB_cmp, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_SHB_cmp; +#endif + + typedef MichaelHashMap< cds::gc::HP, typename ll::LazyList_HP_cmp_stat, traits_MichaelMap_hash > MichaelMap_Lazy_HP_cmp_stat; + typedef MichaelHashMap< cds::gc::DHP, typename ll::LazyList_DHP_cmp_stat, traits_MichaelMap_hash > MichaelMap_Lazy_DHP_cmp_stat; + typedef MichaelHashMap< cds::gc::nogc, typename ll::LazyList_NOGC_cmp_stat, traits_MichaelMap_hash > MichaelMap_Lazy_NOGC_cmp_stat; + typedef MichaelHashMap< rcu_gpi, typename ll::LazyList_RCU_GPI_cmp_stat, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_GPI_cmp_stat; + typedef MichaelHashMap< rcu_gpb, typename ll::LazyList_RCU_GPB_cmp_stat, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_GPB_cmp_stat; + typedef MichaelHashMap< rcu_gpt, typename ll::LazyList_RCU_GPT_cmp_stat, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_GPT_cmp_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef MichaelHashMap< rcu_shb, typename ll::LazyList_RCU_SHB_cmp_stat, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_SHB_cmp_stat; +#endif + + typedef MichaelHashMap< cds::gc::nogc, typename ll::LazyList_NOGC_unord, traits_MichaelMap_hash > MichaelMap_Lazy_NOGC_unord; + + typedef MichaelHashMap< cds::gc::HP, typename ll::LazyList_HP_less, traits_MichaelMap_hash > MichaelMap_Lazy_HP_less; + typedef MichaelHashMap< cds::gc::DHP, typename ll::LazyList_DHP_less, traits_MichaelMap_hash > MichaelMap_Lazy_DHP_less; + typedef MichaelHashMap< cds::gc::nogc, typename ll::LazyList_NOGC_less, traits_MichaelMap_hash > MichaelMap_Lazy_NOGC_less; + typedef MichaelHashMap< rcu_gpi, typename ll::LazyList_RCU_GPI_less, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_GPI_less; + typedef MichaelHashMap< rcu_gpb, typename ll::LazyList_RCU_GPB_less, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_GPB_less; + typedef MichaelHashMap< rcu_gpt, typename ll::LazyList_RCU_GPT_less, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_GPT_less; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef MichaelHashMap< rcu_shb, typename ll::LazyList_RCU_SHB_less, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_SHB_less; +#endif + + typedef MichaelHashMap< cds::gc::HP, typename ll::LazyList_HP_less_stat, traits_MichaelMap_hash > MichaelMap_Lazy_HP_less_stat; + typedef MichaelHashMap< cds::gc::DHP, typename ll::LazyList_DHP_less_stat, traits_MichaelMap_hash > MichaelMap_Lazy_DHP_less_stat; + typedef MichaelHashMap< cds::gc::nogc, typename ll::LazyList_NOGC_less_stat, traits_MichaelMap_hash > MichaelMap_Lazy_NOGC_less_stat; + typedef MichaelHashMap< rcu_gpi, typename ll::LazyList_RCU_GPI_less_stat, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_GPI_less_stat; + typedef MichaelHashMap< rcu_gpb, typename ll::LazyList_RCU_GPB_less_stat, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_GPB_less_stat; + typedef MichaelHashMap< rcu_gpt, typename ll::LazyList_RCU_GPT_less_stat, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_GPT_less_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef MichaelHashMap< rcu_shb, typename ll::LazyList_RCU_SHB_less_stat, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_SHB_less_stat; +#endif + + typedef MichaelHashMap< cds::gc::HP, typename ll::LazyList_HP_cmp_seqcst, traits_MichaelMap_hash > MichaelMap_Lazy_HP_cmp_seqcst; + typedef MichaelHashMap< cds::gc::DHP, typename ll::LazyList_DHP_cmp_seqcst, traits_MichaelMap_hash > MichaelMap_Lazy_DHP_cmp_seqcst; + typedef MichaelHashMap< cds::gc::nogc, typename ll::LazyList_NOGC_cmp_seqcst, traits_MichaelMap_hash > MichaelMap_Lazy_NOGC_cmp_seqcst; + typedef MichaelHashMap< rcu_gpi, typename ll::LazyList_RCU_GPI_cmp_seqcst, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_GPI_cmp_seqcst; + typedef MichaelHashMap< rcu_gpb, typename ll::LazyList_RCU_GPB_cmp_seqcst, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_GPB_cmp_seqcst; + typedef MichaelHashMap< rcu_gpt, typename ll::LazyList_RCU_GPT_cmp_seqcst, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_GPT_cmp_seqcst; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef MichaelHashMap< rcu_shb, typename ll::LazyList_RCU_SHB_cmp_seqcst, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_SHB_cmp_seqcst; +#endif + + typedef MichaelHashMap< cds::gc::HP, typename ll::LazyList_HP_less_seqcst, traits_MichaelMap_hash > MichaelMap_Lazy_HP_less_seqcst; + typedef MichaelHashMap< cds::gc::DHP, typename ll::LazyList_DHP_less_seqcst, traits_MichaelMap_hash > MichaelMap_Lazy_DHP_less_seqcst; + typedef MichaelHashMap< cds::gc::nogc, typename ll::LazyList_NOGC_less_seqcst, traits_MichaelMap_hash > MichaelMap_Lazy_NOGC_less_seqcst; + typedef MichaelHashMap< rcu_gpi, typename ll::LazyList_RCU_GPI_less_seqcst, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_GPI_less_seqcst; + typedef MichaelHashMap< rcu_gpb, typename ll::LazyList_RCU_GPB_less_seqcst, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_GPB_less_seqcst; + typedef MichaelHashMap< rcu_gpt, typename ll::LazyList_RCU_GPT_less_seqcst, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_GPT_less_seqcst; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef MichaelHashMap< rcu_shb, typename ll::LazyList_RCU_SHB_less_seqcst, traits_MichaelMap_hash > MichaelMap_Lazy_RCU_SHB_less_seqcst; +#endif + + + // *************************************************************************** + // MichaelHashMap based on IterableKVList + typedef iterable_list_type< Key, Value > il; + + typedef MichaelHashMap< cds::gc::HP, typename il::IterableList_HP_cmp, traits_MichaelMap_hash > MichaelMap_Iterable_HP_cmp; + typedef MichaelHashMap< cds::gc::DHP, typename il::IterableList_DHP_cmp, traits_MichaelMap_hash > MichaelMap_Iterable_DHP_cmp; + + typedef MichaelHashMap< cds::gc::HP, typename il::IterableList_HP_cmp_stat, traits_MichaelMap_hash > MichaelMap_Iterable_HP_cmp_stat; + typedef MichaelHashMap< cds::gc::DHP, typename il::IterableList_DHP_cmp_stat, traits_MichaelMap_hash > MichaelMap_Iterable_DHP_cmp_stat; + + typedef MichaelHashMap< cds::gc::HP, typename il::IterableList_HP_less, traits_MichaelMap_hash > MichaelMap_Iterable_HP_less; + typedef MichaelHashMap< cds::gc::DHP, typename il::IterableList_DHP_less, traits_MichaelMap_hash > MichaelMap_Iterable_DHP_less; + + typedef MichaelHashMap< cds::gc::HP, typename il::IterableList_HP_less_stat, traits_MichaelMap_hash > MichaelMap_Iterable_HP_less_stat; + typedef MichaelHashMap< cds::gc::DHP, typename il::IterableList_DHP_less_stat, traits_MichaelMap_hash > MichaelMap_Iterable_DHP_less_stat; + + typedef MichaelHashMap< cds::gc::HP, typename il::IterableList_HP_cmp_seqcst, traits_MichaelMap_hash > MichaelMap_Iterable_HP_cmp_seqcst; + typedef MichaelHashMap< cds::gc::DHP, typename il::IterableList_DHP_cmp_seqcst, traits_MichaelMap_hash > MichaelMap_Iterable_DHP_cmp_seqcst; + + }; +} // namespace map + +#define CDSSTRESS_MichaelMap_case( fixture, test_case, michael_map_type, key_type, value_type ) \ + TEST_P( fixture, michael_map_type ) \ + { \ + typedef map::map_type< tag_MichaelHashMap, key_type, value_type >::michael_map_type map_type; \ + test_case(); \ + } + +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + +#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL > 1 +# define CDSSTRESS_MichaelMap_SHRCU_2( fixture, test_case, key_type, value_type ) \ + +#else +# define CDSSTRESS_MichaelMap_SHRCU_2( fixture, test_case, key_type, value_type ) +#endif + +#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL == 1 +# define CDSSTRESS_MichaelMap_SHRCU_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_RCU_SHT_cmp, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_RCU_SHB_less, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_Lazy_RCU_SHT_cmp, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_Lazy_RCU_SHB_less, key_type, value_type ) \ + +#else +# define CDSSTRESS_MichaelMap_SHRCU_1( fixture, test_case, key_type, value_type ) +#endif + +# define CDSSTRESS_MichaelMap_SHRCU( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_RCU_SHB_cmp, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_RCU_SHT_less, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_Lazy_RCU_SHB_cmp, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_Lazy_RCU_SHT_less, key_type, value_type ) \ + CDSSTRESS_MichaelMap_SHRCU_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_MichaelMap_SHRCU_2( fixture, test_case, key_type, value_type ) \ + +#else +# define CDSSTRESS_MichaelMap_SHRCU( fixture, test_case, key_type, value_type ) +#endif + +#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL > 1 +# define CDSSTRESS_MichaelMap_HP_2( fixture, test_case, key_type, value_type ) \ + +# define CDSSTRESS_MichaelMap_RCU_2( fixture, test_case, key_type, value_type ) \ + +# define CDSSTRESS_MichaelMap_2( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_MichaelMap_HP_2( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_MichaelMap_RCU_2( fixture, test_case, key_type, value_type ) \ + +#else +# define CDSSTRESS_MichaelMap_HP_2( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_MichaelMap_RCU_2( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_MichaelMap_2( fixture, test_case, key_type, value_type ) +#endif + +#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL == 1 + +# define CDSSTRESS_MichaelMap_Iterable_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_Iterable_DHP_cmp, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_Iterable_HP_less, key_type, value_type ) \ + +# define CDSSTRESS_MichaelMap_HP_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_DHP_cmp, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_HP_less, key_type, value_type ) \ + \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_Lazy_DHP_cmp, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_Lazy_HP_less, key_type, value_type ) \ + +# define CDSSTRESS_MichaelMap_RCU_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_RCU_GPB_cmp, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_RCU_GPI_less, key_type, value_type ) \ + \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_Lazy_RCU_GPB_cmp, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_Lazy_RCU_GPI_less, key_type, value_type ) \ + \ + CDSSTRESS_MichaelMap_SHRCU( fixture, test_case, key_type, value_type ) \ + +# define CDSSTRESS_MichaelMap_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_MichaelMap_HP_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_MichaelMap_RCU_1( fixture, test_case, key_type, value_type ) \ + +#else +# define CDSSTRESS_MichaelMap_Iterable_1( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_MichaelMap_HP_1( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_MichaelMap_RCU_1( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_MichaelMap_1( fixture, test_case, key_type, value_type ) +#endif + +#define CDSSTRESS_MichaelMap_Iterable( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_Iterable_HP_cmp, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_Iterable_DHP_less, key_type, value_type ) \ + CDSSTRESS_MichaelMap_Iterable_1( fixture, test_case, key_type, value_type ) \ + +#define CDSSTRESS_MichaelMap_HP( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_HP_cmp, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_DHP_less, key_type, value_type ) \ + \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_Lazy_HP_cmp, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_Lazy_DHP_less, key_type, value_type ) \ + \ + CDSSTRESS_MichaelMap_Iterable( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_MichaelMap_HP_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_MichaelMap_HP_2( fixture, test_case, key_type, value_type ) \ + + +#define CDSSTRESS_MichaelMap_RCU( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_RCU_GPI_cmp, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_RCU_GPB_less, key_type, value_type ) \ + \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_Lazy_RCU_GPI_cmp, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_Lazy_RCU_GPB_less, key_type, value_type ) \ + \ + CDSSTRESS_MichaelMap_RCU_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_MichaelMap_RCU_2( fixture, test_case, key_type, value_type ) \ + +#define CDSSTRESS_MichaelMap( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_MichaelMap_HP( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_MichaelMap_RCU( fixture, test_case, key_type, value_type ) \ + +#define CDSSTRESS_MichaelMap_nogc( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_NOGC_cmp, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_NOGC_less, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_Lazy_NOGC_cmp, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_Lazy_NOGC_unord, key_type, value_type ) \ + CDSSTRESS_MichaelMap_case( fixture, test_case, MichaelMap_Lazy_NOGC_less, key_type, value_type ) \ + + +#endif // ifndef CDSUNIT_MAP_TYPE_MICHAEL_H diff --git a/test/stress/parallel/parallel-map/map_type_michael_list.h b/test/stress/parallel/parallel-map/map_type_michael_list.h new file mode 100644 index 00000000..e09a3b73 --- /dev/null +++ b/test/stress/parallel/parallel-map/map_type_michael_list.h @@ -0,0 +1,145 @@ +/* + 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_MAP_TYPE_MICHAEL_LIST_H +#define CDSUNIT_MAP_TYPE_MICHAEL_LIST_H + +#include "map_type.h" + +#include +#include +#include +#include + +#include + +namespace map { + + template + struct michael_list_type + { + typedef typename map_type_base::key_compare compare; + typedef typename map_type_base::key_less less; + + struct traits_MichaelList_cmp : + public cc::michael_list::make_traits< + co::compare< compare > + >::type + {}; + typedef cc::MichaelKVList< cds::gc::HP, Key, Value, traits_MichaelList_cmp > MichaelList_HP_cmp; + typedef cc::MichaelKVList< cds::gc::DHP, Key, Value, traits_MichaelList_cmp > MichaelList_DHP_cmp; + typedef cc::MichaelKVList< cds::gc::nogc, Key, Value, traits_MichaelList_cmp > MichaelList_NOGC_cmp; + typedef cc::MichaelKVList< rcu_gpi, Key, Value, traits_MichaelList_cmp > MichaelList_RCU_GPI_cmp; + typedef cc::MichaelKVList< rcu_gpb, Key, Value, traits_MichaelList_cmp > MichaelList_RCU_GPB_cmp; + typedef cc::MichaelKVList< rcu_gpt, Key, Value, traits_MichaelList_cmp > MichaelList_RCU_GPT_cmp; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef cc::MichaelKVList< rcu_shb, Key, Value, 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::MichaelKVList< cds::gc::HP, Key, Value, traits_MichaelList_cmp_stat > MichaelList_HP_cmp_stat; + typedef cc::MichaelKVList< cds::gc::DHP, Key, Value, traits_MichaelList_cmp_stat > MichaelList_DHP_cmp_stat; + typedef cc::MichaelKVList< cds::gc::nogc, Key, Value, traits_MichaelList_cmp_stat > MichaelList_NOGC_cmp_stat; + typedef cc::MichaelKVList< rcu_gpi, Key, Value, traits_MichaelList_cmp_stat > MichaelList_RCU_GPI_cmp_stat; + typedef cc::MichaelKVList< rcu_gpb, Key, Value, traits_MichaelList_cmp_stat > MichaelList_RCU_GPB_cmp_stat; + typedef cc::MichaelKVList< rcu_gpt, Key, Value, traits_MichaelList_cmp_stat > MichaelList_RCU_GPT_cmp_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef cc::MichaelKVList< rcu_shb, Key, Value, traits_MichaelList_cmp_stat > MichaelList_RCU_SHB_cmp_stat; +#endif + + struct traits_MichaelList_cmp_seqcst : + public cc::michael_list::make_traits< + co::compare< compare > + ,co::memory_model< co::v::sequential_consistent > + >::type + {}; + typedef cc::MichaelKVList< cds::gc::HP, Key, Value, traits_MichaelList_cmp_seqcst > MichaelList_HP_cmp_seqcst; + typedef cc::MichaelKVList< cds::gc::DHP, Key, Value, traits_MichaelList_cmp_seqcst > MichaelList_DHP_cmp_seqcst; + typedef cc::MichaelKVList< cds::gc::nogc, Key, Value, traits_MichaelList_cmp_seqcst > MichaelList_NOGC_cmp_seqcst; + typedef cc::MichaelKVList< rcu_gpi, Key, Value, traits_MichaelList_cmp_seqcst > MichaelList_RCU_GPI_cmp_seqcst; + typedef cc::MichaelKVList< rcu_gpb, Key, Value, traits_MichaelList_cmp_seqcst > MichaelList_RCU_GPB_cmp_seqcst; + typedef cc::MichaelKVList< rcu_gpt, Key, Value, traits_MichaelList_cmp_seqcst > MichaelList_RCU_GPT_cmp_seqcst; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef cc::MichaelKVList< rcu_shb, Key, Value, 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::MichaelKVList< cds::gc::HP, Key, Value, traits_MichaelList_less > MichaelList_HP_less; + typedef cc::MichaelKVList< cds::gc::DHP, Key, Value, traits_MichaelList_less > MichaelList_DHP_less; + typedef cc::MichaelKVList< cds::gc::nogc, Key, Value, traits_MichaelList_less > MichaelList_NOGC_less; + typedef cc::MichaelKVList< rcu_gpi, Key, Value, traits_MichaelList_less > MichaelList_RCU_GPI_less; + typedef cc::MichaelKVList< rcu_gpb, Key, Value, traits_MichaelList_less > MichaelList_RCU_GPB_less; + typedef cc::MichaelKVList< rcu_gpt, Key, Value, traits_MichaelList_less > MichaelList_RCU_GPT_less; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef cc::MichaelKVList< rcu_shb, Key, Value, 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::MichaelKVList< cds::gc::HP, Key, Value, traits_MichaelList_less_stat > MichaelList_HP_less_stat; + typedef cc::MichaelKVList< cds::gc::DHP, Key, Value, traits_MichaelList_less_stat > MichaelList_DHP_less_stat; + typedef cc::MichaelKVList< cds::gc::nogc, Key, Value, traits_MichaelList_less_stat > MichaelList_NOGC_less_stat; + typedef cc::MichaelKVList< rcu_gpi, Key, Value, traits_MichaelList_less_stat > MichaelList_RCU_GPI_less_stat; + typedef cc::MichaelKVList< rcu_gpb, Key, Value, traits_MichaelList_less_stat > MichaelList_RCU_GPB_less_stat; + typedef cc::MichaelKVList< rcu_gpt, Key, Value, traits_MichaelList_less_stat > MichaelList_RCU_GPT_less_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef cc::MichaelKVList< rcu_shb, Key, Value, 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::MichaelKVList< cds::gc::HP, Key, Value, traits_MichaelList_less_seqcst > MichaelList_HP_less_seqcst; + typedef cc::MichaelKVList< cds::gc::DHP, Key, Value, traits_MichaelList_less_seqcst > MichaelList_DHP_less_seqcst; + typedef cc::MichaelKVList< cds::gc::nogc, Key, Value, traits_MichaelList_less_seqcst > MichaelList_NOGC_less_seqcst; + typedef cc::MichaelKVList< rcu_gpi, Key, Value, traits_MichaelList_less_seqcst > MichaelList_RCU_GPI_less_seqcst; + typedef cc::MichaelKVList< rcu_gpb, Key, Value, traits_MichaelList_less_seqcst > MichaelList_RCU_GPB_less_seqcst; + typedef cc::MichaelKVList< rcu_gpt, Key, Value, traits_MichaelList_less_seqcst > MichaelList_RCU_GPT_less_seqcst; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef cc::MichaelKVList< rcu_shb, Key, Value, traits_MichaelList_less_seqcst > MichaelList_RCU_SHB_less_seqcst; +#endif + + }; + +} // namespace map + +#endif // ifndef CDSUNIT_MAP_TYPE_MICHAEL_LIST_H diff --git a/test/stress/parallel/parallel-map/map_type_skip_list.h b/test/stress/parallel/parallel-map/map_type_skip_list.h new file mode 100644 index 00000000..b56f14ec --- /dev/null +++ b/test/stress/parallel/parallel-map/map_type_skip_list.h @@ -0,0 +1,484 @@ +/* + 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_MAP_TYPE_SKIP_LIST_H +#define CDSUNIT_MAP_TYPE_SKIP_LIST_H + +#include "map_type.h" + +#include +#include +#include +#include + +#include + +namespace map { + + template + class SkipListMap : public cc::SkipListMap< GC, Key, T, Traits > + { + typedef cc::SkipListMap< GC, Key, T, Traits > base_class; + public: + template + SkipListMap( Config const& /*cfg*/) + : base_class() + {} + + std::pair extract_min_key() + { + auto xp = base_class::extract_min(); + if ( xp ) + return std::make_pair( xp->first, true ); + return std::make_pair( Key(), false ); + } + + std::pair extract_max_key() + { + auto xp = base_class::extract_max(); + if ( xp ) + return std::make_pair( xp->first, true ); + return std::make_pair( Key(), false ); + } + + // 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_SkipListMap; + + template + struct map_type< tag_SkipListMap, Key, Value >: public map_type_base< Key, Value > + { + typedef map_type_base< Key, Value > base_class; + typedef typename base_class::key_compare compare; + typedef typename base_class::key_less less; + + class traits_SkipListMap_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 SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_turbo32 > SkipListMap_hp_less_turbo32; + typedef SkipListMap< cds::gc::DHP, Key, Value, traits_SkipListMap_less_turbo32 > SkipListMap_dhp_less_turbo32; + typedef SkipListMap< cds::gc::nogc, Key, Value, traits_SkipListMap_less_turbo32 > SkipListMap_nogc_less_turbo32; + typedef SkipListMap< rcu_gpi, Key, Value, traits_SkipListMap_less_turbo32 > SkipListMap_rcu_gpi_less_turbo32; + typedef SkipListMap< rcu_gpb, Key, Value, traits_SkipListMap_less_turbo32 > SkipListMap_rcu_gpb_less_turbo32; + typedef SkipListMap< rcu_gpt, Key, Value, traits_SkipListMap_less_turbo32 > SkipListMap_rcu_gpt_less_turbo32; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SkipListMap< rcu_shb, Key, Value, traits_SkipListMap_less_turbo32 > SkipListMap_rcu_shb_less_turbo32; +#endif + + class traits_SkipListMap_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 SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_turbo24 > SkipListMap_hp_less_turbo24; + typedef SkipListMap< cds::gc::DHP, Key, Value, traits_SkipListMap_less_turbo24 > SkipListMap_dhp_less_turbo24; + typedef SkipListMap< cds::gc::nogc, Key, Value, traits_SkipListMap_less_turbo24 > SkipListMap_nogc_less_turbo24; + typedef SkipListMap< rcu_gpi, Key, Value, traits_SkipListMap_less_turbo24 > SkipListMap_rcu_gpi_less_turbo24; + typedef SkipListMap< rcu_gpb, Key, Value, traits_SkipListMap_less_turbo24 > SkipListMap_rcu_gpb_less_turbo24; + typedef SkipListMap< rcu_gpt, Key, Value, traits_SkipListMap_less_turbo24 > SkipListMap_rcu_gpt_less_turbo24; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SkipListMap< rcu_shb, Key, Value, traits_SkipListMap_less_turbo24 > SkipListMap_rcu_shb_less_turbo24; +#endif + + class traits_SkipListMap_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 SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_turbo16 > SkipListMap_hp_less_turbo16; + typedef SkipListMap< cds::gc::DHP, Key, Value, traits_SkipListMap_less_turbo16 > SkipListMap_dhp_less_turbo16; + typedef SkipListMap< cds::gc::nogc, Key, Value, traits_SkipListMap_less_turbo16 > SkipListMap_nogc_less_turbo16; + typedef SkipListMap< rcu_gpi, Key, Value, traits_SkipListMap_less_turbo16 > SkipListMap_rcu_gpi_less_turbo16; + typedef SkipListMap< rcu_gpb, Key, Value, traits_SkipListMap_less_turbo16 > SkipListMap_rcu_gpb_less_turbo16; + typedef SkipListMap< rcu_gpt, Key, Value, traits_SkipListMap_less_turbo16 > SkipListMap_rcu_gpt_less_turbo16; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SkipListMap< rcu_shb, Key, Value, traits_SkipListMap_less_turbo16 > SkipListMap_rcu_shb_less_turbo16; +#endif + + class traits_SkipListMap_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 SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_turbo32_seqcst > SkipListMap_hp_less_turbo32_seqcst; + typedef SkipListMap< cds::gc::DHP, Key, Value, traits_SkipListMap_less_turbo32_seqcst > SkipListMap_dhp_less_turbo32_seqcst; + typedef SkipListMap< cds::gc::nogc, Key, Value, traits_SkipListMap_less_turbo32_seqcst > SkipListMap_nogc_less_turbo32_seqcst; + typedef SkipListMap< rcu_gpi, Key, Value, traits_SkipListMap_less_turbo32_seqcst > SkipListMap_rcu_gpi_less_turbo32_seqcst; + typedef SkipListMap< rcu_gpb, Key, Value, traits_SkipListMap_less_turbo32_seqcst > SkipListMap_rcu_gpb_less_turbo32_seqcst; + typedef SkipListMap< rcu_gpt, Key, Value, traits_SkipListMap_less_turbo32_seqcst > SkipListMap_rcu_gpt_less_turbo32_seqcst; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SkipListMap< rcu_shb, Key, Value, traits_SkipListMap_less_turbo32_seqcst > SkipListMap_rcu_shb_less_turbo32_seqcst; +#endif + + class traits_SkipListMap_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 SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_turbo32_stat > SkipListMap_hp_less_turbo32_stat; + typedef SkipListMap< cds::gc::DHP, Key, Value, traits_SkipListMap_less_turbo32_stat > SkipListMap_dhp_less_turbo32_stat; + typedef SkipListMap< cds::gc::nogc, Key, Value, traits_SkipListMap_less_turbo32_stat > SkipListMap_nogc_less_turbo32_stat; + typedef SkipListMap< rcu_gpi, Key, Value, traits_SkipListMap_less_turbo32_stat > SkipListMap_rcu_gpi_less_turbo32_stat; + typedef SkipListMap< rcu_gpb, Key, Value, traits_SkipListMap_less_turbo32_stat > SkipListMap_rcu_gpb_less_turbo32_stat; + typedef SkipListMap< rcu_gpt, Key, Value, traits_SkipListMap_less_turbo32_stat > SkipListMap_rcu_gpt_less_turbo32_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SkipListMap< rcu_shb, Key, Value, traits_SkipListMap_less_turbo32_stat > SkipListMap_rcu_shb_less_turbo32_stat; +#endif + + class traits_SkipListMap_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 SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_turbo24_stat > SkipListMap_hp_less_turbo24_stat; + typedef SkipListMap< cds::gc::DHP, Key, Value, traits_SkipListMap_less_turbo24_stat > SkipListMap_dhp_less_turbo24_stat; + typedef SkipListMap< cds::gc::nogc, Key, Value, traits_SkipListMap_less_turbo24_stat > SkipListMap_nogc_less_turbo24_stat; + typedef SkipListMap< rcu_gpi, Key, Value, traits_SkipListMap_less_turbo24_stat > SkipListMap_rcu_gpi_less_turbo24_stat; + typedef SkipListMap< rcu_gpb, Key, Value, traits_SkipListMap_less_turbo24_stat > SkipListMap_rcu_gpb_less_turbo24_stat; + typedef SkipListMap< rcu_gpt, Key, Value, traits_SkipListMap_less_turbo24_stat > SkipListMap_rcu_gpt_less_turbo24_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SkipListMap< rcu_shb, Key, Value, traits_SkipListMap_less_turbo24_stat > SkipListMap_rcu_shb_less_turbo24_stat; +#endif + + class traits_SkipListMap_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 SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_turbo16_stat > SkipListMap_hp_less_turbo16_stat; + typedef SkipListMap< cds::gc::DHP, Key, Value, traits_SkipListMap_less_turbo16_stat > SkipListMap_dhp_less_turbo16_stat; + typedef SkipListMap< cds::gc::nogc, Key, Value, traits_SkipListMap_less_turbo16_stat > SkipListMap_nogc_less_turbo16_stat; + typedef SkipListMap< rcu_gpi, Key, Value, traits_SkipListMap_less_turbo16_stat > SkipListMap_rcu_gpi_less_turbo16_stat; + typedef SkipListMap< rcu_gpb, Key, Value, traits_SkipListMap_less_turbo16_stat > SkipListMap_rcu_gpb_less_turbo16_stat; + typedef SkipListMap< rcu_gpt, Key, Value, traits_SkipListMap_less_turbo16_stat > SkipListMap_rcu_gpt_less_turbo16_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SkipListMap< rcu_shb, Key, Value, traits_SkipListMap_less_turbo16_stat > SkipListMap_rcu_shb_less_turbo16_stat; +#endif + + class traits_SkipListMap_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 SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_cmp_turbo32 > SkipListMap_hp_cmp_turbo32; + typedef SkipListMap< cds::gc::DHP, Key, Value, traits_SkipListMap_cmp_turbo32 > SkipListMap_dhp_cmp_turbo32; + typedef SkipListMap< cds::gc::nogc, Key, Value, traits_SkipListMap_cmp_turbo32 > SkipListMap_nogc_cmp_turbo32; + typedef SkipListMap< rcu_gpi, Key, Value, traits_SkipListMap_cmp_turbo32 > SkipListMap_rcu_gpi_cmp_turbo32; + typedef SkipListMap< rcu_gpb, Key, Value, traits_SkipListMap_cmp_turbo32 > SkipListMap_rcu_gpb_cmp_turbo32; + typedef SkipListMap< rcu_gpt, Key, Value, traits_SkipListMap_cmp_turbo32 > SkipListMap_rcu_gpt_cmp_turbo32; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SkipListMap< rcu_shb, Key, Value, traits_SkipListMap_cmp_turbo32 > SkipListMap_rcu_shb_cmp_turbo32; +#endif + + class traits_SkipListMap_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 SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_cmp_turbo32_stat > SkipListMap_hp_cmp_turbo32_stat; + typedef SkipListMap< cds::gc::DHP, Key, Value, traits_SkipListMap_cmp_turbo32_stat > SkipListMap_dhp_cmp_turbo32_stat; + typedef SkipListMap< cds::gc::nogc, Key, Value, traits_SkipListMap_cmp_turbo32_stat > SkipListMap_nogc_cmp_turbo32_stat; + typedef SkipListMap< rcu_gpi, Key, Value, traits_SkipListMap_cmp_turbo32_stat > SkipListMap_rcu_gpi_cmp_turbo32_stat; + typedef SkipListMap< rcu_gpb, Key, Value, traits_SkipListMap_cmp_turbo32_stat > SkipListMap_rcu_gpb_cmp_turbo32_stat; + typedef SkipListMap< rcu_gpt, Key, Value, traits_SkipListMap_cmp_turbo32_stat > SkipListMap_rcu_gpt_cmp_turbo32_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SkipListMap< rcu_shb, Key, Value, traits_SkipListMap_cmp_turbo32_stat > SkipListMap_rcu_shb_cmp_turbo32_stat; +#endif + + class traits_SkipListMap_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 SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_xorshift32 > SkipListMap_hp_less_xorshift32; + typedef SkipListMap< cds::gc::DHP, Key, Value, traits_SkipListMap_less_xorshift32 > SkipListMap_dhp_less_xorshift32; + typedef SkipListMap< cds::gc::nogc, Key, Value, traits_SkipListMap_less_xorshift32 > SkipListMap_nogc_less_xorshift32; + typedef SkipListMap< rcu_gpi, Key, Value, traits_SkipListMap_less_xorshift32 > SkipListMap_rcu_gpi_less_xorshift32; + typedef SkipListMap< rcu_gpb, Key, Value, traits_SkipListMap_less_xorshift32 > SkipListMap_rcu_gpb_less_xorshift32; + typedef SkipListMap< rcu_gpt, Key, Value, traits_SkipListMap_less_xorshift32 > SkipListMap_rcu_gpt_less_xorshift32; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SkipListMap< rcu_shb, Key, Value, traits_SkipListMap_less_xorshift32 > SkipListMap_rcu_shb_less_xorshift32; +#endif + + class traits_SkipListMap_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 SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_xorshift24 > SkipListMap_hp_less_xorshift24; + typedef SkipListMap< cds::gc::DHP, Key, Value, traits_SkipListMap_less_xorshift24 > SkipListMap_dhp_less_xorshift24; + typedef SkipListMap< cds::gc::nogc, Key, Value, traits_SkipListMap_less_xorshift24 > SkipListMap_nogc_less_xorshift24; + typedef SkipListMap< rcu_gpi, Key, Value, traits_SkipListMap_less_xorshift24 > SkipListMap_rcu_gpi_less_xorshift24; + typedef SkipListMap< rcu_gpb, Key, Value, traits_SkipListMap_less_xorshift24 > SkipListMap_rcu_gpb_less_xorshift24; + typedef SkipListMap< rcu_gpt, Key, Value, traits_SkipListMap_less_xorshift24 > SkipListMap_rcu_gpt_less_xorshift24; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SkipListMap< rcu_shb, Key, Value, traits_SkipListMap_less_xorshift24 > SkipListMap_rcu_shb_less_xorshift24; +#endif + + class traits_SkipListMap_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 SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_xorshift16 > SkipListMap_hp_less_xorshift16; + typedef SkipListMap< cds::gc::DHP, Key, Value, traits_SkipListMap_less_xorshift16 > SkipListMap_dhp_less_xorshift16; + typedef SkipListMap< cds::gc::nogc, Key, Value, traits_SkipListMap_less_xorshift16 > SkipListMap_nogc_less_xorshift16; + typedef SkipListMap< rcu_gpi, Key, Value, traits_SkipListMap_less_xorshift16 > SkipListMap_rcu_gpi_less_xorshift16; + typedef SkipListMap< rcu_gpb, Key, Value, traits_SkipListMap_less_xorshift16 > SkipListMap_rcu_gpb_less_xorshift16; + typedef SkipListMap< rcu_gpt, Key, Value, traits_SkipListMap_less_xorshift16 > SkipListMap_rcu_gpt_less_xorshift16; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SkipListMap< rcu_shb, Key, Value, traits_SkipListMap_less_xorshift16 > SkipListMap_rcu_shb_less_xorshift16; +#endif + + class traits_SkipListMap_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 SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_xorshift32_stat > SkipListMap_hp_less_xorshift32_stat; + typedef SkipListMap< cds::gc::DHP, Key, Value, traits_SkipListMap_less_xorshift32_stat > SkipListMap_dhp_less_xorshift32_stat; + typedef SkipListMap< cds::gc::nogc, Key, Value, traits_SkipListMap_less_xorshift32_stat > SkipListMap_nogc_less_xorshift32_stat; + typedef SkipListMap< rcu_gpi, Key, Value, traits_SkipListMap_less_xorshift32_stat > SkipListMap_rcu_gpi_less_xorshift32_stat; + typedef SkipListMap< rcu_gpb, Key, Value, traits_SkipListMap_less_xorshift32_stat > SkipListMap_rcu_gpb_less_xorshift32_stat; + typedef SkipListMap< rcu_gpt, Key, Value, traits_SkipListMap_less_xorshift32_stat > SkipListMap_rcu_gpt_less_xorshift32_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SkipListMap< rcu_shb, Key, Value, traits_SkipListMap_less_xorshift32_stat > SkipListMap_rcu_shb_less_xorshift32_stat; +#endif + + class traits_SkipListMap_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 SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_xorshift24_stat > SkipListMap_hp_less_xorshift24_stat; + typedef SkipListMap< cds::gc::DHP, Key, Value, traits_SkipListMap_less_xorshift24_stat > SkipListMap_dhp_less_xorshift24_stat; + typedef SkipListMap< cds::gc::nogc, Key, Value, traits_SkipListMap_less_xorshift24_stat > SkipListMap_nogc_less_xorshift24_stat; + typedef SkipListMap< rcu_gpi, Key, Value, traits_SkipListMap_less_xorshift24_stat > SkipListMap_rcu_gpi_less_xorshift24_stat; + typedef SkipListMap< rcu_gpb, Key, Value, traits_SkipListMap_less_xorshift24_stat > SkipListMap_rcu_gpb_less_xorshift24_stat; + typedef SkipListMap< rcu_gpt, Key, Value, traits_SkipListMap_less_xorshift24_stat > SkipListMap_rcu_gpt_less_xorshift24_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SkipListMap< rcu_shb, Key, Value, traits_SkipListMap_less_xorshift24_stat > SkipListMap_rcu_shb_less_xorshift24_stat; +#endif + + class traits_SkipListMap_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 SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_xorshift16_stat > SkipListMap_hp_less_xorshift16_stat; + typedef SkipListMap< cds::gc::DHP, Key, Value, traits_SkipListMap_less_xorshift16_stat > SkipListMap_dhp_less_xorshift16_stat; + typedef SkipListMap< cds::gc::nogc, Key, Value, traits_SkipListMap_less_xorshift16_stat > SkipListMap_nogc_less_xorshift16_stat; + typedef SkipListMap< rcu_gpi, Key, Value, traits_SkipListMap_less_xorshift16_stat > SkipListMap_rcu_gpi_less_xorshift16_stat; + typedef SkipListMap< rcu_gpb, Key, Value, traits_SkipListMap_less_xorshift16_stat > SkipListMap_rcu_gpb_less_xorshift16_stat; + typedef SkipListMap< rcu_gpt, Key, Value, traits_SkipListMap_less_xorshift16_stat > SkipListMap_rcu_gpt_less_xorshift16_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SkipListMap< rcu_shb, Key, Value, traits_SkipListMap_less_xorshift16_stat > SkipListMap_rcu_shb_less_xorshift16_stat; +#endif + + class traits_SkipListMap_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 SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_cmp_xorshift32 > SkipListMap_hp_cmp_xorshift32; + typedef SkipListMap< cds::gc::DHP, Key, Value, traits_SkipListMap_cmp_xorshift32 > SkipListMap_dhp_cmp_xorshift32; + typedef SkipListMap< cds::gc::nogc, Key, Value, traits_SkipListMap_cmp_xorshift32 > SkipListMap_nogc_cmp_xorshift32; + typedef SkipListMap< rcu_gpi, Key, Value, traits_SkipListMap_cmp_xorshift32 > SkipListMap_rcu_gpi_cmp_xorshift32; + typedef SkipListMap< rcu_gpb, Key, Value, traits_SkipListMap_cmp_xorshift32 > SkipListMap_rcu_gpb_cmp_xorshift32; + typedef SkipListMap< rcu_gpt, Key, Value, traits_SkipListMap_cmp_xorshift32 > SkipListMap_rcu_gpt_cmp_xorshift32; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SkipListMap< rcu_shb, Key, Value, traits_SkipListMap_cmp_xorshift32 > SkipListMap_rcu_shb_cmp_xorshift32; +#endif + + class traits_SkipListMap_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 SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_cmp_xorshift32_stat > SkipListMap_hp_cmp_xorshift32_stat; + typedef SkipListMap< cds::gc::DHP, Key, Value, traits_SkipListMap_cmp_xorshift32_stat > SkipListMap_dhp_cmp_xorshift32_stat; + typedef SkipListMap< cds::gc::nogc, Key, Value, traits_SkipListMap_cmp_xorshift32_stat > SkipListMap_nogc_cmp_xorshift32_stat; + typedef SkipListMap< rcu_gpi, Key, Value, traits_SkipListMap_cmp_xorshift32_stat > SkipListMap_rcu_gpi_cmp_xorshift32_stat; + typedef SkipListMap< rcu_gpb, Key, Value, traits_SkipListMap_cmp_xorshift32_stat > SkipListMap_rcu_gpb_cmp_xorshift32_stat; + typedef SkipListMap< rcu_gpt, Key, Value, traits_SkipListMap_cmp_xorshift32_stat > SkipListMap_rcu_gpt_cmp_xorshift32_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SkipListMap< rcu_shb, Key, Value, traits_SkipListMap_cmp_xorshift32_stat > SkipListMap_rcu_shb_cmp_xorshift32_stat; +#endif + + }; + + template + static inline void print_stat( cds_test::property_stream& o, SkipListMap< GC, K, T, Traits > const& m ) + { + o << m.statistics(); + } + +} // namespace map + +#define CDSSTRESS_SkipListMap_case( fixture, test_case, skiplist_map_type, key_type, value_type ) \ + TEST_F( fixture, skiplist_map_type ) \ + { \ + typedef map::map_type< tag_SkipListMap, key_type, value_type >::skiplist_map_type map_type; \ + test_case(); \ + } + +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + +#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL > 1 +# define CDSSTRESS_SkipListMap_SHRCU_2( fixture, test_case, key_type, value_type ) \ + +#else +# define CDSSTRESS_SkipListMap_SHRCU_2( fixture, test_case, key_type, value_type ) +#endif + +#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL == 1 +# define CDSSTRESS_SkipListMap_SHRCU_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_rcu_shb_cmp_turbo32, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_rcu_shb_cmp_xorshift32, key_type, value_type ) \ + +#else +# define CDSSTRESS_SkipListMap_SHRCU_1( fixture, test_case, key_type, value_type ) +#endif + + +# define CDSSTRESS_SkipListMap_SHRCU( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_rcu_shb_less_turbo32, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_rcu_shb_less_xorshift32, key_type, value_type ) \ + CDSSTRESS_SkipListMap_SHRCU_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SkipListMap_SHRCU_2( fixture, test_case, key_type, value_type ) \ + +#else +# define CDSSTRESS_SkipListMap_SHRCU( fixture, test_case, key_type, value_type ) +#endif + +#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL > 1 +# define CDSSTRESS_SkipListMap_HP_2( fixture, test_case, key_type, value_type ) \ + +# define CDSSTRESS_SkipListMap_RCU_2( fixture, test_case, key_type, value_type ) \ + +# define CDSSTRESS_SkipListMap_2( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SkipListMap_HP_2( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SkipListMap_RCU_2( fixture, test_case, key_type, value_type ) \ + +#else +# define CDSSTRESS_SkipListMap_HP_2( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_SkipListMap_RCU_2( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_SkipListMap_2( fixture, test_case, key_type, value_type ) +#endif + +#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL == 1 +# define CDSSTRESS_SkipListMap_HP_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_dhp_less_turbo32, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_hp_cmp_turbo32, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_dhp_less_xorshift32, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_hp_cmp_xorshift32, key_type, value_type ) \ + +# define CDSSTRESS_SkipListMap_RCU_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_rcu_gpb_less_turbo32, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_rcu_gpi_cmp_turbo32, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_rcu_gpb_less_xorshift32, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_rcu_gpi_cmp_xorshift32, key_type, value_type ) \ + CDSSTRESS_SkipListMap_SHRCU( fixture, test_case, key_type, value_type ) + +# define CDSSTRESS_SkipListMap_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SkipListMap_HP_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SkipListMap_RCU_1( fixture, test_case, key_type, value_type ) \ + +#else +# define CDSSTRESS_SkipListMap_HP_1( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_SkipListMap_RCU_1( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_SkipListMap_1( fixture, test_case, key_type, value_type ) +#endif + + +#define CDSSTRESS_SkipListMap_HP( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_hp_less_turbo32, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_hp_less_turbo24, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_hp_less_turbo16, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_dhp_cmp_turbo32, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_hp_less_xorshift32, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_hp_less_xorshift24, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_hp_less_xorshift16, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_dhp_cmp_xorshift32, key_type, value_type ) \ + CDSSTRESS_SkipListMap_HP_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SkipListMap_HP_2( fixture, test_case, key_type, value_type ) \ + +#define CDSSTRESS_SkipListMap_RCU( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_rcu_gpi_less_turbo32, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_rcu_gpb_cmp_turbo32, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_rcu_gpi_less_xorshift32, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_rcu_gpb_cmp_xorshift32, key_type, value_type ) \ + CDSSTRESS_SkipListMap_RCU_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SkipListMap_RCU_2( fixture, test_case, key_type, value_type ) \ + +#define CDSSTRESS_SkipListMap( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SkipListMap_HP( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SkipListMap_RCU( fixture, test_case, key_type, value_type ) \ + +#define CDSSTRESS_SkipListMap_nogc( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_nogc_less_turbo32, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_nogc_less_turbo24, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_nogc_less_turbo16, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_nogc_cmp_turbo32, key_type, value_type ) \ + CDSSTRESS_SkipListMap_case( fixture, test_case, SkipListMap_nogc_cmp_xorshift32, key_type, value_type ) \ + +#endif // ifndef CDSUNIT_MAP_TYPE_SKIP_LIST_H diff --git a/test/stress/parallel/parallel-map/map_type_split_list.h b/test/stress/parallel/parallel-map/map_type_split_list.h new file mode 100644 index 00000000..0eb56bbb --- /dev/null +++ b/test/stress/parallel/parallel-map/map_type_split_list.h @@ -0,0 +1,733 @@ +/* + 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_MAP_TYPE_SPLIT_LIST_H +#define CDSUNIT_MAP_TYPE_SPLIT_LIST_H + +#include "map_type.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +namespace map { + + template + class SplitListMap : public cc::SplitListMap< GC, Key, T, Traits > + { + typedef cc::SplitListMap< GC, Key, T, Traits > base_class; + public: + template + SplitListMap( Config const& cfg) + : base_class( cfg.s_nMapSize, 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; + }; + + template + class SplitListMap< cds::gc::nogc, Key, T, Traits> : public cc::SplitListMap< cds::gc::nogc, Key, T, Traits > + { + typedef cc::SplitListMap< cds::gc::nogc, Key, T, Traits > base_class; + public: + template + SplitListMap( Config const& cfg) + : base_class( cfg.s_nMapSize, cfg.s_nLoadFactor ) + {} + + template + bool insert( K const& key ) + { + return base_class::insert( key ) != base_class::end(); + } + + template + bool insert( K const& key, V const& val ) + { + return base_class::insert( key, val ) != base_class::end(); + } + + template + bool insert_with( K const& key, Func func ) + { + return base_class::insert_with( key, func ) != base_class::end(); + } + + template + bool find( K const& key ) + { + return base_class::find( key ) != base_class::end(); + } + + void clear() + {} + + // for testing + static CDS_CONSTEXPR bool const c_bExtractSupported = true; + static CDS_CONSTEXPR bool const c_bLoadFactorDepended = true; + }; + + struct tag_SplitListMap; + + template + struct map_type< tag_SplitListMap, Key, Value >: public map_type_base< Key, Value > + { + typedef map_type_base< Key, Value > base_class; + typedef typename base_class::key_compare compare; + typedef typename base_class::key_less less; + typedef typename base_class::equal_to equal_to; + typedef typename base_class::key_hash hash; + + + // *************************************************************************** + // SplitListMap 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< cds::atomicity::cache_friendly_item_counter > + ,cc::split_list::ordered_list_traits< + typename cc::michael_list::make_traits< + co::compare< compare > + >::type + > + >::type + {}; + typedef SplitListMap< cds::gc::HP, Key, Value, traits_SplitList_Michael_dyn_cmp > SplitList_Michael_HP_dyn_cmp; + typedef SplitListMap< cds::gc::DHP, Key, Value, traits_SplitList_Michael_dyn_cmp > SplitList_Michael_DHP_dyn_cmp; + typedef SplitListMap< cds::gc::nogc, Key, Value, traits_SplitList_Michael_dyn_cmp > SplitList_Michael_NOGC_dyn_cmp; + typedef SplitListMap< rcu_gpi, Key, Value, traits_SplitList_Michael_dyn_cmp > SplitList_Michael_RCU_GPI_dyn_cmp; + typedef SplitListMap< rcu_gpb, Key, Value, traits_SplitList_Michael_dyn_cmp > SplitList_Michael_RCU_GPB_dyn_cmp; + typedef SplitListMap< rcu_gpt, Key, Value, traits_SplitList_Michael_dyn_cmp > SplitList_Michael_RCU_GPT_dyn_cmp; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SplitListMap< rcu_shb, Key, Value, 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 SplitListMap< cds::gc::HP, Key, Value, traits_SplitList_Michael_dyn_cmp_swar > SplitList_Michael_HP_dyn_cmp_swar; + typedef SplitListMap< cds::gc::DHP, Key, Value, traits_SplitList_Michael_dyn_cmp_swar > SplitList_Michael_DHP_dyn_cmp_swar; + typedef SplitListMap< cds::gc::nogc, Key, Value, traits_SplitList_Michael_dyn_cmp_swar > SplitList_Michael_NOGC_dyn_cmp_swar; + typedef SplitListMap< rcu_gpi, Key, Value, traits_SplitList_Michael_dyn_cmp_swar > SplitList_Michael_RCU_GPI_dyn_cmp_swar; + typedef SplitListMap< rcu_gpb, Key, Value, traits_SplitList_Michael_dyn_cmp_swar > SplitList_Michael_RCU_GPB_dyn_cmp_swar; + typedef SplitListMap< rcu_gpt, Key, Value, traits_SplitList_Michael_dyn_cmp_swar > SplitList_Michael_RCU_GPT_dyn_cmp_swar; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SplitListMap< rcu_shb, Key, Value, traits_SplitList_Michael_dyn_cmp_swar > SplitList_Michael_RCU_SHB_dyn_cmp_swar; +#endif + + struct traits_SplitList_Michael_dyn_cmp_stat : public traits_SplitList_Michael_dyn_cmp + { + typedef cc::split_list::stat<> stat; + typedef typename cc::michael_list::make_traits< + co::compare< compare > + ,co::stat< cc::michael_list::stat<> > + >::type ordered_list_traits; + }; + typedef SplitListMap< cds::gc::HP, Key, Value, traits_SplitList_Michael_dyn_cmp_stat > SplitList_Michael_HP_dyn_cmp_stat; + typedef SplitListMap< cds::gc::DHP, Key, Value, traits_SplitList_Michael_dyn_cmp_stat > SplitList_Michael_DHP_dyn_cmp_stat; + typedef SplitListMap< cds::gc::nogc, Key, Value, traits_SplitList_Michael_dyn_cmp_stat> SplitList_Michael_NOGC_dyn_cmp_stat; + typedef SplitListMap< rcu_gpi, Key, Value, traits_SplitList_Michael_dyn_cmp_stat > SplitList_Michael_RCU_GPI_dyn_cmp_stat; + typedef SplitListMap< rcu_gpb, Key, Value, traits_SplitList_Michael_dyn_cmp_stat > SplitList_Michael_RCU_GPB_dyn_cmp_stat; + typedef SplitListMap< rcu_gpt, Key, Value, traits_SplitList_Michael_dyn_cmp_stat > SplitList_Michael_RCU_GPT_dyn_cmp_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SplitListMap< rcu_shb, Key, Value, 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< cds::atomicity::cache_friendly_item_counter > + ,co::memory_model< co::v::sequential_consistent > + ,cc::split_list::ordered_list_traits< + typename cc::michael_list::make_traits< + co::compare< compare > + ,co::memory_model< co::v::sequential_consistent > + >::type + > + >::type + {}; + typedef SplitListMap< cds::gc::HP, Key, Value, traits_SplitList_Michael_dyn_cmp_seqcst > SplitList_Michael_HP_dyn_cmp_seqcst; + typedef SplitListMap< cds::gc::DHP, Key, Value, traits_SplitList_Michael_dyn_cmp_seqcst > SplitList_Michael_DHP_dyn_cmp_seqcst; + typedef SplitListMap< cds::gc::nogc, Key, Value, traits_SplitList_Michael_dyn_cmp_seqcst> SplitList_Michael_NOGC_dyn_cmp_seqcst; + typedef SplitListMap< rcu_gpi, Key, Value, traits_SplitList_Michael_dyn_cmp_seqcst > SplitList_Michael_RCU_GPI_dyn_cmp_seqcst; + typedef SplitListMap< rcu_gpb, Key, Value, traits_SplitList_Michael_dyn_cmp_seqcst > SplitList_Michael_RCU_GPB_dyn_cmp_seqcst; + typedef SplitListMap< rcu_gpt, Key, Value, traits_SplitList_Michael_dyn_cmp_seqcst > SplitList_Michael_RCU_GPT_dyn_cmp_seqcst; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SplitListMap< rcu_shb, Key, Value, 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< cds::atomicity::cache_friendly_item_counter > + ,cc::split_list::ordered_list_traits< + typename cc::michael_list::make_traits< + co::compare< compare > + >::type + > + >::type + {}; + typedef SplitListMap< cds::gc::HP, Key, Value, traits_SplitList_Michael_st_cmp > SplitList_Michael_HP_st_cmp; + typedef SplitListMap< cds::gc::DHP, Key, Value, traits_SplitList_Michael_st_cmp > SplitList_Michael_DHP_st_cmp; + typedef SplitListMap< cds::gc::nogc, Key, Value, traits_SplitList_Michael_st_cmp> SplitList_Michael_NOGC_st_cmp; + typedef SplitListMap< rcu_gpi, Key, Value, traits_SplitList_Michael_st_cmp > SplitList_Michael_RCU_GPI_st_cmp; + typedef SplitListMap< rcu_gpb, Key, Value, traits_SplitList_Michael_st_cmp > SplitList_Michael_RCU_GPB_st_cmp; + typedef SplitListMap< rcu_gpt, Key, Value, traits_SplitList_Michael_st_cmp > SplitList_Michael_RCU_GPT_st_cmp; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SplitListMap< rcu_shb, Key, Value, 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< cds::atomicity::cache_friendly_item_counter > + ,cc::split_list::ordered_list_traits< + typename cc::michael_list::make_traits< + co::less< less > + >::type + > + >::type + {}; + typedef SplitListMap< cds::gc::HP, Key, Value, traits_SplitList_Michael_dyn_less > SplitList_Michael_HP_dyn_less; + typedef SplitListMap< cds::gc::DHP, Key, Value, traits_SplitList_Michael_dyn_less > SplitList_Michael_DHP_dyn_less; + typedef SplitListMap< cds::gc::nogc, Key, Value, traits_SplitList_Michael_dyn_less> SplitList_Michael_NOGC_dyn_less; + typedef SplitListMap< rcu_gpi, Key, Value, traits_SplitList_Michael_dyn_less > SplitList_Michael_RCU_GPI_dyn_less; + typedef SplitListMap< rcu_gpb, Key, Value, traits_SplitList_Michael_dyn_less > SplitList_Michael_RCU_GPB_dyn_less; + typedef SplitListMap< rcu_gpt, Key, Value, traits_SplitList_Michael_dyn_less > SplitList_Michael_RCU_GPT_dyn_less; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SplitListMap< rcu_shb, Key, Value, 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< cds::atomicity::cache_friendly_item_counter > + ,cc::split_list::ordered_list_traits< + typename cc::michael_list::make_traits< + co::less< less > + >::type + > + >::type + {}; + typedef SplitListMap< cds::gc::HP, Key, Value, traits_SplitList_Michael_st_less > SplitList_Michael_HP_st_less; + typedef SplitListMap< cds::gc::DHP, Key, Value, traits_SplitList_Michael_st_less > SplitList_Michael_DHP_st_less; + typedef SplitListMap< cds::gc::nogc, Key, Value, traits_SplitList_Michael_st_less> SplitList_Michael_NOGC_st_less; + typedef SplitListMap< rcu_gpi, Key, Value, traits_SplitList_Michael_st_less > SplitList_Michael_RCU_GPI_st_less; + typedef SplitListMap< rcu_gpb, Key, Value, traits_SplitList_Michael_st_less > SplitList_Michael_RCU_GPB_st_less; + typedef SplitListMap< rcu_gpt, Key, Value, traits_SplitList_Michael_st_less > SplitList_Michael_RCU_GPT_st_less; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SplitListMap< rcu_shb, Key, Value, traits_SplitList_Michael_st_less > SplitList_Michael_RCU_SHB_st_less; +#endif + + struct traits_SplitList_Michael_st_less_stat : traits_SplitList_Michael_st_less + { + typedef cc::split_list::stat<> stat; + typedef typename cc::michael_list::make_traits< + co::less< less > + , co::stat< cc::michael_list::stat<> > + >::type ordered_list_traits; + + }; + typedef SplitListMap< cds::gc::HP, Key, Value, traits_SplitList_Michael_st_less_stat > SplitList_Michael_HP_st_less_stat; + typedef SplitListMap< cds::gc::DHP, Key, Value, traits_SplitList_Michael_st_less_stat > SplitList_Michael_DHP_st_less_stat; + typedef SplitListMap< cds::gc::nogc, Key, Value, traits_SplitList_Michael_st_less_stat> SplitList_Michael_NOGC_st_less_stat; + typedef SplitListMap< rcu_gpi, Key, Value, traits_SplitList_Michael_st_less_stat > SplitList_Michael_RCU_GPI_st_less_stat; + typedef SplitListMap< rcu_gpb, Key, Value, traits_SplitList_Michael_st_less_stat > SplitList_Michael_RCU_GPB_st_less_stat; + typedef SplitListMap< rcu_gpt, Key, Value, traits_SplitList_Michael_st_less_stat > SplitList_Michael_RCU_GPT_st_less_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SplitListMap< rcu_shb, Key, Value, traits_SplitList_Michael_st_less_stat > SplitList_Michael_RCU_SHB_st_less_stat; +#endif + + + // *************************************************************************** + // SplitListMap based on LazyKVList + + struct SplitList_Lazy_dyn_cmp : + public cc::split_list::make_traits< + cc::split_list::ordered_list + ,co::hash< hash > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > + ,cc::split_list::ordered_list_traits< + typename cc::lazy_list::make_traits< + co::compare< compare > + >::type + > + >::type + {}; + typedef SplitListMap< cds::gc::HP, Key, Value, SplitList_Lazy_dyn_cmp > SplitList_Lazy_HP_dyn_cmp; + typedef SplitListMap< cds::gc::DHP, Key, Value, SplitList_Lazy_dyn_cmp > SplitList_Lazy_DHP_dyn_cmp; + typedef SplitListMap< cds::gc::nogc, Key, Value, SplitList_Lazy_dyn_cmp> SplitList_Lazy_NOGC_dyn_cmp; + typedef SplitListMap< rcu_gpi, Key, Value, SplitList_Lazy_dyn_cmp > SplitList_Lazy_RCU_GPI_dyn_cmp; + typedef SplitListMap< rcu_gpb, Key, Value, SplitList_Lazy_dyn_cmp > SplitList_Lazy_RCU_GPB_dyn_cmp; + typedef SplitListMap< rcu_gpt, Key, Value, SplitList_Lazy_dyn_cmp > SplitList_Lazy_RCU_GPT_dyn_cmp; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SplitListMap< rcu_shb, Key, Value, SplitList_Lazy_dyn_cmp > SplitList_Lazy_RCU_SHB_dyn_cmp; +#endif + + struct SplitList_Lazy_dyn_cmp_stat : public 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 SplitListMap< cds::gc::HP, Key, Value, SplitList_Lazy_dyn_cmp_stat > SplitList_Lazy_HP_dyn_cmp_stat; + typedef SplitListMap< cds::gc::DHP, Key, Value, SplitList_Lazy_dyn_cmp_stat > SplitList_Lazy_DHP_dyn_cmp_stat; + typedef SplitListMap< cds::gc::nogc, Key, Value, SplitList_Lazy_dyn_cmp_stat> SplitList_Lazy_NOGC_dyn_cmp_stat; + typedef SplitListMap< rcu_gpi, Key, Value, SplitList_Lazy_dyn_cmp_stat > SplitList_Lazy_RCU_GPI_dyn_cmp_stat; + typedef SplitListMap< rcu_gpb, Key, Value, SplitList_Lazy_dyn_cmp_stat > SplitList_Lazy_RCU_GPB_dyn_cmp_stat; + typedef SplitListMap< rcu_gpt, Key, Value, SplitList_Lazy_dyn_cmp_stat > SplitList_Lazy_RCU_GPT_dyn_cmp_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SplitListMap< rcu_shb, Key, Value, SplitList_Lazy_dyn_cmp_stat > SplitList_Lazy_RCU_SHB_dyn_cmp_stat; +#endif + + struct SplitList_Lazy_dyn_cmp_seqcst : + public cc::split_list::make_traits< + cc::split_list::ordered_list + ,co::hash< hash > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > + ,co::memory_model< co::v::sequential_consistent > + ,cc::split_list::ordered_list_traits< + typename cc::lazy_list::make_traits< + co::compare< compare > + ,co::memory_model< co::v::sequential_consistent > + >::type + > + >::type + {}; + typedef SplitListMap< cds::gc::HP, Key, Value, SplitList_Lazy_dyn_cmp_seqcst > SplitList_Lazy_HP_dyn_cmp_seqcst; + typedef SplitListMap< cds::gc::DHP, Key, Value, SplitList_Lazy_dyn_cmp_seqcst > SplitList_Lazy_DHP_dyn_cmp_seqcst; + typedef SplitListMap< cds::gc::nogc, Key, Value, SplitList_Lazy_dyn_cmp_seqcst> SplitList_Lazy_NOGC_dyn_cmp_seqcst; + typedef SplitListMap< rcu_gpi, Key, Value, SplitList_Lazy_dyn_cmp_seqcst > SplitList_Lazy_RCU_GPI_dyn_cmp_seqcst; + typedef SplitListMap< rcu_gpb, Key, Value, SplitList_Lazy_dyn_cmp_seqcst > SplitList_Lazy_RCU_GPB_dyn_cmp_seqcst; + typedef SplitListMap< rcu_gpt, Key, Value, SplitList_Lazy_dyn_cmp_seqcst > SplitList_Lazy_RCU_GPT_dyn_cmp_seqcst; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SplitListMap< rcu_shb, Key, Value, SplitList_Lazy_dyn_cmp_seqcst > SplitList_Lazy_RCU_SHB_dyn_cmp_seqcst; +#endif + + struct 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< cds::atomicity::cache_friendly_item_counter > + ,cc::split_list::ordered_list_traits< + typename cc::lazy_list::make_traits< + co::compare< compare > + >::type + > + >::type + {}; + typedef SplitListMap< cds::gc::HP, Key, Value, SplitList_Lazy_st_cmp > SplitList_Lazy_HP_st_cmp; + typedef SplitListMap< cds::gc::DHP, Key, Value, SplitList_Lazy_st_cmp > SplitList_Lazy_DHP_st_cmp; + typedef SplitListMap< cds::gc::nogc, Key, Value, SplitList_Lazy_st_cmp> SplitList_Lazy_NOGC_st_cmp; + typedef SplitListMap< rcu_gpi, Key, Value, SplitList_Lazy_st_cmp > SplitList_Lazy_RCU_GPI_st_cmp; + typedef SplitListMap< rcu_gpb, Key, Value, SplitList_Lazy_st_cmp > SplitList_Lazy_RCU_GPB_st_cmp; + typedef SplitListMap< rcu_gpt, Key, Value, SplitList_Lazy_st_cmp > SplitList_Lazy_RCU_GPT_st_cmp; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SplitListMap< rcu_shb, Key, Value, SplitList_Lazy_st_cmp > SplitList_Lazy_RCU_SHB_st_cmp; +#endif + + + struct SplitList_Lazy_dyn_less : + public cc::split_list::make_traits< + cc::split_list::ordered_list + ,co::hash< hash > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > + ,cc::split_list::ordered_list_traits< + typename cc::lazy_list::make_traits< + co::less< less > + >::type + > + >::type + {}; + typedef SplitListMap< cds::gc::HP, Key, Value, SplitList_Lazy_dyn_less > SplitList_Lazy_HP_dyn_less; + typedef SplitListMap< cds::gc::DHP, Key, Value, SplitList_Lazy_dyn_less > SplitList_Lazy_DHP_dyn_less; + typedef SplitListMap< cds::gc::nogc, Key, Value, SplitList_Lazy_dyn_less> SplitList_Lazy_NOGC_dyn_less; + typedef SplitListMap< rcu_gpi, Key, Value, SplitList_Lazy_dyn_less > SplitList_Lazy_RCU_GPI_dyn_less; + typedef SplitListMap< rcu_gpb, Key, Value, SplitList_Lazy_dyn_less > SplitList_Lazy_RCU_GPB_dyn_less; + typedef SplitListMap< rcu_gpt, Key, Value, SplitList_Lazy_dyn_less > SplitList_Lazy_RCU_GPT_dyn_less; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SplitListMap< rcu_shb, Key, Value, SplitList_Lazy_dyn_less > SplitList_Lazy_RCU_SHB_dyn_less; +#endif + + struct 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< cds::atomicity::cache_friendly_item_counter > + ,cc::split_list::ordered_list_traits< + typename cc::lazy_list::make_traits< + co::less< less > + >::type + > + >::type + {}; + typedef SplitListMap< cds::gc::HP, Key, Value, SplitList_Lazy_st_less > SplitList_Lazy_HP_st_less; + typedef SplitListMap< cds::gc::DHP, Key, Value, SplitList_Lazy_st_less > SplitList_Lazy_DHP_st_less; + typedef SplitListMap< cds::gc::nogc, Key, Value, SplitList_Lazy_st_less> SplitList_Lazy_NOGC_st_less; + typedef SplitListMap< rcu_gpi, Key, Value, SplitList_Lazy_st_less > SplitList_Lazy_RCU_GPI_st_less; + typedef SplitListMap< rcu_gpb, Key, Value, SplitList_Lazy_st_less > SplitList_Lazy_RCU_GPB_st_less; + typedef SplitListMap< rcu_gpt, Key, Value, SplitList_Lazy_st_less > SplitList_Lazy_RCU_GPT_st_less; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SplitListMap< rcu_shb, Key, Value, SplitList_Lazy_st_less > SplitList_Lazy_RCU_SHB_st_less; +#endif + + struct SplitList_Lazy_st_less_stat : public 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 SplitListMap< cds::gc::HP, Key, Value, SplitList_Lazy_st_less_stat > SplitList_Lazy_HP_st_less_stat; + typedef SplitListMap< cds::gc::DHP, Key, Value, SplitList_Lazy_st_less_stat > SplitList_Lazy_DHP_st_less_stat; + typedef SplitListMap< cds::gc::nogc, Key, Value, SplitList_Lazy_st_less_stat> SplitList_Lazy_NOGC_st_less_stat; + typedef SplitListMap< rcu_gpi, Key, Value, SplitList_Lazy_st_less_stat > SplitList_Lazy_RCU_GPI_st_less_stat; + typedef SplitListMap< rcu_gpb, Key, Value, SplitList_Lazy_st_less_stat > SplitList_Lazy_RCU_GPB_st_less_stat; + typedef SplitListMap< rcu_gpt, Key, Value, SplitList_Lazy_st_less_stat > SplitList_Lazy_RCU_GPT_st_less_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef SplitListMap< rcu_shb, Key, Value, SplitList_Lazy_st_less_stat > SplitList_Lazy_RCU_SHB_st_less_stat; +#endif + + + // *************************************************************************** + // SplitListMap 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< cds::atomicity::cache_friendly_item_counter > + ,cc::split_list::ordered_list_traits< + typename cc::iterable_list::make_traits< + co::compare< compare > + >::type + > + >::type + {}; + typedef SplitListMap< cds::gc::HP, Key, Value, traits_SplitList_Iterable_dyn_cmp > SplitList_Iterable_HP_dyn_cmp; + typedef SplitListMap< cds::gc::DHP, Key, Value, traits_SplitList_Iterable_dyn_cmp > SplitList_Iterable_DHP_dyn_cmp; + + struct traits_SplitList_Iterable_dyn_cmp_stat : public traits_SplitList_Iterable_dyn_cmp + { + typedef cc::split_list::stat<> stat; + typedef typename cc::iterable_list::make_traits< + co::compare< compare > + , co::stat< cc::iterable_list::stat<>> + >::type ordered_list_traits; + }; + typedef SplitListMap< cds::gc::HP, Key, Value, traits_SplitList_Iterable_dyn_cmp_stat > SplitList_Iterable_HP_dyn_cmp_stat; + typedef SplitListMap< cds::gc::DHP, Key, Value, 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< cds::atomicity::cache_friendly_item_counter > + ,co::memory_model< co::v::sequential_consistent > + ,cc::split_list::ordered_list_traits< + typename cc::iterable_list::make_traits< + co::compare< compare > + ,co::memory_model< co::v::sequential_consistent > + >::type + > + >::type + {}; + typedef SplitListMap< cds::gc::HP, Key, Value, traits_SplitList_Iterable_dyn_cmp_seqcst > SplitList_Iterable_HP_dyn_cmp_seqcst; + typedef SplitListMap< cds::gc::DHP, Key, Value, 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< cds::atomicity::cache_friendly_item_counter > + ,cc::split_list::ordered_list_traits< + typename cc::iterable_list::make_traits< + co::compare< compare > + >::type + > + >::type + {}; + typedef SplitListMap< cds::gc::HP, Key, Value, traits_SplitList_Iterable_st_cmp > SplitList_Iterable_HP_st_cmp; + typedef SplitListMap< cds::gc::DHP, Key, Value, 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< cds::atomicity::cache_friendly_item_counter > + ,cc::split_list::ordered_list_traits< + typename cc::iterable_list::make_traits< + co::less< less > + >::type + > + >::type + {}; + typedef SplitListMap< cds::gc::HP, Key, Value, traits_SplitList_Iterable_dyn_less > SplitList_Iterable_HP_dyn_less; + typedef SplitListMap< cds::gc::DHP, Key, Value, 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< cds::atomicity::cache_friendly_item_counter > + ,cc::split_list::ordered_list_traits< + typename cc::iterable_list::make_traits< + co::less< less > + >::type + > + >::type + {}; + typedef SplitListMap< cds::gc::HP, Key, Value, traits_SplitList_Iterable_st_less > SplitList_Iterable_HP_st_less; + typedef SplitListMap< cds::gc::DHP, Key, Value, traits_SplitList_Iterable_st_less > SplitList_Iterable_DHP_st_less; + + struct traits_SplitList_Iterable_st_less_stat : traits_SplitList_Iterable_st_less + { + typedef cc::split_list::stat<> stat; + typedef typename cc::iterable_list::make_traits< + co::less< less > + , co::stat< cc::iterable_list::stat<>> + >::type ordered_list_traits; + }; + typedef SplitListMap< cds::gc::HP, Key, Value, traits_SplitList_Iterable_st_less_stat > SplitList_Iterable_HP_st_less_stat; + typedef SplitListMap< cds::gc::DHP, Key, Value, traits_SplitList_Iterable_st_less_stat > SplitList_Iterable_DHP_st_less_stat; + }; + + template + static inline void print_stat( cds_test::property_stream& o, SplitListMap< GC, K, T, Traits > const& m ) + { + o << m.statistics() + << cds_test::stat_prefix( "list_stat" ) + << m.list_statistics() + << cds_test::stat_prefix( "" ); + } + +} // namespace map + +#define CDSSTRESS_SplitListMap_case( fixture, test_case, splitlist_map_type, key_type, value_type ) \ + TEST_P( fixture, splitlist_map_type ) \ + { \ + typedef map::map_type< tag_SplitListMap, key_type, value_type >::splitlist_map_type map_type; \ + test_case(); \ + } + +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + +#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL > 1 +# define CDSSTRESS_SplitListMap_SHRCU_2( fixture, test_case, key_type, value_type ) \ + +#else +# define CDSSTRESS_SplitListMap_SHRCU_2( fixture, test_case, key_type, value_type ) +#endif + +#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL == 1 +# define CDSSTRESS_SplitListMap_SHRCU_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_RCU_SHT_dyn_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_RCU_SHB_st_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_RCU_SHT_st_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_RCU_SHB_dyn_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_RCU_SHT_st_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_RCU_SHT_dyn_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_RCU_SHB_st_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_RCU_SHT_st_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_RCU_SHB_dyn_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_RCU_SHT_st_less, key_type, value_type ) \ + +#else +# define CDSSTRESS_SplitListMap_SHRCU_1( fixture, test_case, key_type, value_type ) +#endif + + +# define CDSSTRESS_SplitListMap_SHRCU( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_RCU_SHB_dyn_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_RCU_SHT_dyn_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_RCU_SHB_st_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_RCU_SHB_dyn_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_RCU_SHT_dyn_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_RCU_SHB_st_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_SHRCU_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SplitListMap_SHRCU_2( fixture, test_case, key_type, value_type ) \ + +#else +# define CDSSTRESS_SplitListMap_SHRCU( fixture, test_case, key_type, value_type ) +#endif + +#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL > 1 +# define CDSSTRESS_SplitListMap_HP_2( fixture, test_case, key_type, value_type ) \ + +# define CDSSTRESS_SplitListMap_RCU_2( fixture, test_case, key_type, value_type ) \ + +# define CDSSTRESS_SplitListMap_2( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SplitListMap_HP_2( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SplitListMap_RCU_2( fixture, test_case, key_type, value_type ) \ + + +#else +# define CDSSTRESS_SplitListMap_HP_2( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_SplitListMap_RCU_2( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_SplitListMap_2( fixture, test_case, key_type, value_type ) +#endif + +#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL == 1 +# define CDSSTRESS_SplitListMap_HP_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_DHP_dyn_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_DHP_dyn_cmp_swar, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_HP_st_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_DHP_dyn_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_HP_st_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_DHP_dyn_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_HP_st_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_DHP_dyn_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_HP_st_less, key_type, value_type ) \ + +# define CDSSTRESS_SplitListMap_RCU_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_RCU_GPI_st_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_RCU_GPB_dyn_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_RCU_GPI_st_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_RCU_GPB_dyn_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_RCU_GPI_st_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_RCU_GPB_dyn_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_RCU_GPI_st_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_SHRCU( fixture, test_case, key_type, value_type ) \ + +# define CDSSTRESS_SplitListMap_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SplitListMap_HP_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SplitListMap_RCU_1( fixture, test_case, key_type, value_type ) \ + +#else +# define CDSSTRESS_SplitListMap_HP_1( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_SplitListMap_RCU_1( fixture, test_case, key_type, value_type ) +# define CDSSTRESS_SplitListMap_1( fixture, test_case, key_type, value_type ) +#endif + + +#define CDSSTRESS_SplitListMap_HP( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_HP_dyn_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_HP_dyn_cmp_swar, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_DHP_st_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_HP_dyn_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_DHP_st_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_HP_dyn_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_DHP_st_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_HP_dyn_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_DHP_st_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_HP_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SplitListMap_HP_2( fixture, test_case, key_type, value_type ) \ + +#define CDSSTRESS_SplitListMap_RCU( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_RCU_GPI_dyn_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_RCU_GPB_dyn_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_RCU_GPB_dyn_cmp_swar, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_RCU_GPB_st_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_RCU_GPI_dyn_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_RCU_GPB_st_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_RCU_GPI_dyn_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_RCU_GPB_st_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_RCU_GPI_dyn_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_RCU_GPB_st_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_RCU_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SplitListMap_RCU_2( fixture, test_case, key_type, value_type ) \ + +#define CDSSTRESS_SplitListMap( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SplitListMap_HP( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SplitListMap_RCU( fixture, test_case, key_type, value_type ) \ + +#if defined(CDS_STRESS_TEST_LEVEL) && CDS_STRESS_TEST_LEVEL > 0 +# define CDSSTRESS_SplitListIterableMap_1( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Iterable_DHP_dyn_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Iterable_HP_st_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Iterable_DHP_dyn_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Iterable_HP_st_less, key_type, value_type ) \ + +#else +# define CDSSTRESS_SplitListIterableMap_1( fixture, test_case, key_type, value_type ) +#endif + + +#define CDSSTRESS_SplitListIterableMap( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Iterable_HP_dyn_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Iterable_DHP_st_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Iterable_HP_dyn_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Iterable_DHP_st_less, key_type, value_type ) \ + CDSSTRESS_SplitListIterableMap_1( fixture, test_case, key_type, value_type ) \ + + +#define CDSSTRESS_SplitListMap_nogc( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_NOGC_dyn_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_NOGC_st_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_NOGC_dyn_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Michael_NOGC_st_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_NOGC_dyn_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_NOGC_st_cmp, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_NOGC_dyn_less, key_type, value_type ) \ + CDSSTRESS_SplitListMap_case( fixture, test_case, SplitList_Lazy_NOGC_st_less, key_type, value_type ) \ + +#endif // ifndef CDSUNIT_MAP_TYPE_SPLIT_LIST_H diff --git a/test/stress/parallel/parallel-map/map_type_std.h b/test/stress/parallel/parallel-map/map_type_std.h new file mode 100644 index 00000000..8b88c673 --- /dev/null +++ b/test/stress/parallel/parallel-map/map_type_std.h @@ -0,0 +1,271 @@ +/* + 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_MAP_TYPE_STD_H +#define CDSUNIT_MAP_TYPE_STD_H + +#include "map_type.h" + +#include +#include + +namespace map { + + struct empty_lock + { + void lock() {} + void unlock() {} + }; + + template >::other + > + class StdMap: public std::map, Alloc> + { + Lock m_lock; + typedef std::unique_lock scoped_lock; + typedef std::map, Alloc> base_class; + public: + typedef typename base_class::mapped_type value_type; + typedef typename base_class::value_type pair_type; + typedef size_t item_counter; + + StdMap() + {} + + template + StdMap( Config const& ) + {} + + bool contains( const Key& key ) + { + scoped_lock al( m_lock ); + return base_class::find( key ) != base_class::end(); + } + + bool insert( const Key& key, const Value& val ) + { + scoped_lock al( m_lock ); + return base_class::insert( typename base_class::value_type( key, val )).second; + } + + template + bool insert( const Key& key, const T& val, Func func ) + { + scoped_lock al( m_lock ); + std::pair pRet = base_class::insert( typename base_class::value_type( key, Value())); + if ( pRet.second ) { + func( pRet.first->second, val ); + return true; + } + return false; + } + + template + std::pair update( const T& key, Func func, bool /*bAllowInsert*/ = true ) + { + scoped_lock al( m_lock ); + std::pair pRet = base_class::insert( typename base_class::value_type( key, Value())); + if ( pRet.second ) { + func( true, *pRet.first ); + return std::make_pair( true, true ); + } + else { + func( false, *pRet.first ); + return std::make_pair( true, false ); + } + } + + bool erase( const Key& key ) + { + scoped_lock al( m_lock ); + return base_class::erase( key ) != 0; + } + + template + bool erase( const T& key, Func func ) + { + scoped_lock al( m_lock ); + typename base_class::iterator it = base_class::find( 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; + static CDS_CONSTEXPR bool const c_bEraseExactKey = false; + }; + + template >::other + > + class StdHashMap + : public std::unordered_map< + Key, Value + , std::hash + , std::equal_to + , Alloc + > + { + public: + Lock m_lock; + typedef std::unique_lock scoped_lock; + typedef std::unordered_map< + Key, Value + , std::hash + , std::equal_to + , Alloc + > base_class; + public: + typedef typename base_class::mapped_type value_type; + typedef size_t item_counter; + + StdHashMap() + {} + + template + StdHashMap( Config const& ) + {} + + bool contains( const Key& key ) + { + scoped_lock al( m_lock ); + return base_class::find( key ) != base_class::end(); + } + + bool insert( const Key& key, const Value& val ) + { + scoped_lock al( m_lock ); + return base_class::insert( typename base_class::value_type(key, val)).second; + } + + template + bool insert( const Key& key, const T& val, Func func ) + { + scoped_lock al( m_lock ); + std::pair pRet = base_class::insert( typename base_class::value_type(key, Value())); + if ( pRet.second ) { + func( pRet.first->second, val ); + return true; + } + return false; + } + + template + std::pair update( const T& key, Func func, bool /*bAllowInsert*/ = true ) + { + scoped_lock al( m_lock ); + std::pair pRet = base_class::insert( typename base_class::value_type( key, Value())); + if ( pRet.second ) { + func( true, *pRet.first ); + return std::make_pair( true, true ); + } + else { + func( false, *pRet.first ); + return std::make_pair( true, false ); + } + } + + bool erase( const Key& key ) + { + scoped_lock al( m_lock ); + return base_class::erase( key ) != 0; + } + + template + bool erase( const T& key, Func func ) + { + scoped_lock al( m_lock ); + typename base_class::iterator it = base_class::find( key ); + if ( it != base_class::end()) { + func( *it ); + return base_class::erase( key ) != 0; + } + 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 = false; + }; + + struct tag_StdMap; + + template + struct map_type< tag_StdMap, Key, Value >: public map_type_base< Key, Value > + { + typedef map_type_base< Key, Value > base_class; + typedef typename base_class::key_compare compare; + typedef typename base_class::key_less less; + + typedef StdMap< Key, Value, cds::sync::spin > StdMap_Spin; + typedef StdMap< Key, Value, std::mutex > StdMap_Mutex; + typedef StdMap< Key, Value, empty_lock> StdMap_NoLock; + + typedef StdHashMap< Key, Value, cds::sync::spin > StdHashMap_Spin; + typedef StdHashMap< Key, Value, std::mutex > StdHashMap_Mutex; + typedef StdHashMap< Key, Value, empty_lock > StdHashMap_NoLock; + }; +} // namespace map + + +#define CDSSTRESS_StdMap_case( fixture, test_case, std_map_type, key_type, value_type ) \ + TEST_F( fixture, std_map_type ) \ + { \ + typedef map::map_type< tag_StdMap, key_type, value_type >::std_map_type map_type; \ + test_case(); \ + } + +#define CDSSTRESS_StdMap( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_StdMap_case( fixture, test_case, StdMap_Spin, key_type, value_type ) \ + CDSSTRESS_StdMap_case( fixture, test_case, StdHashMap_Spin, key_type, value_type ) \ + +#define CDSSTRESS_StdMap_nolock( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_StdMap_case( fixture, test_case, StdMap_NoLock, key_type, value_type ) \ + CDSSTRESS_StdMap_case( fixture, test_case, StdHashMap_NoLock, key_type, value_type ) + +#endif // ifndef CDSUNIT_MAP_TYPE_STD_H diff --git a/test/stress/parallel/parallel-map/map_type_striped.h b/test/stress/parallel/parallel-map/map_type_striped.h new file mode 100644 index 00000000..88be541f --- /dev/null +++ b/test/stress/parallel/parallel-map/map_type_striped.h @@ -0,0 +1,311 @@ +/* + 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_MAP_TYPE_STRIPED_H +#define CDSUNIT_MAP_TYPE_STRIPED_H + +#include "map_type.h" +#include +#include +#include + +#include +#if BOOST_VERSION >= 104800 +# include +# include +# include +# include +#endif +#include +#include + +namespace map { + + struct tag_StripedMap; + + template + struct map_type< tag_StripedMap, Key, Value >: public map_type_base< Key, Value > + { + typedef map_type_base< Key, Value > base_class; + typedef typename base_class::key_compare compare; + typedef typename base_class::key_less less; + typedef typename base_class::equal_to equal_to; + typedef typename base_class::key_hash hash; + typedef typename base_class::hash2 hash2; + + // for sequential containers + template + class StripedHashMap_seq: + public cc::StripedMap< BucketEntry, + co::mutex_policy< cc::striped_set::striping<> > + ,co::resizing_policy > + , Options... + > + { + typedef cc::StripedMap< 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 + StripedHashMap_seq( Config const& cfg ) + : base_class( cfg.s_nMapSize / cfg.s_nLoadFactor / 16, *(new(&m_placeHolder) resizing_policy_t( 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 StripedHashMap_ord: + public cc::StripedMap< BucketEntry, + co::resizing_policy > + ,co::mutex_policy< cc::striped_set::striping<> > + , Options... + > + { + typedef cc::StripedMap< 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 + StripedHashMap_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; + }; + + + typedef StripedHashMap_seq< + std::list< std::pair< Key const, Value > > + , co::hash< hash2 > + , co::less< less > + > StripedMap_list; + + typedef StripedHashMap_ord< + std::unordered_map< Key, Value, hash, equal_to > + , co::hash< hash2 > + > StripedMap_hashmap; + + typedef StripedHashMap_ord< + std::map< Key, Value, less > + , co::hash< hash2 > + > StripedMap_map; + + typedef StripedHashMap_ord< + boost::unordered_map< Key, Value, hash, equal_to > + , co::hash< hash2 > + > StripedMap_boost_unordered_map; + +# if BOOST_VERSION >= 104800 + typedef StripedHashMap_seq< + boost::container::slist< std::pair< Key const, Value > > + , co::hash< hash2 > + , co::less< less > + > StripedMap_slist; + + typedef StripedHashMap_seq< + boost::container::list< std::pair< Key const, Value > > + , co::hash< hash2 > + , co::less< less > + > StripedMap_boost_list; + + typedef StripedHashMap_ord< + boost::container::map< Key, Value, less > + , co::hash< hash2 > + > StripedMap_boost_map; + + typedef StripedHashMap_ord< + boost::container::flat_map< Key, Value, less > + , co::hash< hash2 > + > StripedMap_boost_flat_map; +# endif // BOOST_VERSION >= 104800 + + + // *************************************************************************** + // RefinableHashMap + + // for sequential containers + template + class RefinableHashMap_seq: + public cc::StripedMap< BucketEntry, + co::resizing_policy > + ,co::mutex_policy< cc::striped_set::refinable<> > + , Options... + > + { + typedef cc::StripedMap< 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 + RefinableHashMap_seq( Config const& cfg ) + : base_class( cfg.s_nMapSize / cfg.s_nLoadFactor / 16, *(new(&m_placeHolder) resizing_policy_t( 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 RefinableHashMap_ord: + public cc::StripedMap< BucketEntry, + co::resizing_policy > + ,co::mutex_policy< cc::striped_set::refinable<> > + , Options... + > + { + typedef cc::StripedMap< 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 + RefinableHashMap_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; + }; + + + typedef RefinableHashMap_seq< + std::list< std::pair< Key const, Value > > + , co::hash< hash2 > + , co::less< less > + > RefinableMap_list; + +# if BOOST_VERSION >= 104800 + typedef RefinableHashMap_seq< + boost::container::slist< std::pair< Key const, Value > > + , co::hash< hash2 > + , co::less< less > + > RefinableMap_slist; +# endif + + typedef RefinableHashMap_ord< + std::map< Key, Value, less > + , co::hash< hash2 > + > RefinableMap_map; + + typedef RefinableHashMap_ord< + std::unordered_map< Key, Value, hash, equal_to > + , co::hash< hash2 > + > RefinableMap_hashmap; + + typedef RefinableHashMap_ord< + boost::unordered_map< Key, Value, hash, equal_to > + , co::hash< hash2 > + > RefinableMap_boost_unordered_map; + +# if BOOST_VERSION >= 104800 + typedef RefinableHashMap_seq< + boost::container::list< std::pair< Key const, Value > > + , co::hash< hash2 > + , co::less< less > + > RefinableMap_boost_list; + + typedef RefinableHashMap_ord< + boost::container::map< Key, Value, less > + , co::hash< hash2 > + > RefinableMap_boost_map; + + typedef RefinableHashMap_ord< + boost::container::flat_map< Key, Value, less > + , co::hash< hash2 > + > RefinableMap_boost_flat_map; +# endif // #if BOOST_VERSION >= 104800 + + }; +} // namespace map + +#define CDSSTRESS_StripedMap_case( fixture, test_case, striped_map_type, key_type, value_type ) \ + TEST_P( fixture, striped_map_type ) \ + { \ + typedef map::map_type< tag_StripedMap, key_type, value_type >::striped_map_type map_type; \ + test_case(); \ + } + +#define CDSSTRESS_StripedMap( fixture, test_case, key_type, value_type ) \ + CDSSTRESS_StripedMap_case( fixture, test_case, StripedMap_list, key_type, value_type ) \ + CDSSTRESS_StripedMap_case( fixture, test_case, StripedMap_hashmap, key_type, value_type ) \ + CDSSTRESS_StripedMap_case( fixture, test_case, StripedMap_map, key_type, value_type ) \ + CDSSTRESS_StripedMap_case( fixture, test_case, RefinableMap_list, key_type, value_type ) \ + CDSSTRESS_StripedMap_case( fixture, test_case, RefinableMap_map, key_type, value_type ) \ + CDSSTRESS_StripedMap_case( fixture, test_case, RefinableMap_hashmap, key_type, value_type ) \ + +#endif // ifndef CDSUNIT_MAP_TYPE_STRIPED_H diff --git a/test/stress/parallel/parallel-map/minmax/CMakeLists.txt b/test/stress/parallel/parallel-map/minmax/CMakeLists.txt new file mode 100644 index 00000000..2481fe9c --- /dev/null +++ b/test/stress/parallel/parallel-map/minmax/CMakeLists.txt @@ -0,0 +1,19 @@ +set(PACKAGE_NAME stress-sequential-map-minmax) + +set(CDSSTRESS_MAP_MINMAX_SOURCES + ../../../main.cpp + map_minmax.cpp + map_minmax_bronsonavltree.cpp + map_minmax_ellentree.cpp + map_minmax_skip.cpp +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. +) + +add_executable(${PACKAGE_NAME} ${CDSSTRESS_MAP_MINMAX_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/parallel/parallel-map/minmax/map_minmax.cpp b/test/stress/parallel/parallel-map/minmax/map_minmax.cpp new file mode 100644 index 00000000..fd7f6729 --- /dev/null +++ b/test/stress/parallel/parallel-map/minmax/map_minmax.cpp @@ -0,0 +1,72 @@ +/* + 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 "map_minmax.h" + +namespace map { + + size_t Map_MinMax::s_nMapSize = 50000; + size_t Map_MinMax::s_nInsThreadCount = 4; + size_t Map_MinMax::s_nExtractThreadCount = 4; + size_t Map_MinMax::s_nPassCount = 1000; + + size_t Map_MinMax::s_nFeldmanMap_HeadBits = 8; + size_t Map_MinMax::s_nFeldmanMap_ArrayBits = 8; + + void Map_MinMax::SetUpTestCase() + { + cds_test::config const& cfg = get_config( "map_minmax" ); + + s_nMapSize = cfg.get_size_t( "MapSize", s_nMapSize ); + if ( s_nMapSize < 1000 ) + s_nMapSize = 1000; + + s_nInsThreadCount = cfg.get_size_t( "InsThreadCount", s_nInsThreadCount ); + if ( s_nInsThreadCount == 0 ) + s_nInsThreadCount = 1; + + s_nExtractThreadCount = cfg.get_size_t( "ExtractThreadCount", s_nExtractThreadCount ); + if ( s_nExtractThreadCount ) + s_nExtractThreadCount = 1; + + s_nPassCount = cfg.get_size_t( "PassCount", s_nPassCount ); + if ( s_nPassCount == 0 ) + s_nPassCount = 100; + + s_nFeldmanMap_HeadBits = cfg.get_size_t( "FeldmanMapHeadBits", s_nFeldmanMap_HeadBits ); + if ( s_nFeldmanMap_HeadBits == 0 ) + s_nFeldmanMap_HeadBits = 4; + + s_nFeldmanMap_ArrayBits = cfg.get_size_t( "FeldmanMapArrayBits", s_nFeldmanMap_ArrayBits ); + if ( s_nFeldmanMap_ArrayBits == 0 ) + s_nFeldmanMap_ArrayBits = 4; + } + +} // namespace map diff --git a/test/stress/parallel/parallel-map/minmax/map_minmax.h b/test/stress/parallel/parallel-map/minmax/map_minmax.h new file mode 100644 index 00000000..6958d727 --- /dev/null +++ b/test/stress/parallel/parallel-map/minmax/map_minmax.h @@ -0,0 +1,402 @@ +/* + 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 "map_type.h" +#include + +namespace map { + + class Map_MinMax: public cds_test::stress_fixture + { + public: + static size_t s_nInsThreadCount; // insert thread count + static size_t s_nExtractThreadCount; // extract thread count + static size_t s_nMapSize; // max map size + static size_t s_nPassCount; + + static size_t s_nFeldmanMap_HeadBits; + static size_t s_nFeldmanMap_ArrayBits; + + static size_t s_nLoadFactor; // current load factor + + static void SetUpTestCase(); + //static void TearDownTestCase(); + + protected: + typedef int key_type; + typedef int value_type; + typedef std::pair pair_type; + + atomics::atomic m_nInsThreadCount; + key_type m_KeyMin; + key_type m_KeyMax; + + enum { + inserter_thread, + extractor_thread, + }; + + template + class Inserter: public cds_test::thread + { + typedef cds_test::thread base_class; + Map& m_Map; + std::vector m_arr; + + void init_data() + { + Map_MinMax& fixture = pool().template fixture(); + key_type keyMin = fixture.m_KeyMin; + key_type keyMax = fixture.m_KeyMax; + + for ( key_type i = keyMin + 10; i >= keyMin; --i ) + m_arr.push_back( i ); + for ( key_type i = keyMax - 10; i <= keyMax; ++i ) + m_arr.push_back( i ); + shuffle( m_arr.begin(), m_arr.end()); + } + + public: + size_t m_nInsertMinSuccess = 0; + size_t m_nInsertMinFailed = 0; + size_t m_nInsertMaxSuccess = 0; + size_t m_nInsertMaxFailed = 0; + + public: + Inserter( cds_test::thread_pool& pool, Map& map ) + : base_class( pool, inserter_thread ) + , m_Map( map ) + { + init_data(); + } + + Inserter( Inserter& src ) + : base_class( src ) + , m_Map( src.m_Map ) + { + init_data(); + } + + virtual thread * clone() + { + return new Inserter( *this ); + } + + virtual void test() + { + Map_MinMax& fixture = pool().template fixture(); + + key_type keyMin = fixture.m_KeyMin; + key_type keyMax = fixture.m_KeyMax; + + for ( size_t nPass = 0; nPass < s_nPassCount; ++nPass ) { + for ( key_type key : m_arr ) { + if ( m_Map.insert( key, key )) { + if ( key == keyMin ) + ++m_nInsertMinSuccess; + else if ( key == keyMax ) + ++m_nInsertMaxSuccess; + } + else { + if ( key == keyMin ) + ++m_nInsertMinFailed; + else if ( key == keyMax ) + ++m_nInsertMaxFailed; + } + } + } + + fixture.m_nInsThreadCount.fetch_sub( 1, atomics::memory_order_release ); + } + }; + + // Deletes odd keys from [0..N) + template + class Extractor: public cds_test::thread + { + typedef cds_test::thread base_class; + Map& m_Map; + + public: + size_t m_nDeleteMin = 0; + size_t m_nDeleteMinFailed = 0; + size_t m_nDeleteMax = 0; + size_t m_nDeleteMaxFailed = 0; + + public: + Extractor( cds_test::thread_pool& pool, Map& map ) + : base_class( pool, extractor_thread ) + , m_Map( map ) + {} + + Extractor( Extractor& src ) + : base_class( src ) + , m_Map( src.m_Map ) + {} + + virtual thread * clone() + { + return new Extractor( *this ); + } + + virtual void test() + { + Map& rMap = m_Map; + + typename Map::guarded_ptr gp; + Map_MinMax& fixture = pool().template fixture(); + + key_type keyMin = fixture.m_KeyMin; + key_type keyMax = fixture.m_KeyMax; + + do { + gp = rMap.extract_min(); + if ( gp ) { + if ( gp->first == keyMin ) + ++m_nDeleteMin; + } + else + ++m_nDeleteMinFailed; + + gp = rMap.extract_max(); + if ( gp ) { + if ( gp->first == keyMax ) + ++m_nDeleteMax; + } + else + ++m_nDeleteMaxFailed; + + } while ( fixture.m_nInsThreadCount.load( atomics::memory_order_acquire ) != 0 ); + + gp = rMap.extract_min(); + if ( gp ) { + if ( gp->first == keyMin ) + ++m_nDeleteMin; + } + else + ++m_nDeleteMinFailed; + + gp = rMap.extract_max(); + if ( gp ) { + if ( gp->first == keyMax ) + ++m_nDeleteMax; + } + else + ++m_nDeleteMaxFailed; + } + }; + + template + class Extractor< cds::urcu::gc, Map > : public cds_test::thread + { + typedef cds_test::thread base_class; + Map& m_Map; + + public: + size_t m_nDeleteMin = 0; + size_t m_nDeleteMinFailed = 0; + size_t m_nDeleteMax = 0; + size_t m_nDeleteMaxFailed = 0; + + public: + Extractor( cds_test::thread_pool& pool, Map& map ) + : base_class( pool, extractor_thread ) + , m_Map( map ) + {} + + Extractor( Extractor& src ) + : base_class( src ) + , m_Map( src.m_Map ) + {} + + virtual thread * clone() + { + return new Extractor( *this ); + } + + virtual void test() + { + Map& rMap = m_Map; + Map_MinMax& fixture = pool().template fixture(); + + key_type keyMin = fixture.m_KeyMin; + key_type keyMax = fixture.m_KeyMax; + + static_assert( !Map::c_bExtractLockExternal, "No external RCU locking required" ); + + do { + auto res = rMap.extract_min_key(); + if ( res.second ) { + if ( res.first == keyMin ) + ++m_nDeleteMin; + } + else + ++m_nDeleteMinFailed; + + res = rMap.extract_max_key(); + if ( res.second ) { + if ( res.first == keyMax ) + ++m_nDeleteMax; + } + else + ++m_nDeleteMaxFailed; + } while ( fixture.m_nInsThreadCount.load( atomics::memory_order_acquire ) != 0 ); + + auto res = rMap.extract_min_key(); + if ( res.second ) { + if ( res.first == keyMin ) + ++m_nDeleteMin; + } + else + ++m_nDeleteMinFailed; + + res = rMap.extract_max_key(); + if ( res.second ) { + if ( res.first == keyMax ) + ++m_nDeleteMax; + } + else + ++m_nDeleteMaxFailed; + } + }; + + protected: + template + void do_test( Map& testMap ) + { + typedef Inserter insert_thread; + typedef Extractor< typename Map::gc, Map > extract_thread; + + m_nInsThreadCount.store( s_nInsThreadCount, atomics::memory_order_release ); + + { + std::vector arr; + arr.resize( s_nMapSize ); + for ( int i = 0; i < static_cast( s_nMapSize ); ++i ) + arr[i] = i;; + shuffle( arr.begin(), arr.end()); + + for ( key_type key : arr ) + testMap.insert( key, key ); + } + + m_KeyMin = 0; + m_KeyMax = static_cast( s_nMapSize - 1 ); + + cds_test::thread_pool& pool = get_pool(); + pool.add( new insert_thread( pool, testMap ), s_nInsThreadCount ); + pool.add( new extract_thread( pool, testMap ), s_nExtractThreadCount ); + + propout() << std::make_pair( "insert_thread_count", s_nInsThreadCount ) + << std::make_pair( "extract_thread_count", s_nExtractThreadCount ) + << std::make_pair( "map_size", s_nMapSize ) + << std::make_pair( "pass_count", s_nPassCount ); + + std::chrono::milliseconds duration = pool.run(); + + propout() << std::make_pair( "duration", duration ); + + size_t nInsertMinSuccess = 0; + size_t nInsertMinFailed = 0; + size_t nInsertMaxSuccess = 0; + size_t nInsertMaxFailed = 0; + size_t nDeleteMin = 0; + size_t nDeleteMinFailed = 0; + size_t nDeleteMax = 0; + size_t nDeleteMaxFailed = 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); + nInsertMinSuccess += inserter.m_nInsertMinSuccess; + nInsertMinFailed += inserter.m_nInsertMinFailed; + nInsertMaxSuccess += inserter.m_nInsertMaxSuccess; + nInsertMaxFailed += inserter.m_nInsertMaxFailed; + } + break; + case extractor_thread: + { + extract_thread& extractor = static_cast(thr); + nDeleteMin += extractor.m_nDeleteMin; + nDeleteMinFailed += extractor.m_nDeleteMinFailed; + nDeleteMax += extractor.m_nDeleteMax; + nDeleteMaxFailed += extractor.m_nDeleteMaxFailed; + } + break; + default: + assert( false ); + } + } + + EXPECT_EQ( nDeleteMinFailed, 0u ); + EXPECT_EQ( nDeleteMaxFailed, 0u ); + + EXPECT_EQ( nDeleteMin, nInsertMinSuccess + 1 ); + EXPECT_EQ( nDeleteMax, nInsertMaxSuccess + 1 ); + + propout() + << std::make_pair( "insert_min", nInsertMinSuccess + 1 ) + << std::make_pair( "insert_min_double", nInsertMinFailed ) + << std::make_pair( "insert_max", nInsertMaxSuccess + 1 ) + << std::make_pair( "insert_max_double", nInsertMaxFailed ) + << std::make_pair( "extract_min", nDeleteMin ) + << std::make_pair( "extract_min_failed", nDeleteMinFailed ) + << std::make_pair( "extract_max", nDeleteMax ) + << std::make_pair( "extract_max_failed", nDeleteMaxFailed ); + + analyze( testMap ); + } + + template + void analyze( Map& testMap ) + { + print_stat( propout(), testMap ); + + check_before_cleanup( testMap ); + testMap.clear(); + EXPECT_TRUE( testMap.empty()) << "map.size=" << testMap.size(); + + additional_check( testMap ); + additional_cleanup( testMap ); + } + + template + void run_test() + { + static_assert( Map::c_bExtractSupported, "Map class must support extract() method" ); + Map testMap( *this ); + do_test( testMap ); + } + }; + +} // namespace map diff --git a/test/stress/parallel/parallel-map/minmax/map_minmax_bronsonavltree.cpp b/test/stress/parallel/parallel-map/minmax/map_minmax_bronsonavltree.cpp new file mode 100644 index 00000000..3319a0b2 --- /dev/null +++ b/test/stress/parallel/parallel-map/minmax/map_minmax_bronsonavltree.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 "map_minmax.h" +#include "map_type_bronson_avltree.h" + +namespace map { + + CDSSTRESS_BronsonAVLTreeMap( Map_MinMax, run_test, int, int ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/minmax/map_minmax_ellentree.cpp b/test/stress/parallel/parallel-map/minmax/map_minmax_ellentree.cpp new file mode 100644 index 00000000..3329efad --- /dev/null +++ b/test/stress/parallel/parallel-map/minmax/map_minmax_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 "map_minmax.h" +#include "map_type_ellen_bintree.h" + +namespace map { + + CDSSTRESS_EllenBinTreeMap( Map_MinMax, run_test, int, int ) + +} // namespace map diff --git a/test/stress/parallel/parallel-map/minmax/map_minmax_skip.cpp b/test/stress/parallel/parallel-map/minmax/map_minmax_skip.cpp new file mode 100644 index 00000000..c75767a7 --- /dev/null +++ b/test/stress/parallel/parallel-map/minmax/map_minmax_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 "map_minmax.h" +#include "map_type_skip_list.h" + +namespace map { + + CDSSTRESS_SkipListMap( Map_MinMax, run_test, int, int ) + +} // namespace map diff --git a/test/stress/parallel/parallel-misc/CMakeLists.txt b/test/stress/parallel/parallel-misc/CMakeLists.txt new file mode 100644 index 00000000..d1373fa0 --- /dev/null +++ b/test/stress/parallel/parallel-misc/CMakeLists.txt @@ -0,0 +1,22 @@ +set(PACKAGE_NAME stress-parallel-misc) + +set(CDSSTRESS_MISC_SOURCES + main.cpp + rigtorp_spsc_driver.cpp + rigtorp_mpmc_driver.cpp + deque_driver.cpp + spinlock_driver.cpp + seqlock_driver.cpp + rwlock_driver.cpp + mcslock_driver.cpp + backoff.cpp +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_executable(${PACKAGE_NAME} ${CDSSTRESS_MISC_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/parallel/parallel-misc/backoff.cpp b/test/stress/parallel/parallel-misc/backoff.cpp new file mode 100644 index 00000000..85c014c9 --- /dev/null +++ b/test/stress/parallel/parallel-misc/backoff.cpp @@ -0,0 +1,15 @@ +#include "common.h" +#include +#include +#include +#include +#include +#include +#include + +namespace cds_others { + +size_t BackoffTraits::lower_bound = 16; +size_t BackoffTraits::upper_bound = 1024; + +} // namespace cds_others diff --git a/test/stress/parallel/parallel-misc/common.h b/test/stress/parallel/parallel-misc/common.h new file mode 100644 index 00000000..b6a3a505 --- /dev/null +++ b/test/stress/parallel/parallel-misc/common.h @@ -0,0 +1,22 @@ +#ifndef _CDS_STRESS_TEST_COMMON_H +#define _CDS_STRESS_TEST_COMMON_H + +#include + +typedef unsigned long long ullong; + +#define GetConfig(field) s_n##field = cfg.get_size_t(#field, s_n##field) + +#define GetConfigExpected(field, expected) \ + s_n##field = cfg.get_size_t(#field, s_n##field); \ + if (s_n##field < (expected)) { \ + s_n##field = expected; \ + } + +#ifdef PERFORMANCE +#define DEBUG(stmt) +#else +#define DEBUG(stmt) stmt +#endif + +#endif diff --git a/test/stress/parallel/parallel-misc/deque_driver.cpp b/test/stress/parallel/parallel-misc/deque_driver.cpp new file mode 100644 index 00000000..a17484eb --- /dev/null +++ b/test/stress/parallel/parallel-misc/deque_driver.cpp @@ -0,0 +1,73 @@ +#include "common.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace { + +typedef cds_others::ChaseLevDeque Deque; +static size_t s_nDequePassCount = 1000; +static size_t s_nDequeStealerThreadCount = 5; +static size_t s_nDequeMainPassCount = 100000000; + +class ChaseLevDequeTest : public cds_test::stress_fixture { +protected: + static atomic_int terminate_stealer; + static ullong *sums; + static ullong *succ_counts; + static ullong push_sum; + static ullong push_count; + + static void SetUpTestCase() { + cds_test::config const &cfg = get_config("SequentialMisc"); + GetConfig(DequePassCount); + GetConfig(DequeStealerThreadCount); + GetConfig(DequeMainPassCount); + } +}; + +atomic_int ChaseLevDequeTest::terminate_stealer; +ullong *ChaseLevDequeTest::sums; +ullong *ChaseLevDequeTest::succ_counts; +ullong ChaseLevDequeTest::push_count; +ullong ChaseLevDequeTest::push_sum; + +TEST_F(ChaseLevDequeTest, ChaseLevDeque_push_take) { + std::unique_ptr deque(new Deque()); + size_t sum = 0; + int res; + for (size_t i = 0; i < s_nDequePassCount; ++i) { + deque->push(i); + res = deque->take(); + sum += res; + } + size_t supposed_sum = s_nDequePassCount * (s_nDequePassCount - 1) / 2; + if (sum != supposed_sum) { + std::cout << "Sequential deque take sum: " << sum << " != " << supposed_sum + << "\n"; + } +} + +TEST_F(ChaseLevDequeTest, ChaseLevDeque_push_steal) { + std::unique_ptr deque(new Deque()); + size_t sum = 0; + int res; + for (size_t i = 0; i < s_nDequePassCount; ++i) { + deque->push(i); + res = deque->steal(); + sum += res; + } + size_t supposed_sum = s_nDequePassCount * (s_nDequePassCount - 1) / 2; + if (sum != supposed_sum) { + std::cout << "Sequential deque steal sum: " << sum << " != " << supposed_sum + << "\n"; + } +} + +} // namespace diff --git a/test/stress/parallel/parallel-misc/main.cpp b/test/stress/parallel/parallel-misc/main.cpp new file mode 100644 index 00000000..0a5f913b --- /dev/null +++ b/test/stress/parallel/parallel-misc/main.cpp @@ -0,0 +1,62 @@ +/* + 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 +#include +#ifdef CDSUNIT_USE_URCU +# include +# include +# include +# include +#endif + +#ifdef CDS_ENABLE_HPSTAT +# include +# include +# include +#endif + +int main(int argc, char **argv) { + int result; + // Read test config file + cds_test::init_config(argc, argv); + + std::cout << "Hardware concurrency: " << std::thread::hardware_concurrency() + << "\n"; + + // Init Google test + ::testing::InitGoogleTest(&argc, argv); + + result = RUN_ALL_TESTS(); + return result; +} diff --git a/test/stress/parallel/parallel-misc/mcslock_driver.cpp b/test/stress/parallel/parallel-misc/mcslock_driver.cpp new file mode 100644 index 00000000..a4a9d172 --- /dev/null +++ b/test/stress/parallel/parallel-misc/mcslock_driver.cpp @@ -0,0 +1,45 @@ +#include "common.h" +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace { + +static size_t s_nMCSLockThreadCount = 6; +static size_t s_nMCSLockPassCount = 3000000; + +class MCSLockTest : public cds_test::stress_fixture { +protected: + static ullong x; + + static void SetUpTestCase() { + cds_test::config const &cfg = get_config("SequentialMisc"); + GetConfig(MCSLockPassCount); + GetConfig(MCSLockThreadCount); + } +}; + +ullong MCSLockTest::x; + +TEST_F(MCSLockTest, MCSLock) { + cds_others::BackoffTraits::lower_bound = 16; + cds_others::BackoffTraits::upper_bound = 1024; + std::unique_ptr my_mutex(new cds_others::mcs_mutex()); + cds_others::mcs_mutex::guard g(my_mutex.get()); + my_mutex->unlock(&g); + for (size_t i = 0; i < s_nMCSLockPassCount; i++) { + my_mutex->lock(&g); + x++; + my_mutex->unlock(&g); + } + my_mutex->lock(&g); +} + +} // namespace diff --git a/test/stress/parallel/parallel-misc/rigtorp_mpmc_driver.cpp b/test/stress/parallel/parallel-misc/rigtorp_mpmc_driver.cpp new file mode 100644 index 00000000..0066f901 --- /dev/null +++ b/test/stress/parallel/parallel-misc/rigtorp_mpmc_driver.cpp @@ -0,0 +1,62 @@ +#include "common.h" +#include +#include +#include +#include + +using namespace std; + +namespace { + +class rigtorpMPMCQueueTest : public cds_test::stress_fixture { +protected: + static size_t s_nRigtorpMPMCQueuePassCount; + static size_t s_nRigtorpMPMCQueueEnqueueStride; + static size_t s_nRigtorpMPMCQueueCapacity; + + static void SetUpTestCase() { + cds_test::config const &cfg = get_config("SequentialMisc"); + GetConfigExpected(RigtorpMPMCQueuePassCount, 10000); + GetConfigExpected(RigtorpMPMCQueueEnqueueStride, 1024); + GetConfigExpected(RigtorpMPMCQueueCapacity, 2048); + if (s_nRigtorpMPMCQueueCapacity <= s_nRigtorpMPMCQueueEnqueueStride) { + s_nRigtorpMPMCQueueCapacity = 2 * s_nRigtorpMPMCQueueEnqueueStride; + } + } + + void test() { + std::unique_ptr> q( + new rigtorp::MPMCQueue(s_nRigtorpMPMCQueueCapacity)); + size_t nNo = 0; + size_t pop_sum = 0; + + while (nNo < s_nRigtorpMPMCQueuePassCount) { + size_t curr_push_count = std::min(s_nRigtorpMPMCQueuePassCount - nNo, + s_nRigtorpMPMCQueueEnqueueStride); + for (size_t i = 0; i < curr_push_count; i++) { + q->push(nNo); + ++nNo; + } + + for (size_t i = 0; i < curr_push_count; i++) { + size_t res; + q->pop(res); + pop_sum += res; + } + } + + size_t supposed_sum = + s_nRigtorpMPMCQueuePassCount * (s_nRigtorpMPMCQueuePassCount - 1) / 2; + EXPECT_EQ(pop_sum, supposed_sum); + } +}; + +size_t rigtorpMPMCQueueTest::s_nRigtorpMPMCQueuePassCount; +size_t rigtorpMPMCQueueTest::s_nRigtorpMPMCQueueEnqueueStride; +size_t rigtorpMPMCQueueTest::s_nRigtorpMPMCQueueCapacity; + +TEST_F(rigtorpMPMCQueueTest, PushPop) { + test(); +} + +} // namespace diff --git a/test/stress/parallel/parallel-misc/rigtorp_spsc_driver.cpp b/test/stress/parallel/parallel-misc/rigtorp_spsc_driver.cpp new file mode 100644 index 00000000..ef3380ad --- /dev/null +++ b/test/stress/parallel/parallel-misc/rigtorp_spsc_driver.cpp @@ -0,0 +1,65 @@ +#include "common.h" +#include +#include +#include +#include + +using namespace std; + +namespace { + +class rigtorpSPSCQueueTest : public cds_test::stress_fixture { +protected: + static size_t s_nRigtorpSPSCQueuePassCount; + static size_t s_nRigtorpSPSCQueueEnqueueStride; + static size_t s_nRigtorpSPSCQueueCapacity; + + rigtorp::SPSCQueue* q; + + static void SetUpTestCase() { + cds_test::config const &cfg = get_config("SequentialMisc"); + GetConfigExpected(RigtorpSPSCQueuePassCount, 10000); + GetConfigExpected(RigtorpSPSCQueueEnqueueStride, 1024); + GetConfigExpected(RigtorpSPSCQueueCapacity, 2048); + if (s_nRigtorpSPSCQueueCapacity <= s_nRigtorpSPSCQueueEnqueueStride) { + s_nRigtorpSPSCQueueCapacity = 2 * s_nRigtorpSPSCQueueEnqueueStride; + } + } + + void test() { + std::unique_ptr> q( + new rigtorp::SPSCQueue(s_nRigtorpSPSCQueueCapacity)); + size_t nNo = 0; + size_t push_sum = 0; + size_t pop_sum = 0; + + while (nNo < s_nRigtorpSPSCQueuePassCount) { + size_t curr_push_count = std::min(s_nRigtorpSPSCQueuePassCount - nNo, + s_nRigtorpSPSCQueueEnqueueStride); + for (size_t i = 0; i < curr_push_count; i++) { + q->push(nNo); + push_sum += nNo; + ++nNo; + } + + size_t* res = nullptr; + while ((res = q->front())) { + pop_sum += *res; + q->pop(); + } + EXPECT_EQ(pop_sum, push_sum); + push_sum = 0; + pop_sum = 0; + } + } +}; + +size_t rigtorpSPSCQueueTest::s_nRigtorpSPSCQueuePassCount; +size_t rigtorpSPSCQueueTest::s_nRigtorpSPSCQueueEnqueueStride; +size_t rigtorpSPSCQueueTest::s_nRigtorpSPSCQueueCapacity; + +TEST_F(rigtorpSPSCQueueTest, PushPop) { + test(); +} + +} // namespace diff --git a/test/stress/parallel/parallel-misc/rwlock_driver.cpp b/test/stress/parallel/parallel-misc/rwlock_driver.cpp new file mode 100644 index 00000000..ab9ca0a7 --- /dev/null +++ b/test/stress/parallel/parallel-misc/rwlock_driver.cpp @@ -0,0 +1,71 @@ +#include "common.h" +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace { + +static size_t s_nRWLockThreadCount = 6; +static size_t s_nRWLockPassCount = 200000; + +typedef cds_others::RWLock RWLock; +class RWLockTest : public cds_test::stress_fixture { +protected: + static size_t sum; + static size_t x; + + static void SetUpTestCase() { + cds_test::config const &cfg = get_config("SequentialMisc"); + GetConfig(RWLockThreadCount); + GetConfig(RWLockPassCount); + } + + static void ReaderWriterThread(RWLock *rwlock, int write_percentage) { + for (size_t i = 0; i < s_nRWLockPassCount; i++) { + if (rand(100) < write_percentage) { + if (rwlock->read_can_lock()) { + if (!rwlock->read_trylock()) { + rwlock->read_lock(); + } + sum += x; + rwlock->read_unlock(); + } else { + rwlock->read_lock(); + sum += x; + rwlock->read_unlock(); + } + } else { + if (rwlock->write_can_lock()) { + if (!rwlock->write_trylock()) { + rwlock->write_lock(); + } + x++; + rwlock->write_unlock(); + } else { + rwlock->write_lock(); + x++; + rwlock->write_unlock(); + } + } + } + } +}; + +size_t RWLockTest::x; +size_t RWLockTest::sum; + +TEST_F(RWLockTest, ReadWriteLock) { + std::unique_ptr rwlock(new RWLock()); + for (int write_percentage = 5; write_percentage < 40; write_percentage += 5) { + ReaderWriterThread(rwlock.get(), write_percentage); + } +} + +} // namespace diff --git a/test/stress/parallel/parallel-misc/seqlock_driver.cpp b/test/stress/parallel/parallel-misc/seqlock_driver.cpp new file mode 100644 index 00000000..3a7d865d --- /dev/null +++ b/test/stress/parallel/parallel-misc/seqlock_driver.cpp @@ -0,0 +1,50 @@ +#include "common.h" +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace { + +typedef cds_others::SeqLock SeqLock; + +static size_t s_nSeqLockReaderWriterThreadCount = 6; +static size_t s_nSeqLockPassCount = 2000000; + +class SeqLockTest : public cds_test::stress_fixture { +protected: + static size_t sum; + + static void SetUpTestCase() { + cds_test::config const &cfg = get_config("SequentialMisc"); + GetConfig(SeqLockReaderWriterThreadCount); + GetConfig(SeqLockPassCount); + } + + static void ReaderWriterThread(SeqLock *seqlock, int write_percentage) { + for (size_t i = 0; i < s_nSeqLockPassCount; i++) { + if (rand(100) < write_percentage) { + sum += seqlock->read(); + } else { + seqlock->write(rand(10)); + } + } + } +}; + +size_t SeqLockTest::sum; + +TEST_F(SeqLockTest, SeqLock) { + std::unique_ptr seqlock(new SeqLock()); + for (int write_percentage = 5; write_percentage < 50; write_percentage += 5) { + ReaderWriterThread(seqlock.get(), write_percentage); + } +} + +} // namespace diff --git a/test/stress/parallel/parallel-misc/spinlock_driver.cpp b/test/stress/parallel/parallel-misc/spinlock_driver.cpp new file mode 100644 index 00000000..6dce8121 --- /dev/null +++ b/test/stress/parallel/parallel-misc/spinlock_driver.cpp @@ -0,0 +1,73 @@ +#include "common.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace { + +typedef cds_others::TicketLock TicketLock; +typedef cds::sync::spin SpinLock; +typedef cds::sync::reentrant_spin32 Reentrant32; +typedef cds::sync::reentrant_spin64 Reentrant64; +static size_t s_nSpinLockThreadCount = 6; +static size_t s_nSpinLockPassCount = 2500000000; +static size_t s_nTicketLockPassCount = 4000000; + +#define TASK(lock_type, lock_ptr, pass_cnt) \ + static void Thread##lock_type(lock_type *lock_ptr) { \ + for (size_t i = 0; i < pass_cnt; i++) { \ + lock_ptr->lock(); \ + x++; \ + lock_ptr->unlock(); \ + } \ + } + +#define LOCK_TEST(lock_type, lock_ptr, pass_cnt) \ + TEST_F(SpinLockTest, lock_type) { \ + std::unique_ptr lock_ptr(new lock_type()); \ + x = 0; \ + Thread##lock_type(lock_ptr.get()); \ + } + +class SpinLockTest : public cds_test::stress_fixture { +protected: + static size_t x; + static TicketLock *ticket_mutex; + static SpinLock *spin_mutex; + static Reentrant32 *reentrant_mutex32; + static Reentrant64 *reentrant_mutex64; + + static void SetUpTestCase() { + cds_test::config const &cfg = get_config("SequentialMisc"); + GetConfig(SpinLockThreadCount); + GetConfig(SpinLockPassCount); + GetConfig(TicketLockPassCount); + } + + TASK(TicketLock, ticket_mutex, s_nTicketLockPassCount) + TASK(SpinLock, spin_mutex, s_nSpinLockPassCount) + TASK(Reentrant32, reentrant_mutex32, s_nSpinLockPassCount) + TASK(Reentrant64, reentrant_mutex64, s_nSpinLockPassCount) +}; + +size_t SpinLockTest::x; +TicketLock *SpinLockTest::ticket_mutex; +SpinLock *SpinLockTest::spin_mutex; +Reentrant32 *SpinLockTest::reentrant_mutex32; +Reentrant64 *SpinLockTest::reentrant_mutex64; + +LOCK_TEST(TicketLock, ticket_mutex, s_nTicketLockPassCount) +LOCK_TEST(SpinLock, spin_mutex, s_nSpinLockPassCount) +LOCK_TEST(Reentrant32, reentrant_mutex32, s_nSpinLockPassCount) +LOCK_TEST(Reentrant64, reentrant_mutex64, s_nSpinLockPassCount) + +} // namespace diff --git a/test/stress/parallel/parallel_freelist_put_get.cpp b/test/stress/parallel/parallel_freelist_put_get.cpp new file mode 100644 index 00000000..04308c99 --- /dev/null +++ b/test/stress/parallel/parallel_freelist_put_get.cpp @@ -0,0 +1,178 @@ +/* + 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 ); + + std::unique_ptr> worker( + new Worker(pool, list)); + worker->test(); + + // analyze result + size_t nTotal = 0; + for ( auto const& i : arr ) + nTotal += i.counter; + + EXPECT_EQ( worker->m_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) { \ + std::unique_ptr fl(new freelist_type()); \ + 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()) { + using FL = cds::intrusive::TaggedFreeList; + std::unique_ptr fl(new FL()); + test( *fl ); + } + else + std::cout << "Double-width CAS is not supported\n"; + } +#endif + +} // namespace diff --git a/test/stress/parallel/parallel_freelist_put_get_single.cpp b/test/stress/parallel/parallel_freelist_put_get_single.cpp new file mode 100644 index 00000000..b8a00e31 --- /dev/null +++ b/test/stress/parallel/parallel_freelist_put_get_single.cpp @@ -0,0 +1,156 @@ +/* + 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 ); + 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 ); + std::unique_ptr> worker( + new Worker(pool, list)); + worker->test(); + 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) { \ + std::unique_ptr fl(new freelist_type()); \ + 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()) { + using FL = cds::intrusive::TaggedFreeList; + std::unique_ptr fl(new FL()); + test( *fl ); + } + else + std::cout << "Double-width CAS is not supported\n"; + } +#endif + +} // namespace diff --git a/test/stress/parallel/parallel_queue.cpp b/test/stress/parallel/parallel_queue.cpp new file mode 100644 index 00000000..6e8760d5 --- /dev/null +++ b/test/stress/parallel/parallel_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; \ + std::unique_ptr queue(new queue_type(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; \ + std::unique_ptr queue(new queue_type()); \ + 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; \ + std::unique_ptr queue(new queue_type(s_nBufferSize)); \ + test(*queue); \ + } + +CDSSTRESS_WeakRingBuffer_void(sequential_weak_ring_buffer) + +#undef CDSSTRESS_Queue_F + +} // namespace diff --git a/test/stress/parallel/parallel_stack.cpp b/test/stress/parallel/parallel_stack.cpp new file mode 100644 index 00000000..b3598e3d --- /dev/null +++ b/test/stress/parallel/parallel_stack.cpp @@ -0,0 +1,117 @@ +/* + 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; \ + std::unique_ptr stack(new stack_type()); \ + test(*stack); \ + } + +#define CDSSTRESS_SequentialEliminationStack_F(test_fixture, type_name) \ + TEST_F(test_fixture, type_name) { \ + typedef stack::Types::type_name stack_type; \ + std::unique_ptr stack( \ + new stack_type(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 diff --git a/test/stress/parallel/test.cpp b/test/stress/parallel/test.cpp new file mode 100644 index 00000000..a632e17a --- /dev/null +++ b/test/stress/parallel/test.cpp @@ -0,0 +1,70 @@ +/* + 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" +#include +#include + +namespace { + +class sequential_test : public cds_test::stress_fixture { + +}; + +atomics::atomic x; +atomics::atomic y; +typedef cds::sync::spin SpinLock; +SpinLock l; + +struct value_type { + size_t num; +}; + +typedef stack::Types::Treiber_HP stack_type; +stack_type stack; +rigtorp::SPSCQueue q(10); + +TEST_F(sequential_test, TEST) { +// l.lock(); +// l.unlock(); +// y.store(1, atomics::memory_order_relaxed); +// value_type v = {1}; +// stack.push(v); +// stack.pop(v); + + q.push(1); +} + +} // namespace