)
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)
add_custom_target( stress-all
DEPENDS
stress-sequential-all
+ stress-parallel-all
#stress-misc
#stress-freelist
#stress-map
--- /dev/null
+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
+)
--- /dev/null
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCDSUNIT_USE_URCU")
+
+#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/delodd)
+#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/del3)
+#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/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
+)
--- /dev/null
+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})
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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<size_t> 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<size_t> 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<size_t> lf;
+ for ( size_t n = 1; n <= s_nMaxLoadFactor; n *= 2 )
+ lf.push_back( n );
+
+ return lf;
+ }
+
+#ifdef CDSTEST_GTEST_INSTANTIATE_TEST_CASE_P_HAS_4TH_ARG
+ static std::string get_test_parameter_name( testing::TestParamInfo<size_t> const& p )
+ {
+ return std::to_string( p.param );
+ }
+ INSTANTIATE_TEST_CASE_P( a, 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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_type.h"
+#include <cds/os/topology.h>
+
+namespace map {
+
+ namespace {
+ struct key_thread
+ {
+ uint32_t nKey;
+ uint16_t nThread;
+
+ key_thread( size_t key, size_t threadNo )
+ : nKey( static_cast<uint32_t>(key))
+ , nThread( static_cast<uint16_t>(threadNo))
+ {}
+
+ key_thread()
+ : nKey()
+ , nThread()
+ {}
+ };
+
+ static_assert(sizeof( key_thread ) % 8 == 0, "Key size mismatch!!!");
+ } // namespace
+
+ template <>
+ struct cmp<key_thread> {
+ int operator ()(key_thread const& k1, key_thread const& k2) const
+ {
+ if ( k1.nKey < k2.nKey )
+ return -1;
+ if ( k1.nKey > k2.nKey )
+ return 1;
+ if ( k1.nThread < k2.nThread )
+ return -1;
+ if ( k1.nThread > k2.nThread )
+ return 1;
+ return 0;
+ }
+ int operator ()(key_thread const& k1, size_t k2) const
+ {
+ if ( k1.nKey < k2 )
+ return -1;
+ if ( k1.nKey > k2 )
+ return 1;
+ return 0;
+ }
+ int operator ()(size_t k1, key_thread const& k2) const
+ {
+ if ( k1 < k2.nKey )
+ return -1;
+ if ( k1 > k2.nKey )
+ return 1;
+ return 0;
+ }
+ };
+
+ template <>
+ struct less<key_thread>
+ {
+ 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<key_thread>
+ {
+ typedef size_t result_type;
+ typedef key_thread argument_type;
+
+ size_t operator()( key_thread const& k ) const
+ {
+ return std::hash<size_t>()(k.nKey);
+ }
+ size_t operator()( size_t k ) const
+ {
+ return std::hash<size_t>()(k);
+ }
+ };
+
+ class 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<size_t> m_arrElements;
+
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+
+ template <typename Pred>
+ static void prepare_array( std::vector<size_t>& 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<key_type const, value_type> pair_type;
+
+ atomics::atomic<size_t> m_nInsThreadCount;
+
+ enum {
+ inserter_thread,
+ deleter_thread,
+ extractor_thread,
+ find_thread,
+ };
+
+ // Inserts keys from [0..N)
+ template <class Map>
+ class Inserter: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Map& m_Map;
+
+ struct update_func
+ {
+ template <typename Q>
+ void operator()( bool /*bNew*/, Q const& ) const
+ {}
+
+ template <typename Q, typename V>
+ void operator()( bool /*bNew*/, Q const&, V& ) const
+ {}
+
+ // FeldmanHashMap
+ template <typename Q>
+ 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<size_t> 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<Map_Del3>();
+
+ 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 Map>
+ 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<size_t> 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<Map_Del3>();
+ 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 GC, class Map >
+ 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<size_t> 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<Map_Del3>();
+ 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 RCU, class Map >
+ class Extractor< cds::urcu::gc<RCU>, 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<size_t> 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<Map_Del3>();
+
+ 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 Map>
+ 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<Map_Del3>();
+ std::vector<size_t> 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 <class Map>
+ void do_test( Map& testMap )
+ {
+ typedef Inserter<Map> insert_thread;
+ typedef Deleter<Map> delete_thread;
+ typedef Observer<Map> 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<insert_thread&>( thr );
+ nInsertSuccess += inserter.m_nInsertSuccess;
+ nInsertFailed += inserter.m_nInsertFailed;
+ nInsertInitSuccess += inserter.m_nInsertInitSuccess;
+ nInsertInitFailed += inserter.m_nInsertInitFailed;
+ }
+ break;
+ case deleter_thread:
+ {
+ delete_thread& deleter = static_cast<delete_thread&>( thr );
+ nDeleteSuccess += deleter.m_nDeleteSuccess;
+ nDeleteFailed += deleter.m_nDeleteFailed;
+ }
+ break;
+ case find_thread:
+ {
+ observer_thread& observer = static_cast<observer_thread&>( thr );
+ nFindEvenSuccess = observer.m_nFindEvenSuccess;
+ nFindEvenFailed = observer.m_nFindEvenFailed;
+ nFindOddSuccess = observer.m_nFindOddSuccess;
+ nFindOddFailed = observer.m_nFindOddFailed;
+ }
+ break;
+ }
+ }
+
+ 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 <class Map>
+ void do_test_extract( Map& testMap )
+ {
+ typedef Inserter<Map> insert_thread;
+ typedef Deleter<Map> delete_thread;
+ typedef Extractor< typename Map::gc, Map > extract_thread;
+ typedef Observer<Map> observer_thread;
+
+ cds_test::thread_pool &pool = get_pool();
+ std::unique_ptr<insert_thread> inserter(
+ new insert_thread(pool, testMap));
+ std::unique_ptr<delete_thread> deleter(
+ new delete_thread(pool, testMap));
+ std::unique_ptr<extract_thread> extractor(
+ new extract_thread(pool, testMap));
+ std::unique_ptr<observer_thread> 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 <class Map>
+ 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 <class Map>
+ 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 <class Map>
+ void run_test()
+ {
+ size_t nMapSize = s_nMapSize;
+ s_nMapSize *= s_nInsThreadCount;
+
+ Map testMap( *this );
+
+ s_nMapSize = nMapSize;
+ do_test( testMap );
+ }
+
+ template <class Map>
+ void run_feldman();
+
+ template <class Map>
+ void run_bronson_avl_tree();
+
+ template <class Map>
+ void run_ellen_bin_tree();
+
+ template <class Map>
+ void run_skip_list();
+
+ template <class Map>
+ void run_michael();
+ };
+
+ class Map_Del3_LF: public Map_Del3
+ , public ::testing::WithParamInterface<size_t>
+ {
+ public:
+ template <class Map>
+ void run_test()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Map_Del3::run_test<Map>();
+ }
+
+ template <class Map>
+ void run_test_extract()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Map_Del3::run_test_extract<Map>();
+ }
+
+ static std::vector<size_t> get_load_factors();
+ };
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_del3.h"
+#include "map_type_bronson_avltree.h"
+
+namespace map {
+
+ template <class Map>
+ void Map_Del3::run_bronson_avl_tree()
+ {
+ Map_Del3::s_nPassCount = Map_Del3::s_nBronsonAVLTreeMapPassCount;
+ run_test_extract<Map>();
+ }
+
+ CDSSTRESS_BronsonAVLTreeMap( Map_Del3, run_bronson_avl_tree, key_thread, size_t )
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_del3.h"
+#include "map_type_cuckoo.h"
+
+namespace map {
+
+// CDSSTRESS_CuckooMap( Map_Del3, run_test, key_thread, size_t )
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_del3.h"
+#include "map_type_ellen_bintree.h"
+
+namespace map {
+
+ template <class Map>
+ void Map_Del3::run_ellen_bin_tree()
+ {
+ Map_Del3::s_nPassCount = Map_Del3::s_nEllenBinTreeMapPassCount;
+ run_test_extract<Map>();
+ }
+
+ CDSSTRESS_EllenBinTreeMap( Map_Del3, run_ellen_bin_tree, key_thread, size_t )
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_del3.h"
+#include "map_type_feldman_hashmap.h"
+
+namespace map {
+
+ template <class Map>
+ 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<map_type>();
+ }
+
+ CDSSTRESS_FeldmanHashMap_fixed( Map_Del3, run_feldman, key_thread, size_t )
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_del3.h"
+#include "map_type_michael.h"
+
+namespace map {
+
+ template <class Map>
+ void Map_Del3::run_michael()
+ {
+ Map_Del3::s_nPassCount = Map_Del3::s_nMichaelMapPassCount;
+ run_test_extract<Map>();
+ }
+
+ CDSSTRESS_MichaelMap( Map_Del3_LF, run_michael, key_thread, size_t )
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_del3.h"
+#include "map_type_skip_list.h"
+
+namespace map {
+
+ template <class Map>
+ void Map_Del3::run_skip_list()
+ {
+ Map_Del3::s_nPassCount = Map_Del3::s_nSkipListMapPassCount;
+ run_test_extract<Map>();
+ }
+
+ CDSSTRESS_SkipListMap( Map_Del3, run_skip_list, key_thread, size_t )
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+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})
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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<size_t> 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<size_t> 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<size_t> lf;
+ for ( size_t n = 1; n <= s_nMaxLoadFactor; n *= 2 )
+ lf.push_back( n );
+
+ return lf;
+ }
+
+#ifdef CDSTEST_GTEST_INSTANTIATE_TEST_CASE_P_HAS_4TH_ARG
+ static std::string get_test_parameter_name( testing::TestParamInfo<size_t> const& p )
+ {
+ return std::to_string( p.param );
+ }
+ INSTANTIATE_TEST_CASE_P( a, 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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_type.h"
+#include <cds/os/topology.h>
+
+namespace map {
+
+ namespace {
+ struct key_thread
+ {
+ uint32_t nKey;
+ uint16_t nThread;
+
+ key_thread( size_t key, size_t threadNo )
+ : nKey( static_cast<uint32_t>(key))
+ , nThread( static_cast<uint16_t>(threadNo))
+ {}
+
+ key_thread()
+ : nKey()
+ , nThread()
+ {}
+ };
+
+ static_assert(sizeof( key_thread ) % 8 == 0, "Key size mismatch!!!");
+ } // namespace
+
+ template <>
+ struct cmp<key_thread> {
+ int operator ()(key_thread const& k1, key_thread const& k2) const
+ {
+ if ( k1.nKey < k2.nKey )
+ return -1;
+ if ( k1.nKey > k2.nKey )
+ return 1;
+ if ( k1.nThread < k2.nThread )
+ return -1;
+ if ( k1.nThread > k2.nThread )
+ return 1;
+ return 0;
+ }
+ int operator ()(key_thread const& k1, size_t k2) const
+ {
+ if ( k1.nKey < k2 )
+ return -1;
+ if ( k1.nKey > k2 )
+ return 1;
+ return 0;
+ }
+ int operator ()(size_t k1, key_thread const& k2) const
+ {
+ if ( k1 < k2.nKey )
+ return -1;
+ if ( k1 > k2.nKey )
+ return 1;
+ return 0;
+ }
+ };
+
+ template <>
+ struct less<key_thread>
+ {
+ 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<key_thread>
+ {
+ typedef size_t result_type;
+ typedef key_thread argument_type;
+
+ size_t operator()( key_thread const& k ) const
+ {
+ return std::hash<size_t>()(k.nKey);
+ }
+ size_t operator()( size_t k ) const
+ {
+ return std::hash<size_t>()(k);
+ }
+ };
+
+ class 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<size_t> m_arrElements;
+
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+
+ template <typename Pred>
+ static void prepare_array( std::vector<size_t>& 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<key_type const, value_type> pair_type;
+
+ atomics::atomic<size_t> m_nInsThreadCount;
+
+ enum {
+ inserter_thread,
+ deleter_thread,
+ extractor_thread,
+ find_thread,
+ };
+
+ // Inserts keys from [0..N)
+ template <class Map>
+ class Inserter: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Map& m_Map;
+
+ struct update_func
+ {
+ template <typename Q>
+ void operator()( bool /*bNew*/, Q const& ) const
+ {}
+
+ template <typename Q, typename V>
+ void operator()( bool /*bNew*/, Q const&, V& ) const
+ {}
+
+ // FeldmanHashMap
+ template <typename Q>
+ 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<size_t> 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<Map_DelOdd>();
+
+ 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 Map>
+ 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<size_t> 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<Map_DelOdd>();
+ 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 GC, class Map >
+ 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<size_t> 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<Map_DelOdd>();
+ size_t const nInsThreadCount = s_nInsThreadCount;
+
+ do {
+ if ( id() & 1 ) {
+ for ( auto el : m_arr ) {
+ for ( size_t k = 0; k < nInsThreadCount; ++k ) {
+ gp = 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 RCU, class Map >
+ class Extractor< cds::urcu::gc<RCU>, 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<size_t> 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<Map_DelOdd>();
+
+ 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 Map>
+ 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<Map_DelOdd>();
+ std::vector<size_t> 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 <class Map>
+ void do_test( Map& testMap )
+ {
+ typedef Inserter<Map> insert_thread;
+ typedef Deleter<Map> delete_thread;
+ typedef Observer<Map> 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<insert_thread&>( thr );
+ nInsertSuccess += inserter.m_nInsertSuccess;
+ nInsertFailed += inserter.m_nInsertFailed;
+ nInsertInitSuccess += inserter.m_nInsertInitSuccess;
+ nInsertInitFailed += inserter.m_nInsertInitFailed;
+ }
+ break;
+ case deleter_thread:
+ {
+ delete_thread& deleter = static_cast<delete_thread&>( thr );
+ nDeleteSuccess += deleter.m_nDeleteSuccess;
+ nDeleteFailed += deleter.m_nDeleteFailed;
+ }
+ break;
+ case find_thread:
+ {
+ observer_thread& observer = static_cast<observer_thread&>( thr );
+ nFindEvenSuccess = observer.m_nFindEvenSuccess;
+ nFindEvenFailed = observer.m_nFindEvenFailed;
+ nFindOddSuccess = observer.m_nFindOddSuccess;
+ nFindOddFailed = observer.m_nFindOddFailed;
+ }
+ break;
+ }
+ }
+
+ 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 <class Map>
+ void do_test_extract( Map& testMap )
+ {
+ typedef Inserter<Map> insert_thread;
+ typedef Deleter<Map> delete_thread;
+ typedef Extractor< typename Map::gc, Map > extract_thread;
+ typedef Observer<Map> 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<insert_thread&>(thr);
+ nInsertSuccess += inserter.m_nInsertSuccess;
+ nInsertFailed += inserter.m_nInsertFailed;
+ nInsertInitSuccess += inserter.m_nInsertInitSuccess;
+ nInsertInitFailed += inserter.m_nInsertInitFailed;
+ }
+ break;
+ case deleter_thread:
+ {
+ delete_thread& deleter = static_cast<delete_thread&>(thr);
+ nDeleteSuccess += deleter.m_nDeleteSuccess;
+ nDeleteFailed += deleter.m_nDeleteFailed;
+ }
+ break;
+ case extractor_thread:
+ {
+ extract_thread& extractor = static_cast<extract_thread&>(thr);
+ nExtractSuccess += extractor.m_nDeleteSuccess;
+ nExtractFailed += extractor.m_nDeleteFailed;
+ }
+ break;
+ case find_thread:
+ {
+ observer_thread& observer = static_cast<observer_thread&>( thr );
+ nFindEvenSuccess = observer.m_nFindEvenSuccess;
+ nFindEvenFailed = observer.m_nFindEvenFailed;
+ nFindOddSuccess = observer.m_nFindOddSuccess;
+ nFindOddFailed = observer.m_nFindOddFailed;
+ }
+ break;
+ default:
+ assert( false );
+ }
+ }
+
+ size_t const nInitialOddKeys = ( s_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 <class Map>
+ 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 <class Map>
+ 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 <class Map>
+ void run_test()
+ {
+ size_t nMapSize = s_nMapSize;
+ s_nMapSize *= s_nInsThreadCount;
+
+ Map testMap( *this );
+
+ s_nMapSize = nMapSize;
+ do_test( testMap );
+ }
+
+ template <class Map>
+ void run_feldman();
+ };
+
+ class Map_DelOdd_LF: public Map_DelOdd
+ , public ::testing::WithParamInterface<size_t>
+ {
+ public:
+ template <class Map>
+ void run_test()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Map_DelOdd::run_test<Map>();
+ }
+
+ template <class Map>
+ void run_test_extract()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Map_DelOdd::run_test_extract<Map>();
+ }
+
+ static std::vector<size_t> get_load_factors();
+ };
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_delodd.h"
+#include "map_type_bronson_avltree.h"
+
+namespace map {
+
+ CDSSTRESS_BronsonAVLTreeMap( Map_DelOdd, run_test_extract, key_thread, size_t )
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_delodd.h"
+#include "map_type_cuckoo.h"
+
+namespace map {
+
+// CDSSTRESS_CuckooMap( Map_DelOdd, run_test, key_thread, size_t )
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_delodd.h"
+#include "map_type_ellen_bintree.h"
+
+namespace map {
+
+ CDSSTRESS_EllenBinTreeMap( Map_DelOdd, run_test_extract, key_thread, size_t )
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_delodd.h"
+#include "map_type_feldman_hashmap.h"
+
+namespace map {
+
+ template <class Map>
+ 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<map_type>();
+ }
+
+ CDSSTRESS_FeldmanHashMap_fixed( Map_DelOdd, run_feldman, key_thread, size_t )
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_delodd.h"
+#include "map_type_michael.h"
+
+namespace map {
+
+ CDSSTRESS_MichaelMap( Map_DelOdd_LF, run_test_extract, key_thread, size_t )
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_delodd.h"
+#include "map_type_skip_list.h"
+
+namespace map {
+
+ CDSSTRESS_SkipListMap( Map_DelOdd, run_test_extract, key_thread, size_t )
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+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})
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_find_string.h"
+#include <cds_test/hash_func.h>
+
+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<std::string> 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 <typename Hash>
+ void Map_find_string::fill_string_array()
+ {
+ typedef Hash hasher;
+ typedef typename hasher::result_type hash_type;
+
+ std::map<hash_type, size_t> 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<std::hash<std::string>>();
+ }
+
+#if CDS_BUILD_BITS == 64
+ void Map_find_string_city32::SetUpTestCase()
+ {
+ setup_test_case();
+ fill_string_array<cds_test::city32>();
+ }
+
+ void Map_find_string_city64::SetUpTestCase()
+ {
+ setup_test_case();
+ fill_string_array<cds_test::city64>();
+ }
+
+ void Map_find_string_city128::SetUpTestCase()
+ {
+ setup_test_case();
+ fill_string_array<cds_test::city128>();
+ }
+
+#endif
+
+ std::vector<size_t> 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<size_t> lf;
+ for ( size_t n = 1; n <= s_nMaxLoadFactor; n *= 2 )
+ lf.push_back( n );
+
+ return lf;
+ }
+
+#ifdef CDSTEST_GTEST_INSTANTIATE_TEST_CASE_P_HAS_4TH_ARG
+ static std::string get_test_parameter_name( testing::TestParamInfo<size_t> const& p )
+ {
+ return std::to_string( p.param );
+ }
+ INSTANTIATE_TEST_CASE_P( a, 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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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_type> value_vector;
+ static std::vector<std::string> s_arrString;
+ static value_vector s_Data;
+
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+
+ static void setup_test_case();
+ static std::vector<size_t> get_load_factors();
+
+ private:
+ template <typename Iterator, typename Map>
+ static bool check_result( Iterator const& it, Map const& map )
+ {
+ return it != map.end();
+ }
+ template <typename Map>
+ static bool check_result( bool b, Map const& )
+ {
+ return b;
+ }
+
+ template <class Map>
+ 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 <typename Hash>
+ static void fill_string_array();
+
+ template <class Map>
+ void test( Map& testMap )
+ {
+ typedef Worker<Map> 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> worker_thread(new worker(pool, testMap));
+ worker_thread->test();
+
+ testMap.clear();
+ additional_cleanup(testMap);
+ }
+
+ template <class Map>
+ void run_test()
+ {
+ ASSERT_GT( s_Data.size(), 0u );
+
+ Map testMap( *this );
+ test( testMap );
+ }
+
+ template <class Map>
+ void run_bronson_avl_tree() {
+ Map_find_string::s_nPassCount =
+ Map_find_string::s_nBronsonAVLTreeMapPassCount;
+ run_test<Map>();
+ }
+
+ template <class Map>
+ void run_ellen_bin_tree() {
+ Map_find_string::s_nPassCount =
+ Map_find_string::s_nEllenBinTreeMapPassCount;
+ run_test<Map>();
+ }
+
+ template <class Map>
+ void run_feldman() {
+ Map_find_string::s_nPassCount =
+ Map_find_string::s_nFeldmanPassCount;
+ run_test<Map>();
+ }
+
+ template <class Map>
+ void run_michael() {
+ Map_find_string::s_nPassCount =
+ Map_find_string::s_nMichaelMapPassCount;
+ run_test<Map>();
+ }
+
+ template <class Map>
+ void run_skip_list() {
+ Map_find_string::s_nPassCount =
+ Map_find_string::s_nSkipListMapPassCount;
+ run_test<Map>();
+ }
+
+ template <class Map>
+ void run_split_list() {
+ Map_find_string::s_nPassCount =
+ Map_find_string::s_nSplitListMapPassCount;
+ run_test<Map>();
+ }
+
+ };
+
+ class Map_find_string_stdhash: public Map_find_string
+ {
+ public:
+ static void SetUpTestCase();
+
+ template <class Map>
+ void run_test()
+ {
+ Map_find_string::run_test<Map>();
+ }
+ };
+
+#if CDS_BUILD_BITS == 64
+ class Map_find_string_city32: public Map_find_string
+ {
+ public:
+ static void SetUpTestCase();
+
+ template <class Map>
+ void run_test()
+ {
+ Map_find_string::run_test<Map>();
+ }
+ };
+
+ class Map_find_string_city64: public Map_find_string
+ {
+ public:
+ static void SetUpTestCase();
+
+ template <class Map>
+ void run_test()
+ {
+ Map_find_string::run_test<Map>();
+ }
+ };
+
+ class Map_find_string_city128: public Map_find_string
+ {
+ public:
+ static void SetUpTestCase();
+
+ template <class Map>
+ void run_test()
+ {
+ Map_find_string::run_test<Map>();
+ }
+ };
+
+#endif // #if CDS_BUILD_BITS == 64
+
+ class Map_find_string_LF: public Map_find_string
+ , public ::testing::WithParamInterface<size_t>
+ {
+ public:
+ template <class Map>
+ void run_test()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Map_find_string::run_test<Map>();
+ }
+ };
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+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})
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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<size_t> 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<size_t> lf;
+ for ( size_t n = 1; n <= s_nMaxLoadFactor; n *= 2 )
+ lf.push_back( n );
+
+ return lf;
+ }
+
+#ifdef CDSTEST_GTEST_INSTANTIATE_TEST_CASE_P_HAS_4TH_ARG
+ static std::string get_test_parameter_name( testing::TestParamInfo<size_t> const& p )
+ {
+ return std::to_string( p.param );
+ }
+ INSTANTIATE_TEST_CASE_P( a, 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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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<bool> 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_type> key_array;
+ static key_array s_arrKeys;
+
+ protected:
+ enum {
+ insert_thread,
+ delete_thread,
+ update_thread
+ };
+
+ template <class Map>
+ 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 <typename Pair>
+ void operator()( Pair& val )
+ {
+ operator()( val.first, val.second );
+ }
+
+ template <typename Key, typename Val >
+ 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 Map>
+ 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 <typename Key, typename Val>
+ void operator()( bool /*bNew*/, Key const& key, Val& v )
+ {
+ std::unique_lock<typename value_type::lock_type> 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 <typename Pair>
+ void operator()( bool bNew, Pair& val )
+ {
+ operator()( bNew, val.first, val.second );
+ }
+
+ // For FeldmanHashMap, IterableList
+ template <typename Val>
+ 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<typename value_type::lock_type> 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<bool, bool> 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<bool, bool> 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 Map>
+ 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 <typename Key, typename Val>
+ 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 <typename Pair>
+ 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 <class Map>
+ void do_test( Map& testMap )
+ {
+ typedef Inserter<Map> inserter;
+ typedef Deleter<Map> deleter;
+ typedef Updater<Map> 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<inserter&>( thr );
+ nInsertSuccess += t.m_nInsertSuccess;
+ nInsertFailed += t.m_nInsertFailed;
+ nInsFuncCalled += t.m_nTestFunctorRef;
+ }
+ break;
+ case delete_thread:
+ {
+ deleter& t = static_cast<deleter&>(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<updater&>(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 <class Map>
+ void run_test()
+ {
+ Map testMap( *this );
+ do_test( testMap );
+ }
+
+ template <class Map>
+ 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<size_t>
+ {
+ public:
+ template <class Set>
+ void run_test()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Map_InsDel_func::run_test<Set>();
+ }
+
+ template <class Set>
+ void run_test2()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Map_InsDel_func::run_test2<Set>();
+ }
+
+ static std::vector<size_t> get_load_factors();
+ };
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+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})
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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<size_t> 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<size_t> lf;
+ for ( size_t n = 1; n <= s_nMaxLoadFactor; n *= 2 )
+ lf.push_back( n );
+
+ return lf;
+ }
+
+#ifdef CDSTEST_GTEST_INSTANTIATE_TEST_CASE_P_HAS_4TH_ARG
+ static std::string get_test_parameter_name( testing::TestParamInfo<size_t> const& p )
+ {
+ return std::to_string( p.param );
+ }
+ INSTANTIATE_TEST_CASE_P( a, 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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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 Map>
+ class Inserter: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Map& m_Map;
+
+ struct update_func
+ {
+ void operator()( bool bNew, std::pair<key_type const, value_type>& item ) const
+ {
+ if ( bNew )
+ item.second = item.first;
+ }
+
+ // for boost::container::flat_map
+ void operator()( bool bNew, std::pair<key_type, value_type>& 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<key_type const, value_type>& item, std::pair<key_type const, value_type>* 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<bool, bool> updateResult = rMap.update( nGoalItem, update_func(), true );
+ if ( updateResult.second ) {
+ ++m_nInsertSuccess;
+ ++nAttempt;
+ }
+ else
+ ++m_nInsertFailed;
+ }
+ }
+ }
+ };
+
+ template <class Map>
+ 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 <class Map>
+ void do_test( Map& testMap )
+ {
+ typedef Inserter<Map> inserter;
+ typedef Deleter<Map> deleter;
+
+ // Fill the map
+ {
+ std::vector<key_type> 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<inserter&>(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<deleter&>(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 <class Map>
+ void run_test()
+ {
+ Map testMap( *this );
+ do_test<Map>( testMap );
+ }
+ };
+
+ class Map_InsDel_item_int_LF: public Map_InsDel_item_int
+ , public ::testing::WithParamInterface<size_t>
+ {
+ public:
+ template <class Set>
+ void run_test()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Map_InsDel_item_int::run_test<Set>();
+ }
+
+ static std::vector<size_t> get_load_factors();
+ };
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+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})
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_insdel_string.h"
+#include <cds_test/hash_func.h>
+
+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<std::string> 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<std::string> 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<size_t> 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<size_t> lf;
+ for ( size_t n = 1; n <= s_nMaxLoadFactor; n *= 2 )
+ lf.push_back( n );
+
+ return lf;
+ }
+
+ template <typename Hash>
+ void Map_InsDel_string::fill_string_array()
+ {
+ typedef Hash hasher;
+ typedef typename hasher::result_type hash_type;
+
+ std::map<hash_type, size_t> mapHash;
+ s_arrKeys.clear();
+ std::vector<std::string> 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<std::hash<std::string>>();
+ }
+
+#if CDS_BUILD_BITS == 64
+ void Map_InsDel_string_city32::SetUpTestCase()
+ {
+ setup_test_case();
+ fill_string_array<cds_test::city32>();
+ }
+
+ void Map_InsDel_string_city64::SetUpTestCase()
+ {
+ setup_test_case();
+ fill_string_array<cds_test::city64>();
+ }
+
+ void Map_InsDel_string_city128::SetUpTestCase()
+ {
+ setup_test_case();
+ fill_string_array<cds_test::city128>();
+ }
+
+#endif
+
+#ifdef CDSTEST_GTEST_INSTANTIATE_TEST_CASE_P_HAS_4TH_ARG
+ static std::string get_test_parameter_name( testing::TestParamInfo<size_t> const& p )
+ {
+ return std::to_string( p.param );
+ }
+ INSTANTIATE_TEST_CASE_P( a, 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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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<size_t> get_load_factors();
+
+ typedef std::string key_type;
+ typedef size_t value_type;
+
+ static std::vector<std::string> s_arrKeys;
+
+ protected:
+ enum {
+ insert_thread,
+ delete_thread
+ };
+
+ template <class Map>
+ 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 Map>
+ 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 <typename Hash>
+ static void fill_string_array();
+
+ template <class Map>
+ void do_test( Map& testMap )
+ {
+ typedef Inserter<Map> inserter;
+ typedef Deleter<Map> deleter;
+
+ cds_test::thread_pool& pool = get_pool();
+ std::unique_ptr<inserter> inserter_thrd(
+ new inserter(pool, testMap));
+ std::unique_ptr<deleter> 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 <class Map>
+ void run_test()
+ {
+ Map testMap( *this );
+ do_test( testMap );
+ }
+
+ template <class Map>
+ void run_bronson_avl_tree() {
+ Map_InsDel_string::s_nThreadPassCount =
+ Map_InsDel_string::s_nBronsonAVLTreeMapPassCount;
+ run_test<Map>();
+ }
+
+ template <class Map>
+ void run_ellen_bin_tree() {
+ Map_InsDel_string::s_nThreadPassCount =
+ Map_InsDel_string::s_nEllenBinTreeMapPassCount;
+ run_test<Map>();
+ }
+
+ template <class Map>
+ void run_feldman() {
+ Map_InsDel_string::s_nThreadPassCount =
+ Map_InsDel_string::s_nFeldmanPassCount;
+ run_test<Map>();
+ }
+
+ template <class Map>
+ void run_michael() {
+ Map_InsDel_string::s_nThreadPassCount =
+ Map_InsDel_string::s_nMichaelMapPassCount;
+ run_test<Map>();
+ }
+
+ template <class Map>
+ void run_skip_list() {
+ Map_InsDel_string::s_nThreadPassCount =
+ Map_InsDel_string::s_nSkipListMapPassCount;
+ run_test<Map>();
+ }
+
+ template <class Map>
+ void run_split_list() {
+ Map_InsDel_string::s_nThreadPassCount =
+ Map_InsDel_string::s_nSplitListMapPassCount;
+ run_test<Map>();
+ }
+ };
+
+ class Map_InsDel_string_stdhash: public Map_InsDel_string
+ {
+ public:
+ static void SetUpTestCase();
+
+ template <class Map>
+ void run_test()
+ {
+ Map_InsDel_string::run_test<Map>();
+ }
+ };
+
+#if CDS_BUILD_BITS == 64
+ class Map_InsDel_string_city32: public Map_InsDel_string
+ {
+ public:
+ static void SetUpTestCase();
+
+ template <class Map>
+ void run_test()
+ {
+ Map_InsDel_string::run_test<Map>();
+ }
+ };
+
+ class Map_InsDel_string_city64: public Map_InsDel_string
+ {
+ public:
+ static void SetUpTestCase();
+
+ template <class Map>
+ void run_test()
+ {
+ Map_InsDel_string::run_test<Map>();
+ }
+ };
+
+ class Map_InsDel_string_city128: public Map_InsDel_string
+ {
+ public:
+ static void SetUpTestCase();
+
+ template <class Map>
+ void run_test()
+ {
+ Map_InsDel_string::run_test<Map>();
+ }
+ };
+
+#endif // #if CDS_BUILD_BITS == 64
+
+ class Map_InsDel_string_LF: public Map_InsDel_string
+ , public ::testing::WithParamInterface<size_t>
+ {
+ public:
+ template <class Map>
+ void run_test()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Map_InsDel_string::run_test<Map>();
+ }
+ };
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_insdel_string.h"
+#include "map_type_cuckoo.h"
+
+namespace map {
+
+// CDSSTRESS_CuckooMap( Map_InsDel_string, run_test, std::string, size_t )
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_insdel_string.h"
+#include "map_type_std.h"
+
+namespace map {
+
+// CDSSTRESS_StdMap( Map_InsDel_string, run_test, std::string, size_t )
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+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
+)
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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<size_t> 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<size_t> 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<size_t> 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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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 Map>
+ 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 <typename Q>
+ 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 <class Map>
+ void do_test( Map& testMap )
+ {
+ typedef Worker<Map> worker;
+ cds_test::thread_pool& pool = get_pool();
+ std::unique_ptr<worker> worker_thrd(new worker(pool, testMap));
+ worker_thrd->test();
+
+ testMap.clear();
+ EXPECT_TRUE( testMap.empty());
+ additional_cleanup( testMap );
+ }
+
+ template <class Map>
+ void run_test()
+ {
+ std::unique_ptr<Map> testMap(new Map(*this));
+ do_test(*testMap);
+ }
+
+ template <class Map>
+ void run_bronson_avl_tree() {
+ Map_InsDelFind::s_nPassCount =
+ Map_InsDelFind::s_nBronsonAVLTreeMapPassCount;
+ run_test<Map>();
+ }
+
+ template <class Map>
+ void run_ellen_bin_tree_hp() {
+ Map_InsDelFind::s_nPassCount =
+ Map_InsDelFind::s_nHpEllenBinTreeMapPassCount;
+ run_test<Map>();
+ }
+
+ template <class Map>
+ void run_skip_list_hp() {
+ Map_InsDelFind::s_nPassCount =
+ Map_InsDelFind::s_nHpSkipListMapPassCount;
+ run_test<Map>();
+ }
+
+ template <class Map>
+ void run_feldman_hp() {
+ Map_InsDelFind::s_nPassCount =
+ Map_InsDelFind::s_nHpFeldmanPassCount;
+ run_test<Map>();
+ }
+
+ template <class Map>
+ void run_ellen_bin_tree_rcu() {
+ Map_InsDelFind::s_nPassCount =
+ Map_InsDelFind::s_nRcuEllenBinTreeMapPassCount;
+ run_test<Map>();
+ }
+
+ template <class Map>
+ void run_skip_list_rcu() {
+ Map_InsDelFind::s_nPassCount =
+ Map_InsDelFind::s_nRcuSkipListMapPassCount;
+ run_test<Map>();
+ }
+
+ template <class Map>
+ void run_feldman_rcu() {
+ Map_InsDelFind::s_nPassCount =
+ Map_InsDelFind::s_nRcuFeldmanPassCount;
+ run_test<Map>();
+ }
+ };
+
+ class Map_InsDelFind_LF: public Map_InsDelFind
+ , public ::testing::WithParamInterface<size_t>
+ {
+ public:
+ template <class Map>
+ void run_test()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Map_InsDelFind::run_test<Map>();
+ }
+
+ template <class Map>
+ void run_michael_hp() {
+ Map_InsDelFind::s_nPassCount =
+ Map_InsDelFind::s_nHpMichaelMapPassCount;
+ Map_InsDelFind_LF::run_test<Map>();
+ }
+
+ template <class Map>
+ void run_split_list_hp() {
+ Map_InsDelFind::s_nPassCount =
+ Map_InsDelFind::s_nHpSplitListMapPassCount;
+ Map_InsDelFind_LF::run_test<Map>();
+ }
+
+ template <class Map>
+ void run_michael_rcu() {
+ Map_InsDelFind::s_nPassCount =
+ Map_InsDelFind::s_nRcuMichaelMapPassCount;
+ Map_InsDelFind_LF::run_test<Map>();
+ }
+
+ template <class Map>
+ void run_split_list_rcu() {
+ Map_InsDelFind::s_nPassCount =
+ Map_InsDelFind::s_nRcuSplitListMapPassCount;
+ Map_InsDelFind_LF::run_test<Map>();
+ }
+
+ static std::vector<size_t> get_load_factors();
+ };
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_insdelfind.h"
+#include "map_type_cuckoo.h"
+
+namespace map {
+
+// CDSSTRESS_CuckooMap( Map_InsDelFind, run_test, size_t, size_t )
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_insdelfind.h"
+#include "map_type_std.h"
+
+namespace map {
+
+// CDSSTRESS_StdMap( Map_InsDelFind, run_test, size_t, size_t )
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_insdelfind.h"
+#include "map_type_striped.h"
+
+namespace map {
+
+// CDSSTRESS_StripedMap( Map_InsDelFind_LF, run_test, size_t, size_t )
+
+} // namespace map
--- /dev/null
+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})
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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<size_t> 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<size_t> 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<size_t> lf;
+ for ( size_t n = 1; n <= s_nMaxLoadFactor; n *= 2 )
+ lf.push_back( n );
+
+ return lf;
+ }
+
+#ifdef CDSTEST_GTEST_INSTANTIATE_TEST_CASE_P_HAS_4TH_ARG
+ static std::string get_test_parameter_name( testing::TestParamInfo<size_t> const& p )
+ {
+ return std::to_string( p.param );
+ }
+ INSTANTIATE_TEST_CASE_P( a, 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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_type.h"
+#include <cds/os/topology.h>
+
+namespace map {
+
+ namespace {
+ struct key_thread
+ {
+ uint32_t nKey;
+ uint16_t nThread;
+
+ key_thread( size_t key, size_t threadNo )
+ : nKey( static_cast<uint32_t>(key))
+ , nThread( static_cast<uint16_t>(threadNo))
+ {}
+
+ key_thread()
+ : nKey()
+ , nThread()
+ {}
+ };
+
+ static_assert(sizeof( key_thread ) % 8 == 0, "Key size mismatch!!!");
+ } // namespace
+
+ template <>
+ struct cmp<key_thread> {
+ int operator ()(key_thread const& k1, key_thread const& k2) const
+ {
+ if ( k1.nKey < k2.nKey )
+ return -1;
+ if ( k1.nKey > k2.nKey )
+ return 1;
+ if ( k1.nThread < k2.nThread )
+ return -1;
+ if ( k1.nThread > k2.nThread )
+ return 1;
+ return 0;
+ }
+ int operator ()(key_thread const& k1, size_t k2) const
+ {
+ if ( k1.nKey < k2 )
+ return -1;
+ if ( k1.nKey > k2 )
+ return 1;
+ return 0;
+ }
+ int operator ()(size_t k1, key_thread const& k2) const
+ {
+ if ( k1 < k2.nKey )
+ return -1;
+ if ( k1 > k2.nKey )
+ return 1;
+ return 0;
+ }
+ };
+
+ template <>
+ struct less<key_thread>
+ {
+ 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<key_thread>
+ {
+ typedef size_t result_type;
+ typedef key_thread argument_type;
+
+ size_t operator()( key_thread const& k ) const
+ {
+ return std::hash<size_t>()(k.nKey);
+ }
+ size_t operator()( size_t k ) const
+ {
+ return std::hash<size_t>()(k);
+ }
+ };
+
+ class 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<size_t> m_arrElements;
+
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+
+ template <typename Pred>
+ static void prepare_array( std::vector<size_t>& 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<key_type const, value_type> pair_type;
+
+ atomics::atomic<size_t> m_nInsThreadCount;
+
+ enum {
+ inserter_thread,
+ deleter_thread,
+ extractor_thread,
+ find_thread,
+ };
+
+ // Inserts keys from [0..N)
+ template <class Map>
+ class Inserter: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Map& m_Map;
+
+ struct update_func
+ {
+ template <typename Q>
+ void operator()( bool /*bNew*/, Q const& ) const
+ {}
+
+ template <typename Q, typename V>
+ void operator()( bool /*bNew*/, Q const&, V& ) const
+ {}
+
+ // FeldmanHashMap
+ template <typename Q>
+ 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<size_t> 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<Map_Iter_Del3>();
+
+ 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 Map, typename Iterator>
+ 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<size_t> 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<Map_Iter_Del3>();
+
+ do {
+ auto itEnd = rMap.template get_end<Iterator>();
+ for ( auto it = rMap.template get_begin<Iterator>(); 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 GC, class Map >
+ 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<size_t> 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<Map_Iter_Del3>();
+ size_t const nInsThreadCount = s_nInsThreadCount;
+
+ do {
+ if ( id() & 1 ) {
+ for ( auto el : m_arr ) {
+ for ( size_t k = 0; k < nInsThreadCount; ++k ) {
+ gp = 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 RCU, class Map >
+ class Extractor< cds::urcu::gc<RCU>, 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<size_t> 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<Map_Iter_Del3>();
+
+ 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 Map>
+ 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<Map_Iter_Del3>();
+ std::vector<size_t> 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 <typename Iterator, class Map>
+ void do_test( Map& testMap )
+ {
+ typedef Inserter<Map> insert_thread;
+ typedef Deleter<Map, Iterator> delete_thread;
+ typedef Observer<Map> 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<insert_thread&>( thr );
+ nInsertSuccess += inserter.m_nInsertSuccess;
+ nInsertFailed += inserter.m_nInsertFailed;
+ nInsertInitSuccess += inserter.m_nInsertInitSuccess;
+ nInsertInitFailed += inserter.m_nInsertInitFailed;
+ }
+ break;
+ case deleter_thread:
+ {
+ delete_thread& deleter = static_cast<delete_thread&>( thr );
+ nDeleteSuccess += deleter.m_nDeleteSuccess;
+ nDeleteFailed += deleter.m_nDeleteFailed;
+ }
+ break;
+ case find_thread:
+ {
+ observer_thread& observer = static_cast<observer_thread&>( thr );
+ nFindEvenSuccess = observer.m_nFindEvenSuccess;
+ nFindEvenFailed = observer.m_nFindEvenFailed;
+ nFindOddSuccess = observer.m_nFindOddSuccess;
+ nFindOddFailed = observer.m_nFindOddFailed;
+ }
+ break;
+ }
+ }
+
+ 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 <typename Iterator, class Map>
+ void do_test_extract( Map& testMap )
+ {
+ typedef Inserter<Map> insert_thread;
+ typedef Deleter<Map, Iterator> delete_thread;
+ typedef Extractor< typename Map::gc, Map > extract_thread;
+ typedef Observer<Map> 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<insert_thread&>(thr);
+ nInsertSuccess += inserter.m_nInsertSuccess;
+ nInsertFailed += inserter.m_nInsertFailed;
+ nInsertInitSuccess += inserter.m_nInsertInitSuccess;
+ nInsertInitFailed += inserter.m_nInsertInitFailed;
+ }
+ break;
+ case deleter_thread:
+ {
+ delete_thread& deleter = static_cast<delete_thread&>(thr);
+ nDeleteSuccess += deleter.m_nDeleteSuccess;
+ nDeleteFailed += deleter.m_nDeleteFailed;
+ }
+ break;
+ case extractor_thread:
+ {
+ extract_thread& extractor = static_cast<extract_thread&>(thr);
+ nExtractSuccess += extractor.m_nDeleteSuccess;
+ nExtractFailed += extractor.m_nDeleteFailed;
+ }
+ break;
+ case find_thread:
+ {
+ observer_thread& observer = static_cast<observer_thread&>( thr );
+ nFindEvenSuccess = observer.m_nFindEvenSuccess;
+ nFindEvenFailed = observer.m_nFindEvenFailed;
+ nFindOddSuccess = observer.m_nFindOddSuccess;
+ nFindOddFailed = observer.m_nFindOddFailed;
+ }
+ break;
+ default:
+ assert( false );
+ }
+ }
+
+ size_t const nInitialOddKeys = ( s_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 <class Map>
+ 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 <class Map, typename Iterator=typename Map::iterator>
+ 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<Iterator>( testMap );
+ }
+
+ template <class Map, typename Iterator=typename Map::iterator>
+ void run_test()
+ {
+ size_t nMapSize = s_nMapSize;
+ s_nMapSize *= s_nInsThreadCount;
+
+ Map testMap( *this );
+
+ s_nMapSize = nMapSize;
+ do_test<Iterator>( testMap );
+ }
+
+ template <class Map>
+ void run_feldman();
+ };
+
+ class Map_Iter_Del3_reverse: public Map_Iter_Del3
+ {
+ public:
+ template <class Map>
+ void run_feldman();
+ };
+
+
+ class Map_Iter_Del3_LF: public Map_Iter_Del3
+ , public ::testing::WithParamInterface<size_t>
+ {
+ public:
+ template <class Map>
+ void run_test()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Map_Iter_Del3::run_test<Map>();
+ }
+
+ template <class Map>
+ void run_test_extract()
+ {
+ s_nLoadFactor = GetParam();
+ propout() << std::make_pair( "load_factor", s_nLoadFactor );
+ Map_Iter_Del3::run_test_extract<Map>();
+ }
+
+ static std::vector<size_t> get_load_factors();
+ };
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_iter_erase.h"
+#include "map_type_feldman_hashmap.h"
+
+namespace map {
+
+ template <class Map>
+ 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<map_type>();
+ }
+
+ template <class Map>
+ 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<map_type, typename map_type::reverse_iterator>();
+ }
+
+ 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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CDSUNIT_MAP_TYPE_H
+#define CDSUNIT_MAP_TYPE_H
+
+#include <cds/urcu/general_instant.h>
+#include <cds/urcu/general_buffered.h>
+#include <cds/urcu/general_threaded.h>
+#include <cds/urcu/signal_buffered.h>
+
+#include <cds/sync/spinlock.h>
+#include <cds/opt/hash.h>
+#include <boost/functional/hash/hash.hpp>
+
+#include <cds_test/stress_test.h>
+#include <cds_test/check_size.h>
+
+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 <typename Key>
+ struct less;
+
+ template <typename Key>
+ struct cmp {
+ int operator ()(Key const& k1, Key const& k2) const
+ {
+ if ( less<Key>( k1, k2 ))
+ return -1;
+ return less<Key>( k2, k1 ) ? 1 : 0;
+ }
+ };
+
+ template <typename Key>
+ struct hash;
+
+#define CDSUNIT_INT_COMPARE(t) template <> struct cmp<t> { int operator()( t k1, t k2 ) 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<t> { 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<std::string>
+ {
+ int operator()(std::string const& s1, std::string const& s2)
+ {
+ return s1.compare( s2 );
+ }
+ int operator()(std::string const& s1, char const * s2)
+ {
+ return s1.compare( s2 );
+ }
+ int operator()(char const * s1, std::string const& s2)
+ {
+ return -s2.compare( s1 );
+ }
+ };
+
+ template <>
+ struct less<std::string>
+ {
+ bool operator ()( std::string const& k1, std::string const& k2 ) const
+ {
+ return cmp<std::string>()(k1, k2) < 0;
+ }
+ bool operator ()( std::string const& k1, char const* k2 ) const
+ {
+ return cmp<std::string>()(k1, k2) < 0;
+ }
+ bool operator ()( char const* k1, std::string const& k2 ) const
+ {
+ return cmp<std::string>()(k1, k2) < 0;
+ }
+ };
+
+ template <typename T>
+ struct hash
+ {
+ typedef size_t result_type;
+ typedef T argument_type;
+
+ size_t operator()( T const& k ) const
+ {
+ return std::hash<size_t>()(k.nKey);
+ }
+
+ size_t operator()( size_t k ) const
+ {
+ return std::hash<size_t>()(k);
+ }
+ };
+
+ template <>
+ struct hash<size_t>
+ {
+ typedef size_t result_type;
+ typedef size_t argument_type;
+
+ size_t operator()( size_t k ) const
+ {
+ return std::hash<size_t>()(k);
+ }
+ };
+
+ template <>
+ struct hash<std::string>
+ {
+ typedef size_t result_type;
+ typedef std::string argument_type;
+
+ size_t operator()( std::string const& k ) const
+ {
+ return std::hash<std::string>()(k);
+ }
+ };
+
+ // forward
+ template <typename ImplSelector, typename Key, typename Value>
+ struct map_type;
+
+ template <typename Key, typename Value>
+ struct map_type_base
+ {
+ typedef map::hash<Key> key_hash;
+ typedef map::less<Key> key_less;
+ typedef cmp<Key> 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 <typename Q>
+ 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 <typename Map>
+ static inline void print_stat( cds_test::property_stream& o, Map const& m )
+ {
+ o << m.statistics();
+ }
+
+
+ template <typename Map>
+ static inline void check_before_cleanup( Map& /*m*/ )
+ {}
+
+ template <typename Map>
+ static inline void additional_cleanup( Map& /*m*/ )
+ {}
+
+ template <typename Map>
+ static inline void additional_check( Map& /*m*/ )
+ {}
+
+} // namespace map
+
+#endif // ifndef CDSUNIT_MAP_TYPE_H
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CDSUNIT_MAP_TYPE_BRONSON_AVLTREE_H
+#define CDSUNIT_MAP_TYPE_BRONSON_AVLTREE_H
+
+#include "map_type.h"
+
+#include <cds/memory/vyukov_queue_pool.h>
+#include <cds/sync/pool_monitor.h>
+#include <cds/container/bronson_avltree_map_rcu.h>
+
+#include <cds_test/stat_bronson_avltree_out.h>
+#include <cds_test/stat_sync_monitor_out.h>
+
+namespace map {
+
+ template <class GC, typename Key, typename T, typename Traits = cc::bronson_avltree::traits >
+ class BronsonAVLTreeMap : public cc::BronsonAVLTreeMap< GC, Key, T, Traits >
+ {
+ typedef cc::BronsonAVLTreeMap< GC, Key, T, Traits > base_class;
+ public:
+ template <typename Config>
+ BronsonAVLTreeMap( Config const& /*cfg*/ )
+ : base_class()
+ {}
+
+ std::pair<Key, bool> 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<Key, bool> 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 <typename Key, typename Value>
+ 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<BronsonAVLTreeMap_simple_pool> 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<BronsonAVLTreeMap_simple_pool, cds::opt::none, true > 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<BronsonAVLTreeMap_lazy_pool> 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<BronsonAVLTreeMap_lazy_pool, cds::opt::none, true > 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<BronsonAVLTreeMap_bounded_pool> 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<BronsonAVLTreeMap_bounded_pool, cds::opt::none, true > 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 <typename GC, typename Key, typename T, typename Traits>
+ static inline void print_stat( cds_test::property_stream& o, BronsonAVLTreeMap<GC, Key, T, Traits> const& m )
+ {
+ o << m.statistics()
+ << m.monitor().statistics();
+ }
+
+ template <typename GC, typename Key, typename T, typename Traits>
+ static inline void check_before_cleanup( BronsonAVLTreeMap<GC, Key, T, Traits>& 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<map_type>(); \
+ }
+
+#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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CDSUNIT_MAP_TYPE_CUCKOO_H
+#define CDSUNIT_MAP_TYPE_CUCKOO_H
+
+#include "map_type.h"
+#include <cds/container/cuckoo_map.h>
+#include <cds_test/stat_cuckoo_out.h>
+#include <cds_test/hash_func.h>
+
+namespace map {
+
+ template <typename K, typename V, typename Traits>
+ class CuckooMap: public cc::CuckooMap< K, V, Traits >
+ {
+ public:
+ typedef cc::CuckooMap< K, V, Traits > base_class;
+
+ public:
+ template <typename Config>
+ CuckooMap( Config const& cfg )
+ : base_class(
+ cfg.s_nCuckooInitialSize,
+ static_cast<unsigned int>( cfg.s_nCuckooProbesetSize ),
+ static_cast<unsigned int>( cfg.s_nCuckooProbesetThreshold )
+ )
+ {}
+
+ template <typename Q, typename Pred>
+ bool erase_with( Q const& key, Pred /*pred*/ )
+ {
+ return 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 <typename Key, typename Value>
+ 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 <typename Traits>
+ struct traits_CuckooStripedMap: public Traits
+ {
+ typedef cc::cuckoo::striping<> mutex_policy;
+ };
+ template <typename Traits>
+ 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<traits_CuckooMap_list_unord>> CuckooStripedMap_list_unord;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_list_unord>> 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<traits_CuckooMap_list_unord_stat>> CuckooStripedMap_list_unord_stat;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_list_unord_stat>> 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<traits_CuckooMap_list_unord_storehash>> CuckooStripedMap_list_unord_storehash;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_list_unord_storehash>> 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<traits_CuckooMap_list_ord>> CuckooStripedMap_list_ord;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_list_ord>> 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<traits_CuckooMap_list_ord_stat>> CuckooStripedMap_list_ord_stat;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_list_ord_stat>> 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<traits_CuckooMap_list_ord_storehash>> CuckooStripedMap_list_ord_storehash;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_list_ord_storehash>> 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<traits_CuckooMap_vector_unord>> CuckooStripedMap_vector_unord;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_vector_unord>> 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<traits_CuckooMap_vector_unord_stat>> CuckooStripedMap_vector_unord_stat;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_vector_unord_stat>> 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<traits_CuckooMap_vector_unord_storehash>> CuckooStripedMap_vector_unord_storehash;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_vector_unord_storehash>> 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<traits_CuckooMap_vector_ord>> CuckooStripedMap_vector_ord;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_vector_ord>> 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<traits_CuckooMap_vector_ord_stat>> CuckooStripedMap_vector_ord_stat;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_vector_ord_stat>> 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<traits_CuckooMap_vector_ord_storehash>> CuckooStripedMap_vector_ord_storehash;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_vector_ord_storehash>> 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<traits_CuckooMap_list_unord_city64>> CuckooStripedMap_list_unord_city64;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_list_unord_city64>> 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<traits_CuckooMap_list_unord_city64_stat>> CuckooStripedMap_list_unord_city64_stat;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_list_unord_city64_stat>> 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<traits_CuckooMap_list_unord_city64_storehash>> CuckooStripedMap_list_unord_city64_storehash;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_list_unord_city64_storehash>> 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<traits_CuckooMap_list_ord_city64>> CuckooStripedMap_list_ord_city64;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_list_ord_city64>> 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<traits_CuckooMap_list_ord_city64_stat>> CuckooStripedMap_list_ord_city64_stat;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_list_ord_city64_stat>> 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<traits_CuckooMap_list_ord_city64_storehash>> CuckooStripedMap_list_ord_city64_storehash;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_list_ord_city64_storehash>> 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<traits_CuckooMap_vector_unord_city64>> CuckooStripedMap_vector_unord_city64;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_vector_unord_city64>> 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<traits_CuckooMap_vector_unord_city64_stat>> CuckooStripedMap_vector_unord_city64_stat;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_vector_unord_city64_stat>> 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<traits_CuckooMap_vector_unord_city64_storehash>> CuckooStripedMap_vector_unord_city64_storehash;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_vector_unord_city64_storehash>> 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<traits_CuckooMap_vector_ord_city64>> CuckooStripedMap_vector_ord_city64;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_vector_ord_city64>> 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<traits_CuckooMap_vector_ord_city64_stat>> CuckooStripedMap_vector_ord_city64_stat;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_vector_ord_city64_stat>> 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<traits_CuckooMap_vector_ord_city64_storehash>> CuckooStripedMap_vector_ord_city64_storehash;
+ typedef CuckooMap< Key, Value, traits_CuckooRefinableMap<traits_CuckooMap_vector_ord_city64_storehash>> CuckooRefinableMap_vector_ord_city64_storehash;
+#endif // CDS_BUILD_BITS == 64
+ };
+
+ template <typename Key, typename T, typename Traits >
+ 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 <typename Key, typename V, typename Traits>
+ 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<typename map_type::base_class const&>(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<map_type>(); \
+ }
+
+#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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CDSUNIT_MAP_TYPE_ELLEN_BINTREE_H
+#define CDSUNIT_MAP_TYPE_ELLEN_BINTREE_H
+
+#include "map_type.h"
+
+#include <cds/container/ellen_bintree_map_rcu.h>
+#include <cds/container/ellen_bintree_map_hp.h>
+#include <cds/container/ellen_bintree_map_dhp.h>
+
+#include <cds_test/stat_ellenbintree_out.h>
+#include "framework/ellen_bintree_update_desc_pool.h"
+
+namespace map {
+
+ template <class GC, typename Key, typename T, typename Traits = cc::ellen_bintree::traits >
+ class EllenBinTreeMap : public cc::EllenBinTreeMap< GC, Key, T, Traits >
+ {
+ typedef cc::EllenBinTreeMap< GC, Key, T, Traits > base_class;
+ public:
+ template <typename Config>
+ EllenBinTreeMap( Config const& /*cfg*/)
+ : base_class()
+ {}
+
+ std::pair<Key, bool> 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<Key, bool> 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 <typename Key, typename Value>
+ 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<cds::gc::HP, Key, Value> 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<cds::gc::DHP, Key, Value> 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<rcu_gpi, Key, Value> 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<rcu_gpb, Key, Value> 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<rcu_gpt, Key, Value> 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<rcu_shb, Key, Value> 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 <typename GC, typename Key, typename T, typename Traits>
+ static inline void print_stat( cds_test::property_stream& o, EllenBinTreeMap<GC, Key, T, Traits> const& s )
+ {
+ o << s.statistics();
+ }
+ template <typename GC, typename Key, typename T, typename Traits>
+ static inline void additional_cleanup( EllenBinTreeMap<GC, Key, T, Traits>& /*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 <typename GC, typename Key, typename T, typename Traits>
+ static inline void additional_check( EllenBinTreeMap<GC, Key, T, Traits>& m )
+ {
+ GC::force_dispose();
+ ellen_bintree_check::check_stat( m.statistics());
+ }
+
+ template <typename GC, typename Key, typename T, typename Traits>
+ static inline void check_before_cleanup( EllenBinTreeMap<GC, Key, T, Traits>& 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<map_type>(); \
+ }
+
+#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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CDSUNIT_MAP_TYPE_FELDMAN_HASHMAP_H
+#define CDSUNIT_MAP_TYPE_FELDMAN_HASHMAP_H
+
+#include "map_type.h"
+
+#include <cds/container/feldman_hashmap_hp.h>
+#include <cds/container/feldman_hashmap_dhp.h>
+#include <cds/container/feldman_hashmap_rcu.h>
+
+#include <cds_test/stat_feldman_hashset_out.h>
+#include <cds_test/hash_func.h>
+
+namespace map {
+
+ template <class GC, typename Key, typename T, typename Traits = cc::feldman_hashmap::traits>
+ class FeldmanHashMap : public cc::FeldmanHashMap< GC, Key, T, Traits >
+ {
+ typedef cc::FeldmanHashMap< GC, Key, T, Traits > base_class;
+ public:
+
+ template <typename OtherTraits>
+ struct rebind_traits {
+ typedef FeldmanHashMap<GC, Key, T, OtherTraits > result;
+ };
+
+ template <typename Config>
+ FeldmanHashMap( Config const& cfg)
+ : base_class( cfg.s_nFeldmanMap_HeadBits, cfg.s_nFeldmanMap_ArrayBits )
+ {}
+
+ template <typename Iterator>
+ typename std::enable_if< std::is_same< Iterator, typename base_class::iterator>::value, Iterator>::type
+ get_begin()
+ {
+ return base_class::begin();
+ }
+
+ template <typename Iterator>
+ typename std::enable_if< std::is_same< Iterator, typename base_class::iterator>::value, Iterator>::type
+ get_end()
+ {
+ return base_class::end();
+ }
+
+ template <typename Iterator>
+ typename std::enable_if< std::is_same< Iterator, typename base_class::reverse_iterator>::value, Iterator>::type
+ get_begin()
+ {
+ return base_class::rbegin();
+ }
+
+ template <typename Iterator>
+ typename std::enable_if< std::is_same< Iterator, typename base_class::reverse_iterator>::value, Iterator>::type
+ get_end()
+ {
+ return base_class::rend();
+ }
+
+ // for testing
+ static CDS_CONSTEXPR bool const c_bExtractSupported = true;
+ static CDS_CONSTEXPR bool const c_bLoadFactorDepended = false;
+ static CDS_CONSTEXPR bool const c_bEraseExactKey = true;
+ };
+
+ struct tag_FeldmanHashMap;
+
+ template <typename Key, typename Value>
+ 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<size_t> 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<size_t> 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<Key> 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 <typename GC, typename K, typename T, typename Traits >
+ 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<map_type>(); \
+ }
+
+
+#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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CDSUNIT_MAP_TYPE_ITERABLE_LIST_H
+#define CDSUNIT_MAP_TYPE_ITERABLE_LIST_H
+
+#include "map_type.h"
+
+#include <cds/container/iterable_kvlist_hp.h>
+#include <cds/container/iterable_kvlist_dhp.h>
+
+#include <cds_test/stat_iterable_list_out.h>
+
+namespace map {
+
+ template <typename Key, typename Value>
+ struct iterable_list_type
+ {
+ typedef typename map_type_base<Key, Value>::key_compare compare;
+ typedef typename map_type_base<Key, Value>::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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CDSUNIT_MAP_TYPE_LAZY_LIST_H
+#define CDSUNIT_MAP_TYPE_LAZY_LIST_H
+
+#include "map_type.h"
+
+#include <cds/container/lazy_kvlist_hp.h>
+#include <cds/container/lazy_kvlist_dhp.h>
+#include <cds/container/lazy_kvlist_rcu.h>
+#include <cds/container/lazy_kvlist_nogc.h>
+
+#include <cds_test/stat_lazy_list_out.h>
+
+namespace map {
+
+ template <typename Key, typename Value>
+ struct lazy_list_type
+ {
+ typedef typename map_type_base<Key, Value>::key_compare compare;
+ typedef typename map_type_base<Key, Value>::key_less less;
+ typedef typename map_type_base<Key, Value>::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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CDSUNIT_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 <cds/container/michael_map.h>
+#include <cds/container/michael_map_rcu.h>
+#include <cds/container/michael_map_nogc.h>
+
+namespace map {
+
+ template <class GC, typename List, typename Traits = cc::michael_map::traits>
+ class MichaelHashMap : public cc::MichaelHashMap< GC, List, Traits >
+ {
+ typedef cc::MichaelHashMap< GC, List, Traits > base_class;
+ public:
+ template <typename Config>
+ MichaelHashMap( Config const& cfg)
+ : base_class( cfg.s_nMapSize, cfg.s_nLoadFactor )
+ {}
+
+ template <typename Iterator>
+ typename std::enable_if< std::is_same< Iterator, typename base_class::iterator>::value, Iterator>::type
+ get_begin()
+ {
+ return base_class::begin();
+ }
+
+ template <typename Iterator>
+ typename std::enable_if< std::is_same< Iterator, typename base_class::iterator>::value, Iterator>::type
+ get_end()
+ {
+ return base_class::end();
+ }
+
+ // for testing
+ static CDS_CONSTEXPR bool const c_bExtractSupported = true;
+ static CDS_CONSTEXPR bool const c_bLoadFactorDepended = true;
+ static CDS_CONSTEXPR bool const c_bEraseExactKey = false;
+ };
+
+ struct tag_MichaelHashMap;
+
+ template <typename Key, typename Value>
+ 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<map_type>(); \
+ }
+
+#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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CDSUNIT_MAP_TYPE_MICHAEL_LIST_H
+#define CDSUNIT_MAP_TYPE_MICHAEL_LIST_H
+
+#include "map_type.h"
+
+#include <cds/container/michael_kvlist_hp.h>
+#include <cds/container/michael_kvlist_dhp.h>
+#include <cds/container/michael_kvlist_rcu.h>
+#include <cds/container/michael_kvlist_nogc.h>
+
+#include <cds_test/stat_michael_list_out.h>
+
+namespace map {
+
+ template <typename Key, typename Value>
+ struct michael_list_type
+ {
+ typedef typename map_type_base<Key, Value>::key_compare compare;
+ typedef typename map_type_base<Key, Value>::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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CDSUNIT_MAP_TYPE_SKIP_LIST_H
+#define CDSUNIT_MAP_TYPE_SKIP_LIST_H
+
+#include "map_type.h"
+
+#include <cds/container/skip_list_map_hp.h>
+#include <cds/container/skip_list_map_dhp.h>
+#include <cds/container/skip_list_map_rcu.h>
+#include <cds/container/skip_list_map_nogc.h>
+
+#include <cds_test/stat_skiplist_out.h>
+
+namespace map {
+
+ template <class GC, typename Key, typename T, typename Traits = cc::skip_list::traits >
+ class SkipListMap : public cc::SkipListMap< GC, Key, T, Traits >
+ {
+ typedef cc::SkipListMap< GC, Key, T, Traits > base_class;
+ public:
+ template <typename Config>
+ SkipListMap( Config const& /*cfg*/)
+ : base_class()
+ {}
+
+ std::pair<Key, bool> 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<Key, bool> 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 <typename Key, typename Value>
+ 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 <typename GC, typename K, typename T, typename Traits >
+ 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<map_type>(); \
+ }
+
+#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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CDSUNIT_MAP_TYPE_SPLIT_LIST_H
+#define CDSUNIT_MAP_TYPE_SPLIT_LIST_H
+
+#include "map_type.h"
+
+#include <cds/container/michael_kvlist_hp.h>
+#include <cds/container/michael_kvlist_dhp.h>
+#include <cds/container/michael_kvlist_rcu.h>
+#include <cds/container/michael_kvlist_nogc.h>
+
+#include <cds/container/lazy_kvlist_hp.h>
+#include <cds/container/lazy_kvlist_dhp.h>
+#include <cds/container/lazy_kvlist_rcu.h>
+#include <cds/container/lazy_kvlist_nogc.h>
+
+#include <cds/container/iterable_kvlist_hp.h>
+#include <cds/container/iterable_kvlist_dhp.h>
+
+#include <cds/container/split_list_map.h>
+#include <cds/container/split_list_map_rcu.h>
+#include <cds/container/split_list_map_nogc.h>
+
+#include <cds_test/stat_splitlist_out.h>
+#include <cds_test/stat_michael_list_out.h>
+#include <cds_test/stat_lazy_list_out.h>
+#include <cds_test/stat_iterable_list_out.h>
+
+namespace map {
+
+ template <class GC, typename Key, typename T, typename Traits = cc::split_list::traits >
+ class SplitListMap : public cc::SplitListMap< GC, Key, T, Traits >
+ {
+ typedef cc::SplitListMap< GC, Key, T, Traits > base_class;
+ public:
+ template <typename Config>
+ SplitListMap( Config const& cfg)
+ : base_class( cfg.s_nMapSize, cfg.s_nLoadFactor )
+ {}
+
+ template <typename Iterator>
+ typename std::enable_if< std::is_same< Iterator, typename base_class::iterator>::value, Iterator>::type
+ get_begin()
+ {
+ return base_class::begin();
+ }
+
+ template <typename Iterator>
+ typename std::enable_if< std::is_same< Iterator, typename base_class::iterator>::value, Iterator>::type
+ get_end()
+ {
+ return base_class::end();
+ }
+
+ // for testing
+ static CDS_CONSTEXPR bool const c_bExtractSupported = true;
+ static CDS_CONSTEXPR bool const c_bLoadFactorDepended = true;
+ static CDS_CONSTEXPR bool const c_bEraseExactKey = false;
+ };
+
+ template <typename Key, typename T, typename Traits >
+ 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 <typename Config>
+ SplitListMap( Config const& cfg)
+ : base_class( cfg.s_nMapSize, cfg.s_nLoadFactor )
+ {}
+
+ template <typename K>
+ bool insert( K const& key )
+ {
+ return base_class::insert( key ) != base_class::end();
+ }
+
+ template <typename K, typename V>
+ bool insert( K const& key, V const& val )
+ {
+ return base_class::insert( key, val ) != base_class::end();
+ }
+
+ template <typename K, typename Func>
+ bool insert_with( K const& key, Func func )
+ {
+ return base_class::insert_with( key, func ) != base_class::end();
+ }
+
+ template <typename K>
+ 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 <typename Key, typename Value>
+ 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<cc::michael_list_tag>
+ ,co::hash< hash >
+ ,co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::michael_list::make_traits<
+ co::compare< compare >
+ >::type
+ >
+ >::type
+ {};
+ typedef 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<cc::michael_list_tag>
+ ,co::hash< hash >
+ , co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ ,co::memory_model< co::v::sequential_consistent >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::michael_list::make_traits<
+ co::compare< compare >
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ >
+ >::type
+ {};
+ typedef 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::michael_list_tag>
+ ,cc::split_list::dynamic_bucket_table< false >
+ ,co::hash< hash >
+ , co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::michael_list::make_traits<
+ co::compare< compare >
+ >::type
+ >
+ >::type
+ {};
+ typedef 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<cc::michael_list_tag>
+ ,co::hash< hash >
+ , co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::michael_list::make_traits<
+ co::less< less >
+ >::type
+ >
+ >::type
+ {};
+ typedef 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::michael_list_tag>
+ ,cc::split_list::dynamic_bucket_table< false >
+ ,co::hash< hash >
+ , co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::michael_list::make_traits<
+ co::less< less >
+ >::type
+ >
+ >::type
+ {};
+ typedef 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<cc::lazy_list_tag>
+ ,co::hash< hash >
+ , co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::lazy_list::make_traits<
+ co::compare< compare >
+ >::type
+ >
+ >::type
+ {};
+ typedef 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<cc::lazy_list_tag>
+ ,co::hash< hash >
+ , co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ ,co::memory_model< co::v::sequential_consistent >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::lazy_list::make_traits<
+ co::compare< compare >
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ >
+ >::type
+ {};
+ typedef 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::lazy_list_tag>
+ ,cc::split_list::dynamic_bucket_table< false >
+ ,co::hash< hash >
+ , co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::lazy_list::make_traits<
+ co::compare< compare >
+ >::type
+ >
+ >::type
+ {};
+ typedef 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<cc::lazy_list_tag>
+ ,co::hash< hash >
+ , co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::lazy_list::make_traits<
+ co::less< less >
+ >::type
+ >
+ >::type
+ {};
+ typedef 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::lazy_list_tag>
+ ,cc::split_list::dynamic_bucket_table< false >
+ ,co::hash< hash >
+ , co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::lazy_list::make_traits<
+ co::less< less >
+ >::type
+ >
+ >::type
+ {};
+ typedef 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<cc::iterable_list_tag>
+ ,co::hash< hash >
+ , co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::iterable_list::make_traits<
+ co::compare< compare >
+ >::type
+ >
+ >::type
+ {};
+ typedef 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<cc::iterable_list_tag>
+ ,co::hash< hash >
+ , co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ ,co::memory_model< co::v::sequential_consistent >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::iterable_list::make_traits<
+ co::compare< compare >
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ >
+ >::type
+ {};
+ typedef 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::iterable_list_tag>
+ ,cc::split_list::dynamic_bucket_table< false >
+ ,co::hash< hash >
+ , co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::iterable_list::make_traits<
+ co::compare< compare >
+ >::type
+ >
+ >::type
+ {};
+ typedef 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<cc::iterable_list_tag>
+ ,co::hash< hash >
+ , co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::iterable_list::make_traits<
+ co::less< less >
+ >::type
+ >
+ >::type
+ {};
+ typedef 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::iterable_list_tag>
+ ,cc::split_list::dynamic_bucket_table< false >
+ ,co::hash< hash >
+ , co::item_counter< cds::atomicity::cache_friendly_item_counter >
+ ,cc::split_list::ordered_list_traits<
+ typename cc::iterable_list::make_traits<
+ co::less< less >
+ >::type
+ >
+ >::type
+ {};
+ typedef 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 <typename GC, typename K, typename T, typename Traits >
+ 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<map_type>(); \
+ }
+
+#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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CDSUNIT_MAP_TYPE_STD_H
+#define CDSUNIT_MAP_TYPE_STD_H
+
+#include "map_type.h"
+
+#include <map>
+#include <unordered_map>
+
+namespace map {
+
+ struct empty_lock
+ {
+ void lock() {}
+ void unlock() {}
+ };
+
+ template <typename Key, typename Value, typename Lock,
+ class Alloc = typename CDS_DEFAULT_ALLOCATOR::template rebind<std::pair<Key const, Value> >::other
+ >
+ class StdMap: public std::map<Key, Value, std::less<Key>, Alloc>
+ {
+ Lock m_lock;
+ typedef std::unique_lock<Lock> scoped_lock;
+ typedef std::map<Key, Value, std::less<Key>, 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 <class Config>
+ 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 <typename T, typename Func>
+ bool insert( const Key& key, const T& val, Func func )
+ {
+ scoped_lock al( m_lock );
+ std::pair<typename base_class::iterator, bool> pRet = base_class::insert( typename base_class::value_type( key, Value()));
+ if ( pRet.second ) {
+ func( pRet.first->second, val );
+ return true;
+ }
+ return false;
+ }
+
+ template <typename T, typename Func>
+ std::pair<bool, bool> update( const T& key, Func func, bool /*bAllowInsert*/ = true )
+ {
+ scoped_lock al( m_lock );
+ std::pair<typename base_class::iterator, bool> 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 <typename T, typename Func>
+ 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 <typename Key, typename Value, typename Lock,
+ class Alloc = typename CDS_DEFAULT_ALLOCATOR::template rebind<std::pair<Key const, Value> >::other
+ >
+ class StdHashMap
+ : public std::unordered_map<
+ Key, Value
+ , std::hash<Key>
+ , std::equal_to<Key>
+ , Alloc
+ >
+ {
+ public:
+ Lock m_lock;
+ typedef std::unique_lock<Lock> scoped_lock;
+ typedef std::unordered_map<
+ Key, Value
+ , std::hash<Key>
+ , std::equal_to<Key>
+ , Alloc
+ > base_class;
+ public:
+ typedef typename base_class::mapped_type value_type;
+ typedef size_t item_counter;
+
+ StdHashMap()
+ {}
+
+ template <class Config>
+ 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 <typename T, typename Func>
+ bool insert( const Key& key, const T& val, Func func )
+ {
+ scoped_lock al( m_lock );
+ std::pair<typename base_class::iterator, bool> pRet = base_class::insert( typename base_class::value_type(key, Value()));
+ if ( pRet.second ) {
+ func( pRet.first->second, val );
+ return true;
+ }
+ return false;
+ }
+
+ template <typename T, typename Func>
+ std::pair<bool, bool> update( const T& key, Func func, bool /*bAllowInsert*/ = true )
+ {
+ scoped_lock al( m_lock );
+ std::pair<typename base_class::iterator, bool> 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 <typename T, typename Func>
+ 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 <typename Key, typename Value>
+ 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<map_type>(); \
+ }
+
+#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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CDSUNIT_MAP_TYPE_STRIPED_H
+#define CDSUNIT_MAP_TYPE_STRIPED_H
+
+#include "map_type.h"
+#include <cds/container/striped_map/std_list.h>
+#include <cds/container/striped_map/std_map.h>
+#include <cds/container/striped_map/std_hash_map.h>
+
+#include <boost/version.hpp>
+#if BOOST_VERSION >= 104800
+# include <cds/container/striped_map/boost_list.h>
+# include <cds/container/striped_map/boost_slist.h>
+# include <cds/container/striped_map/boost_map.h>
+# include <cds/container/striped_map/boost_flat_map.h>
+#endif
+#include <cds/container/striped_map/boost_unordered_map.h>
+#include <cds/container/striped_map.h>
+
+namespace map {
+
+ struct tag_StripedMap;
+
+ template <typename Key, typename Value>
+ 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 BucketEntry, typename... Options>
+ class StripedHashMap_seq:
+ public cc::StripedMap< BucketEntry,
+ co::mutex_policy< cc::striped_set::striping<> >
+ ,co::resizing_policy<cc::striped_set::load_factor_resizing<0> >
+ , Options...
+ >
+ {
+ typedef cc::StripedMap< BucketEntry,
+ co::mutex_policy< cc::striped_set::striping<> >
+ ,co::resizing_policy<cc::striped_set::load_factor_resizing<0> >
+ , Options...
+ > base_class;
+ typedef typename base_class::resizing_policy resizing_policy_t;
+
+ resizing_policy_t m_placeHolder;
+ public:
+ template <class Config>
+ 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 BucketEntry, typename... Options>
+ class StripedHashMap_ord:
+ public cc::StripedMap< BucketEntry,
+ co::resizing_policy<cc::striped_set::load_factor_resizing<0> >
+ ,co::mutex_policy< cc::striped_set::striping<> >
+ , Options...
+ >
+ {
+ typedef cc::StripedMap< BucketEntry,
+ co::resizing_policy<cc::striped_set::load_factor_resizing<0> >
+ ,co::mutex_policy< cc::striped_set::striping<> >
+ , Options...
+ > base_class;
+ typedef typename base_class::resizing_policy resizing_policy_t;
+
+ resizing_policy_t m_placeHolder;
+ public:
+ template <class Config>
+ 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 BucketEntry, typename... Options>
+ class RefinableHashMap_seq:
+ public cc::StripedMap< BucketEntry,
+ co::resizing_policy<cc::striped_set::load_factor_resizing<0> >
+ ,co::mutex_policy< cc::striped_set::refinable<> >
+ , Options...
+ >
+ {
+ typedef cc::StripedMap< BucketEntry,
+ co::resizing_policy<cc::striped_set::load_factor_resizing<0> >
+ ,co::mutex_policy< cc::striped_set::refinable<> >
+ , Options...
+ > base_class;
+ typedef typename base_class::resizing_policy resizing_policy_t;
+
+ resizing_policy_t m_placeHolder;
+ public:
+ template <class Config>
+ 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 BucketEntry, typename... Options>
+ class RefinableHashMap_ord:
+ public cc::StripedMap< BucketEntry,
+ co::resizing_policy<cc::striped_set::load_factor_resizing<0> >
+ ,co::mutex_policy< cc::striped_set::refinable<> >
+ , Options...
+ >
+ {
+ typedef cc::StripedMap< BucketEntry,
+ co::resizing_policy<cc::striped_set::load_factor_resizing<0> >
+ ,co::mutex_policy< cc::striped_set::refinable<> >
+ , Options...
+ > base_class;
+ typedef typename base_class::resizing_policy resizing_policy_t;
+
+ resizing_policy_t m_placeHolder;
+ public:
+ template <class Config>
+ 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<map_type>(); \
+ }
+
+#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
--- /dev/null
+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})
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_type.h"
+#include <cds/os/topology.h>
+
+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<key_type const, value_type> pair_type;
+
+ atomics::atomic<size_t> m_nInsThreadCount;
+ key_type m_KeyMin;
+ key_type m_KeyMax;
+
+ enum {
+ inserter_thread,
+ extractor_thread,
+ };
+
+ template <class Map>
+ class Inserter: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ Map& m_Map;
+ std::vector<key_type> m_arr;
+
+ void init_data()
+ {
+ Map_MinMax& fixture = pool().template fixture<Map_MinMax>();
+ 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<Map_MinMax>();
+
+ 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 GC, class Map >
+ 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<Map_MinMax>();
+
+ 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 RCU, class Map >
+ class Extractor< cds::urcu::gc<RCU>, 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<Map_MinMax>();
+
+ 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 <class Map>
+ void do_test( Map& testMap )
+ {
+ typedef Inserter<Map> insert_thread;
+ typedef Extractor< typename Map::gc, Map > extract_thread;
+
+ m_nInsThreadCount.store( s_nInsThreadCount, atomics::memory_order_release );
+
+ {
+ std::vector<key_type> arr;
+ arr.resize( s_nMapSize );
+ for ( int i = 0; i < static_cast<int>( 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<int>( 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<insert_thread&>(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<extract_thread&>(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 <class Map>
+ 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 <class Map>
+ void run_test()
+ {
+ static_assert( Map::c_bExtractSupported, "Map class must support extract() method" );
+ Map testMap( *this );
+ do_test( testMap );
+ }
+ };
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_minmax.h"
+#include "map_type_bronson_avltree.h"
+
+namespace map {
+
+ CDSSTRESS_BronsonAVLTreeMap( Map_MinMax, run_test, int, int )
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_minmax.h"
+#include "map_type_ellen_bintree.h"
+
+namespace map {
+
+ CDSSTRESS_EllenBinTreeMap( Map_MinMax, run_test, int, int )
+
+} // namespace map
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "map_minmax.h"
+#include "map_type_skip_list.h"
+
+namespace map {
+
+ CDSSTRESS_SkipListMap( Map_MinMax, run_test, int, int )
+
+} // namespace map
--- /dev/null
+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})
--- /dev/null
+#include "common.h"
+#include <atomic>
+#include <cds/gc/dhp.h>
+#include <cds/gc/hp.h>
+#include <cds/misc/backoff.h>
+#include <cds_test/stress_test.h>
+#include <iostream>
+#include <memory>
+
+namespace cds_others {
+
+size_t BackoffTraits::lower_bound = 16;
+size_t BackoffTraits::upper_bound = 1024;
+
+} // namespace cds_others
--- /dev/null
+#ifndef _CDS_STRESS_TEST_COMMON_H
+#define _CDS_STRESS_TEST_COMMON_H
+
+#include <cds_test/stress_test.h>
+
+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
--- /dev/null
+#include "common.h"
+#include <cds/misc/chase-lev-deque.h>
+#include <cds_test/stress_test.h>
+#include <cstdlib>
+#include <ctime>
+#include <iostream>
+#include <memory>
+#include <thread>
+
+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> 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> 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
--- /dev/null
+/*\r
+ This file is a part of libcds - Concurrent Data Structures library\r
+\r
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017\r
+\r
+ Source code repo: http://github.com/khizmax/libcds/\r
+ Download: http://sourceforge.net/projects/libcds/files/\r
+\r
+ Redistribution and use in source and binary forms, with or without\r
+ modification, are permitted provided that the following conditions are met:\r
+\r
+ * Redistributions of source code must retain the above copyright notice, this\r
+ list of conditions and the following disclaimer.\r
+\r
+ * Redistributions in binary form must reproduce the above copyright notice,\r
+ this list of conditions and the following disclaimer in the documentation\r
+ and/or other materials provided with the distribution.\r
+\r
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\r
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\r
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\r
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+*/\r
+\r
+#include <cds_test/stress_test.h>\r
+\r
+#include <cds/init.h>\r
+#include <cds/gc/hp.h>\r
+#include <cds/gc/dhp.h>\r
+#ifdef CDSUNIT_USE_URCU\r
+# include <cds/urcu/general_instant.h>\r
+# include <cds/urcu/general_buffered.h>\r
+# include <cds/urcu/general_threaded.h>\r
+# include <cds/urcu/signal_buffered.h>\r
+#endif\r
+\r
+#ifdef CDS_ENABLE_HPSTAT\r
+# include <cds_test/stat_hp_out.h>\r
+# include <cds_test/stat_dhp_out.h>\r
+# include <iostream>\r
+#endif\r
+\r
+int main(int argc, char **argv) {\r
+ int result;\r
+ // Read test config file\r
+ cds_test::init_config(argc, argv);\r
+\r
+ std::cout << "Hardware concurrency: " << std::thread::hardware_concurrency()\r
+ << "\n";\r
+\r
+ // Init Google test\r
+ ::testing::InitGoogleTest(&argc, argv);\r
+\r
+ result = RUN_ALL_TESTS();\r
+ return result;\r
+}\r
--- /dev/null
+#include "common.h"
+#include <atomic>
+#include <cds/gc/dhp.h>
+#include <cds/gc/hp.h>
+#include <cds/misc/mcs-lock.h>
+#include <cds_test/stress_test.h>
+#include <iostream>
+#include <memory>
+#include <thread>
+
+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<cds_others::mcs_mutex> 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
--- /dev/null
+#include "common.h"
+#include <cds/misc/RigtorpMPMCQueue.h>
+#include <cds_test/stress_test.h>
+#include <ctime>
+#include <iostream>
+
+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<rigtorp::MPMCQueue<size_t>> q(
+ new rigtorp::MPMCQueue<size_t>(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
--- /dev/null
+#include "common.h"
+#include <cds/misc/RigtorpSPSCQueue.h>
+#include <cds_test/stress_test.h>
+#include <ctime>
+#include <iostream>
+
+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<size_t>* 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<rigtorp::SPSCQueue<size_t>> q(
+ new rigtorp::SPSCQueue<size_t>(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
--- /dev/null
+#include "common.h"
+#include <atomic>
+#include <cds/gc/dhp.h>
+#include <cds/gc/hp.h>
+#include <cds/misc/rwlock.h>
+#include <cds_test/stress_test.h>
+#include <iostream>
+#include <memory>
+#include <thread>
+
+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> rwlock(new RWLock());
+ for (int write_percentage = 5; write_percentage < 40; write_percentage += 5) {
+ ReaderWriterThread(rwlock.get(), write_percentage);
+ }
+}
+
+} // namespace
--- /dev/null
+#include "common.h"
+#include <atomic>
+#include <cds/gc/dhp.h>
+#include <cds/gc/hp.h>
+#include <cds/misc/seqlock.h>
+#include <cds_test/stress_test.h>
+#include <iostream>
+#include <memory>
+#include <thread>
+
+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> seqlock(new SeqLock());
+ for (int write_percentage = 5; write_percentage < 50; write_percentage += 5) {
+ ReaderWriterThread(seqlock.get(), write_percentage);
+ }
+}
+
+} // namespace
--- /dev/null
+#include "common.h"
+#include <atomic>
+#include <cds/gc/dhp.h>
+#include <cds/gc/hp.h>
+#include <cds/sync/spinlock.h>
+#include <cds/misc/ticket_lock.h>
+#include <cds_test/stress_test.h>
+#include <iostream>
+#include <iostream>
+#include <memory>
+#include <thread>
+
+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_type> 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
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cds_test/stress_test.h>
+
+#include <cds/intrusive/free_list.h>
+#include <cds/intrusive/free_list_cached.h>
+#ifdef CDS_DCAS_SUPPORT
+# include <cds/intrusive/free_list_tagged.h>
+#endif
+
+namespace {
+ class put_get: public cds_test::stress_fixture
+ {
+ protected:
+ static size_t s_nThreadCount;
+ static size_t s_nPassCount;
+ static size_t const c_nArraySize = 100;
+
+ template <typename FreeList >
+ struct value_type: public FreeList::node
+ {
+ size_t counter;
+
+ value_type()
+ : counter(0)
+ {}
+ };
+
+ template <class FreeList>
+ class Worker: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ public:
+ FreeList& m_FreeList;
+ size_t m_nSuccess = 0;
+
+ public:
+ Worker( cds_test::thread_pool& pool, FreeList& s )
+ : base_class( pool )
+ , m_FreeList( s )
+ {}
+
+ Worker( Worker& src )
+ : base_class( src )
+ , m_FreeList( src.m_FreeList )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Worker( *this );
+ }
+
+ virtual void test()
+ {
+ typedef value_type<FreeList> item_type;
+ item_type* arr[ c_nArraySize ];
+
+ for ( size_t pass = 0; pass < s_nPassCount; ++pass ) {
+ size_t n = 0;
+ item_type* p;
+
+ while ( (p = static_cast<item_type*>( m_FreeList.get())) != nullptr ) {
+ CDS_TSAN_ANNOTATE_IGNORE_RW_BEGIN;
+ p->counter++;
+ CDS_TSAN_ANNOTATE_IGNORE_RW_END;
+ arr[n] = p;
+ ++m_nSuccess;
+ ++n;
+ }
+
+ for ( size_t i = 0; i < n; ++i )
+ m_FreeList.put( arr[i] );
+ }
+ }
+ };
+
+ public:
+ static void SetUpTestCase()
+ {
+ cds_test::config const& cfg = get_config( "SequentialFreeList" );
+
+ s_nPassCount = cfg.get_size_t( "PassCount", s_nPassCount );
+
+ s_nThreadCount = 1;
+ if ( s_nPassCount == 0 )
+ s_nPassCount = 1000;
+ }
+ //static void TearDownTestCase();
+
+ protected:
+
+ template <typename FreeList>
+ void test( FreeList& list )
+ {
+ cds_test::thread_pool& pool = get_pool();
+
+ value_type<FreeList> arr[c_nArraySize];
+
+ for ( auto& i : arr )
+ list.put( &i );
+
+ std::unique_ptr<Worker<FreeList>> worker(
+ new Worker<FreeList>(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<freelist_type> fl(new freelist_type()); \
+ test(*fl); \
+ }
+
+ CDSSTRESS_FREELIST_F( FreeList, cds::intrusive::FreeList )
+
+ typedef cds::intrusive::CachedFreeList<cds::intrusive::FreeList> cached_free_list;
+ CDSSTRESS_FREELIST_F( CachedFreeList, cached_free_list )
+
+#ifdef CDS_DCAS_SUPPORT
+ TEST_F( put_get, TaggetFreeList )
+ {
+ struct tagged_ptr {
+ void* p;
+ uintptr_t tag;
+ };
+
+ atomics::atomic<tagged_ptr> tp;
+ if ( tp.is_lock_free()) {
+ using FL = cds::intrusive::TaggedFreeList;
+ std::unique_ptr<FL> fl(new FL());
+ test( *fl );
+ }
+ else
+ std::cout << "Double-width CAS is not supported\n";
+ }
+#endif
+
+} // namespace
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cds_test/stress_test.h>
+
+#include <cds/intrusive/free_list.h>
+#include <cds/intrusive/free_list_cached.h>
+#ifdef CDS_DCAS_SUPPORT
+# include <cds/intrusive/free_list_tagged.h>
+#endif
+
+namespace {
+ class put_get_single: public cds_test::stress_fixture
+ {
+ protected:
+ static size_t s_nThreadCount;
+ static size_t s_nPassCount;
+
+ template <typename FreeList >
+ struct value_type: public FreeList::node
+ {
+ atomics::atomic<size_t> counter;
+
+ value_type()
+ : counter(0)
+ {}
+ };
+
+ template <class FreeList>
+ class Worker: public cds_test::thread
+ {
+ typedef cds_test::thread base_class;
+ public:
+ FreeList& m_FreeList;
+ size_t m_nSuccess = 0;
+
+ public:
+ Worker( cds_test::thread_pool& pool, FreeList& s )
+ : base_class( pool )
+ , m_FreeList( s )
+ {}
+
+ Worker( Worker& src )
+ : base_class( src )
+ , m_FreeList( src.m_FreeList )
+ {}
+
+ virtual thread * clone()
+ {
+ return new Worker( *this );
+ }
+
+ virtual void test()
+ {
+ typedef value_type<FreeList> item_type;
+
+ for ( size_t pass = 0; pass < s_nPassCount; ++pass ) {
+ item_type* p;
+ while ( (p = static_cast<item_type*>( m_FreeList.get())) == nullptr );
+ m_FreeList.put( p );
+ }
+ }
+ };
+
+ public:
+ static void SetUpTestCase()
+ {
+ cds_test::config const& cfg = get_config( "SequentialFreeList" );
+
+ s_nPassCount = cfg.get_size_t( "SinglePassCount", s_nPassCount );
+
+ s_nThreadCount = 1;
+ if ( s_nPassCount == 0 )
+ s_nPassCount = 1000;
+ }
+ //static void TearDownTestCase();
+
+ protected:
+
+ template <typename FreeList>
+ void test( FreeList& list )
+ {
+ cds_test::thread_pool& pool = get_pool();
+
+ value_type<FreeList> item;;
+ list.put( &item );
+
+ pool.add( new Worker<FreeList>( pool, list ), s_nThreadCount );
+ std::unique_ptr<Worker<FreeList>> worker(
+ new Worker<FreeList>(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<freelist_type> fl(new freelist_type()); \
+ test(*fl); \
+ }
+
+ CDSSTRESS_FREELIST_F( FreeList, cds::intrusive::FreeList )
+
+ typedef cds::intrusive::CachedFreeList<cds::intrusive::FreeList> cached_free_list;
+ CDSSTRESS_FREELIST_F( CachedFreeList, cached_free_list )
+
+#ifdef CDS_DCAS_SUPPORT
+ TEST_F( put_get_single, TaggetFreeList )
+ {
+ struct tagged_ptr {
+ void* p;
+ uintptr_t tag;
+ };
+
+ atomics::atomic<tagged_ptr> tp;
+ if ( tp.is_lock_free()) {
+ using FL = cds::intrusive::TaggedFreeList;
+ std::unique_ptr<FL> fl(new FL());
+ test( *fl );
+ }
+ else
+ std::cout << "Double-width CAS is not supported\n";
+ }
+#endif
+
+} // namespace
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "../misc/common.h"
+#include "../queue/queue_type.h"
+
+#include <algorithm>
+#include <type_traits>
+#include <vector>
+
+// Sequential queue push/pop test
+namespace {
+
+static size_t s_nEnqueueCount = 4000000;
+// Call 's_nEnqueueStride' number of enqueue before dequeue.
+static size_t s_nEnqueueStride = 10000;
+static size_t s_nQueueSize = 100000;
+static size_t s_nVyukovQueuePushCount = 300000;
+
+struct old_value {
+ size_t nNo;
+};
+
+template <class Value = old_value>
+class sequential_queue : public cds_test::stress_fixture {
+protected:
+ using value_type = Value;
+
+ template <typename Queue>
+ void test(Queue &q, size_t enqueue_count = s_nEnqueueCount) {
+ value_type v;
+ v.nNo = 0;
+ size_t push_failure = 0;
+ size_t pop_sum = 0;
+
+ while (v.nNo < enqueue_count) {
+ size_t curr_push_count =
+ std::min(enqueue_count - v.nNo, s_nEnqueueStride);
+ for (size_t i = 0; i < curr_push_count; i++) {
+ if (q.push(v))
+ ++v.nNo;
+ else
+ ++push_failure;
+ }
+
+ value_type res;
+ while (q.pop(res)) {
+ pop_sum += res.nNo;
+ }
+ }
+
+ if (push_failure) {
+ std::cout << "Sequential queue push error count: " << push_failure
+ << "\n";
+ }
+ size_t supposed_sum = enqueue_count * (enqueue_count - 1) / 2;
+ if (pop_sum != supposed_sum) {
+ std::cout << "Sequential queue pop sum: " << pop_sum
+ << " != " << supposed_sum << "\n";
+ }
+ }
+
+public:
+ static void SetUpTestCase() {
+ cds_test::config const &cfg = get_config("SequentialQueue");
+ GetConfig(EnqueueCount);
+ GetConfig(EnqueueStride);
+ GetConfig(QueueSize);
+ GetConfig(VyukovQueuePushCount);
+ }
+};
+
+using simple_sequential_queue = sequential_queue<>;
+
+#define CDSSTRESS_Sequential_Queue_F(test_fixture, type_name) \
+ TEST_F(test_fixture, type_name) { \
+ typedef queue::Types<value_type>::type_name queue_type; \
+ std::unique_ptr<queue_type> 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<value_type>::type_name queue_type; \
+ std::unique_ptr<queue_type> 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<size_t> {
+ typedef sequential_queue<> base_class;
+
+protected:
+ template <typename Queue> void test() {
+ size_t quasi_factor = GetParam();
+ Queue q(quasi_factor);
+ base_class::test(q);
+ }
+
+public:
+ static std::vector<size_t> get_test_parameters() {
+ cds_test::config const &cfg =
+ cds_test::stress_fixture::get_config("SequentialQueue");
+ bool bIterative = cfg.get_bool("SegmentedQueue_Iterate", false);
+ size_t quasi_factor = cfg.get_size_t("SegmentedQueue_SegmentSize", 256);
+
+ std::vector<size_t> args;
+ if (bIterative && quasi_factor > 4) {
+ for (size_t qf = 4; qf <= quasi_factor; qf *= 2)
+ args.push_back(qf);
+ } else {
+ if (quasi_factor > 2)
+ args.push_back(quasi_factor);
+ else
+ args.push_back(2);
+ }
+
+ return args;
+ }
+};
+
+#undef CDSSTRESS_Sequential_Queue_F
+#define CDSSTRESS_Sequential_Queue_F(test_fixture, type_name) \
+ TEST_P(test_fixture, type_name) { \
+ typedef typename queue::Types<value_type>::type_name queue_type; \
+ test<queue_type>(); \
+ }
+
+#define CDSSTRESS_Sequential_SegmentedQueue(test_fixture) \
+ CDSSTRESS_Sequential_Queue_F(test_fixture, SegmentedQueue_HP_spin); \
+ CDSSTRESS_Sequential_Queue_F(test_fixture, SegmentedQueue_HP_spin_padding); \
+ CDSSTRESS_Sequential_Queue_F(test_fixture, SegmentedQueue_DHP_spin);
+
+CDSSTRESS_Sequential_SegmentedQueue(sequential_segmented_queue)
+
+#ifdef CDSTEST_GTEST_INSTANTIATE_TEST_CASE_P_HAS_4TH_ARG
+ static std::string
+ get_test_parameter_name(testing::TestParamInfo<size_t> const &p) {
+ return std::to_string(p.param);
+}
+INSTANTIATE_TEST_CASE_P(
+ SQ, sequential_segmented_queue,
+ ::testing::ValuesIn(sequential_segmented_queue::get_test_parameters()),
+ get_test_parameter_name);
+#else
+ INSTANTIATE_TEST_CASE_P(
+ SQ, sequential_segmented_queue,
+ ::testing::ValuesIn(sequential_segmented_queue::get_test_parameters()));
+#endif
+
+// ********************************************************************
+// SPSC WeakRingBuffer
+static size_t s_nBufferSize = 1024 * 1024;
+static size_t s_nPushCount = 1000000;
+
+class sequential_weak_ring_buffer : public cds_test::stress_fixture {
+protected:
+ typedef size_t value_type;
+
+ template <typename Queue> void test(Queue &m_Queue) {
+ size_t const nPushCount = s_nPushCount;
+ size_t m_nPushed = 0;
+ size_t m_nPushFailed = 0;
+ size_t m_nPopped = 0;
+ size_t m_nBadValue = 0;
+ size_t m_nPopFrontFailed = 0;
+ size_t m_nPopEmpty = 0;
+
+ for (size_t i = 0; i < nPushCount; ++i) {
+ size_t len = rand(1024) + 64;
+ void *buf = m_Queue.back(len);
+ if (buf) {
+ memset(buf, len % 256, len);
+ m_Queue.push_back();
+ m_nPushed += len;
+ } else
+ ++m_nPushFailed;
+ }
+
+ while (true) {
+ auto buf = m_Queue.front();
+ if (buf.first) {
+ m_nPopped += buf.second;
+
+ uint8_t val = static_cast<uint8_t>(buf.second % 256);
+ uint8_t const *p = reinterpret_cast<uint8_t *>(buf.first);
+ for (uint8_t const *pEnd = p + buf.second; p < pEnd; ++p) {
+ if (*p != val) {
+ ++m_nBadValue;
+ break;
+ }
+ }
+
+ if (!m_Queue.pop_front())
+ ++m_nPopFrontFailed;
+ } else {
+ ++m_nPopEmpty;
+ if (m_Queue.empty())
+ break;
+ }
+ }
+ }
+
+public:
+ static void SetUpTestCase() {
+ cds_test::config const &cfg = get_config("SequentialRingBuffer");
+
+ s_nBufferSize = cfg.get_size_t("BufferSize", s_nBufferSize);
+ s_nPushCount = cfg.get_size_t("PushCount", s_nPushCount);
+
+ if (s_nBufferSize < 1024 * 64)
+ s_nBufferSize = 1024 * 64;
+ if (s_nPushCount == 0u)
+ s_nPushCount = 1024;
+ }
+};
+
+#undef CDSSTRESS_Sequential_Queue_F
+#define CDSSTRESS_Sequential_Queue_F(test_fixture, type_name) \
+ TEST_F(test_fixture, type_name) { \
+ typedef queue::Types<value_type>::type_name queue_type; \
+ std::unique_ptr<queue_type> queue(new queue_type(s_nBufferSize)); \
+ test(*queue); \
+ }
+
+CDSSTRESS_WeakRingBuffer_void(sequential_weak_ring_buffer)
+
+#undef CDSSTRESS_Queue_F
+
+} // namespace
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "../misc/common.h"
+#include "../stack/stack_type.h"
+
+namespace {
+
+#define CDSSTRESS_SequentialTreiberStack_F(test_fixture, type_name) \
+ TEST_F(test_fixture, type_name) { \
+ typedef stack::Types<value_type>::type_name stack_type; \
+ std::unique_ptr<stack_type> stack(new stack_type()); \
+ test(*stack); \
+ }
+
+#define CDSSTRESS_SequentialEliminationStack_F(test_fixture, type_name) \
+ TEST_F(test_fixture, type_name) { \
+ typedef stack::Types<value_type>::type_name stack_type; \
+ std::unique_ptr<stack_type> 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 <typename Stack>
+ void test(Stack &stack) {
+ size_t push_error_cnt = 0;
+ size_t pop_sum = 0;
+ value_type v;
+ size_t m_nStartItem = 0;
+ size_t m_nEndItem = s_nSequentialStackPushCount;
+ for (v.nNo = m_nStartItem; v.nNo < m_nEndItem; ++v.nNo) {
+ if (!stack.push(v))
+ ++push_error_cnt;
+ }
+
+ while (stack.pop(v)) {
+ pop_sum += v.nNo;
+ }
+
+ if (push_error_cnt) {
+ std::cout << "Sequential stack push error count: " << push_error_cnt
+ << "\n";
+ }
+ size_t supposed_sum =
+ (m_nStartItem + m_nEndItem - 1) * (m_nEndItem - m_nStartItem) / 2;
+ if (pop_sum != supposed_sum) {
+ std::cout << "Sequential stack pop sum: " << pop_sum
+ << " != " << supposed_sum << "\n";
+ }
+ }
+};
+
+CDSSTRESS_SequentialTreiberStack(sequential_stack);
+CDSSTRESS_SequentialEliminationStack(sequential_stack);
+
+} // namespace
--- /dev/null
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "../misc/common.h"
+#include "../stack/stack_type.h"
+#include <cds/sync/spinlock.h>
+#include <cds/misc/RigtorpSPSCQueue.h>
+
+namespace {
+
+class sequential_test : public cds_test::stress_fixture {
+
+};
+
+atomics::atomic<int> x;
+atomics::atomic<int> y;
+typedef cds::sync::spin SpinLock;
+SpinLock l;
+
+struct value_type {
+ size_t num;
+};
+
+typedef stack::Types<value_type>::Treiber_HP stack_type;
+stack_type stack;
+rigtorp::SPSCQueue<size_t> 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