From: khizmax Date: Wed, 4 Feb 2015 14:37:33 +0000 (+0300) Subject: Bronson AVL-tree impl X-Git-Tag: v2.1.0~305^2~75 X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=43fb532e10a916a00c83debae48156cec8a82e05;p=libcds.git Bronson AVL-tree impl --- diff --git a/cds/container/bronson_avltree_map_rcu.h b/cds/container/bronson_avltree_map_rcu.h index d71dd645..59159654 100644 --- a/cds/container/bronson_avltree_map_rcu.h +++ b/cds/container/bronson_avltree_map_rcu.h @@ -104,6 +104,9 @@ namespace cds { namespace container { /// Enabled or disabled @ref bronson_avltree::relaxed_insert "relaxed insertion" static bool const c_bRelaxedInsert = traits::relaxed_insert; + /// Pointer to removed value object + typedef typename base_class::exempt_ptr exempt_ptr; + protected: //@cond typedef typename base_class::node_type node_type; @@ -286,7 +289,7 @@ namespace cds { namespace container { template bool erase( K const& key ) { - //TODO + return base_class::erase( key ); } /// Deletes the item from the map using \p pred predicate for searching @@ -299,8 +302,7 @@ namespace cds { namespace container { template bool erase_with( K const& key, Less pred ) { - CDS_UNUSED( pred ); - //TODO + return base_class::erase_with( key, pred ); } /// Delete \p key from the map @@ -323,7 +325,7 @@ namespace cds { namespace container { template bool erase( K const& key, Func f ) { - //TODO + return base_class::erase( key, f ); } /// Deletes the item from the map using \p pred predicate for searching @@ -336,8 +338,7 @@ namespace cds { namespace container { template bool erase_with( K const& key, Less pred, Func f ) { - CDS_UNUSED( pred ); - //TODO + return base_class::erase_with( key, pred, f ); } /// Extracts an item with minimal key from the map @@ -384,33 +385,32 @@ namespace cds { namespace container { /// Extracts an item from the map /** The function searches an item with key equal to \p key in the tree, - unlinks it, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to an item found. + unlinks it, and returns \p exempt_ptr pointer to a value found. If \p key is not found the function returns an empty \p exempt_ptr. RCU \p synchronize method can be called. RCU should NOT be locked. - The function does not destroy the item found. + The function does not destroy the value found. The dealloctor will be implicitly invoked when the returned object is destroyed or when - its \p release() member function is called. + its \p reset(nullptr) member function is called. */ template exempt_ptr extract( Q const& key ) { - //TODO + return base_class::extract( key ); } /// Extracts an item from the map using \p pred for searching /** - The function is an analog of \p extract(exempt_ptr&, Q const&) + The function is an analog of \p extract(Q const&) but \p pred is used for key compare. \p Less has the interface like \p std::less and should meet \ref cds_container_EllenBinTreeSet_rcu_less "predicate requirements". \p pred must imply the same element order as the comparator used for building the map. */ template - exempt_ptr extract_with( Q const& val, Less pred ) + exempt_ptr extract_with( Q const& key, Less pred ) { - CDS_UNUSED( pred ); - //TODO + return base_class::extract_with( key, pred ); } /// Find the key \p key diff --git a/cds/container/impl/bronson_avltree_map_rcu.h b/cds/container/impl/bronson_avltree_map_rcu.h index 475089b8..17b6e03b 100644 --- a/cds/container/impl/bronson_avltree_map_rcu.h +++ b/cds/container/impl/bronson_avltree_map_rcu.h @@ -3,10 +3,12 @@ #ifndef CDSLIB_CONTAINER_IMPL_BRONSON_AVLTREE_MAP_RCU_H #define CDSLIB_CONTAINER_IMPL_BRONSON_AVLTREE_MAP_RCU_H +#include // unique_ptr #include #include #include + namespace cds { namespace container { /// Bronson et al AVL-tree (RCU specialization for storing pointer to values) @@ -66,6 +68,9 @@ namespace cds { namespace container { /// Enabled or disabled @ref bronson_avltree::relaxed_insert "relaxed insertion" static bool const c_bRelaxedInsert = traits::relaxed_insert; + /// Pointer to removed value object + typedef std::unique_ptr< mapped_type, disposer > exempt_ptr; + protected: //@cond typedef typename sync_monitor::template node_injection< bronson_avltree::node< key_type, mapped_type >> node_type; @@ -250,7 +255,12 @@ namespace cds { namespace container { template bool erase( K const& key ) { - return do_update( key, key_comparator(), []( mapped_type& ) {}, update_flags::allow_remove ) == update_flags::result_removed; + return do_update( + key, + key_comparator(), + []( mapped_type * pVal ) { disposer()(pVal); }, + update_flags::allow_remove + ) == update_flags::result_removed; } /// Deletes the item from the map using \p pred predicate for searching @@ -267,7 +277,7 @@ namespace cds { namespace container { return do_update( key, cds::details::predicate_wrapper(), - []( mapped_type& ) {}, + []( mapped_type * pVal ) { disposer()(pVal); }, update_flags::allow_remove ) == update_flags::result_removed; } @@ -294,7 +304,7 @@ namespace cds { namespace container { return do_update( key, key_comparator(), - [&f]( mapped_type& val ) { f( val ); }, + [&f]( mapped_type * pVal ) { f( *pVal ); disposer()(pVal); }, update_flags::allow_remove ) == update_flags::result_removed; } @@ -313,7 +323,7 @@ namespace cds { namespace container { return do_update( key, cds::details::predicate_wrapper(), - [&f]( mapped_type& val ) { f( val ); }, + [&f]( mapped_type * pVal ) { f( *pVal ); disposer()(pVal); }, update_flags::allow_remove ) == update_flags::result_removed; } @@ -362,33 +372,48 @@ namespace cds { namespace container { /// Extracts an item from the map /** The function searches an item with key equal to \p key in the tree, - unlinks it, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to an item found. + unlinks it, and returns \p exempt_ptr pointer to a value found. If \p key is not found the function returns an empty \p exempt_ptr. RCU \p synchronize method can be called. RCU should NOT be locked. - The function does not destroy the item found. - The dealloctor will be implicitly invoked when the returned object is destroyed or when - its \p release() member function is called. + The function does not destroy the value found. + The disposer will be implicitly invoked when the returned object is destroyed or when + its \p reset(nullptr) member function is called. */ template exempt_ptr extract( Q const& key ) { - //TODO + exempt_ptr pExtracted; + + do_update( + key, + key_comparator(), + [&pExtracted]( mapped_type * pVal ) { pExtracted.reset( pVal ); }, + update_flags::allow_remove + ); + return pExtracted; } /// Extracts an item from the map using \p pred for searching /** - The function is an analog of \p extract(exempt_ptr&, Q const&) + The function is an analog of \p extract(Q const&) but \p pred is used for key compare. - \p Less has the interface like \p std::less and should meet \ref cds_container_EllenBinTreeSet_rcu_less - "predicate requirements". - \p pred must imply the same element order as the comparator used for building the map. + \p Less has the interface like \p std::less. + \p pred must imply the same element order as the comparator used for building the tree. */ template - exempt_ptr extract_with( Q const& val, Less pred ) + exempt_ptr extract_with( Q const& key, Less pred ) { CDS_UNUSED( pred ); - //TODO + exempt_ptr pExtracted; + + do_update( + key, + cds::details::predicate_wrapper(), + [&pExtracted]( mapped_type * pVal ) { pExtracted.reset( pVal ); }, + update_flags::allow_remove + ); + return pExtracted; } /// Find the key \p key @@ -856,8 +881,6 @@ namespace cds { namespace container { if ( !pNode->is_valued( atomics::memory_order_relaxed ) ) return update_flags::failed; - int result = update_flags::retry; - if ( pNode->child( -1, atomics::memory_order_relaxed ) == nullptr || pNode->child( 1, atomics::memory_order_relaxed ) == nullptr ) { @@ -883,14 +906,14 @@ namespace cds { namespace container { pDamaged = fix_height_locked( pParent ); } - func( *pOld ); - disposer()(pOld); + func( pOld ); // calls pOld disposer inside m_stat.onDisposeValue(); fix_height_and_rebalance( pDamaged, disp ); return upfate_flags::result_removed; } else { + int result = update_flags::retry; { node_scoped_lock ln( m_Monitor, *pNode ); mapped_type * pOld = pNode->value( atomics::memory_order_relaxed ); @@ -901,12 +924,12 @@ namespace cds { namespace container { } if ( result == upfate_flags::result_removed ) { - func( *pOld ); - disposer()(pOld); + func( *pOld ); // calls pOld disposer inside m_stat.onDisposeValue(); } + + return result; } - return update_flags::retry; } bool try_unlink_locked( node_type * pParent, node_type * pNode, rcu_disposer& disp )