/*
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:
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_CONTAINER_IMPL_BRONSON_AVLTREE_MAP_RCU_H
void clean()
{
- assert( !gc::is_locked() );
+ assert( !gc::is_locked());
// TODO: use RCU::batch_retire
this sequence
\code
set.clear();
- assert( set.empty() );
+ assert( set.empty());
\endcode
the assertion could be raised.
*/
void clear()
{
- while ( extract_min() );
+ while ( extract_min());
}
/// Clears the tree (not thread safe)
template <typename Q, typename Compare, typename Func>
find_result try_find( Q const& key, Compare cmp, Func f, node_type * pNode, int nDir, version_type nVersion ) const
{
- assert( gc::is_locked() );
+ assert( gc::is_locked());
assert( pNode );
struct stack_record
int nCmp = cmp( key, pChild->m_key );
if ( nCmp == 0 ) {
- if ( pChild->is_valued( memory_model::memory_order_acquire ) ) {
+ if ( pChild->is_valued( memory_model::memory_order_acquire )) {
// key found
node_scoped_lock l( m_Monitor, *pChild );
if ( child(pNode, nDir, memory_model::memory_order_acquire) == pChild ) {
if ( pChild->is_valued( memory_model::memory_order_relaxed )) {
- if ( f( pChild ) ) {
+ if ( f( pChild )) {
m_stat.onFindSuccess();
return find_result::found;
}
template <typename K, typename Compare, typename Func>
int try_update_root( K const& key, Compare cmp, int nFlags, Func funcUpdate, rcu_disposer& disp )
{
- assert( gc::is_locked() );
+ assert( gc::is_locked());
while ( true ) {
int result;
template <typename K, typename Compare, typename Func>
bool try_remove_root( K const& key, Compare cmp, Func func, rcu_disposer& disp )
{
- assert( gc::is_locked() );
+ assert( gc::is_locked());
while ( true ) {
int result;
template <typename K, typename Compare, typename Func>
int try_update( K const& key, Compare cmp, int nFlags, Func funcUpdate, node_type * pNode, version_type nVersion, rcu_disposer& disp )
{
- assert( gc::is_locked() );
+ assert( gc::is_locked());
assert( nVersion != node_type::unlinked );
struct stack_record
template <typename K, typename Compare, typename Func>
int try_remove( K const& key, Compare cmp, Func func, node_type * pParent, node_type * pNode, version_type nVersion, rcu_disposer& disp )
{
- assert( gc::is_locked() );
+ assert( gc::is_locked());
assert( nVersion != node_type::unlinked );
struct stack_record
template <typename Func>
int try_extract_minmax( int nDir, Func func, node_type * pParent, node_type * pNode, version_type nVersion, rcu_disposer& disp )
{
- assert( gc::is_locked() );
+ assert( gc::is_locked());
assert( nVersion != node_type::unlinked );
struct stack_record
nVersion = stack[pos].nVersion;
while ( true ) {
- node_type * pChild = child( pNode, nDir, memory_model::memory_order_acquire );
+ int iterDir = nDir;
+ node_type * pChild = child( pNode, iterDir, memory_model::memory_order_acquire );
if ( pNode->version(memory_model::memory_order_acquire) != nVersion ) {
--pos;
m_stat.onRemoveRetry();
break;
}
- if ( pChild == nullptr ) {
+ if ( !pChild ) {
// Found min/max
- assert(pNode->is_valued( memory_model::memory_order_acquire ));
- int result = try_remove_node( pParent, pNode, nVersion, func, disp );
- if ( result != update_flags::retry )
- return result;
- --pos;
- m_stat.onRemoveRetry();
- break;
+ if ( pNode->is_valued( memory_model::memory_order_acquire ) ) {
+ int result = try_remove_node( pParent, pNode, nVersion, func, disp );
+
+ if ( result == update_flags::result_removed )
+ return result;
+
+ --pos;
+ m_stat.onRemoveRetry();
+ break;
+ }
+ else {
+ // check right (for min) or left (for max) child node
+ iterDir = -iterDir;
+ pChild = child( pNode, iterDir, memory_model::memory_order_acquire );
+ if ( !pChild ) {
+ --pos;
+ m_stat.onRemoveRetry();
+ break;
+ }
+ }
}
version_type nChildVersion = pChild->version( memory_model::memory_order_acquire );
pChild->template wait_until_shrink_completed<back_off>( memory_model::memory_order_acquire );
// retry
}
- else if ( pChild == child( pNode, nDir, memory_model::memory_order_acquire )) {
+ else if ( pChild == child( pNode, iterDir, memory_model::memory_order_acquire )) {
// this second read is important, because it is protected by nChildVersion
// validate the read that our caller took to get to node
return update_flags::retry;
}
- if ( pNode->is_valued( memory_model::memory_order_relaxed ) && !(nFlags & update_flags::allow_update) ) {
+ if ( pNode->is_valued( memory_model::memory_order_relaxed ) && !(nFlags & update_flags::allow_update)) {
m_stat.onInsertFailed();
return update_flags::failed;
}
assert( pParent != nullptr );
assert( pNode != nullptr );
- if ( !pNode->is_valued( memory_model::memory_order_acquire ) )
+ if ( !pNode->is_valued( memory_model::memory_order_acquire ))
return update_flags::failed;
if ( child( pNode, left_child, memory_model::memory_order_acquire ) == nullptr
bool try_unlink_locked( node_type * pParent, node_type * pNode, rcu_disposer& disp )
{
// pParent and pNode must be locked
- assert( !pParent->is_unlinked(memory_model::memory_order_relaxed) );
+ assert( !pParent->is_unlinked(memory_model::memory_order_relaxed));
node_type * pParentLeft = child( pParent, left_child, memory_model::memory_order_relaxed );
node_type * pParentRight = child( pParent, right_child, memory_model::memory_order_relaxed );
{
while ( pNode && parent( pNode, memory_model::memory_order_acquire )) {
int nCond = estimate_node_condition( pNode );
- if ( nCond == nothing_required || pNode->is_unlinked( memory_model::memory_order_acquire ) )
+ if ( nCond == nothing_required || pNode->is_unlinked( memory_model::memory_order_acquire ))
return;
if ( nCond != unlink_required && nCond != rebalance_required )
if ( pLRight != nullptr )
pLRight->parent( pNode, memory_model::memory_order_release );
- atomics::atomic_thread_fence( memory_model::memory_order_release );
-
pLeft->m_pRight.store( pNode, memory_model::memory_order_release );
pNode->parent( pLeft, memory_model::memory_order_release );
- atomics::atomic_thread_fence( memory_model::memory_order_release );
-
if ( pParentLeft == pNode )
pParent->m_pLeft.store( pLeft, memory_model::memory_order_release );
else {
}
pLeft->parent( pParent, memory_model::memory_order_release );
- atomics::atomic_thread_fence( memory_model::memory_order_release );
-
// fix up heights links
int hNode = 1 + std::max( hLR, hR );
set_height( pNode, hNode, memory_model::memory_order_release );
}
// pLeft might also have routing node damage (if pLeft.left was null)
- if ( hLL == 0 && !pLeft->is_valued(memory_model::memory_order_acquire) ) {
+ if ( hLL == 0 && !pLeft->is_valued(memory_model::memory_order_acquire)) {
m_stat.onDamageAfterRightRotation();
return pLeft;
}
if ( pRLeft != nullptr )
pRLeft->parent( pNode, memory_model::memory_order_release );
- atomics::atomic_thread_fence( memory_model::memory_order_release );
-
pRight->m_pLeft.store( pNode, memory_model::memory_order_release );
pNode->parent( pRight, memory_model::memory_order_release );
- atomics::atomic_thread_fence( memory_model::memory_order_release );
-
if ( pParentLeft == pNode )
pParent->m_pLeft.store( pRight, memory_model::memory_order_release );
else {
}
pRight->parent( pParent, memory_model::memory_order_release );
- atomics::atomic_thread_fence( memory_model::memory_order_release );
-
// fix up heights
int hNode = 1 + std::max( hL, hRL );
set_height( pNode, hNode, memory_model::memory_order_release );
return pNode;
}
- if ( (pRLeft == nullptr || hL == 0) && !pNode->is_valued(memory_model::memory_order_relaxed) ) {
+ if ( (pRLeft == nullptr || hL == 0) && !pNode->is_valued(memory_model::memory_order_relaxed)) {
m_stat.onRemoveAfterLeftRotation();
return pNode;
}
return pRight;
}
- if ( hRR == 0 && !pRight->is_valued(memory_model::memory_order_acquire) ) {
+ if ( hRR == 0 && !pRight->is_valued(memory_model::memory_order_acquire)) {
m_stat.onDamageAfterLeftRotation();
return pRight;
}
return pNode;
}
- if ( (pRLL == nullptr || hL == 0) && !pNode->is_valued(memory_model::memory_order_relaxed) ) {
+ if ( (pRLL == nullptr || hL == 0) && !pNode->is_valued(memory_model::memory_order_relaxed)) {
m_stat.onRemoveAfterLRRotation();
return pNode;
}