Commit 871b5391 by Danila Klimenko

chromatic_tree: Fine-grained locking implementation without rebalancing

parent 8ded09ad
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include <embb/base/internal/platform.h> #include <embb/base/internal/platform.h>
#include <embb/base/exceptions.h> #include <embb/base/exceptions.h>
#include <embb/base/c/counter.h>
namespace embb { namespace embb {
namespace base { namespace base {
...@@ -484,71 +483,6 @@ class UniqueLock { ...@@ -484,71 +483,6 @@ class UniqueLock {
friend class embb::base::ConditionVariable; 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 base
} // namespace embb } // namespace embb
......
...@@ -30,6 +30,14 @@ ...@@ -30,6 +30,14 @@
#include <assert.h> #include <assert.h>
#include <algorithm> #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 embb {
namespace containers { namespace containers {
namespace internal { namespace internal {
...@@ -37,13 +45,13 @@ namespace internal { ...@@ -37,13 +45,13 @@ namespace internal {
template<typename Key, typename Value> template<typename Key, typename Value>
ChromaticTreeNode<Key, Value>:: ChromaticTreeNode<Key, Value>::
ChromaticTreeNode(const Key& key, const Value& value, const int weight, ChromaticTreeNode(const Key& key, const Value& value, const int weight,
ChromaticTreeNode<Key, Value>* const & left, const ChildPointer& left, const ChildPointer& right)
ChromaticTreeNode<Key, Value>* const & right)
: key_(key), : key_(key),
value_(value), value_(value),
weight_(weight), weight_(weight),
left_(left), left_(left),
right_(right) {} right_(right),
retired_(false) {}
template<typename Key, typename Value> template<typename Key, typename Value>
ChromaticTreeNode<Key, Value>:: ChromaticTreeNode<Key, Value>::
...@@ -52,16 +60,8 @@ ChromaticTreeNode(const Key& key, const Value& value, const int weight) ...@@ -52,16 +60,8 @@ ChromaticTreeNode(const Key& key, const Value& value, const int weight)
value_(value), value_(value),
weight_(weight), weight_(weight),
left_(NULL), left_(NULL),
right_(NULL) {} right_(NULL),
retired_(false) {}
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_) {}
template<typename Key, typename Value> template<typename Key, typename Value>
const Key& ChromaticTreeNode<Key, Value>::GetKey() const { const Key& ChromaticTreeNode<Key, Value>::GetKey() const {
...@@ -79,12 +79,14 @@ int ChromaticTreeNode<Key, Value>::GetWeight() const { ...@@ -79,12 +79,14 @@ int ChromaticTreeNode<Key, Value>::GetWeight() const {
} }
template<typename Key, typename Value> template<typename Key, typename Value>
ChromaticTreeNode<Key, Value>*& ChromaticTreeNode<Key, Value>::GetLeft() { typename ChromaticTreeNode<Key, Value>::AtomicChildPointer&
ChromaticTreeNode<Key, Value>::GetLeft() {
return left_; return left_;
} }
template<typename Key, typename Value> template<typename Key, typename Value>
ChromaticTreeNode<Key, Value>*& ChromaticTreeNode<Key, Value>::GetRight() { typename ChromaticTreeNode<Key, Value>::AtomicChildPointer&
ChromaticTreeNode<Key, Value>::GetRight() {
return right_; return right_;
} }
...@@ -95,11 +97,22 @@ template<typename Key, typename Value, typename Compare, typename NodePool> ...@@ -95,11 +97,22 @@ template<typename Key, typename Value, typename Compare, typename NodePool>
ChromaticTree<Key, Value, Compare, NodePool>:: ChromaticTree<Key, Value, Compare, NodePool>::
ChromaticTree(size_t capacity, Key undefined_key, Value undefined_value, ChromaticTree(size_t capacity, Key undefined_key, Value undefined_value,
Compare compare) 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), undefined_value_(undefined_value),
compare_(compare), compare_(compare),
capacity_(capacity), 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_); entry_ = node_pool_.Allocate(undefined_key_, undefined_value_);
NodePtr sentinel = node_pool_.Allocate(undefined_key_, undefined_value_); NodePtr sentinel = node_pool_.Allocate(undefined_key_, undefined_value_);
entry_->GetLeft() = sentinel; entry_->GetLeft() = sentinel;
...@@ -109,25 +122,26 @@ template<typename Key, typename Value, typename Compare, typename NodePool> ...@@ -109,25 +122,26 @@ template<typename Key, typename Value, typename Compare, typename NodePool>
ChromaticTree<Key, Value, Compare, NodePool>:: ChromaticTree<Key, Value, Compare, NodePool>::
~ChromaticTree() { ~ChromaticTree() {
Destruct(entry_->GetLeft()); Destruct(entry_->GetLeft());
node_pool_.Free(entry_); FreeNode(entry_);
} }
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) {
ReaderLockGuard guard(readwrite_lock_.GetReader());
NodePtr leaf; NodePtr leaf;
Search(key, 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)); compare_(leaf->GetKey(), key));
if (!IsSentinel(leaf) && keys_are_equal) {
if (keys_are_equal) {
value = leaf->GetValue(); 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> template<typename Key, typename Value, typename Compare, typename NodePool>
...@@ -140,65 +154,75 @@ TryInsert(const Key& key, const Value& value) { ...@@ -140,65 +154,75 @@ TryInsert(const Key& key, const Value& value) {
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>::
TryInsert(const Key& key, const Value& value, Value& old_value) { TryInsert(const Key& key, const Value& value, Value& old_value) {
WriterLockGuard guard(readwrite_lock_.GetWriter()); NodePtr new_leaf = NULL;
NodePtr new_sibling = NULL;
NodePtr leaf, parent; NodePtr new_parent = NULL;
Search(key, leaf, parent); bool insertion_succeeded = false;
assert(HasChild(parent, leaf)); 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; new_leaf = node_pool_.Allocate(key, value);
bool added_violation = false; 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()) || int new_weight = (HasFixedWeight(leaf)) ? 1 : (leaf->GetWeight() - 1);
compare_(leaf->GetKey(), key)); if (IsSentinel(leaf) || compare_(key, leaf->GetKey())) {
if (!IsSentinel(leaf) && keys_are_equal) { new_parent = node_pool_.Allocate(leaf->GetKey(), undefined_value_,
old_value = leaf->GetValue(); new_weight, new_leaf, new_sibling);
new_parent = node_pool_.Allocate(key, value, leaf->GetWeight()); } else {
if (new_parent == NULL) { new_parent = node_pool_.Allocate(key, undefined_value_,
return false; new_weight, new_sibling, new_leaf);
}
if (new_parent == NULL) break;
} }
} else {
old_value = undefined_value_;
NodePtr new_leaf = node_pool_.Allocate(key, value); GetPointerToChild(parent, leaf).CompareAndSwap(leaf, new_parent);
if (new_leaf == NULL) {
return false;
}
NodePtr new_sibling = node_pool_.Allocate(*leaf);
if (new_sibling == NULL) {
node_pool_.Free(new_leaf);
return false;
}
int new_weight = (HasFixedWeight(leaf)) ? 1 : (leaf->GetWeight() - 1); insertion_succeeded = true;
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) { leaf->Retire();
node_pool_.Free(new_leaf); leaf_lock.Unlock();
node_pool_.Free(new_sibling); node_hazard_manager_.GuardPointer(1, NULL);
return false; 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); if (!insertion_succeeded) {
new_subtree_ptr = new_parent; if (new_leaf != NULL) FreeNode(new_leaf);
if (new_sibling != NULL) FreeNode(new_sibling);
node_pool_.Free(leaf); if (new_parent != NULL) FreeNode(new_parent);
if (added_violation) {
CleanUp(key);
} }
return true; return insertion_succeeded;
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename NodePool>
...@@ -211,47 +235,89 @@ TryDelete(const Key& key) { ...@@ -211,47 +235,89 @@ TryDelete(const Key& key) {
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>::
TryDelete(const Key& key, Value& old_value) { TryDelete(const Key& key, Value& old_value) {
WriterLockGuard guard(readwrite_lock_.GetWriter()); NodePtr new_leaf = NULL;
bool deletion_succeeded = false;
NodePtr leaf, parent, grandparent;
Search(key, leaf, parent, grandparent); while (!deletion_succeeded) {
NodePtr leaf, parent, grandparent;
bool keys_are_equal = !(compare_(key, leaf->GetKey()) || Search(key, leaf, parent, grandparent);
compare_(leaf->GetKey(), key));
if (IsSentinel(leaf) || !keys_are_equal) { // Reached leaf has a different key - nothing to delete
old_value = undefined_value_; if (IsSentinel(leaf) || (compare_(key, leaf->GetKey()) ||
return false; compare_(leaf->GetKey(), key))) {
} old_value = undefined_value_;
deletion_succeeded = true;
assert(HasChild(grandparent, parent)); break;
assert(HasChild(parent, leaf)); }
NodePtr sibling = ((parent->GetLeft() == leaf) ? // Try to lock the grandparent
parent->GetRight() : parent->GetLeft()); 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)) ? old_value = leaf->GetValue();
1 : (parent->GetWeight() + sibling->GetWeight());
bool added_violation = (new_weight > 1);
NodePtr new_leaf = node_pool_.Allocate( GetPointerToChild(grandparent, parent).CompareAndSwap(parent, new_leaf);
sibling->GetKey(), sibling->GetValue(), new_weight,
sibling->GetLeft(), sibling->GetRight());
assert((new_leaf != NULL) && "No nodes available for replacement!");
NodePtr& new_subtree_ptr = GetPointerToChild(grandparent, parent); deletion_succeeded = true;
new_subtree_ptr = new_leaf;
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); // if (new_weight > 1) {
node_pool_.Free(sibling); // CleanUp(key);
node_pool_.Free(parent); // }
}
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) { if (!deletion_succeeded) {
CleanUp(key); if (new_leaf != NULL) FreeNode(new_leaf);
} }
return true; return deletion_succeeded;
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename NodePool>
...@@ -274,31 +340,77 @@ IsEmpty() { ...@@ -274,31 +340,77 @@ IsEmpty() {
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename NodePool>
void ChromaticTree<Key, Value, Compare, NodePool>:: void ChromaticTree<Key, Value, Compare, NodePool>::
Search(const Key& key, NodePtr& leaf) const { Search(const Key& key, NodePtr& leaf) {
NodePtr parent; NodePtr parent;
Search(key, leaf, 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> template<typename Key, typename Value, typename Compare, typename NodePool>
void ChromaticTree<Key, Value, Compare, NodePool>:: void ChromaticTree<Key, Value, Compare, NodePool>::
Search(const Key& key, NodePtr& leaf, NodePtr& parent) const { Search(const Key& key, NodePtr& leaf, NodePtr& parent) {
NodePtr grandparent; bool reached_leaf = false;
Search(key, leaf, parent, grandparent);
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> template<typename Key, typename Value, typename Compare, typename NodePool>
void ChromaticTree<Key, Value, Compare, NodePool>:: void ChromaticTree<Key, Value, Compare, NodePool>::
Search(const Key& key, NodePtr& leaf, NodePtr& parent, Search(const Key& key, NodePtr& leaf, NodePtr& parent, NodePtr& grandparent) {
NodePtr& grandparent) const { bool reached_leaf = false;
grandparent = NULL;
parent = entry_; while (!reached_leaf) {
leaf = entry_->GetLeft(); grandparent = NULL;
while (!IsLeaf(leaf)) { parent = entry_;
grandparent = parent; node_hazard_manager_.GuardPointer(1, parent);
parent = leaf;
leaf = (IsSentinel(leaf) || compare_(key, leaf->GetKey())) ? leaf = entry_->GetLeft();
leaf->GetLeft() : leaf->GetRight(); 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 { ...@@ -327,7 +439,7 @@ HasChild(const NodePtr& parent, const NodePtr& child) const {
} }
template<typename Key, typename Value, typename Compare, typename NodePool> 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>:: ChromaticTree<Key, Value, Compare, NodePool>::
GetPointerToChild(const NodePtr& parent, const NodePtr& child) const { GetPointerToChild(const NodePtr& parent, const NodePtr& child) const {
assert(HasChild(parent, child)); assert(HasChild(parent, child));
...@@ -341,13 +453,63 @@ Destruct(const NodePtr& node) { ...@@ -341,13 +453,63 @@ Destruct(const NodePtr& node) {
Destruct(node->GetLeft()); Destruct(node->GetLeft());
Destruct(node->GetRight()); 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); node_pool_.Free(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) {
while (true) { for (;;) {
NodePtr grandgrandparent = NULL; NodePtr grandgrandparent = NULL;
NodePtr grandparent = NULL; NodePtr grandparent = NULL;
NodePtr parent = entry_; NodePtr parent = entry_;
...@@ -360,6 +522,7 @@ CleanUp(const Key& key) { ...@@ -360,6 +522,7 @@ CleanUp(const Key& key) {
parent = leaf; parent = leaf;
leaf = (IsSentinel(leaf) || compare_(key, leaf->GetKey())) ? leaf = (IsSentinel(leaf) || compare_(key, leaf->GetKey())) ?
leaf->GetLeft() : leaf->GetRight(); leaf->GetLeft() : leaf->GetRight();
VERIFY_ADDRESS(leaf);
} }
if (leaf->GetWeight() == 1) { if (leaf->GetWeight() == 1) {
...@@ -382,14 +545,14 @@ Rebalance(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx, ...@@ -382,14 +545,14 @@ Rebalance(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
if (!HasChild(u, ux)) return false; if (!HasChild(u, ux)) return false;
//TODO: weakLLX(ux); //TODO: weakLLX(ux);
NodePtr uxl = ux->GetLeft(); NodePtr uxl = ux->GetLeft(); VERIFY_ADDRESS(uxl);
NodePtr uxr = ux->GetRight(); NodePtr uxr = ux->GetRight(); VERIFY_ADDRESS(uxr);
bool uxx_is_left = (uxx == uxl); bool uxx_is_left = (uxx == uxl);
if (!HasChild(ux, uxx)) return false; if (!HasChild(ux, uxx)) return false;
//TODO: weakLLX(uxx); //TODO: weakLLX(uxx);
NodePtr uxxl = uxx->GetLeft(); NodePtr uxxl = uxx->GetLeft(); VERIFY_ADDRESS(uxxl);
NodePtr uxxr = uxx->GetRight(); NodePtr uxxr = uxx->GetRight(); VERIFY_ADDRESS(uxxr);
bool uxxx_is_left = (uxxx == uxxl); bool uxxx_is_left = (uxxx == uxxl);
if (!HasChild(uxx, uxxx)) return false; if (!HasChild(uxx, uxxx)) return false;
...@@ -471,7 +634,7 @@ OverweightLeft(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx, ...@@ -471,7 +634,7 @@ OverweightLeft(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
assert(uxx->GetWeight() > 0); assert(uxx->GetWeight() > 0);
//TODO: weakLLX(uxxr); //TODO: weakLLX(uxxr);
// Note: we know that 'uxxr' is not a leaf because it has weight 0. // 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); //TODO: weakLLX(uxxrl);
// Root -> Middle -> Right -> Left // Root -> Middle -> Right -> Left
...@@ -480,8 +643,8 @@ OverweightLeft(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx, ...@@ -480,8 +643,8 @@ OverweightLeft(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
// Root -> Middle -> Right -> Middle // Root -> Middle -> Right -> Middle
} else if (uxxrl->GetWeight() == 1) { } else if (uxxrl->GetWeight() == 1) {
NodePtr uxxrll = uxxrl->GetLeft(); NodePtr uxxrll = uxxrl->GetLeft(); VERIFY_ADDRESS(uxxrll);
NodePtr uxxrlr = uxxrl->GetRight(); NodePtr uxxrlr = uxxrl->GetRight(); VERIFY_ADDRESS(uxxrlr);
if (uxxrlr == NULL) return false; if (uxxrlr == NULL) return false;
// Root -> Middle -> Right -> Middle -> Left // Root -> Middle -> Right -> Middle -> Left
...@@ -514,8 +677,8 @@ OverweightLeft(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx, ...@@ -514,8 +677,8 @@ OverweightLeft(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
// Root -> Right // Root -> Right
} else if (uxxr->GetWeight() == 1) { } else if (uxxr->GetWeight() == 1) {
//TODO: weakLLX(uxxr); //TODO: weakLLX(uxxr);
NodePtr uxxrl = uxxr->GetLeft(); NodePtr uxxrl = uxxr->GetLeft(); VERIFY_ADDRESS(uxxrl);
NodePtr uxxrr = uxxr->GetRight(); NodePtr uxxrr = uxxr->GetRight(); VERIFY_ADDRESS(uxxrr);
if (uxxrl == NULL) return false; if (uxxrl == NULL) return false;
// Root -> Right -> Left // Root -> Right -> Left
...@@ -544,8 +707,6 @@ OverweightLeft(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx, ...@@ -544,8 +707,6 @@ OverweightLeft(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
//TODO: weakLLX(uxxr); //TODO: weakLLX(uxxr);
return W7(ux, uxx, uxxl, uxxr); return W7(ux, uxx, uxxl, uxxr);
} }
return true;
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename NodePool>
...@@ -593,7 +754,7 @@ OverweightRight(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx, ...@@ -593,7 +754,7 @@ OverweightRight(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
assert(uxx->GetWeight() > 0); assert(uxx->GetWeight() > 0);
//TODO: weakLLX(uxxl); //TODO: weakLLX(uxxl);
// Note: we know that 'uxxl' is not a leaf because it has weight 0. // 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); //TODO: weakLLX(uxxlr);
// Root -> Middle -> Right -> Left // Root -> Middle -> Right -> Left
...@@ -602,8 +763,8 @@ OverweightRight(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx, ...@@ -602,8 +763,8 @@ OverweightRight(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
// Root -> Middle -> Right -> Middle // Root -> Middle -> Right -> Middle
} else if (uxxlr->GetWeight() == 1) { } else if (uxxlr->GetWeight() == 1) {
NodePtr uxxlrl = uxxlr->GetLeft(); NodePtr uxxlrl = uxxlr->GetLeft(); VERIFY_ADDRESS(uxxlrl);
NodePtr uxxlrr = uxxlr->GetRight(); NodePtr uxxlrr = uxxlr->GetRight(); VERIFY_ADDRESS(uxxlrr);
if (uxxlrl == NULL) return false; if (uxxlrl == NULL) return false;
// Root -> Middle -> Right -> Middle -> Left // Root -> Middle -> Right -> Middle -> Left
...@@ -636,8 +797,8 @@ OverweightRight(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx, ...@@ -636,8 +797,8 @@ OverweightRight(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
// Root -> Right // Root -> Right
} else if (uxxl->GetWeight() == 1) { } else if (uxxl->GetWeight() == 1) {
//TODO: weakLLX(uxxl); //TODO: weakLLX(uxxl);
NodePtr uxxll = uxxl->GetLeft(); NodePtr uxxll = uxxl->GetLeft(); VERIFY_ADDRESS(uxxll);
NodePtr uxxlr = uxxl->GetRight(); NodePtr uxxlr = uxxl->GetRight(); VERIFY_ADDRESS(uxxlr);
if (uxxll == NULL) return false; if (uxxll == NULL) return false;
// Root -> Right -> Left // Root -> Right -> Left
...@@ -666,923 +827,8 @@ OverweightRight(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx, ...@@ -666,923 +827,8 @@ OverweightRight(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
//TODO: weakLLX(uxxl); //TODO: weakLLX(uxxl);
return W7(ux, uxx, uxxl, uxxr); 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 containers
} // namespace embb } // 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 @@ ...@@ -31,6 +31,7 @@
#include <functional> #include <functional>
#include <embb/base/mutex.h> #include <embb/base/mutex.h>
#include <embb/containers/internal/hazard_pointer.h>
namespace embb { namespace embb {
namespace containers { namespace containers {
...@@ -48,6 +49,9 @@ namespace internal { ...@@ -48,6 +49,9 @@ namespace internal {
template<typename Key, typename Value> template<typename Key, typename Value>
class ChromaticTreeNode { class ChromaticTreeNode {
public: public:
typedef ChromaticTreeNode<Key, Value>* ChildPointer;
typedef embb::base::Atomic<ChildPointer> AtomicChildPointer;
/** /**
* Creates a node with given parameters. * Creates a node with given parameters.
* *
...@@ -58,8 +62,7 @@ class ChromaticTreeNode { ...@@ -58,8 +62,7 @@ class ChromaticTreeNode {
* \param[IN] right Pointer to the right child node * \param[IN] right Pointer to the right child node
*/ */
ChromaticTreeNode(const Key& key, const Value& value, const int weight, ChromaticTreeNode(const Key& key, const Value& value, const int weight,
ChromaticTreeNode<Key, Value>* const & left, const ChildPointer& left, const ChildPointer& right);
ChromaticTreeNode<Key, Value>* const & right);
/** /**
* Creates a node given only a key-value pair. Node will have no child nodes * Creates a node given only a key-value pair. Node will have no child nodes
...@@ -71,14 +74,6 @@ class ChromaticTreeNode { ...@@ -71,14 +74,6 @@ class ChromaticTreeNode {
ChromaticTreeNode(const Key& key, const Value& value, const int weight = 1); 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. * Accessor for the stored key.
* *
* \return Stored key * \return Stored key
...@@ -104,21 +99,31 @@ class ChromaticTreeNode { ...@@ -104,21 +99,31 @@ class ChromaticTreeNode {
* *
* \return Reference to the left child pointer * \return Reference to the left child pointer
*/ */
ChromaticTreeNode<Key, Value>*& GetLeft(); AtomicChildPointer& GetLeft();
/** /**
* Accessor for the right child pointer. * Accessor for the right child pointer.
* *
* \return Reference to 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: private:
const Key key_; /**< Stored key */ ChromaticTreeNode(const ChromaticTreeNode&);
const Value value_; /**< Stored value */ ChromaticTreeNode& operator=(const ChromaticTreeNode&);
const int weight_; /**< Weight of the node */
ChromaticTreeNode<Key, Value>* left_; /**< Pointer to left child node */ const Key key_; /**< Stored key */
ChromaticTreeNode<Key, Value>* right_; /**< Pointer to right child node */ 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 } // namespace internal
...@@ -215,7 +220,7 @@ class ChromaticTree { ...@@ -215,7 +220,7 @@ class ChromaticTree {
* \param[IN] value New value to be inserted * \param[IN] value New value to be inserted
* *
* \return \c true if the given key-value pair was successfully inserted into * \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); bool TryInsert(const Key& key, const Value& value);
...@@ -232,7 +237,7 @@ class ChromaticTree { ...@@ -232,7 +237,7 @@ class ChromaticTree {
* tree for the given key * tree for the given key
* *
* \return \c true if the given key-value pair was successfully inserted into * \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); bool TryInsert(const Key& key, const Value& value, Value& old_value);
...@@ -242,7 +247,7 @@ class ChromaticTree { ...@@ -242,7 +247,7 @@ class ChromaticTree {
* \param[IN] key Key to be removed * \param[IN] key Key to be removed
* *
* \return \c true if the given key-value pair was successfully deleted from * \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); bool TryDelete(const Key& key);
...@@ -256,7 +261,7 @@ class ChromaticTree { ...@@ -256,7 +261,7 @@ class ChromaticTree {
* tree for the given key * tree for the given key
* *
* \return \c true if the given key-value pair was successfully deleted from * \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); bool TryDelete(const Key& key, Value& old_value);
...@@ -291,8 +296,14 @@ class ChromaticTree { ...@@ -291,8 +296,14 @@ class ChromaticTree {
* Typedef for a pointer to a node of the tree. * Typedef for a pointer to a node of the tree.
*/ */
typedef internal::ChromaticTreeNode<Key, Value>* NodePtr; 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 * 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 * given key (the leaf found by this method may or may not contain the given
...@@ -301,7 +312,7 @@ class ChromaticTree { ...@@ -301,7 +312,7 @@ class ChromaticTree {
* \param[IN] key Key to be searched for * \param[IN] key Key to be searched for
* \param[IN,OUT] leaf Reference to the reached leaf * \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 * Follows a path from the root of the tree to some leaf searching for the
...@@ -312,7 +323,7 @@ class ChromaticTree { ...@@ -312,7 +323,7 @@ class ChromaticTree {
* \param[IN,OUT] leaf Reference to the reached leaf * \param[IN,OUT] leaf Reference to the reached leaf
* \param[IN,OUT] parent Reference to the parent of 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 * Follows a path from the root of the tree to some leaf searching for the
...@@ -325,7 +336,7 @@ class ChromaticTree { ...@@ -325,7 +336,7 @@ class ChromaticTree {
* \param[IN,OUT] grandparent Reference to the grandparent of the reached leaf * \param[IN,OUT] grandparent Reference to the grandparent of the reached leaf
*/ */
void Search(const Key& key, NodePtr& leaf, NodePtr& parent, void Search(const Key& key, NodePtr& leaf, NodePtr& parent,
NodePtr& grandparent) const; NodePtr& grandparent);
/** /**
* Checks whether the given node is a leaf. * Checks whether the given node is a leaf.
...@@ -376,7 +387,8 @@ class ChromaticTree { ...@@ -376,7 +387,8 @@ class ChromaticTree {
* \return Reference to a member pointer of the \c parent that points to * \return Reference to a member pointer of the \c parent that points to
* the \c child * 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 * Destroys all the nodes of a subtree rooted at the given node, including the
...@@ -387,13 +399,39 @@ class ChromaticTree { ...@@ -387,13 +399,39 @@ class ChromaticTree {
* \param node Root of the subtree to be destroyed * \param node Root of the subtree to be destroyed
*/ */
void Destruct(const NodePtr& node); 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 * 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 * checks for any tree balancing violations. If a violation is found, tries
* to fix it by using a set of rebalancing rotations. * 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 * \return \c true if the tree was successfully rebalanced, \c false otherwise
*/ */
...@@ -412,76 +450,16 @@ class ChromaticTree { ...@@ -412,76 +450,16 @@ class ChromaticTree {
const NodePtr& uxl, const NodePtr& uxr, const NodePtr& uxl, const NodePtr& uxr,
const NodePtr& uxxl, const NodePtr& uxxr, const NodePtr& uxxl, const NodePtr& uxxr,
const bool& uxx_is_right); 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> >;
/** // The following included header contains the class methods implementing
* Computes the hight of the subtree rooted at the given node. // tree rotations. It is generated automatically and must be included
* // directly inside the class definition.
* \notthreadsafe # include <embb/containers/internal/lock_free_chromatic_tree-rebalance.h>
*
* \param[IN] node Root of the subtree for which the height is requested /** Callback functor for the hazard pointer that frees retired nodes */
* embb::base::Function<void, NodePtr> free_node_callback_;
* \return The height of a subtree rooted at node \c node. (The height of a /** Hazard pointer instance for protection of node pointers */
* leaf node is defined to be zero). embb::containers::internal::HazardPointer<NodePtr> node_hazard_manager_;
*/
int GetHeight(const NodePtr& node) const;
bool IsBalanced() const;
bool IsBalanced(const NodePtr& node) const;
const Key undefined_key_; /**< A dummy key used by the tree */ const Key undefined_key_; /**< A dummy key used by the tree */
const Value undefined_value_; /**< A dummy value used by the tree */ const Value undefined_value_; /**< A dummy value used by the tree */
...@@ -491,11 +469,10 @@ class ChromaticTree { ...@@ -491,11 +469,10 @@ class ChromaticTree {
NodePtr entry_; /**< Pointer to the sentinel node used as NodePtr entry_; /**< Pointer to the sentinel node used as
* the entry point into the tree */ * the entry point into the tree */
typedef embb::base::ReadWriteLock::Reader ReadWriteLockReader; /**
typedef embb::base::ReadWriteLock::Writer ReadWriteLockWriter; * Friending the test class for white-box testing
typedef embb::base::LockGuard<ReadWriteLockReader> ReaderLockGuard; */
typedef embb::base::LockGuard<ReadWriteLockWriter> WriterLockGuard; friend class test::TreeTest<ChromaticTree<Key, Value, Compare, NodePool> >;
embb::base::ReadWriteLock readwrite_lock_;
}; };
} // namespace containers } // namespace containers
......
...@@ -66,11 +66,11 @@ TreeTest<Tree>::TreeTest() ...@@ -66,11 +66,11 @@ TreeTest<Tree>::TreeTest()
Add(&TreeTest::TreeTestConcurrentGet_ReaderMethod, this, Add(&TreeTest::TreeTestConcurrentGet_ReaderMethod, this,
NUM_TEST_THREADS / 2, NUM_ITERATIONS). NUM_TEST_THREADS / 2, NUM_ITERATIONS).
Post(&TreeTest::TreeTestConcurrentGet_Post, this); Post(&TreeTest::TreeTestConcurrentGet_Post, this);
CreateUnit("TreeTestBalance"). // CreateUnit("TreeTestBalance").
Pre(&TreeTest::TreeTestBalance_Pre, this). // Pre(&TreeTest::TreeTestBalance_Pre, this).
Add(&TreeTest::TreeTestBalance_ThreadMethod, this, // Add(&TreeTest::TreeTestBalance_ThreadMethod, this,
NUM_TEST_THREADS, 1). // NUM_TEST_THREADS, 1).
Post(&TreeTest::TreeTestBalance_Post, this); // Post(&TreeTest::TreeTestBalance_Post, this);
} }
template<typename Tree> 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