// -*- C++ -*- //============================================================================= /** * @file RB_Tree.h * * @author Chris Gill */ //============================================================================= #ifndef ACE_RB_TREE_H #define ACE_RB_TREE_H #include /**/ "ace/pre.h" #include "ace/Global_Macros.h" #include "ace/Functor_T.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ ACE_BEGIN_VERSIONED_NAMESPACE_DECL // Forward decl. template class ACE_RB_Tree_Iterator_Base; // Forward decl. template class ACE_RB_Tree_Iterator; // Forward decl. template class ACE_RB_Tree_Reverse_Iterator; // Forward decl. class ACE_Allocator; class ACE_RB_Tree_Node_Base { public: enum RB_Tree_Node_Color {RED, BLACK}; }; /** * @class ACE_RB_Tree_Node * * @brief Implements a node in a Red-Black Tree ADT. */ template class ACE_RB_Tree_Node : public ACE_RB_Tree_Node_Base { public: /// Constructor. ACE_RB_Tree_Node (const EXT_ID &k, const INT_ID &t); /// Destructor. ~ACE_RB_Tree_Node (); /// Key accessor. EXT_ID &key (); /// Item accessor. INT_ID &item (); /// Set color of the node. void color (RB_Tree_Node_Color c); /// Get color of the node. RB_Tree_Node_Color color (); /// Accessor for node's parent pointer. ACE_RB_Tree_Node *parent (); /// Mutator for node's parent pointer. void parent (ACE_RB_Tree_Node * p); /// Accessor for node's left child pointer. ACE_RB_Tree_Node *left (); /// Mutator for node's left child pointer. void left (ACE_RB_Tree_Node *l); /// Accessor for node's right child pointer. ACE_RB_Tree_Node *right (); /// Mutator for node's right child pointer void right (ACE_RB_Tree_Node * r); private: /// The key. EXT_ID k_; /// The item. INT_ID t_; /// Color of the node. RB_Tree_Node_Color color_; /// Pointer to node's parent. ACE_RB_Tree_Node *parent_; /// Pointer to node's left child. ACE_RB_Tree_Node *left_; /// Pointer to node's right child. ACE_RB_Tree_Node *right_; }; class ACE_RB_Tree_Base { public: /// Search result enumeration. enum RB_SearchResult {LEFT, EXACT, RIGHT}; /// Get the allocator; /** * @note This method is inlined here rather than in RB_Tree.inl * since that file may be included multiple times when * inlining is disabled. In those platform/configuration * combinations, multiple definitions of this method occurred. * Placing the definition inline in the header avoids such errors. */ ACE_Allocator * allocator () const { return this->allocator_; } protected: // = Protected members. /// Pointer to a memory allocator. ACE_Allocator *allocator_; }; /** * @class ACE_RB_Tree * * @brief Implements a Red-Black Tree ADT, according to T. H. Corman, * C. E. Leiserson, and R. L. Rivest, "Introduction to Algorithms" * 1990, MIT, chapter 14. * * A number of Changes have been made to this class template * in order to conform to the ACE_Hash_Map_Manager_Ex * interface. All previously supported public methods are * still part of this class. However, these are marked as * DEPRECATED and will be removed from this class in * a future version of ACE. Please migrate your code * to the appropriate public methods indicated in the * method deprecation comments. * This class uses an ACE_Allocator to allocate memory. The * user can make this a persistent class by providing an * ACE_Allocator with a persistable memory pool. * * Requirements and Performance Characteristics * - Internal Structure: * Binary tree * - Duplicates allowed? * No * - Random access allowed? * No * - Search speed: * Log(n) * - Insert/replace speed: * Log(n) * - Iterator still valid after change to container? * Yes, except if the iterated-over element is removed. * - Frees memory for removed elements? * Yes * - Items inserted by: * Value * - Requirements for contained type * -# Default constructor * -# Copy constructor * -# operator= * -# operator== * -# operator< */ template class ACE_RB_Tree : public ACE_RB_Tree_Base { public: friend class ACE_RB_Tree_Iterator_Base; friend class ACE_RB_Tree_Iterator; friend class ACE_RB_Tree_Reverse_Iterator; typedef EXT_ID KEY; typedef INT_ID VALUE; typedef ACE_LOCK lock_type; typedef ACE_RB_Tree_Node ENTRY; // = ACE-style iterator typedefs. typedef ACE_RB_Tree_Iterator ITERATOR; typedef ACE_RB_Tree_Reverse_Iterator REVERSE_ITERATOR; // = STL-style iterator typedefs. typedef ACE_RB_Tree_Iterator iterator; typedef ACE_RB_Tree_Reverse_Iterator reverse_iterator; /// Constructor. ACE_RB_Tree (ACE_Allocator *alloc = nullptr); /// Copy constructor. ACE_RB_Tree (const ACE_RB_Tree &rbt); /// Initialize an RB Tree. int open (ACE_Allocator *alloc = nullptr); /// Close down an RB_Tree and release dynamically allocated /// resources. int close (); /// Destructor. virtual ~ACE_RB_Tree (); // = insertion, removal, and search methods. /** * Associate @a ext_id with @a int_id. If @a ext_id is already in the * tree then the is not changed. Returns 0 if a * new entry is bound successfully, returns 1 if an attempt is made * to bind an existing entry, and returns -1 if failures occur. */ int bind (const EXT_ID &item, const INT_ID &int_id); /** * Same as a normal bind, except the tree entry is also passed back * to the caller. The entry in this case will either be the newly * created entry, or the existing one. */ int bind (const EXT_ID &ext_id, const INT_ID &int_id, ACE_RB_Tree_Node *&entry); /** * Associate @a ext_id with @a int_id if and only if @a ext_id is not * in the tree. If @a ext_id is already in the tree then the @a int_id * parameter is assigned the existing value in the tree. Returns 0 * if a new entry is bound successfully, returns 1 if an attempt is * made to bind an existing entry, and returns -1 if failures occur. */ int trybind (const EXT_ID &ext_id, INT_ID &int_id); /** * Same as a normal trybind, except the tree entry is also passed * back to the caller. The entry in this case will either be the * newly created entry, or the existing one. */ int trybind (const EXT_ID &ext_id, INT_ID &int_id, ACE_RB_Tree_Node *&entry); /** * Reassociate @a ext_id with @a int_id. If @a ext_id is not in the * tree then behaves just like . Returns 0 if a new entry is * bound successfully, returns 1 if an existing entry was rebound, * and returns -1 if failures occur. */ int rebind (const EXT_ID &ext_id, const INT_ID &int_id); /** * Same as a normal rebind, except the tree entry is also passed back * to the caller. The entry in this case will either be the newly * created entry, or the existing one. */ int rebind (const EXT_ID &ext_id, const INT_ID &int_id, ACE_RB_Tree_Node *&entry); /** * Associate @a ext_id with @a int_id. If @a ext_id is not in the tree * then behaves just like . Otherwise, store the old value of * @a int_id into the "out" parameter and rebind the new parameters. * Returns 0 if a new entry is bound successfully, returns 1 if an * existing entry was rebound, and returns -1 if failures occur. */ int rebind (const EXT_ID &ext_id, const INT_ID &int_id, INT_ID &old_int_id); /** * Same as a normal rebind, except the tree entry is also passed back * to the caller. The entry in this case will either be the newly * created entry, or the existing one. */ int rebind (const EXT_ID &ext_id, const INT_ID &int_id, INT_ID &old_int_id, ACE_RB_Tree_Node *&entry); /** * Associate @a ext_id with @a int_id. If @a ext_id is not in the tree * then behaves just like . Otherwise, store the old values * of @a ext_id and @a int_id into the "out" parameters and rebind the * new parameters. This is very useful if you need to have an * atomic way of updating and you also need * full control over memory allocation. Returns 0 if a new entry is * bound successfully, returns 1 if an existing entry was rebound, * and returns -1 if failures occur. */ int rebind (const EXT_ID &ext_id, const INT_ID &int_id, EXT_ID &old_ext_id, INT_ID &old_int_id); /** * Same as a normal rebind, except the tree entry is also passed back * to the caller. The entry in this case will either be the newly * created entry, or the existing one. */ int rebind (const EXT_ID &ext_id, const INT_ID &int_id, EXT_ID &old_ext_id, INT_ID &old_int_id, ACE_RB_Tree_Node *&entry); /// Locate @a ext_id and pass out parameter via @a int_id. If found, /// return 0, returns -1 if not found. int find (const EXT_ID &ext_id, INT_ID &int_id); /// Locate @a ext_id and pass out parameter via @a entry. If found, /// return 0, returns -1 if not found. int find (const EXT_ID &ext_id, ACE_RB_Tree_Node *&entry); /** * Unbind (remove) the @a ext_id from the tree. Don't return the * @a int_id to the caller (this is useful for collections where the * @c int_ids are *not* dynamically allocated...) */ int unbind (const EXT_ID &ext_id); /// Break any association of @a ext_id. Returns the value of @a int_id /// in case the caller needs to deallocate memory. int unbind (const EXT_ID &ext_id, INT_ID &int_id); /** * Remove entry from tree. This method should be used with *extreme* * caution, and only for optimization purposes. The node being passed * in had better have been allocated by the tree that is unbinding it. */ int unbind (ACE_RB_Tree_Node *entry); // = Public helper methods. /// Returns the current number of nodes in the tree. size_t current_size () const; /// Assignment operator. void operator= (const ACE_RB_Tree &rbt); /** * Returns a reference to the underlying . This makes it * possible to acquire the lock explicitly, which can be useful in * some cases if you instantiate the ACE_Atomic_Op with an * ACE_Recursive_Mutex or ACE_Process_Mutex, or if you need to * guard the state of an iterator. * @note The right name would be , but HP/C++ will choke on that! */ ACE_LOCK &mutex (); /// Dump the state of an object. void dump () const; // = STL styled iterator factory functions. /// Return forward iterator positioned at first node in tree. ACE_RB_Tree_Iterator begin (); /// Return forward iterator positioned at last node in tree. ACE_RB_Tree_Iterator end (); /// Return reverse iterator positioned at last node in tree. ACE_RB_Tree_Reverse_Iterator rbegin (); /// Return reverse iterator positioned at first node in tree. ACE_RB_Tree_Reverse_Iterator rend (); /// Recursively tests the invariant red-black properties at each /// node of the tree. Returns 0 if invariant holds, else -1. /// This method is computationally expensive, and should only be /// called for testing purposes, and not in code that depends on the /// algorithmic complexity bounds provided by the other methods. int test_invariant (); // = DEPRECATED methods. // Please migrate your code to use the new methods instead /** * Returns a pointer to the item corresponding to the * given key, or 0 if it cannot find the key in the tree. * * @deprecated signature will change to become * int find (const EXT_ID &ext_id); which will return * 0 if the @a ext_id is in the tree, otherwise -1. */ INT_ID* find (const EXT_ID &k); /** * 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 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. * @deprecated */ INT_ID* insert (const EXT_ID &k, const INT_ID &t); /** * 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. * @deprecated */ int remove (const EXT_ID &k); /// @deprecated /// Destroys all nodes and sets the root pointer null. void clear (); /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; protected: /// Reinitialize constructor. /** * This constructor is used to provide a valid vtable and allocator * if the tree is reconstructed from shared memory. Constructor * used by the derived class that has an allocator */ ACE_RB_Tree (void *location, ACE_Allocator *alloc); // = Protected methods. These should only be called with locks held. /// Recursively tests the invariant red-black properties at each /// node of the tree. Returns 0 if invariant holds, else -1. int test_invariant_recurse (ACE_RB_Tree_Node * x, int & expected_black_height, int measured_black_height); /// Method for right rotation of the tree about a given node. void RB_rotate_right (ACE_RB_Tree_Node * x); /// Method for left rotation of the tree about a given node. void RB_rotate_left (ACE_RB_Tree_Node * x); /// Method for restoring Red-Black properties after deletion. void RB_delete_fixup (ACE_RB_Tree_Node * x, ACE_RB_Tree_Node * parent); /// Method to find the successor node of the given node in the tree. ACE_RB_Tree_Node * RB_tree_successor (ACE_RB_Tree_Node *x) const; /// Method to find the predecessor node of the given node in the /// tree. ACE_RB_Tree_Node * RB_tree_predecessor (ACE_RB_Tree_Node *x) const; /// Method to find the minimum node of the subtree rooted at the /// given node. ACE_RB_Tree_Node * RB_tree_minimum (ACE_RB_Tree_Node *x) const; /// Method to find the maximum node of the subtree rooted at the /// given node. ACE_RB_Tree_Node * RB_tree_maximum (ACE_RB_Tree_Node *x) const; /** * Returns 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. * It stores the result of the search in the result argument: * LEFT if the node is to the left of the node to be inserted, * RIGHT if the node is to the right of the node to be inserted, * or EXACT if an exactly matching node already exists. */ ACE_RB_Tree_Node *find_node (const EXT_ID &k, ACE_RB_Tree_Base::RB_SearchResult &result); /// Rebalance the tree after insertion of a node. void RB_rebalance (ACE_RB_Tree_Node * x); /// Delete children (left and right) of the node. Must be called with /// lock held. void delete_children_i (ACE_RB_Tree_Node *parent); /// Close down an RB_Tree. this method should /// only be called with locks already held. int close_i (); /** * Retrieves a pointer to the item corresponding to the * given key. If find_exact==1, find the exact match node, * otherwise just find a match node * Returns 0 for success, or -1 if it cannot find the key in the tree. */ int find_i (const EXT_ID &ext_id, ACE_RB_Tree_Node* &entry, int find_exact = 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. The default implementation also requires that * the key type support well defined < semantics. 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. */ INT_ID* insert_i (const EXT_ID &k, const INT_ID &t); /** * 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. */ int insert_i (const EXT_ID &k, const INT_ID &t, ACE_RB_Tree_Node *&entry); /** * 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. Returns the stored internal id in the second argument. */ int remove_i (const EXT_ID &k, INT_ID &i); /// Removes the item associated with the given key from the tree and /// destroys it. int remove_i (ACE_RB_Tree_Node *z); /// Recursive function to dump the state of an object. void dump_i (ACE_RB_Tree_Node *node) const; /// Function to dump node contents. Does nothing in its /// basic form, but template specialization can be used to /// provide definitions for various EXT_ID and INT_ID types. void dump_node_i (ACE_RB_Tree_Node &node) const; /// Less than comparison function for keys, using comparison functor. int lessthan (const EXT_ID &k1, const EXT_ID &k2); private: // = Private members. /// Synchronization variable for the MT_SAFE ACE_RB_Tree. ACE_LOCK lock_; /// The root of the tree. ACE_RB_Tree_Node *root_; /// Comparison functor for comparing nodes in the tree. COMPARE_KEYS compare_keys_; /// The current number of nodes in the tree. size_t current_size_; }; /** * @class ACE_RB_Tree_Iterator_Base * * @brief Implements a common base class for iterators for a Red-Black Tree ADT. */ template class ACE_RB_Tree_Iterator_Base { public: /// Copy constructor. ACE_RB_Tree_Iterator_Base (const ACE_RB_Tree_Iterator_Base &iter); /// Assignment operator: copies both the tree reference and the position in the tree. void operator= (const ACE_RB_Tree_Iterator_Base &iter); // = Iteration methods. /// Returns 1 when the iteration has completed, otherwise 0. int done () const; /// STL-like iterator dereference operator: returns a reference /// to the node underneath the iterator. ACE_RB_Tree_Node & operator* () const; /// STL-like iterator dereference operator: returns a pointer /// to the node underneath the iterator. ACE_RB_Tree_Node * operator-> () const; /// Returns a const reference to the tree over which we're iterating. const ACE_RB_Tree &tree (); /// Comparison operator: returns 1 if both iterators point to the same position, otherwise 0. bool operator== (const ACE_RB_Tree_Iterator_Base &) const; /// Comparison operator: returns 1 if the iterators point to different positions, otherwise 0. bool operator!= (const ACE_RB_Tree_Iterator_Base &) const; /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; protected: /// Create the singular iterator. No valid iterator can be equal to /// it, it is illegal to dereference a singular iterator, etc. etc. ACE_RB_Tree_Iterator_Base (); /** * Constructor. Takes an ACE_RB_Tree over which to iterate, and * an integer indicating (if non-zero) to position the iterator * at the first element in the tree (if this integer is 0, the * iterator is positioned at the last element in the tree). */ ACE_RB_Tree_Iterator_Base (const ACE_RB_Tree &tree, int set_first); /** * Constructor. Takes an ACE_RB_Tree over which to iterate, and * a pointer to a node in the tree. */ ACE_RB_Tree_Iterator_Base (const ACE_RB_Tree &tree, ACE_RB_Tree_Node* entry); /** * Constructor. Takes an ACE_RB_Tree over which to iterate, and a key. * The key must come first to distinguish the case of EXT_ID == int. */ ACE_RB_Tree_Iterator_Base (const EXT_ID& key, ACE_RB_Tree &tree); /// Destructor. ~ACE_RB_Tree_Iterator_Base (); // = Internal methods /// Move forward by one element in the tree. Returns 0 when /// there are no more elements in the tree, otherwise 1. int forward_i (); /// Move back by one element in the tree. Returns 0 when /// there are no more elements in the tree, otherwise 1. int reverse_i (); /// Dump the state of an object. void dump_i () const; // = Protected members. /// Reference to the ACE_RB_Tree over which we're iterating. const ACE_RB_Tree *tree_; /// Pointer to the node currently under the iterator. ACE_RB_Tree_Node *node_; }; /** * @class ACE_RB_Tree_Iterator * * @brief Implements an iterator for a Red-Black Tree ADT. */ template class ACE_RB_Tree_Iterator : public ACE_RB_Tree_Iterator_Base { public: /** * Create the singular iterator. * It is illegal to deference the iterator, no valid iterator is * equal to a singular iterator, etc. etc. */ ACE_RB_Tree_Iterator (); /** * Constructor. Takes an ACE_RB_Tree over which to iterate, and * an integer indicating (if non-zero) to position the iterator * at the first element in the tree (if this integer is 0, the * iterator is positioned at the last element in the tree). */ ACE_RB_Tree_Iterator (const ACE_RB_Tree &tree, int set_first = 1); /** * Constructor. Takes an ACE_RB_Tree over which to iterate * and a pointer to a node in the tree. */ ACE_RB_Tree_Iterator (const ACE_RB_Tree &tree, ACE_RB_Tree_Node* entry); /** * Constructor. Takes an ACE_RB_Tree over which to iterate, and a key; * the key comes first in order to distinguish the case of EXT_ID == int. */ ACE_RB_Tree_Iterator (const EXT_ID &key, ACE_RB_Tree &tree); /// Destructor. ~ACE_RB_Tree_Iterator (); // = ACE-style iteration methods. /// Move forward by one element in the tree. Returns /// 0 when all elements have been seen, else 1. int advance (); /// Dump the state of an object. void dump () const; // = STL-style iteration methods. /// Prefix advance. ACE_RB_Tree_Iterator & operator++ (); /// Postfix advance. ACE_RB_Tree_Iterator operator++ (int); /// Prefix reverse. ACE_RB_Tree_Iterator & operator-- (); /// Postfix reverse. ACE_RB_Tree_Iterator operator-- (int); /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; /** * Passes back the under the iterator. Returns 0 if * the iteration has completed, otherwise 1. This method must * be declared and defined in both the derived forward and * reverse iterator classes rather than in the base iterator * class because of a method signature resolution problem * caused by the existence of the deprecated next () * method in the derived forward iterator class. When that * deprecated method is removed, this method should be removed * from the derived classes and placed in the base class. */ int next (ACE_RB_Tree_Node *&next_entry) const; // = DEPRECATED methods. Please migrate your code to use the new methods instead /// @deprecated /// Accessor for key of node under iterator (if any). EXT_ID *key (); /// @deprecated /// Accessor for item of node under iterator (if any). INT_ID *item (); /// @deprecated /// Move to the first item in the iteration (and in the tree). int first (); /// @deprecated /// Move to the last item in the iteration (and in the tree). int last (); /// @deprecated /// Move to the next item in the iteration (and in the tree). int next (); /// @deprecated /// Move to the previous item in the iteration (and in the tree). int previous (); /** * @deprecated: use the base class method instead. * Returns 0 if the iterator is positioned over a valid ACE_RB_Tree * node, returns 1 if not. */ int is_done (); }; /** * @class ACE_RB_Tree_Reverse_Iterator * * @brief Implements a reverse iterator for a Red-Black Tree ADT. */ template class ACE_RB_Tree_Reverse_Iterator : public ACE_RB_Tree_Iterator_Base { public: /** * Create the singular iterator. * It is illegal to deference the iterator, no valid iterator is * equal to a singular iterator, etc. etc. */ ACE_RB_Tree_Reverse_Iterator (); /** * Constructor. Takes an ACE_RB_Tree over which to iterate, and * an integer indicating (if non-zero) to position the iterator * at the last element in the tree (if this integer is 0, the * iterator is positioned at the first element in the tree). */ ACE_RB_Tree_Reverse_Iterator (const ACE_RB_Tree &tree, int set_last = 1); /** * Constructor. Takes an ACE_RB_Tree over which to iterate, and * a point to a node in the tree. */ ACE_RB_Tree_Reverse_Iterator (const ACE_RB_Tree &tree, ACE_RB_Tree_Node* entry); /** * Constructor. Takes an ACE_RB_Tree over which to iterate, and a key; * the key comes first in order to distinguish the case of EXT_ID == int. */ ACE_RB_Tree_Reverse_Iterator (const EXT_ID &key, ACE_RB_Tree &tree); /// Destructor. ~ACE_RB_Tree_Reverse_Iterator (); // = ACE-style iteration methods. /// Move forward by one element in the tree. Returns /// 0 when all elements have been seen, else 1. int advance (); /// Dump the state of an object. void dump () const; // = STL-style iteration methods. /// Prefix advance. ACE_RB_Tree_Reverse_Iterator & operator++ (); /// Postfix advance. ACE_RB_Tree_Reverse_Iterator operator++ (int); /// Prefix reverse. ACE_RB_Tree_Reverse_Iterator & operator-- (); /// Postfix reverse. ACE_RB_Tree_Reverse_Iterator operator-- (int); /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; /** * Passes back the under the iterator. Returns 0 if * the iteration has completed, otherwise 1. This method must * be declared and defined in both the derived forward and * reverse iterator classes rather than in the base iterator * class because of a method signature resolution problem * caused by the existence of the deprecated next () * method in the derived forward iterator class. When that * deprecated method is removed, this method should be removed * from the derived classes and placed in the base class. */ int next (ACE_RB_Tree_Node *&next_entry) const; }; ACE_END_VERSIONED_NAMESPACE_DECL #if defined (__ACE_INLINE__) #include "ace/RB_Tree.inl" #endif /* __ACE_INLINE__ */ #include "ace/RB_Tree.cpp" #include /**/ "ace/post.h" #endif /* ! defined (ACE_RB_TREE_H) */