Commit 871b5391 by Danila Klimenko

chromatic_tree: Fine-grained locking implementation without rebalancing

parent 8ded09ad
......@@ -29,7 +29,6 @@
#include <embb/base/internal/platform.h>
#include <embb/base/exceptions.h>
#include <embb/base/c/counter.h>
namespace embb {
namespace base {
......@@ -484,71 +483,6 @@ class UniqueLock {
friend class embb::base::ConditionVariable;
};
class ReadWriteLock {
public:
ReadWriteLock() : read_lock_(), write_lock_(),
reader_(self()), writer_(self()) {
embb_counter_init(&active_readers_);
}
void ReadLock() {
LockGuard<Mutex> read_guard(read_lock_);
unsigned int me = embb_counter_increment(&active_readers_);
if (me == 0) {
write_lock_.Lock();
}
}
void ReadUnlock() {
unsigned int me = embb_counter_decrement(&active_readers_);
if (me == 1) {
write_lock_.Unlock();
}
}
void WriteLock() {
read_lock_.Lock();
write_lock_.Lock();
}
void WriteUnlock() {
write_lock_.Unlock();
read_lock_.Unlock();
}
~ReadWriteLock() {
embb_counter_destroy(&active_readers_);
}
class Reader {
public:
explicit Reader(ReadWriteLock& rwlock) : readwrite_lock_(rwlock) {}
void Lock() { readwrite_lock_.ReadLock(); }
void Unlock() { readwrite_lock_.ReadUnlock(); }
private:
ReadWriteLock& readwrite_lock_;
};
class Writer {
public:
explicit Writer(ReadWriteLock& rwlock) : readwrite_lock_(rwlock) {}
void Lock() { readwrite_lock_.WriteLock(); }
void Unlock() { readwrite_lock_.WriteUnlock(); }
private:
ReadWriteLock& readwrite_lock_;
};
Reader& GetReader() { return reader_; }
Writer& GetWriter() { return writer_; }
private:
ReadWriteLock(const ReadWriteLock&);
ReadWriteLock& operator=(const ReadWriteLock&);
ReadWriteLock& self() { return *this; }
Mutex read_lock_;
Mutex write_lock_;
embb_counter_t active_readers_;
Reader reader_;
Writer writer_;
};
} // namespace base
} // namespace embb
......
......@@ -30,6 +30,14 @@
#include <assert.h>
#include <algorithm>
#ifdef EMBB_DEBUG
static const size_t INVALID_POINTER = static_cast<size_t>(-1);
# define VERIFY_ADDRESS(addr) assert(reinterpret_cast<size_t>((addr)) != \
INVALID_POINTER)
#else
# define VERIFY_ADDRESS(address) ((void)0)
#endif
namespace embb {
namespace containers {
namespace internal {
......@@ -37,13 +45,13 @@ namespace internal {
template<typename Key, typename Value>
ChromaticTreeNode<Key, Value>::
ChromaticTreeNode(const Key& key, const Value& value, const int weight,
ChromaticTreeNode<Key, Value>* const & left,
ChromaticTreeNode<Key, Value>* const & right)
const ChildPointer& left, const ChildPointer& right)
: key_(key),
value_(value),
weight_(weight),
left_(left),
right_(right) {}
right_(right),
retired_(false) {}
template<typename Key, typename Value>
ChromaticTreeNode<Key, Value>::
......@@ -52,16 +60,8 @@ ChromaticTreeNode(const Key& key, const Value& value, const int weight)
value_(value),
weight_(weight),
left_(NULL),
right_(NULL) {}
template<typename Key, typename Value>
ChromaticTreeNode<Key, Value>::
ChromaticTreeNode(const ChromaticTreeNode& other)
: key_(other.key_),
value_(other.value_),
weight_(other.weight_),
left_(other.left_),
right_(other.right_) {}
right_(NULL),
retired_(false) {}
template<typename Key, typename Value>
const Key& ChromaticTreeNode<Key, Value>::GetKey() const {
......@@ -79,12 +79,14 @@ int ChromaticTreeNode<Key, Value>::GetWeight() const {
}
template<typename Key, typename Value>
ChromaticTreeNode<Key, Value>*& ChromaticTreeNode<Key, Value>::GetLeft() {
typename ChromaticTreeNode<Key, Value>::AtomicChildPointer&
ChromaticTreeNode<Key, Value>::GetLeft() {
return left_;
}
template<typename Key, typename Value>
ChromaticTreeNode<Key, Value>*& ChromaticTreeNode<Key, Value>::GetRight() {
typename ChromaticTreeNode<Key, Value>::AtomicChildPointer&
ChromaticTreeNode<Key, Value>::GetRight() {
return right_;
}
......@@ -95,11 +97,22 @@ template<typename Key, typename Value, typename Compare, typename NodePool>
ChromaticTree<Key, Value, Compare, NodePool>::
ChromaticTree(size_t capacity, Key undefined_key, Value undefined_value,
Compare compare)
: undefined_key_(undefined_key),
#ifdef EMBB_PLATFORM_COMPILER_MSVC
#pragma warning(push)
#pragma warning(disable:4355)
#endif
: free_node_callback_(*this, &ChromaticTree::FreeNode),
#ifdef EMBB_PLATFORM_COMPILER_MSVC
#pragma warning(pop)
#endif
node_hazard_manager_(free_node_callback_, NULL, 8),
undefined_key_(undefined_key),
undefined_value_(undefined_value),
compare_(compare),
capacity_(capacity),
node_pool_(2 + 5 + 2 * 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;
......@@ -109,25 +122,26 @@ template<typename Key, typename Value, typename Compare, typename NodePool>
ChromaticTree<Key, Value, Compare, NodePool>::
~ChromaticTree() {
Destruct(entry_->GetLeft());
node_pool_.Free(entry_);
FreeNode(entry_);
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
Get(const Key& key, Value& value) {
ReaderLockGuard guard(readwrite_lock_.GetReader());
NodePtr leaf;
Search(key, leaf);
bool keys_are_equal = !(compare_(key, leaf->GetKey()) ||
bool keys_are_equal = !IsSentinel(leaf) &&
!(compare_(key, leaf->GetKey()) ||
compare_(leaf->GetKey(), key));
if (!IsSentinel(leaf) && keys_are_equal) {
if (keys_are_equal) {
value = leaf->GetValue();
return true;
} else {
return false;
}
node_hazard_manager_.GuardPointer(0, NULL);
return keys_are_equal;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
......@@ -140,65 +154,75 @@ TryInsert(const Key& key, const Value& value) {
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
TryInsert(const Key& key, const Value& value, Value& old_value) {
WriterLockGuard guard(readwrite_lock_.GetWriter());
NodePtr leaf, parent;
Search(key, leaf, parent);
assert(HasChild(parent, leaf));
NodePtr new_leaf = NULL;
NodePtr new_sibling = NULL;
NodePtr new_parent = NULL;
bool insertion_succeeded = false;
while (!insertion_succeeded) {
NodePtr leaf, parent;
Search(key, leaf, parent);
// Try to lock the parent
UniqueLock parent_lock(parent->GetMutex(), embb::base::try_lock);
if (!parent_lock.OwnsLock() || parent->IsRetired()) continue;
// Verify that the leaf is still the parent's child
if (!HasChild(parent, leaf)) continue;
// Try to lock the leaf
UniqueLock leaf_lock(leaf->GetMutex(), embb::base::try_lock);
if (!leaf_lock.OwnsLock() || leaf->IsRetired()) continue;
// Reached leaf has a matching key: replace it with a new copy
if (!IsSentinel(leaf) && !(compare_(key, leaf->GetKey()) ||
compare_(leaf->GetKey(), key))) {
old_value = leaf->GetValue();
new_parent = node_pool_.Allocate(key, value, leaf->GetWeight());
if (new_parent == NULL) break;
// Reached leaf has a different key: add a new leaf
} else {
old_value = undefined_value_;
NodePtr new_parent;
bool added_violation = false;
new_leaf = node_pool_.Allocate(key, value);
if (new_leaf == NULL) break;
new_sibling = node_pool_.Allocate(leaf->GetKey(), leaf->GetValue());
if (new_sibling == NULL) break;
bool keys_are_equal = !(compare_(key, leaf->GetKey()) ||
compare_(leaf->GetKey(), key));
if (!IsSentinel(leaf) && keys_are_equal) {
old_value = leaf->GetValue();
new_parent = node_pool_.Allocate(key, value, leaf->GetWeight());
if (new_parent == NULL) {
return false;
int new_weight = (HasFixedWeight(leaf)) ? 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);
} else {
new_parent = node_pool_.Allocate(key, undefined_value_,
new_weight, new_sibling, new_leaf);
}
if (new_parent == NULL) break;
}
} else {
old_value = undefined_value_;
NodePtr new_leaf = node_pool_.Allocate(key, value);
if (new_leaf == NULL) {
return false;
}
NodePtr new_sibling = node_pool_.Allocate(*leaf);
if (new_sibling == NULL) {
node_pool_.Free(new_leaf);
return false;
}
GetPointerToChild(parent, leaf).CompareAndSwap(leaf, new_parent);
int new_weight = (HasFixedWeight(leaf)) ? 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);
} else {
new_parent = node_pool_.Allocate(
key, undefined_value_, new_weight, new_sibling, new_leaf);
}
insertion_succeeded = true;
if (new_parent == NULL) {
node_pool_.Free(new_leaf);
node_pool_.Free(new_sibling);
return false;
}
leaf->Retire();
leaf_lock.Unlock();
node_hazard_manager_.GuardPointer(1, NULL);
RemoveNode(leaf);
added_violation = (parent->GetWeight() == 0 && new_weight == 0);
// if (parent->GetWeight() == 0 && new_parent->GetWeight() == 0) {
// CleanUp(key);
// }
}
node_hazard_manager_.GuardPointer(0, NULL);
node_hazard_manager_.GuardPointer(1, NULL);
NodePtr& new_subtree_ptr = GetPointerToChild(parent, leaf);
new_subtree_ptr = new_parent;
node_pool_.Free(leaf);
if (added_violation) {
CleanUp(key);
if (!insertion_succeeded) {
if (new_leaf != NULL) FreeNode(new_leaf);
if (new_sibling != NULL) FreeNode(new_sibling);
if (new_parent != NULL) FreeNode(new_parent);
}
return true;
return insertion_succeeded;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
......@@ -211,47 +235,89 @@ TryDelete(const Key& key) {
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
TryDelete(const Key& key, Value& old_value) {
WriterLockGuard guard(readwrite_lock_.GetWriter());
NodePtr leaf, parent, grandparent;
Search(key, leaf, parent, grandparent);
bool keys_are_equal = !(compare_(key, leaf->GetKey()) ||
compare_(leaf->GetKey(), key));
if (IsSentinel(leaf) || !keys_are_equal) {
old_value = undefined_value_;
return false;
}
assert(HasChild(grandparent, parent));
assert(HasChild(parent, leaf));
NodePtr new_leaf = NULL;
bool deletion_succeeded = false;
while (!deletion_succeeded) {
NodePtr leaf, parent, grandparent;
Search(key, leaf, parent, grandparent);
// Reached leaf has a different key - nothing to delete
if (IsSentinel(leaf) || (compare_(key, leaf->GetKey()) ||
compare_(leaf->GetKey(), key))) {
old_value = undefined_value_;
deletion_succeeded = true;
break;
}
NodePtr sibling = ((parent->GetLeft() == leaf) ?
parent->GetRight() : parent->GetLeft());
// Try to lock the grandparent
UniqueLock grandparent_lock(grandparent->GetMutex(), embb::base::try_lock);
if (!grandparent_lock.OwnsLock() || grandparent->IsRetired()) continue;
// Verify that the parent is still the grandparent's child
if (!HasChild(grandparent, parent)) continue;
// Try to lock the parent
UniqueLock parent_lock(parent->GetMutex(), embb::base::try_lock);
if (!parent_lock.OwnsLock() || parent->IsRetired()) continue;
// Verify that the leaf is still the parent's child
if (!HasChild(parent, leaf)) continue;
AtomicNodePtr& other_child = ((parent->GetLeft() == leaf) ?
parent->GetRight() : parent->GetLeft());
NodePtr sibling = other_child;
node_hazard_manager_.GuardPointer(3, sibling);
if (sibling != other_child) continue;
VERIFY_ADDRESS(sibling);
// Try to lock the sibling
UniqueLock sibling_lock(sibling->GetMutex(), embb::base::try_lock);
if (!sibling_lock.OwnsLock() || sibling->IsRetired()) continue;
// Try to lock the leaf
UniqueLock leaf_lock(leaf->GetMutex(), embb::base::try_lock);
if (!leaf_lock.OwnsLock() || leaf->IsRetired()) continue;
int new_weight = (HasFixedWeight(parent)) ?
1 : (parent->GetWeight() + sibling->GetWeight());
new_leaf = node_pool_.Allocate(
sibling->GetKey(), sibling->GetValue(), new_weight,
sibling->GetLeft(), sibling->GetRight());
if (new_leaf == NULL) break;
int new_weight = (HasFixedWeight(parent)) ?
1 : (parent->GetWeight() + sibling->GetWeight());
bool added_violation = (new_weight > 1);
old_value = leaf->GetValue();
NodePtr new_leaf = node_pool_.Allocate(
sibling->GetKey(), sibling->GetValue(), new_weight,
sibling->GetLeft(), sibling->GetRight());
assert((new_leaf != NULL) && "No nodes available for replacement!");
GetPointerToChild(grandparent, parent).CompareAndSwap(parent, new_leaf);
NodePtr& new_subtree_ptr = GetPointerToChild(grandparent, parent);
new_subtree_ptr = new_leaf;
deletion_succeeded = true;
old_value = leaf->GetValue();
parent->Retire();
parent_lock.Unlock();
node_hazard_manager_.GuardPointer(1, NULL);
RemoveNode(parent);
leaf->Retire();
leaf_lock.Unlock();
node_hazard_manager_.GuardPointer(2, NULL);
RemoveNode(leaf);
sibling->Retire();
sibling_lock.Unlock();
node_hazard_manager_.GuardPointer(3, NULL);
RemoveNode(sibling);
node_pool_.Free(leaf);
node_pool_.Free(sibling);
node_pool_.Free(parent);
// if (new_weight > 1) {
// CleanUp(key);
// }
}
node_hazard_manager_.GuardPointer(0, NULL);
node_hazard_manager_.GuardPointer(1, NULL);
node_hazard_manager_.GuardPointer(2, NULL);
node_hazard_manager_.GuardPointer(3, NULL);
if (added_violation) {
CleanUp(key);
if (!deletion_succeeded) {
if (new_leaf != NULL) FreeNode(new_leaf);
}
return true;
return deletion_succeeded;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
......@@ -274,31 +340,77 @@ IsEmpty() {
template<typename Key, typename Value, typename Compare, typename NodePool>
void ChromaticTree<Key, Value, Compare, NodePool>::
Search(const Key& key, NodePtr& leaf) const {
Search(const Key& key, NodePtr& leaf) {
NodePtr parent;
Search(key, leaf, parent);
node_hazard_manager_.GuardPointer(0, leaf);
node_hazard_manager_.GuardPointer(1, NULL);
}
template<typename Key, typename Value, typename Compare, typename NodePool>
void ChromaticTree<Key, Value, Compare, NodePool>::
Search(const Key& key, NodePtr& leaf, NodePtr& parent) const {
NodePtr grandparent;
Search(key, leaf, parent, grandparent);
Search(const Key& key, NodePtr& leaf, NodePtr& parent) {
bool reached_leaf = false;
while (!reached_leaf) {
parent = entry_;
node_hazard_manager_.GuardPointer(0, parent);
leaf = entry_->GetLeft();
node_hazard_manager_.GuardPointer(1, leaf);
if (leaf != entry_->GetLeft()) continue;
reached_leaf = IsLeaf(leaf);
while (!reached_leaf) {
parent = leaf;
node_hazard_manager_.GuardPointer(0, parent);
AtomicNodePtr& next_leaf =
(IsSentinel(leaf) || compare_(key, leaf->GetKey())) ?
leaf->GetLeft() : leaf->GetRight();
leaf = next_leaf;
node_hazard_manager_.GuardPointer(1, leaf);
if (leaf != next_leaf || parent->IsRetired()) break;
VERIFY_ADDRESS(leaf);
reached_leaf = IsLeaf(leaf);
}
}
}
template<typename Key, typename Value, typename Compare, typename NodePool>
void ChromaticTree<Key, Value, Compare, NodePool>::
Search(const Key& key, NodePtr& leaf, NodePtr& parent,
NodePtr& grandparent) const {
grandparent = NULL;
parent = entry_;
leaf = entry_->GetLeft();
while (!IsLeaf(leaf)) {
grandparent = parent;
parent = leaf;
leaf = (IsSentinel(leaf) || compare_(key, leaf->GetKey())) ?
leaf->GetLeft() : leaf->GetRight();
Search(const Key& key, NodePtr& leaf, NodePtr& parent, NodePtr& grandparent) {
bool reached_leaf = false;
while (!reached_leaf) {
grandparent = NULL;
parent = entry_;
node_hazard_manager_.GuardPointer(1, parent);
leaf = entry_->GetLeft();
node_hazard_manager_.GuardPointer(2, leaf);
if (leaf != entry_->GetLeft()) continue;
reached_leaf = IsLeaf(leaf);
while (!reached_leaf) {
grandparent = parent;
node_hazard_manager_.GuardPointer(0, grandparent);
parent = leaf;
node_hazard_manager_.GuardPointer(1, parent);
AtomicNodePtr& next_leaf =
(IsSentinel(leaf) || compare_(key, leaf->GetKey())) ?
leaf->GetLeft() : leaf->GetRight();
leaf = next_leaf;
node_hazard_manager_.GuardPointer(2, leaf);
if (leaf != next_leaf || parent->IsRetired()) break;
VERIFY_ADDRESS(leaf);
reached_leaf = IsLeaf(leaf);
}
}
}
......@@ -327,7 +439,7 @@ HasChild(const NodePtr& parent, const NodePtr& child) const {
}
template<typename Key, typename Value, typename Compare, typename NodePool>
typename ChromaticTree<Key, Value, Compare, NodePool>::NodePtr&
typename ChromaticTree<Key, Value, Compare, NodePool>::AtomicNodePtr&
ChromaticTree<Key, Value, Compare, NodePool>::
GetPointerToChild(const NodePtr& parent, const NodePtr& child) const {
assert(HasChild(parent, child));
......@@ -341,13 +453,63 @@ Destruct(const NodePtr& node) {
Destruct(node->GetLeft());
Destruct(node->GetRight());
}
FreeNode(node);
}
template<typename Key, typename Value, typename Compare, typename NodePool>
int ChromaticTree<Key, Value, Compare, NodePool>::
GetHeight(const NodePtr& node) const {
int height = 0;
if (node != NULL) {
height = 1 + ::std::max(GetHeight(node->GetLeft()),
GetHeight(node->GetRight()));
}
return height;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
IsBalanced() const {
return IsBalanced(entry_->GetLeft());
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
IsBalanced(const NodePtr& node) const {
// Overweight violation
bool has_violation = node->GetWeight() > 1;
if (!has_violation && !IsLeaf(node)) {
NodePtr left = node->GetLeft();
NodePtr right = node->GetRight();
// Red-red violation
has_violation = node->GetWeight() == 0 &&
(left->GetWeight() == 0 || right->GetWeight() == 0);
// Check children
if (!has_violation) {
has_violation = !IsBalanced(left) || !IsBalanced(right);
}
}
return !has_violation;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
void ChromaticTree<Key, Value, Compare, NodePool>::
FreeNode(NodePtr node) {
#ifdef EMBB_DEBUG
node->GetLeft() = reinterpret_cast<NodePtr>(INVALID_POINTER);
node->GetRight() = reinterpret_cast<NodePtr>(INVALID_POINTER);
#endif
node_pool_.Free(node);
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
CleanUp(const Key& key) {
while (true) {
for (;;) {
NodePtr grandgrandparent = NULL;
NodePtr grandparent = NULL;
NodePtr parent = entry_;
......@@ -360,6 +522,7 @@ CleanUp(const Key& key) {
parent = leaf;
leaf = (IsSentinel(leaf) || compare_(key, leaf->GetKey())) ?
leaf->GetLeft() : leaf->GetRight();
VERIFY_ADDRESS(leaf);
}
if (leaf->GetWeight() == 1) {
......@@ -382,14 +545,14 @@ Rebalance(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
if (!HasChild(u, ux)) return false;
//TODO: weakLLX(ux);
NodePtr uxl = ux->GetLeft();
NodePtr uxr = ux->GetRight();
NodePtr uxl = ux->GetLeft(); VERIFY_ADDRESS(uxl);
NodePtr uxr = ux->GetRight(); VERIFY_ADDRESS(uxr);
bool uxx_is_left = (uxx == uxl);
if (!HasChild(ux, uxx)) return false;
//TODO: weakLLX(uxx);
NodePtr uxxl = uxx->GetLeft();
NodePtr uxxr = uxx->GetRight();
NodePtr uxxl = uxx->GetLeft(); VERIFY_ADDRESS(uxxl);
NodePtr uxxr = uxx->GetRight(); VERIFY_ADDRESS(uxxr);
bool uxxx_is_left = (uxxx == uxxl);
if (!HasChild(uxx, uxxx)) return false;
......@@ -471,7 +634,7 @@ OverweightLeft(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
assert(uxx->GetWeight() > 0);
//TODO: weakLLX(uxxr);
// Note: we know that 'uxxr' is not a leaf because it has weight 0.
NodePtr uxxrl = uxxr->GetLeft();
NodePtr uxxrl = uxxr->GetLeft(); VERIFY_ADDRESS(uxxrl);
//TODO: weakLLX(uxxrl);
// Root -> Middle -> Right -> Left
......@@ -480,8 +643,8 @@ OverweightLeft(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
// Root -> Middle -> Right -> Middle
} else if (uxxrl->GetWeight() == 1) {
NodePtr uxxrll = uxxrl->GetLeft();
NodePtr uxxrlr = uxxrl->GetRight();
NodePtr uxxrll = uxxrl->GetLeft(); VERIFY_ADDRESS(uxxrll);
NodePtr uxxrlr = uxxrl->GetRight(); VERIFY_ADDRESS(uxxrlr);
if (uxxrlr == NULL) return false;
// Root -> Middle -> Right -> Middle -> Left
......@@ -514,8 +677,8 @@ OverweightLeft(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
// Root -> Right
} else if (uxxr->GetWeight() == 1) {
//TODO: weakLLX(uxxr);
NodePtr uxxrl = uxxr->GetLeft();
NodePtr uxxrr = uxxr->GetRight();
NodePtr uxxrl = uxxr->GetLeft(); VERIFY_ADDRESS(uxxrl);
NodePtr uxxrr = uxxr->GetRight(); VERIFY_ADDRESS(uxxrr);
if (uxxrl == NULL) return false;
// Root -> Right -> Left
......@@ -544,8 +707,6 @@ OverweightLeft(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
//TODO: weakLLX(uxxr);
return W7(ux, uxx, uxxl, uxxr);
}
return true;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
......@@ -593,7 +754,7 @@ OverweightRight(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
assert(uxx->GetWeight() > 0);
//TODO: weakLLX(uxxl);
// Note: we know that 'uxxl' is not a leaf because it has weight 0.
NodePtr uxxlr = uxxl->GetRight();
NodePtr uxxlr = uxxl->GetRight(); VERIFY_ADDRESS(uxxlr);
//TODO: weakLLX(uxxlr);
// Root -> Middle -> Right -> Left
......@@ -602,8 +763,8 @@ OverweightRight(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
// Root -> Middle -> Right -> Middle
} else if (uxxlr->GetWeight() == 1) {
NodePtr uxxlrl = uxxlr->GetLeft();
NodePtr uxxlrr = uxxlr->GetRight();
NodePtr uxxlrl = uxxlr->GetLeft(); VERIFY_ADDRESS(uxxlrl);
NodePtr uxxlrr = uxxlr->GetRight(); VERIFY_ADDRESS(uxxlrr);
if (uxxlrl == NULL) return false;
// Root -> Middle -> Right -> Middle -> Left
......@@ -636,8 +797,8 @@ OverweightRight(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
// Root -> Right
} else if (uxxl->GetWeight() == 1) {
//TODO: weakLLX(uxxl);
NodePtr uxxll = uxxl->GetLeft();
NodePtr uxxlr = uxxl->GetRight();
NodePtr uxxll = uxxl->GetLeft(); VERIFY_ADDRESS(uxxll);
NodePtr uxxlr = uxxl->GetRight(); VERIFY_ADDRESS(uxxlr);
if (uxxll == NULL) return false;
// Root -> Right -> Left
......@@ -666,923 +827,8 @@ OverweightRight(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
//TODO: weakLLX(uxxl);
return W7(ux, uxx, uxxl, uxxr);
}
return true;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
int ChromaticTree<Key, Value, Compare, NodePool>::
GetHeight(const NodePtr& node) const {
int height = 0;
if (node != NULL) {
height = 1 + ::std::max(GetHeight(node->GetLeft()),
GetHeight(node->GetRight()));
}
return height;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
IsBalanced() const {
return IsBalanced(entry_->GetLeft());
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
IsBalanced(const NodePtr& node) const {
// Overweight violation
bool has_violation = node->GetWeight() > 1;
if (!has_violation && !IsLeaf(node)) {
NodePtr left = node->GetLeft();
NodePtr right = node->GetRight();
// Red-red violation
has_violation = node->GetWeight() == 0 &&
(left->GetWeight() == 0 || right->GetWeight() == 0);
// Check children
if (!has_violation) {
has_violation = !IsBalanced(left) || !IsBalanced(right);
}
}
return !has_violation;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
BLK(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr) {
NodePtr nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nx = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
HasFixedWeight(ux) ? 1 : ux->GetWeight() - 1,
nxl, nxr);
if (nxl == NULL ||
nxr == NULL ||
nx == NULL) {
if (nxl) node_pool_.Free(nxl);
if (nxr) node_pool_.Free(nxr);
if (nx) node_pool_.Free(nx);
return false;
}
NodePtr& new_subtree_ptr = GetPointerToChild(u, ux);
new_subtree_ptr = nx;
node_pool_.Free(ux);
node_pool_.Free(uxl);
node_pool_.Free(uxr);
return true;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
PUSH_L(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr) {
NodePtr nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
0,
uxr->GetLeft(), uxr->GetRight());
NodePtr nx = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
HasFixedWeight(ux) ? 1 : ux->GetWeight() + 1,
nxl, nxr);
if (nxl == NULL ||
nxr == NULL ||
nx == NULL) {
if (nxl) node_pool_.Free(nxl);
if (nxr) node_pool_.Free(nxr);
if (nx) node_pool_.Free(nx);
return false;
}
NodePtr& new_subtree_ptr = GetPointerToChild(u, ux);
new_subtree_ptr = nx;
node_pool_.Free(ux);
node_pool_.Free(uxl);
node_pool_.Free(uxr);
return true;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
PUSH_R(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr) {
NodePtr nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
0,
uxl->GetLeft(), uxl->GetRight());
NodePtr nx = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
HasFixedWeight(ux) ? 1 : ux->GetWeight() + 1,
nxl, nxr);
if (nxr == NULL ||
nxl == NULL ||
nx == NULL) {
if (nxr) node_pool_.Free(nxr);
if (nxl) node_pool_.Free(nxl);
if (nx) node_pool_.Free(nx);
return false;
}
NodePtr& new_subtree_ptr = GetPointerToChild(u, ux);
new_subtree_ptr = nx;
node_pool_.Free(ux);
node_pool_.Free(uxl);
node_pool_.Free(uxr);
return true;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
RB1_L(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl) {
NodePtr nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
0,
uxl->GetRight(), ux->GetRight());
NodePtr nx = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
ux->GetWeight(),
uxl->GetLeft(), nxr);
if (nxr == NULL ||
nx == NULL) {
if (nxr) node_pool_.Free(nxr);
if (nx) node_pool_.Free(nx);
return false;
}
NodePtr& new_subtree_ptr = GetPointerToChild(u, ux);
new_subtree_ptr = nx;
node_pool_.Free(ux);
node_pool_.Free(uxl);
return true;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
RB1_R(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxr) {
NodePtr nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
0,
ux->GetLeft(), uxr->GetLeft());
NodePtr nx = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
ux->GetWeight(),
nxl, uxr->GetRight());
if (nxl == NULL ||
nx == NULL) {
if (nxl) node_pool_.Free(nxl);
if (nx) node_pool_.Free(nx);
return false;
}
NodePtr& new_subtree_ptr = GetPointerToChild(u, ux);
new_subtree_ptr = nx;
node_pool_.Free(ux);
node_pool_.Free(uxr);
return true;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
RB2_L(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxlr) {
NodePtr nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
0,
uxl->GetLeft(), uxlr->GetLeft());
NodePtr nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
0,
uxlr->GetRight(), ux->GetRight());
NodePtr nx = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(),
ux->GetWeight(),
nxl, nxr);
if (nxl == NULL ||
nxr == NULL ||
nx == NULL) {
if (nxl) node_pool_.Free(nxl);
if (nxr) node_pool_.Free(nxr);
if (nx) node_pool_.Free(nx);
return false;
}
NodePtr& new_subtree_ptr = GetPointerToChild(u, ux);
new_subtree_ptr = nx;
node_pool_.Free(ux);
node_pool_.Free(uxl);
node_pool_.Free(uxlr);
return true;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
RB2_R(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxr,
const NodePtr& uxrl) {
NodePtr nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
0,
uxrl->GetRight(), uxr->GetRight());
NodePtr nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
0,
ux->GetLeft(), uxrl->GetLeft());
NodePtr nx = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(),
ux->GetWeight(),
nxl, nxr);
if (nxr == NULL ||
nxl == NULL ||
nx == NULL) {
if (nxr) node_pool_.Free(nxr);
if (nxl) node_pool_.Free(nxl);
if (nx) node_pool_.Free(nx);
return false;
}
NodePtr& new_subtree_ptr = GetPointerToChild(u, ux);
new_subtree_ptr = nx;
node_pool_.Free(ux);
node_pool_.Free(uxr);
node_pool_.Free(uxrl);
return true;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
W1_L(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxrl) {
NodePtr nxll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxlr = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(),
uxrl->GetWeight() - 1,
uxrl->GetLeft(), uxrl->GetRight());
NodePtr nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxll, nxlr);
NodePtr nx = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
ux->GetWeight(),
nxl, uxr->GetRight());
if (nxll == NULL ||
nxlr == NULL ||
nxl == NULL ||
nx == NULL) {
if (nxll) node_pool_.Free(nxll);
if (nxlr) node_pool_.Free(nxlr);
if (nxl) node_pool_.Free(nxl);
if (nx) node_pool_.Free(nx);
return false;
}
NodePtr& new_subtree_ptr = GetPointerToChild(u, ux);
new_subtree_ptr = nx;
node_pool_.Free(ux);
node_pool_.Free(uxl);
node_pool_.Free(uxr);
node_pool_.Free(uxrl);
return true;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
W1_R(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxlr) {
NodePtr nxrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nxrl = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(),
uxlr->GetWeight() - 1,
uxlr->GetLeft(), uxlr->GetRight());
NodePtr nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxrl, nxrr);
NodePtr nx = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
ux->GetWeight(),
uxl->GetLeft(), nxr);
if (nxrr == NULL ||
nxrl == NULL ||
nxr == NULL ||
nx == NULL) {
if (nxrr) node_pool_.Free(nxrr);
if (nxrl) node_pool_.Free(nxrl);
if (nxr) node_pool_.Free(nxr);
if (nx) node_pool_.Free(nx);
return false;
}
NodePtr& new_subtree_ptr = GetPointerToChild(u, ux);
new_subtree_ptr = nx;
node_pool_.Free(ux);
node_pool_.Free(uxl);
node_pool_.Free(uxr);
node_pool_.Free(uxlr);
return true;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
W2_L(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxrl) {
NodePtr nxll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxlr = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(),
0,
uxrl->GetLeft(), uxrl->GetRight());
NodePtr nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxll, nxlr);
NodePtr nx = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
ux->GetWeight(),
nxl, uxr->GetRight());
if (nxll == NULL ||
nxlr == NULL ||
nxl == NULL ||
nx == NULL) {
if (nxll) node_pool_.Free(nxll);
if (nxlr) node_pool_.Free(nxlr);
if (nxl) node_pool_.Free(nxl);
if (nx) node_pool_.Free(nx);
return false;
}
NodePtr& new_subtree_ptr = GetPointerToChild(u, ux);
new_subtree_ptr = nx;
node_pool_.Free(ux);
node_pool_.Free(uxl);
node_pool_.Free(uxr);
node_pool_.Free(uxrl);
return true;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
W2_R(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxlr) {
NodePtr nxrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nxrl = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(),
0,
uxlr->GetLeft(), uxlr->GetRight());
NodePtr nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxrl, nxrr);
NodePtr nx = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
ux->GetWeight(),
uxl->GetLeft(), nxr);
if (nxrr == NULL ||
nxrl == NULL ||
nxr == NULL ||
nx == NULL) {
if (nxrr) node_pool_.Free(nxrr);
if (nxrl) node_pool_.Free(nxrl);
if (nxr) node_pool_.Free(nxr);
if (nx) node_pool_.Free(nx);
return false;
}
NodePtr& new_subtree_ptr = GetPointerToChild(u, ux);
new_subtree_ptr = nx;
node_pool_.Free(ux);
node_pool_.Free(uxl);
node_pool_.Free(uxr);
node_pool_.Free(uxlr);
return true;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
W3_L(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxrl,
const NodePtr& uxrll) {
NodePtr nxlll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxll = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxlll, uxrll->GetLeft());
NodePtr nxlr = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(),
1,
uxrll->GetRight(), uxrl->GetRight());
NodePtr nxl = node_pool_.Allocate(
uxrll->GetKey(), uxrll->GetValue(),
0,
nxll, nxlr);
NodePtr nx = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
ux->GetWeight(),
nxl, uxr->GetRight());
if (nxlll == NULL ||
nxll == NULL ||
nxlr == NULL ||
nxl == NULL ||
nx == NULL) {
if (nxlll) node_pool_.Free(nxlll);
if (nxll) node_pool_.Free(nxll);
if (nxlr) node_pool_.Free(nxlr);
if (nxl) node_pool_.Free(nxl);
if (nx) node_pool_.Free(nx);
return false;
}
NodePtr& new_subtree_ptr = GetPointerToChild(u, ux);
new_subtree_ptr = nx;
node_pool_.Free(ux);
node_pool_.Free(uxl);
node_pool_.Free(uxr);
node_pool_.Free(uxrl);
node_pool_.Free(uxrll);
return true;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
W3_R(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxlr,
const NodePtr& uxlrr) {
NodePtr nxrrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nxrr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
uxlrr->GetRight(), nxrrr);
NodePtr nxrl = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(),
1,
uxlr->GetLeft(), uxlrr->GetLeft());
NodePtr nxr = node_pool_.Allocate(
uxlrr->GetKey(), uxlrr->GetValue(),
0,
nxrl, nxrr);
NodePtr nx = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
ux->GetWeight(),
uxl->GetLeft(), nxr);
if (nxrrr == NULL ||
nxrr == NULL ||
nxrl == NULL ||
nxr == NULL ||
nx == NULL) {
if (nxrrr) node_pool_.Free(nxrrr);
if (nxrr) node_pool_.Free(nxrr);
if (nxrl) node_pool_.Free(nxrl);
if (nxr) node_pool_.Free(nxr);
if (nx) node_pool_.Free(nx);
return false;
}
NodePtr& new_subtree_ptr = GetPointerToChild(u, ux);
new_subtree_ptr = nx;
node_pool_.Free(ux);
node_pool_.Free(uxl);
node_pool_.Free(uxr);
node_pool_.Free(uxlr);
node_pool_.Free(uxlrr);
return true;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
W4_L(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxrl,
const NodePtr& uxrlr) {
NodePtr nxll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxrl = node_pool_.Allocate(
uxrlr->GetKey(), uxrlr->GetValue(),
1,
uxrlr->GetLeft(), uxrlr->GetRight());
NodePtr nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxll, uxrl->GetLeft());
NodePtr nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
0,
nxrl, uxr->GetRight());
NodePtr nx = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(),
ux->GetWeight(),
nxl, nxr);
if (nxll == NULL ||
nxrl == NULL ||
nxl == NULL ||
nxr == NULL ||
nx == NULL) {
if (nxll) node_pool_.Free(nxll);
if (nxrl) node_pool_.Free(nxrl);
if (nxl) node_pool_.Free(nxl);
if (nxr) node_pool_.Free(nxr);
if (nx) node_pool_.Free(nx);
return false;
}
NodePtr& new_subtree_ptr = GetPointerToChild(u, ux);
new_subtree_ptr = nx;
node_pool_.Free(ux);
node_pool_.Free(uxl);
node_pool_.Free(uxr);
node_pool_.Free(uxrl);
node_pool_.Free(uxrlr);
return true;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
W4_R(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxlr,
const NodePtr& uxlrl) {
NodePtr nxrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nxlr = node_pool_.Allocate(
uxlrl->GetKey(), uxlrl->GetValue(),
1,
uxlrl->GetLeft(), uxlrl->GetRight());
NodePtr nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
uxlr->GetRight(), nxrr);
NodePtr nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
0,
uxl->GetLeft(), nxlr);
NodePtr nx = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(),
ux->GetWeight(),
nxl, nxr);
if (nxrr == NULL ||
nxlr == NULL ||
nxr == NULL ||
nxl == NULL ||
nx == NULL) {
if (nxrr) node_pool_.Free(nxrr);
if (nxlr) node_pool_.Free(nxlr);
if (nxr) node_pool_.Free(nxr);
if (nxl) node_pool_.Free(nxl);
if (nx) node_pool_.Free(nx);
return false;
}
NodePtr& new_subtree_ptr = GetPointerToChild(u, ux);
new_subtree_ptr = nx;
node_pool_.Free(ux);
node_pool_.Free(uxl);
node_pool_.Free(uxr);
node_pool_.Free(uxlr);
node_pool_.Free(uxlrl);
return true;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
W5_L(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxrr) {
NodePtr nxll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxll, uxr->GetLeft());
NodePtr nxr = node_pool_.Allocate(
uxrr->GetKey(), uxrr->GetValue(),
1,
uxrr->GetLeft(), uxrr->GetRight());
NodePtr nx = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
ux->GetWeight(),
nxl, nxr);
if (nxll == NULL ||
nxl == NULL ||
nxr == NULL ||
nx == NULL) {
if (nxll) node_pool_.Free(nxll);
if (nxl) node_pool_.Free(nxl);
if (nxr) node_pool_.Free(nxr);
if (nx) node_pool_.Free(nx);
return false;
}
NodePtr& new_subtree_ptr = GetPointerToChild(u, ux);
new_subtree_ptr = nx;
node_pool_.Free(ux);
node_pool_.Free(uxl);
node_pool_.Free(uxr);
node_pool_.Free(uxrr);
return true;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
W5_R(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxll) {
NodePtr nxrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
uxl->GetRight(), nxrr);
NodePtr nxl = node_pool_.Allocate(
uxll->GetKey(), uxll->GetValue(),
1,
uxll->GetLeft(), uxll->GetRight());
NodePtr nx = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
ux->GetWeight(),
nxl, nxr);
if (nxrr == NULL ||
nxr == NULL ||
nxl == NULL ||
nx == NULL) {
if (nxrr) node_pool_.Free(nxrr);
if (nxr) node_pool_.Free(nxr);
if (nxl) node_pool_.Free(nxl);
if (nx) node_pool_.Free(nx);
return false;
}
NodePtr& new_subtree_ptr = GetPointerToChild(u, ux);
new_subtree_ptr = nx;
node_pool_.Free(ux);
node_pool_.Free(uxl);
node_pool_.Free(uxr);
node_pool_.Free(uxll);
return true;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
W6_L(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxrl) {
NodePtr nxll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxll, uxrl->GetLeft());
NodePtr nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
1,
uxrl->GetRight(), uxr->GetRight());
NodePtr nx = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(),
ux->GetWeight(),
nxl, nxr);
if (nxll == NULL ||
nxl == NULL ||
nxr == NULL ||
nx == NULL) {
if (nxll) node_pool_.Free(nxll);
if (nxl) node_pool_.Free(nxl);
if (nxr) node_pool_.Free(nxr);
if (nx) node_pool_.Free(nx);
return false;
}
NodePtr& new_subtree_ptr = GetPointerToChild(u, ux);
new_subtree_ptr = nx;
node_pool_.Free(ux);
node_pool_.Free(uxl);
node_pool_.Free(uxr);
node_pool_.Free(uxrl);
return true;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
W6_R(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxlr) {
NodePtr nxrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
uxlr->GetRight(), nxrr);
NodePtr nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
1,
uxl->GetLeft(), uxlr->GetLeft());
NodePtr nx = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(),
ux->GetWeight(),
nxl, nxr);
if (nxrr == NULL ||
nxr == NULL ||
nxl == NULL ||
nx == NULL) {
if (nxrr) node_pool_.Free(nxrr);
if (nxr) node_pool_.Free(nxr);
if (nxl) node_pool_.Free(nxl);
if (nx) node_pool_.Free(nx);
return false;
}
NodePtr& new_subtree_ptr = GetPointerToChild(u, ux);
new_subtree_ptr = nx;
node_pool_.Free(ux);
node_pool_.Free(uxl);
node_pool_.Free(uxr);
node_pool_.Free(uxlr);
return true;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
W7(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr) {
NodePtr nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nx = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
HasFixedWeight(ux) ? 1 : ux->GetWeight() + 1,
nxl, nxr);
if (nxl == NULL ||
nxr == NULL ||
nx == NULL) {
if (nxl) node_pool_.Free(nxl);
if (nxr) node_pool_.Free(nxr);
if (nx) node_pool_.Free(nx);
return false;
}
NodePtr& new_subtree_ptr = GetPointerToChild(u, ux);
new_subtree_ptr = nx;
node_pool_.Free(ux);
node_pool_.Free(uxl);
node_pool_.Free(uxr);
return true;
}
} // namespace containers
} // namespace embb
......
/*
* Copyright (c) 2014-2015, Siemens AG. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR 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.
*/
//
// This file was created automatically by a code generator.
// 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_
bool BLK(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr) {
NodePtr nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nx = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
HasFixedWeight(ux) ? 1 : ux->GetWeight() - 1,
nxl, nxr);
if (nxl == NULL ||
nxr == NULL ||
nx == NULL) {
if (nxl) FreeNode(nxl);
if (nxr) FreeNode(nxr);
if (nx) FreeNode(nx);
return false;
}
NodePtr expected = ux;
GetPointerToChild(u, ux).CompareAndSwap(expected, nx);
RetireNode(ux);
RetireNode(uxl);
RetireNode(uxr);
return true;
}
bool PUSH_L(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr) {
NodePtr nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
0,
uxr->GetLeft(), uxr->GetRight());
NodePtr nx = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
HasFixedWeight(ux) ? 1 : ux->GetWeight() + 1,
nxl, nxr);
if (nxl == NULL ||
nxr == NULL ||
nx == NULL) {
if (nxl) FreeNode(nxl);
if (nxr) FreeNode(nxr);
if (nx) FreeNode(nx);
return false;
}
NodePtr expected = ux;
GetPointerToChild(u, ux).CompareAndSwap(expected, nx);
RetireNode(ux);
RetireNode(uxl);
RetireNode(uxr);
return true;
}
bool PUSH_R(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr) {
NodePtr nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
0,
uxl->GetLeft(), uxl->GetRight());
NodePtr nx = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
HasFixedWeight(ux) ? 1 : ux->GetWeight() + 1,
nxl, nxr);
if (nxr == NULL ||
nxl == NULL ||
nx == NULL) {
if (nxr) FreeNode(nxr);
if (nxl) FreeNode(nxl);
if (nx) FreeNode(nx);
return false;
}
NodePtr expected = ux;
GetPointerToChild(u, ux).CompareAndSwap(expected, nx);
RetireNode(ux);
RetireNode(uxl);
RetireNode(uxr);
return true;
}
bool RB1_L(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl) {
NodePtr nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
0,
uxl->GetRight(), ux->GetRight());
NodePtr nx = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
ux->GetWeight(),
uxl->GetLeft(), nxr);
if (nxr == NULL ||
nx == NULL) {
if (nxr) FreeNode(nxr);
if (nx) FreeNode(nx);
return false;
}
NodePtr expected = ux;
GetPointerToChild(u, ux).CompareAndSwap(expected, nx);
RetireNode(ux);
RetireNode(uxl);
return true;
}
bool RB1_R(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxr) {
NodePtr nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
0,
ux->GetLeft(), uxr->GetLeft());
NodePtr nx = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
ux->GetWeight(),
nxl, uxr->GetRight());
if (nxl == NULL ||
nx == NULL) {
if (nxl) FreeNode(nxl);
if (nx) FreeNode(nx);
return false;
}
NodePtr expected = ux;
GetPointerToChild(u, ux).CompareAndSwap(expected, nx);
RetireNode(ux);
RetireNode(uxr);
return true;
}
bool RB2_L(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxlr) {
NodePtr nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
0,
uxl->GetLeft(), uxlr->GetLeft());
NodePtr nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
0,
uxlr->GetRight(), ux->GetRight());
NodePtr nx = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(),
ux->GetWeight(),
nxl, nxr);
if (nxl == NULL ||
nxr == NULL ||
nx == NULL) {
if (nxl) FreeNode(nxl);
if (nxr) FreeNode(nxr);
if (nx) FreeNode(nx);
return false;
}
NodePtr expected = ux;
GetPointerToChild(u, ux).CompareAndSwap(expected, nx);
RetireNode(ux);
RetireNode(uxl);
RetireNode(uxlr);
return true;
}
bool RB2_R(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxr,
const NodePtr& uxrl) {
NodePtr nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
0,
uxrl->GetRight(), uxr->GetRight());
NodePtr nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
0,
ux->GetLeft(), uxrl->GetLeft());
NodePtr nx = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(),
ux->GetWeight(),
nxl, nxr);
if (nxr == NULL ||
nxl == NULL ||
nx == NULL) {
if (nxr) FreeNode(nxr);
if (nxl) FreeNode(nxl);
if (nx) FreeNode(nx);
return false;
}
NodePtr expected = ux;
GetPointerToChild(u, ux).CompareAndSwap(expected, nx);
RetireNode(ux);
RetireNode(uxr);
RetireNode(uxrl);
return true;
}
bool W1_L(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxrl) {
NodePtr nxll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxlr = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(),
uxrl->GetWeight() - 1,
uxrl->GetLeft(), uxrl->GetRight());
NodePtr nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxll, nxlr);
NodePtr nx = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
ux->GetWeight(),
nxl, uxr->GetRight());
if (nxll == NULL ||
nxlr == NULL ||
nxl == NULL ||
nx == NULL) {
if (nxll) FreeNode(nxll);
if (nxlr) FreeNode(nxlr);
if (nxl) FreeNode(nxl);
if (nx) FreeNode(nx);
return false;
}
NodePtr expected = ux;
GetPointerToChild(u, ux).CompareAndSwap(expected, nx);
RetireNode(ux);
RetireNode(uxl);
RetireNode(uxr);
RetireNode(uxrl);
return true;
}
bool W1_R(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxlr) {
NodePtr nxrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nxrl = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(),
uxlr->GetWeight() - 1,
uxlr->GetLeft(), uxlr->GetRight());
NodePtr nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxrl, nxrr);
NodePtr nx = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
ux->GetWeight(),
uxl->GetLeft(), nxr);
if (nxrr == NULL ||
nxrl == NULL ||
nxr == NULL ||
nx == NULL) {
if (nxrr) FreeNode(nxrr);
if (nxrl) FreeNode(nxrl);
if (nxr) FreeNode(nxr);
if (nx) FreeNode(nx);
return false;
}
NodePtr expected = ux;
GetPointerToChild(u, ux).CompareAndSwap(expected, nx);
RetireNode(ux);
RetireNode(uxl);
RetireNode(uxr);
RetireNode(uxlr);
return true;
}
bool W2_L(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxrl) {
NodePtr nxll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxlr = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(),
0,
uxrl->GetLeft(), uxrl->GetRight());
NodePtr nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxll, nxlr);
NodePtr nx = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
ux->GetWeight(),
nxl, uxr->GetRight());
if (nxll == NULL ||
nxlr == NULL ||
nxl == NULL ||
nx == NULL) {
if (nxll) FreeNode(nxll);
if (nxlr) FreeNode(nxlr);
if (nxl) FreeNode(nxl);
if (nx) FreeNode(nx);
return false;
}
NodePtr expected = ux;
GetPointerToChild(u, ux).CompareAndSwap(expected, nx);
RetireNode(ux);
RetireNode(uxl);
RetireNode(uxr);
RetireNode(uxrl);
return true;
}
bool W2_R(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxlr) {
NodePtr nxrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nxrl = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(),
0,
uxlr->GetLeft(), uxlr->GetRight());
NodePtr nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxrl, nxrr);
NodePtr nx = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
ux->GetWeight(),
uxl->GetLeft(), nxr);
if (nxrr == NULL ||
nxrl == NULL ||
nxr == NULL ||
nx == NULL) {
if (nxrr) FreeNode(nxrr);
if (nxrl) FreeNode(nxrl);
if (nxr) FreeNode(nxr);
if (nx) FreeNode(nx);
return false;
}
NodePtr expected = ux;
GetPointerToChild(u, ux).CompareAndSwap(expected, nx);
RetireNode(ux);
RetireNode(uxl);
RetireNode(uxr);
RetireNode(uxlr);
return true;
}
bool W3_L(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxrl,
const NodePtr& uxrll) {
NodePtr nxlll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxll = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxlll, uxrll->GetLeft());
NodePtr nxlr = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(),
1,
uxrll->GetRight(), uxrl->GetRight());
NodePtr nxl = node_pool_.Allocate(
uxrll->GetKey(), uxrll->GetValue(),
0,
nxll, nxlr);
NodePtr nx = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
ux->GetWeight(),
nxl, uxr->GetRight());
if (nxlll == NULL ||
nxll == NULL ||
nxlr == NULL ||
nxl == NULL ||
nx == NULL) {
if (nxlll) FreeNode(nxlll);
if (nxll) FreeNode(nxll);
if (nxlr) FreeNode(nxlr);
if (nxl) FreeNode(nxl);
if (nx) FreeNode(nx);
return false;
}
NodePtr expected = ux;
GetPointerToChild(u, ux).CompareAndSwap(expected, nx);
RetireNode(ux);
RetireNode(uxl);
RetireNode(uxr);
RetireNode(uxrl);
RetireNode(uxrll);
return true;
}
bool W3_R(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxlr,
const NodePtr& uxlrr) {
NodePtr nxrrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nxrr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
uxlrr->GetRight(), nxrrr);
NodePtr nxrl = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(),
1,
uxlr->GetLeft(), uxlrr->GetLeft());
NodePtr nxr = node_pool_.Allocate(
uxlrr->GetKey(), uxlrr->GetValue(),
0,
nxrl, nxrr);
NodePtr nx = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
ux->GetWeight(),
uxl->GetLeft(), nxr);
if (nxrrr == NULL ||
nxrr == NULL ||
nxrl == NULL ||
nxr == NULL ||
nx == NULL) {
if (nxrrr) FreeNode(nxrrr);
if (nxrr) FreeNode(nxrr);
if (nxrl) FreeNode(nxrl);
if (nxr) FreeNode(nxr);
if (nx) FreeNode(nx);
return false;
}
NodePtr expected = ux;
GetPointerToChild(u, ux).CompareAndSwap(expected, nx);
RetireNode(ux);
RetireNode(uxl);
RetireNode(uxr);
RetireNode(uxlr);
RetireNode(uxlrr);
return true;
}
bool W4_L(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxrl,
const NodePtr& uxrlr) {
NodePtr nxll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxrl = node_pool_.Allocate(
uxrlr->GetKey(), uxrlr->GetValue(),
1,
uxrlr->GetLeft(), uxrlr->GetRight());
NodePtr nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxll, uxrl->GetLeft());
NodePtr nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
0,
nxrl, uxr->GetRight());
NodePtr nx = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(),
ux->GetWeight(),
nxl, nxr);
if (nxll == NULL ||
nxrl == NULL ||
nxl == NULL ||
nxr == NULL ||
nx == NULL) {
if (nxll) FreeNode(nxll);
if (nxrl) FreeNode(nxrl);
if (nxl) FreeNode(nxl);
if (nxr) FreeNode(nxr);
if (nx) FreeNode(nx);
return false;
}
NodePtr expected = ux;
GetPointerToChild(u, ux).CompareAndSwap(expected, nx);
RetireNode(ux);
RetireNode(uxl);
RetireNode(uxr);
RetireNode(uxrl);
RetireNode(uxrlr);
return true;
}
bool W4_R(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxlr,
const NodePtr& uxlrl) {
NodePtr nxrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nxlr = node_pool_.Allocate(
uxlrl->GetKey(), uxlrl->GetValue(),
1,
uxlrl->GetLeft(), uxlrl->GetRight());
NodePtr nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
uxlr->GetRight(), nxrr);
NodePtr nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
0,
uxl->GetLeft(), nxlr);
NodePtr nx = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(),
ux->GetWeight(),
nxl, nxr);
if (nxrr == NULL ||
nxlr == NULL ||
nxr == NULL ||
nxl == NULL ||
nx == NULL) {
if (nxrr) FreeNode(nxrr);
if (nxlr) FreeNode(nxlr);
if (nxr) FreeNode(nxr);
if (nxl) FreeNode(nxl);
if (nx) FreeNode(nx);
return false;
}
NodePtr expected = ux;
GetPointerToChild(u, ux).CompareAndSwap(expected, nx);
RetireNode(ux);
RetireNode(uxl);
RetireNode(uxr);
RetireNode(uxlr);
RetireNode(uxlrl);
return true;
}
bool W5_L(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxrr) {
NodePtr nxll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxll, uxr->GetLeft());
NodePtr nxr = node_pool_.Allocate(
uxrr->GetKey(), uxrr->GetValue(),
1,
uxrr->GetLeft(), uxrr->GetRight());
NodePtr nx = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
ux->GetWeight(),
nxl, nxr);
if (nxll == NULL ||
nxl == NULL ||
nxr == NULL ||
nx == NULL) {
if (nxll) FreeNode(nxll);
if (nxl) FreeNode(nxl);
if (nxr) FreeNode(nxr);
if (nx) FreeNode(nx);
return false;
}
NodePtr expected = ux;
GetPointerToChild(u, ux).CompareAndSwap(expected, nx);
RetireNode(ux);
RetireNode(uxl);
RetireNode(uxr);
RetireNode(uxrr);
return true;
}
bool W5_R(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxll) {
NodePtr nxrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
uxl->GetRight(), nxrr);
NodePtr nxl = node_pool_.Allocate(
uxll->GetKey(), uxll->GetValue(),
1,
uxll->GetLeft(), uxll->GetRight());
NodePtr nx = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
ux->GetWeight(),
nxl, nxr);
if (nxrr == NULL ||
nxr == NULL ||
nxl == NULL ||
nx == NULL) {
if (nxrr) FreeNode(nxrr);
if (nxr) FreeNode(nxr);
if (nxl) FreeNode(nxl);
if (nx) FreeNode(nx);
return false;
}
NodePtr expected = ux;
GetPointerToChild(u, ux).CompareAndSwap(expected, nx);
RetireNode(ux);
RetireNode(uxl);
RetireNode(uxr);
RetireNode(uxll);
return true;
}
bool W6_L(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxrl) {
NodePtr nxll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxll, uxrl->GetLeft());
NodePtr nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
1,
uxrl->GetRight(), uxr->GetRight());
NodePtr nx = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(),
ux->GetWeight(),
nxl, nxr);
if (nxll == NULL ||
nxl == NULL ||
nxr == NULL ||
nx == NULL) {
if (nxll) FreeNode(nxll);
if (nxl) FreeNode(nxl);
if (nxr) FreeNode(nxr);
if (nx) FreeNode(nx);
return false;
}
NodePtr expected = ux;
GetPointerToChild(u, ux).CompareAndSwap(expected, nx);
RetireNode(ux);
RetireNode(uxl);
RetireNode(uxr);
RetireNode(uxrl);
return true;
}
bool W6_R(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr,
const NodePtr& uxlr) {
NodePtr nxrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
uxlr->GetRight(), nxrr);
NodePtr nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
1,
uxl->GetLeft(), uxlr->GetLeft());
NodePtr nx = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(),
ux->GetWeight(),
nxl, nxr);
if (nxrr == NULL ||
nxr == NULL ||
nxl == NULL ||
nx == NULL) {
if (nxrr) FreeNode(nxrr);
if (nxr) FreeNode(nxr);
if (nxl) FreeNode(nxl);
if (nx) FreeNode(nx);
return false;
}
NodePtr expected = ux;
GetPointerToChild(u, ux).CompareAndSwap(expected, nx);
RetireNode(ux);
RetireNode(uxl);
RetireNode(uxr);
RetireNode(uxlr);
return true;
}
bool W7(const NodePtr& u,
const NodePtr& ux,
const NodePtr& uxl,
const NodePtr& uxr) {
NodePtr nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nx = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
HasFixedWeight(ux) ? 1 : ux->GetWeight() + 1,
nxl, nxr);
if (nxl == NULL ||
nxr == NULL ||
nx == NULL) {
if (nxl) FreeNode(nxl);
if (nxr) FreeNode(nxr);
if (nx) FreeNode(nx);
return false;
}
NodePtr expected = ux;
GetPointerToChild(u, ux).CompareAndSwap(expected, nx);
RetireNode(ux);
RetireNode(uxl);
RetireNode(uxr);
return true;
}
#endif // EMBB_CONTAINERS_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_
......@@ -31,6 +31,7 @@
#include <functional>
#include <embb/base/mutex.h>
#include <embb/containers/internal/hazard_pointer.h>
namespace embb {
namespace containers {
......@@ -48,6 +49,9 @@ namespace internal {
template<typename Key, typename Value>
class ChromaticTreeNode {
public:
typedef ChromaticTreeNode<Key, Value>* ChildPointer;
typedef embb::base::Atomic<ChildPointer> AtomicChildPointer;
/**
* Creates a node with given parameters.
*
......@@ -58,8 +62,7 @@ class ChromaticTreeNode {
* \param[IN] right Pointer to the right child node
*/
ChromaticTreeNode(const Key& key, const Value& value, const int weight,
ChromaticTreeNode<Key, Value>* const & left,
ChromaticTreeNode<Key, Value>* const & right);
const ChildPointer& left, const ChildPointer& right);
/**
* Creates a node given only a key-value pair. Node will have no child nodes
......@@ -71,14 +74,6 @@ class ChromaticTreeNode {
ChromaticTreeNode(const Key& key, const Value& value, const int weight = 1);
/**
* Creates a copy of a given node.
*
* \param[IN] other Node to be copied
*/
ChromaticTreeNode(const ChromaticTreeNode& other);
/**
* Accessor for the stored key.
*
* \return Stored key
......@@ -104,21 +99,31 @@ class ChromaticTreeNode {
*
* \return Reference to the left child pointer
*/
ChromaticTreeNode<Key, Value>*& GetLeft();
AtomicChildPointer& GetLeft();
/**
* Accessor for the right child pointer.
*
* \return Reference to the right child pointer
*/
ChromaticTreeNode<Key, Value>*& GetRight();
AtomicChildPointer& GetRight();
void Retire() { retired_ = true; }
bool IsRetired() const { return retired_; }
embb::base::Mutex& GetMutex() { return mutex_; }
private:
const Key key_; /**< Stored key */
const Value value_; /**< Stored value */
const int weight_; /**< Weight of the node */
ChromaticTreeNode<Key, Value>* left_; /**< Pointer to left child node */
ChromaticTreeNode<Key, Value>* right_; /**< Pointer to right child node */
ChromaticTreeNode(const ChromaticTreeNode&);
ChromaticTreeNode& operator=(const ChromaticTreeNode&);
const Key key_; /**< Stored key */
const Value value_; /**< Stored value */
const int weight_; /**< Weight of the node */
AtomicChildPointer left_; /**< Pointer to left child node */
AtomicChildPointer right_; /**< Pointer to right child node */
embb::base::Atomic<bool> retired_;
embb::base::Mutex mutex_;
};
} // namespace internal
......@@ -215,7 +220,7 @@ class ChromaticTree {
* \param[IN] value New value to be inserted
*
* \return \c true if the given key-value pair was successfully inserted into
* the tree, \c false if tree has reached its capacity
* the tree, \c false if the tree has reached its capacity
*/
bool TryInsert(const Key& key, const Value& value);
......@@ -232,7 +237,7 @@ class ChromaticTree {
* tree for the given key
*
* \return \c true if the given key-value pair was successfully inserted into
* the tree, \c false if tree has reached its capacity
* the tree, \c false if the tree has reached its capacity
*/
bool TryInsert(const Key& key, const Value& value, Value& old_value);
......@@ -242,7 +247,7 @@ class ChromaticTree {
* \param[IN] key Key to be removed
*
* \return \c true if the given key-value pair was successfully deleted from
* the tree, \c false if the given key was not stored in the tree
* the tree, \c false if the tree is out of memory
*/
bool TryDelete(const Key& key);
......@@ -256,7 +261,7 @@ class ChromaticTree {
* tree for the given key
*
* \return \c true if the given key-value pair was successfully deleted from
* the tree, \c false if the given key was not stored in the tree
* the tree, \c false if the tree is out of memory
*/
bool TryDelete(const Key& key, Value& old_value);
......@@ -291,8 +296,14 @@ class ChromaticTree {
* Typedef for a pointer to a node of the tree.
*/
typedef internal::ChromaticTreeNode<Key, Value>* NodePtr;
/**
* Typedef for an atomic pointer to a node of the tree.
*/
typedef embb::base::Atomic<NodePtr> AtomicNodePtr;
typedef embb::base::UniqueLock<embb::base::Mutex> UniqueLock;
/**
* Follows a path from the root of the tree to some leaf searching for the
* given key (the leaf found by this method may or may not contain the given
......@@ -301,7 +312,7 @@ class ChromaticTree {
* \param[IN] key Key to be searched for
* \param[IN,OUT] leaf Reference to the reached leaf
*/
void Search(const Key& key, NodePtr& leaf) const;
void Search(const Key& key, NodePtr& leaf);
/**
* Follows a path from the root of the tree to some leaf searching for the
......@@ -312,7 +323,7 @@ class ChromaticTree {
* \param[IN,OUT] leaf Reference to the reached leaf
* \param[IN,OUT] parent Reference to the parent of the reached leaf
*/
void Search(const Key& key, NodePtr& leaf, NodePtr& parent) const;
void Search(const Key& key, NodePtr& leaf, NodePtr& parent);
/**
* Follows a path from the root of the tree to some leaf searching for the
......@@ -325,7 +336,7 @@ class ChromaticTree {
* \param[IN,OUT] grandparent Reference to the grandparent of the reached leaf
*/
void Search(const Key& key, NodePtr& leaf, NodePtr& parent,
NodePtr& grandparent) const;
NodePtr& grandparent);
/**
* Checks whether the given node is a leaf.
......@@ -376,7 +387,8 @@ class ChromaticTree {
* \return Reference to a member pointer of the \c parent that points to
* the \c child
*/
NodePtr& GetPointerToChild(const NodePtr& parent, const NodePtr& child) const;
AtomicNodePtr& GetPointerToChild(const NodePtr& parent,
const NodePtr& child) const;
/**
* Destroys all the nodes of a subtree rooted at the given node, including the
......@@ -387,13 +399,39 @@ class ChromaticTree {
* \param node Root of the subtree to be destroyed
*/
void Destruct(const NodePtr& node);
/**
* Computes the hight of the subtree rooted at the given node.
*
* \notthreadsafe
*
* \param[IN] node Root of the subtree for which the height is requested
*
* \return The height of a subtree rooted at node \c node. (The height of a
* leaf node is defined to be zero).
*/
int GetHeight(const NodePtr& node) const;
bool IsBalanced() const;
bool IsBalanced(const NodePtr& node) const;
void RemoveNode(const NodePtr& node) {
node_hazard_manager_.EnqueuePointerForDeletion(node);
}
/**
* Free a tree node by returning it to the node pool.
*
* \param[IN] node A node to be freed.
*/
void FreeNode(NodePtr node);
/**
* Follows the path from the root to some leaf (directed by the given key) and
* checks for any tree balancing violations. If a violation is found, tries
* to fix it by using a set of rebalancing rotations.
*
* \param key Key to be searched for
* \param[IN] key Key to be searched for
*
* \return \c true if the tree was successfully rebalanced, \c false otherwise
*/
......@@ -412,76 +450,16 @@ class ChromaticTree {
const NodePtr& uxl, const NodePtr& uxr,
const NodePtr& uxxl, const NodePtr& uxxr,
const bool& uxx_is_right);
bool BLK(const NodePtr& u, const NodePtr& ux,
const NodePtr& uxl, const NodePtr& uxr);
bool PUSH_L(const NodePtr& u, const NodePtr& ux,
const NodePtr& uxl, const NodePtr& uxr);
bool PUSH_R(const NodePtr& u, const NodePtr& ux,
const NodePtr& uxl, const NodePtr& uxr);
bool RB1_L(const NodePtr& u, const NodePtr& ux, const NodePtr& uxl);
bool RB1_R(const NodePtr& u, const NodePtr& ux, const NodePtr& uxr);
bool RB2_L(const NodePtr& u, const NodePtr& ux,
const NodePtr& uxl, const NodePtr& uxlr);
bool RB2_R(const NodePtr& u, const NodePtr& ux,
const NodePtr& uxr, const NodePtr& uxrl);
bool W1_L(const NodePtr& u, const NodePtr& ux,
const NodePtr& uxl, const NodePtr& uxr,
const NodePtr& uxrl);
bool W1_R(const NodePtr& u, const NodePtr& ux,
const NodePtr& uxl, const NodePtr& uxr,
const NodePtr& uxlr);
bool W2_L(const NodePtr& u, const NodePtr& ux,
const NodePtr& uxl, const NodePtr& uxr,
const NodePtr& uxrl);
bool W2_R(const NodePtr& u, const NodePtr& ux,
const NodePtr& uxl, const NodePtr& uxr,
const NodePtr& uxlr);
bool W3_L(const NodePtr& u, const NodePtr& ux,
const NodePtr& uxl, const NodePtr& uxr,
const NodePtr& uxrl, const NodePtr& uxrll);
bool W3_R(const NodePtr& u, const NodePtr& ux,
const NodePtr& uxl, const NodePtr& uxr,
const NodePtr& uxlr, const NodePtr& uxlrr);
bool W4_L(const NodePtr& u, const NodePtr& ux,
const NodePtr& uxl, const NodePtr& uxr,
const NodePtr& uxrl, const NodePtr& uxrlr);
bool W4_R(const NodePtr& u, const NodePtr& ux,
const NodePtr& uxl, const NodePtr& uxr,
const NodePtr& uxlr, const NodePtr& uxlrl);
bool W5_L(const NodePtr& u, const NodePtr& ux,
const NodePtr& uxl, const NodePtr& uxr,
const NodePtr& uxrr);
bool W5_R(const NodePtr& u, const NodePtr& ux,
const NodePtr& uxl, const NodePtr& uxr,
const NodePtr& uxll);
bool W6_L(const NodePtr& u, const NodePtr& ux,
const NodePtr& uxl, const NodePtr& uxr,
const NodePtr& uxrl);
bool W6_R(const NodePtr& u, const NodePtr& ux,
const NodePtr& uxl, const NodePtr& uxr,
const NodePtr& uxlr);
bool W7(const NodePtr& u, const NodePtr& ux,
const NodePtr& uxl, const NodePtr& uxr);
/**
* Friending the test class for white-box testing
*/
friend class test::TreeTest<ChromaticTree<Key, Value, Compare, NodePool> >;
/**
* Computes the hight of the subtree rooted at the given node.
*
* \notthreadsafe
*
* \param[IN] node Root of the subtree for which the height is requested
*
* \return The height of a subtree rooted at node \c node. (The height of a
* leaf node is defined to be zero).
*/
int GetHeight(const NodePtr& node) const;
bool IsBalanced() const;
bool IsBalanced(const NodePtr& node) const;
// The following included header contains the class methods implementing
// tree rotations. It is generated automatically and must be included
// directly inside the class definition.
# include <embb/containers/internal/lock_free_chromatic_tree-rebalance.h>
/** Callback functor for the hazard pointer that frees retired nodes */
embb::base::Function<void, NodePtr> free_node_callback_;
/** Hazard pointer instance for protection of node pointers */
embb::containers::internal::HazardPointer<NodePtr> node_hazard_manager_;
const Key undefined_key_; /**< A dummy key used by the tree */
const Value undefined_value_; /**< A dummy value used by the tree */
......@@ -491,11 +469,10 @@ class ChromaticTree {
NodePtr entry_; /**< Pointer to the sentinel node used as
* the entry point into the tree */
typedef embb::base::ReadWriteLock::Reader ReadWriteLockReader;
typedef embb::base::ReadWriteLock::Writer ReadWriteLockWriter;
typedef embb::base::LockGuard<ReadWriteLockReader> ReaderLockGuard;
typedef embb::base::LockGuard<ReadWriteLockWriter> WriterLockGuard;
embb::base::ReadWriteLock readwrite_lock_;
/**
* Friending the test class for white-box testing
*/
friend class test::TreeTest<ChromaticTree<Key, Value, Compare, NodePool> >;
};
} // namespace containers
......
......@@ -66,11 +66,11 @@ TreeTest<Tree>::TreeTest()
Add(&TreeTest::TreeTestConcurrentGet_ReaderMethod, this,
NUM_TEST_THREADS / 2, NUM_ITERATIONS).
Post(&TreeTest::TreeTestConcurrentGet_Post, this);
CreateUnit("TreeTestBalance").
Pre(&TreeTest::TreeTestBalance_Pre, this).
Add(&TreeTest::TreeTestBalance_ThreadMethod, this,
NUM_TEST_THREADS, 1).
Post(&TreeTest::TreeTestBalance_Post, this);
// CreateUnit("TreeTestBalance").
// Pre(&TreeTest::TreeTestBalance_Pre, this).
// Add(&TreeTest::TreeTestBalance_ThreadMethod, this,
// NUM_TEST_THREADS, 1).
// Post(&TreeTest::TreeTestBalance_Post, this);
}
template<typename 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