Commit abd38fe8 by Danila Klimenko

chromatic_tree: checking if node is the root is no longer hazardous

parent acb6cf6b
...@@ -65,8 +65,8 @@ class AtomicPointer : public AtomicArithmetic<BaseType*, DifferenceType, S> { ...@@ -65,8 +65,8 @@ class AtomicPointer : public AtomicArithmetic<BaseType*, DifferenceType, S> {
bool IsPointer() const; bool IsPointer() const;
// The methods below are documented in atomic.h // The methods below are documented in atomic.h
BaseType* operator->(); BaseType* operator->() const;
BaseType& operator*(); BaseType& operator*() const;
}; };
template<typename BaseType, typename DifferenceType, size_t S> template<typename BaseType, typename DifferenceType, size_t S>
...@@ -93,13 +93,13 @@ inline bool AtomicPointer<BaseType, DifferenceType, S>:: ...@@ -93,13 +93,13 @@ inline bool AtomicPointer<BaseType, DifferenceType, S>::
template<typename BaseType, typename DifferenceType, size_t S> template<typename BaseType, typename DifferenceType, size_t S>
inline BaseType* AtomicPointer<BaseType, DifferenceType, S>:: inline BaseType* AtomicPointer<BaseType, DifferenceType, S>::
operator->() { operator->() const {
return this->Load(); return this->Load();
} }
template<typename BaseType, typename DifferenceType, size_t S> template<typename BaseType, typename DifferenceType, size_t S>
inline BaseType& AtomicPointer<BaseType, DifferenceType, S>:: inline BaseType& AtomicPointer<BaseType, DifferenceType, S>::
operator*() { operator*() const {
return *(this->Load()); return *(this->Load());
} }
......
...@@ -238,10 +238,13 @@ ChromaticTree(size_t capacity, Key undefined_key, Value undefined_value, ...@@ -238,10 +238,13 @@ ChromaticTree(size_t capacity, Key undefined_key, Value undefined_value,
capacity_(capacity), capacity_(capacity),
node_pool_(2 + 5 + 2 * capacity_ + node_pool_(2 + 5 + 2 * capacity_ +
node_hazard_manager_.GetRetiredListMaxSize() * node_hazard_manager_.GetRetiredListMaxSize() *
embb::base::Thread::GetThreadsMaxCount()) { embb::base::Thread::GetThreadsMaxCount()),
entry_ = node_pool_.Allocate(undefined_key_, undefined_value_); entry_(node_pool_.Allocate(undefined_key_, undefined_value_, 1,
NodePtr sentinel = node_pool_.Allocate(undefined_key_, undefined_value_); node_pool_.Allocate(undefined_key_,
entry_->GetLeft() = sentinel; undefined_value_),
static_cast<NodePtr>(NULL))) {
assert(entry_ != NULL);
assert(entry_->GetLeft().Load() != NULL);
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename NodePool>
...@@ -254,8 +257,8 @@ ChromaticTree<Key, Value, Compare, NodePool>:: ...@@ -254,8 +257,8 @@ ChromaticTree<Key, Value, Compare, NodePool>::
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>:: bool ChromaticTree<Key, Value, Compare, NodePool>::
Get(const Key& key, Value& value) { Get(const Key& key, Value& value) {
HazardNodePtr parent(node_hazard_manager_.GetGuardedPointer(0), NULL); HazardNodePtr parent(node_hazard_manager_.GetGuardedPointer(0));
HazardNodePtr leaf (node_hazard_manager_.GetGuardedPointer(1), NULL); HazardNodePtr leaf (node_hazard_manager_.GetGuardedPointer(1));
Search(key, leaf, parent); Search(key, leaf, parent);
bool keys_are_equal = !IsSentinel(leaf) && bool keys_are_equal = !IsSentinel(leaf) &&
...@@ -286,8 +289,8 @@ TryInsert(const Key& key, const Value& value, Value& old_value) { ...@@ -286,8 +289,8 @@ TryInsert(const Key& key, const Value& value, Value& old_value) {
bool added_violation = false; bool added_violation = false;
while (!insertion_succeeded) { while (!insertion_succeeded) {
HazardNodePtr parent(node_hazard_manager_.GetGuardedPointer(0), NULL); HazardNodePtr parent(node_hazard_manager_.GetGuardedPointer(0));
HazardNodePtr leaf (node_hazard_manager_.GetGuardedPointer(1), NULL); HazardNodePtr leaf (node_hazard_manager_.GetGuardedPointer(1));
Search(key, leaf, parent); Search(key, leaf, parent);
// Try to lock the parent // Try to lock the parent
...@@ -316,7 +319,7 @@ TryInsert(const Key& key, const Value& value, Value& old_value) { ...@@ -316,7 +319,7 @@ TryInsert(const Key& key, const Value& value, Value& old_value) {
new_sibling = node_pool_.Allocate(leaf->GetKey(), leaf->GetValue()); new_sibling = node_pool_.Allocate(leaf->GetKey(), leaf->GetValue());
if (new_sibling == NULL) break; 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())) { if (IsSentinel(leaf) || compare_(key, leaf->GetKey())) {
new_parent = node_pool_.Allocate(leaf->GetKey(), undefined_value_, new_parent = node_pool_.Allocate(leaf->GetKey(), undefined_value_,
new_weight, new_leaf, new_sibling); new_weight, new_leaf, new_sibling);
...@@ -365,9 +368,9 @@ TryDelete(const Key& key, Value& old_value) { ...@@ -365,9 +368,9 @@ TryDelete(const Key& key, Value& old_value) {
bool added_violation = false; bool added_violation = false;
while (!deletion_succeeded) { while (!deletion_succeeded) {
HazardNodePtr grandparent(node_hazard_manager_.GetGuardedPointer(0), NULL); HazardNodePtr grandparent(node_hazard_manager_.GetGuardedPointer(0));
HazardNodePtr parent (node_hazard_manager_.GetGuardedPointer(1), NULL); HazardNodePtr parent (node_hazard_manager_.GetGuardedPointer(1));
HazardNodePtr leaf (node_hazard_manager_.GetGuardedPointer(2), NULL); HazardNodePtr leaf (node_hazard_manager_.GetGuardedPointer(2));
Search(key, leaf, parent, grandparent); Search(key, leaf, parent, grandparent);
// Reached leaf has a different key - nothing to delete // Reached leaf has a different key - nothing to delete
...@@ -389,7 +392,7 @@ TryDelete(const Key& key, Value& old_value) { ...@@ -389,7 +392,7 @@ TryDelete(const Key& key, Value& old_value) {
if (!parent_lock.OwnsLock() || parent->IsRetired()) continue; if (!parent_lock.OwnsLock() || parent->IsRetired()) continue;
// Get the sibling (and protect it with hazard pointer) // 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) ? sibling.ProtectHazard((parent->GetLeft() == leaf) ?
parent->GetRight() : parent->GetLeft()); parent->GetRight() : parent->GetLeft());
if (parent->IsRetired() || !sibling.IsActive()) continue; if (parent->IsRetired() || !sibling.IsActive()) continue;
...@@ -406,7 +409,7 @@ TryDelete(const Key& key, Value& old_value) { ...@@ -406,7 +409,7 @@ TryDelete(const Key& key, Value& old_value) {
UniqueLock leaf_lock(leaf->GetMutex(), embb::base::try_lock); UniqueLock leaf_lock(leaf->GetMutex(), embb::base::try_lock);
if (!leaf_lock.OwnsLock() || leaf->IsRetired()) continue; if (!leaf_lock.OwnsLock() || leaf->IsRetired()) continue;
int new_weight = (HasFixedWeight(parent)) ? int new_weight = (IsSentinel(grandparent)) ?
1 : (parent->GetWeight() + sibling->GetWeight()); 1 : (parent->GetWeight() + sibling->GetWeight());
new_leaf = node_pool_.Allocate( new_leaf = node_pool_.Allocate(
...@@ -453,8 +456,7 @@ GetUndefinedValue() { ...@@ -453,8 +456,7 @@ GetUndefinedValue() {
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>:: bool ChromaticTree<Key, Value, Compare, NodePool>::
IsEmpty() const { IsEmpty() const {
NodePtr entry = entry_; //Bug: "operator->()" is not const in AtomicPointer<> return IsLeaf(entry_->GetLeft());
return IsLeaf(entry->GetLeft());
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename NodePool>
...@@ -515,15 +517,7 @@ IsLeaf(const NodePtr& node) const { ...@@ -515,15 +517,7 @@ IsLeaf(const NodePtr& node) const {
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>:: bool ChromaticTree<Key, Value, Compare, NodePool>::
IsSentinel(const NodePtr& node) const { IsSentinel(const NodePtr& node) const {
NodePtr entry = entry_; //Bug: "operator->()" is not const in AtomicPointer<> return (node == entry_) || (node == entry_->GetLeft());
return (node == entry) || (node == entry->GetLeft());
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
HasFixedWeight(const NodePtr& node) const {
NodePtr entry = entry_; //Bug: "operator->()" is not const in AtomicPointer<>
return (IsSentinel(node)) || (node == entry->GetLeft()->GetLeft());
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename NodePool>
...@@ -564,8 +558,7 @@ GetHeight(const NodePtr& node) const { ...@@ -564,8 +558,7 @@ GetHeight(const NodePtr& node) const {
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>:: bool ChromaticTree<Key, Value, Compare, NodePool>::
IsBalanced() const { IsBalanced() const {
NodePtr entry = entry_; //Bug: "operator->()" is not const in AtomicPointer<> return IsBalanced(entry_->GetLeft());
return IsBalanced(entry->GetLeft());
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename NodePool>
...@@ -613,16 +606,16 @@ FreeNode(NodePtr node) { ...@@ -613,16 +606,16 @@ FreeNode(NodePtr node) {
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>:: bool ChromaticTree<Key, Value, Compare, NodePool>::
CleanUp(const Key& key) { CleanUp(const Key& key) {
HazardNodePtr grangranparent(node_hazard_manager_.GetGuardedPointer(0), NULL); HazardNodePtr grandgrandparent(node_hazard_manager_.GetGuardedPointer(0));
HazardNodePtr grandparent (node_hazard_manager_.GetGuardedPointer(1), NULL); HazardNodePtr grandparent (node_hazard_manager_.GetGuardedPointer(1));
HazardNodePtr parent (node_hazard_manager_.GetGuardedPointer(2), NULL); HazardNodePtr parent (node_hazard_manager_.GetGuardedPointer(2));
HazardNodePtr leaf (node_hazard_manager_.GetGuardedPointer(3), NULL); HazardNodePtr leaf (node_hazard_manager_.GetGuardedPointer(3));
bool reached_leaf = false; bool reached_leaf = false;
while (!reached_leaf) { while (!reached_leaf) {
bool found_violation = false; bool found_violation = false;
grangranparent.ProtectHazard(entry_); grandgrandparent.ProtectHazard(entry_);
grandparent.ProtectHazard(entry_); grandparent.ProtectHazard(entry_);
parent.ProtectHazard(entry_); parent.ProtectHazard(entry_);
leaf.ProtectHazard(entry_->GetLeft()); leaf.ProtectHazard(entry_->GetLeft());
...@@ -630,7 +623,7 @@ CleanUp(const Key& key) { ...@@ -630,7 +623,7 @@ CleanUp(const Key& key) {
reached_leaf = IsLeaf(leaf); reached_leaf = IsLeaf(leaf);
while (!reached_leaf && !found_violation) { while (!reached_leaf && !found_violation) {
grangranparent.AdoptGuard(grandparent); grandgrandparent.AdoptGuard(grandparent);
grandparent.AdoptGuard(parent); grandparent.AdoptGuard(parent);
parent.AdoptGuard(leaf); parent.AdoptGuard(leaf);
leaf.ProtectHazard((IsSentinel(leaf) || compare_(key, leaf->GetKey())) ? leaf.ProtectHazard((IsSentinel(leaf) || compare_(key, leaf->GetKey())) ?
...@@ -647,7 +640,8 @@ CleanUp(const Key& key) { ...@@ -647,7 +640,8 @@ CleanUp(const Key& key) {
if (found_violation) { if (found_violation) {
reached_leaf = false; 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!"); assert(false && "No memory for rebalancing!");
return false; return false;
} }
...@@ -662,7 +656,7 @@ CleanUp(const Key& key) { ...@@ -662,7 +656,7 @@ CleanUp(const Key& key) {
if (!lock_name.OwnsLock() || node->IsRetired()) return EMBB_BUSY; if (!lock_name.OwnsLock() || node->IsRetired()) return EMBB_BUSY;
#define DEFINE_NODE_WITH_HAZARD(h_num, node, parent, method) \ #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()); \ node.ProtectHazard(parent->method()); \
if (parent->IsRetired() || !node.IsActive()) return EMBB_BUSY; \ if (parent->IsRetired() || !node.IsActive()) return EMBB_BUSY; \
VERIFY_ADDRESS(static_cast<NodePtr>(node)) VERIFY_ADDRESS(static_cast<NodePtr>(node))
......
...@@ -29,8 +29,8 @@ ...@@ -29,8 +29,8 @@
// Any direct changes will be lost after rebuild of the project. // Any direct changes will be lost after rebuild of the project.
// //
#ifndef EMBB_CONTAINERS_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_ #ifndef EMBB_CONTAINERS_INTERNAL_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_
#define EMBB_CONTAINERS_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_ #define EMBB_CONTAINERS_INTERNAL_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_
embb_errors_t BLK( embb_errors_t BLK(
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& u, UniqueLock& u_lock,
...@@ -47,7 +47,7 @@ embb_errors_t BLK( ...@@ -47,7 +47,7 @@ embb_errors_t BLK(
uxr->GetLeft(), uxr->GetRight()); uxr->GetLeft(), uxr->GetRight());
NodePtr nx = node_pool_.Allocate( NodePtr nx = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
HasFixedWeight(ux) ? 1 : ux->GetWeight() - 1, IsSentinel(u) ? 1 : ux->GetWeight() - 1,
nxl, nxr); nxl, nxr);
if (nxl == NULL || if (nxl == NULL ||
...@@ -88,7 +88,7 @@ embb_errors_t PUSH_L( ...@@ -88,7 +88,7 @@ embb_errors_t PUSH_L(
uxr->GetLeft(), uxr->GetRight()); uxr->GetLeft(), uxr->GetRight());
NodePtr nx = node_pool_.Allocate( NodePtr nx = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
HasFixedWeight(ux) ? 1 : ux->GetWeight() + 1, IsSentinel(u) ? 1 : ux->GetWeight() + 1,
nxl, nxr); nxl, nxr);
if (nxl == NULL || if (nxl == NULL ||
...@@ -129,7 +129,7 @@ embb_errors_t PUSH_R( ...@@ -129,7 +129,7 @@ embb_errors_t PUSH_R(
uxl->GetLeft(), uxl->GetRight()); uxl->GetLeft(), uxl->GetRight());
NodePtr nx = node_pool_.Allocate( NodePtr nx = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
HasFixedWeight(ux) ? 1 : ux->GetWeight() + 1, IsSentinel(u) ? 1 : ux->GetWeight() + 1,
nxl, nxr); nxl, nxr);
if (nxr == NULL || if (nxr == NULL ||
...@@ -938,7 +938,7 @@ embb_errors_t W7( ...@@ -938,7 +938,7 @@ embb_errors_t W7(
uxr->GetLeft(), uxr->GetRight()); uxr->GetLeft(), uxr->GetRight());
NodePtr nx = node_pool_.Allocate( NodePtr nx = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
HasFixedWeight(ux) ? 1 : ux->GetWeight() + 1, IsSentinel(u) ? 1 : ux->GetWeight() + 1,
nxl, nxr); nxl, nxr);
if (nxl == NULL || if (nxl == NULL ||
...@@ -964,4 +964,4 @@ embb_errors_t W7( ...@@ -964,4 +964,4 @@ embb_errors_t W7(
return EMBB_SUCCESS; return EMBB_SUCCESS;
} }
#endif // EMBB_CONTAINERS_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_ #endif // EMBB_CONTAINERS_INTERNAL_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_
...@@ -540,15 +540,6 @@ class ChromaticTree { ...@@ -540,15 +540,6 @@ class ChromaticTree {
bool IsSentinel(const NodePtr& node) const; 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. * Checks whether the given node has a specified child node.
* *
* \param[IN] parent Parent node * \param[IN] parent Parent node
...@@ -673,7 +664,7 @@ class ChromaticTree { ...@@ -673,7 +664,7 @@ class ChromaticTree {
const Compare compare_; /**< Comparator object for the keys */ const Compare compare_; /**< Comparator object for the keys */
size_t capacity_; /**< User-requested capacity of the tree */ size_t capacity_; /**< User-requested capacity of the tree */
NodePool node_pool_; /**< Comparator object for the keys */ 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 */ * the entry point into the tree */
/** /**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment