Fixed UBsan warning "call to function through pointer to incorrect function type"
[libcds.git] / cds / intrusive / impl / ellen_bintree.h
index f8f086331b0e524b296ce0a4203fa8ba038bb86b..f935c13f5d9ce65dd122be34494bf050e59e4482 100644 (file)
@@ -1,11 +1,11 @@
 /*
     This file is a part of libcds - Concurrent Data Structures library
 
-    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
 
     Source code repo: http://github.com/khizmax/libcds/
     Download: http://sourceforge.net/projects/libcds/files/
-    
+
     Redistribution and use in source and binary forms, with or without
     modification, are permitted provided that the following conditions are met:
 
@@ -25,7 +25,7 @@
     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.     
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 #ifndef CDSLIB_INTRUSIVE_IMPL_ELLEN_BINTREE_H
@@ -168,13 +168,13 @@ namespace cds { namespace intrusive {
         {
             static internal_node const& to_internal_node( tree_node const& n )
             {
-                assert( n.is_internal() );
+                assert( n.is_internal());
                 return static_cast<internal_node const&>( n );
             }
 
             static leaf_node const& to_leaf_node( tree_node const& n )
             {
-                assert( n.is_leaf() );
+                assert( n.is_leaf());
                 return static_cast<leaf_node const&>( n );
             }
         };
@@ -243,9 +243,9 @@ namespace cds { namespace intrusive {
 
     protected:
         //@cond
-        static void free_leaf_node( value_type * p )
+        static void free_leaf_node( void* p )
         {
-            disposer()( );
+            disposer()( reinterpret_cast<value_type*>( p ));
         }
 
         internal_node * alloc_internal_node() const
@@ -255,15 +255,15 @@ namespace cds { namespace intrusive {
             return pNode;
         }
 
-        static void free_internal_node( internal_node * pNode )
+        static void free_internal_node( void* pNode )
         {
-            cxx_node_allocator().Delete( pNode );
+            cxx_node_allocator().Delete( reinterpret_cast<internal_node*>( pNode ));
         }
 
         struct internal_node_deleter {
-            void operator()( internal_node * p) const
+            void operator()( internal_node* p) const
             {
-                free_internal_node( p );
+                cxx_node_allocator().Delete( p );
             }
         };
 
@@ -275,14 +275,14 @@ namespace cds { namespace intrusive {
             return cxx_update_desc_allocator().New();
         }
 
-        static void free_update_desc( update_desc * pDesc )
+        static void free_update_desc( void* pDesc )
         {
-            cxx_update_desc_allocator().Delete( pDesc );
+            cxx_update_desc_allocator().Delete( reinterpret_cast<update_desc*>( pDesc ));
         }
 
         void retire_node( tree_node * pNode ) const
         {
-            if ( pNode->is_leaf() ) {
+            if ( pNode->is_leaf()) {
                 assert( static_cast<leaf_node *>( pNode ) != &m_LeafInf1 );
                 assert( static_cast<leaf_node *>( pNode ) != &m_LeafInf2 );
 
@@ -366,8 +366,8 @@ namespace cds { namespace intrusive {
             back_off bkoff;
 
             for ( ;; ) {
-                if ( search( res, val, node_compare() )) {
-                    if ( pNewInternal.get() )
+                if ( search( res, val, node_compare())) {
+                    if ( pNewInternal.get())
                         m_Stat.onInternalNodeDeleted() ;    // unique_internal_node_ptr deletes internal node
                     m_Stat.onInsertFailed();
                     return false;
@@ -375,8 +375,8 @@ namespace cds { namespace intrusive {
 
                 if ( res.updGrandParent.bits() == update_desc::Clean && res.updParent.bits() == update_desc::Clean ) {
 
-                    if ( !pNewInternal.get() )
-                        pNewInternal.reset( alloc_internal_node() );
+                    if ( !pNewInternal.get())
+                        pNewInternal.reset( alloc_internal_node());
 
                     if ( try_insert( val, pNewInternal.get(), res )) {
                         f( val );
@@ -433,9 +433,9 @@ namespace cds { namespace intrusive {
             back_off bkoff;
 
             for ( ;; ) {
-                if ( search( res, val, node_compare() )) {
+                if ( search( res, val, node_compare())) {
                     func( false, *node_traits::to_value_ptr( res.pLeaf ), val );
-                    if ( pNewInternal.get() )
+                    if ( pNewInternal.get())
                         m_Stat.onInternalNodeDeleted() ;    // unique_internal_node_ptr deletes internal node
                     m_Stat.onUpdateExist();
                     return std::make_pair( true, false );
@@ -445,8 +445,8 @@ namespace cds { namespace intrusive {
                     if ( !bAllowInsert )
                         return std::make_pair( false, false );
 
-                    if ( !pNewInternal.get() )
-                        pNewInternal.reset( alloc_internal_node() );
+                    if ( !pNewInternal.get())
+                        pNewInternal.reset( alloc_internal_node());
 
                     if ( try_insert( val, pNewInternal.get(), res )) {
                         func( true, val, val );
@@ -499,7 +499,7 @@ namespace cds { namespace intrusive {
             unlinks it from the tree, and returns \p true.
             If the item with key equal to \p key is not found the function return \p false.
 
-            Note the \p Traits::less and/or \p Traits::compare predicate should accept a parameter of type \p Q 
+            Note the \p Traits::less and/or \p Traits::compare predicate should accept a parameter of type \p Q
             that can be not the same as \p value_type.
         */
         template <typename Q>
