EllenBinTree doc fixed
[libcds.git] / cds / intrusive / impl / ellen_bintree.h
index e6f2e9936b9885dce021bc079850f95bdb3b44be..21fd7c29396754ab683316bf9c9e6d5c1e014238 100644 (file)
@@ -1,14 +1,13 @@
 //$$CDS-header$$
 
-#ifndef __CDS_INTRUSIVE_IMPL_ELLEN_BINTREE_H
-#define __CDS_INTRUSIVE_IMPL_ELLEN_BINTREE_H
+#ifndef CDSLIB_INTRUSIVE_IMPL_ELLEN_BINTREE_H
+#define CDSLIB_INTRUSIVE_IMPL_ELLEN_BINTREE_H
 
 #include <memory>
 #include <cds/intrusive/details/ellen_bintree_base.h>
 #include <cds/opt/compare.h>
 #include <cds/details/binary_functor_wrapper.h>
 #include <cds/urcu/details/check_deadlock.h>
-#include <cds/gc/guarded_ptr.h>
 
 namespace cds { namespace intrusive {
 
@@ -34,11 +33,11 @@ namespace cds { namespace intrusive {
         the priority value plus some uniformly distributed random value.
 
         @note In the current implementation we do not use helping technique described in the original paper.
-        In Hazard Pointer schema helping is too complicated and does not give any observable benefits.
+        In Hazard Pointer schema the helping is too complicated and does not give any observable benefits.
         Instead of helping, when a thread encounters a concurrent operation it just spins waiting for
-        the operation done. Such solution allows greatly simplify the implementation of tree.
+        the operation done. Such solution allows greatly simplify implementation of the tree.
 
-        @warning Recall the tree is <b>unbalanced</b>. The complexity of operations is <tt>O(log N)</tt>
+        @attention Recall the tree is <b>unbalanced</b>. The complexity of operations is <tt>O(log N)</tt>
         for uniformly distributed random keys, but in worst case the complexity is <tt>O(N)</tt>.
 
         @note Do not include <tt><cds/intrusive/impl/ellen_bintree.h></tt> header file explicitly.
@@ -119,7 +118,7 @@ namespace cds { namespace intrusive {
         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
+        typedef typename gc::template guarded_ptr< value_type > guarded_ptr; ///< Guarded pointer
 
     protected:
         //@cond
@@ -161,6 +160,8 @@ namespace cds { namespace intrusive {
         typedef typename traits::node_allocator        node_allocator;        ///< Allocator for internal node
         typedef typename traits::update_desc_allocator update_desc_allocator; ///< Update descriptor allocator
 
+        static CDS_CONSTEXPR const size_t c_nHazardPtrCount = 9; ///< Count of hazard pointer required for the algorithm
+
     protected:
         //@cond
         typedef ellen_bintree::details::compare< key_type, value_type, key_comparator, node_traits > node_compare;
@@ -175,9 +176,7 @@ namespace cds { namespace intrusive {
                 Guard_Leaf,
                 Guard_updGrandParent,
                 Guard_updParent,
-
-                // helping
-                Guard_helpLeaf,
+                Guard_temporary,
 
                 // end of guard indices
                 guard_count
@@ -201,11 +200,6 @@ namespace cds { namespace intrusive {
                 ,bRightLeaf( false )
                 ,bRightParent( false )
             {}
-
-            void clean_help_guards()
-            {
-                guards.clear( Guard_helpLeaf );
-            }
         };
         //@endcond
 
@@ -372,20 +366,21 @@ namespace cds { namespace intrusive {
             return true;
         }
 
-        /// Ensures that the \p val exists in the tree
+        /// Updates the node
         /**
             The operation performs inserting or changing data with lock-free manner.
 
-            If the item \p val is not found in the tree, then \p val is inserted into the tree.
+            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 - an item of the tree
-            - \p val - the argument \p val passed to the \p ensure function
+            - \p item - item of the set
+            - \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.
 
@@ -393,13 +388,14 @@ namespace cds { namespace intrusive {
             that during changing no any other modifications could be made on this item by concurrent threads.
 
             Returns std::pair<bool, bool> 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 tree.
+            already exists.
 
             @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename Func>
-        std::pair<bool, bool> ensure( value_type& val, Func func )
+        std::pair<bool, bool> update( value_type& val, Func func, bool bAllowInsert = true )
         {
             typename gc::Guard guardInsert;
             guardInsert.assign( &val );
@@ -418,6 +414,8 @@ namespace cds { namespace intrusive {
                 }
 
                 if ( res.updGrandParent.bits() == update_desc::Clean && res.updParent.bits() == update_desc::Clean )  {
+                    if ( !bAllowInsert )
+                        return std::make_pair( false, false );
 
                     if ( !pNewInternal.get() )
                         pNewInternal.reset( alloc_internal_node() );
@@ -437,6 +435,14 @@ namespace cds { namespace intrusive {
             m_Stat.onEnsureNew();
             return std::make_pair( true, true );
         }
+        //@cond
+        template <typename Func>
+        CDS_DEPRECATED("ensure() is deprecated, use update()")
+        std::pair<bool, bool> ensure( value_type& val, Func func )
+        {
+            return update( val, func, true );
+        }
+        //@endcond
 
         /// Unlinks the item \p val from the tree
         /**
@@ -486,6 +492,7 @@ namespace cds { namespace intrusive {
         template <typename Q, typename Less>
         bool erase_with( const Q& key, Less pred )
         {
+            CDS_UNUSED( pred );
             typedef ellen_bintree::details::compare<
                 key_type,
                 value_type,
@@ -535,6 +542,7 @@ namespace cds { namespace intrusive {
         template <typename Q, typename Less, typename Func>
         bool erase_with( Q const& key, Less pred, Func f )
         {
+            CDS_UNUSED( pred );
             typedef ellen_bintree::details::compare<
                 key_type,
                 value_type,
@@ -549,82 +557,87 @@ namespace cds { namespace intrusive {
 
         /// Extracts an item with minimal key from the tree
         /**
-            The function searches an item with minimal key, unlinks it, and returns pointer to an item found in \p dest parameter.
-            If the tree is empty the function returns \p false.
+            The function searches an item with minimal key, unlinks it, and returns a guarded pointer to an item found.
+            If the tree is empty the function returns an empty guarded pointer.
 
             @note Due the concurrent nature of the tree, the function extracts <i>nearly</i> minimum key.
             It means that the function gets leftmost leaf of the tree and tries to unlink it.
             During unlinking, a concurrent thread may insert an item with key less than leftmost item's key.
             So, the function returns the item with minimum key at the moment of tree traversing.
 
-            The guarded pointer \p dest prevents disposer invocation for returned item,
-            see cds::gc::guarded_ptr for explanation.
+            The returned \p guarded_ptr prevents disposer invocation for returned item,
+            see \p cds::gc::guarded_ptr for explanation.
             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
         */
-        bool extract_min( guarded_ptr& dest )
+        guarded_ptr extract_min()
         {
-            return extract_min_( dest.guard());
+            guarded_ptr gp;
+            extract_min_( gp.guard() );
+            return gp;
         }
 
         /// Extracts an item with maximal key from the tree
         /**
-            The function searches an item with maximal key, unlinks it, and returns pointer to an item found in \p dest parameter.
-            If the tree is empty the function returns \p false.
+            The function searches an item with maximal key, unlinks it, and returns a guarded pointer to an item found.
+            If the tree is empty the function returns an empty \p guarded_ptr.
 
             @note Due the concurrent nature of the tree, the function extracts <i>nearly</i> maximal key.
             It means that the function gets rightmost leaf of the tree and tries to unlink it.
             During unlinking, a concurrent thread may insert an item with key great than rightmost item's key.
             So, the function returns the item with maximal key at the moment of tree traversing.
 
-            The guarded pointer \p dest prevents disposer invocation for returned item,
+            The returned \p guarded_ptr prevents disposer invocation for returned item,
             see cds::gc::guarded_ptr for explanation.
             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
         */
-        bool extract_max( guarded_ptr& dest )
+        guarded_ptr extract_max()
         {
-            return extract_max_( dest.guard() );
+            guarded_ptr gp;
+            extract_max_( gp.guard());
+            return gp;
         }
 
         /// Extracts an item from the tree
         /** \anchor cds_intrusive_EllenBinTree_extract
             The function searches an item with key equal to \p key in the tree,
-            unlinks it, and returns pointer to an item found in \p dest parameter.
-            If the item  is not found the function returns \p false.
+            unlinks it, and returns a guarded pointer to an item found.
+            If the item  is not found the function returns an empty \p guarded_ptr.
 
-            The guarded pointer \p dest prevents disposer invocation for returned item,
+            \p guarded_ptr prevents disposer invocation for returned item,
             see cds::gc::guarded_ptr for explanation.
             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
         */
         template <typename Q>
-        bool extract( guarded_ptr& dest, Q const& key )
+        guarded_ptr extract( Q const& key )
         {
-            return extract_( dest.guard(), key );
+            guarded_ptr gp;
+            extract_( gp.guard(), key );
+            return gp;
         }
 
         /// Extracts an item from the tree using \p pred for searching
         /**
-            The function is an analog of \ref cds_intrusive_EllenBinTree_extract "extract(guarded_ptr& dest, Q const&)"
+            The function is an analog of \ref cds_intrusive_EllenBinTree_extract "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_intrusive_EllenBinTree_less
             "Predicate requirements".
             \p pred must imply the same element order as the comparator used for building the tree.
         */
         template <typename Q, typename Less>
-        bool extract_with( guarded_ptr& dest, Q const& key, Less pred )
+        guarded_ptr extract_with( Q const& key, Less pred )
         {
-            return extract_with_( dest.guard(), key, pred );
+            guarded_ptr gp;
+            extract_with_( gp.guard(), key, pred );
+            return gp;
         }
 
-        /// Finds the key \p key
-        /** @anchor cds_intrusive_EllenBinTree_find_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 <typename Q>
-        bool find( Q const& key ) const
+        bool contains( Q const& key ) const
         {
             search_result    res;
             if ( search( res, key, node_compare() )) {
@@ -635,19 +648,25 @@ namespace cds { namespace intrusive {
             m_Stat.onFindFailed();
             return false;
         }
+        //@cond
+        template <typename Q>
+        CDS_DEPRECATED("deprecated, use contains()")
+        bool find( Q const& key ) const
+        {
+            return contains( key );
+        }
+        //@endcond
 
-        /// Finds the key \p key with comparing functor \p pred
+        /// Checks whether the set contains \p key using \p pred predicate for searching
         /**
-            The function is an analog of \ref cds_intrusive_EllenBinTree_find_val "find(Q const&)"
-            but \p pred is used for key compare.
-            \p Less functor has the interface like \p std::less and should meet \ref cds_intrusive_EllenBinTree_less
-            "Predicate requirements".
-            \p pred must imply the same element order as the comparator used for building the tree.
-            \p pred should accept arguments of type \p Q, \p key_type, \p value_type in any combination.
+            The function is similar to <tt>contains( key )</tt> 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 <typename Q, typename Less>
-        bool find_with( Q const& key, Less pred ) const
+        bool contains( Q const& key, Less pred ) const
         {
+            CDS_UNUSED( pred );
             typedef ellen_bintree::details::compare<
                 key_type,
                 value_type,
@@ -663,6 +682,14 @@ namespace cds { namespace intrusive {
             m_Stat.onFindFailed();
             return false;
         }
+        //@cond
+        template <typename Q, typename Less>
+        CDS_DEPRECATED("deprecated, use contains()")
+        bool find_with( Q const& key, Less pred ) const
+        {
+            return contains( key, pred );
+        }
+        //@endcond
 
         /// Finds the key \p key
         /** @anchor cds_intrusive_EllenBinTree_find_func
@@ -718,31 +745,35 @@ namespace cds { namespace intrusive {
 
         /// Finds \p key and returns the item found
         /** @anchor cds_intrusive_EllenBinTree_get
-            The function searches the item with key equal to \p key and returns the item found in \p dest parameter.
-            The function returns \p true if \p key is found, \p false otherwise.
+            The function searches the item with key equal to \p key and returns the item found as \p guarded_ptr object.
+            The function returns an empty guarded pointer is \p key is not found.
 
-            The guarded pointer \p dest prevents disposer invocation for returned item,
-            see cds::gc::guarded_ptr for explanation.
+            \p guarded_ptr prevents disposer invocation for returned item,
+            see \p cds::gc::guarded_ptr for explanation.
             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
         */
         template <typename Q>
-        bool get( guarded_ptr& dest, Q const& key ) const
+        guarded_ptr get( Q const& key ) const
         {
-            return get_( dest.guard(), key );
+            guarded_ptr gp;
+            get_( gp.guard(), key );
+            return gp;
         }
 
         /// Finds \p key with predicate \p pred and returns the item found
         /**
-            The function is an analog of \ref cds_intrusive_EllenBinTree_get "get(guarded_ptr&, Q const&)"
+            The function is an analog of \ref cds_intrusive_EllenBinTree_get "get(Q const&)"
             but \p pred is used for key comparing.
             \p Less functor has the interface like \p std::less and should meet \ref cds_intrusive_EllenBinTree_less
             "Predicate requirements".
             \p pred must imply the same element order as the comparator used for building the tree.
         */
         template <typename Q, typename Less>
-        bool get_with( guarded_ptr& dest, Q const& key, Less pred ) const
+        guarded_ptr get_with( Q const& key, Less pred ) const
         {
-            return get_with_( dest.guard(), key, pred );
+            guarded_ptr gp;
+            get_with_( gp.guard(), key, pred );
+            return gp;
         }
 
         /// Checks if the tree is empty
@@ -767,7 +798,9 @@ namespace cds { namespace intrusive {
         void clear()
         {
             guarded_ptr gp;
-            while ( extract_min(gp));
+            do {
+                gp = extract_min();
+            }  while ( gp );
         }
 
         /// Clears the tree (not thread safe)
@@ -864,14 +897,21 @@ namespace cds { namespace intrusive {
 
         tree_node * protect_child_node( search_result& res, internal_node * pParent, bool bRight, update_ptr updParent ) const
         {
-            tree_node * p;
-            tree_node * pn = bRight ? pParent->m_pRight.load( memory_model::memory_order_relaxed ) : pParent->m_pLeft.load( memory_model::memory_order_relaxed );
-            do {
-                p = pn;
-                res.guards.assign( search_result::Guard_Leaf, static_cast<internal_node *>( p ));
-                res.guards.assign( search_result::Guard_helpLeaf, node_traits::to_value_ptr( static_cast<leaf_node *>( p ) ));
-                pn = bRight ? pParent->m_pRight.load( memory_model::memory_order_acquire ) : pParent->m_pLeft.load( memory_model::memory_order_acquire );
-            } while ( p != pn );
+        retry:
+            tree_node * p = bRight
+                ? res.guards.protect( search_result::Guard_Leaf, pParent->m_pRight,
+                    []( tree_node * p ) -> internal_node* { return static_cast<internal_node *>(p);})
+                : res.guards.protect( search_result::Guard_Leaf, pParent->m_pLeft,
+                    []( tree_node * p ) -> internal_node* { return static_cast<internal_node *>(p);});
+
+            // If we use member hook, data node pointer != internal node pointer
+            // So, we need protect the child twice: as internal node and as data node
+            // and then analyze what kind of node we have
+            tree_node * pVal = bRight
+                ? res.guards.protect( search_result::Guard_temporary, pParent->m_pRight,
+                    []( tree_node * p ) -> value_type* { return node_traits::to_value_ptr( static_cast<leaf_node *>(p));} )
+                : res.guards.protect( search_result::Guard_temporary, pParent->m_pLeft,
+                    []( tree_node * p ) -> value_type* { return node_traits::to_value_ptr( static_cast<leaf_node *>(p));} );
 
             // child node is guarded
             // See whether pParent->m_pUpdate has not been changed
@@ -880,21 +920,20 @@ namespace cds { namespace intrusive {
                 return nullptr;
             }
 
-            if ( p && p->is_leaf() )
-                res.guards.copy( search_result::Guard_Leaf, search_result::Guard_helpLeaf );
-            res.guards.clear( search_result::Guard_helpLeaf );
+            if ( p != pVal )
+                goto retry;
+
+            if ( p && p->is_leaf())
+                res.guards.assign( search_result::Guard_Leaf, node_traits::to_value_ptr( static_cast<leaf_node *>( p )));
+
+            res.guards.clear( search_result::Guard_temporary );
+
             return p;
         }
 
-        update_ptr search_protect_update( search_result& res, atomics::atomic<update_ptr> const& src ) const
+        static update_ptr search_protect_update( search_result& res, atomics::atomic<update_ptr> const& src )
         {
-            update_ptr ret;
-            update_ptr upd( src.load( memory_model::memory_order_relaxed ) );
-            do {
-                ret = upd;
-                res.guards.assign( search_result::Guard_updParent, upd );
-            } while ( ret != (upd = src.load( memory_model::memory_order_acquire )) );
-            return ret;
+            return res.guards.protect( search_result::Guard_updParent, src, [](update_ptr p) -> update_desc* { return p.ptr(); });
         }
 
         template <typename KeyValue, typename Compare>
@@ -1111,18 +1150,8 @@ namespace cds { namespace intrusive {
 
             assert( res.pGrandParent != nullptr );
 
-            return
-                static_cast<internal_node *>(
-                    res.bRightParent
-                        ? res.pGrandParent->m_pRight.load(memory_model::memory_order_relaxed)
-                        : res.pGrandParent->m_pLeft.load(memory_model::memory_order_relaxed)
-                    ) == res.pParent
-                &&
-                static_cast<leaf_node *>(
-                    res.bRightLeaf
-                        ? res.pParent->m_pRight.load(memory_model::memory_order_relaxed)
-                        : res.pParent->m_pLeft.load(memory_model::memory_order_relaxed)
-                ) == res.pLeaf;
+            return static_cast<internal_node *>(res.pGrandParent->get_child( res.bRightParent, memory_model::memory_order_relaxed )) == res.pParent
+                && static_cast<leaf_node *>( res.pParent->get_child( res.bRightLeaf, memory_model::memory_order_relaxed )) == res.pLeaf;
         }
 
         bool help_delete( update_desc * pOp )
@@ -1159,21 +1188,11 @@ namespace cds { namespace intrusive {
             }
         }
 
-        tree_node * protect_sibling( typename gc::Guard& guard, atomics::atomic<tree_node *>& sibling )
+        static tree_node * protect_sibling( typename gc::Guard& guard, atomics::atomic<tree_node *>& sibling )
         {
-            typename gc::Guard guardLeaf;
-
-            tree_node * pSibling;
-            tree_node * p = sibling.load( memory_model::memory_order_relaxed );
-            do {
-                pSibling = p;
-                guard.assign( static_cast<internal_node *>(p) );
-                guardLeaf.assign( node_traits::to_value_ptr( static_cast<leaf_node *>(p)));
-            } while ( pSibling != ( p = sibling.load( memory_model::memory_order_acquire )) );
-
+            tree_node * pSibling = guard.protect( sibling, [](tree_node * p) -> internal_node* { return static_cast<internal_node *>(p); } );
             if ( pSibling->is_leaf() )
-                guard.copy( guardLeaf );
-
+                guard.assign( node_traits::to_value_ptr( static_cast<leaf_node *>( pSibling )));
             return pSibling;
         }
 
@@ -1206,9 +1225,7 @@ namespace cds { namespace intrusive {
             assert( res.pLeaf->is_leaf() );
 
             // check search result
-            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 ) {
+            if ( res.pParent->get_child( res.bRightLeaf, memory_model::memory_order_acquire ) == res.pLeaf ) {
                 leaf_node * pNewLeaf = node_traits::to_node_ptr( val );
 
                 int nCmp = node_compare()(val, *res.pLeaf);
@@ -1227,8 +1244,8 @@ namespace cds { namespace intrusive {
                 }
                 else {
                     assert( !res.pLeaf->is_internal() );
-                    pNewInternal->infinite_key( 0 );
 
+                    pNewInternal->infinite_key( 0 );
                     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 );
@@ -1313,15 +1330,15 @@ namespace cds { namespace intrusive {
         }
 
         template <typename Q>
-        bool extract_( typename gc::Guard& guard, Q const& key )
+        bool extract_( typename guarded_ptr::native_guard& guard, Q const& key )
         {
             return erase_( key, node_compare(),
                 []( Q const&, leaf_node const& ) -> bool { return true; },
-                [&guard]( value_type& found ) { guard.assign( &found ); } );
+                [&guard]( value_type& found ) { guard.set( &found ); } );
         }
 
         template <typename Q, typename Less>
-        bool extract_with_( typename gc::Guard& guard, Q const& key, Less pred )
+        bool extract_with_( typename guarded_ptr::native_guard& guard, Q const& key, Less /*pred*/ )
         {
             typedef ellen_bintree::details::compare<
                 key_type,
@@ -1332,10 +1349,10 @@ namespace cds { namespace intrusive {
 
             return erase_( key, compare_functor(),
                 []( Q const&, leaf_node const& ) -> bool { return true; },
-                [&guard]( value_type& found ) { guard.assign( &found ); } );
+                [&guard]( value_type& found ) { guard.set( &found ); } );
         }
 
-        bool extract_max_( typename gc::Guard& guard )
+        bool extract_max_( typename guarded_ptr::native_guard& gp )
         {
             update_desc * pOp = nullptr;
             search_result res;
@@ -1366,7 +1383,7 @@ namespace cds { namespace intrusive {
 
                         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 ) )
                                 break;
@@ -1381,11 +1398,11 @@ namespace cds { namespace intrusive {
 
             --m_ItemCounter;
             m_Stat.onExtractMaxSuccess();
-            guard.assign( node_traits::to_value_ptr( res.pLeaf ) );
+            gp.set( node_traits::to_value_ptr( res.pLeaf ));
             return true;
         }
 
-        bool extract_min_( typename gc::Guard& guard )
+        bool extract_min_( typename guarded_ptr::native_guard& gp )
         {
             update_desc * pOp = nullptr;
             search_result res;
@@ -1431,7 +1448,7 @@ namespace cds { namespace intrusive {
 
             --m_ItemCounter;
             m_Stat.onExtractMinSuccess();
-            guard.assign( node_traits::to_value_ptr( res.pLeaf ));
+            gp.set( node_traits::to_value_ptr( res.pLeaf ));
             return true;
         }
 
@@ -1452,7 +1469,7 @@ namespace cds { namespace intrusive {
         }
 
         template <typename Q, typename Less, typename Func>
-        bool find_with_( Q& val, Less pred, Func f ) const
+        bool find_with_( Q& val, Less /*pred*/, Func f ) const
         {
             typedef ellen_bintree::details::compare<
                 key_type,
@@ -1475,15 +1492,15 @@ namespace cds { namespace intrusive {
         }
 
         template <typename Q>
-        bool get_( typename gc::Guard& guard, Q const& val ) const
+        bool get_( typename guarded_ptr::native_guard& guard, Q const& val ) const
         {
-            return find_( val, [&guard]( value_type& found, Q const& ) { guard.assign( &found ); } );
+            return find_( val, [&guard]( value_type& found, Q const& ) { guard.set( &found ); } );
         }
 
         template <typename Q, typename Less>
-        bool get_with_( typename gc::Guard& guard, Q const& val, Less pred ) const
+        bool get_with_( typename guarded_ptr::native_guard& guard, Q const& val, Less pred ) const
         {
-            return find_with_( val, pred, [&guard]( value_type& found, Q const& ) { guard.assign( &found ); } );
+            return find_with_( val, pred, [&guard]( value_type& found, Q const& ) { guard.set( &found ); } );
         }
 
         //@endcond
@@ -1491,4 +1508,4 @@ namespace cds { namespace intrusive {
 
 }} // namespace cds::intrusive
 
-#endif // #ifndef __CDS_INTRUSIVE_IMPL_ELLEN_BINTREE_H
+#endif // #ifndef CDSLIB_INTRUSIVE_IMPL_ELLEN_BINTREE_H