From 7759bb803b78eed5a9f8ffc321fdde6bf45156dd Mon Sep 17 00:00:00 2001 From: khizmax Date: Tue, 1 Sep 2015 22:31:01 +0300 Subject: [PATCH] CuckooMap, CuckooSet: - replaced ensure() with update() - replaced find( key ) with contains( key ) MapDelOdd MT-test was refactored for CuckooMap --- cds/container/cuckoo_map.h | 76 ++++++---- cds/container/cuckoo_set.h | 129 ++++++++-------- cds/container/details/cuckoo_base.h | 6 +- cds/container/lazy_kvlist_rcu.h | 2 +- cds/container/michael_list_rcu.h | 2 +- cds/container/split_list_set_nogc.h | 2 +- cds/intrusive/cuckoo_set.h | 173 +++++++++++----------- cds/intrusive/lazy_list_nogc.h | 2 +- projects/Win/vc12/cds.sln | 4 - projects/Win/vc12/unit-map-delodd.vcxproj | 2 +- tests/data/test-debug.conf | 7 +- tests/data/test-express.conf | 7 +- tests/data/test.conf | 5 + tests/unit/map2/map_defs.h | 74 +++------ tests/unit/map2/map_delodd.cpp | 6 +- tests/unit/map2/map_delodd.h | 72 ++++----- tests/unit/map2/map_delodd_cuckoo.cpp | 10 +- tests/unit/map2/map_type_cuckoo.h | 28 ++-- tests/unit/print_cuckoo_stat.h | 10 +- 19 files changed, 310 insertions(+), 307 deletions(-) diff --git a/cds/container/cuckoo_map.h b/cds/container/cuckoo_map.h index b5204ffd..efc841a8 100644 --- a/cds/container/cuckoo_map.h +++ b/cds/container/cuckoo_map.h @@ -486,46 +486,47 @@ namespace cds { namespace container { return false; } - /// Ensures that the \p key exists in the map + /// Updates the node /** The operation performs inserting or changing data with lock-free manner. - If the \p key not found in the map, then the new item created from \p key - is inserted into the map (note that in this case the \ref key_type should be - constructible from type \p K). + If \p key is not found in the map, then \p key is inserted iff \p bAllowInsert is \p true. Otherwise, the functor \p func is called with item found. - The functor \p Func may be a function with signature: - \code - void func( bool bNew, value_type& item ); - \endcode - or a functor: + The functor \p func signature is: \code struct my_functor { void operator()( bool bNew, value_type& item ); }; \endcode - with arguments: - \p bNew - \p true if the item has been inserted, \p false otherwise - - \p item - item of the list - - The functor may change any fields of the \p item.second that is \ref value_type. + - \p item - an item of the map for \p key - Returns std::pair where \p first is true if operation is successfull, - \p second is true if new item has been added or \p false if the item with \p key - already is in the list. + Returns std::pair where \p first is \p true if operation is successfull, + i.e. the node has been inserted or updated, + \p second is \p true if new item has been added or \p false if the item with \p key + already exists. */ template - std::pair ensure( K const& key, Func func ) + std::pair update( K const& key, Func func, bool bAllowInsert = true ) { scoped_node_ptr pNode( alloc_node( key )); - std::pair res = base_class::ensure( *pNode, - [&func](bool bNew, node_type& item, node_type const& ){ func( bNew, item.m_val ); } + std::pair res = base_class::update( *pNode, + [&func](bool bNew, node_type& item, node_type const& ){ func( bNew, item.m_val ); }, + bAllowInsert ); if ( res.first && res.second ) pNode.release(); return res; } + //@cond + template + CDS_DEPRECATED("ensure() is deprecated, use update()") + std::pair ensure( K const& key, Func func ) + { + return update( key, func, true ;) + } + //@endcond /// Delete \p key from the map /** \anchor cds_nonintrusive_CuckooMap_erase_val @@ -651,32 +652,45 @@ namespace cds { namespace container { [&f](node_type& item, K const& ) { f( item.m_val );}); } - /// Find the key \p key - /** \anchor cds_nonintrusive_CuckooMap_find_val - + /// Checks whether the map contains \p key + /** The function searches the item with key equal to \p key and returns \p true if it is found, and \p false otherwise. */ template + bool contains( K const& key ) + { + return base_class::contains( key ); + } + //@cond + template + CDS_DEPRECATED("the function is deprecated, use contains()") bool find( K const& key ) { - return base_class::find( key ); + return contains( key ); } + //@endcond - /// Find the key \p val using \p pred predicate for comparing + /// Checks whether the map contains \p key using \p pred predicate for searching /** - The function is an analog of \ref cds_nonintrusive_CuckooMap_find_val "find(K const&)" - but \p pred is used for key comparison. - If you use ordered cuckoo map, then \p Predicate should have the interface and semantics like \p std::less. - If you use unordered cuckoo map, then \p Predicate should have the interface and semantics like \p std::equal_to. - \p pred must imply the same element order as the comparator used for building the map. + The function is similar to contains( key ) but \p pred is used for key comparing. + \p Less functor has the interface like \p std::less. + \p Less must imply the same element order as the comparator used for building the map. */ template - bool find_with( K const& key, Predicate pred ) + bool contains( K const& key, Predicate pred ) { CDS_UNUSED( pred ); - return base_class::find_with( key, cds::details::predicate_wrapper() ); + return base_class::contains( key, cds::details::predicate_wrapper() ); } + //@cond + template + CDS_DEPRECATED("the function is deprecated, use contains()") + bool find_with( K const& key, Predicate pred ) + { + return contains( key, pred ); + } + //@endcond /// Clears the map void clear() diff --git a/cds/container/cuckoo_set.h b/cds/container/cuckoo_set.h index 1142cce7..74133014 100644 --- a/cds/container/cuckoo_set.h +++ b/cds/container/cuckoo_set.h @@ -535,45 +535,51 @@ namespace cds { namespace container { return false; } - /// Ensures that the \p val exists in the set + /// Updates the node /** - The operation performs inserting or changing data. + The operation performs inserting or changing data with lock-free manner. - If the \p val key not found in the set, then the new item created from \p val - is inserted into the set. Otherwise, the functor \p func is called with the item found. - The functor \p Func should be a function with signature: - \code - void func( bool bNew, value_type& item, const Q& val ); - \endcode - or a functor: + If the item \p val is not found in the set, then \p val is inserted into the set + iff \p bAllowInsert is \p true. + Otherwise, the functor \p func is called with item found. + The functor \p func signature is: \code struct my_functor { void operator()( bool bNew, value_type& item, const Q& val ); }; \endcode - with arguments: - \p bNew - \p true if the item has been inserted, \p false otherwise - \p item - item of the set - - \p val - argument \p val passed into the \p ensure function + - \p val - argument \p val passed into the \p %update() function + If new item has been inserted (i.e. \p bNew is \p true) then \p item and \p val arguments + refer to the same thing. - The functor can change non-key fields of the \p item. - - Returns std::pair where \p first is true if operation is successfull, - \p second is true if new item has been added or \p false if the item with \p val key + Returns std::pair where \p first is \p true if operation is successfull, + i.e. the node has been inserted or updated, + \p second is \p true if new item has been added or \p false if the item with \p key already exists. */ template - std::pair ensure( Q const& val, Func func ) + std::pair update( Q const& val, Func func, bool bAllowInsert = true ) { scoped_node_ptr pNode( alloc_node( val )); - std::pair res = base_class::ensure( *pNode, - [&val,&func](bool bNew, node_type& item, node_type const& ){ func( bNew, item.m_val, val ); } + std::pair res = base_class::update( *pNode, + [&val,&func](bool bNew, node_type& item, node_type const& ){ func( bNew, item.m_val, val ); }, + bAllowInsert ); if ( res.first && res.second ) pNode.release(); return res; } + //@cond + template + CDS_DEPRECATED("ensure() is deprecated, use update()") + std::pair ensure( Q const& val, Func func ) + { + return update( val, func, true ); + } + //@endcond /// Delete \p key from the set /** \anchor cds_nonintrusive_CuckooSet_erase @@ -690,6 +696,13 @@ namespace cds { namespace container { { return base_class::find( val, [&f](node_type& item, Q& v) { f( item.m_val, v );}); } + //@cond + template + bool find( Q const& val, Func f ) + { + return base_class::find( val, [&f](node_type& item, Q const& v) { f( item.m_val, v );}); + } + //@endcond /// Find the key \p val using \p pred predicate for comparing /** @@ -706,40 +719,7 @@ namespace cds { namespace container { return base_class::find_with( val, typename maker::template predicate_wrapper(), [&f](node_type& item, Q& v) { f( item.m_val, v );}); } - - /// Find the key \p val - /** \anchor cds_nonintrusive_CuckooSet_find_cfunc - - The function searches the item with key equal to \p val and calls the functor \p f for item found. - The interface of \p Func functor is: - \code - struct functor { - void operator()( value_type& item, Q const& val ); - }; - \endcode - where \p item is the item found, \p val is the find function argument. - - The functor can change non-key fields of \p item. - - The type \p Q can differ from \ref value_type of items storing in the container. - Therefore, the \p value_type should be comparable with type \p Q. - - The function returns \p true if \p val is found, \p false otherwise. - */ - template - bool find( Q const& val, Func f ) - { - return base_class::find( val, [&f](node_type& item, Q const& v) { f( item.m_val, v );}); - } - - /// Find the key \p val using \p pred predicate for comparing - /** - The function is an analog of \ref cds_nonintrusive_CuckooSet_find_cfunc "find(Q const&, Func)" - but \p pred is used for key comparison. - If you use ordered cuckoo set, then \p Predicate should have the interface and semantics like \p std::less. - If you use unordered cuckoo set, then \p Predicate should have the interface and semantics like \p std::equal_to. - \p pred must imply the same element order as the comparator used for building the set. - */ + //@cond template bool find_with( Q const& val, Predicate pred, Func f ) { @@ -747,36 +727,47 @@ namespace cds { namespace container { return base_class::find_with( val, typename maker::template predicate_wrapper(), [&f](node_type& item, Q const& v) { f( item.m_val, v );}); } + //@endcond - /// Find the key \p val - /** \anchor cds_nonintrusive_CuckooSet_find_val - - The function searches the item with key equal to \p val + /// Checks whether the set contains \p key + /** + The function searches the item with key equal to \p key and returns \p true if it is found, and \p false otherwise. - - Note the hash functor specified for class \p Traits template parameter - should accept a parameter of type \p Q that can be not the same as \ref value_type. */ template - bool find( Q const& val ) + bool contains( Q const& key ) { - return base_class::find( val, [](node_type&, Q const&) {}); + return base_class::find( key, [](node_type&, Q const&) {}); } + //@cond + template + CDS_DEPRECATED("the function is deprecated, use contains()") + bool find( Q const& key ) + { + return contains( key ); + } + //@endcond - /// Find the key \p val using \p pred predicate for comparing + /// Checks whether the set contains \p key using \p pred predicate for searching /** - The function is an analog of \ref cds_nonintrusive_CuckooSet_find_val "find(Q const&)" - but \p pred is used for key comparison. - If you use ordered cuckoo set, then \p Predicate should have the interface and semantics like \p std::less. - If you use unordered cuckoo set, then \p Predicate should have the interface and semantics like \p std::equal_to. - \p pred must imply the same element order as the comparator used for building the set. + The function is similar to contains( key ) but \p pred is used for key comparing. + \p Less functor has the interface like \p std::less. + \p Less must imply the same element order as the comparator used for building the set. */ template - bool find_with( Q const& val, Predicate pred ) + bool contains( Q const& key, Predicate pred ) { CDS_UNUSED( pred ); - return base_class::find_with( val, typename maker::template predicate_wrapper(), [](node_type&, Q const&) {}); + return base_class::find_with( key, typename maker::template predicate_wrapper(), [](node_type&, Q const&) {}); + } + //@cond + template + CDS_DEPRECATED("the function is deprecated, use contains()") + bool find_with( Q const& key, Predicate pred ) + { + return contains( key, pred ); } + //@endcond /// Clears the set /** diff --git a/cds/container/details/cuckoo_base.h b/cds/container/details/cuckoo_base.h index 34f07a2e..d30c0621 100644 --- a/cds/container/details/cuckoo_base.h +++ b/cds/container/details/cuckoo_base.h @@ -102,11 +102,7 @@ namespace cds { namespace container { #ifdef CDS_DOXYGEN_INVOKED /// Probe set type option /** - The option specifies probe set type for the CuckooSet and CuckooMap. - Available \p Type: - - \p cuckoo::list - the probe-set is a single-linked list. - - \p cuckoo::vector - the probe-set is a vector - with constant-size \p Capacity where \p Capacity is an unsigned int constant. + @copydetails cds::intrusive::cuckoo::probeset_type */ template struct probeset_type diff --git a/cds/container/lazy_kvlist_rcu.h b/cds/container/lazy_kvlist_rcu.h index 2bb6eaca..6eb12850 100644 --- a/cds/container/lazy_kvlist_rcu.h +++ b/cds/container/lazy_kvlist_rcu.h @@ -450,7 +450,7 @@ namespace cds { namespace container { template std::pair ensure( const K& key, Func f ) { - return update( head(), key, f, true ); + return update( key, f, true ); } //@endcond diff --git a/cds/container/michael_list_rcu.h b/cds/container/michael_list_rcu.h index 9cfaa1b7..5377e195 100644 --- a/cds/container/michael_list_rcu.h +++ b/cds/container/michael_list_rcu.h @@ -428,7 +428,7 @@ namespace cds { namespace container { // Deprecated, use update() template std::pair ensure( Q const& key, Func f ) - {1 + { return update( key, f, true ); } //@endcond diff --git a/cds/container/split_list_set_nogc.h b/cds/container/split_list_set_nogc.h index f7ffd259..ad031f49 100644 --- a/cds/container/split_list_set_nogc.h +++ b/cds/container/split_list_set_nogc.h @@ -306,7 +306,7 @@ namespace cds { namespace container { std::pair ret = base_class::update_( *pNode, [](bool /*bNew*/, node_type& /*item*/, node_type& /*val*/){}, - bAllowInser ); + bAllowInsert ); if ( ret.first != base_class::end() && ret.second ) { pNode.release(); return std::make_pair( iterator(ret.first), ret.second ); diff --git a/cds/intrusive/cuckoo_set.h b/cds/intrusive/cuckoo_set.h index be873686..031aa2b2 100644 --- a/cds/intrusive/cuckoo_set.h +++ b/cds/intrusive/cuckoo_set.h @@ -79,14 +79,17 @@ namespace cds { namespace intrusive { //@endcond //@cond - // Probeset type declarations. + /// List probeset type struct list; + //@endcond + + /// Vector probeset type template struct vector { + /// Vector capacity static unsigned int const c_nCapacity = Capacity; }; - //@endcond /// CuckooSet node /** @@ -172,7 +175,6 @@ namespace cds { namespace intrusive { { m_pNext = nullptr; } - }; template @@ -986,11 +988,11 @@ namespace cds { namespace intrusive { counter_type m_nInsertRelocateCount ; ///< Count of \p relocate function call from \p insert counter_type m_nInsertRelocateFault ; ///< Count of failed \p relocate function call from \p insert - counter_type m_nEnsureExistCount ; ///< Count of call \p ensure function for existing node - counter_type m_nEnsureSuccessCount ; ///< Count of successfull \p insert function call for new node - counter_type m_nEnsureResizeCount ; ///< Count of \p resize function call from \p ensure - counter_type m_nEnsureRelocateCount ; ///< Count of \p relocate function call from \p ensure - counter_type m_nEnsureRelocateFault ; ///< Count of failed \p relocate function call from \p ensure + counter_type m_nUpdateExistCount ; ///< Count of call \p update() function for existing node + counter_type m_nUpdateSuccessCount ; ///< Count of successfull \p insert function call for new node + counter_type m_nUpdateResizeCount ; ///< Count of \p resize function call from \p update() + counter_type m_nUpdateRelocateCount ; ///< Count of \p relocate function call from \p update() + counter_type m_nUpdateRelocateFault ; ///< Count of failed \p relocate function call from \p update() counter_type m_nUnlinkSuccess ; ///< Count of success \p unlink function call counter_type m_nUnlinkFailed ; ///< Count of failed \p unlink function call @@ -1026,11 +1028,11 @@ namespace cds { namespace intrusive { void onInsertRelocate() { ++m_nInsertRelocateCount; } void onInsertRelocateFault() { ++m_nInsertRelocateFault; } - void onEnsureExist() { ++m_nEnsureExistCount; } - void onEnsureSuccess() { ++m_nEnsureSuccessCount; } - void onEnsureResize() { ++m_nEnsureResizeCount; } - void onEnsureRelocate() { ++m_nEnsureRelocateCount; } - void onEnsureRelocateFault() { ++m_nEnsureRelocateFault; } + void onUpdateExist() { ++m_nUpdateExistCount; } + void onUpdateSuccess() { ++m_nUpdateSuccessCount; } + void onUpdateResize() { ++m_nUpdateResizeCount; } + void onUpdateRelocate() { ++m_nUpdateRelocateCount; } + void onUpdateRelocateFault() { ++m_nUpdateRelocateFault; } void onUnlinkSuccess() { ++m_nUnlinkSuccess; } void onUnlinkFailed() { ++m_nUnlinkFailed; } @@ -1067,11 +1069,11 @@ namespace cds { namespace intrusive { void onInsertRelocate() const {} void onInsertRelocateFault() const {} - void onEnsureExist() const {} - void onEnsureSuccess() const {} - void onEnsureResize() const {} - void onEnsureRelocate() const {} - void onEnsureRelocateFault() const {} + void onUpdateExist() const {} + void onUpdateSuccess() const {} + void onUpdateResize() const {} + void onUpdateRelocate() const {} + void onUpdateRelocateFault() const {} void onUnlinkSuccess() const {} void onUnlinkFailed() const {} @@ -1984,7 +1986,6 @@ namespace cds { namespace intrusive { static void store_hash( node_type * pNode, size_t * pHashes ) { cuckoo::details::hash_ops< node_type, c_nNodeHashArraySize >::store( pNode, pHashes ); - //memcpy( pNode->m_arrHash, pHashes, sizeof(size_t) * c_nArity ); } static bool equal_hash( node_type& node, unsigned int nTable, size_t nHash ) @@ -2015,7 +2016,7 @@ namespace cds { namespace intrusive { free_bucket_tables( m_BucketTable, m_nBucketMask + 1 ); } - static unsigned int const c_nUndefTable = (unsigned int) -1; + static CDS_CONSTEXPR unsigned int const c_nUndefTable = (unsigned int) -1; template unsigned int contains( position * arrPos, size_t * arrHash, Q const& val, Predicate pred ) { @@ -2436,31 +2437,33 @@ namespace cds { namespace intrusive { return true; } - /// Ensures that the \p val exists in the set + /// Updates the node /** The operation performs inserting or changing data with lock-free manner. - If the item \p val not found in the set, then \p val is inserted into the set. + If the item \p val is not found in the set, then \p val is inserted into the set + iff \p bAllowInsert is \p true. Otherwise, the functor \p func is called with item found. - The functor signature is: + The functor \p func signature is: \code void func( bool bNew, value_type& item, value_type& val ); \endcode with arguments: - \p bNew - \p true if the item has been inserted, \p false otherwise - \p item - item of the set - - \p val - argument \p val passed into the \p ensure function + - \p val - argument \p val passed into the \p %update() function If new item has been inserted (i.e. \p bNew is \p true) then \p item and \p val arguments - refers to the same thing. + refer to the same thing. The functor may change non-key fields of the \p item. - Returns std::pair where \p first is \p true if operation is successful, + Returns std::pair where \p first is \p true if operation is successfull, + i.e. the node has been inserted or updated, \p second is \p true if new item has been added or \p false if the item with \p key - already is in the set. + already exists. */ template - std::pair ensure( value_type& val, Func func ) + std::pair update( value_type& val, Func func, bool bAllowInsert = true ) { hash_array arrHash; position arrPos[ c_nArity ]; @@ -2477,12 +2480,15 @@ namespace cds { namespace intrusive { unsigned int nTable = contains( arrPos, arrHash, val, key_predicate() ); if ( nTable != c_nUndefTable ) { func( false, *node_traits::to_value_ptr( *arrPos[nTable].itFound ), val ); - m_Stat.onEnsureExist(); + m_Stat.onUpdateExist(); return std::make_pair( true, false ); } - node_type * pNode = node_traits::to_node_ptr( val ); - store_hash( pNode, arrHash ); + if ( !bAllowInsert ) + return std::make_pair( false, false ); + + //node_type * pNode = node_traits::to_node_ptr( val ); + //store_hash( pNode, arrHash ); for ( unsigned int i = 0; i < c_nArity; ++i ) { bucket_entry& refBucket = bucket( i, arrHash[i] ); @@ -2490,7 +2496,7 @@ namespace cds { namespace intrusive { refBucket.insert_after( arrPos[i].itPrev, pNode ); func( true, val, val ); ++m_ItemCounter; - m_Stat.onEnsureSuccess(); + m_Stat.onUpdateSuccess(); return std::make_pair( true, true ); } } @@ -2509,21 +2515,29 @@ namespace cds { namespace intrusive { } } - m_Stat.onEnsureResize(); + m_Stat.onUpdateResize(); resize(); } do_relocate: - m_Stat.onEnsureRelocate(); + m_Stat.onUpdateRelocate(); if ( !relocate( nGoalTable, arrHash )) { - m_Stat.onEnsureRelocateFault(); - m_Stat.onEnsureResize(); + m_Stat.onUpdateRelocateFault(); + m_Stat.onUpdateResize(); resize(); } - m_Stat.onEnsureSuccess(); + m_Stat.onUpdateSuccess(); return std::make_pair( true, true ); } + //@cond + // Deprecated, use update() + template + std::pair ensure( value_type& val, Func func ) + { + return update( val, func, true ); + } + //@endcond /// Unlink the item \p val from the set /** @@ -2649,6 +2663,13 @@ namespace cds { namespace intrusive { { return find_( val, key_predicate(), f ); } + //@cond + template + bool find( Q const& val, Func f ) + { + return find_( val, key_predicate(), f ); + } + //@endcond /// Find the key \p val using \p pred predicate for comparing /** @@ -2664,74 +2685,54 @@ namespace cds { namespace intrusive { CDS_UNUSED( pred ); return find_( val, typename predicate_wrapper::type(), f ); } - - /// Find the key \p val - /** \anchor cds_intrusive_CuckooSet_find_cfunc - The function searches the item with key equal to \p val and calls the functor \p f for item found. - The interface of \p Func functor is: - \code - struct functor { - void operator()( value_type& item, Q const& val ); - }; - \endcode - where \p item is the item found, \p val is the find function argument. - - The functor may change non-key fields of \p item. - - The \p val argument is non-const since it can be used as \p f functor destination i.e., the functor - may modify both arguments. - - The function returns \p true if \p val is found, \p false otherwise. - */ - template - bool find( Q const& val, Func f ) - { - return find_( val, key_predicate(), f ); - } - - /// Find the key \p val using \p pred predicate for comparing - /** - The function is an analog of \ref cds_intrusive_CuckooSet_find_cfunc "find(Q const&, Func)" - but \p pred is used for key comparison. - If you use ordered cuckoo set, then \p Predicate should have the interface and semantics like \p std::less. - If you use unordered cuckoo set, then \p Predicate should have the interface and semantics like \p std::equal_to. - \p pred must imply the same element order as the comparator used for building the set. - */ + //@cond template bool find_with( Q const& val, Predicate pred, Func f ) { CDS_UNUSED( pred ); return find_( val, typename predicate_wrapper::type(), f ); } + //@endcond - /// Find the key \p val - /** \anchor cds_intrusive_CuckooSet_find_val - The function searches the item with key equal to \p val + /// Checks whether the set contains \p key + /** + The function searches the item with key equal to \p key and returns \p true if it is found, and \p false otherwise. - - Note the hash functor specified for class \p Traits template parameter - should accept a parameter of type \p Q that can be not the same as \p value_type. */ template - bool find( Q const& val ) + bool contains( Q const& key ) { - return find( val, [](value_type&, Q const& ) {} ); + return find( key, [](value_type&, Q const& ) {} ); } + //@cond + // Deprecated, use contains() + template + bool find( Q const& key ) + { + return contains( key ); + } + //@endcond - /// Find the key \p val using \p pred predicate for comparing + /// Checks whether the set contains \p key using \p pred predicate for searching /** - The function is an analog of \ref cds_intrusive_CuckooSet_find_val "find(Q const&)" - but \p pred is used for key comparison. - If you use ordered cuckoo set, then \p Predicate should have the interface and semantics like \p std::less. - If you use unordered cuckoo set, then \p Predicate should have the interface and semantics like \p std::equal_to. - \p pred must imply the same element order as the comparator used for building the set. + The function is similar to contains( key ) but \p pred is used for key comparing. + \p Less functor has the interface like \p std::less. + \p Less must imply the same element order as the comparator used for building the set. */ template - bool find_with( Q const& val, Predicate pred ) + bool contains( Q const& key, Predicate pred ) { CDS_UNUSED( pred ); - return find_with( val, typename predicate_wrapper::type(), [](value_type& , Q const& ) {} ); + return find_with( key, typename predicate_wrapper::type(), [](value_type& , Q const& ) {} ); } + //@cond + // Deprecated,use contains() + template + bool find_with( Q const& key, Predicate pred ) + { + return contains( key, pred ); + } + //@endcond /// Clears the set /** diff --git a/cds/intrusive/lazy_list_nogc.h b/cds/intrusive/lazy_list_nogc.h index 40595f18..6ecb29bf 100644 --- a/cds/intrusive/lazy_list_nogc.h +++ b/cds/intrusive/lazy_list_nogc.h @@ -380,7 +380,7 @@ namespace cds { namespace intrusive { template std::pair ensure( value_type& val, Func func ) { - return update( &m_Head, val, func, true ); + return update( val, func, true ); } //@endcond diff --git a/projects/Win/vc12/cds.sln b/projects/Win/vc12/cds.sln index 8f96230c..a203d44c 100644 --- a/projects/Win/vc12/cds.sln +++ b/projects/Win/vc12/cds.sln @@ -415,7 +415,6 @@ Global {BA2A9239-0299-4069-BB0E-16DACE87ADE0}.DebugVLD|Win32.ActiveCfg = DebugVLD|Win32 {BA2A9239-0299-4069-BB0E-16DACE87ADE0}.DebugVLD|Win32.Build.0 = DebugVLD|Win32 {BA2A9239-0299-4069-BB0E-16DACE87ADE0}.DebugVLD|x64.ActiveCfg = DebugVLD|x64 - {BA2A9239-0299-4069-BB0E-16DACE87ADE0}.DebugVLD|x64.Build.0 = DebugVLD|x64 {BA2A9239-0299-4069-BB0E-16DACE87ADE0}.ICL-Debug|Win32.ActiveCfg = ICL-Debug|Win32 {BA2A9239-0299-4069-BB0E-16DACE87ADE0}.ICL-Debug|Win32.Build.0 = ICL-Debug|Win32 {BA2A9239-0299-4069-BB0E-16DACE87ADE0}.ICL-Debug|x64.ActiveCfg = ICL-Debug|x64 @@ -435,7 +434,6 @@ Global {CA25BDBF-B354-4597-B6D2-220ABBB0D2F4}.DebugVLD|Win32.ActiveCfg = DebugVLD|Win32 {CA25BDBF-B354-4597-B6D2-220ABBB0D2F4}.DebugVLD|Win32.Build.0 = DebugVLD|Win32 {CA25BDBF-B354-4597-B6D2-220ABBB0D2F4}.DebugVLD|x64.ActiveCfg = DebugVLD|x64 - {CA25BDBF-B354-4597-B6D2-220ABBB0D2F4}.DebugVLD|x64.Build.0 = DebugVLD|x64 {CA25BDBF-B354-4597-B6D2-220ABBB0D2F4}.ICL-Debug|Win32.ActiveCfg = ICL-Debug|Win32 {CA25BDBF-B354-4597-B6D2-220ABBB0D2F4}.ICL-Debug|Win32.Build.0 = ICL-Debug|Win32 {CA25BDBF-B354-4597-B6D2-220ABBB0D2F4}.ICL-Debug|x64.ActiveCfg = ICL-Debug|x64 @@ -635,7 +633,6 @@ Global {7521DD92-56FF-4ECA-93E5-CCE50862354B}.DebugVLD|Win32.ActiveCfg = DebugVLD|Win32 {7521DD92-56FF-4ECA-93E5-CCE50862354B}.DebugVLD|Win32.Build.0 = DebugVLD|Win32 {7521DD92-56FF-4ECA-93E5-CCE50862354B}.DebugVLD|x64.ActiveCfg = DebugVLD|x64 - {7521DD92-56FF-4ECA-93E5-CCE50862354B}.DebugVLD|x64.Build.0 = DebugVLD|x64 {7521DD92-56FF-4ECA-93E5-CCE50862354B}.ICL-Debug|Win32.ActiveCfg = ICL-Debug|Win32 {7521DD92-56FF-4ECA-93E5-CCE50862354B}.ICL-Debug|Win32.Build.0 = ICL-Debug|Win32 {7521DD92-56FF-4ECA-93E5-CCE50862354B}.ICL-Debug|x64.ActiveCfg = ICL-Debug|x64 @@ -655,7 +652,6 @@ Global {CA6F0834-0628-4CD7-8800-AEABCD636360}.DebugVLD|Win32.ActiveCfg = DebugVLD|Win32 {CA6F0834-0628-4CD7-8800-AEABCD636360}.DebugVLD|Win32.Build.0 = DebugVLD|Win32 {CA6F0834-0628-4CD7-8800-AEABCD636360}.DebugVLD|x64.ActiveCfg = DebugVLD|x64 - {CA6F0834-0628-4CD7-8800-AEABCD636360}.DebugVLD|x64.Build.0 = DebugVLD|x64 {CA6F0834-0628-4CD7-8800-AEABCD636360}.ICL-Debug|Win32.ActiveCfg = ICL-Debug|Win32 {CA6F0834-0628-4CD7-8800-AEABCD636360}.ICL-Debug|Win32.Build.0 = ICL-Debug|Win32 {CA6F0834-0628-4CD7-8800-AEABCD636360}.ICL-Debug|x64.ActiveCfg = ICL-Debug|x64 diff --git a/projects/Win/vc12/unit-map-delodd.vcxproj b/projects/Win/vc12/unit-map-delodd.vcxproj index fae5da4b..4ceb02af 100644 --- a/projects/Win/vc12/unit-map-delodd.vcxproj +++ b/projects/Win/vc12/unit-map-delodd.vcxproj @@ -48,7 +48,7 @@ false - true + false false diff --git a/tests/data/test-debug.conf b/tests/data/test-debug.conf index c765db2b..df31370c 100644 --- a/tests/data/test-debug.conf +++ b/tests/data/test-debug.conf @@ -193,4 +193,9 @@ InsThreadCount=2 DelThreadCount=2 ExtractThreadCount=2 MaxLoadFactor=4 -PrintGCStateFlag=1 \ No newline at end of file +PrintGCStateFlag=1 +#Cuckoo map properties +CuckooInitialSize=256 +CuckooProbesetSize=8 +# 0 - use default +CuckooProbesetThreshold=0 diff --git a/tests/data/test-express.conf b/tests/data/test-express.conf index 8b285e8d..04965af4 100644 --- a/tests/data/test-express.conf +++ b/tests/data/test-express.conf @@ -191,4 +191,9 @@ InsThreadCount=4 DelThreadCount=3 ExtractThreadCount=3 MaxLoadFactor=4 -PrintGCStateFlag=1 \ No newline at end of file +PrintGCStateFlag=1 +#Cuckoo map properties +CuckooInitialSize=1024 +CuckooProbesetSize=16 +# 0 - use default +CuckooProbesetThreshold=0 diff --git a/tests/data/test.conf b/tests/data/test.conf index a5468fca..62327b6a 100644 --- a/tests/data/test.conf +++ b/tests/data/test.conf @@ -187,3 +187,8 @@ DelThreadCount=3 ExtractThreadCount=3 MaxLoadFactor=4 PrintGCStateFlag=1 +#Cuckoo map properties +CuckooInitialSize=1024 +CuckooProbesetSize=16 +# 0 - use default +CuckooProbesetThreshold=0 diff --git a/tests/unit/map2/map_defs.h b/tests/unit/map2/map_defs.h index f8559b30..96c93787 100644 --- a/tests/unit/map2/map_defs.h +++ b/tests/unit/map2/map_defs.h @@ -693,56 +693,30 @@ // CuckooMap #define CDSUNIT_DECLARE_CuckooMap \ - CDSUNIT_DECLARE_TEST(CuckooStripedMap_list_unord)\ - CDSUNIT_DECLARE_TEST(CuckooStripedMap_list_ord)\ - CDSUNIT_DECLARE_TEST(CuckooStripedMap_vector_unord)\ - CDSUNIT_DECLARE_TEST(CuckooStripedMap_vector_ord)\ - CDSUNIT_DECLARE_TEST(CuckooStripedMap_list_unord_stat)\ - CDSUNIT_DECLARE_TEST(CuckooStripedMap_list_ord_stat)\ - CDSUNIT_DECLARE_TEST(CuckooStripedMap_vector_unord_stat)\ - CDSUNIT_DECLARE_TEST(CuckooStripedMap_vector_ord_stat)\ - CDSUNIT_DECLARE_TEST(CuckooRefinableMap_list_unord)\ - CDSUNIT_DECLARE_TEST(CuckooRefinableMap_list_ord)\ - CDSUNIT_DECLARE_TEST(CuckooRefinableMap_vector_unord)\ - CDSUNIT_DECLARE_TEST(CuckooRefinableMap_vector_ord) \ - CDSUNIT_DECLARE_TEST(CuckooRefinableMap_list_unord_stat)\ - CDSUNIT_DECLARE_TEST(CuckooRefinableMap_list_ord_stat)\ - CDSUNIT_DECLARE_TEST(CuckooRefinableMap_vector_unord_stat)\ - CDSUNIT_DECLARE_TEST(CuckooRefinableMap_vector_ord_stat) \ - CDSUNIT_DECLARE_TEST(CuckooStripedMap_list_unord_storehash)\ - CDSUNIT_DECLARE_TEST(CuckooStripedMap_list_ord_storehash)\ - CDSUNIT_DECLARE_TEST(CuckooStripedMap_vector_unord_storehash)\ - CDSUNIT_DECLARE_TEST(CuckooStripedMap_vector_ord_storehash)\ - CDSUNIT_DECLARE_TEST(CuckooRefinableMap_list_unord_storehash)\ - CDSUNIT_DECLARE_TEST(CuckooRefinableMap_list_ord_storehash)\ - CDSUNIT_DECLARE_TEST(CuckooRefinableMap_vector_unord_storehash)\ - CDSUNIT_DECLARE_TEST(CuckooRefinableMap_vector_ord_storehash) - -#define CDSUNIT_DEFINE_CuckooMap( IMPL, C ) \ - TEST_MAP(IMPL, C, CuckooStripedMap_list_unord)\ - TEST_MAP(IMPL, C, CuckooStripedMap_list_ord)\ - TEST_MAP(IMPL, C, CuckooStripedMap_vector_unord)\ - TEST_MAP(IMPL, C, CuckooStripedMap_vector_ord)\ - TEST_MAP(IMPL, C, CuckooStripedMap_list_unord_stat)\ - TEST_MAP(IMPL, C, CuckooStripedMap_list_ord_stat)\ - TEST_MAP(IMPL, C, CuckooStripedMap_vector_unord_stat)\ - TEST_MAP(IMPL, C, CuckooStripedMap_vector_ord_stat)\ - TEST_MAP(IMPL, C, CuckooRefinableMap_list_unord)\ - TEST_MAP(IMPL, C, CuckooRefinableMap_list_ord)\ - TEST_MAP(IMPL, C, CuckooRefinableMap_vector_unord)\ - TEST_MAP(IMPL, C, CuckooRefinableMap_vector_ord) \ - TEST_MAP(IMPL, C, CuckooRefinableMap_list_unord_stat)\ - TEST_MAP(IMPL, C, CuckooRefinableMap_list_ord_stat)\ - TEST_MAP(IMPL, C, CuckooRefinableMap_vector_unord_stat)\ - TEST_MAP(IMPL, C, CuckooRefinableMap_vector_ord_stat) \ - TEST_MAP(IMPL, C, CuckooStripedMap_list_unord_storehash)\ - TEST_MAP(IMPL, C, CuckooStripedMap_list_ord_storehash)\ - TEST_MAP(IMPL, C, CuckooStripedMap_vector_unord_storehash)\ - TEST_MAP(IMPL, C, CuckooStripedMap_vector_ord_storehash)\ - TEST_MAP(IMPL, C, CuckooRefinableMap_list_unord_storehash)\ - TEST_MAP(IMPL, C, CuckooRefinableMap_list_ord_storehash)\ - TEST_MAP(IMPL, C, CuckooRefinableMap_vector_unord_storehash)\ - TEST_MAP(IMPL, C, CuckooRefinableMap_vector_ord_storehash) + TEST_CASE(tag_CuckooMap, CuckooStripedMap_list_unord)\ + TEST_CASE(tag_CuckooMap, CuckooStripedMap_list_ord)\ + TEST_CASE(tag_CuckooMap, CuckooStripedMap_vector_unord)\ + TEST_CASE(tag_CuckooMap, CuckooStripedMap_vector_ord)\ + TEST_CASE(tag_CuckooMap, CuckooStripedMap_list_unord_stat)\ + TEST_CASE(tag_CuckooMap, CuckooStripedMap_list_ord_stat)\ + TEST_CASE(tag_CuckooMap, CuckooStripedMap_vector_unord_stat)\ + TEST_CASE(tag_CuckooMap, CuckooStripedMap_vector_ord_stat)\ + TEST_CASE(tag_CuckooMap, CuckooRefinableMap_list_unord)\ + TEST_CASE(tag_CuckooMap, CuckooRefinableMap_list_ord)\ + TEST_CASE(tag_CuckooMap, CuckooRefinableMap_vector_unord)\ + TEST_CASE(tag_CuckooMap, CuckooRefinableMap_vector_ord) \ + TEST_CASE(tag_CuckooMap, CuckooRefinableMap_list_unord_stat)\ + TEST_CASE(tag_CuckooMap, CuckooRefinableMap_list_ord_stat)\ + TEST_CASE(tag_CuckooMap, CuckooRefinableMap_vector_unord_stat)\ + TEST_CASE(tag_CuckooMap, CuckooRefinableMap_vector_ord_stat) \ + TEST_CASE(tag_CuckooMap, CuckooStripedMap_list_unord_storehash)\ + TEST_CASE(tag_CuckooMap, CuckooStripedMap_list_ord_storehash)\ + TEST_CASE(tag_CuckooMap, CuckooStripedMap_vector_unord_storehash)\ + TEST_CASE(tag_CuckooMap, CuckooStripedMap_vector_ord_storehash)\ + TEST_CASE(tag_CuckooMap, CuckooRefinableMap_list_unord_storehash)\ + TEST_CASE(tag_CuckooMap, CuckooRefinableMap_list_ord_storehash)\ + TEST_CASE(tag_CuckooMap, CuckooRefinableMap_vector_unord_storehash)\ + TEST_CASE(tag_CuckooMap, CuckooRefinableMap_vector_ord_storehash) #define CDSUNIT_TEST_CuckooMap \ CPPUNIT_TEST(CuckooStripedMap_list_unord)\ diff --git a/tests/unit/map2/map_delodd.cpp b/tests/unit/map2/map_delodd.cpp index 795d58d6..2bee64ed 100644 --- a/tests/unit/map2/map_delodd.cpp +++ b/tests/unit/map2/map_delodd.cpp @@ -12,8 +12,10 @@ namespace map2 { c_nExtractThreadCount = cfg.getULong("ExtractThreadCount", static_cast(c_nExtractThreadCount) ); c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", static_cast(c_nMaxLoadFactor) ); c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true ); - c_nMultiLevelMap_HeadBits = cfg.getULong("MultiLevelMap_HeadBits", static_cast(c_nMultiLevelMap_HeadBits) ); - c_nMultiLevelMap_ArrayBits = cfg.getULong("MultiLevelMap_ArrayBits", static_cast(c_nMultiLevelMap_ArrayBits) ); + + c_nCuckooInitialSize = cfg.getULong("CuckooInitialSize", static_cast(c_nCuckooInitialSize) ); + c_nCuckooProbesetSize = cfg.getULong("CuckooProbesetSize", static_cast(c_nCuckooProbesetSize) ); + c_nCuckooProbesetThreshold = cfg.getULong("CuckooProbesetThreshold", static_cast(c_nCuckooProbesetThreshold) ); if ( c_nInsThreadCount == 0 ) diff --git a/tests/unit/map2/map_delodd.h b/tests/unit/map2/map_delodd.h index 57a6db6f..61908482 100644 --- a/tests/unit/map2/map_delodd.h +++ b/tests/unit/map2/map_delodd.h @@ -120,8 +120,9 @@ namespace map2 { size_t c_nExtractThreadCount = 4; // extract thread count size_t c_nMapSize = 1000000; // max map size size_t c_nMaxLoadFactor = 8; // maximum load factor - size_t c_nMultiLevelMap_HeadBits = 10; // for MultiLevelHashMap - log2(size of head array) - size_t c_nMultiLevelMap_ArrayBits = 8; // for MultiLevelHashMap - log2(size of array node) + size_t c_nCuckooInitialSize = 1024;// initial size for CuckooMap + size_t c_nCuckooProbesetSize = 16; // CuckooMap probeset size (only for list-based probeset) + size_t c_nCuckooProbesetThreshold = 0; // CUckooMap probeset threshold (o - use default) bool c_bPrintGCState = true; @@ -651,39 +652,44 @@ namespace map2 { template void run_test() { - if ( Map::c_bExtractSupported ) { - CPPUNIT_MSG( "Thread count: insert=" << c_nInsThreadCount - << ", delete=" << c_nDelThreadCount - << ", extract=" << c_nExtractThreadCount - << "; set size=" << c_nMapSize - ); - if ( Map::c_bLoadFactorDepended ) { - for ( c_nLoadFactor = 1; c_nLoadFactor <= c_nMaxLoadFactor; c_nLoadFactor *= 2 ) { - CPPUNIT_MSG( "Load factor=" << c_nLoadFactor ); - do_test_extract(); - if ( c_bPrintGCState ) - print_gc_state(); - } - } - else + static_assert( Map::c_bExtractSupported, "Map class must support extract() method" ); + + CPPUNIT_MSG( "Thread count: insert=" << c_nInsThreadCount + << ", delete=" << c_nDelThreadCount + << ", extract=" << c_nExtractThreadCount + << "; set size=" << c_nMapSize + ); + if ( Map::c_bLoadFactorDepended ) { + for ( c_nLoadFactor = 1; c_nLoadFactor <= c_nMaxLoadFactor; c_nLoadFactor *= 2 ) { + CPPUNIT_MSG( "Load factor=" << c_nLoadFactor ); do_test_extract(); - } - else { - CPPUNIT_MSG( "Insert thread count=" << c_nInsThreadCount - << " delete thread count=" << c_nDelThreadCount - << " set size=" << c_nMapSize - ); - if ( Map::c_bLoadFactorDepended ) { - for ( c_nLoadFactor = 1; c_nLoadFactor <= c_nMaxLoadFactor; c_nLoadFactor *= 2 ) { - CPPUNIT_MSG( "Load factor=" << c_nLoadFactor ); - do_test(); - if ( c_bPrintGCState ) - print_gc_state(); - } + if ( c_bPrintGCState ) + print_gc_state(); } - else + } + else + do_test_extract(); + } + + template + void run_test_no_extract() + { + static_assert( !Map::c_bExtractSupported, "Map class must not support extract() method" ); + + CPPUNIT_MSG( "Insert thread count=" << c_nInsThreadCount + << " delete thread count=" << c_nDelThreadCount + << " set size=" << c_nMapSize + ); + if ( Map::c_bLoadFactorDepended ) { + for ( c_nLoadFactor = 1; c_nLoadFactor <= c_nMaxLoadFactor; c_nLoadFactor *= 2 ) { + CPPUNIT_MSG( "Load factor=" << c_nLoadFactor ); do_test(); + if ( c_bPrintGCState ) + print_gc_state(); + } } + else + do_test(); } void setUpParams( const CppUnitMini::TestCfg& cfg ); @@ -694,6 +700,7 @@ namespace map2 { CDSUNIT_DECLARE_SkipListMap CDSUNIT_DECLARE_EllenBinTreeMap CDSUNIT_DECLARE_BronsonAVLTreeMap + CDSUNIT_DECLARE_CuckooMap // This test is not suitable for MultiLevelHashMap //CDSUNIT_DECLARE_MultiLevelHashMap @@ -704,14 +711,13 @@ namespace map2 { CDSUNIT_TEST_SkipListMap CDSUNIT_TEST_EllenBinTreeMap CDSUNIT_TEST_BronsonAVLTreeMap + CDSUNIT_TEST_CuckooMap //CDSUNIT_TEST_MultiLevelHashMap // the test is not suitable CPPUNIT_TEST_SUITE_END(); ////CDSUNIT_DECLARE_StripedMap ////CDSUNIT_DECLARE_RefinableMap - //CDSUNIT_DECLARE_CuckooMap - //CDSUNIT_DECLARE_MultiLevelHashMap ////CDSUNIT_DECLARE_StdMap }; } // namespace map2 diff --git a/tests/unit/map2/map_delodd_cuckoo.cpp b/tests/unit/map2/map_delodd_cuckoo.cpp index 3d314b5f..72e5c205 100644 --- a/tests/unit/map2/map_delodd_cuckoo.cpp +++ b/tests/unit/map2/map_delodd_cuckoo.cpp @@ -3,10 +3,10 @@ #include "map2/map_delodd.h" #include "map2/map_type_cuckoo.h" -namespace map2 { - CDSUNIT_DEFINE_CuckooMap(cds::intrusive::cuckoo::implementation_tag, Map_DelOdd) +#undef TEST_CASE +#define TEST_CASE(TAG, X) void Map_DelOdd::X() { run_test_no_extract::X>(); } +#include "map2/map_defs.h" - CPPUNIT_TEST_SUITE_PART( Map_DelOdd, run_CuckooMap ) - CDSUNIT_TEST_CuckooMap - CPPUNIT_TEST_SUITE_END_PART() +namespace map2 { + CDSUNIT_DECLARE_CuckooMap } // namespace map2 diff --git a/tests/unit/map2/map_type_cuckoo.h b/tests/unit/map2/map_type_cuckoo.h index 3875ead7..c99d8676 100644 --- a/tests/unit/map2/map_type_cuckoo.h +++ b/tests/unit/map2/map_type_cuckoo.h @@ -4,34 +4,42 @@ #define CDSUNIT_MAP_TYPE_CUCKOO_H #include "map2/map_type.h" - #include - #include "print_cuckoo_stat.h" namespace map2 { template - class CuckooMap : - public cc::CuckooMap< K, V, Traits > + class CuckooMap: public cc::CuckooMap< K, V, Traits > { public: - typedef cc::CuckooMap< K, V, Traits > cuckoo_base_class; + typedef cc::CuckooMap< K, V, Traits > base_class; public: - CuckooMap( size_t nCapacity, size_t nLoadFactor ) - : cuckoo_base_class( nCapacity / (nLoadFactor * 16), (unsigned int) 4 ) + template + CuckooMap( Config const& cfg ) + : base_class( + cfg.c_nCuckooInitialSize, + static_cast( cfg.c_nCuckooProbesetSize ), + static_cast( cfg.c_nCuckooProbesetThreshold ) + ) {} template bool erase_with( Q const& key, Pred /*pred*/ ) { - return cuckoo_base_class::erase_with( key, typename std::conditional< cuckoo_base_class::c_isSorted, Pred, typename Pred::equal_to>::type() ); + 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; }; + struct tag_CuckooMap; + template - struct map_type< cds::intrusive::cuckoo::implementation_tag, Key, Value >: public map_type_base< Key, 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::compare compare; @@ -160,7 +168,7 @@ namespace map2 { static inline void print_stat( CuckooMap< K, V, Traits > const& m ) { typedef CuckooMap< K, V, Traits > map_type; - print_stat( static_cast(m) ); + print_stat( static_cast(m) ); } } // namespace map2 diff --git a/tests/unit/print_cuckoo_stat.h b/tests/unit/print_cuckoo_stat.h index 1d2fc9cf..a8f05762 100644 --- a/tests/unit/print_cuckoo_stat.h +++ b/tests/unit/print_cuckoo_stat.h @@ -63,11 +63,11 @@ namespace std { << "\t\t m_nInsertResizeCount: " << s.m_nInsertResizeCount.get() << "\n" << "\t\t m_nInsertRelocateCount: " << s.m_nInsertRelocateCount.get() << "\n" << "\t\t m_nInsertRelocateFault: " << s.m_nInsertRelocateFault.get() << "\n" - << "\t\t m_nEnsureExistCount: " << s.m_nEnsureExistCount.get() << "\n" - << "\t\t m_nEnsureSuccessCount: " << s.m_nEnsureSuccessCount.get() << "\n" - << "\t\t m_nEnsureResizeCount: " << s.m_nEnsureResizeCount.get() << "\n" - << "\t\t m_nEnsureRelocateCount: " << s.m_nEnsureRelocateCount.get() << "\n" - << "\t\t m_nEnsureRelocateFault: " << s.m_nEnsureRelocateFault.get() << "\n" + << "\t\t m_nUpdateExistCount: " << s.m_nUpdateExistCount.get() << "\n" + << "\t\t m_nUpdateSuccessCount: " << s.m_nUpdateSuccessCount.get() << "\n" + << "\t\t m_nUpdateResizeCount: " << s.m_nUpdateResizeCount.get() << "\n" + << "\t\t m_nUpdateRelocateCount: " << s.m_nUpdateRelocateCount.get() << "\n" + << "\t\t m_nUpdateRelocateFault: " << s.m_nUpdateRelocateFault.get() << "\n" << "\t\t m_nUnlinkSuccess: " << s.m_nUnlinkSuccess.get() << "\n" << "\t\t m_nUnlinkFailed: " << s.m_nUnlinkFailed.get() << "\n" << "\t\t m_nEraseSuccess: " << s.m_nEraseSuccess.get() << "\n" -- 2.34.1