Commit e518a31d by Danila Klimenko

Code refactoring (const-correctness, internal interfaces)

parent abd38fe8
...@@ -478,7 +478,7 @@ class Atomic<BaseType*> : public embb::base::internal::atomic:: ...@@ -478,7 +478,7 @@ class Atomic<BaseType*> : public embb::base::internal::atomic::
public: public:
Atomic() : embb::base::internal::atomic:: Atomic() : embb::base::internal::atomic::
AtomicPointer<BaseType, ptrdiff_t, sizeof(BaseType*)>() {} AtomicPointer<BaseType, ptrdiff_t, sizeof(BaseType*)>() {}
Atomic(BaseType* p) : embb::base::internal::atomic:: explicit Atomic(BaseType* p) : embb::base::internal::atomic::
AtomicPointer<BaseType, ptrdiff_t, sizeof(BaseType*)>(p) {} AtomicPointer<BaseType, ptrdiff_t, sizeof(BaseType*)>(p) {}
BaseType* operator=(BaseType* p) { BaseType* operator=(BaseType* p) {
......
...@@ -177,8 +177,7 @@ CompareAndSwap(BaseType& expected, BaseType desired) { ...@@ -177,8 +177,7 @@ CompareAndSwap(BaseType& expected, BaseType desired) {
compare_and_swap(&AtomicValue, &native_expected, native_desired)) !=0 compare_and_swap(&AtomicValue, &native_expected, native_desired)) !=0
? true : false; ? true : false;
if (!return_val) memcpy(&expected, &native_expected, sizeof(expected));
expected = Load();
return return_val; return return_val;
} }
......
...@@ -418,6 +418,118 @@ void HazardPointer< GuardType >::EnqueuePointerForDeletion( ...@@ -418,6 +418,118 @@ void HazardPointer< GuardType >::EnqueuePointerForDeletion(
template<typename GuardType> template<typename GuardType>
const double embb::containers::internal::HazardPointer<GuardType>:: const double embb::containers::internal::HazardPointer<GuardType>::
RETIRE_THRESHOLD = 1.25f; RETIRE_THRESHOLD = 1.25f;
template<typename Type>
UniqueHazardPointer<Type>::
UniqueHazardPointer()
: hazard_guard_(NULL), undefined_guard_(NULL), active_(false) {}
template<typename Type>
UniqueHazardPointer<Type>::
UniqueHazardPointer(AtomicTypePtr& hazard_guard, Type* undefined_guard)
: hazard_guard_(&hazard_guard),
undefined_guard_(undefined_guard),
active_(LoadGuardedPointer() == undefined_guard_) {}
template<typename Type>
UniqueHazardPointer<Type>::~UniqueHazardPointer() {
if (IsActive()) ClearHazard();
}
template<typename Type>
bool UniqueHazardPointer<Type>::ProtectHazard(const AtomicTypePtr& hazard) {
assert(OwnsHazardGuard());
// Read the hazard and store it into the guard
StoreGuardedPointer(hazard.Load());
// Check whether the guard is valid
SetActive(LoadGuardedPointer() == hazard.Load());
// Clear the guard if it is invalid
if (!IsActive()) ClearHazard();
return IsActive();
}
template<typename Type>
void UniqueHazardPointer<Type>::ProtectSafe(Type* safe_ptr) {
assert(OwnsHazardGuard());
StoreGuardedPointer(safe_ptr);
SetActive(true);
}
template<typename Type>
UniqueHazardPointer<Type>::operator Type* () const {
assert(IsActive());
return LoadGuardedPointer();
}
template<typename Type>
Type* UniqueHazardPointer<Type>::operator->() const {
assert(IsActive());
return LoadGuardedPointer();
}
template<typename Type>
Type& UniqueHazardPointer<Type>::operator*() const {
assert(IsActive());
return *(LoadGuardedPointer());
}
template<typename Type>
void UniqueHazardPointer<Type>::AdoptGuard(const UniqueHazardPointer& other) {
assert(OwnsHazardGuard());
StoreGuardedPointer(other.LoadGuardedPointer());
SetActive(other.active_);
}
template<typename Type>
void UniqueHazardPointer<Type>::Swap(UniqueHazardPointer& other) {
std::swap(hazard_guard_, other.hazard_guard_);
std::swap(undefined_guard_, other.undefined_guard_);
std::swap(active_, other.active_);
}
template<typename Type>
Type* UniqueHazardPointer<Type>::ReleaseHazard() {
assert(IsActive());
Type* released_hazard = LoadGuardedPointer();
ClearHazard();
SetActive(false);
return released_hazard;
}
template<typename Type>
bool UniqueHazardPointer<Type>::IsActive() const {
return active_;
}
template<typename Type>
void UniqueHazardPointer<Type>::SetActive(bool active) {
active_ = active;
}
template<typename Type>
void UniqueHazardPointer<Type>::ClearHazard() {
StoreGuardedPointer(undefined_guard_);
}
template<typename Type>
Type* UniqueHazardPointer<Type>::LoadGuardedPointer() const {
return hazard_guard_->Load();
}
template<typename Type>
void UniqueHazardPointer<Type>::StoreGuardedPointer(Type* ptr) {
hazard_guard_->Store(ptr);
}
template<typename Type>
bool UniqueHazardPointer<Type>::OwnsHazardGuard() const {
return hazard_guard_ != NULL;
}
} // namespace internal } // namespace internal
} // namespace containers } // namespace containers
} // namespace embb } // namespace embb
......
...@@ -529,6 +529,175 @@ class HazardPointer { ...@@ -529,6 +529,175 @@ class HazardPointer {
*/ */
void EnqueuePointerForDeletion(GuardType guardedElement); void EnqueuePointerForDeletion(GuardType guardedElement);
}; };
/**
* Ownership wrapper for a hazard pointer
*
* Uses an entry of the hazard table (guard) to provide protection for a single
* hazardous pointer. While providing standard pointer dereference and member
* access operators, it requires special care for pointer assignment (realized
* via 'ProtectHazard' method).
* On destruction, it clears the wrapped hazard table entry, releasing the
* protected hazardous pointer (if any).
*
* \tparam Type Type of the object to be protected by the hazard pointer
*/
template<typename Type>
class UniqueHazardPointer {
public:
/** Typedef for a atomic pointer to the guarded object. */
typedef embb::base::Atomic<Type*> AtomicTypePtr;
/**
* Creates an uninitialized, empty wrapper.
*
* An uninitialized wrapper may only be swapped with another wrapper (using
* \c Swap() method) or checked for being active (using 'IsActive()' method,
* which should always return /c false for an uninitialized wrapper).
*/
UniqueHazardPointer();
/**
* Creates a wrapper that uses the given hazard table entry (referred to as
* "guard") to protect hazardous pointers.
*
* \param[IN] hazard_guard Reference to a hazard table entry
* \param[IN] undefined_guard Dummy value used to clear the hazard table entry
*/
explicit
UniqueHazardPointer(AtomicTypePtr& hazard_guard,
Type* undefined_guard = NULL);
/**
* If initialized and active, clears the hazard table entry.
*/
~UniqueHazardPointer();
/**
* Tries to protect the given hazard using the wrapped guard.
* If it succeeds, the hazard may be safely dereferenced as long as the guard
* is not destroyed or reset to protect another hazard.
*
* \param hazard The hazard to be protected
* \return \c true if the specified hazard is now protected by the guard,
* \c false if the hazard was modified by a concurrent thread
*/
bool ProtectHazard(const AtomicTypePtr& hazard);
/**
* Uses the wrapped guard to protect a pointer that is not hazardous yet.
*
* \param safe_ptr The pointer to be protected
*/
void ProtectSafe(Type* safe_ptr);
/**
* Type cast operator.
*
* \return The hazardous pointer protected by this wrapper
*/
operator Type* () const;
/**
* Pointer member access operator.
*
* \return The hazardous pointer protected by this wrapper
*/
Type* operator->() const;
/**
* Pointer dereference operator.
*
* \return Reference to the object pointed to by the protected pointer
*/
Type& operator*() const;
/**
* Protects the hazard that is currently protected by another wrapper (so it
* becomes protected by two guards simultaneously). The other wrapper remains
* unmodified.
*
* \param other Another wrapper those protected pointer is to be protected by
* the calling wrapper
*/
void AdoptGuard(const UniqueHazardPointer& other);
/**
* Swaps the guard ownership with another wrapper. Swaps not just the
* protected hazards, but the hazard guards themselves.
*
* \param other Another wrapper to swap guards with
*/
void Swap(UniqueHazardPointer& other);
/**
* Clears the hazard guard and returns the hazard previously protected by that
* guard.
*
* \return The hazardous pointer previously protected by this wrapper
*/
Type* ReleaseHazard();
/**
* Check whether the wrapper is active.
*
* \return \c true if the wrapper is initialized and currently protecting some
* hazard, \c false otherwise
*/
bool IsActive() const;
private:
/**
* Sets the 'active' flag of this wrapper.
*
* \param active The new value for the flag
*/
void SetActive(bool active);
/**
* Reset the wrapped hazard guard to a state when it is not protecting any
* hazards.
*/
void ClearHazard();
/**
* Retrieves the hazardous pointer currently protected by the wrapped guard.
*
* \return The hazardous pointer protected by this wrapper
*/
Type* LoadGuardedPointer() const;
/**
* Updates the wrapped guard to protect the specified hazardous pointer.
*
* \param ptr Hazardous pointer to be protected
*/
void StoreGuardedPointer(Type* ptr);
/**
* Check whether the wrapper is initialized (i.e. it wraps some hazard guard)
*
* \return \c true if this wrapper is initialized, \c false otherwise
*/
bool OwnsHazardGuard() const;
/**
* Disable copy construction and assignment.
*/
UniqueHazardPointer(const UniqueHazardPointer&);
UniqueHazardPointer& operator=(const UniqueHazardPointer&);
/**
* Pointer to a hazard table entry (the guard) that is used to store the
* hazardous pointers
*/
AtomicTypePtr* hazard_guard_;
/** Dummy value used to clear the hazard guard from any hazards */
Type* undefined_guard_;
/** Flag set to true when the guard is protecting some hazardous pointer */
bool active_;
};
} // namespace internal } // namespace internal
} // namespace containers } // namespace containers
} // namespace embb } // namespace embb
......
...@@ -44,8 +44,8 @@ namespace internal { ...@@ -44,8 +44,8 @@ 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, int weight,
const ChildPointer& left, const ChildPointer& right) Node* left, Node* right)
: key_(key), : key_(key),
value_(value), value_(value),
weight_(weight), weight_(weight),
...@@ -55,7 +55,7 @@ ChromaticTreeNode(const Key& key, const Value& value, const int weight, ...@@ -55,7 +55,7 @@ ChromaticTreeNode(const Key& key, const Value& value, const int weight,
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, int weight)
: key_(key), : key_(key),
value_(value), value_(value),
weight_(weight), weight_(weight),
...@@ -79,18 +79,44 @@ int ChromaticTreeNode<Key, Value>::GetWeight() const { ...@@ -79,18 +79,44 @@ int ChromaticTreeNode<Key, Value>::GetWeight() const {
} }
template<typename Key, typename Value> template<typename Key, typename Value>
typename ChromaticTreeNode<Key, Value>::AtomicChildPointer& typename ChromaticTreeNode<Key, Value>::AtomicNodePtr&
ChromaticTreeNode<Key, Value>::GetLeft() { ChromaticTreeNode<Key, Value>::GetLeft() {
return left_; return left_;
} }
template<typename Key, typename Value> template<typename Key, typename Value>
typename ChromaticTreeNode<Key, Value>::AtomicChildPointer& typename ChromaticTreeNode<Key, Value>::Node*
ChromaticTreeNode<Key, Value>::GetLeft() const {
return left_.Load();
}
template<typename Key, typename Value>
typename ChromaticTreeNode<Key, Value>::AtomicNodePtr&
ChromaticTreeNode<Key, Value>::GetRight() { ChromaticTreeNode<Key, Value>::GetRight() {
return right_; return right_;
} }
template<typename Key, typename Value> template<typename Key, typename Value>
typename ChromaticTreeNode<Key, Value>::Node*
ChromaticTreeNode<Key, Value>::GetRight() const {
return right_.Load();
}
template<typename Key, typename Value>
bool ChromaticTreeNode<Key, Value>::
ReplaceChild(Node* old_child, Node* new_child) {
bool replaced = false;
if (left_ == old_child) {
replaced = left_.CompareAndSwap(old_child, new_child);
} else if (right_ == old_child) {
replaced = right_.CompareAndSwap(old_child, new_child);
}
return replaced;
}
template<typename Key, typename Value>
void ChromaticTreeNode<Key, Value>::Retire() { void ChromaticTreeNode<Key, Value>::Retire() {
retired_ = true; retired_ = true;
} }
...@@ -105,133 +131,23 @@ embb::base::Mutex& ChromaticTreeNode<Key, Value>::GetMutex() { ...@@ -105,133 +131,23 @@ embb::base::Mutex& ChromaticTreeNode<Key, Value>::GetMutex() {
return mutex_; return mutex_;
} }
template<typename GuardedType>
UniqueHazardPointer<GuardedType>::
UniqueHazardPointer()
: hazard_guard_(NULL), undefined_guard_(NULL), active_(false) {}
template<typename GuardedType>
UniqueHazardPointer<GuardedType>::
UniqueHazardPointer(AtomicGuard& hazard_guard, GuardedPtr undefined_guard)
: hazard_guard_(&hazard_guard),
undefined_guard_(undefined_guard),
active_(LoadGuardedPointer() == undefined_guard_) {}
template<typename GuardedType>
UniqueHazardPointer<GuardedType>::
~UniqueHazardPointer() {
if (IsActive()) ClearHazard();
}
template<typename GuardedType>
bool UniqueHazardPointer<GuardedType>::
ProtectHazard(const AtomicGuard& hazard) {
assert(OwnsHazardGuard());
// Read the hazard and store it into the guard
StoreGuardedPointer(hazard.Load());
// Check whether the guard is valid
SetActive(LoadGuardedPointer() == hazard.Load());
// Clear the guard if it is invalid
if (!IsActive()) ClearHazard();
return IsActive();
}
template<typename GuardedType>
UniqueHazardPointer<GuardedType>::operator GuardedPtr () const {
assert(IsActive());
return LoadGuardedPointer();
}
template<typename GuardedType>
typename UniqueHazardPointer<GuardedType>::GuardedPtr
UniqueHazardPointer<GuardedType>::operator->() const {
assert(IsActive());
return LoadGuardedPointer();
}
template<typename GuardedType>
GuardedType& UniqueHazardPointer<GuardedType>::operator*() const {
assert(IsActive());
return *(LoadGuardedPointer());
}
template<typename GuardedType>
void UniqueHazardPointer<GuardedType>::
AdoptGuard(const UniqueHazardPointer<GuardedType>& other) {
assert(OwnsHazardGuard());
StoreGuardedPointer(other.LoadGuardedPointer());
SetActive(other.active_);
}
template<typename GuardedType>
void UniqueHazardPointer<GuardedType>::
Swap(UniqueHazardPointer<GuardedType>& other) {
std::swap(hazard_guard_, other.hazard_guard_);
std::swap(undefined_guard_, other.undefined_guard_);
std::swap(active_, other.active_);
}
template<typename GuardedType>
typename UniqueHazardPointer<GuardedType>::GuardedPtr
UniqueHazardPointer<GuardedType>::ReleaseHazard() {
assert(IsActive());
GuardedPtr released_hazard = LoadGuardedPointer();
ClearHazard();
SetActive(false);
return released_hazard;
}
template<typename GuardedType>
bool UniqueHazardPointer<GuardedType>::IsActive() const {
return active_;
}
template<typename GuardedType>
void UniqueHazardPointer<GuardedType>::SetActive(bool active) {
active_ = active;
}
template<typename GuardedType>
void UniqueHazardPointer<GuardedType>::ClearHazard() {
StoreGuardedPointer(undefined_guard_);
}
template<typename GuardedType>
typename UniqueHazardPointer<GuardedType>::GuardedPtr
UniqueHazardPointer<GuardedType>::LoadGuardedPointer() const {
return hazard_guard_->Load();
}
template<typename GuardedType>
void UniqueHazardPointer<GuardedType>::StoreGuardedPointer(GuardedPtr ptr) {
hazard_guard_->Store(ptr);
}
template<typename GuardedType>
bool UniqueHazardPointer<GuardedType>::OwnsHazardGuard() const {
return hazard_guard_ != NULL;
}
} // namespace internal } // namespace internal
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
ChromaticTree<Key, Value, Compare, NodePool>:: ChromaticTree<Key, Value, Compare, ValuePool>::
ChromaticTree(size_t capacity, Key undefined_key, Value undefined_value, ChromaticTree(size_t capacity, Key undefined_key, Value undefined_value,
Compare compare) Compare compare)
#ifdef EMBB_PLATFORM_COMPILER_MSVC #ifdef EMBB_PLATFORM_COMPILER_MSVC
#pragma warning(push) #pragma warning(push)
#pragma warning(disable:4355) #pragma warning(disable:4355)
#endif #endif
: free_node_callback_(*this, &ChromaticTree::FreeNode), : node_hazard_manager_(
embb::base::Function<void, Node*>(*this, &ChromaticTree::FreeNode),
NULL, 10),
#ifdef EMBB_PLATFORM_COMPILER_MSVC #ifdef EMBB_PLATFORM_COMPILER_MSVC
#pragma warning(pop) #pragma warning(pop)
#endif #endif
node_hazard_manager_(free_node_callback_, NULL, 10),
undefined_key_(undefined_key), undefined_key_(undefined_key),
undefined_value_(undefined_value), undefined_value_(undefined_value),
compare_(compare), compare_(compare),
...@@ -242,20 +158,20 @@ ChromaticTree(size_t capacity, Key undefined_key, Value undefined_value, ...@@ -242,20 +158,20 @@ ChromaticTree(size_t capacity, Key undefined_key, Value undefined_value,
entry_(node_pool_.Allocate(undefined_key_, undefined_value_, 1, entry_(node_pool_.Allocate(undefined_key_, undefined_value_, 1,
node_pool_.Allocate(undefined_key_, node_pool_.Allocate(undefined_key_,
undefined_value_), undefined_value_),
static_cast<NodePtr>(NULL))) { static_cast<Node*>(NULL))) {
assert(entry_ != NULL); assert(entry_ != NULL);
assert(entry_->GetLeft().Load() != NULL); assert(entry_->GetLeft() != NULL);
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
ChromaticTree<Key, Value, Compare, NodePool>:: ChromaticTree<Key, Value, Compare, ValuePool>::
~ChromaticTree() { ~ChromaticTree() {
Destruct(entry_->GetLeft()); Destruct(entry_->GetLeft());
FreeNode(entry_); FreeNode(entry_);
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, NodePool>:: bool ChromaticTree<Key, Value, Compare, ValuePool>::
Get(const Key& key, Value& value) { Get(const Key& key, Value& value) {
HazardNodePtr parent(node_hazard_manager_.GetGuardedPointer(0)); HazardNodePtr parent(node_hazard_manager_.GetGuardedPointer(0));
HazardNodePtr leaf (node_hazard_manager_.GetGuardedPointer(1)); HazardNodePtr leaf (node_hazard_manager_.GetGuardedPointer(1));
...@@ -272,19 +188,19 @@ Get(const Key& key, Value& value) { ...@@ -272,19 +188,19 @@ Get(const Key& key, Value& value) {
return keys_are_equal; return keys_are_equal;
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, NodePool>:: bool ChromaticTree<Key, Value, Compare, ValuePool>::
TryInsert(const Key& key, const Value& value) { TryInsert(const Key& key, const Value& value) {
Value old_value; Value old_value;
return TryInsert(key, value, old_value); return TryInsert(key, value, old_value);
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, NodePool>:: bool ChromaticTree<Key, Value, Compare, ValuePool>::
TryInsert(const Key& key, const Value& value, Value& old_value) { TryInsert(const Key& key, const Value& value, Value& old_value) {
NodePtr new_leaf = NULL; Node* new_leaf = NULL;
NodePtr new_sibling = NULL; Node* new_sibling = NULL;
NodePtr new_parent = NULL; Node* new_parent = NULL;
bool insertion_succeeded = false; bool insertion_succeeded = false;
bool added_violation = false; bool added_violation = false;
...@@ -330,9 +246,7 @@ TryInsert(const Key& key, const Value& value, Value& old_value) { ...@@ -330,9 +246,7 @@ TryInsert(const Key& key, const Value& value, Value& old_value) {
if (new_parent == NULL) break; if (new_parent == NULL) break;
} }
NodePtr expected = leaf; insertion_succeeded = parent->ReplaceChild(leaf, new_parent);
insertion_succeeded = GetPointerToChild(parent, leaf)
.CompareAndSwap(expected, new_parent);
assert(insertion_succeeded); // For now (FGL tree) this CAS may not fail assert(insertion_succeeded); // For now (FGL tree) this CAS may not fail
if (!insertion_succeeded) continue; if (!insertion_succeeded) continue;
...@@ -353,17 +267,17 @@ TryInsert(const Key& key, const Value& value, Value& old_value) { ...@@ -353,17 +267,17 @@ TryInsert(const Key& key, const Value& value, Value& old_value) {
return insertion_succeeded; return insertion_succeeded;
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, NodePool>:: bool ChromaticTree<Key, Value, Compare, ValuePool>::
TryDelete(const Key& key) { TryDelete(const Key& key) {
Value old_value; Value old_value;
return TryDelete(key, old_value); return TryDelete(key, old_value);
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, NodePool>:: bool ChromaticTree<Key, Value, Compare, ValuePool>::
TryDelete(const Key& key, Value& old_value) { TryDelete(const Key& key, Value& old_value) {
NodePtr new_leaf = NULL; Node* new_leaf = NULL;
bool deletion_succeeded = false; bool deletion_succeeded = false;
bool added_violation = false; bool added_violation = false;
...@@ -396,7 +310,7 @@ TryDelete(const Key& key, Value& old_value) { ...@@ -396,7 +310,7 @@ TryDelete(const Key& key, Value& old_value) {
sibling.ProtectHazard((parent->GetLeft() == leaf) ? sibling.ProtectHazard((parent->GetLeft() == leaf) ?
parent->GetRight() : parent->GetLeft()); parent->GetRight() : parent->GetLeft());
if (parent->IsRetired() || !sibling.IsActive()) continue; if (parent->IsRetired() || !sibling.IsActive()) continue;
VERIFY_ADDRESS(static_cast<NodePtr>(sibling)); VERIFY_ADDRESS(static_cast<Node*>(sibling));
// Verify that the leaf is still the parent's child // Verify that the leaf is still the parent's child
if (!HasChild(parent, leaf)) continue; if (!HasChild(parent, leaf)) continue;
...@@ -419,9 +333,7 @@ TryDelete(const Key& key, Value& old_value) { ...@@ -419,9 +333,7 @@ TryDelete(const Key& key, Value& old_value) {
old_value = leaf->GetValue(); old_value = leaf->GetValue();
NodePtr expected = parent; deletion_succeeded = grandparent->ReplaceChild(parent, new_leaf);
deletion_succeeded = GetPointerToChild(grandparent, parent)
.CompareAndSwap(expected, new_leaf);
assert(deletion_succeeded); // For now (FGL tree) this CAS may not fail assert(deletion_succeeded); // For now (FGL tree) this CAS may not fail
if (!deletion_succeeded) continue; if (!deletion_succeeded) continue;
...@@ -441,31 +353,31 @@ TryDelete(const Key& key, Value& old_value) { ...@@ -441,31 +353,31 @@ TryDelete(const Key& key, Value& old_value) {
return deletion_succeeded; return deletion_succeeded;
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
size_t ChromaticTree<Key, Value, Compare, NodePool>:: size_t ChromaticTree<Key, Value, Compare, ValuePool>::
GetCapacity() const { GetCapacity() const {
return capacity_; return capacity_;
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
const Value& ChromaticTree<Key, Value, Compare, NodePool>:: const Value& ChromaticTree<Key, Value, Compare, ValuePool>::
GetUndefinedValue() { GetUndefinedValue() const {
return undefined_value_; return undefined_value_;
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, NodePool>:: bool ChromaticTree<Key, Value, Compare, ValuePool>::
IsEmpty() const { IsEmpty() const {
return IsLeaf(entry_->GetLeft()); return IsLeaf(entry_->GetLeft());
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
void ChromaticTree<Key, Value, Compare, NodePool>:: void ChromaticTree<Key, Value, Compare, ValuePool>::
Search(const Key& key, HazardNodePtr& leaf, HazardNodePtr& parent) { Search(const Key& key, HazardNodePtr& leaf, HazardNodePtr& parent) {
bool reached_leaf = false; bool reached_leaf = false;
while (!reached_leaf) { while (!reached_leaf) {
parent.ProtectHazard(entry_); parent.ProtectSafe(entry_);
leaf.ProtectHazard(entry_->GetLeft()); leaf.ProtectHazard(entry_->GetLeft());
if (parent->IsRetired() || !leaf.IsActive()) continue; if (parent->IsRetired() || !leaf.IsActive()) continue;
...@@ -475,22 +387,22 @@ Search(const Key& key, HazardNodePtr& leaf, HazardNodePtr& parent) { ...@@ -475,22 +387,22 @@ Search(const Key& key, HazardNodePtr& leaf, HazardNodePtr& parent) {
leaf.ProtectHazard((IsSentinel(leaf) || compare_(key, leaf->GetKey())) ? leaf.ProtectHazard((IsSentinel(leaf) || compare_(key, leaf->GetKey())) ?
leaf->GetLeft() : leaf->GetRight()); leaf->GetLeft() : leaf->GetRight());
if (parent->IsRetired() || !leaf.IsActive()) break; if (parent->IsRetired() || !leaf.IsActive()) break;
VERIFY_ADDRESS(static_cast<NodePtr>(leaf)); VERIFY_ADDRESS(static_cast<Node*>(leaf));
reached_leaf = IsLeaf(leaf); reached_leaf = IsLeaf(leaf);
} }
} }
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
void ChromaticTree<Key, Value, Compare, NodePool>:: void ChromaticTree<Key, Value, Compare, ValuePool>::
Search(const Key& key, HazardNodePtr& leaf, HazardNodePtr& parent, Search(const Key& key, HazardNodePtr& leaf, HazardNodePtr& parent,
HazardNodePtr& grandparent) { HazardNodePtr& grandparent) {
bool reached_leaf = false; bool reached_leaf = false;
while (!reached_leaf) { while (!reached_leaf) {
grandparent.ProtectHazard(entry_); grandparent.ProtectSafe(entry_);
parent.ProtectHazard(entry_); parent.ProtectSafe(entry_);
leaf.ProtectHazard(entry_->GetLeft()); leaf.ProtectHazard(entry_->GetLeft());
if (parent->IsRetired() || !leaf.IsActive()) continue; if (parent->IsRetired() || !leaf.IsActive()) continue;
...@@ -501,42 +413,34 @@ Search(const Key& key, HazardNodePtr& leaf, HazardNodePtr& parent, ...@@ -501,42 +413,34 @@ Search(const Key& key, HazardNodePtr& leaf, HazardNodePtr& parent,
leaf.ProtectHazard((IsSentinel(leaf) || compare_(key, leaf->GetKey())) ? leaf.ProtectHazard((IsSentinel(leaf) || compare_(key, leaf->GetKey())) ?
leaf->GetLeft() : leaf->GetRight()); leaf->GetLeft() : leaf->GetRight());
if (parent->IsRetired() || !leaf.IsActive()) break; if (parent->IsRetired() || !leaf.IsActive()) break;
VERIFY_ADDRESS(static_cast<NodePtr>(leaf)); VERIFY_ADDRESS(static_cast<Node*>(leaf));
reached_leaf = IsLeaf(leaf); reached_leaf = IsLeaf(leaf);
} }
} }
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, NodePool>:: bool ChromaticTree<Key, Value, Compare, ValuePool>::
IsLeaf(const NodePtr& node) const { IsLeaf(const Node* node) const {
return node->GetLeft() == NULL; return node->GetLeft() == NULL;
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, NodePool>:: bool ChromaticTree<Key, Value, Compare, ValuePool>::
IsSentinel(const NodePtr& node) const { IsSentinel(const Node* node) const {
return (node == entry_) || (node == entry_->GetLeft()); return (node == entry_) || (node == entry_->GetLeft());
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, NodePool>:: bool ChromaticTree<Key, Value, Compare, ValuePool>::
HasChild(const NodePtr& parent, const NodePtr& child) const { HasChild(const Node* parent, const Node* child) const {
return (parent->GetLeft() == child || parent->GetRight() == child); return (parent->GetLeft() == child || parent->GetRight() == child);
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
typename ChromaticTree<Key, Value, Compare, NodePool>::AtomicNodePtr& void ChromaticTree<Key, Value, Compare, ValuePool>::
ChromaticTree<Key, Value, Compare, NodePool>:: Destruct(Node* node) {
GetPointerToChild(const NodePtr& parent, const NodePtr& child) const {
assert(HasChild(parent, child));
return (parent->GetLeft() == child) ? parent->GetLeft() : parent->GetRight();
}
template<typename Key, typename Value, typename Compare, typename NodePool>
void ChromaticTree<Key, Value, Compare, NodePool>::
Destruct(const NodePtr& node) {
if (!IsLeaf(node)) { if (!IsLeaf(node)) {
Destruct(node->GetLeft()); Destruct(node->GetLeft());
Destruct(node->GetRight()); Destruct(node->GetRight());
...@@ -544,9 +448,9 @@ Destruct(const NodePtr& node) { ...@@ -544,9 +448,9 @@ Destruct(const NodePtr& node) {
FreeNode(node); FreeNode(node);
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
int ChromaticTree<Key, Value, Compare, NodePool>:: int ChromaticTree<Key, Value, Compare, ValuePool>::
GetHeight(const NodePtr& node) const { GetHeight(const Node* node) const {
int height = 0; int height = 0;
if (node != NULL) { if (node != NULL) {
height = 1 + ::std::max(GetHeight(node->GetLeft()), height = 1 + ::std::max(GetHeight(node->GetLeft()),
...@@ -555,21 +459,21 @@ GetHeight(const NodePtr& node) const { ...@@ -555,21 +459,21 @@ GetHeight(const NodePtr& node) const {
return height; return height;
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, NodePool>:: bool ChromaticTree<Key, Value, Compare, ValuePool>::
IsBalanced() const { IsBalanced() const {
return IsBalanced(entry_->GetLeft()); return IsBalanced(entry_->GetLeft());
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, NodePool>:: bool ChromaticTree<Key, Value, Compare, ValuePool>::
IsBalanced(const NodePtr& node) const { IsBalanced(const Node* node) const {
// Overweight violation // Overweight violation
bool has_violation = node->GetWeight() > 1; bool has_violation = node->GetWeight() > 1;
if (!has_violation && !IsLeaf(node)) { if (!has_violation && !IsLeaf(node)) {
NodePtr left = node->GetLeft(); const Node* left = node->GetLeft();
NodePtr right = node->GetRight(); const Node* right = node->GetRight();
// Red-red violation // Red-red violation
has_violation = node->GetWeight() == 0 && has_violation = node->GetWeight() == 0 &&
...@@ -584,27 +488,27 @@ IsBalanced(const NodePtr& node) const { ...@@ -584,27 +488,27 @@ IsBalanced(const NodePtr& node) const {
return !has_violation; return !has_violation;
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
void ChromaticTree<Key, Value, Compare, NodePool>:: void ChromaticTree<Key, Value, Compare, ValuePool>::
RetireHazardousNode(HazardNodePtr& node, UniqueLock& node_lock) { RetireHazardousNode(HazardNodePtr& node, UniqueLock& node_lock) {
node->Retire(); node->Retire();
node_lock.Unlock(); node_lock.Unlock();
NodePtr node_to_delete = node.ReleaseHazard(); Node* node_to_delete = node.ReleaseHazard();
node_hazard_manager_.EnqueuePointerForDeletion(node_to_delete); node_hazard_manager_.EnqueuePointerForDeletion(node_to_delete);
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
void ChromaticTree<Key, Value, Compare, NodePool>:: void ChromaticTree<Key, Value, Compare, ValuePool>::
FreeNode(NodePtr node) { FreeNode(Node* node) {
#ifdef EMBB_DEBUG #ifdef EMBB_DEBUG
node->GetLeft() = reinterpret_cast<NodePtr>(INVALID_POINTER); node->GetLeft() = reinterpret_cast<Node*>(INVALID_POINTER);
node->GetRight() = reinterpret_cast<NodePtr>(INVALID_POINTER); node->GetRight() = reinterpret_cast<Node*>(INVALID_POINTER);
#endif #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 ValuePool>
bool ChromaticTree<Key, Value, Compare, NodePool>:: bool ChromaticTree<Key, Value, Compare, ValuePool>::
CleanUp(const Key& key) { CleanUp(const Key& key) {
HazardNodePtr grandgrandparent(node_hazard_manager_.GetGuardedPointer(0)); HazardNodePtr grandgrandparent(node_hazard_manager_.GetGuardedPointer(0));
HazardNodePtr grandparent (node_hazard_manager_.GetGuardedPointer(1)); HazardNodePtr grandparent (node_hazard_manager_.GetGuardedPointer(1));
...@@ -615,9 +519,9 @@ CleanUp(const Key& key) { ...@@ -615,9 +519,9 @@ CleanUp(const Key& key) {
while (!reached_leaf) { while (!reached_leaf) {
bool found_violation = false; bool found_violation = false;
grandgrandparent.ProtectHazard(entry_); grandgrandparent.ProtectSafe(entry_);
grandparent.ProtectHazard(entry_); grandparent.ProtectSafe(entry_);
parent.ProtectHazard(entry_); parent.ProtectSafe(entry_);
leaf.ProtectHazard(entry_->GetLeft()); leaf.ProtectHazard(entry_->GetLeft());
if (parent->IsRetired() || !leaf.IsActive()) continue; if (parent->IsRetired() || !leaf.IsActive()) continue;
...@@ -629,7 +533,7 @@ CleanUp(const Key& key) { ...@@ -629,7 +533,7 @@ CleanUp(const Key& key) {
leaf.ProtectHazard((IsSentinel(leaf) || compare_(key, leaf->GetKey())) ? leaf.ProtectHazard((IsSentinel(leaf) || compare_(key, leaf->GetKey())) ?
leaf->GetLeft() : leaf->GetRight()); leaf->GetLeft() : leaf->GetRight());
if (parent->IsRetired() || !leaf.IsActive()) break; if (parent->IsRetired() || !leaf.IsActive()) break;
VERIFY_ADDRESS(static_cast<NodePtr>(leaf)); VERIFY_ADDRESS(static_cast<Node*>(leaf));
found_violation = (leaf->GetWeight() > 1) || found_violation = (leaf->GetWeight() > 1) ||
(leaf->GetWeight() == 0 && parent->GetWeight() == 0); (leaf->GetWeight() == 0 && parent->GetWeight() == 0);
...@@ -659,10 +563,10 @@ CleanUp(const Key& key) { ...@@ -659,10 +563,10 @@ CleanUp(const Key& key) {
HazardNodePtr node(node_hazard_manager_.GetGuardedPointer(h_num)); \ HazardNodePtr node(node_hazard_manager_.GetGuardedPointer(h_num)); \
node.ProtectHazard(parent->method()); \ node.ProtectHazard(parent->method()); \
if (parent->IsRetired() || !node.IsActive()) return EMBB_BUSY; \ if (parent->IsRetired() || !node.IsActive()) return EMBB_BUSY; \
VERIFY_ADDRESS(static_cast<NodePtr>(node)) VERIFY_ADDRESS(static_cast<Node*>(node))
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
embb_errors_t ChromaticTree<Key, Value, Compare, NodePool>:: embb_errors_t ChromaticTree<Key, Value, Compare, ValuePool>::
Rebalance(HazardNodePtr& u, HazardNodePtr& ux, HazardNodePtr& uxx, Rebalance(HazardNodePtr& u, HazardNodePtr& ux, HazardNodePtr& uxx,
HazardNodePtr& uxxx) { HazardNodePtr& uxxx) {
// Protect node 'u' // Protect node 'u'
...@@ -730,8 +634,8 @@ Rebalance(HazardNodePtr& u, HazardNodePtr& ux, HazardNodePtr& uxx, ...@@ -730,8 +634,8 @@ Rebalance(HazardNodePtr& u, HazardNodePtr& ux, HazardNodePtr& uxx,
} }
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
embb_errors_t ChromaticTree<Key, Value, Compare, NodePool>:: embb_errors_t ChromaticTree<Key, Value, Compare, ValuePool>::
OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock, OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& ux, UniqueLock& ux_lock,
HazardNodePtr& uxx, UniqueLock& uxx_lock, HazardNodePtr& uxx, UniqueLock& uxx_lock,
...@@ -876,8 +780,8 @@ OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock, ...@@ -876,8 +780,8 @@ OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock,
} }
} }
template<typename Key, typename Value, typename Compare, typename NodePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
embb_errors_t ChromaticTree<Key, Value, Compare, NodePool>:: embb_errors_t ChromaticTree<Key, Value, Compare, ValuePool>::
OverweightRight(HazardNodePtr& u, UniqueLock& u_lock, OverweightRight(HazardNodePtr& u, UniqueLock& u_lock,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& ux, UniqueLock& ux_lock,
HazardNodePtr& uxx, UniqueLock& uxx_lock, HazardNodePtr& uxx, UniqueLock& uxx_lock,
......
...@@ -37,15 +37,15 @@ embb_errors_t BLK( ...@@ -37,15 +37,15 @@ embb_errors_t BLK(
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& ux, UniqueLock& ux_lock,
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock) { HazardNodePtr& uxr, UniqueLock& uxr_lock) {
NodePtr nxl = node_pool_.Allocate( Node* nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(), uxl->GetKey(), uxl->GetValue(),
1, 1,
uxl->GetLeft(), uxl->GetRight()); uxl->GetLeft(), uxl->GetRight());
NodePtr nxr = node_pool_.Allocate( Node* nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(), uxr->GetKey(), uxr->GetValue(),
1, 1,
uxr->GetLeft(), uxr->GetRight()); uxr->GetLeft(), uxr->GetRight());
NodePtr nx = node_pool_.Allocate( Node* nx = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
IsSentinel(u) ? 1 : ux->GetWeight() - 1, IsSentinel(u) ? 1 : ux->GetWeight() - 1,
nxl, nxr); nxl, nxr);
...@@ -59,9 +59,7 @@ embb_errors_t BLK( ...@@ -59,9 +59,7 @@ embb_errors_t BLK(
return EMBB_NOMEM; return EMBB_NOMEM;
} }
NodePtr expected = ux; bool rotation_succeeded = u->ReplaceChild(ux, nx);
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY; if (!rotation_succeeded) return EMBB_BUSY;
...@@ -78,15 +76,15 @@ embb_errors_t PUSH_L( ...@@ -78,15 +76,15 @@ embb_errors_t PUSH_L(
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& ux, UniqueLock& ux_lock,
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock) { HazardNodePtr& uxr, UniqueLock& uxr_lock) {
NodePtr nxl = node_pool_.Allocate( Node* nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(), uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1, uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight()); uxl->GetLeft(), uxl->GetRight());
NodePtr nxr = node_pool_.Allocate( Node* nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(), uxr->GetKey(), uxr->GetValue(),
0, 0,
uxr->GetLeft(), uxr->GetRight()); uxr->GetLeft(), uxr->GetRight());
NodePtr nx = node_pool_.Allocate( Node* nx = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
IsSentinel(u) ? 1 : ux->GetWeight() + 1, IsSentinel(u) ? 1 : ux->GetWeight() + 1,
nxl, nxr); nxl, nxr);
...@@ -100,9 +98,7 @@ embb_errors_t PUSH_L( ...@@ -100,9 +98,7 @@ embb_errors_t PUSH_L(
return EMBB_NOMEM; return EMBB_NOMEM;
} }
NodePtr expected = ux; bool rotation_succeeded = u->ReplaceChild(ux, nx);
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY; if (!rotation_succeeded) return EMBB_BUSY;
...@@ -119,15 +115,15 @@ embb_errors_t PUSH_R( ...@@ -119,15 +115,15 @@ embb_errors_t PUSH_R(
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& ux, UniqueLock& ux_lock,
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock) { HazardNodePtr& uxr, UniqueLock& uxr_lock) {
NodePtr nxr = node_pool_.Allocate( Node* nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(), uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1, uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight()); uxr->GetLeft(), uxr->GetRight());
NodePtr nxl = node_pool_.Allocate( Node* nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(), uxl->GetKey(), uxl->GetValue(),
0, 0,
uxl->GetLeft(), uxl->GetRight()); uxl->GetLeft(), uxl->GetRight());
NodePtr nx = node_pool_.Allocate( Node* nx = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
IsSentinel(u) ? 1 : ux->GetWeight() + 1, IsSentinel(u) ? 1 : ux->GetWeight() + 1,
nxl, nxr); nxl, nxr);
...@@ -141,9 +137,7 @@ embb_errors_t PUSH_R( ...@@ -141,9 +137,7 @@ embb_errors_t PUSH_R(
return EMBB_NOMEM; return EMBB_NOMEM;
} }
NodePtr expected = ux; bool rotation_succeeded = u->ReplaceChild(ux, nx);
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY; if (!rotation_succeeded) return EMBB_BUSY;
...@@ -159,11 +153,11 @@ embb_errors_t RB1_L( ...@@ -159,11 +153,11 @@ embb_errors_t RB1_L(
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& u, UniqueLock& u_lock,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& ux, UniqueLock& ux_lock,
HazardNodePtr& uxl, UniqueLock& uxl_lock) { HazardNodePtr& uxl, UniqueLock& uxl_lock) {
NodePtr nxr = node_pool_.Allocate( Node* nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
0, 0,
uxl->GetRight(), ux->GetRight()); uxl->GetRight(), ux->GetRight());
NodePtr nx = node_pool_.Allocate( Node* nx = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(), uxl->GetKey(), uxl->GetValue(),
ux->GetWeight(), ux->GetWeight(),
uxl->GetLeft(), nxr); uxl->GetLeft(), nxr);
...@@ -175,9 +169,7 @@ embb_errors_t RB1_L( ...@@ -175,9 +169,7 @@ embb_errors_t RB1_L(
return EMBB_NOMEM; return EMBB_NOMEM;
} }
NodePtr expected = ux; bool rotation_succeeded = u->ReplaceChild(ux, nx);
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY; if (!rotation_succeeded) return EMBB_BUSY;
...@@ -192,11 +184,11 @@ embb_errors_t RB1_R( ...@@ -192,11 +184,11 @@ embb_errors_t RB1_R(
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& u, UniqueLock& u_lock,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& ux, UniqueLock& ux_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock) { HazardNodePtr& uxr, UniqueLock& uxr_lock) {
NodePtr nxl = node_pool_.Allocate( Node* nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
0, 0,
ux->GetLeft(), uxr->GetLeft()); ux->GetLeft(), uxr->GetLeft());
NodePtr nx = node_pool_.Allocate( Node* nx = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(), uxr->GetKey(), uxr->GetValue(),
ux->GetWeight(), ux->GetWeight(),
nxl, uxr->GetRight()); nxl, uxr->GetRight());
...@@ -208,9 +200,7 @@ embb_errors_t RB1_R( ...@@ -208,9 +200,7 @@ embb_errors_t RB1_R(
return EMBB_NOMEM; return EMBB_NOMEM;
} }
NodePtr expected = ux; bool rotation_succeeded = u->ReplaceChild(ux, nx);
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY; if (!rotation_succeeded) return EMBB_BUSY;
...@@ -226,15 +216,15 @@ embb_errors_t RB2_L( ...@@ -226,15 +216,15 @@ embb_errors_t RB2_L(
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& ux, UniqueLock& ux_lock,
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxlr, UniqueLock& uxlr_lock) { HazardNodePtr& uxlr, UniqueLock& uxlr_lock) {
NodePtr nxl = node_pool_.Allocate( Node* nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(), uxl->GetKey(), uxl->GetValue(),
0, 0,
uxl->GetLeft(), uxlr->GetLeft()); uxl->GetLeft(), uxlr->GetLeft());
NodePtr nxr = node_pool_.Allocate( Node* nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
0, 0,
uxlr->GetRight(), ux->GetRight()); uxlr->GetRight(), ux->GetRight());
NodePtr nx = node_pool_.Allocate( Node* nx = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(), uxlr->GetKey(), uxlr->GetValue(),
ux->GetWeight(), ux->GetWeight(),
nxl, nxr); nxl, nxr);
...@@ -248,9 +238,7 @@ embb_errors_t RB2_L( ...@@ -248,9 +238,7 @@ embb_errors_t RB2_L(
return EMBB_NOMEM; return EMBB_NOMEM;
} }
NodePtr expected = ux; bool rotation_succeeded = u->ReplaceChild(ux, nx);
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY; if (!rotation_succeeded) return EMBB_BUSY;
...@@ -267,15 +255,15 @@ embb_errors_t RB2_R( ...@@ -267,15 +255,15 @@ embb_errors_t RB2_R(
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& ux, UniqueLock& ux_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxrl, UniqueLock& uxrl_lock) { HazardNodePtr& uxrl, UniqueLock& uxrl_lock) {
NodePtr nxr = node_pool_.Allocate( Node* nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(), uxr->GetKey(), uxr->GetValue(),
0, 0,
uxrl->GetRight(), uxr->GetRight()); uxrl->GetRight(), uxr->GetRight());
NodePtr nxl = node_pool_.Allocate( Node* nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
0, 0,
ux->GetLeft(), uxrl->GetLeft()); ux->GetLeft(), uxrl->GetLeft());
NodePtr nx = node_pool_.Allocate( Node* nx = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(), uxrl->GetKey(), uxrl->GetValue(),
ux->GetWeight(), ux->GetWeight(),
nxl, nxr); nxl, nxr);
...@@ -289,9 +277,7 @@ embb_errors_t RB2_R( ...@@ -289,9 +277,7 @@ embb_errors_t RB2_R(
return EMBB_NOMEM; return EMBB_NOMEM;
} }
NodePtr expected = ux; bool rotation_succeeded = u->ReplaceChild(ux, nx);
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY; if (!rotation_succeeded) return EMBB_BUSY;
...@@ -309,19 +295,19 @@ embb_errors_t W1_L( ...@@ -309,19 +295,19 @@ embb_errors_t W1_L(
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxrl, UniqueLock& uxrl_lock) { HazardNodePtr& uxrl, UniqueLock& uxrl_lock) {
NodePtr nxll = node_pool_.Allocate( Node* nxll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(), uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1, uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight()); uxl->GetLeft(), uxl->GetRight());
NodePtr nxlr = node_pool_.Allocate( Node* nxlr = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(), uxrl->GetKey(), uxrl->GetValue(),
uxrl->GetWeight() - 1, uxrl->GetWeight() - 1,
uxrl->GetLeft(), uxrl->GetRight()); uxrl->GetLeft(), uxrl->GetRight());
NodePtr nxl = node_pool_.Allocate( Node* nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
1, 1,
nxll, nxlr); nxll, nxlr);
NodePtr nx = node_pool_.Allocate( Node* nx = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(), uxr->GetKey(), uxr->GetValue(),
ux->GetWeight(), ux->GetWeight(),
nxl, uxr->GetRight()); nxl, uxr->GetRight());
...@@ -337,9 +323,7 @@ embb_errors_t W1_L( ...@@ -337,9 +323,7 @@ embb_errors_t W1_L(
return EMBB_NOMEM; return EMBB_NOMEM;
} }
NodePtr expected = ux; bool rotation_succeeded = u->ReplaceChild(ux, nx);
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY; if (!rotation_succeeded) return EMBB_BUSY;
...@@ -358,19 +342,19 @@ embb_errors_t W1_R( ...@@ -358,19 +342,19 @@ embb_errors_t W1_R(
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxlr, UniqueLock& uxlr_lock) { HazardNodePtr& uxlr, UniqueLock& uxlr_lock) {
NodePtr nxrr = node_pool_.Allocate( Node* nxrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(), uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1, uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight()); uxr->GetLeft(), uxr->GetRight());
NodePtr nxrl = node_pool_.Allocate( Node* nxrl = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(), uxlr->GetKey(), uxlr->GetValue(),
uxlr->GetWeight() - 1, uxlr->GetWeight() - 1,
uxlr->GetLeft(), uxlr->GetRight()); uxlr->GetLeft(), uxlr->GetRight());
NodePtr nxr = node_pool_.Allocate( Node* nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
1, 1,
nxrl, nxrr); nxrl, nxrr);
NodePtr nx = node_pool_.Allocate( Node* nx = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(), uxl->GetKey(), uxl->GetValue(),
ux->GetWeight(), ux->GetWeight(),
uxl->GetLeft(), nxr); uxl->GetLeft(), nxr);
...@@ -386,9 +370,7 @@ embb_errors_t W1_R( ...@@ -386,9 +370,7 @@ embb_errors_t W1_R(
return EMBB_NOMEM; return EMBB_NOMEM;
} }
NodePtr expected = ux; bool rotation_succeeded = u->ReplaceChild(ux, nx);
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY; if (!rotation_succeeded) return EMBB_BUSY;
...@@ -407,19 +389,19 @@ embb_errors_t W2_L( ...@@ -407,19 +389,19 @@ embb_errors_t W2_L(
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxrl, UniqueLock& uxrl_lock) { HazardNodePtr& uxrl, UniqueLock& uxrl_lock) {
NodePtr nxll = node_pool_.Allocate( Node* nxll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(), uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1, uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight()); uxl->GetLeft(), uxl->GetRight());
NodePtr nxlr = node_pool_.Allocate( Node* nxlr = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(), uxrl->GetKey(), uxrl->GetValue(),
0, 0,
uxrl->GetLeft(), uxrl->GetRight()); uxrl->GetLeft(), uxrl->GetRight());
NodePtr nxl = node_pool_.Allocate( Node* nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
1, 1,
nxll, nxlr); nxll, nxlr);
NodePtr nx = node_pool_.Allocate( Node* nx = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(), uxr->GetKey(), uxr->GetValue(),
ux->GetWeight(), ux->GetWeight(),
nxl, uxr->GetRight()); nxl, uxr->GetRight());
...@@ -435,9 +417,7 @@ embb_errors_t W2_L( ...@@ -435,9 +417,7 @@ embb_errors_t W2_L(
return EMBB_NOMEM; return EMBB_NOMEM;
} }
NodePtr expected = ux; bool rotation_succeeded = u->ReplaceChild(ux, nx);
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY; if (!rotation_succeeded) return EMBB_BUSY;
...@@ -456,19 +436,19 @@ embb_errors_t W2_R( ...@@ -456,19 +436,19 @@ embb_errors_t W2_R(
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxlr, UniqueLock& uxlr_lock) { HazardNodePtr& uxlr, UniqueLock& uxlr_lock) {
NodePtr nxrr = node_pool_.Allocate( Node* nxrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(), uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1, uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight()); uxr->GetLeft(), uxr->GetRight());
NodePtr nxrl = node_pool_.Allocate( Node* nxrl = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(), uxlr->GetKey(), uxlr->GetValue(),
0, 0,
uxlr->GetLeft(), uxlr->GetRight()); uxlr->GetLeft(), uxlr->GetRight());
NodePtr nxr = node_pool_.Allocate( Node* nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
1, 1,
nxrl, nxrr); nxrl, nxrr);
NodePtr nx = node_pool_.Allocate( Node* nx = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(), uxl->GetKey(), uxl->GetValue(),
ux->GetWeight(), ux->GetWeight(),
uxl->GetLeft(), nxr); uxl->GetLeft(), nxr);
...@@ -484,9 +464,7 @@ embb_errors_t W2_R( ...@@ -484,9 +464,7 @@ embb_errors_t W2_R(
return EMBB_NOMEM; return EMBB_NOMEM;
} }
NodePtr expected = ux; bool rotation_succeeded = u->ReplaceChild(ux, nx);
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY; if (!rotation_succeeded) return EMBB_BUSY;
...@@ -506,23 +484,23 @@ embb_errors_t W3_L( ...@@ -506,23 +484,23 @@ embb_errors_t W3_L(
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxrl, UniqueLock& uxrl_lock, HazardNodePtr& uxrl, UniqueLock& uxrl_lock,
HazardNodePtr& uxrll, UniqueLock& uxrll_lock) { HazardNodePtr& uxrll, UniqueLock& uxrll_lock) {
NodePtr nxlll = node_pool_.Allocate( Node* nxlll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(), uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1, uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight()); uxl->GetLeft(), uxl->GetRight());
NodePtr nxll = node_pool_.Allocate( Node* nxll = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
1, 1,
nxlll, uxrll->GetLeft()); nxlll, uxrll->GetLeft());
NodePtr nxlr = node_pool_.Allocate( Node* nxlr = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(), uxrl->GetKey(), uxrl->GetValue(),
1, 1,
uxrll->GetRight(), uxrl->GetRight()); uxrll->GetRight(), uxrl->GetRight());
NodePtr nxl = node_pool_.Allocate( Node* nxl = node_pool_.Allocate(
uxrll->GetKey(), uxrll->GetValue(), uxrll->GetKey(), uxrll->GetValue(),
0, 0,
nxll, nxlr); nxll, nxlr);
NodePtr nx = node_pool_.Allocate( Node* nx = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(), uxr->GetKey(), uxr->GetValue(),
ux->GetWeight(), ux->GetWeight(),
nxl, uxr->GetRight()); nxl, uxr->GetRight());
...@@ -540,9 +518,7 @@ embb_errors_t W3_L( ...@@ -540,9 +518,7 @@ embb_errors_t W3_L(
return EMBB_NOMEM; return EMBB_NOMEM;
} }
NodePtr expected = ux; bool rotation_succeeded = u->ReplaceChild(ux, nx);
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY; if (!rotation_succeeded) return EMBB_BUSY;
...@@ -563,23 +539,23 @@ embb_errors_t W3_R( ...@@ -563,23 +539,23 @@ embb_errors_t W3_R(
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxlr, UniqueLock& uxlr_lock, HazardNodePtr& uxlr, UniqueLock& uxlr_lock,
HazardNodePtr& uxlrr, UniqueLock& uxlrr_lock) { HazardNodePtr& uxlrr, UniqueLock& uxlrr_lock) {
NodePtr nxrrr = node_pool_.Allocate( Node* nxrrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(), uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1, uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight()); uxr->GetLeft(), uxr->GetRight());
NodePtr nxrr = node_pool_.Allocate( Node* nxrr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
1, 1,
uxlrr->GetRight(), nxrrr); uxlrr->GetRight(), nxrrr);
NodePtr nxrl = node_pool_.Allocate( Node* nxrl = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(), uxlr->GetKey(), uxlr->GetValue(),
1, 1,
uxlr->GetLeft(), uxlrr->GetLeft()); uxlr->GetLeft(), uxlrr->GetLeft());
NodePtr nxr = node_pool_.Allocate( Node* nxr = node_pool_.Allocate(
uxlrr->GetKey(), uxlrr->GetValue(), uxlrr->GetKey(), uxlrr->GetValue(),
0, 0,
nxrl, nxrr); nxrl, nxrr);
NodePtr nx = node_pool_.Allocate( Node* nx = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(), uxl->GetKey(), uxl->GetValue(),
ux->GetWeight(), ux->GetWeight(),
uxl->GetLeft(), nxr); uxl->GetLeft(), nxr);
...@@ -597,9 +573,7 @@ embb_errors_t W3_R( ...@@ -597,9 +573,7 @@ embb_errors_t W3_R(
return EMBB_NOMEM; return EMBB_NOMEM;
} }
NodePtr expected = ux; bool rotation_succeeded = u->ReplaceChild(ux, nx);
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY; if (!rotation_succeeded) return EMBB_BUSY;
...@@ -620,23 +594,23 @@ embb_errors_t W4_L( ...@@ -620,23 +594,23 @@ embb_errors_t W4_L(
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxrl, UniqueLock& uxrl_lock, HazardNodePtr& uxrl, UniqueLock& uxrl_lock,
HazardNodePtr& uxrlr, UniqueLock& uxrlr_lock) { HazardNodePtr& uxrlr, UniqueLock& uxrlr_lock) {
NodePtr nxll = node_pool_.Allocate( Node* nxll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(), uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1, uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight()); uxl->GetLeft(), uxl->GetRight());
NodePtr nxrl = node_pool_.Allocate( Node* nxrl = node_pool_.Allocate(
uxrlr->GetKey(), uxrlr->GetValue(), uxrlr->GetKey(), uxrlr->GetValue(),
1, 1,
uxrlr->GetLeft(), uxrlr->GetRight()); uxrlr->GetLeft(), uxrlr->GetRight());
NodePtr nxl = node_pool_.Allocate( Node* nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
1, 1,
nxll, uxrl->GetLeft()); nxll, uxrl->GetLeft());
NodePtr nxr = node_pool_.Allocate( Node* nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(), uxr->GetKey(), uxr->GetValue(),
0, 0,
nxrl, uxr->GetRight()); nxrl, uxr->GetRight());
NodePtr nx = node_pool_.Allocate( Node* nx = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(), uxrl->GetKey(), uxrl->GetValue(),
ux->GetWeight(), ux->GetWeight(),
nxl, nxr); nxl, nxr);
...@@ -654,9 +628,7 @@ embb_errors_t W4_L( ...@@ -654,9 +628,7 @@ embb_errors_t W4_L(
return EMBB_NOMEM; return EMBB_NOMEM;
} }
NodePtr expected = ux; bool rotation_succeeded = u->ReplaceChild(ux, nx);
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY; if (!rotation_succeeded) return EMBB_BUSY;
...@@ -677,23 +649,23 @@ embb_errors_t W4_R( ...@@ -677,23 +649,23 @@ embb_errors_t W4_R(
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxlr, UniqueLock& uxlr_lock, HazardNodePtr& uxlr, UniqueLock& uxlr_lock,
HazardNodePtr& uxlrl, UniqueLock& uxlrl_lock) { HazardNodePtr& uxlrl, UniqueLock& uxlrl_lock) {
NodePtr nxrr = node_pool_.Allocate( Node* nxrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(), uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1, uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight()); uxr->GetLeft(), uxr->GetRight());
NodePtr nxlr = node_pool_.Allocate( Node* nxlr = node_pool_.Allocate(
uxlrl->GetKey(), uxlrl->GetValue(), uxlrl->GetKey(), uxlrl->GetValue(),
1, 1,
uxlrl->GetLeft(), uxlrl->GetRight()); uxlrl->GetLeft(), uxlrl->GetRight());
NodePtr nxr = node_pool_.Allocate( Node* nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
1, 1,
uxlr->GetRight(), nxrr); uxlr->GetRight(), nxrr);
NodePtr nxl = node_pool_.Allocate( Node* nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(), uxl->GetKey(), uxl->GetValue(),
0, 0,
uxl->GetLeft(), nxlr); uxl->GetLeft(), nxlr);
NodePtr nx = node_pool_.Allocate( Node* nx = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(), uxlr->GetKey(), uxlr->GetValue(),
ux->GetWeight(), ux->GetWeight(),
nxl, nxr); nxl, nxr);
...@@ -711,9 +683,7 @@ embb_errors_t W4_R( ...@@ -711,9 +683,7 @@ embb_errors_t W4_R(
return EMBB_NOMEM; return EMBB_NOMEM;
} }
NodePtr expected = ux; bool rotation_succeeded = u->ReplaceChild(ux, nx);
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY; if (!rotation_succeeded) return EMBB_BUSY;
...@@ -733,19 +703,19 @@ embb_errors_t W5_L( ...@@ -733,19 +703,19 @@ embb_errors_t W5_L(
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxrr, UniqueLock& uxrr_lock) { HazardNodePtr& uxrr, UniqueLock& uxrr_lock) {
NodePtr nxll = node_pool_.Allocate( Node* nxll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(), uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1, uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight()); uxl->GetLeft(), uxl->GetRight());
NodePtr nxl = node_pool_.Allocate( Node* nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
1, 1,
nxll, uxr->GetLeft()); nxll, uxr->GetLeft());
NodePtr nxr = node_pool_.Allocate( Node* nxr = node_pool_.Allocate(
uxrr->GetKey(), uxrr->GetValue(), uxrr->GetKey(), uxrr->GetValue(),
1, 1,
uxrr->GetLeft(), uxrr->GetRight()); uxrr->GetLeft(), uxrr->GetRight());
NodePtr nx = node_pool_.Allocate( Node* nx = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(), uxr->GetKey(), uxr->GetValue(),
ux->GetWeight(), ux->GetWeight(),
nxl, nxr); nxl, nxr);
...@@ -761,9 +731,7 @@ embb_errors_t W5_L( ...@@ -761,9 +731,7 @@ embb_errors_t W5_L(
return EMBB_NOMEM; return EMBB_NOMEM;
} }
NodePtr expected = ux; bool rotation_succeeded = u->ReplaceChild(ux, nx);
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY; if (!rotation_succeeded) return EMBB_BUSY;
...@@ -782,19 +750,19 @@ embb_errors_t W5_R( ...@@ -782,19 +750,19 @@ embb_errors_t W5_R(
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxll, UniqueLock& uxll_lock) { HazardNodePtr& uxll, UniqueLock& uxll_lock) {
NodePtr nxrr = node_pool_.Allocate( Node* nxrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(), uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1, uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight()); uxr->GetLeft(), uxr->GetRight());
NodePtr nxr = node_pool_.Allocate( Node* nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
1, 1,
uxl->GetRight(), nxrr); uxl->GetRight(), nxrr);
NodePtr nxl = node_pool_.Allocate( Node* nxl = node_pool_.Allocate(
uxll->GetKey(), uxll->GetValue(), uxll->GetKey(), uxll->GetValue(),
1, 1,
uxll->GetLeft(), uxll->GetRight()); uxll->GetLeft(), uxll->GetRight());
NodePtr nx = node_pool_.Allocate( Node* nx = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(), uxl->GetKey(), uxl->GetValue(),
ux->GetWeight(), ux->GetWeight(),
nxl, nxr); nxl, nxr);
...@@ -810,9 +778,7 @@ embb_errors_t W5_R( ...@@ -810,9 +778,7 @@ embb_errors_t W5_R(
return EMBB_NOMEM; return EMBB_NOMEM;
} }
NodePtr expected = ux; bool rotation_succeeded = u->ReplaceChild(ux, nx);
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY; if (!rotation_succeeded) return EMBB_BUSY;
...@@ -831,19 +797,19 @@ embb_errors_t W6_L( ...@@ -831,19 +797,19 @@ embb_errors_t W6_L(
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxrl, UniqueLock& uxrl_lock) { HazardNodePtr& uxrl, UniqueLock& uxrl_lock) {
NodePtr nxll = node_pool_.Allocate( Node* nxll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(), uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1, uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight()); uxl->GetLeft(), uxl->GetRight());
NodePtr nxl = node_pool_.Allocate( Node* nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
1, 1,
nxll, uxrl->GetLeft()); nxll, uxrl->GetLeft());
NodePtr nxr = node_pool_.Allocate( Node* nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(), uxr->GetKey(), uxr->GetValue(),
1, 1,
uxrl->GetRight(), uxr->GetRight()); uxrl->GetRight(), uxr->GetRight());
NodePtr nx = node_pool_.Allocate( Node* nx = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(), uxrl->GetKey(), uxrl->GetValue(),
ux->GetWeight(), ux->GetWeight(),
nxl, nxr); nxl, nxr);
...@@ -859,9 +825,7 @@ embb_errors_t W6_L( ...@@ -859,9 +825,7 @@ embb_errors_t W6_L(
return EMBB_NOMEM; return EMBB_NOMEM;
} }
NodePtr expected = ux; bool rotation_succeeded = u->ReplaceChild(ux, nx);
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY; if (!rotation_succeeded) return EMBB_BUSY;
...@@ -880,19 +844,19 @@ embb_errors_t W6_R( ...@@ -880,19 +844,19 @@ embb_errors_t W6_R(
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxlr, UniqueLock& uxlr_lock) { HazardNodePtr& uxlr, UniqueLock& uxlr_lock) {
NodePtr nxrr = node_pool_.Allocate( Node* nxrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(), uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1, uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight()); uxr->GetLeft(), uxr->GetRight());
NodePtr nxr = node_pool_.Allocate( Node* nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
1, 1,
uxlr->GetRight(), nxrr); uxlr->GetRight(), nxrr);
NodePtr nxl = node_pool_.Allocate( Node* nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(), uxl->GetKey(), uxl->GetValue(),
1, 1,
uxl->GetLeft(), uxlr->GetLeft()); uxl->GetLeft(), uxlr->GetLeft());
NodePtr nx = node_pool_.Allocate( Node* nx = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(), uxlr->GetKey(), uxlr->GetValue(),
ux->GetWeight(), ux->GetWeight(),
nxl, nxr); nxl, nxr);
...@@ -908,9 +872,7 @@ embb_errors_t W6_R( ...@@ -908,9 +872,7 @@ embb_errors_t W6_R(
return EMBB_NOMEM; return EMBB_NOMEM;
} }
NodePtr expected = ux; bool rotation_succeeded = u->ReplaceChild(ux, nx);
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY; if (!rotation_succeeded) return EMBB_BUSY;
...@@ -928,15 +890,15 @@ embb_errors_t W7( ...@@ -928,15 +890,15 @@ embb_errors_t W7(
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& ux, UniqueLock& ux_lock,
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock) { HazardNodePtr& uxr, UniqueLock& uxr_lock) {
NodePtr nxl = node_pool_.Allocate( Node* nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(), uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1, uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight()); uxl->GetLeft(), uxl->GetRight());
NodePtr nxr = node_pool_.Allocate( Node* nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(), uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1, uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight()); uxr->GetLeft(), uxr->GetRight());
NodePtr nx = node_pool_.Allocate( Node* nx = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), ux->GetKey(), ux->GetValue(),
IsSentinel(u) ? 1 : ux->GetWeight() + 1, IsSentinel(u) ? 1 : ux->GetWeight() + 1,
nxl, nxr); nxl, nxr);
...@@ -950,9 +912,7 @@ embb_errors_t W7( ...@@ -950,9 +912,7 @@ embb_errors_t W7(
return EMBB_NOMEM; return EMBB_NOMEM;
} }
NodePtr expected = ux; bool rotation_succeeded = u->ReplaceChild(ux, nx);
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY; if (!rotation_succeeded) return EMBB_BUSY;
......
...@@ -50,8 +50,8 @@ namespace internal { ...@@ -50,8 +50,8 @@ namespace internal {
template<typename Key, typename Value> template<typename Key, typename Value>
class ChromaticTreeNode { class ChromaticTreeNode {
public: public:
typedef ChromaticTreeNode<Key, Value>* ChildPointer; typedef ChromaticTreeNode<Key, Value> Node;
typedef embb::base::Atomic<ChildPointer> AtomicChildPointer; typedef embb::base::Atomic<Node*> AtomicNodePtr;
/** /**
* Creates a node with given parameters. * Creates a node with given parameters.
...@@ -62,8 +62,8 @@ class ChromaticTreeNode { ...@@ -62,8 +62,8 @@ class ChromaticTreeNode {
* \param[IN] left Pointer to the left child node * \param[IN] left Pointer to the left child node
* \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, int weight,
const ChildPointer& left, const ChildPointer& right); Node* left, Node* 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
...@@ -73,7 +73,7 @@ class ChromaticTreeNode { ...@@ -73,7 +73,7 @@ class ChromaticTreeNode {
* \param[IN] value Value of the new node * \param[IN] value Value of the new node
* \param[IN] weight Weight of the new node * \param[IN] weight Weight of the new node
*/ */
ChromaticTreeNode(const Key& key, const Value& value, const int weight = 1); ChromaticTreeNode(const Key& key, const Value& value, int weight = 1);
/** /**
* Accessor for the stored key. * Accessor for the stored key.
...@@ -101,14 +101,30 @@ class ChromaticTreeNode { ...@@ -101,14 +101,30 @@ class ChromaticTreeNode {
* *
* \return Reference to the left child pointer * \return Reference to the left child pointer
*/ */
AtomicChildPointer& GetLeft(); AtomicNodePtr& GetLeft();
Node* GetLeft() const;
/** /**
* 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
*/ */
AtomicChildPointer& GetRight(); AtomicNodePtr& GetRight();
Node* GetRight() const;
/**
* Tries to replace one of the child pointers that compares equal to
* \c old_child with the \c new_child using an atomic compare-and-swap
* operation. If neither left nor right child pointer is pointing to
* \c old_child, returns \c false.
*
* \param old_child[IN] Pointer to an old child node to compare against
* \param new_child[IN] Pointer to the new child node
*
* \return \c true if one of the child pointers is now pointing to
* \c new_child, \c false otherwise
*/
bool ReplaceChild(Node* old_child, Node* new_child);
/** /**
* Marks node for deletion from the tree * Marks node for deletion from the tree
...@@ -136,183 +152,16 @@ class ChromaticTreeNode { ...@@ -136,183 +152,16 @@ class ChromaticTreeNode {
ChromaticTreeNode(const ChromaticTreeNode&); ChromaticTreeNode(const ChromaticTreeNode&);
ChromaticTreeNode& operator=(const ChromaticTreeNode&); ChromaticTreeNode& operator=(const ChromaticTreeNode&);
const Key key_; /**< Stored key */ const Key key_; /**< Stored key */
const Value value_; /**< Stored value */ const Value value_; /**< Stored value */
const int weight_; /**< Weight of the node */ const int weight_; /**< Weight of the node */
AtomicChildPointer left_; /**< Pointer to left child node */ AtomicNodePtr left_; /**< Pointer to left child node */
AtomicChildPointer right_; /**< Pointer to right child node */ AtomicNodePtr right_; /**< Pointer to right child node */
embb::base::Atomic<bool> retired_; /**< Retired (marked for deletion) flag */ embb::base::Atomic<bool> retired_; /**< Retired (marked for deletion) flag */
embb::base::Mutex mutex_; /**< Fine-grained locking tree: per node mutex */ embb::base::Mutex mutex_; /**< Fine-grained locking tree: per node mutex */
}; };
/**
* Ownership wrapper for a hazard pointer
*
* Uses an entry of the hazard table to provide protection for a single
* hazardous pointer. While providing standard pointer dereference and member
* access operators, it requires special care for pointer assignment (realized
* via 'ProtectHazard' method).
* On destruction, it clears the wrapped hazard table entry, releasing the
* protected hazardous pointer (if any).
*
* \tparam GuardedType Type of the object to be protected by the hazard pointer
*/
template<typename GuardedType>
class UniqueHazardPointer {
public:
/**
* Typedef for a pointer to the guarded object.
*/
typedef GuardedType* GuardedPtr;
/**
* Typedef for a atomic pointer to the guarded object.
*/
typedef embb::base::Atomic<GuardedPtr> AtomicGuard;
/**
* Creates an uninitialized, empty wrapper.
*
* An uninitialized wrapper may only be swapped with another wrapper (using
* \c Swap() method) or checked for being active (using 'IsActive()' method,
* which should always return /c false for an uninitialized wrapper).
*/
UniqueHazardPointer();
/**
* Creates a wrapper that uses the given hazard table entry (referred to as
* "guard") to protect hazardous pointers.
*
* \param[IN] hazard_guard Reference to a hazard table entry
* \param[IN] undefined_guard Dummy value used to clear the hazard table entry
*/
explicit
UniqueHazardPointer(AtomicGuard& hazard_guard,
GuardedPtr undefined_guard = NULL);
/**
* If initialized and active, clears the hazard table entry.
*/
~UniqueHazardPointer();
/**
* Tries to protect the given hazard using the wrapped hazard pointer (guard).
* If it succeeds, the hazard may be safely dereferenced as long as the guard
* is not destroyed or reset to protect another hazard.
*
* \param hazard The hazard to be protected
* \return \c true if the specified hazard is now protected by the guard,
* \c false if the hazard was modified by a concurrent thread
*/
bool ProtectHazard(const AtomicGuard& hazard);
/**
* Type cast operator.
*
* \return The hazardous pointer protected by this wrapper
*/
operator GuardedPtr () const;
/**
* Pointer member access operator.
*
* \return The hazardous pointer protected by this wrapper
*/
GuardedPtr operator->() const;
/**
* Pointer dereference operator.
*
* \return Reference to the object pointed to by the protected pointer
*/
GuardedType& operator*() const;
/**
* Protects the hazard that is currently protected by another wrapper (so it
* becomes protected by two guards simultaneously). The other wrapper remains
* unmodified.
*
* \param other Another wrapper those protected pointer is to be protected by
* the calling wrapper
*/
void AdoptGuard(const UniqueHazardPointer<GuardedType>& other);
/**
* Swaps the guard ownership with another wrapper. Swaps not just the
* protected hazards, but the hazard guards themselves.
*
* \param other Another wrapper to swap guards with
*/
void Swap(UniqueHazardPointer<GuardedType>& other);
/**
* Clears the hazard guard and returns the hazard previously protected by that
* guard.
*
* \return The hazardous pointer previously protected by this wrapper
*/
GuardedPtr ReleaseHazard();
/**
* Check whether the wrapper is active.
*
* \return \c true if the wrapper is initialized and currently protecting some
* hazard, \c false otherwise
*/
bool IsActive() const;
private:
/**
* Sets the 'active' flag of this wrapper.
*
* \param active The new value for the flag
*/
void SetActive(bool active);
/**
* Reset the wrapped hazard guard to a state when it is not protecting any
* hazards.
*/
void ClearHazard();
/**
* Retrieves the hazardous pointer currently protected by the wrapped guard.
*
* \return The hazardous pointer protected by this wrapper
*/
GuardedPtr LoadGuardedPointer() const;
/**
* Updates the wrapped guard to protect the specified hazardous pointer.
*
* \param ptr Hazardous pointer to be protected
*/
void StoreGuardedPointer(GuardedPtr ptr);
/**
* Check whether the wrapper is initialized (i.e. it wraps some hazard guard)
*
* \return \c true if this wrapper is initialized, \c false otherwise
*/
bool OwnsHazardGuard() const;
/**
* Disable copy construction and assignment.
*/
UniqueHazardPointer(const UniqueHazardPointer&);
UniqueHazardPointer& operator=(const UniqueHazardPointer&);
/**
* Pointer to a hazard table entry (the guard) that is used to store the
* hazardous pointers
*/
AtomicGuard* hazard_guard_;
/** Dummy value used to clear the hazard guard from any hazards */
GuardedPtr undefined_guard_;
/** Flag set to true when the guard is protecting some hazardous pointer */
bool active_;
};
} // namespace internal } // namespace internal
namespace test { namespace test {
...@@ -330,20 +179,19 @@ class TreeTest; ...@@ -330,20 +179,19 @@ class TreeTest;
* Implements a balanced BST with support for \c Get, \c Insert and \c Delete * Implements a balanced BST with support for \c Get, \c Insert and \c Delete
* operations. * operations.
* *
* \tparam Key Key type * \tparam Key Key type
* \tparam Value Value type * \tparam Value Value type
* \tparam Compare Custom comparator type for the keys. An object of the * \tparam Compare Custom comparator type for the keys. An object of the
* type \c Compare must must be a functor taking two * type \c Compare must must be a functor taking two
* arguments \c rhs and \c lhs of type \c Key and * arguments \c rhs and \c lhs of type \c Key and
* returning \c true if and only if <tt>(rhs < lhs)</tt> holds * returning \c true if and only if <tt>(rhs < lhs)</tt> holds
* \tparam NodePool The object pool type used for allocation/deallocation * \tparam ValuePool Type of the value pool to be used inside object pools for
* of tree nodes. * tree nodes and operation objects.
*/ */
template<typename Key, template<typename Key,
typename Value, typename Value,
typename Compare = ::std::less<Key>, typename Compare = ::std::less<Key>,
typename NodePool = ObjectPool<internal::ChromaticTreeNode<Key, Value>, typename ValuePool = LockFreeTreeValuePool<bool, false>
LockFreeTreeValuePool<bool, false> >
> >
class ChromaticTree { class ChromaticTree {
public: public:
...@@ -465,7 +313,7 @@ class ChromaticTree { ...@@ -465,7 +313,7 @@ class ChromaticTree {
* *
* \return Object of type \c Value that is used by the tree as a dummy value * \return Object of type \c Value that is used by the tree as a dummy value
*/ */
const Value& GetUndefinedValue(); const Value& GetUndefinedValue() const;
/** /**
* Checks whether the tree is currently empty. * Checks whether the tree is currently empty.
...@@ -475,26 +323,16 @@ class ChromaticTree { ...@@ -475,26 +323,16 @@ class ChromaticTree {
bool IsEmpty() const; bool IsEmpty() const;
private: private:
/** /** Typedef for a node of the tree. */
* Typedef for a node of the tree.
*/
typedef internal::ChromaticTreeNode<Key, Value> Node; typedef internal::ChromaticTreeNode<Key, Value> Node;
/** /** Typedef for an atomic pointer to a node of the tree. */
* Typedef for a pointer to a node of the tree. typedef embb::base::Atomic<Node*> AtomicNodePtr;
*/ /** Typedef for an pointer to a node protected by a Hazard Pointer. */
typedef internal::ChromaticTreeNode<Key, Value>* NodePtr;
/**
* Typedef for an atomic pointer to a node of the tree.
*/
typedef embb::base::Atomic<NodePtr> AtomicNodePtr;
/**
* Typedef for an pointer to a node protected by a Hazard Pointer.
*/
typedef internal::UniqueHazardPointer<Node> HazardNodePtr; typedef internal::UniqueHazardPointer<Node> HazardNodePtr;
/** /** Typedef for the UniqueLock class. */
* Typedef for the UniqueLock class.
*/
typedef embb::base::UniqueLock<embb::base::Mutex> UniqueLock; typedef embb::base::UniqueLock<embb::base::Mutex> UniqueLock;
/** Typedef for an object pool for tree nodes. */
typedef ObjectPool<Node, ValuePool> NodePool;
/** /**
...@@ -528,7 +366,7 @@ class ChromaticTree { ...@@ -528,7 +366,7 @@ class ChromaticTree {
* *
* \return \c true if the given node is a leaf, \c false otherwise * \return \c true if the given node is a leaf, \c false otherwise
*/ */
bool IsLeaf(const NodePtr& node) const; bool IsLeaf(const Node* node) const;
/** /**
* Checks whether the given node is a sentinel node. * Checks whether the given node is a sentinel node.
...@@ -537,7 +375,7 @@ class ChromaticTree { ...@@ -537,7 +375,7 @@ class ChromaticTree {
* *
* \return \c true if the given node is a sentinel node, \c false otherwise * \return \c true if the given node is a sentinel node, \c false otherwise
*/ */
bool IsSentinel(const NodePtr& node) const; bool IsSentinel(const Node* node) const;
/** /**
* Checks whether the given node has a specified child node. * Checks whether the given node has a specified child node.
...@@ -548,22 +386,8 @@ class ChromaticTree { ...@@ -548,22 +386,8 @@ class ChromaticTree {
* \return \c true if \c child is a child node of \c parent, \c false * \return \c true if \c child is a child node of \c parent, \c false
* otherwise * otherwise
*/ */
bool HasChild(const NodePtr& parent, const NodePtr& child) const; bool HasChild(const Node* parent, const Node* child) const;
/**
* Accessor for the child pointer of a given parent to the specified child.
*
* \pre The \c child has to be an actual child of the \c parent.
*
* \param[IN] parent Parent node
* \param[IN] child Child node of the \c parent
*
* \return Reference to a member pointer of the \c parent that points to
* the \c child
*/
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
* node itself. * node itself.
...@@ -572,7 +396,7 @@ class ChromaticTree { ...@@ -572,7 +396,7 @@ 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(Node* node);
/** /**
* Computes the hight of the subtree rooted at the given node. * Computes the hight of the subtree rooted at the given node.
...@@ -584,7 +408,7 @@ class ChromaticTree { ...@@ -584,7 +408,7 @@ class ChromaticTree {
* \return The height of a subtree rooted at node \c node. (The height of a * \return The height of a subtree rooted at node \c node. (The height of a
* leaf node is defined to be zero). * leaf node is defined to be zero).
*/ */
int GetHeight(const NodePtr& node) const; int GetHeight(const Node* node) const;
/** /**
* Check whether the tree is currently in a balanced state (if it is a valid * Check whether the tree is currently in a balanced state (if it is a valid
...@@ -601,7 +425,7 @@ class ChromaticTree { ...@@ -601,7 +425,7 @@ class ChromaticTree {
* *
* \return \c true if the tree is balanced, \c false otherwise * \return \c true if the tree is balanced, \c false otherwise
*/ */
bool IsBalanced(const NodePtr& node) const; bool IsBalanced(const Node* node) const;
/** /**
* Free a tree node using the Hazard Pointers memory reclamation routines. * Free a tree node using the Hazard Pointers memory reclamation routines.
...@@ -616,7 +440,7 @@ class ChromaticTree { ...@@ -616,7 +440,7 @@ class ChromaticTree {
* *
* \param[IN] node A node to be freed. * \param[IN] node A node to be freed.
*/ */
void FreeNode(NodePtr node); void FreeNode(Node* 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
...@@ -654,23 +478,21 @@ class ChromaticTree { ...@@ -654,23 +478,21 @@ class ChromaticTree {
// directly inside the class definition. // directly inside the class definition.
# include <embb/containers/internal/lock_free_chromatic_tree-rebalance.h> # include <embb/containers/internal/lock_free_chromatic_tree-rebalance.h>
/** Callback functor for the hazard pointer that frees retired nodes */
embb::base::Function<void, NodePtr> free_node_callback_;
/** Hazard pointer instance for protection of node pointers */ /** Hazard pointer instance for protection of node pointers */
embb::containers::internal::HazardPointer<NodePtr> node_hazard_manager_; internal::HazardPointer<Node*> node_hazard_manager_;
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 */
const Compare compare_; /**< Comparator object for the keys */ const Compare compare_; /**< Comparator object for the keys */
size_t capacity_; /**< User-requested capacity of the tree */ size_t capacity_; /**< User-requested capacity of the tree */
NodePool node_pool_; /**< Comparator object for the keys */ NodePool node_pool_; /**< Comparator object for the keys */
const AtomicNodePtr entry_; /**< Pointer to the sentinel node used as Node* const entry_; /**< Pointer to the sentinel node used as
* the entry point into the tree */ * the entry point into the tree */
/** /**
* Friending the test class for white-box testing * Friending the test class for white-box testing
*/ */
friend class test::TreeTest<ChromaticTree<Key, Value, Compare, NodePool> >; friend class test::TreeTest<ChromaticTree>;
}; };
} // namespace containers } // namespace containers
......
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