1 // $Id: RB_Tree.cpp 81768 2008-05-23 12:45:54Z sma $
3 #ifndef ACE_RB_TREE_CPP
4 #define ACE_RB_TREE_CPP
6 #include "ace/Global_Macros.h"
7 #include "ace/RB_Tree.h"
8 #include "ace/SString.h"
10 #if !defined (ACE_LACKS_PRAGMA_ONCE)
12 #endif /* ACE_LACKS_PRAGMA_ONCE */
14 #if !defined (__ACE_INLINE__)
15 #include "ace/RB_Tree.inl"
16 #endif /* __ACE_INLINE__ */
18 #include "ace/Log_Msg.h"
20 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
24 template <class EXT_ID
, class INT_ID
>
25 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
>::ACE_RB_Tree_Node (const EXT_ID
&k
, const INT_ID
&t
)
33 ACE_TRACE ("ACE_RB_Tree_Node<EXT_ID, INT_ID>::ACE_RB_Tree_Node (const EXT_ID &k, const INT_ID &t)");
39 template <class EXT_ID
, class INT_ID
>
40 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
>::~ACE_RB_Tree_Node (void)
42 ACE_TRACE ("ACE_RB_Tree_Node<EXT_ID, INT_ID>::~ACE_RB_Tree_Node");
47 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
>
48 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::ACE_RB_Tree (ACE_Allocator
*alloc
)
52 ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::"
53 "ACE_RB_Tree (ACE_Allocator *alloc)");
55 if (this->open (alloc
) == -1)
57 ACE_TEXT ("ACE_RB_Tree::ACE_RB_Tree\n")));
62 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
>
63 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
)
67 ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::"
68 "ACE_RB_Tree (const ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &rbt)");
69 ACE_WRITE_GUARD (ACE_LOCK
, ace_mon
, this->lock_
);
70 allocator_
= rbt
.allocator_
;
72 // Make a deep copy of the passed tree.
73 ACE_RB_Tree_Iterator
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
> iter(rbt
);
77 iter
.is_done () == 0; iter
.next ())
78 insert_i (*(iter
.key ()),
82 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
>
83 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::ACE_RB_Tree (
91 this->current_size_
= 0;
94 this->allocator_
= alloc
;
98 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
>
99 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::~ACE_RB_Tree ()
101 ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::~ACE_RB_Tree");
103 // Use the locked public method, to be totally safe, as the class
104 // can be used with an allocator and placement new.
108 // Assignment operator.
110 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
> void
111 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
)
113 ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator =");
114 ACE_WRITE_GUARD (ACE_LOCK
, ace_mon
, this->lock_
);
118 // Clear out the existing tree.
121 // Make a deep copy of the passed tree.
122 ACE_RB_Tree_Iterator
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
> iter(rbt
);
125 iter
.is_done () == 0;
127 insert_i (*(iter
.key ()),
130 // Use the same allocator as the rhs.
131 allocator_
= rbt
.allocator_
;
134 // Less than comparison function for keys, default functor
135 // implementation returns 1 if k1 < k2, 0 otherwise.
137 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
> int
138 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::lessthan (const EXT_ID
&k1
, const EXT_ID
&k2
)
140 ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::lessthan");
141 return this->compare_keys_ (k1
, k2
);
144 // Method for right rotation of the tree about a given node.
146 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
> void
147 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::RB_rotate_right (ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *x
)
149 ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_rotate_right");
152 ACE_ERROR ((LM_ERROR
,
154 ACE_TEXT ("\nerror: x is a null pointer in ")
155 ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::RB_rotate_right\n")));
156 else if (! (x
->left()))
157 ACE_ERROR ((LM_ERROR
,
159 ACE_TEXT ("\nerror: x->left () is a null pointer in ")
160 ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::RB_rotate_right\n")));
163 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> * y
;
165 x
->left (y
->right ());
167 y
->right ()->parent (x
);
168 y
->parent (x
->parent ());
171 if (x
== x
->parent ()->right ())
172 x
->parent ()->right (y
);
174 x
->parent ()->left (y
);
183 // Method for left rotation of the tree about a given node.
185 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
> void
186 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::RB_rotate_left (ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> * x
)
188 ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_rotate_left");
191 ACE_ERROR ((LM_ERROR
,
193 ACE_TEXT ("\nerror: x is a null pointer in ")
194 ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::RB_rotate_left\n")));
195 else if (! (x
->right()))
196 ACE_ERROR ((LM_ERROR
,
198 ACE_TEXT ("\nerror: x->right () is a null pointer ")
199 ACE_TEXT ("in ACE_RB_Tree<EXT_ID, INT_ID>::RB_rotate_left\n")));
202 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> * y
;
204 x
->right (y
->left ());
206 y
->left ()->parent (x
);
207 y
->parent (x
->parent ());
210 if (x
== x
->parent ()->left ())
211 x
->parent ()->left (y
);
213 x
->parent ()->right (y
);
222 // Method for restoring Red-Black properties after a specific deletion case.
224 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
> void
225 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::
226 RB_delete_fixup (ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *x
,
227 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *parent
)
229 ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_delete_fixup");
231 while (x
!= this->root_
233 || x
->color () == ACE_RB_Tree_Node_Base::BLACK
))
235 if (x
== parent
->left ())
237 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *w
= parent
->right ();
238 if (w
&& w
->color () == ACE_RB_Tree_Node_Base::RED
)
240 w
->color (ACE_RB_Tree_Node_Base::BLACK
);
241 parent
->color (ACE_RB_Tree_Node_Base::RED
);
242 RB_rotate_left (parent
);
243 w
= parent
->right ();
245 // CLR pp. 263 says that nil nodes are implicitly colored BLACK
248 || w
->left ()->color () == ACE_RB_Tree_Node_Base::BLACK
)
250 || w
->right ()->color () == ACE_RB_Tree_Node_Base::BLACK
))
252 w
->color (ACE_RB_Tree_Node_Base::RED
);
254 parent
= x
->parent ();
258 // CLR pp. 263 says that nil nodes are implicitly colored BLACK
261 || w
->right ()->color () == ACE_RB_Tree_Node_Base::BLACK
))
264 w
->left ()->color (ACE_RB_Tree_Node_Base::BLACK
);
265 w
->color (ACE_RB_Tree_Node_Base::RED
);
267 w
= parent
->right ();
271 w
->color (parent
->color ());
273 w
->right ()->color (ACE_RB_Tree_Node_Base::BLACK
);
275 parent
->color (ACE_RB_Tree_Node_Base::BLACK
);
276 RB_rotate_left (parent
);
282 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *w
= parent
->left ();
283 if (w
&& w
->color () == ACE_RB_Tree_Node_Base::RED
)
285 w
->color (ACE_RB_Tree_Node_Base::BLACK
);
286 parent
->color (ACE_RB_Tree_Node_Base::RED
);
287 RB_rotate_right (parent
);
290 // CLR pp. 263 says that nil nodes are implicitly colored BLACK
293 || w
->left ()->color () == ACE_RB_Tree_Node_Base::BLACK
)
295 || w
->right ()->color () == ACE_RB_Tree_Node_Base::BLACK
))
297 w
->color (ACE_RB_Tree_Node_Base::RED
);
299 parent
= x
->parent ();
303 // CLR pp. 263 says that nil nodes are implicitly colored BLACK
306 || w
->left ()->color () == ACE_RB_Tree_Node_Base::BLACK
))
308 w
->color (ACE_RB_Tree_Node_Base::RED
);
310 w
->right ()->color (ACE_RB_Tree_Node_Base::BLACK
);
316 w
->color (parent
->color ());
318 w
->left ()->color (ACE_RB_Tree_Node_Base::BLACK
);
320 parent
->color (ACE_RB_Tree_Node_Base::BLACK
);
321 RB_rotate_right (parent
);
328 x
->color (ACE_RB_Tree_Node_Base::BLACK
);
331 // Return a pointer to a matching node if there is one, a pointer to
332 // the node under which to insert the item if the tree is not empty
333 // and there is no such match, or 0 if the tree is empty.
335 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
> ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *
336 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::find_node (const EXT_ID
&k
, ACE_RB_Tree_Base::RB_SearchResult
&result
)
338 ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::find_node");
340 // Start at the root.
341 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *current
= root_
;
345 // While there are more nodes to examine.
346 if (this->lessthan (current
->key (), k
))
348 // If the search key is greater than the current node's key.
349 if (current
->right ())
350 // If the right subtree is not empty, search to the right.
351 current
= current
->right ();
354 // If the right subtree is empty, we're done searching,
355 // and are positioned to the left of the insertion point.
360 else if (this->lessthan (k
, current
->key ()))
362 // Else if the search key is less than the current node's key.
363 if (current
->left ())
364 // If the left subtree is not empty, search to the left.
365 current
= current
->left ();
368 // If the left subtree is empty, we're done searching,
369 // and are positioned to the right of the insertion point.
376 // If the keys match exactly, we're done as well.
385 // Rebalance the tree after insertion of a node.
387 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
> void
388 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::RB_rebalance (ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> * x
)
390 ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_rebalance");
392 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *y
= 0;
396 && x
->parent ()->color () == ACE_RB_Tree_Node_Base::RED
)
398 if (! x
->parent ()->parent ())
400 // If we got here, something is drastically wrong!
401 ACE_ERROR ((LM_ERROR
,
403 ACE_TEXT ("\nerror: parent's parent is null in ")
404 ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::RB_rebalance\n")));
408 if (x
->parent () == x
->parent ()->parent ()->left ())
410 y
= x
->parent ()->parent ()->right ();
411 if (y
&& y
->color () == ACE_RB_Tree_Node_Base::RED
)
413 // Handle case 1 (see CLR book, pp. 269).
414 x
->parent ()->color (ACE_RB_Tree_Node_Base::BLACK
);
415 y
->color (ACE_RB_Tree_Node_Base::BLACK
);
416 x
->parent ()->parent ()->color (ACE_RB_Tree_Node_Base::RED
);
417 x
= x
->parent ()->parent ();
421 if (x
== x
->parent ()->right ())
423 // Transform case 2 into case 3 (see CLR book, pp. 269).
428 // Handle case 3 (see CLR book, pp. 269).
429 x
->parent ()->color (ACE_RB_Tree_Node_Base::BLACK
);
430 x
->parent ()->parent ()->color (ACE_RB_Tree_Node_Base::RED
);
431 RB_rotate_right (x
->parent ()->parent ());
436 y
= x
->parent ()->parent ()->left ();
437 if (y
&& y
->color () == ACE_RB_Tree_Node_Base::RED
)
439 // Handle case 1 (see CLR book, pp. 269).
440 x
->parent ()->color (ACE_RB_Tree_Node_Base::BLACK
);
441 y
->color (ACE_RB_Tree_Node_Base::BLACK
);
442 x
->parent ()->parent ()->color (ACE_RB_Tree_Node_Base::RED
);
443 x
= x
->parent ()->parent ();
447 if (x
== x
->parent ()->left ())
449 // Transform case 2 into case 3 (see CLR book, pp. 269).
454 // Handle case 3 (see CLR book, pp. 269).
455 x
->parent ()->color (ACE_RB_Tree_Node_Base::BLACK
);
456 x
->parent ()->parent ()->color (ACE_RB_Tree_Node_Base::RED
);
457 RB_rotate_left (x
->parent ()->parent ());
463 // Method to find the successor node of the given node in the tree.
465 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
> ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *
466 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::RB_tree_successor (ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *x
) const
468 ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_tree_successor");
474 return RB_tree_minimum (x
->right ());
476 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *y
= x
->parent ();
477 while ((y
) && (x
== y
->right ()))
486 // Method to find the predecessor node of the given node in the tree.
488 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
> ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *
489 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::RB_tree_predecessor (ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *x
) const
491 ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_tree_predecessor");
496 return RB_tree_maximum (x
->left ());
498 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *y
= x
->parent ();
500 while ((y
) && (x
== y
->left ()))
509 // Method to find the minimum node of the subtree rooted at the given node.
511 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
> ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *
512 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::RB_tree_minimum (ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *x
) const
514 ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_tree_minimum");
516 while ((x
) && (x
->left ()))
522 // Method to find the maximum node of the subtree rooted at the given node.
524 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
> ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *
525 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::RB_tree_maximum (ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *x
) const
527 ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_tree_maximum");
529 while ((x
) && (x
->right ()))
535 // Delete children (left and right) of the node. Must be called with
537 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
>
538 void ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::delete_children_i
539 (ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *parent
)
543 this->delete_children_i (parent
->left ());
544 this->delete_children_i (parent
->right ());
545 ACE_DES_FREE_TEMPLATE2
547 this->allocator_
->free
,
550 ACE_DES_FREE_TEMPLATE2
552 this->allocator_
->free
,
561 // Close down an RB_Tree. this method should only be called with
562 // locks already held.
564 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
> int
565 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::close_i ()
567 ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::close_i");
569 this->delete_children_i (this->root_
);
570 ACE_DES_FREE_TEMPLATE2 (this->root_
,
571 this->allocator()->free
,
574 this->current_size_
= 0;
579 // Returns a pointer to the item corresponding to the given key, or 0
580 // if it cannot find the key in the tree. This method should only be
581 // called with locks already held.
583 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
> int
584 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::find_i (const EXT_ID
&k
,
585 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
>* &entry
, int find_exact
)
587 ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::find_i");
589 // Try to find a match.
590 RB_SearchResult result
= LEFT
;
591 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *current
= find_node (k
, result
);
596 if (!find_exact
|| result
== EXACT
)
597 entry
= current
; // Assign the entry for any match.
598 return (result
== EXACT
? 0 : -1);
601 // The node is not there.
605 // Inserts a *copy* of the key and the item into the tree: both the
606 // key type EXT_ID and the item type INT_ID must have well defined
607 // semantics for copy construction and < comparison. This method
608 // returns a pointer to the inserted item copy, or 0 if an error
609 // occurred. NOTE: if an identical key already exists in the tree, no
610 // new item is created, and the returned pointer addresses the
611 // existing item associated with the existing key. This method should
612 // only be called with locks already held.
614 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
> INT_ID
*
615 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::insert_i (const EXT_ID
&k
, const INT_ID
&t
)
617 ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::insert_i (const EXT_ID &k, const INT_ID &t)");
619 // Find the closest matching node, if there is one.
620 RB_SearchResult result
= LEFT
;
621 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *current
= find_node (k
, result
);
624 // If the keys match, just return a pointer to the node's item.
626 return ¤t
->item ();
628 // Otherwise if we're to the left of the insertion point, insert
629 // into the right subtree.
630 else if (result
== LEFT
)
632 if (current
->right ())
634 // If there is already a right subtree, complain.
635 ACE_ERROR_RETURN ((LM_ERROR
,
637 ACE_TEXT ("\nright subtree already present in ")
638 ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::insert_i\n")),
643 // The right subtree is empty: insert new node there.
644 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *tmp
= 0;
646 ACE_NEW_MALLOC_RETURN
648 (reinterpret_cast<ACE_RB_Tree_Node
<EXT_ID
, INT_ID
>*>
649 (this->allocator_
->malloc (sizeof (*tmp
)))),
650 (ACE_RB_Tree_Node
<EXT_ID
, INT_ID
>) (k
, t
),
652 current
->right (tmp
);
654 // If the node was successfully inserted, set its
655 // parent, rebalance the tree, color the root black, and
656 // return a pointer to the inserted item.
657 INT_ID
*item
= &(current
->right ()->item ());
658 current
->right ()->parent (current
);
659 RB_rebalance (current
->right ());
660 root_
->color (ACE_RB_Tree_Node_Base::BLACK
);
665 // Otherwise, we're to the right of the insertion point, so
666 // insert into the left subtree.
667 else // (result == RIGHT)
669 if (current
->left ())
670 // If there is already a left subtree, complain.
671 ACE_ERROR_RETURN ((LM_ERROR
,
673 ACE_TEXT ("\nleft subtree already present in ")
674 ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::insert_i\n")),
678 // The left subtree is empty: insert new node there.
679 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *tmp
= 0;
680 ACE_NEW_MALLOC_RETURN
682 (reinterpret_cast<ACE_RB_Tree_Node
<EXT_ID
, INT_ID
>*>
683 (this->allocator_
->malloc (sizeof (*tmp
)))),
684 (ACE_RB_Tree_Node
<EXT_ID
, INT_ID
>) (k
, t
),
688 // If the node was successfully inserted, set its
689 // parent, rebalance the tree, color the root black, and
690 // return a pointer to the inserted item.
691 INT_ID
*item
= ¤t
->left ()->item ();
692 current
->left ()->parent (current
);
693 RB_rebalance (current
->left ());
694 root_
->color (ACE_RB_Tree_Node_Base::BLACK
);
702 // The tree is empty: insert at the root and color the root
704 ACE_NEW_MALLOC_RETURN
706 (reinterpret_cast<ACE_RB_Tree_Node
<EXT_ID
, INT_ID
>*>
707 (this->allocator_
->malloc (sizeof (ACE_RB_Tree_Node
<EXT_ID
, INT_ID
>)))),
708 (ACE_RB_Tree_Node
<EXT_ID
, INT_ID
>) (k
, t
),
710 this->root_
->color (ACE_RB_Tree_Node_Base::BLACK
);
712 return &this->root_
->item ();
716 // Inserts a *copy* of the key and the item into the tree: both the
717 // key type EXT_ID and the item type INT_ID must have well defined
718 // semantics for copy construction. The default implementation also
719 // requires that the key type support well defined < semantics. This
720 // method passes back a pointer to the inserted (or existing) node,
721 // and the search status. If the node already exists, the method
722 // returns 1. If the node does not exist, and a new one is
723 // successfully created, and the method returns 0. If there was an
724 // error, the method returns -1.
726 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
> int
727 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::insert_i (const EXT_ID
&k
,
729 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *&entry
)
731 ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::insert_i (const EXT_ID &k, const INT_ID &t, "
732 "ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry)");
734 // Find the closest matching node, if there is one.
735 RB_SearchResult result
= LEFT
;
736 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *current
= find_node (k
, result
);
739 // If the keys match, just return a pointer to the node's item.
745 // Otherwise if we're to the left of the insertion
746 // point, insert into the right subtree.
747 else if (result
== LEFT
)
749 if (current
->right ())
751 // If there is already a right subtree, complain.
752 ACE_ERROR_RETURN ((LM_ERROR
,
754 ACE_TEXT ("\nright subtree already present in ")
755 ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::insert_i\n")),
760 // The right subtree is empty: insert new node there.
761 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *tmp
= 0;
762 ACE_NEW_MALLOC_RETURN
764 (reinterpret_cast<ACE_RB_Tree_Node
<EXT_ID
, INT_ID
>*>
765 (this->allocator_
->malloc (sizeof (*tmp
)))),
766 (ACE_RB_Tree_Node
<EXT_ID
, INT_ID
>) (k
, t
),
768 current
->right (tmp
);
770 // If the node was successfully inserted, set its parent, rebalance
771 // the tree, color the root black, and return a pointer to the
773 entry
= current
->right ();
774 current
->right ()->parent (current
);
775 RB_rebalance (current
->right ());
776 this->root_
->color (ACE_RB_Tree_Node_Base::BLACK
);
777 ++this->current_size_
;
781 // Otherwise, we're to the right of the insertion point, so
782 // insert into the left subtree.
783 else // (result == RIGHT)
785 if (current
->left ())
786 // If there is already a left subtree, complain.
787 ACE_ERROR_RETURN ((LM_ERROR
,
789 ACE_TEXT ("\nleft subtree already present in ")
790 ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::insert_i\n")),
794 // The left subtree is empty: insert new node there.
795 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *tmp
= 0;
796 ACE_NEW_MALLOC_RETURN
798 (reinterpret_cast<ACE_RB_Tree_Node
<EXT_ID
, INT_ID
>*>
799 (this->allocator_
->malloc (sizeof (*tmp
)))),
800 (ACE_RB_Tree_Node
<EXT_ID
, INT_ID
>) (k
, t
),
803 // If the node was successfully inserted, set its
804 // parent, rebalance the tree, color the root black, and
805 // return a pointer to the inserted item.
806 entry
= current
->left ();
807 current
->left ()->parent (current
);
808 RB_rebalance (current
->left ());
809 this->root_
->color (ACE_RB_Tree_Node_Base::BLACK
);
810 ++this->current_size_
;
817 // The tree is empty: insert at the root and color the root black.
818 ACE_NEW_MALLOC_RETURN
820 (reinterpret_cast<ACE_RB_Tree_Node
<EXT_ID
, INT_ID
>*>
821 (this->allocator_
->malloc (sizeof (ACE_RB_Tree_Node
<EXT_ID
, INT_ID
>)))),
822 (ACE_RB_Tree_Node
<EXT_ID
, INT_ID
>) (k
, t
),
824 this->root_
->color (ACE_RB_Tree_Node_Base::BLACK
);
825 ++this->current_size_
;
831 // Removes the item associated with the given key from the tree and
832 // destroys it. Returns 1 if it found the item and successfully
833 // destroyed it, 0 if it did not find the item, or -1 if an error
834 // occurred. This method should only be called with locks already
837 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
> int
838 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::remove_i (const EXT_ID
&k
, INT_ID
&i
)
840 ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::remove_i (const EXT_ID &k, INT_ID &i)");
842 // Find a matching node, if there is one.
843 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *z
;
844 RB_SearchResult result
= LEFT
;
845 z
= find_node (k
, result
);
847 // If there is a matching node: remove and destroy it.
848 if (z
&& result
== EXACT
)
850 // Return the internal id stored in the deleted node.
852 return -1 == this->remove_i (z
) ? -1 : 1;
855 // No matching node was found: return 0.
859 /// Recursive function to dump the state of an object.
860 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
> void
861 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::
862 dump_i (ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *node
) const
864 #if defined (ACE_HAS_DUMP)
869 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("\ndown left\n")));
870 this->dump_i (node
->left ());
871 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("\nup left\n")));
873 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("\ndown right\n")));
874 this->dump_i (node
->right ());
875 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("\nup right\n")));
879 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("\nNULL POINTER (BLACK)\n")));
881 #else /* !ACE_HAS_DUMP */
882 ACE_UNUSED_ARG (node
);
883 #endif /* ACE_HAS_DUMP */
886 /// Function to dump node itself. Does not show parameterized node contents
887 /// in its basic form, but template specialization can be used to
888 /// provide definitions for various EXT_ID and INT_ID types.
890 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
> void
891 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::
892 dump_node_i (ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> &node
) const
894 #if defined (ACE_HAS_DUMP)
895 const char * color_str
= (node
.color () == ACE_RB_Tree_Node_Base::RED
)
898 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT (" color=[%s]\n"), color_str
));
899 #else /* !ACE_HAS_DUMP */
900 ACE_UNUSED_ARG (node
);
901 #endif /* ACE_HAS_DUMP */
904 /// Tests the red-black invariant(s) throughout the whole tree.
906 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
> int
907 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::test_invariant (void)
909 ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::test_invariant");
910 ACE_READ_GUARD_RETURN (ACE_LOCK
, ace_mon
, this->lock_
, -1);
912 // Recurse from the root, starting with the measured black height at
913 // 0, and the expected black height at -1, which will cause the
914 // count from first measured path to a leaf to be used as the
915 // expected one from that point onward (the key is to check
917 int expected_black_height
= -1;
918 if (this->test_invariant_recurse (this->root_
, expected_black_height
, 0) == 0)
920 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("invariant holds\n")));
927 /// Recursive function to test the red-black invariant(s) at all nodes in a subtree.
929 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
> int
930 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::test_invariant_recurse (ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *x
,
931 int & expected_black_height
,
932 int measured_black_height
)
934 ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::test_invariant_recurse");
938 // Count each leaf (zero pointer) as a black node (per CLR algorithm description).
939 ++measured_black_height
;
941 if (expected_black_height
== -1)
943 expected_black_height
= measured_black_height
;
945 else if (expected_black_height
!= measured_black_height
)
947 ACE_ERROR_RETURN ((LM_ERROR
,
948 ACE_TEXT ("\nexpected_black_height = %d but ")
949 ACE_TEXT ("\nmeasured_black_height = %d in ")
950 ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::test_invariant_recurse\n"),
951 expected_black_height
, measured_black_height
),
958 // Check the invariant that a red node cannot have a red child.
959 if (x
->color () == ACE_RB_Tree_Node_Base::RED
)
961 if (x
->left () && x
->left ()->color () == ACE_RB_Tree_Node_Base::RED
)
963 ACE_ERROR_RETURN ((LM_ERROR
,
965 ACE_TEXT ("\nRED parent has RED left child in ")
966 ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::test_invariant_recurse\n")),
970 if (x
->right () && x
->right ()->color () == ACE_RB_Tree_Node_Base::RED
)
972 ACE_ERROR_RETURN ((LM_ERROR
,
974 ACE_TEXT ("\nRED parent has RED right child in ")
975 ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::test_invariant_recurse\n")),
981 // Count each black node traversed.
982 ++measured_black_height
;
985 return (test_invariant_recurse (x
->left (), expected_black_height
, measured_black_height
) == 0)
986 ? test_invariant_recurse (x
->right (), expected_black_height
, measured_black_height
)
990 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
> int
991 ACE_RB_Tree
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::remove_i (ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *z
)
993 ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::remove_i (ACE_RB_Tree_Node<EXT_ID, INT_ID> *z)");
995 // Delete the node and reorganize the tree to satisfy the Red-Black
998 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *x
;
999 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *y
;
1000 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *parent
;
1002 if (z
->left () && z
->right ())
1003 y
= RB_tree_successor (z
);
1015 parent
= y
->parent ();
1023 if (y
== parent
->left ())
1033 // Replace node z with node y, since y's pointer may well be
1034 // held externally, and be linked with y's key and item.
1035 // We will end up deleting the old unlinked, node z.
1037 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *zParent
= z
->parent ();
1038 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *zLeftChild
= z
->left ();
1039 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
> *zRightChild
= z
->right ();
1043 if (z
== zParent
->left ())
1056 y
->parent (zParent
);
1060 zLeftChild
->parent (y
);
1062 y
->left (zLeftChild
);
1066 zRightChild
->parent (y
);
1068 y
->right (zRightChild
);
1075 ACE_RB_Tree_Node_Base::RB_Tree_Node_Color yColor
= y
->color ();
1076 y
->color (z
->color ());
1079 //Reassign the y pointer to z because the node that y points to will be
1084 // CLR pp. 263 says that nil nodes are implicitly colored BLACK
1085 if (!y
|| y
->color () == ACE_RB_Tree_Node_Base::BLACK
)
1086 RB_delete_fixup (x
, parent
);
1091 ACE_DES_FREE_TEMPLATE2 (y
,
1092 this->allocator_
->free
,
1095 --this->current_size_
;
1100 ACE_ALLOC_HOOK_DEFINE(ACE_RB_Tree_Iterator_Base
)
1104 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
>
1105 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
)
1106 : tree_ (&tree
), node_ (0)
1108 ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator_Base (ACE_RB_Tree, int)");
1110 // Position the iterator at the first (or last) node in the tree.
1112 node_
= tree_
->RB_tree_minimum (tree_
->root_
);
1114 node_
= tree_
->RB_tree_maximum (tree_
->root_
);
1117 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
>
1118 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
)
1119 : tree_ (&tree
), node_ (0)
1121 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)");
1125 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
>
1126 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
)
1127 : tree_ (&tree
), node_ (0)
1129 ACE_TRACE("ACE_RB_Tree_Iterator_Base (ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK> &tree, const EXT_ID& key)");
1130 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
>* entry
= 0;
1131 tree
.find_i(key
, entry
);
1135 // Copy constructor.
1137 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
>
1138 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
)
1139 : tree_ (iter
.tree_
),
1142 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)");
1145 // Assignment operator.
1147 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
> void
1148 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
)
1150 ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::operator=");
1160 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
>
1161 ACE_RB_Tree_Iterator_Base
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::~ACE_RB_Tree_Iterator_Base ()
1163 ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::~ACE_RB_Tree_Iterator_Base");
1166 // Dump the state of an object.
1168 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
>
1170 ACE_RB_Tree_Iterator_Base
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::dump_i (void) const
1172 ACE_TRACE ("ACE_RB_Tree_Iterator_Base<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::dump_i");
1174 ACE_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
1175 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("\nnode_ = %x\n"), this->node_
));
1176 ACE_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
1180 ACE_ALLOC_HOOK_DEFINE(ACE_RB_Tree_Iterator
)
1184 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
>
1185 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
,
1187 : ACE_RB_Tree_Iterator_Base
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
> (tree
, set_first
)
1189 ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator");
1192 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
>
1193 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
,
1194 ACE_RB_Tree_Node
<EXT_ID
, INT_ID
>* entry
)
1195 : ACE_RB_Tree_Iterator_Base
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
> (tree
,entry
)
1197 ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator");
1200 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
>
1201 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
)
1202 : ACE_RB_Tree_Iterator_Base
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>(key
,tree
)
1204 ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Iterator");
1209 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
>
1210 ACE_RB_Tree_Iterator
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::~ACE_RB_Tree_Iterator ()
1212 ACE_TRACE ("ACE_RB_Tree_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::~ACE_RB_Tree_Iterator");
1215 ACE_ALLOC_HOOK_DEFINE(ACE_RB_Tree_Reverse_Iterator
)
1219 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
>
1220 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
)
1221 : ACE_RB_Tree_Iterator_Base
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
> (tree
, set_last
? 0 : 1)
1223 ACE_TRACE ("ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Reverse_Iterator");
1226 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
>
1227 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
)
1228 : ACE_RB_Tree_Iterator_Base
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
> (tree
,entry
)
1230 ACE_TRACE ("ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Reverse_Iterator");
1233 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
>
1234 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
)
1235 : ACE_RB_Tree_Iterator_Base
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>(key
,tree
)
1237 ACE_TRACE ("ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::ACE_RB_Tree_Reverse_Iterator");
1242 template <class EXT_ID
, class INT_ID
, class COMPARE_KEYS
, class ACE_LOCK
>
1243 ACE_RB_Tree_Reverse_Iterator
<EXT_ID
, INT_ID
, COMPARE_KEYS
, ACE_LOCK
>::~ACE_RB_Tree_Reverse_Iterator ()
1245 ACE_TRACE ("ACE_RB_Tree_Reverse_Iterator<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::~ACE_RB_Tree_Reverse_Iterator");
1248 ACE_END_VERSIONED_NAMESPACE_DECL
1250 #endif /* !ACE_RB_TREE_CPP */