@@ -550,7 +550,7 @@ namespace cds { namespace intrusive {
 
             If the item with key equal to \p key is not found the function return \p false.
 
-            Note the \p Traits::less and/or \p Traits::compare predicate should accept a parameter of type \p Q 
+            Note the \p Traits::less and/or \p Traits::compare predicate should accept a parameter of type \p Q
             that can be not the same as \p value_type.
         */
         template <typename Q, typename Func>
@@ -601,9 +601,7 @@ namespace cds { namespace intrusive {
         */
         guarded_ptr extract_min()
         {
-            guarded_ptr gp;
-            extract_min_( gp.guard() );
-            return gp;
+            return extract_min_();
         }
 
         /// Extracts an item with maximal key from the tree
@@ -622,9 +620,7 @@ namespace cds { namespace intrusive {
         */
         guarded_ptr extract_max()
         {
-            guarded_ptr gp;
-            extract_max_( gp.guard());
-            return gp;
+            return extract_max_();
         }
 
         /// Extracts an item from the tree
@@ -640,9 +636,7 @@ namespace cds { namespace intrusive {
         template <typename Q>
         guarded_ptr extract( Q const& key )
         {
-            guarded_ptr gp;
-            extract_( gp.guard(), key );
-            return gp;
+            return extract_( key );
         }
 
         /// Extracts an item from the tree using \p pred for searching
@@ -656,9 +650,7 @@ namespace cds { namespace intrusive {
         template <typename Q, typename Less>
         guarded_ptr extract_with( Q const& key, Less pred )
         {
-            guarded_ptr gp;
-            extract_with_( gp.guard(), key, pred );
-            return gp;
+            return extract_with_( key, pred );
         }
 
         /// Checks whether the set contains \p key
@@ -670,7 +662,7 @@ namespace cds { namespace intrusive {
         bool contains( Q const& key ) const
         {
             search_result    res;
-            if ( search( res, key, node_compare() )) {
+            if ( search( res, key, node_compare())) {
                 m_Stat.onFindSuccess();
                 return true;
             }
@@ -705,7 +697,7 @@ namespace cds { namespace intrusive {
             > compare_functor;
 
             search_result    res;
-            if ( search( res, key, compare_functor() )) {
+            if ( search( res, key, compare_functor())) {
                 m_Stat.onFindSuccess();
                 return true;
             }
@@ -785,9 +777,7 @@ namespace cds { namespace intrusive {
         template <typename Q>
         guarded_ptr get( Q const& key ) const
         {
-            guarded_ptr gp;
-            get_( gp.guard(), key );
-            return gp;
+            return get_( key );
         }
 
         /// Finds \p key with predicate \p pred and returns the item found
@@ -801,9 +791,7 @@ namespace cds { namespace intrusive {
         template <typename Q, typename Less>
         guarded_ptr get_with( Q const& key, Less pred ) const
         {
-            guarded_ptr gp;
-            get_with_( gp.guard(), key, pred );
-            return gp;
+            return get_with_( key, pred );
         }
 
         /// Checks if the tree is empty
@@ -819,7 +807,7 @@ namespace cds { namespace intrusive {
             this sequence
             \code
             tree.clear();
-            assert( tree.empty() );
+            assert( tree.empty());
             \endcode
             the assertion could be raised.
 
@@ -846,7 +834,7 @@ namespace cds { namespace intrusive {
                 tree_node *     pLeaf = const_cast<internal_node *>( &m_Root );
 
                 // Get leftmost leaf
-                while ( pLeaf->is_internal() ) {
+                while ( pLeaf->is_internal()) {
                     pGrandParent = pParent;
                     pParent = static_cast<internal_node *>( pLeaf );
                     pLeaf = pParent->m_pLeft.load( memory_model::memory_order_relaxed );
@@ -860,10 +848,10 @@ namespace cds { namespace intrusive {
                 // Remove leftmost leaf and its parent node
                 assert( pGrandParent );
                 assert( pParent );
-                assert( pLeaf->is_leaf() );
+                assert( pLeaf->is_leaf());
 
                 pGrandParent->m_pLeft.store( pParent->m_pRight.load( memory_model::memory_order_relaxed ), memory_model::memory_order_relaxed );
-                free_leaf_node( node_traits::to_value_ptr( static_cast<leaf_node *>( pLeaf ) ) );
+                free_leaf_node( node_traits::to_value_ptr( static_cast<leaf_node *>( pLeaf )));
                 free_internal_node( pParent );
             }
         }
@@ -912,11 +900,11 @@ namespace cds { namespace intrusive {
                 && node_compare()( *pLeft, *pRight ) < 0 )
             {
                 bool bRet = true;
-                if ( pLeft->is_internal() )
-                    bRet = check_consistency( static_cast<internal_node *>( pLeft ) );
+                if ( pLeft->is_internal())
+                    bRet = check_consistency( static_cast<internal_node *>( pLeft ));
                 assert( bRet );
 
-                if ( bRet && pRight->is_internal() )
+                if ( bRet && pRight->is_internal())
                     bRet = bRet && check_consistency( static_cast<internal_node *>( pRight ));
                 assert( bRet );
 
@@ -984,7 +972,7 @@ namespace cds { namespace intrusive {
             updParent = nullptr;
             bRightLeaf = false;
             tree_node * pLeaf = const_cast<internal_node *>( &m_Root );
-            while ( pLeaf->is_internal() ) {
+            while ( pLeaf->is_internal()) {
                 res.guards.copy( search_result::Guard_GrandParent, search_result::Guard_Parent );
                 pGrandParent = pParent;
                 res.guards.copy( search_result::Guard_Parent, search_result::Guard_Leaf );
@@ -995,7 +983,7 @@ namespace cds { namespace intrusive {
 
                 updParent = search_protect_update( res, pParent->m_pUpdate );
 
-                switch ( updParent.bits() ) {
+                switch ( updParent.bits()) {
                     case update_desc::DFlag:
                     case update_desc::Mark:
                         m_Stat.onSearchRetry();
@@ -1012,8 +1000,8 @@ namespace cds { namespace intrusive {
                 }
             }
 
-            assert( pLeaf->is_leaf() );
-            nCmp = cmp( key, *static_cast<leaf_node *>(pLeaf) );
+            assert( pLeaf->is_leaf());
+            nCmp = cmp( key, *static_cast<leaf_node *>(pLeaf));
 
             res.pGrandParent    = pGrandParent;
             res.pParent         = pParent;
@@ -1038,7 +1026,7 @@ namespace cds { namespace intrusive {
             pGrandParent = nullptr;
             updParent = nullptr;
             tree_node *     pLeaf = const_cast<internal_node *>( &m_Root );
-            while ( pLeaf->is_internal() ) {
+            while ( pLeaf->is_internal()) {
                 res.guards.copy( search_result::Guard_GrandParent, search_result::Guard_Parent );
                 pGrandParent = pParent;
                 res.guards.copy( search_result::Guard_Parent, search_result::Guard_Leaf );
@@ -1048,7 +1036,7 @@ namespace cds { namespace intrusive {
 
                 updParent = search_protect_update( res, pParent->m_pUpdate );
 
-                switch ( updParent.bits() ) {
+                switch ( updParent.bits()) {
                     case update_desc::DFlag:
                     case update_desc::Mark:
                         m_Stat.onSearchRetry();
@@ -1067,7 +1055,7 @@ namespace cds { namespace intrusive {
 
             res.pGrandParent    = pGrandParent;
             res.pParent         = pParent;
-            assert( pLeaf->is_leaf() );
+            assert( pLeaf->is_leaf());
             res.pLeaf           = static_cast<leaf_node *>( pLeaf );
             res.updParent       = updParent;
             res.updGrandParent  = updGrandParent;
@@ -1092,7 +1080,7 @@ namespace cds { namespace intrusive {
             updParent = nullptr;
             bRightLeaf = false;
             tree_node * pLeaf = const_cast<internal_node *>( &m_Root );
-            while ( pLeaf->is_internal() ) {
+            while ( pLeaf->is_internal()) {
                 res.guards.copy( search_result::Guard_GrandParent, search_result::Guard_Parent );
                 pGrandParent = pParent;
                 res.guards.copy( search_result::Guard_Parent, search_result::Guard_Leaf );
@@ -1103,7 +1091,7 @@ namespace cds { namespace intrusive {
 
                 updParent = search_protect_update( res, pParent->m_pUpdate );
 
-                switch ( updParent.bits() ) {
+                switch ( updParent.bits()) {
                     case update_desc::DFlag:
                     case update_desc::Mark:
                         m_Stat.onSearchRetry();
@@ -1123,7 +1111,7 @@ namespace cds { namespace intrusive {
 
             res.pGrandParent    = pGrandParent;
             res.pParent         = pParent;
-            assert( pLeaf->is_leaf() );
+            assert( pLeaf->is_leaf());
             res.pLeaf           = static_cast<leaf_node *>( pLeaf );
             res.updParent       = updParent;
             res.updGrandParent  = updGrandParent;
@@ -1137,18 +1125,18 @@ namespace cds { namespace intrusive {
         void help( update_ptr pUpdate )
         {
             // pUpdate must be guarded!
-            switch ( pUpdate.bits() ) {
+            switch ( pUpdate.bits()) {
                 case update_desc::IFlag:
-                    help_insert( pUpdate.ptr() );
+                    help_insert( pUpdate.ptr());
                     m_Stat.onHelpInsert();
                     break;
                 case update_desc::DFlag:
-                    help_delete( pUpdate.ptr() );
+                    help_delete( pUpdate.ptr());
                     m_Stat.onHelpDelete();
                     break;
                 case update_desc::Mark:
                     //m_Stat.onHelpMark();
-                    //help_marked( pUpdate.ptr() );
+                    //help_marked( pUpdate.ptr());
                     break;
             }
         }
@@ -1221,7 +1209,7 @@ namespace cds { namespace intrusive {
         static tree_node * protect_sibling( typename gc::Guard& guard, atomics::atomic<tree_node *>& sibling )
         {
             tree_node * pSibling = guard.protect( sibling, [](tree_node * p) -> internal_node* { return static_cast<internal_node *>(p); } );
-            if ( pSibling->is_leaf() )
+            if ( pSibling->is_leaf())
                 guard.assign( node_traits::to_value_ptr( static_cast<leaf_node *>( pSibling )));
             return pSibling;
         }
@@ -1252,7 +1240,7 @@ namespace cds { namespace intrusive {
         bool try_insert( value_type& val, internal_node * pNewInternal, search_result& res )
         {
             assert( res.updParent.bits() == update_desc::Clean );
-            assert( res.pLeaf->is_leaf() );
+            assert( res.pLeaf->is_leaf());
 
             // check search result
             if ( res.pParent->get_child( res.bRightLeaf, memory_model::memory_order_acquire ) == res.pLeaf ) {
@@ -1261,7 +1249,7 @@ namespace cds { namespace intrusive {
                 int nCmp = node_compare()(val, *res.pLeaf);
                 if ( nCmp < 0 ) {
                     if ( res.pGrandParent ) {
-                        assert( !res.pLeaf->infinite_key() );
+                        assert( !res.pLeaf->infinite_key());
                         pNewInternal->infinite_key( 0 );
                         key_extractor()(pNewInternal->m_Key, *node_traits::to_value_ptr( res.pLeaf ));
                     }
@@ -1273,13 +1261,13 @@ namespace cds { namespace intrusive {
                     pNewInternal->m_pRight.store( static_cast<tree_node *>(res.pLeaf), memory_model::memory_order_release );
                 }
                 else {
-                    assert( !res.pLeaf->is_internal() );
+                    assert( !res.pLeaf->is_internal());
 
                     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 );
-                    assert( !res.pLeaf->infinite_key() );
+                    assert( !res.pLeaf->infinite_key());
                 }
 
                 typename gc::Guard guard;
@@ -1291,9 +1279,9 @@ namespace cds { namespace intrusive {
                 pOp->iInfo.pLeaf = res.pLeaf;
                 pOp->iInfo.bRightLeaf = res.bRightLeaf;
 
-                update_ptr updCur( res.updParent.ptr() );
+                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 );
@@ -1316,7 +1304,7 @@ namespace cds { namespace intrusive {
             back_off bkoff;
 
             for ( ;; ) {
-                if ( !search( res, val, cmp ) || !eq( val, *res.pLeaf ) ) {
+                if ( !search( res, val, cmp ) || !eq( val, *res.pLeaf )) {
                     if ( pOp )
                         retire_update_desc( pOp );
                     m_Stat.onEraseFailed();
@@ -1326,7 +1314,7 @@ namespace cds { namespace intrusive {
                 if ( res.updGrandParent.bits() == update_desc::Clean && res.updParent.bits() == update_desc::Clean ) {
                     if ( !pOp )
                         pOp = alloc_update_desc();
-                    if ( check_delete_precondition( res ) ) {
+                    if ( check_delete_precondition( res )) {
                         typename gc::Guard guard;
                         guard.assign( pOp );
 
@@ -1337,12 +1325,12 @@ namespace cds { namespace intrusive {
                         pOp->dInfo.bRightParent = res.bRightParent;
                         pOp->dInfo.bRightLeaf = res.bRightLeaf;
 
-                        update_ptr updGP( res.updGrandParent.ptr() );
+                        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;
@@ -1359,16 +1347,62 @@ namespace cds { namespace intrusive {
             return true;
         }
 
+        template <typename Q, typename Compare>
+        guarded_ptr extract_item( Q const& key, Compare cmp )
+        {
+            update_desc * pOp = nullptr;
+            search_result res;
+            back_off bkoff;
+
+            for ( ;; ) {
+                if ( !search( res, key, cmp )) {
+                    if ( pOp )
+                        retire_update_desc( pOp );
+                    m_Stat.onEraseFailed();
+                    return guarded_ptr();
+                }
+
+                if ( res.updGrandParent.bits() == update_desc::Clean && res.updParent.bits() == update_desc::Clean ) {
+                    if ( !pOp )
+                        pOp = alloc_update_desc();
+                    if ( check_delete_precondition( res )) {
+                        typename gc::Guard guard;
+                        guard.assign( pOp );
+
+                        pOp->dInfo.pGrandParent = res.pGrandParent;
+                        pOp->dInfo.pParent = res.pParent;
+                        pOp->dInfo.pLeaf = res.pLeaf;
+                        pOp->dInfo.pUpdateParent = res.updParent.ptr();
+                        pOp->dInfo.bRightParent = res.bRightParent;
+                        pOp->dInfo.bRightLeaf = res.bRightLeaf;
+
+                        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 ))
+                                break;
+                            pOp = nullptr;
+                        }
+                    }
+                }
+
+                bkoff();
+                m_Stat.onEraseRetry();
+            }
+
+            --m_ItemCounter;
+            m_Stat.onEraseSuccess();
+            return guarded_ptr( res.guards.release( search_result::Guard_Leaf ));
+        }
+
         template <typename Q>
-        bool extract_( typename guarded_ptr::native_guard& guard, Q const& key )
+        guarded_ptr extract_( Q const& key )
         {
-            return erase_( key, node_compare(),
-                []( Q const&, leaf_node const& ) -> bool { return true; },
-                [&guard]( value_type& found ) { guard.set( &found ); } );
+            return extract_item( key, node_compare());
         }
 
         template <typename Q, typename Less>
-        bool extract_with_( typename guarded_ptr::native_guard& guard, Q const& key, Less /*pred*/ )
+        guarded_ptr extract_with_( Q const& key, Less /*pred*/ )
         {
             typedef ellen_bintree::details::compare<
                 key_type,
@@ -1377,12 +1411,10 @@ namespace cds { namespace intrusive {
                 node_traits
             > compare_functor;
 
-            return erase_( key, compare_functor(),
-                []( Q const&, leaf_node const& ) -> bool { return true; },
-                [&guard]( value_type& found ) { guard.set( &found ); } );
+            return extract_item( key, compare_functor());
         }
 
-        bool extract_max_( typename guarded_ptr::native_guard& gp )
+        guarded_ptr extract_max_()
         {
             update_desc * pOp = nullptr;
             search_result res;
@@ -1394,13 +1426,13 @@ namespace cds { namespace intrusive {
                     if ( pOp )
                         retire_update_desc( pOp );
                     m_Stat.onExtractMaxFailed();
-                    return false;
+                    return guarded_ptr();
                 }
 
                 if ( res.updGrandParent.bits() == update_desc::Clean && res.updParent.bits() == update_desc::Clean ) {
                     if ( !pOp )
                         pOp = alloc_update_desc();
-                    if ( check_delete_precondition( res ) ) {
+                    if ( check_delete_precondition( res )) {
                         typename gc::Guard guard;
                         guard.assign( pOp );
 
@@ -1411,11 +1443,11 @@ namespace cds { namespace intrusive {
                         pOp->dInfo.bRightParent = res.bRightParent;
                         pOp->dInfo.bRightLeaf = res.bRightLeaf;
 
-                        update_ptr updGP( res.updGrandParent.ptr() );
+                        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;
                         }
@@ -1428,11 +1460,10 @@ namespace cds { namespace intrusive {
 
             --m_ItemCounter;
             m_Stat.onExtractMaxSuccess();
-            gp.set( node_traits::to_value_ptr( res.pLeaf ));
-            return true;
+            return guarded_ptr( res.guards.release( search_result::Guard_Leaf ));
         }
 
-        bool extract_min_( typename guarded_ptr::native_guard& gp )
+        guarded_ptr extract_min_()
         {
             update_desc * pOp = nullptr;
             search_result res;
@@ -1444,13 +1475,13 @@ namespace cds { namespace intrusive {
                     if ( pOp )
                         retire_update_desc( pOp );
                     m_Stat.onExtractMinFailed();
-                    return false;
+                    return guarded_ptr();
                 }
 
                 if ( res.updGrandParent.bits() == update_desc::Clean && res.updParent.bits() == update_desc::Clean ) {
                     if ( !pOp )
                         pOp = alloc_update_desc();
-                    if ( check_delete_precondition( res ) ) {
+                    if ( check_delete_precondition( res )) {
                         typename gc::Guard guard;
                         guard.assign( pOp );
 
@@ -1461,7 +1492,7 @@ namespace cds { namespace intrusive {
                         pOp->dInfo.bRightParent = res.bRightParent;
                         pOp->dInfo.bRightLeaf = res.bRightLeaf;
 
-                        update_ptr updGP( res.updGrandParent.ptr() );
+                        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 ))
                         {
@@ -1478,15 +1509,14 @@ namespace cds { namespace intrusive {
 
             --m_ItemCounter;
             m_Stat.onExtractMinSuccess();
-            gp.set( node_traits::to_value_ptr( res.pLeaf ));
-            return true;
+            return guarded_ptr( res.guards.release( search_result::Guard_Leaf ));
         }
 
         template <typename Q, typename Func>
         bool find_( Q& val, Func f ) const
         {
             search_result    res;
-            if ( search( res, val, node_compare() )) {
+            if ( search( res, val, node_compare())) {
                 assert( res.pLeaf );
                 f( *node_traits::to_value_ptr( res.pLeaf ), val );
 
@@ -1509,7 +1539,7 @@ namespace cds { namespace intrusive {
             > compare_functor;
 
             search_result    res;
-            if ( search( res, val, compare_functor() )) {
+            if ( search( res, val, compare_functor())) {
                 assert( res.pLeaf );
                 f( *node_traits::to_value_ptr( res.pLeaf ), val );
 
@@ -1522,15 +1552,41 @@ namespace cds { namespace intrusive {
         }
 
         template <typename Q>
-        bool get_( typename guarded_ptr::native_guard& guard, Q const& val ) const
+        guarded_ptr get_( Q const& val ) const
         {
-            return find_( val, [&guard]( value_type& found, Q const& ) { guard.set( &found ); } );
+            search_result    res;
+            if ( search( res, val, node_compare())) {
+                assert( res.pLeaf );
+                m_Stat.onFindSuccess();
+                return guarded_ptr( res.guards.release( search_result::Guard_Leaf ));
+            }
+
+            m_Stat.onFindFailed();
+            return guarded_ptr();
         }
 
         template <typename Q, typename Less>
-        bool get_with_( typename guarded_ptr::native_guard& guard, Q const& val, Less pred ) const
+        guarded_ptr get_with_( Q const& val, Less pred ) const
         {
-            return find_with_( val, pred, [&guard]( value_type& found, Q const& ) { guard.set( &found ); } );
+            CDS_UNUSED( pred );
+
+            typedef ellen_bintree::details::compare<
+                key_type,
+                value_type,
+                opt::details::make_comparator_from_less<Less>,
+                node_traits
+            > compare_functor;
+
+            search_result    res;
+            if ( search( res, val, compare_functor())) {
+                assert( res.pLeaf );
+                m_Stat.onFindSuccess();
+                return guarded_ptr( res.guards.release( search_result::Guard_Leaf ));
+            }
+
+            m_Stat.onFindFailed();
+            return guarded_ptr();
+
         }
 
         //@endcond