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::
public:
Atomic() : embb::base::internal::atomic::
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) {}
BaseType* operator=(BaseType* p) {
......
......@@ -177,8 +177,7 @@ CompareAndSwap(BaseType& expected, BaseType desired) {
compare_and_swap(&AtomicValue, &native_expected, native_desired)) !=0
? true : false;
if (!return_val)
expected = Load();
memcpy(&expected, &native_expected, sizeof(expected));
return return_val;
}
......
......@@ -418,6 +418,118 @@ void HazardPointer< GuardType >::EnqueuePointerForDeletion(
template<typename GuardType>
const double embb::containers::internal::HazardPointer<GuardType>::
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 containers
} // namespace embb
......
......@@ -529,6 +529,175 @@ class HazardPointer {
*/
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 containers
} // namespace embb
......
......@@ -44,8 +44,8 @@ namespace internal {
template<typename Key, typename Value>
ChromaticTreeNode<Key, Value>::
ChromaticTreeNode(const Key& key, const Value& value, const int weight,
const ChildPointer& left, const ChildPointer& right)
ChromaticTreeNode(const Key& key, const Value& value, int weight,
Node* left, Node* right)
: key_(key),
value_(value),
weight_(weight),
......@@ -55,7 +55,7 @@ ChromaticTreeNode(const Key& key, const Value& value, const int weight,
template<typename Key, typename 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),
value_(value),
weight_(weight),
......@@ -79,18 +79,44 @@ int ChromaticTreeNode<Key, Value>::GetWeight() const {
}
template<typename Key, typename Value>
typename ChromaticTreeNode<Key, Value>::AtomicChildPointer&
typename ChromaticTreeNode<Key, Value>::AtomicNodePtr&
ChromaticTreeNode<Key, Value>::GetLeft() {
return left_;
}
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() {
return right_;
}
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() {
retired_ = true;
}
......@@ -105,133 +131,23 @@ embb::base::Mutex& ChromaticTreeNode<Key, Value>::GetMutex() {
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
template<typename Key, typename Value, typename Compare, typename NodePool>
ChromaticTree<Key, Value, Compare, NodePool>::
template<typename Key, typename Value, typename Compare, typename ValuePool>
ChromaticTree<Key, Value, Compare, ValuePool>::
ChromaticTree(size_t capacity, Key undefined_key, Value undefined_value,
Compare compare)
#ifdef EMBB_PLATFORM_COMPILER_MSVC
#pragma warning(push)
#pragma warning(disable:4355)
#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
#pragma warning(pop)
#endif
node_hazard_manager_(free_node_callback_, NULL, 10),
undefined_key_(undefined_key),
undefined_value_(undefined_value),
compare_(compare),
......@@ -242,20 +158,20 @@ ChromaticTree(size_t capacity, Key undefined_key, Value undefined_value,
entry_(node_pool_.Allocate(undefined_key_, undefined_value_, 1,
node_pool_.Allocate(undefined_key_,
undefined_value_),
static_cast<NodePtr>(NULL))) {
static_cast<Node*>(NULL))) {
assert(entry_ != NULL);
assert(entry_->GetLeft().Load() != NULL);
assert(entry_->GetLeft() != NULL);
}
template<typename Key, typename Value, typename Compare, typename NodePool>
ChromaticTree<Key, Value, Compare, NodePool>::
template<typename Key, typename Value, typename Compare, typename ValuePool>
ChromaticTree<Key, Value, Compare, ValuePool>::
~ChromaticTree() {
Destruct(entry_->GetLeft());
FreeNode(entry_);
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
Get(const Key& key, Value& value) {
HazardNodePtr parent(node_hazard_manager_.GetGuardedPointer(0));
HazardNodePtr leaf (node_hazard_manager_.GetGuardedPointer(1));
......@@ -272,19 +188,19 @@ Get(const Key& key, Value& value) {
return keys_are_equal;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
TryInsert(const Key& key, const Value& value) {
Value old_value;
return TryInsert(key, value, old_value);
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
TryInsert(const Key& key, const Value& value, Value& old_value) {
NodePtr new_leaf = NULL;
NodePtr new_sibling = NULL;
NodePtr new_parent = NULL;
Node* new_leaf = NULL;
Node* new_sibling = NULL;
Node* new_parent = NULL;
bool insertion_succeeded = false;
bool added_violation = false;
......@@ -330,9 +246,7 @@ TryInsert(const Key& key, const Value& value, Value& old_value) {
if (new_parent == NULL) break;
}
NodePtr expected = leaf;
insertion_succeeded = GetPointerToChild(parent, leaf)
.CompareAndSwap(expected, new_parent);
insertion_succeeded = parent->ReplaceChild(leaf, new_parent);
assert(insertion_succeeded); // For now (FGL tree) this CAS may not fail
if (!insertion_succeeded) continue;
......@@ -353,17 +267,17 @@ TryInsert(const Key& key, const Value& value, Value& old_value) {
return insertion_succeeded;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
TryDelete(const Key& key) {
Value old_value;
return TryDelete(key, old_value);
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
TryDelete(const Key& key, Value& old_value) {
NodePtr new_leaf = NULL;
Node* new_leaf = NULL;
bool deletion_succeeded = false;
bool added_violation = false;
......@@ -396,7 +310,7 @@ TryDelete(const Key& key, Value& old_value) {
sibling.ProtectHazard((parent->GetLeft() == leaf) ?
parent->GetRight() : parent->GetLeft());
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
if (!HasChild(parent, leaf)) continue;
......@@ -419,9 +333,7 @@ TryDelete(const Key& key, Value& old_value) {
old_value = leaf->GetValue();
NodePtr expected = parent;
deletion_succeeded = GetPointerToChild(grandparent, parent)
.CompareAndSwap(expected, new_leaf);
deletion_succeeded = grandparent->ReplaceChild(parent, new_leaf);
assert(deletion_succeeded); // For now (FGL tree) this CAS may not fail
if (!deletion_succeeded) continue;
......@@ -441,31 +353,31 @@ TryDelete(const Key& key, Value& old_value) {
return deletion_succeeded;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
size_t ChromaticTree<Key, Value, Compare, NodePool>::
template<typename Key, typename Value, typename Compare, typename ValuePool>
size_t ChromaticTree<Key, Value, Compare, ValuePool>::
GetCapacity() const {
return capacity_;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
const Value& ChromaticTree<Key, Value, Compare, NodePool>::
GetUndefinedValue() {
template<typename Key, typename Value, typename Compare, typename ValuePool>
const Value& ChromaticTree<Key, Value, Compare, ValuePool>::
GetUndefinedValue() const {
return undefined_value_;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
IsEmpty() const {
return IsLeaf(entry_->GetLeft());
}
template<typename Key, typename Value, typename Compare, typename NodePool>
void ChromaticTree<Key, Value, Compare, NodePool>::
template<typename Key, typename Value, typename Compare, typename ValuePool>
void ChromaticTree<Key, Value, Compare, ValuePool>::
Search(const Key& key, HazardNodePtr& leaf, HazardNodePtr& parent) {
bool reached_leaf = false;
while (!reached_leaf) {
parent.ProtectHazard(entry_);
parent.ProtectSafe(entry_);
leaf.ProtectHazard(entry_->GetLeft());
if (parent->IsRetired() || !leaf.IsActive()) continue;
......@@ -475,22 +387,22 @@ Search(const Key& key, HazardNodePtr& leaf, HazardNodePtr& parent) {
leaf.ProtectHazard((IsSentinel(leaf) || compare_(key, leaf->GetKey())) ?
leaf->GetLeft() : leaf->GetRight());
if (parent->IsRetired() || !leaf.IsActive()) break;
VERIFY_ADDRESS(static_cast<NodePtr>(leaf));
VERIFY_ADDRESS(static_cast<Node*>(leaf));
reached_leaf = IsLeaf(leaf);
}
}
}
template<typename Key, typename Value, typename Compare, typename NodePool>
void ChromaticTree<Key, Value, Compare, NodePool>::
template<typename Key, typename Value, typename Compare, typename ValuePool>
void ChromaticTree<Key, Value, Compare, ValuePool>::
Search(const Key& key, HazardNodePtr& leaf, HazardNodePtr& parent,
HazardNodePtr& grandparent) {
bool reached_leaf = false;
while (!reached_leaf) {
grandparent.ProtectHazard(entry_);
parent.ProtectHazard(entry_);
grandparent.ProtectSafe(entry_);
parent.ProtectSafe(entry_);
leaf.ProtectHazard(entry_->GetLeft());
if (parent->IsRetired() || !leaf.IsActive()) continue;
......@@ -501,42 +413,34 @@ Search(const Key& key, HazardNodePtr& leaf, HazardNodePtr& parent,
leaf.ProtectHazard((IsSentinel(leaf) || compare_(key, leaf->GetKey())) ?
leaf->GetLeft() : leaf->GetRight());
if (parent->IsRetired() || !leaf.IsActive()) break;
VERIFY_ADDRESS(static_cast<NodePtr>(leaf));
VERIFY_ADDRESS(static_cast<Node*>(leaf));
reached_leaf = IsLeaf(leaf);
}
}
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
IsLeaf(const NodePtr& node) const {
template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
IsLeaf(const Node* node) const {
return node->GetLeft() == NULL;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
IsSentinel(const NodePtr& node) const {
template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
IsSentinel(const Node* node) const {
return (node == entry_) || (node == entry_->GetLeft());
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
HasChild(const NodePtr& parent, const NodePtr& child) const {
template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
HasChild(const Node* parent, const Node* child) const {
return (parent->GetLeft() == child || parent->GetRight() == child);
}
template<typename Key, typename Value, typename Compare, typename NodePool>
typename ChromaticTree<Key, Value, Compare, NodePool>::AtomicNodePtr&
ChromaticTree<Key, Value, Compare, NodePool>::
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) {
template<typename Key, typename Value, typename Compare, typename ValuePool>
void ChromaticTree<Key, Value, Compare, ValuePool>::
Destruct(Node* node) {
if (!IsLeaf(node)) {
Destruct(node->GetLeft());
Destruct(node->GetRight());
......@@ -544,9 +448,9 @@ Destruct(const NodePtr& node) {
FreeNode(node);
}
template<typename Key, typename Value, typename Compare, typename NodePool>
int ChromaticTree<Key, Value, Compare, NodePool>::
GetHeight(const NodePtr& node) const {
template<typename Key, typename Value, typename Compare, typename ValuePool>
int ChromaticTree<Key, Value, Compare, ValuePool>::
GetHeight(const Node* node) const {
int height = 0;
if (node != NULL) {
height = 1 + ::std::max(GetHeight(node->GetLeft()),
......@@ -555,21 +459,21 @@ GetHeight(const NodePtr& node) const {
return height;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
IsBalanced() const {
return IsBalanced(entry_->GetLeft());
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
IsBalanced(const NodePtr& node) const {
template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
IsBalanced(const Node* node) const {
// Overweight violation
bool has_violation = node->GetWeight() > 1;
if (!has_violation && !IsLeaf(node)) {
NodePtr left = node->GetLeft();
NodePtr right = node->GetRight();
const Node* left = node->GetLeft();
const Node* right = node->GetRight();
// Red-red violation
has_violation = node->GetWeight() == 0 &&
......@@ -584,27 +488,27 @@ IsBalanced(const NodePtr& node) const {
return !has_violation;
}
template<typename Key, typename Value, typename Compare, typename NodePool>
void ChromaticTree<Key, Value, Compare, NodePool>::
template<typename Key, typename Value, typename Compare, typename ValuePool>
void ChromaticTree<Key, Value, Compare, ValuePool>::
RetireHazardousNode(HazardNodePtr& node, UniqueLock& node_lock) {
node->Retire();
node_lock.Unlock();
NodePtr node_to_delete = node.ReleaseHazard();
Node* node_to_delete = node.ReleaseHazard();
node_hazard_manager_.EnqueuePointerForDeletion(node_to_delete);
}
template<typename Key, typename Value, typename Compare, typename NodePool>
void ChromaticTree<Key, Value, Compare, NodePool>::
FreeNode(NodePtr node) {
template<typename Key, typename Value, typename Compare, typename ValuePool>
void ChromaticTree<Key, Value, Compare, ValuePool>::
FreeNode(Node* node) {
#ifdef EMBB_DEBUG
node->GetLeft() = reinterpret_cast<NodePtr>(INVALID_POINTER);
node->GetRight() = reinterpret_cast<NodePtr>(INVALID_POINTER);
node->GetLeft() = reinterpret_cast<Node*>(INVALID_POINTER);
node->GetRight() = reinterpret_cast<Node*>(INVALID_POINTER);
#endif
node_pool_.Free(node);
}
template<typename Key, typename Value, typename Compare, typename NodePool>
bool ChromaticTree<Key, Value, Compare, NodePool>::
template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
CleanUp(const Key& key) {
HazardNodePtr grandgrandparent(node_hazard_manager_.GetGuardedPointer(0));
HazardNodePtr grandparent (node_hazard_manager_.GetGuardedPointer(1));
......@@ -615,9 +519,9 @@ CleanUp(const Key& key) {
while (!reached_leaf) {
bool found_violation = false;
grandgrandparent.ProtectHazard(entry_);
grandparent.ProtectHazard(entry_);
parent.ProtectHazard(entry_);
grandgrandparent.ProtectSafe(entry_);
grandparent.ProtectSafe(entry_);
parent.ProtectSafe(entry_);
leaf.ProtectHazard(entry_->GetLeft());
if (parent->IsRetired() || !leaf.IsActive()) continue;
......@@ -629,7 +533,7 @@ CleanUp(const Key& key) {
leaf.ProtectHazard((IsSentinel(leaf) || compare_(key, leaf->GetKey())) ?
leaf->GetLeft() : leaf->GetRight());
if (parent->IsRetired() || !leaf.IsActive()) break;
VERIFY_ADDRESS(static_cast<NodePtr>(leaf));
VERIFY_ADDRESS(static_cast<Node*>(leaf));
found_violation = (leaf->GetWeight() > 1) ||
(leaf->GetWeight() == 0 && parent->GetWeight() == 0);
......@@ -659,10 +563,10 @@ CleanUp(const Key& key) {
HazardNodePtr node(node_hazard_manager_.GetGuardedPointer(h_num)); \
node.ProtectHazard(parent->method()); \
if (parent->IsRetired() || !node.IsActive()) return EMBB_BUSY; \
VERIFY_ADDRESS(static_cast<NodePtr>(node))
VERIFY_ADDRESS(static_cast<Node*>(node))
template<typename Key, typename Value, typename Compare, typename NodePool>
embb_errors_t ChromaticTree<Key, Value, Compare, NodePool>::
template<typename Key, typename Value, typename Compare, typename ValuePool>
embb_errors_t ChromaticTree<Key, Value, Compare, ValuePool>::
Rebalance(HazardNodePtr& u, HazardNodePtr& ux, HazardNodePtr& uxx,
HazardNodePtr& uxxx) {
// Protect node 'u'
......@@ -730,8 +634,8 @@ Rebalance(HazardNodePtr& u, HazardNodePtr& ux, HazardNodePtr& uxx,
}
}
template<typename Key, typename Value, typename Compare, typename NodePool>
embb_errors_t ChromaticTree<Key, Value, Compare, NodePool>::
template<typename Key, typename Value, typename Compare, typename ValuePool>
embb_errors_t ChromaticTree<Key, Value, Compare, ValuePool>::
OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock,
HazardNodePtr& ux, UniqueLock& ux_lock,
HazardNodePtr& uxx, UniqueLock& uxx_lock,
......@@ -876,8 +780,8 @@ OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock,
}
}
template<typename Key, typename Value, typename Compare, typename NodePool>
embb_errors_t ChromaticTree<Key, Value, Compare, NodePool>::
template<typename Key, typename Value, typename Compare, typename ValuePool>
embb_errors_t ChromaticTree<Key, Value, Compare, ValuePool>::
OverweightRight(HazardNodePtr& u, UniqueLock& u_lock,
HazardNodePtr& ux, UniqueLock& ux_lock,
HazardNodePtr& uxx, UniqueLock& uxx_lock,
......
......@@ -37,15 +37,15 @@ embb_errors_t BLK(
HazardNodePtr& ux, UniqueLock& ux_lock,
HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock) {
NodePtr nxl = node_pool_.Allocate(
Node* nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxr = node_pool_.Allocate(
Node* nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nx = node_pool_.Allocate(
Node* nx = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
IsSentinel(u) ? 1 : ux->GetWeight() - 1,
nxl, nxr);
......@@ -59,9 +59,7 @@ embb_errors_t BLK(
return EMBB_NOMEM;
}
NodePtr expected = ux;
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
bool rotation_succeeded = u->ReplaceChild(ux, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY;
......@@ -78,15 +76,15 @@ embb_errors_t PUSH_L(
HazardNodePtr& ux, UniqueLock& ux_lock,
HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock) {
NodePtr nxl = node_pool_.Allocate(
Node* nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxr = node_pool_.Allocate(
Node* nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
0,
uxr->GetLeft(), uxr->GetRight());
NodePtr nx = node_pool_.Allocate(
Node* nx = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
IsSentinel(u) ? 1 : ux->GetWeight() + 1,
nxl, nxr);
......@@ -100,9 +98,7 @@ embb_errors_t PUSH_L(
return EMBB_NOMEM;
}
NodePtr expected = ux;
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
bool rotation_succeeded = u->ReplaceChild(ux, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY;
......@@ -119,15 +115,15 @@ embb_errors_t PUSH_R(
HazardNodePtr& ux, UniqueLock& ux_lock,
HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock) {
NodePtr nxr = node_pool_.Allocate(
Node* nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nxl = node_pool_.Allocate(
Node* nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
0,
uxl->GetLeft(), uxl->GetRight());
NodePtr nx = node_pool_.Allocate(
Node* nx = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
IsSentinel(u) ? 1 : ux->GetWeight() + 1,
nxl, nxr);
......@@ -141,9 +137,7 @@ embb_errors_t PUSH_R(
return EMBB_NOMEM;
}
NodePtr expected = ux;
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
bool rotation_succeeded = u->ReplaceChild(ux, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY;
......@@ -159,11 +153,11 @@ embb_errors_t RB1_L(
HazardNodePtr& u, UniqueLock& u_lock,
HazardNodePtr& ux, UniqueLock& ux_lock,
HazardNodePtr& uxl, UniqueLock& uxl_lock) {
NodePtr nxr = node_pool_.Allocate(
Node* nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
0,
uxl->GetRight(), ux->GetRight());
NodePtr nx = node_pool_.Allocate(
Node* nx = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
ux->GetWeight(),
uxl->GetLeft(), nxr);
......@@ -175,9 +169,7 @@ embb_errors_t RB1_L(
return EMBB_NOMEM;
}
NodePtr expected = ux;
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
bool rotation_succeeded = u->ReplaceChild(ux, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY;
......@@ -192,11 +184,11 @@ embb_errors_t RB1_R(
HazardNodePtr& u, UniqueLock& u_lock,
HazardNodePtr& ux, UniqueLock& ux_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock) {
NodePtr nxl = node_pool_.Allocate(
Node* nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
0,
ux->GetLeft(), uxr->GetLeft());
NodePtr nx = node_pool_.Allocate(
Node* nx = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
ux->GetWeight(),
nxl, uxr->GetRight());
......@@ -208,9 +200,7 @@ embb_errors_t RB1_R(
return EMBB_NOMEM;
}
NodePtr expected = ux;
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
bool rotation_succeeded = u->ReplaceChild(ux, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY;
......@@ -226,15 +216,15 @@ embb_errors_t RB2_L(
HazardNodePtr& ux, UniqueLock& ux_lock,
HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxlr, UniqueLock& uxlr_lock) {
NodePtr nxl = node_pool_.Allocate(
Node* nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
0,
uxl->GetLeft(), uxlr->GetLeft());
NodePtr nxr = node_pool_.Allocate(
Node* nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
0,
uxlr->GetRight(), ux->GetRight());
NodePtr nx = node_pool_.Allocate(
Node* nx = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(),
ux->GetWeight(),
nxl, nxr);
......@@ -248,9 +238,7 @@ embb_errors_t RB2_L(
return EMBB_NOMEM;
}
NodePtr expected = ux;
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
bool rotation_succeeded = u->ReplaceChild(ux, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY;
......@@ -267,15 +255,15 @@ embb_errors_t RB2_R(
HazardNodePtr& ux, UniqueLock& ux_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxrl, UniqueLock& uxrl_lock) {
NodePtr nxr = node_pool_.Allocate(
Node* nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
0,
uxrl->GetRight(), uxr->GetRight());
NodePtr nxl = node_pool_.Allocate(
Node* nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
0,
ux->GetLeft(), uxrl->GetLeft());
NodePtr nx = node_pool_.Allocate(
Node* nx = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(),
ux->GetWeight(),
nxl, nxr);
......@@ -289,9 +277,7 @@ embb_errors_t RB2_R(
return EMBB_NOMEM;
}
NodePtr expected = ux;
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
bool rotation_succeeded = u->ReplaceChild(ux, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY;
......@@ -309,19 +295,19 @@ embb_errors_t W1_L(
HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxrl, UniqueLock& uxrl_lock) {
NodePtr nxll = node_pool_.Allocate(
Node* nxll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxlr = node_pool_.Allocate(
Node* nxlr = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(),
uxrl->GetWeight() - 1,
uxrl->GetLeft(), uxrl->GetRight());
NodePtr nxl = node_pool_.Allocate(
Node* nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxll, nxlr);
NodePtr nx = node_pool_.Allocate(
Node* nx = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
ux->GetWeight(),
nxl, uxr->GetRight());
......@@ -337,9 +323,7 @@ embb_errors_t W1_L(
return EMBB_NOMEM;
}
NodePtr expected = ux;
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
bool rotation_succeeded = u->ReplaceChild(ux, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY;
......@@ -358,19 +342,19 @@ embb_errors_t W1_R(
HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxlr, UniqueLock& uxlr_lock) {
NodePtr nxrr = node_pool_.Allocate(
Node* nxrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nxrl = node_pool_.Allocate(
Node* nxrl = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(),
uxlr->GetWeight() - 1,
uxlr->GetLeft(), uxlr->GetRight());
NodePtr nxr = node_pool_.Allocate(
Node* nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxrl, nxrr);
NodePtr nx = node_pool_.Allocate(
Node* nx = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
ux->GetWeight(),
uxl->GetLeft(), nxr);
......@@ -386,9 +370,7 @@ embb_errors_t W1_R(
return EMBB_NOMEM;
}
NodePtr expected = ux;
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
bool rotation_succeeded = u->ReplaceChild(ux, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY;
......@@ -407,19 +389,19 @@ embb_errors_t W2_L(
HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxrl, UniqueLock& uxrl_lock) {
NodePtr nxll = node_pool_.Allocate(
Node* nxll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxlr = node_pool_.Allocate(
Node* nxlr = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(),
0,
uxrl->GetLeft(), uxrl->GetRight());
NodePtr nxl = node_pool_.Allocate(
Node* nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxll, nxlr);
NodePtr nx = node_pool_.Allocate(
Node* nx = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
ux->GetWeight(),
nxl, uxr->GetRight());
......@@ -435,9 +417,7 @@ embb_errors_t W2_L(
return EMBB_NOMEM;
}
NodePtr expected = ux;
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
bool rotation_succeeded = u->ReplaceChild(ux, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY;
......@@ -456,19 +436,19 @@ embb_errors_t W2_R(
HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxlr, UniqueLock& uxlr_lock) {
NodePtr nxrr = node_pool_.Allocate(
Node* nxrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nxrl = node_pool_.Allocate(
Node* nxrl = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(),
0,
uxlr->GetLeft(), uxlr->GetRight());
NodePtr nxr = node_pool_.Allocate(
Node* nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxrl, nxrr);
NodePtr nx = node_pool_.Allocate(
Node* nx = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
ux->GetWeight(),
uxl->GetLeft(), nxr);
......@@ -484,9 +464,7 @@ embb_errors_t W2_R(
return EMBB_NOMEM;
}
NodePtr expected = ux;
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
bool rotation_succeeded = u->ReplaceChild(ux, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY;
......@@ -506,23 +484,23 @@ embb_errors_t W3_L(
HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxrl, UniqueLock& uxrl_lock,
HazardNodePtr& uxrll, UniqueLock& uxrll_lock) {
NodePtr nxlll = node_pool_.Allocate(
Node* nxlll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxll = node_pool_.Allocate(
Node* nxll = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxlll, uxrll->GetLeft());
NodePtr nxlr = node_pool_.Allocate(
Node* nxlr = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(),
1,
uxrll->GetRight(), uxrl->GetRight());
NodePtr nxl = node_pool_.Allocate(
Node* nxl = node_pool_.Allocate(
uxrll->GetKey(), uxrll->GetValue(),
0,
nxll, nxlr);
NodePtr nx = node_pool_.Allocate(
Node* nx = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
ux->GetWeight(),
nxl, uxr->GetRight());
......@@ -540,9 +518,7 @@ embb_errors_t W3_L(
return EMBB_NOMEM;
}
NodePtr expected = ux;
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
bool rotation_succeeded = u->ReplaceChild(ux, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY;
......@@ -563,23 +539,23 @@ embb_errors_t W3_R(
HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxlr, UniqueLock& uxlr_lock,
HazardNodePtr& uxlrr, UniqueLock& uxlrr_lock) {
NodePtr nxrrr = node_pool_.Allocate(
Node* nxrrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nxrr = node_pool_.Allocate(
Node* nxrr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
uxlrr->GetRight(), nxrrr);
NodePtr nxrl = node_pool_.Allocate(
Node* nxrl = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(),
1,
uxlr->GetLeft(), uxlrr->GetLeft());
NodePtr nxr = node_pool_.Allocate(
Node* nxr = node_pool_.Allocate(
uxlrr->GetKey(), uxlrr->GetValue(),
0,
nxrl, nxrr);
NodePtr nx = node_pool_.Allocate(
Node* nx = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
ux->GetWeight(),
uxl->GetLeft(), nxr);
......@@ -597,9 +573,7 @@ embb_errors_t W3_R(
return EMBB_NOMEM;
}
NodePtr expected = ux;
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
bool rotation_succeeded = u->ReplaceChild(ux, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY;
......@@ -620,23 +594,23 @@ embb_errors_t W4_L(
HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxrl, UniqueLock& uxrl_lock,
HazardNodePtr& uxrlr, UniqueLock& uxrlr_lock) {
NodePtr nxll = node_pool_.Allocate(
Node* nxll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxrl = node_pool_.Allocate(
Node* nxrl = node_pool_.Allocate(
uxrlr->GetKey(), uxrlr->GetValue(),
1,
uxrlr->GetLeft(), uxrlr->GetRight());
NodePtr nxl = node_pool_.Allocate(
Node* nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxll, uxrl->GetLeft());
NodePtr nxr = node_pool_.Allocate(
Node* nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
0,
nxrl, uxr->GetRight());
NodePtr nx = node_pool_.Allocate(
Node* nx = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(),
ux->GetWeight(),
nxl, nxr);
......@@ -654,9 +628,7 @@ embb_errors_t W4_L(
return EMBB_NOMEM;
}
NodePtr expected = ux;
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
bool rotation_succeeded = u->ReplaceChild(ux, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY;
......@@ -677,23 +649,23 @@ embb_errors_t W4_R(
HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxlr, UniqueLock& uxlr_lock,
HazardNodePtr& uxlrl, UniqueLock& uxlrl_lock) {
NodePtr nxrr = node_pool_.Allocate(
Node* nxrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nxlr = node_pool_.Allocate(
Node* nxlr = node_pool_.Allocate(
uxlrl->GetKey(), uxlrl->GetValue(),
1,
uxlrl->GetLeft(), uxlrl->GetRight());
NodePtr nxr = node_pool_.Allocate(
Node* nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
uxlr->GetRight(), nxrr);
NodePtr nxl = node_pool_.Allocate(
Node* nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
0,
uxl->GetLeft(), nxlr);
NodePtr nx = node_pool_.Allocate(
Node* nx = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(),
ux->GetWeight(),
nxl, nxr);
......@@ -711,9 +683,7 @@ embb_errors_t W4_R(
return EMBB_NOMEM;
}
NodePtr expected = ux;
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
bool rotation_succeeded = u->ReplaceChild(ux, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY;
......@@ -733,19 +703,19 @@ embb_errors_t W5_L(
HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxrr, UniqueLock& uxrr_lock) {
NodePtr nxll = node_pool_.Allocate(
Node* nxll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxl = node_pool_.Allocate(
Node* nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxll, uxr->GetLeft());
NodePtr nxr = node_pool_.Allocate(
Node* nxr = node_pool_.Allocate(
uxrr->GetKey(), uxrr->GetValue(),
1,
uxrr->GetLeft(), uxrr->GetRight());
NodePtr nx = node_pool_.Allocate(
Node* nx = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
ux->GetWeight(),
nxl, nxr);
......@@ -761,9 +731,7 @@ embb_errors_t W5_L(
return EMBB_NOMEM;
}
NodePtr expected = ux;
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
bool rotation_succeeded = u->ReplaceChild(ux, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY;
......@@ -782,19 +750,19 @@ embb_errors_t W5_R(
HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxll, UniqueLock& uxll_lock) {
NodePtr nxrr = node_pool_.Allocate(
Node* nxrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nxr = node_pool_.Allocate(
Node* nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
uxl->GetRight(), nxrr);
NodePtr nxl = node_pool_.Allocate(
Node* nxl = node_pool_.Allocate(
uxll->GetKey(), uxll->GetValue(),
1,
uxll->GetLeft(), uxll->GetRight());
NodePtr nx = node_pool_.Allocate(
Node* nx = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
ux->GetWeight(),
nxl, nxr);
......@@ -810,9 +778,7 @@ embb_errors_t W5_R(
return EMBB_NOMEM;
}
NodePtr expected = ux;
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
bool rotation_succeeded = u->ReplaceChild(ux, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY;
......@@ -831,19 +797,19 @@ embb_errors_t W6_L(
HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxrl, UniqueLock& uxrl_lock) {
NodePtr nxll = node_pool_.Allocate(
Node* nxll = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxl = node_pool_.Allocate(
Node* nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
nxll, uxrl->GetLeft());
NodePtr nxr = node_pool_.Allocate(
Node* nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
1,
uxrl->GetRight(), uxr->GetRight());
NodePtr nx = node_pool_.Allocate(
Node* nx = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(),
ux->GetWeight(),
nxl, nxr);
......@@ -859,9 +825,7 @@ embb_errors_t W6_L(
return EMBB_NOMEM;
}
NodePtr expected = ux;
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
bool rotation_succeeded = u->ReplaceChild(ux, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY;
......@@ -880,19 +844,19 @@ embb_errors_t W6_R(
HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock,
HazardNodePtr& uxlr, UniqueLock& uxlr_lock) {
NodePtr nxrr = node_pool_.Allocate(
Node* nxrr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nxr = node_pool_.Allocate(
Node* nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
1,
uxlr->GetRight(), nxrr);
NodePtr nxl = node_pool_.Allocate(
Node* nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
1,
uxl->GetLeft(), uxlr->GetLeft());
NodePtr nx = node_pool_.Allocate(
Node* nx = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(),
ux->GetWeight(),
nxl, nxr);
......@@ -908,9 +872,7 @@ embb_errors_t W6_R(
return EMBB_NOMEM;
}
NodePtr expected = ux;
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
bool rotation_succeeded = u->ReplaceChild(ux, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY;
......@@ -928,15 +890,15 @@ embb_errors_t W7(
HazardNodePtr& ux, UniqueLock& ux_lock,
HazardNodePtr& uxl, UniqueLock& uxl_lock,
HazardNodePtr& uxr, UniqueLock& uxr_lock) {
NodePtr nxl = node_pool_.Allocate(
Node* nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(),
uxl->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight());
NodePtr nxr = node_pool_.Allocate(
Node* nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(),
uxr->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight());
NodePtr nx = node_pool_.Allocate(
Node* nx = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(),
IsSentinel(u) ? 1 : ux->GetWeight() + 1,
nxl, nxr);
......@@ -950,9 +912,7 @@ embb_errors_t W7(
return EMBB_NOMEM;
}
NodePtr expected = ux;
bool rotation_succeeded = GetPointerToChild(u, ux)
.CompareAndSwap(expected, nx);
bool rotation_succeeded = u->ReplaceChild(ux, nx);
assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail
if (!rotation_succeeded) return EMBB_BUSY;
......
......@@ -50,8 +50,8 @@ namespace internal {
template<typename Key, typename Value>
class ChromaticTreeNode {
public:
typedef ChromaticTreeNode<Key, Value>* ChildPointer;
typedef embb::base::Atomic<ChildPointer> AtomicChildPointer;
typedef ChromaticTreeNode<Key, Value> Node;
typedef embb::base::Atomic<Node*> AtomicNodePtr;
/**
* Creates a node with given parameters.
......@@ -62,8 +62,8 @@ class ChromaticTreeNode {
* \param[IN] left Pointer to the left child node
* \param[IN] right Pointer to the right child node
*/
ChromaticTreeNode(const Key& key, const Value& value, const int weight,
const ChildPointer& left, const ChildPointer& right);
ChromaticTreeNode(const Key& key, const Value& value, int weight,
Node* left, Node* right);
/**
* Creates a node given only a key-value pair. Node will have no child nodes
......@@ -73,7 +73,7 @@ class ChromaticTreeNode {
* \param[IN] value Value 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.
......@@ -101,14 +101,30 @@ class ChromaticTreeNode {
*
* \return Reference to the left child pointer
*/
AtomicChildPointer& GetLeft();
AtomicNodePtr& GetLeft();
Node* GetLeft() const;
/**
* Accessor for 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
......@@ -136,183 +152,16 @@ class ChromaticTreeNode {
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 */
const Key key_; /**< Stored key */
const Value value_; /**< Stored value */
const int weight_; /**< Weight of the node */
AtomicNodePtr left_; /**< Pointer to left child node */
AtomicNodePtr right_; /**< Pointer to right child node */
embb::base::Atomic<bool> retired_; /**< Retired (marked for deletion) flag */
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 test {
......@@ -330,20 +179,19 @@ class TreeTest;
* Implements a balanced BST with support for \c Get, \c Insert and \c Delete
* operations.
*
* \tparam Key Key type
* \tparam Value Value type
* \tparam Compare Custom comparator type for the keys. An object of the
* type \c Compare must must be a functor taking two
* arguments \c rhs and \c lhs of type \c Key and
* returning \c true if and only if <tt>(rhs < lhs)</tt> holds
* \tparam NodePool The object pool type used for allocation/deallocation
* of tree nodes.
* \tparam Key Key type
* \tparam Value Value type
* \tparam Compare Custom comparator type for the keys. An object of the
* type \c Compare must must be a functor taking two
* arguments \c rhs and \c lhs of type \c Key and
* returning \c true if and only if <tt>(rhs < lhs)</tt> holds
* \tparam ValuePool Type of the value pool to be used inside object pools for
* tree nodes and operation objects.
*/
template<typename Key,
typename Value,
typename Compare = ::std::less<Key>,
typename NodePool = ObjectPool<internal::ChromaticTreeNode<Key, Value>,
LockFreeTreeValuePool<bool, false> >
typename ValuePool = LockFreeTreeValuePool<bool, false>
>
class ChromaticTree {
public:
......@@ -465,7 +313,7 @@ class ChromaticTree {
*
* \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.
......@@ -475,26 +323,16 @@ class ChromaticTree {
bool IsEmpty() const;
private:
/**
* Typedef for a node of the tree.
*/
/** Typedef for a node of the tree. */
typedef internal::ChromaticTreeNode<Key, Value> Node;
/**
* Typedef for a pointer to a node of the tree.
*/
typedef internal::ChromaticTreeNode<Key, Value>* NodePtr;
/**
* Typedef for an atomic pointer to a node of the tree.
*/
typedef embb::base::Atomic<NodePtr> AtomicNodePtr;
/**
* Typedef for an pointer to a node protected by a Hazard Pointer.
*/
/** Typedef for an atomic 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::UniqueHazardPointer<Node> HazardNodePtr;
/**
* Typedef for the UniqueLock class.
*/
/** Typedef for the UniqueLock class. */
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 {
*
* \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.
......@@ -537,7 +375,7 @@ class ChromaticTree {
*
* \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.
......@@ -548,22 +386,8 @@ class ChromaticTree {
* \return \c true if \c child is a child node of \c parent, \c false
* otherwise
*/
bool HasChild(const NodePtr& parent, const NodePtr& 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;
bool HasChild(const Node* parent, const Node* child) const;
/**
* Destroys all the nodes of a subtree rooted at the given node, including the
* node itself.
......@@ -572,7 +396,7 @@ class ChromaticTree {
*
* \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.
......@@ -584,7 +408,7 @@ class ChromaticTree {
* \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;
int GetHeight(const Node* node) const;
/**
* Check whether the tree is currently in a balanced state (if it is a valid
......@@ -601,7 +425,7 @@ class ChromaticTree {
*
* \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.
......@@ -616,7 +440,7 @@ class ChromaticTree {
*
* \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
......@@ -654,23 +478,21 @@ class ChromaticTree {
// directly inside the class definition.
# include <embb/containers/internal/lock_free_chromatic_tree-rebalance.h>
/** Callback functor for the hazard pointer that frees retired nodes */
embb::base::Function<void, NodePtr> free_node_callback_;
/** Hazard pointer instance for protection of node pointers */
embb::containers::internal::HazardPointer<NodePtr> node_hazard_manager_;
internal::HazardPointer<Node*> 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 */
const Compare compare_; /**< Comparator object for the keys */
size_t capacity_; /**< User-requested capacity of the tree */
NodePool node_pool_; /**< Comparator object for the keys */
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 */
/**
* Friending the test class for white-box testing
*/
friend class test::TreeTest<ChromaticTree<Key, Value, Compare, NodePool> >;
friend class test::TreeTest<ChromaticTree>;
};
} // 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