/// 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;
template <typename K>
bool erase( K const& key )
{
- //TODO
+ return base_class::erase( key );
}
/// Deletes the item from the map using \p pred predicate for searching
template <typename K, typename Less>
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
template <typename K, typename Func>
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
template <typename K, typename Less, typename Func>
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
/// 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 <typename Q>
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 <typename Q, typename Less>
- 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
#ifndef CDSLIB_CONTAINER_IMPL_BRONSON_AVLTREE_MAP_RCU_H
#define CDSLIB_CONTAINER_IMPL_BRONSON_AVLTREE_MAP_RCU_H
+#include <memory> // unique_ptr
#include <cds/container/details/bronson_avltree_base.h>
#include <cds/urcu/details/check_deadlock.h>
#include <cds/details/binary_functor_wrapper.h>
+
namespace cds { namespace container {
/// Bronson et al AVL-tree (RCU specialization for storing pointer to values)
/// 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;
template <typename K>
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
return do_update(
key,
cds::details::predicate_wrapper<key_type, Less, cds::details::trivial_accessor >(),
- []( mapped_type& ) {},
+ []( mapped_type * pVal ) { disposer()(pVal); },
update_flags::allow_remove
) == update_flags::result_removed;
}
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;
}
return do_update(
key,
cds::details::predicate_wrapper<key_type, Less, cds::details::trivial_accessor >(),
- [&f]( mapped_type& val ) { f( val ); },
+ [&f]( mapped_type * pVal ) { f( *pVal ); disposer()(pVal); },
update_flags::allow_remove
) == update_flags::result_removed;
}
/// 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 <typename Q>
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 <typename Q, typename Less>
- 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<key_type, Less, cds::details::trivial_accessor >(),
+ [&pExtracted]( mapped_type * pVal ) { pExtracted.reset( pVal ); },
+ update_flags::allow_remove
+ );
+ return pExtracted;
}
/// Find the key \p key
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 )
{
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 );
}
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 )