@note Do not include <tt><cds/intrusive/impl/ellen_bintree.h></tt> header file explicitly.
There are header file for each GC type:
- <tt><cds/intrusive/ellen_bintree_hp.h></tt> - for Hazard Pointer GC \p cds::gc::HP
- - <tt><cds/intrusive/ellen_bintree_dhp.h></tt> - for Pass-the-Buck GC \p cds::gc::DHP
+ - <tt><cds/intrusive/ellen_bintree_dhp.h></tt> - for Dynamic Hazard Pointer GC \p cds::gc::DHP
- <tt><cds/intrusive/ellen_bintree_rcu.h></tt> - for RCU (see \ref cds_intrusive_EllenBinTree_rcu "RCU-based EllenBinTree")
<b>Template arguments</b> :
typedef typename traits::hook hook; ///< hook type
typedef typename hook::node_type node_type; ///< node type
typedef typename traits::disposer disposer; ///< leaf node disposer
+ typedef typename traits::back_off back_off; ///< back-off strategy
typedef cds::gc::guarded_ptr< gc, value_type > guarded_ptr; ///< Guarded pointer
guardInsert.assign( &val );
unique_internal_node_ptr pNewInternal;
-
search_result res;
+ back_off bkoff;
+
for ( ;; ) {
if ( search( res, val, node_compare() )) {
if ( pNewInternal.get() )
}
}
+ bkoff();
m_Stat.onInsertRetry();
}
guardInsert.assign( &val );
unique_internal_node_ptr pNewInternal;
-
search_result res;
+ back_off bkoff;
+
for ( ;; ) {
if ( search( res, val, node_compare() )) {
func( false, *node_traits::to_value_ptr( res.pLeaf ), val );
break;
}
}
+
+ bkoff();
m_Stat.onEnsureRetry();
}
return true;
}
+ /*
void help( update_ptr pUpdate )
{
// pUpdate must be guarded!
break;
}
}
+ */
void help_insert( update_desc * pOp )
{
assert( res.pLeaf->is_leaf() );
// check search result
- if ( ( res.bRightLeaf
+ if ( (res.bRightLeaf
? res.pParent->m_pRight.load( memory_model::memory_order_acquire )
- : res.pParent->m_pLeft.load( memory_model::memory_order_acquire ) ) == res.pLeaf )
- {
+ : res.pParent->m_pLeft.load( memory_model::memory_order_acquire )) == res.pLeaf ) {
leaf_node * pNewLeaf = node_traits::to_node_ptr( val );
- int nCmp = node_compare()( val, *res.pLeaf );
+ int nCmp = node_compare()(val, *res.pLeaf);
if ( nCmp < 0 ) {
if ( res.pGrandParent ) {
assert( !res.pLeaf->infinite_key() );
pNewInternal->infinite_key( 0 );
- key_extractor()( pNewInternal->m_Key, *node_traits::to_value_ptr( res.pLeaf ) );
+ key_extractor()(pNewInternal->m_Key, *node_traits::to_value_ptr( res.pLeaf ));
}
else {
assert( res.pLeaf->infinite_key() == tree_node::key_infinite1 );
assert( !res.pLeaf->is_internal() );
pNewInternal->infinite_key( 0 );
- key_extractor()( pNewInternal->m_Key, val );
+ key_extractor()(pNewInternal->m_Key, val);
pNewInternal->m_pLeft.store( static_cast<tree_node *>(res.pLeaf), memory_model::memory_order_relaxed );
pNewInternal->m_pRight.store( static_cast<tree_node *>(pNewLeaf), memory_model::memory_order_release );
- assert( !res.pLeaf->infinite_key());
+ assert( !res.pLeaf->infinite_key() );
}
typename gc::Guard guard;
update_ptr updCur( res.updParent.ptr() );
if ( res.pParent->m_pUpdate.compare_exchange_strong( updCur, update_ptr( pOp, update_desc::IFlag ),
- memory_model::memory_order_acquire, atomics::memory_order_relaxed ))
- {
+ memory_model::memory_order_acquire, atomics::memory_order_relaxed ) ) {
// do insert
help_insert( pOp );
retire_update_desc( pOp );
free_update_desc( pOp );
}
}
+
return false;
}
{
update_desc * pOp = nullptr;
search_result res;
+ back_off bkoff;
for ( ;; ) {
if ( !search( res, val, cmp ) || !eq( val, *res.pLeaf ) ) {
update_ptr updGP( res.updGrandParent.ptr() );
if ( res.pGrandParent->m_pUpdate.compare_exchange_strong( updGP, update_ptr( pOp, update_desc::DFlag ),
- memory_model::memory_order_acquire, atomics::memory_order_relaxed ))
- {
- if ( help_delete( pOp )) {
+ memory_model::memory_order_acquire, atomics::memory_order_relaxed ) ) {
+ if ( help_delete( pOp ) ) {
// res.pLeaf is not deleted yet since it is guarded
- f( *node_traits::to_value_ptr( res.pLeaf ));
+ f( *node_traits::to_value_ptr( res.pLeaf ) );
break;
}
pOp = nullptr;
}
}
+ bkoff();
m_Stat.onEraseRetry();
}
{
update_desc * pOp = nullptr;
search_result res;
+ back_off bkoff;
for ( ;; ) {
if ( !search_max( res )) {
return false;
}
- if ( res.updGrandParent.bits() == update_desc::Clean && res.updParent.bits() == update_desc::Clean ) {
+ if ( res.updGrandParent.bits() == update_desc::Clean && res.updParent.bits() == update_desc::Clean ) {
if ( !pOp )
pOp = alloc_update_desc();
if ( check_delete_precondition( res ) ) {
update_ptr updGP( res.updGrandParent.ptr() );
if ( res.pGrandParent->m_pUpdate.compare_exchange_strong( updGP, update_ptr( pOp, update_desc::DFlag ),
- memory_model::memory_order_acquire, atomics::memory_order_relaxed ))
+ memory_model::memory_order_acquire, atomics::memory_order_relaxed ) )
{
- if ( help_delete( pOp ))
+ if ( help_delete( pOp ) )
break;
pOp = nullptr;
}
}
}
+ bkoff();
m_Stat.onExtractMaxRetry();
}
{
update_desc * pOp = nullptr;
search_result res;
+ back_off bkoff;
for ( ;; ) {
if ( !search_min( res )) {
}
}
+ bkoff();
m_Stat.onExtractMinRetry();
}