mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2025-11-29 17:38:24 +08:00
1248 lines
44 KiB
C++
1248 lines
44 KiB
C++
#ifndef ACE_RB_TREE_CPP
|
|
#define ACE_RB_TREE_CPP
|
|
|
|
#include "ace/Global_Macros.h"
|
|
#include "ace/RB_Tree.h"
|
|
#include "ace/SString.h"
|
|
|
|
#if !defined (ACE_LACKS_PRAGMA_ONCE)
|
|
# pragma once
|
|
#endif /* ACE_LACKS_PRAGMA_ONCE */
|
|
|
|
#if !defined (__ACE_INLINE__)
|
|
#include "ace/RB_Tree.inl"
|
|
#endif /* __ACE_INLINE__ */
|
|
|
|
#include "ace/Log_Category.h"
|
|
|
|
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
|
|
|
|
// Constructor.
|
|
|
|
template <class EXT_ID, class INT_ID>
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID>::ACE_RB_Tree_Node (const EXT_ID &k, const INT_ID &t)
|
|
: k_ (k),
|
|
t_ (t),
|
|
color_ (RED),
|
|
parent_ (0),
|
|
left_ (0),
|
|
right_ (0)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree_Node<EXT_ID, INT_ID>::ACE_RB_Tree_Node (const EXT_ID &k, const INT_ID &t)");
|
|
}
|
|
|
|
|
|
// Destructor.
|
|
|
|
template <class EXT_ID, class INT_ID>
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID>::~ACE_RB_Tree_Node (void)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree_Node<EXT_ID, INT_ID>::~ACE_RB_Tree_Node");
|
|
}
|
|
|
|
// Constructor.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree (ACE_Allocator *alloc)
|
|
: root_ (0),
|
|
current_size_ (0)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree (ACE_Allocator *alloc)");
|
|
allocator_ = alloc;
|
|
if (this->open (alloc) == -1)
|
|
ACELIB_ERROR ((LM_ERROR,
|
|
ACE_TEXT ("ACE_RB_Tree::ACE_RB_Tree\n")));
|
|
}
|
|
|
|
// Copy constructor.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &rbt)
|
|
: root_ (0),
|
|
current_size_ (0)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &rbt)");
|
|
ACE_WRITE_GUARD (ACE_LOCK, ace_mon, this->lock_);
|
|
allocator_ = rbt.allocator_;
|
|
|
|
// Make a deep copy of the passed tree.
|
|
ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> iter(rbt);
|
|
|
|
for (iter.first ();
|
|
|
|
iter.is_done () == 0; iter.next ())
|
|
insert_i (*(iter.key ()),
|
|
*(iter.item ()));
|
|
}
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree (
|
|
void *location,
|
|
ACE_Allocator *alloc
|
|
)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree (void *, ACE_Allocator *)");
|
|
|
|
if (location != this)
|
|
{
|
|
this->root_ = 0;
|
|
this->current_size_ = 0;
|
|
}
|
|
|
|
this->allocator_ = alloc;
|
|
}
|
|
// Destructor.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::~ACE_RB_Tree ()
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::~ACE_RB_Tree");
|
|
|
|
// Use the locked public method, to be totally safe, as the class
|
|
// can be used with an allocator and placement new.
|
|
this->close ();
|
|
}
|
|
|
|
// Assignment operator.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> void
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator = (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &rbt)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator =");
|
|
ACE_WRITE_GUARD (ACE_LOCK, ace_mon, this->lock_);
|
|
|
|
if (this != &rbt)
|
|
{
|
|
// Clear out the existing tree.
|
|
close_i ();
|
|
|
|
// Make a deep copy of the passed tree.
|
|
ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> iter(rbt);
|
|
|
|
for (iter.first ();
|
|
iter.is_done () == 0;
|
|
iter.next ())
|
|
insert_i (*(iter.key ()),
|
|
*(iter.item ()));
|
|
|
|
// Use the same allocator as the rhs.
|
|
allocator_ = rbt.allocator_;
|
|
}
|
|
}
|
|
// Less than comparison function for keys, default functor
|
|
// implementation returns 1 if k1 < k2, 0 otherwise.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> int
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::lessthan (const EXT_ID &k1, const EXT_ID &k2)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::lessthan");
|
|
return this->compare_keys_ (k1, k2);
|
|
}
|
|
|
|
// Method for right rotation of the tree about a given node.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> void
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_rotate_right (ACE_RB_Tree_Node<EXT_ID, INT_ID> *x)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_rotate_right");
|
|
|
|
if (!x)
|
|
ACELIB_ERROR ((LM_ERROR,
|
|
ACE_TEXT ("%p\n"),
|
|
ACE_TEXT ("\nerror: x is a null pointer in ")
|
|
ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::RB_rotate_right\n")));
|
|
else if (! (x->left()))
|
|
ACELIB_ERROR ((LM_ERROR,
|
|
ACE_TEXT ("%p\n"),
|
|
ACE_TEXT ("\nerror: x->left () is a null pointer in ")
|
|
ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::RB_rotate_right\n")));
|
|
else
|
|
{
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> * y;
|
|
y = x->left ();
|
|
x->left (y->right ());
|
|
if (y->right ())
|
|
y->right ()->parent (x);
|
|
y->parent (x->parent ());
|
|
if (x->parent ())
|
|
{
|
|
if (x == x->parent ()->right ())
|
|
x->parent ()->right (y);
|
|
else
|
|
x->parent ()->left (y);
|
|
}
|
|
else
|
|
root_ = y;
|
|
y->right (x);
|
|
x->parent (y);
|
|
}
|
|
}
|
|
|
|
// Method for left rotation of the tree about a given node.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> void
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_rotate_left (ACE_RB_Tree_Node<EXT_ID, INT_ID> * x)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_rotate_left");
|
|
|
|
if (! x)
|
|
ACELIB_ERROR ((LM_ERROR,
|
|
ACE_TEXT ("%p\n"),
|
|
ACE_TEXT ("\nerror: x is a null pointer in ")
|
|
ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::RB_rotate_left\n")));
|
|
else if (! (x->right()))
|
|
ACELIB_ERROR ((LM_ERROR,
|
|
ACE_TEXT ("%p\n"),
|
|
ACE_TEXT ("\nerror: x->right () is a null pointer ")
|
|
ACE_TEXT ("in ACE_RB_Tree<EXT_ID, INT_ID>::RB_rotate_left\n")));
|
|
else
|
|
{
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> * y;
|
|
y = x->right ();
|
|
x->right (y->left ());
|
|
if (y->left ())
|
|
y->left ()->parent (x);
|
|
y->parent (x->parent ());
|
|
if (x->parent ())
|
|
{
|
|
if (x == x->parent ()->left ())
|
|
x->parent ()->left (y);
|
|
else
|
|
x->parent ()->right (y);
|
|
}
|
|
else
|
|
root_ = y;
|
|
y->left (x);
|
|
x->parent (y);
|
|
}
|
|
}
|
|
|
|
// Method for restoring Red-Black properties after a specific deletion case.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> void
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::
|
|
RB_delete_fixup (ACE_RB_Tree_Node<EXT_ID, INT_ID> *x,
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> *parent)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_delete_fixup");
|
|
|
|
while (x != this->root_
|
|
&& (!x
|
|
|| x->color () == ACE_RB_Tree_Node_Base::BLACK))
|
|
{
|
|
if (x == parent->left ())
|
|
{
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> *w = parent->right ();
|
|
if (w && w->color () == ACE_RB_Tree_Node_Base::RED)
|
|
{
|
|
w->color (ACE_RB_Tree_Node_Base::BLACK);
|
|
parent->color (ACE_RB_Tree_Node_Base::RED);
|
|
RB_rotate_left (parent);
|
|
w = parent->right ();
|
|
}
|
|
// CLR pp. 263 says that nil nodes are implicitly colored BLACK
|
|
if (w
|
|
&& (!w->left ()
|
|
|| w->left ()->color () == ACE_RB_Tree_Node_Base::BLACK)
|
|
&& (!w->right ()
|
|
|| w->right ()->color () == ACE_RB_Tree_Node_Base::BLACK))
|
|
{
|
|
w->color (ACE_RB_Tree_Node_Base::RED);
|
|
x = parent;
|
|
parent = x->parent ();
|
|
}
|
|
else
|
|
{
|
|
// CLR pp. 263 says that nil nodes are implicitly colored BLACK
|
|
if (w
|
|
&& (!w->right ()
|
|
|| w->right ()->color () == ACE_RB_Tree_Node_Base::BLACK))
|
|
{
|
|
if (w->left ())
|
|
w->left ()->color (ACE_RB_Tree_Node_Base::BLACK);
|
|
w->color (ACE_RB_Tree_Node_Base::RED);
|
|
RB_rotate_right (w);
|
|
w = parent->right ();
|
|
}
|
|
if (w)
|
|
{
|
|
w->color (parent->color ());
|
|
if (w->right ())
|
|
w->right ()->color (ACE_RB_Tree_Node_Base::BLACK);
|
|
}
|
|
parent->color (ACE_RB_Tree_Node_Base::BLACK);
|
|
RB_rotate_left (parent);
|
|
x = root_;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> *w = parent->left ();
|
|
if (w && w->color () == ACE_RB_Tree_Node_Base::RED)
|
|
{
|
|
w->color (ACE_RB_Tree_Node_Base::BLACK);
|
|
parent->color (ACE_RB_Tree_Node_Base::RED);
|
|
RB_rotate_right (parent);
|
|
w = parent->left ();
|
|
}
|
|
// CLR pp. 263 says that nil nodes are implicitly colored BLACK
|
|
if (w
|
|
&& (!w->left ()
|
|
|| w->left ()->color () == ACE_RB_Tree_Node_Base::BLACK)
|
|
&& (!w->right ()
|
|
|| w->right ()->color () == ACE_RB_Tree_Node_Base::BLACK))
|
|
{
|
|
w->color (ACE_RB_Tree_Node_Base::RED);
|
|
x = parent;
|
|
parent = x->parent ();
|
|
}
|
|
else
|
|
{
|
|
// CLR pp. 263 says that nil nodes are implicitly colored BLACK
|
|
if (w
|
|
&& (!w->left ()
|
|
|| w->left ()->color () == ACE_RB_Tree_Node_Base::BLACK))
|
|
{
|
|
w->color (ACE_RB_Tree_Node_Base::RED);
|
|
if (w->right ())
|
|
w->right ()->color (ACE_RB_Tree_Node_Base::BLACK);
|
|
RB_rotate_left (w);
|
|
w = parent->left ();
|
|
}
|
|
if (w)
|
|
{
|
|
w->color (parent->color ());
|
|
if (w->left ())
|
|
w->left ()->color (ACE_RB_Tree_Node_Base::BLACK);
|
|
}
|
|
parent->color (ACE_RB_Tree_Node_Base::BLACK);
|
|
RB_rotate_right (parent);
|
|
x = root_;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (x)
|
|
x->color (ACE_RB_Tree_Node_Base::BLACK);
|
|
}
|
|
|
|
// Return a pointer to a matching node if there is one, a pointer to
|
|
// the node under which to insert the item if the tree is not empty
|
|
// and there is no such match, or 0 if the tree is empty.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> ACE_RB_Tree_Node<EXT_ID, INT_ID> *
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::find_node (const EXT_ID &k, ACE_RB_Tree_Base::RB_SearchResult &result)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::find_node");
|
|
|
|
// Start at the root.
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> *current = root_;
|
|
|
|
while (current)
|
|
{
|
|
// While there are more nodes to examine.
|
|
if (this->lessthan (current->key (), k))
|
|
{
|
|
// If the search key is greater than the current node's key.
|
|
if (current->right ())
|
|
// If the right subtree is not empty, search to the right.
|
|
current = current->right ();
|
|
else
|
|
{
|
|
// If the right subtree is empty, we're done searching,
|
|
// and are positioned to the left of the insertion point.
|
|
result = LEFT;
|
|
break;
|
|
}
|
|
}
|
|
else if (this->lessthan (k, current->key ()))
|
|
{
|
|
// Else if the search key is less than the current node's key.
|
|
if (current->left ())
|
|
// If the left subtree is not empty, search to the left.
|
|
current = current->left ();
|
|
else
|
|
{
|
|
// If the left subtree is empty, we're done searching,
|
|
// and are positioned to the right of the insertion point.
|
|
result = RIGHT;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// If the keys match exactly, we're done as well.
|
|
result = EXACT;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return current;
|
|
}
|
|
|
|
// Rebalance the tree after insertion of a node.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> void
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_rebalance (ACE_RB_Tree_Node<EXT_ID, INT_ID> * x)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_rebalance");
|
|
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> *y = 0;
|
|
|
|
while (x &&
|
|
x->parent ()
|
|
&& x->parent ()->color () == ACE_RB_Tree_Node_Base::RED)
|
|
{
|
|
if (! x->parent ()->parent ())
|
|
{
|
|
// If we got here, something is drastically wrong!
|
|
ACELIB_ERROR ((LM_ERROR,
|
|
ACE_TEXT ("%p\n"),
|
|
ACE_TEXT ("\nerror: parent's parent is null in ")
|
|
ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::RB_rebalance\n")));
|
|
return;
|
|
}
|
|
|
|
if (x->parent () == x->parent ()->parent ()->left ())
|
|
{
|
|
y = x->parent ()->parent ()->right ();
|
|
if (y && y->color () == ACE_RB_Tree_Node_Base::RED)
|
|
{
|
|
// Handle case 1 (see CLR book, pp. 269).
|
|
x->parent ()->color (ACE_RB_Tree_Node_Base::BLACK);
|
|
y->color (ACE_RB_Tree_Node_Base::BLACK);
|
|
x->parent ()->parent ()->color (ACE_RB_Tree_Node_Base::RED);
|
|
x = x->parent ()->parent ();
|
|
}
|
|
else
|
|
{
|
|
if (x == x->parent ()->right ())
|
|
{
|
|
// Transform case 2 into case 3 (see CLR book, pp. 269).
|
|
x = x->parent ();
|
|
RB_rotate_left (x);
|
|
}
|
|
|
|
// Handle case 3 (see CLR book, pp. 269).
|
|
x->parent ()->color (ACE_RB_Tree_Node_Base::BLACK);
|
|
x->parent ()->parent ()->color (ACE_RB_Tree_Node_Base::RED);
|
|
RB_rotate_right (x->parent ()->parent ());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
y = x->parent ()->parent ()->left ();
|
|
if (y && y->color () == ACE_RB_Tree_Node_Base::RED)
|
|
{
|
|
// Handle case 1 (see CLR book, pp. 269).
|
|
x->parent ()->color (ACE_RB_Tree_Node_Base::BLACK);
|
|
y->color (ACE_RB_Tree_Node_Base::BLACK);
|
|
x->parent ()->parent ()->color (ACE_RB_Tree_Node_Base::RED);
|
|
x = x->parent ()->parent ();
|
|
}
|
|
else
|
|
{
|
|
if (x == x->parent ()->left ())
|
|
{
|
|
// Transform case 2 into case 3 (see CLR book, pp. 269).
|
|
x = x->parent ();
|
|
RB_rotate_right (x);
|
|
}
|
|
|
|
// Handle case 3 (see CLR book, pp. 269).
|
|
x->parent ()->color (ACE_RB_Tree_Node_Base::BLACK);
|
|
x->parent ()->parent ()->color (ACE_RB_Tree_Node_Base::RED);
|
|
RB_rotate_left (x->parent ()->parent ());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Method to find the successor node of the given node in the tree.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> ACE_RB_Tree_Node<EXT_ID, INT_ID> *
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_tree_successor (ACE_RB_Tree_Node<EXT_ID, INT_ID> *x) const
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_tree_successor");
|
|
|
|
if (x == 0)
|
|
return 0;
|
|
|
|
if (x->right ())
|
|
return RB_tree_minimum (x->right ());
|
|
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> *y = x->parent ();
|
|
while ((y) && (x == y->right ()))
|
|
{
|
|
x = y;
|
|
y = y->parent ();
|
|
}
|
|
|
|
return y;
|
|
}
|
|
|
|
// Method to find the predecessor node of the given node in the tree.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> ACE_RB_Tree_Node<EXT_ID, INT_ID> *
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_tree_predecessor (ACE_RB_Tree_Node<EXT_ID, INT_ID> *x) const
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_tree_predecessor");
|
|
if (x == 0)
|
|
return 0;
|
|
|
|
if (x->left ())
|
|
return RB_tree_maximum (x->left ());
|
|
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> *y = x->parent ();
|
|
|
|
while ((y) && (x == y->left ()))
|
|
{
|
|
x = y;
|
|
y = y->parent ();
|
|
}
|
|
|
|
return y;
|
|
}
|
|
|
|
// Method to find the minimum node of the subtree rooted at the given node.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> ACE_RB_Tree_Node<EXT_ID, INT_ID> *
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_tree_minimum (ACE_RB_Tree_Node<EXT_ID, INT_ID> *x) const
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_tree_minimum");
|
|
|
|
while ((x) && (x->left ()))
|
|
x = x->left ();
|
|
|
|
return x;
|
|
}
|
|
|
|
// Method to find the maximum node of the subtree rooted at the given node.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> ACE_RB_Tree_Node<EXT_ID, INT_ID> *
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_tree_maximum (ACE_RB_Tree_Node<EXT_ID, INT_ID> *x) const
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_tree_maximum");
|
|
|
|
while ((x) && (x->right ()))
|
|
x = x->right ();
|
|
|
|
return x;
|
|
}
|
|
|
|
// Delete children (left and right) of the node. Must be called with
|
|
// lock held.
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
|
|
void ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::delete_children_i
|
|
(ACE_RB_Tree_Node<EXT_ID, INT_ID> *parent)
|
|
{
|
|
if (parent)
|
|
{
|
|
this->delete_children_i (parent->left ());
|
|
this->delete_children_i (parent->right ());
|
|
ACE_DES_FREE_TEMPLATE2
|
|
(parent->left (),
|
|
this->allocator_->free,
|
|
ACE_RB_Tree_Node,
|
|
EXT_ID, INT_ID);
|
|
ACE_DES_FREE_TEMPLATE2
|
|
(parent->right (),
|
|
this->allocator_->free,
|
|
ACE_RB_Tree_Node,
|
|
EXT_ID, INT_ID);
|
|
parent->left (0);
|
|
parent->right (0);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Close down an RB_Tree. this method should only be called with
|
|
// locks already held.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> int
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::close_i ()
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::close_i");
|
|
|
|
this->delete_children_i (this->root_);
|
|
ACE_DES_FREE_TEMPLATE2 (this->root_,
|
|
this->allocator()->free,
|
|
ACE_RB_Tree_Node,
|
|
EXT_ID, INT_ID);
|
|
this->current_size_ = 0;
|
|
this->root_ = 0;
|
|
return 0;
|
|
}
|
|
|
|
// Returns a pointer to the item corresponding to the given key, or 0
|
|
// if it cannot find the key in the tree. This method should only be
|
|
// called with locks already held.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> int
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::find_i (const EXT_ID &k,
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID>* &entry, int find_exact)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::find_i");
|
|
|
|
// Try to find a match.
|
|
RB_SearchResult result = LEFT;
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> *current = find_node (k, result);
|
|
|
|
if (current)
|
|
{
|
|
// Found a match
|
|
if (!find_exact || result == EXACT)
|
|
entry = current; // Assign the entry for any match.
|
|
return (result == EXACT ? 0 : -1);
|
|
}
|
|
else
|
|
// The node is not there.
|
|
return -1;
|
|
}
|
|
|
|
// Inserts a *copy* of the key and the item into the tree: both the
|
|
// key type EXT_ID and the item type INT_ID must have well defined
|
|
// semantics for copy construction and < comparison. This method
|
|
// returns a pointer to the inserted item copy, or 0 if an error
|
|
// occurred. NOTE: if an identical key already exists in the tree, no
|
|
// new item is created, and the returned pointer addresses the
|
|
// existing item associated with the existing key. This method should
|
|
// only be called with locks already held.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> INT_ID *
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::insert_i (const EXT_ID &k, const INT_ID &t)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::insert_i (const EXT_ID &k, const INT_ID &t)");
|
|
|
|
// Find the closest matching node, if there is one.
|
|
RB_SearchResult result = LEFT;
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> *current = find_node (k, result);
|
|
if (current)
|
|
{
|
|
// If the keys match, just return a pointer to the node's item.
|
|
if (result == EXACT)
|
|
return ¤t->item ();
|
|
|
|
// Otherwise if we're to the left of the insertion point, insert
|
|
// into the right subtree.
|
|
else if (result == LEFT)
|
|
{
|
|
if (current->right ())
|
|
{
|
|
// If there is already a right subtree, complain.
|
|
ACELIB_ERROR_RETURN ((LM_ERROR,
|
|
ACE_TEXT ("%p\n"),
|
|
ACE_TEXT ("\nright subtree already present in ")
|
|
ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::insert_i\n")),
|
|
0);
|
|
}
|
|
else
|
|
{
|
|
// The right subtree is empty: insert new node there.
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> *tmp = 0;
|
|
|
|
ACE_NEW_MALLOC_RETURN
|
|
(tmp,
|
|
(reinterpret_cast<ACE_RB_Tree_Node<EXT_ID, INT_ID>*>
|
|
(this->allocator_->malloc (sizeof (*tmp)))),
|
|
(ACE_RB_Tree_Node<EXT_ID, INT_ID>) (k, t),
|
|
0);
|
|
current->right (tmp);
|
|
|
|
// If the node was successfully inserted, set its
|
|
// parent, rebalance the tree, color the root black, and
|
|
// return a pointer to the inserted item.
|
|
INT_ID *item = &(current->right ()->item ());
|
|
current->right ()->parent (current);
|
|
RB_rebalance (current->right ());
|
|
root_->color (ACE_RB_Tree_Node_Base::BLACK);
|
|
++current_size_;
|
|
return item;
|
|
}
|
|
}
|
|
// Otherwise, we're to the right of the insertion point, so
|
|
// insert into the left subtree.
|
|
else // (result == RIGHT)
|
|
{
|
|
if (current->left ())
|
|
// If there is already a left subtree, complain.
|
|
ACELIB_ERROR_RETURN ((LM_ERROR,
|
|
ACE_TEXT ("%p\n"),
|
|
ACE_TEXT ("\nleft subtree already present in ")
|
|
ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::insert_i\n")),
|
|
0);
|
|
else
|
|
{
|
|
// The left subtree is empty: insert new node there.
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> *tmp = 0;
|
|
ACE_NEW_MALLOC_RETURN
|
|
(tmp,
|
|
(reinterpret_cast<ACE_RB_Tree_Node<EXT_ID, INT_ID>*>
|
|
(this->allocator_->malloc (sizeof (*tmp)))),
|
|
(ACE_RB_Tree_Node<EXT_ID, INT_ID>) (k, t),
|
|
0);
|
|
current->left (tmp);
|
|
|
|
// If the node was successfully inserted, set its
|
|
// parent, rebalance the tree, color the root black, and
|
|
// return a pointer to the inserted item.
|
|
INT_ID *item = ¤t->left ()->item ();
|
|
current->left ()->parent (current);
|
|
RB_rebalance (current->left ());
|
|
root_->color (ACE_RB_Tree_Node_Base::BLACK);
|
|
++current_size_;
|
|
return item;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// The tree is empty: insert at the root and color the root
|
|
// black.
|
|
ACE_NEW_MALLOC_RETURN
|
|
(this->root_,
|
|
(reinterpret_cast<ACE_RB_Tree_Node<EXT_ID, INT_ID>*>
|
|
(this->allocator_->malloc (sizeof (ACE_RB_Tree_Node<EXT_ID, INT_ID>)))),
|
|
(ACE_RB_Tree_Node<EXT_ID, INT_ID>) (k, t),
|
|
0);
|
|
this->root_->color (ACE_RB_Tree_Node_Base::BLACK);
|
|
++current_size_;
|
|
return &this->root_->item ();
|
|
}
|
|
}
|
|
|
|
// Inserts a *copy* of the key and the item into the tree: both the
|
|
// key type EXT_ID and the item type INT_ID must have well defined
|
|
// semantics for copy construction. The default implementation also
|
|
// requires that the key type support well defined < semantics. This
|
|
// method passes back a pointer to the inserted (or existing) node,
|
|
// and the search status. If the node already exists, the method
|
|
// returns 1. If the node does not exist, and a new one is
|
|
// successfully created, and the method returns 0. If there was an
|
|
// error, the method returns -1.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> int
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::insert_i (const EXT_ID &k,
|
|
const INT_ID &t,
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::insert_i");
|
|
|
|
// Find the closest matching node, if there is one.
|
|
RB_SearchResult result = LEFT;
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> *current = find_node (k, result);
|
|
if (current)
|
|
{
|
|
// If the keys match, just return a pointer to the node's item.
|
|
if (result == EXACT)
|
|
{
|
|
entry = current;
|
|
return 1;
|
|
}
|
|
// Otherwise if we're to the left of the insertion
|
|
// point, insert into the right subtree.
|
|
else if (result == LEFT)
|
|
{
|
|
if (current->right ())
|
|
{
|
|
// If there is already a right subtree, complain.
|
|
ACELIB_ERROR_RETURN ((LM_ERROR,
|
|
ACE_TEXT ("%p\n"),
|
|
ACE_TEXT ("\nright subtree already present in ")
|
|
ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::insert_i\n")),
|
|
-1);
|
|
}
|
|
else
|
|
{
|
|
// The right subtree is empty: insert new node there.
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> *tmp = 0;
|
|
ACE_NEW_MALLOC_RETURN
|
|
(tmp,
|
|
(reinterpret_cast<ACE_RB_Tree_Node<EXT_ID, INT_ID>*>
|
|
(this->allocator_->malloc (sizeof (*tmp)))),
|
|
(ACE_RB_Tree_Node<EXT_ID, INT_ID>) (k, t),
|
|
-1);
|
|
current->right (tmp);
|
|
|
|
// If the node was successfully inserted, set its parent, rebalance
|
|
// the tree, color the root black, and return a pointer to the
|
|
// inserted item.
|
|
entry = current->right ();
|
|
current->right ()->parent (current);
|
|
RB_rebalance (current->right ());
|
|
this->root_->color (ACE_RB_Tree_Node_Base::BLACK);
|
|
++this->current_size_;
|
|
return 0;
|
|
}
|
|
}
|
|
// Otherwise, we're to the right of the insertion point, so
|
|
// insert into the left subtree.
|
|
else // (result == RIGHT)
|
|
{
|
|
if (current->left ())
|
|
// If there is already a left subtree, complain.
|
|
ACELIB_ERROR_RETURN ((LM_ERROR,
|
|
ACE_TEXT ("%p\n"),
|
|
ACE_TEXT ("\nleft subtree already present in ")
|
|
ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::insert_i\n")),
|
|
-1);
|
|
else
|
|
{
|
|
// The left subtree is empty: insert new node there.
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> *tmp = 0;
|
|
ACE_NEW_MALLOC_RETURN
|
|
(tmp,
|
|
(reinterpret_cast<ACE_RB_Tree_Node<EXT_ID, INT_ID>*>
|
|
(this->allocator_->malloc (sizeof (*tmp)))),
|
|
(ACE_RB_Tree_Node<EXT_ID, INT_ID>) (k, t),
|
|
-1);
|
|
current->left (tmp);
|
|
// If the node was successfully inserted, set its
|
|
// parent, rebalance the tree, color the root black, and
|
|
// return a pointer to the inserted item.
|
|
entry = current->left ();
|
|
current->left ()->parent (current);
|
|
RB_rebalance (current->left ());
|
|
this->root_->color (ACE_RB_Tree_Node_Base::BLACK);
|
|
++this->current_size_;
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// The tree is empty: insert at the root and color the root black.
|
|
ACE_NEW_MALLOC_RETURN
|
|
(this->root_,
|
|
(reinterpret_cast<ACE_RB_Tree_Node<EXT_ID, INT_ID>*>
|
|
(this->allocator_->malloc (sizeof (ACE_RB_Tree_Node<EXT_ID, INT_ID>)))),
|
|
(ACE_RB_Tree_Node<EXT_ID, INT_ID>) (k, t),
|
|
-1);
|
|
this->root_->color (ACE_RB_Tree_Node_Base::BLACK);
|
|
++this->current_size_;
|
|
entry = this->root_;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// Removes the item associated with the given key from the tree and
|
|
// destroys it. Returns 1 if it found the item and successfully
|
|
// destroyed it, 0 if it did not find the item, or -1 if an error
|
|
// occurred. This method should only be called with locks already
|
|
// held.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> int
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::remove_i (const EXT_ID &k, INT_ID &i)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::remove_i (const EXT_ID &k, INT_ID &i)");
|
|
|
|
// Find a matching node, if there is one.
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> *z;
|
|
RB_SearchResult result = LEFT;
|
|
z = find_node (k, result);
|
|
|
|
// If there is a matching node: remove and destroy it.
|
|
if (z && result == EXACT)
|
|
{
|
|
// Return the internal id stored in the deleted node.
|
|
i = z->item ();
|
|
return -1 == this->remove_i (z) ? -1 : 1;
|
|
}
|
|
|
|
// No matching node was found: return 0.
|
|
return 0;
|
|
}
|
|
|
|
/// Recursive function to dump the state of an object.
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> void
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::
|
|
dump_i (ACE_RB_Tree_Node<EXT_ID, INT_ID> *node) const
|
|
{
|
|
#if defined (ACE_HAS_DUMP)
|
|
if (node)
|
|
{
|
|
dump_node_i (*node);
|
|
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\ndown left\n")));
|
|
this->dump_i (node->left ());
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nup left\n")));
|
|
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\ndown right\n")));
|
|
this->dump_i (node->right ());
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nup right\n")));
|
|
}
|
|
else
|
|
{
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nNULL POINTER (BLACK)\n")));
|
|
}
|
|
#else /* !ACE_HAS_DUMP */
|
|
ACE_UNUSED_ARG (node);
|
|
#endif /* ACE_HAS_DUMP */
|
|
}
|
|
|
|
/// Function to dump node itself. Does not show parameterized node contents
|
|
/// in its basic form, but template specialization can be used to
|
|
/// provide definitions for various EXT_ID and INT_ID types.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> void
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::
|
|
dump_node_i (ACE_RB_Tree_Node<EXT_ID, INT_ID> &node) const
|
|
{
|
|
#if defined (ACE_HAS_DUMP)
|
|
const char * color_str = (node.color () == ACE_RB_Tree_Node_Base::RED)
|
|
? "RED" : "BLACK";
|
|
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT (" color=[%s]\n"), color_str));
|
|
#else /* !ACE_HAS_DUMP */
|
|
ACE_UNUSED_ARG (node);
|
|
#endif /* ACE_HAS_DUMP */
|
|
}
|
|
|
|
/// Tests the red-black invariant(s) throughout the whole tree.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> int
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::test_invariant (void)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::test_invariant");
|
|
ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
|
|
|
|
// Recurse from the root, starting with the measured black height at
|
|
// 0, and the expected black height at -1, which will cause the
|
|
// count from first measured path to a leaf to be used as the
|
|
// expected one from that point onward (the key is to check
|
|
// consistency).
|
|
int expected_black_height = -1;
|
|
if (this->test_invariant_recurse (this->root_, expected_black_height, 0) == 0)
|
|
{
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("invariant holds\n")));
|
|
return 0;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/// Recursive function to test the red-black invariant(s) at all nodes in a subtree.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> int
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::test_invariant_recurse (ACE_RB_Tree_Node<EXT_ID, INT_ID> *x,
|
|
int & expected_black_height,
|
|
int measured_black_height)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::test_invariant_recurse");
|
|
|
|
if (!x)
|
|
{
|
|
// Count each leaf (zero pointer) as a black node (per CLR algorithm description).
|
|
++measured_black_height;
|
|
|
|
if (expected_black_height == -1)
|
|
{
|
|
expected_black_height = measured_black_height;
|
|
}
|
|
else if (expected_black_height != measured_black_height)
|
|
{
|
|
ACELIB_ERROR_RETURN ((LM_ERROR,
|
|
ACE_TEXT ("\nexpected_black_height = %d but ")
|
|
ACE_TEXT ("\nmeasured_black_height = %d in ")
|
|
ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::test_invariant_recurse\n"),
|
|
expected_black_height, measured_black_height),
|
|
-1);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Check the invariant that a red node cannot have a red child.
|
|
if (x->color () == ACE_RB_Tree_Node_Base::RED)
|
|
{
|
|
if (x->left () && x->left ()->color () == ACE_RB_Tree_Node_Base::RED)
|
|
{
|
|
ACELIB_ERROR_RETURN ((LM_ERROR,
|
|
ACE_TEXT ("%p\n"),
|
|
ACE_TEXT ("\nRED parent has RED left child in ")
|
|
ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::test_invariant_recurse\n")),
|
|
-1);
|
|
}
|
|
|
|
if (x->right () && x->right ()->color () == ACE_RB_Tree_Node_Base::RED)
|
|
{
|
|
ACELIB_ERROR_RETURN ((LM_ERROR,
|
|
ACE_TEXT ("%p\n"),
|
|
ACE_TEXT ("\nRED parent has RED right child in ")
|
|
ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::test_invariant_recurse\n")),
|
|
-1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Count each black node traversed.
|
|
++measured_black_height;
|
|
}
|
|
|
|
return (test_invariant_recurse (x->left (), expected_black_height, measured_black_height) == 0)
|
|
? test_invariant_recurse (x->right (), expected_black_height, measured_black_height)
|
|
: -1;
|
|
}
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> int
|
|
ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::remove_i (ACE_RB_Tree_Node<EXT_ID, INT_ID> *z)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::remove_i (ACE_RB_Tree_Node<EXT_ID, INT_ID> *z)");
|
|
|
|
// Delete the node and reorganize the tree to satisfy the Red-Black
|
|
// properties.
|
|
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> *x;
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> *y;
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> *parent;
|
|
|
|
if (z->left () && z->right ())
|
|
y = RB_tree_successor (z);
|
|
else
|
|
y = z;
|
|
|
|
if (!y)
|
|
return -1;
|
|
|
|
if (y->left ())
|
|
x = y->left ();
|
|
else
|
|
x = y->right ();
|
|
|
|
parent = y->parent ();
|
|
if (x)
|
|
{
|
|
x->parent (parent);
|
|
}
|
|
|
|
if (parent)
|
|
{
|
|
if (y == parent->left ())
|
|
parent->left (x);
|
|
else
|
|
parent->right (x);
|
|
}
|
|
else
|
|
this->root_ = x;
|
|
|
|
if (y != z)
|
|
{
|
|
// Replace node z with node y, since y's pointer may well be
|
|
// held externally, and be linked with y's key and item.
|
|
// We will end up deleting the old unlinked, node z.
|
|
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> *zParent = z->parent ();
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> *zLeftChild = z->left ();
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID> *zRightChild = z->right ();
|
|
|
|
if (zParent)
|
|
{
|
|
if (z == zParent->left ())
|
|
{
|
|
zParent->left (y);
|
|
}
|
|
else
|
|
{
|
|
zParent->right (y);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this->root_ = y;
|
|
}
|
|
y->parent (zParent);
|
|
|
|
if (zLeftChild)
|
|
{
|
|
zLeftChild->parent (y);
|
|
}
|
|
y->left (zLeftChild);
|
|
|
|
if (zRightChild)
|
|
{
|
|
zRightChild->parent (y);
|
|
}
|
|
y->right (zRightChild);
|
|
|
|
if (parent == z)
|
|
{
|
|
parent = y;
|
|
}
|
|
|
|
ACE_RB_Tree_Node_Base::RB_Tree_Node_Color yColor = y->color ();
|
|
y->color (z->color ());
|
|
z->color (yColor);
|
|
|
|
//Reassign the y pointer to z because the node that y points to will be
|
|
//deleted
|
|
y = z;
|
|
}
|
|
|
|
// CLR pp. 263 says that nil nodes are implicitly colored BLACK
|
|
if (!y || y->color () == ACE_RB_Tree_Node_Base::BLACK)
|
|
RB_delete_fixup (x, parent);
|
|
|
|
y->parent (0);
|
|
y->right (0);
|
|
y->left (0);
|
|
ACE_DES_FREE_TEMPLATE2 (y,
|
|
this->allocator_->free,
|
|
ACE_RB_Tree_Node,
|
|
EXT_ID, INT_ID);
|
|
--this->current_size_;
|
|
|
|
return 0;
|
|
}
|
|
|
|
ACE_ALLOC_HOOK_DEFINE(ACE_RB_Tree_Iterator_Base)
|
|
|
|
// Constructor.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
|
|
ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator_Base (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree, int set_first)
|
|
: tree_ (&tree), node_ (0)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator_Base (ACE_RB_Tree, int)");
|
|
|
|
// Position the iterator at the first (or last) node in the tree.
|
|
if (set_first)
|
|
node_ = tree_->RB_tree_minimum (tree_->root_);
|
|
else
|
|
node_ = tree_->RB_tree_maximum (tree_->root_);
|
|
}
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
|
|
ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator_Base (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree, ACE_RB_Tree_Node<EXT_ID, INT_ID>* entry)
|
|
: tree_ (&tree), node_ (0)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree_Iterator_Base(const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree, ACE_RB_Tree_Node<EXT_ID, INT_ID>* entry)");
|
|
node_ = entry;
|
|
}
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
|
|
ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator_Base (const EXT_ID& key,ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree)
|
|
: tree_ (&tree), node_ (0)
|
|
{
|
|
ACE_TRACE("ACE_RB_Tree_Iterator_Base (ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree, const EXT_ID& key)");
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID>* entry = 0;
|
|
tree.find_i(key, entry);
|
|
node_ = entry;
|
|
}
|
|
|
|
// Copy constructor.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
|
|
ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator_Base (const ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &iter)
|
|
: tree_ (iter.tree_),
|
|
node_ (iter.node_)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator_Base (ACE_RB_Tree_Iterator_Base)");
|
|
}
|
|
|
|
// Assignment operator.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> void
|
|
ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator= (const ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &iter)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator=");
|
|
if (this != &iter)
|
|
{
|
|
tree_ = iter.tree_;
|
|
node_ = iter.node_;
|
|
}
|
|
}
|
|
|
|
// Destructor.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
|
|
ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::~ACE_RB_Tree_Iterator_Base ()
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::~ACE_RB_Tree_Iterator_Base");
|
|
}
|
|
|
|
// Dump the state of an object.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
|
|
void
|
|
ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::dump_i (void) const
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::dump_i");
|
|
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nnode_ = %x\n"), this->node_));
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
|
|
}
|
|
|
|
|
|
ACE_ALLOC_HOOK_DEFINE(ACE_RB_Tree_Iterator)
|
|
|
|
// Constructor.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
|
|
ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree,
|
|
int set_first)
|
|
: ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> (tree, set_first)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator");
|
|
}
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
|
|
ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree,
|
|
ACE_RB_Tree_Node<EXT_ID, INT_ID>* entry)
|
|
: ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> (tree,entry)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator");
|
|
}
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
|
|
ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator (const EXT_ID& key,ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree)
|
|
: ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>(key,tree)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator");
|
|
}
|
|
|
|
// Destructor.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
|
|
ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::~ACE_RB_Tree_Iterator ()
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::~ACE_RB_Tree_Iterator");
|
|
}
|
|
|
|
ACE_ALLOC_HOOK_DEFINE(ACE_RB_Tree_Reverse_Iterator)
|
|
|
|
// Constructor.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
|
|
ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Reverse_Iterator (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree, int set_last)
|
|
: ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> (tree, set_last ? 0 : 1)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Reverse_Iterator");
|
|
}
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
|
|
ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Reverse_Iterator (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree, ACE_RB_Tree_Node<EXT_ID, INT_ID>* entry)
|
|
: ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> (tree,entry)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Reverse_Iterator");
|
|
}
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
|
|
ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Reverse_Iterator (const EXT_ID& key,ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree)
|
|
: ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>(key,tree)
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Reverse_Iterator");
|
|
}
|
|
|
|
// Destructor.
|
|
|
|
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK>
|
|
ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::~ACE_RB_Tree_Reverse_Iterator ()
|
|
{
|
|
ACE_TRACE ("ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::~ACE_RB_Tree_Reverse_Iterator");
|
|
}
|
|
|
|
ACE_END_VERSIONED_NAMESPACE_DECL
|
|
|
|
#endif /* !ACE_RB_TREE_CPP */
|