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> {
bool IsPointer() const;
// The methods below are documented in atomic.h
BaseType* operator->();
BaseType& operator*();
BaseType* operator->() const;
BaseType& operator*() const;
};
template<typename BaseType, typename DifferenceType, size_t S>
......@@ -93,13 +93,13 @@ inline bool AtomicPointer<BaseType, DifferenceType, S>::
template<typename BaseType, typename DifferenceType, size_t S>
inline BaseType* AtomicPointer<BaseType, DifferenceType, S>::
operator->() {
operator->() const {
return this->Load();
}
template<typename BaseType, typename DifferenceType, size_t S>
inline BaseType& AtomicPointer<BaseType, DifferenceType, S>::
operator*() {
operator*() const {
return *(this->Load());
}
......
......@@ -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<NodePtr>(NULL))) {
assert(entry_ != NULL);
assert(entry_->GetLeft().Load() != NULL);
}
template<typename Key, typename Value, typename Compare, typename NodePool>
......@@ -254,8 +257,8 @@ ChromaticTree<Key, Value, Compare, NodePool>::
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
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<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
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>
......@@ -515,15 +517,7 @@ IsLeaf(const NodePtr& node) const {
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
IsSentinel(const NodePtr& node) const {
NodePtr entry = entry_; //Bug: "operator->()" is not const in AtomicPointer<>
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());
return (node == entry_) || (node == entry_->GetLeft());
}
template<typename Key, typename Value, typename Compare, typename NodePool>
......@@ -564,8 +558,7 @@ GetHeight(const NodePtr& node) const {
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
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>
......@@ -613,16 +606,16 @@ FreeNode(NodePtr node) {
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
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<NodePtr>(node))
......
......@@ -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_
......@@ -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 */
/**
......
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