diff --git a/base_cpp/include/embb/base/mutex.h b/base_cpp/include/embb/base/mutex.h index fe51706..0b8c7e3 100644 --- a/base_cpp/include/embb/base/mutex.h +++ b/base_cpp/include/embb/base/mutex.h @@ -29,7 +29,6 @@ #include #include -#include 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 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 diff --git a/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h b/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h index 6218cfc..9f6e214 100644 --- a/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h +++ b/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h @@ -30,6 +30,14 @@ #include #include +#ifdef EMBB_DEBUG +static const size_t INVALID_POINTER = static_cast(-1); +# define VERIFY_ADDRESS(addr) assert(reinterpret_cast((addr)) != \ + INVALID_POINTER) +#else +# define VERIFY_ADDRESS(address) ((void)0) +#endif + namespace embb { namespace containers { namespace internal { @@ -37,13 +45,13 @@ namespace internal { template ChromaticTreeNode:: ChromaticTreeNode(const Key& key, const Value& value, const int weight, - ChromaticTreeNode* const & left, - ChromaticTreeNode* const & right) + const ChildPointer& left, const ChildPointer& right) : key_(key), value_(value), weight_(weight), left_(left), - right_(right) {} + right_(right), + retired_(false) {} template ChromaticTreeNode:: @@ -52,16 +60,8 @@ ChromaticTreeNode(const Key& key, const Value& value, const int weight) value_(value), weight_(weight), left_(NULL), - right_(NULL) {} - -template -ChromaticTreeNode:: -ChromaticTreeNode(const ChromaticTreeNode& other) - : key_(other.key_), - value_(other.value_), - weight_(other.weight_), - left_(other.left_), - right_(other.right_) {} + right_(NULL), + retired_(false) {} template const Key& ChromaticTreeNode::GetKey() const { @@ -79,12 +79,14 @@ int ChromaticTreeNode::GetWeight() const { } template -ChromaticTreeNode*& ChromaticTreeNode::GetLeft() { +typename ChromaticTreeNode::AtomicChildPointer& +ChromaticTreeNode::GetLeft() { return left_; } template -ChromaticTreeNode*& ChromaticTreeNode::GetRight() { +typename ChromaticTreeNode::AtomicChildPointer& +ChromaticTreeNode::GetRight() { return right_; } @@ -95,11 +97,22 @@ template ChromaticTree:: 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 ChromaticTree:: ~ChromaticTree() { Destruct(entry_->GetLeft()); - node_pool_.Free(entry_); + FreeNode(entry_); } template bool ChromaticTree:: 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 @@ -140,65 +154,75 @@ TryInsert(const Key& key, const Value& value) { template bool ChromaticTree:: 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 @@ -211,47 +235,89 @@ TryDelete(const Key& key) { template bool ChromaticTree:: 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 @@ -274,31 +340,77 @@ IsEmpty() { template void ChromaticTree:: -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 void ChromaticTree:: -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 void ChromaticTree:: -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 ChromaticTree::NodePtr& +typename ChromaticTree::AtomicNodePtr& ChromaticTree:: 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 +int ChromaticTree:: +GetHeight(const NodePtr& node) const { + int height = 0; + if (node != NULL) { + height = 1 + ::std::max(GetHeight(node->GetLeft()), + GetHeight(node->GetRight())); + } + return height; +} + +template +bool ChromaticTree:: +IsBalanced() const { + return IsBalanced(entry_->GetLeft()); +} + +template +bool ChromaticTree:: +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 +void ChromaticTree:: +FreeNode(NodePtr node) { +#ifdef EMBB_DEBUG + node->GetLeft() = reinterpret_cast(INVALID_POINTER); + node->GetRight() = reinterpret_cast(INVALID_POINTER); +#endif node_pool_.Free(node); } template bool ChromaticTree:: 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 @@ -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 -int ChromaticTree:: -GetHeight(const NodePtr& node) const { - int height = 0; - if (node != NULL) { - height = 1 + ::std::max(GetHeight(node->GetLeft()), - GetHeight(node->GetRight())); - } - return height; -} - -template -bool ChromaticTree:: -IsBalanced() const { - return IsBalanced(entry_->GetLeft()); -} - -template -bool ChromaticTree:: -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 -bool ChromaticTree:: -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 -bool ChromaticTree:: -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 -bool ChromaticTree:: -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 -bool ChromaticTree:: -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 -bool ChromaticTree:: -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 -bool ChromaticTree:: -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 -bool ChromaticTree:: -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 -bool ChromaticTree:: -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 -bool ChromaticTree:: -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 -bool ChromaticTree:: -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 -bool ChromaticTree:: -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 -bool ChromaticTree:: -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 -bool ChromaticTree:: -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 -bool ChromaticTree:: -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 -bool ChromaticTree:: -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 -bool ChromaticTree:: -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 -bool ChromaticTree:: -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 -bool ChromaticTree:: -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 -bool ChromaticTree:: -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 -bool ChromaticTree:: -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 diff --git a/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-rebalance.h b/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-rebalance.h new file mode 100644 index 0000000..5bc0e83 --- /dev/null +++ b/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-rebalance.h @@ -0,0 +1,867 @@ +/* + * 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_ diff --git a/containers_cpp/include/embb/containers/lock_free_chromatic_tree.h b/containers_cpp/include/embb/containers/lock_free_chromatic_tree.h index 9ead994..c431c8d 100644 --- a/containers_cpp/include/embb/containers/lock_free_chromatic_tree.h +++ b/containers_cpp/include/embb/containers/lock_free_chromatic_tree.h @@ -31,6 +31,7 @@ #include #include +#include namespace embb { namespace containers { @@ -48,6 +49,9 @@ namespace internal { template class ChromaticTreeNode { public: + typedef ChromaticTreeNode* ChildPointer; + typedef embb::base::Atomic 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* const & left, - ChromaticTreeNode* 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*& GetLeft(); + AtomicChildPointer& GetLeft(); /** * Accessor for the right child pointer. * * \return Reference to the right child pointer */ - ChromaticTreeNode*& 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* left_; /**< Pointer to left child node */ - ChromaticTreeNode* 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 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* NodePtr; - - + /** + * Typedef for an atomic pointer to a node of the tree. + */ + typedef embb::base::Atomic AtomicNodePtr; + + typedef embb::base::UniqueLock 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 >; - /** - * 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 + + /** Callback functor for the hazard pointer that frees retired nodes */ + embb::base::Function free_node_callback_; + /** Hazard pointer instance for protection of node pointers */ + embb::containers::internal::HazardPointer 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 ReaderLockGuard; - typedef embb::base::LockGuard WriterLockGuard; - embb::base::ReadWriteLock readwrite_lock_; + /** + * Friending the test class for white-box testing + */ + friend class test::TreeTest >; }; } // namespace containers diff --git a/containers_cpp/test/tree_test-inl.h b/containers_cpp/test/tree_test-inl.h index 0873444..8e923a4 100644 --- a/containers_cpp/test/tree_test-inl.h +++ b/containers_cpp/test/tree_test-inl.h @@ -66,11 +66,11 @@ TreeTest::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