From abd38fe81ca2eddf8c6887b936c638672cd827c1 Mon Sep 17 00:00:00 2001 From: Danila Klimenko Date: Wed, 20 May 2015 09:29:24 +0200 Subject: [PATCH] chromatic_tree: checking if node is the root is no longer hazardous --- base_cpp/include/embb/base/internal/atomic/atomic_pointer.h | 8 ++++---- containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h | 64 +++++++++++++++++++++++++++++----------------------------------- containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-rebalance.h | 14 +++++++------- containers_cpp/include/embb/containers/lock_free_chromatic_tree.h | 11 +---------- 4 files changed, 41 insertions(+), 56 deletions(-) diff --git a/base_cpp/include/embb/base/internal/atomic/atomic_pointer.h b/base_cpp/include/embb/base/internal/atomic/atomic_pointer.h index d7fd970..a689054 100644 --- a/base_cpp/include/embb/base/internal/atomic/atomic_pointer.h +++ b/base_cpp/include/embb/base/internal/atomic/atomic_pointer.h @@ -65,8 +65,8 @@ class AtomicPointer : public AtomicArithmetic { bool IsPointer() const; // The methods below are documented in atomic.h - BaseType* operator->(); - BaseType& operator*(); + BaseType* operator->() const; + BaseType& operator*() const; }; template @@ -93,13 +93,13 @@ inline bool AtomicPointer:: template inline BaseType* AtomicPointer:: - operator->() { + operator->() const { return this->Load(); } template inline BaseType& AtomicPointer:: - operator*() { + operator*() const { return *(this->Load()); } diff --git a/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h b/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h index d063eb1..0135779 100644 --- a/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h +++ b/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h @@ -238,10 +238,13 @@ ChromaticTree(size_t capacity, Key undefined_key, Value undefined_value, capacity_(capacity), node_pool_(2 + 5 + 2 * capacity_ + node_hazard_manager_.GetRetiredListMaxSize() * - embb::base::Thread::GetThreadsMaxCount()) { - entry_ = node_pool_.Allocate(undefined_key_, undefined_value_); - NodePtr sentinel = node_pool_.Allocate(undefined_key_, undefined_value_); - entry_->GetLeft() = sentinel; + embb::base::Thread::GetThreadsMaxCount()), + entry_(node_pool_.Allocate(undefined_key_, undefined_value_, 1, + node_pool_.Allocate(undefined_key_, + undefined_value_), + static_cast(NULL))) { + assert(entry_ != NULL); + assert(entry_->GetLeft().Load() != NULL); } template @@ -254,8 +257,8 @@ ChromaticTree:: template bool ChromaticTree:: Get(const Key& key, Value& value) { - HazardNodePtr parent(node_hazard_manager_.GetGuardedPointer(0), NULL); - HazardNodePtr leaf (node_hazard_manager_.GetGuardedPointer(1), NULL); + HazardNodePtr parent(node_hazard_manager_.GetGuardedPointer(0)); + HazardNodePtr leaf (node_hazard_manager_.GetGuardedPointer(1)); Search(key, leaf, parent); bool keys_are_equal = !IsSentinel(leaf) && @@ -286,8 +289,8 @@ TryInsert(const Key& key, const Value& value, Value& old_value) { bool added_violation = false; while (!insertion_succeeded) { - HazardNodePtr parent(node_hazard_manager_.GetGuardedPointer(0), NULL); - HazardNodePtr leaf (node_hazard_manager_.GetGuardedPointer(1), NULL); + HazardNodePtr parent(node_hazard_manager_.GetGuardedPointer(0)); + HazardNodePtr leaf (node_hazard_manager_.GetGuardedPointer(1)); Search(key, leaf, parent); // Try to lock the parent @@ -316,7 +319,7 @@ TryInsert(const Key& key, const Value& value, Value& old_value) { new_sibling = node_pool_.Allocate(leaf->GetKey(), leaf->GetValue()); if (new_sibling == NULL) break; - int new_weight = (HasFixedWeight(leaf)) ? 1 : (leaf->GetWeight() - 1); + int new_weight = (IsSentinel(parent)) ? 1 : (leaf->GetWeight() - 1); if (IsSentinel(leaf) || compare_(key, leaf->GetKey())) { new_parent = node_pool_.Allocate(leaf->GetKey(), undefined_value_, new_weight, new_leaf, new_sibling); @@ -365,9 +368,9 @@ TryDelete(const Key& key, Value& old_value) { bool added_violation = false; while (!deletion_succeeded) { - HazardNodePtr grandparent(node_hazard_manager_.GetGuardedPointer(0), NULL); - HazardNodePtr parent (node_hazard_manager_.GetGuardedPointer(1), NULL); - HazardNodePtr leaf (node_hazard_manager_.GetGuardedPointer(2), NULL); + HazardNodePtr grandparent(node_hazard_manager_.GetGuardedPointer(0)); + HazardNodePtr parent (node_hazard_manager_.GetGuardedPointer(1)); + HazardNodePtr leaf (node_hazard_manager_.GetGuardedPointer(2)); Search(key, leaf, parent, grandparent); // Reached leaf has a different key - nothing to delete @@ -389,7 +392,7 @@ TryDelete(const Key& key, Value& old_value) { if (!parent_lock.OwnsLock() || parent->IsRetired()) continue; // Get the sibling (and protect it with hazard pointer) - HazardNodePtr sibling(node_hazard_manager_.GetGuardedPointer(3), NULL); + HazardNodePtr sibling(node_hazard_manager_.GetGuardedPointer(3)); sibling.ProtectHazard((parent->GetLeft() == leaf) ? parent->GetRight() : parent->GetLeft()); if (parent->IsRetired() || !sibling.IsActive()) continue; @@ -406,7 +409,7 @@ TryDelete(const Key& key, Value& old_value) { UniqueLock leaf_lock(leaf->GetMutex(), embb::base::try_lock); if (!leaf_lock.OwnsLock() || leaf->IsRetired()) continue; - int new_weight = (HasFixedWeight(parent)) ? + int new_weight = (IsSentinel(grandparent)) ? 1 : (parent->GetWeight() + sibling->GetWeight()); new_leaf = node_pool_.Allocate( @@ -453,8 +456,7 @@ GetUndefinedValue() { template bool ChromaticTree:: IsEmpty() const { - NodePtr entry = entry_; //Bug: "operator->()" is not const in AtomicPointer<> - return IsLeaf(entry->GetLeft()); + return IsLeaf(entry_->GetLeft()); } template @@ -515,15 +517,7 @@ IsLeaf(const NodePtr& node) const { template bool ChromaticTree:: IsSentinel(const NodePtr& node) const { - NodePtr entry = entry_; //Bug: "operator->()" is not const in AtomicPointer<> - return (node == entry) || (node == entry->GetLeft()); -} - -template -bool ChromaticTree:: -HasFixedWeight(const NodePtr& node) const { - NodePtr entry = entry_; //Bug: "operator->()" is not const in AtomicPointer<> - return (IsSentinel(node)) || (node == entry->GetLeft()->GetLeft()); + return (node == entry_) || (node == entry_->GetLeft()); } template @@ -564,8 +558,7 @@ GetHeight(const NodePtr& node) const { template bool ChromaticTree:: IsBalanced() const { - NodePtr entry = entry_; //Bug: "operator->()" is not const in AtomicPointer<> - return IsBalanced(entry->GetLeft()); + return IsBalanced(entry_->GetLeft()); } template @@ -613,16 +606,16 @@ FreeNode(NodePtr node) { template bool ChromaticTree:: CleanUp(const Key& key) { - HazardNodePtr grangranparent(node_hazard_manager_.GetGuardedPointer(0), NULL); - HazardNodePtr grandparent (node_hazard_manager_.GetGuardedPointer(1), NULL); - HazardNodePtr parent (node_hazard_manager_.GetGuardedPointer(2), NULL); - HazardNodePtr leaf (node_hazard_manager_.GetGuardedPointer(3), NULL); + HazardNodePtr grandgrandparent(node_hazard_manager_.GetGuardedPointer(0)); + HazardNodePtr grandparent (node_hazard_manager_.GetGuardedPointer(1)); + HazardNodePtr parent (node_hazard_manager_.GetGuardedPointer(2)); + HazardNodePtr leaf (node_hazard_manager_.GetGuardedPointer(3)); bool reached_leaf = false; while (!reached_leaf) { bool found_violation = false; - grangranparent.ProtectHazard(entry_); + grandgrandparent.ProtectHazard(entry_); grandparent.ProtectHazard(entry_); parent.ProtectHazard(entry_); leaf.ProtectHazard(entry_->GetLeft()); @@ -630,7 +623,7 @@ CleanUp(const Key& key) { reached_leaf = IsLeaf(leaf); while (!reached_leaf && !found_violation) { - grangranparent.AdoptGuard(grandparent); + grandgrandparent.AdoptGuard(grandparent); grandparent.AdoptGuard(parent); parent.AdoptGuard(leaf); leaf.ProtectHazard((IsSentinel(leaf) || compare_(key, leaf->GetKey())) ? @@ -647,7 +640,8 @@ CleanUp(const Key& key) { if (found_violation) { reached_leaf = false; - if (Rebalance(grangranparent, grandparent, parent, leaf) == EMBB_NOMEM) { + if (Rebalance(grandgrandparent, grandparent, parent, leaf) == + EMBB_NOMEM) { assert(false && "No memory for rebalancing!"); return false; } @@ -662,7 +656,7 @@ CleanUp(const Key& key) { if (!lock_name.OwnsLock() || node->IsRetired()) return EMBB_BUSY; #define DEFINE_NODE_WITH_HAZARD(h_num, node, parent, method) \ - HazardNodePtr node(node_hazard_manager_.GetGuardedPointer(h_num), NULL); \ + HazardNodePtr node(node_hazard_manager_.GetGuardedPointer(h_num)); \ node.ProtectHazard(parent->method()); \ if (parent->IsRetired() || !node.IsActive()) return EMBB_BUSY; \ VERIFY_ADDRESS(static_cast(node)) diff --git a/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-rebalance.h b/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-rebalance.h index 77d34c2..ec9f992 100644 --- a/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-rebalance.h +++ b/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-rebalance.h @@ -29,8 +29,8 @@ // Any direct changes will be lost after rebuild of the project. // -#ifndef EMBB_CONTAINERS_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_ -#define EMBB_CONTAINERS_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_ +#ifndef EMBB_CONTAINERS_INTERNAL_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_ +#define EMBB_CONTAINERS_INTERNAL_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_ embb_errors_t BLK( HazardNodePtr& u, UniqueLock& u_lock, @@ -47,7 +47,7 @@ embb_errors_t BLK( uxr->GetLeft(), uxr->GetRight()); NodePtr nx = node_pool_.Allocate( ux->GetKey(), ux->GetValue(), - HasFixedWeight(ux) ? 1 : ux->GetWeight() - 1, + IsSentinel(u) ? 1 : ux->GetWeight() - 1, nxl, nxr); if (nxl == NULL || @@ -88,7 +88,7 @@ embb_errors_t PUSH_L( uxr->GetLeft(), uxr->GetRight()); NodePtr nx = node_pool_.Allocate( ux->GetKey(), ux->GetValue(), - HasFixedWeight(ux) ? 1 : ux->GetWeight() + 1, + IsSentinel(u) ? 1 : ux->GetWeight() + 1, nxl, nxr); if (nxl == NULL || @@ -129,7 +129,7 @@ embb_errors_t PUSH_R( uxl->GetLeft(), uxl->GetRight()); NodePtr nx = node_pool_.Allocate( ux->GetKey(), ux->GetValue(), - HasFixedWeight(ux) ? 1 : ux->GetWeight() + 1, + IsSentinel(u) ? 1 : ux->GetWeight() + 1, nxl, nxr); if (nxr == NULL || @@ -938,7 +938,7 @@ embb_errors_t W7( uxr->GetLeft(), uxr->GetRight()); NodePtr nx = node_pool_.Allocate( ux->GetKey(), ux->GetValue(), - HasFixedWeight(ux) ? 1 : ux->GetWeight() + 1, + IsSentinel(u) ? 1 : ux->GetWeight() + 1, nxl, nxr); if (nxl == NULL || @@ -964,4 +964,4 @@ embb_errors_t W7( return EMBB_SUCCESS; } -#endif // EMBB_CONTAINERS_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_ +#endif // EMBB_CONTAINERS_INTERNAL_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_ diff --git a/containers_cpp/include/embb/containers/lock_free_chromatic_tree.h b/containers_cpp/include/embb/containers/lock_free_chromatic_tree.h index 1a0e914..1b7fd2f 100644 --- a/containers_cpp/include/embb/containers/lock_free_chromatic_tree.h +++ b/containers_cpp/include/embb/containers/lock_free_chromatic_tree.h @@ -540,15 +540,6 @@ class ChromaticTree { bool IsSentinel(const NodePtr& node) const; /** - * Checks whether the given node has to maintain the constant weight of \c 1. - * - * \param[IN] node Node to be checked - * - * \return \c true if the given node has constant weight, \c false otherwise - */ - bool HasFixedWeight(const NodePtr& node) const; - - /** * Checks whether the given node has a specified child node. * * \param[IN] parent Parent node @@ -673,7 +664,7 @@ class ChromaticTree { const Compare compare_; /**< Comparator object for the keys */ size_t capacity_; /**< User-requested capacity of the tree */ NodePool node_pool_; /**< Comparator object for the keys */ - AtomicNodePtr entry_; /**< Pointer to the sentinel node used as + const AtomicNodePtr entry_; /**< Pointer to the sentinel node used as * the entry point into the tree */ /** -- libgit2 0.26.0