/* -*- C++ -*- */ //============================================================================= /** * @file Hash_Map_Manager_T.h * * $Id$ * * @author Doug Schmidt */ //============================================================================= #ifndef ACE_HASH_MAP_MANAGER_T_H #define ACE_HASH_MAP_MANAGER_T_H #include "ace/pre.h" #include "ace/OS.h" #include "ace/Functor.h" #include "ace/Log_Msg.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ /** * @class ACE_Hash_Map_Entry * * @brief Define an entry in the hash table. */ template class ACE_Hash_Map_Entry { public: // = Initialization and termination methods. /// Constructor. ACE_Hash_Map_Entry (const EXT_ID &ext_id, const INT_ID &int_id, ACE_Hash_Map_Entry *next = 0, ACE_Hash_Map_Entry *prev = 0); /// Constructor. ACE_Hash_Map_Entry (ACE_Hash_Map_Entry *next, ACE_Hash_Map_Entry *prev); # if ! defined (ACE_HAS_BROKEN_NOOP_DTORS) /// Destructor. ~ACE_Hash_Map_Entry (void); #endif /* ! defined (ACE_HAS_BROKEN_NOOP_DTORS) */ /// Key used to look up an entry. EXT_ID ext_id_; /// The contents of the entry itself. INT_ID int_id_; /// Pointer to the next item in the bucket of overflow nodes. ACE_Hash_Map_Entry *next_; /// Pointer to the prev item in the bucket of overflow nodes. ACE_Hash_Map_Entry *prev_; /// Dump the state of an object. void dump (void) const; }; // Forward decl. template class ACE_Hash_Map_Iterator_Base_Ex; // Forward decl. template class ACE_Hash_Map_Iterator_Ex; // Forward decl. template class ACE_Hash_Map_Reverse_Iterator_Ex; // Forward decl. template class ACE_Hash_Map_Bucket_Iterator; // Forward decl. class ACE_Allocator; /** * @class ACE_Hash_Map_Manager_Ex * * @brief Define a map abstraction that efficiently associates * s with s. * * This implementation of a map uses a hash table. Key hashing * is achieved through the HASH_KEY object and key comparison is * achieved through the COMPARE_KEYS object. * This class uses an to allocate memory. The * user can make this a persistent class by providing an * with a persistable memory pool. */ template class ACE_Hash_Map_Manager_Ex { public: friend class ACE_Hash_Map_Iterator_Base_Ex; friend class ACE_Hash_Map_Iterator_Ex; friend class ACE_Hash_Map_Reverse_Iterator_Ex; friend class ACE_Hash_Map_Bucket_Iterator; typedef EXT_ID KEY; typedef INT_ID VALUE; typedef ACE_Hash_Map_Entry ENTRY; // = ACE-style iterator typedefs. typedef ACE_Hash_Map_Iterator_Ex ITERATOR; typedef ACE_Hash_Map_Reverse_Iterator_Ex REVERSE_ITERATOR; // = STL-style iterator typedefs. typedef ACE_Hash_Map_Iterator_Ex iterator; typedef ACE_Hash_Map_Reverse_Iterator_Ex reverse_iterator; // = Initialization and termination methods. /// Initialize a with default size. ACE_Hash_Map_Manager_Ex (ACE_Allocator *alloc = 0); /// Initialize a with size . ACE_Hash_Map_Manager_Ex (size_t size, ACE_Allocator *alloc = 0); /// Initialize a with elements. int open (size_t size = ACE_DEFAULT_MAP_SIZE, ACE_Allocator *alloc = 0); /// Close down a and release dynamically allocated /// resources. int close (void); /// Removes all the entries in . int unbind_all (void); /// Initialize a with size . ~ACE_Hash_Map_Manager_Ex (void); /** * Associate with . If is already in the * map 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 map 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_Hash_Map_Entry *&entry); /** * Associate with if and only if is not * in the map. If is already in the map then the * parameter is assigned the existing value in the map. 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 map 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_Hash_Map_Entry *&entry); /** * Reassociate with . If is not in the * map 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 map 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_Hash_Map_Entry *&entry); /** * Associate with . If is not in the map * then behaves just like . Otherwise, store the old value of * 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 map 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_Hash_Map_Entry *&entry); /** * Associate with . If is not in the map * then behaves just like . Otherwise, store the old values * of and 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 map 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_Hash_Map_Entry *&entry); /// Locate and pass out parameter via . /// Return 0 if found, returns -1 if not found. int find (const EXT_ID &ext_id, INT_ID &int_id) const; /// Returns 0 if the is in the mapping, otherwise -1. int find (const EXT_ID &ext_id) const; /// Locate and pass out parameter via . If found, /// return 0, returns -1 if not found. int find (const EXT_ID &ext_id, ACE_Hash_Map_Entry *&entry) const; /** * Unbind (remove) the from the map. Don't return the * to the caller (this is useful for collections where the * s are *not* dynamically allocated...) */ int unbind (const EXT_ID &ext_id); /// Break any association of . Returns the value of /// in case the caller needs to deallocate memory. int unbind (const EXT_ID &ext_id, INT_ID &int_id); /// Remove entry from map. int unbind (ACE_Hash_Map_Entry *entry); /// Return the current size of the map. size_t current_size (void) const; /// Return the total size of the map. size_t total_size (void) const; /** * 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 with an * or , 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 (void); /// Dump the state of an object. void dump (void) const; // = STL styled iterator factory functions. /// Return forward iterator. ACE_Hash_Map_Iterator_Ex begin (void); ACE_Hash_Map_Iterator_Ex end (void); /// Return reverse iterator. ACE_Hash_Map_Reverse_Iterator_Ex rbegin (void); ACE_Hash_Map_Reverse_Iterator_Ex rend (void); protected: // = The following methods do the actual work. /// Returns 1 if == , else 0. This is defined as a /// separate method to facilitate template specialization. int equal (const EXT_ID &id1, const EXT_ID &id2); /// Compute the hash value of the . This is defined as a /// separate method to facilitate template specialization. u_long hash (const EXT_ID &ext_id); // = These methods assume locks are held by private methods. /// Performs bind. Must be called with locks held. int bind_i (const EXT_ID &ext_id, const INT_ID &int_id); /// Performs bind. Must be called with locks held. int bind_i (const EXT_ID &ext_id, const INT_ID &int_id, ACE_Hash_Map_Entry *&entry); /// Performs trybind. Must be called with locks held. int trybind_i (const EXT_ID &ext_id, INT_ID &int_id); /// Performs trybind. Must be called with locks held. int trybind_i (const EXT_ID &ext_id, INT_ID &int_id, ACE_Hash_Map_Entry *&entry); /// Performs rebind. Must be called with locks held. int rebind_i (const EXT_ID &ext_id, const INT_ID &int_id); /// Performs rebind. Must be called with locks held. int rebind_i (const EXT_ID &ext_id, const INT_ID &int_id, ACE_Hash_Map_Entry *&entry); /// Performs rebind. Must be called with locks held. int rebind_i (const EXT_ID &ext_id, const INT_ID &int_id, INT_ID &old_int_id); /// Performs rebind. Must be called with locks held. int rebind_i (const EXT_ID &ext_id, const INT_ID &int_id, INT_ID &old_int_id, ACE_Hash_Map_Entry *&entry); /// Performs rebind. Must be called with locks held. int rebind_i (const EXT_ID &ext_id, const INT_ID &int_id, EXT_ID &old_ext_id, INT_ID &old_int_id); /// Performs rebind. Must be called with locks held. int rebind_i (const EXT_ID &ext_id, const INT_ID &int_id, EXT_ID &old_ext_id, INT_ID &old_int_id, ACE_Hash_Map_Entry *&entry); /// Performs a find of using as the key. Must be /// called with locks held. int find_i (const EXT_ID &ext_id, INT_ID &int_id); /// Performs a find using as the key. Must be called with /// locks held. int find_i (const EXT_ID &ext_id); /// Performs a find using as the key. Must be called with /// locks held. int find_i (const EXT_ID &ext_id, ACE_Hash_Map_Entry *&entry); /// Performs unbind. Must be called with locks held. int unbind_i (const EXT_ID &ext_id, INT_ID &int_id); /// Performs unbind. Must be called with locks held. int unbind_i (const EXT_ID &ext_id); /// Performs unbind. Must be called with locks held. int unbind_i (ACE_Hash_Map_Entry *entry); /** * Resize the map. Must be called with locks held. Note, that this * method should never be called more than once or else all the * hashing will get screwed up as the size will change. */ int create_buckets (size_t size); /// Close down a . Must be called with /// locks held. int close_i (void); /// Removes all the entries in . Must be called with /// locks held. int unbind_all_i (void); /// Pointer to a memory allocator. ACE_Allocator *allocator_; /// Synchronization variable for the MT_SAFE . ACE_LOCK lock_; /// Function object used for hashing keys. HASH_KEY hash_key_; /// Function object used for comparing keys. COMPARE_KEYS compare_keys_; private: /// Returns the that corresponds to . int shared_find (const EXT_ID &ext_id, ACE_Hash_Map_Entry *&entry, u_long &loc); /** * Array of *s, each of which points to an * that serves as the beginning of a linked * list of s that hash to that bucket. */ ACE_Hash_Map_Entry *table_; /// Total size of the hash table. size_t total_size_; /// Current number of entries in the table (note that this can be /// larger than due to the bucket chaining). size_t cur_size_; }; /** * @class ACE_Hash_Map_Iterator_Base_Ex * * @brief Base iterator for the * * This class factors out common code from its templatized * subclasses. */ template class ACE_Hash_Map_Iterator_Base_Ex { public: // = Initialization method. /// Contructor. If head != 0, the iterator constructed is positioned /// at the head of the map, it is positioned at the end otherwise. ACE_Hash_Map_Iterator_Base_Ex (ACE_Hash_Map_Manager_Ex &mm, int head); // = ITERATION methods. /// Pass back the next that hasn't been seen in the Set. /// Returns 0 when all items have been seen, else 1. int next (ACE_Hash_Map_Entry *&next_entry) const; /// Returns 1 when all items have been seen, else 0. int done (void) const; /// Returns a reference to the interal element is pointing to. ACE_Hash_Map_Entry& operator* (void) const; /// Returns reference the Hash_Map_Manager_Ex that is being iterated /// over. ACE_Hash_Map_Manager_Ex& map (void); /// Check if two iterators point to the same position int operator== (const ACE_Hash_Map_Iterator_Base_Ex &) const; int operator!= (const ACE_Hash_Map_Iterator_Base_Ex &) const; /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; protected: /// Move forward by one element in the set. Returns 0 when there's /// no more item in the set after the current items, else 1. int forward_i (void); /// Move backward by one element in the set. Returns 0 when there's /// no more item in the set before the current item, else 1. int reverse_i (void); /// Dump the state of an object. void dump_i (void) const; /// Map we are iterating over. ACE_Hash_Map_Manager_Ex *map_man_; /// Keeps track of how far we've advanced in the table. ssize_t index_; /// Keeps track of how far we've advanced in a linked list in each /// table slot. ACE_Hash_Map_Entry *next_; }; /** * @class ACE_Hash_Map_Iterator_Ex * * @brief Forward iterator for the . * * This class does not perform any internal locking of the * it is iterating upon since locking is * inherently inefficient and/or error-prone within an STL-style * iterator. If you require locking, you can explicitly use an * or on the 's * internal lock, which is accessible via its method. */ template class ACE_Hash_Map_Iterator_Ex : public ACE_Hash_Map_Iterator_Base_Ex { public: // = Initialization method. ACE_Hash_Map_Iterator_Ex (ACE_Hash_Map_Manager_Ex &mm, int tail = 0); // = Iteration methods. /// Move forward by one element in the set. Returns 0 when all the /// items in the set have been seen, else 1. int advance (void); /// Dump the state of an object. void dump (void) const; // = STL styled iteration, compare, and reference functions. /// Prefix advance. ACE_Hash_Map_Iterator_Ex &operator++ (void); /// Postfix advance. ACE_Hash_Map_Iterator_Ex operator++ (int); /// Prefix reverse. ACE_Hash_Map_Iterator_Ex &operator-- (void); /// Postfix reverse. ACE_Hash_Map_Iterator_Ex operator-- (int); /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; }; /** * @class ACE_Hash_Map_Bucket_Iterator * * @brief Forward iterator for the which only * traverses a particular bucket. The particular bucket is * specified by the parameter specified in the * constructor. * * This class does not perform any internal locking of the * it is iterating upon since locking * is inherently inefficient and/or error-prone within an * STL-style iterator. If you require locking, you can * explicitly use an or on the * 's internal lock, which is * accessible via its method. * Note that this iterator cannot be created by calling a method * on the map, since this would require */ template class ACE_Hash_Map_Bucket_Iterator { public: // = Initialization method. ACE_Hash_Map_Bucket_Iterator (ACE_Hash_Map_Manager_Ex &mm, const EXT_ID &ext_id, int tail = 0); // = STL styled iteration, compare, and reference functions. /// Prefix advance. ACE_Hash_Map_Bucket_Iterator &operator++ (void); /// Postfix advance. ACE_Hash_Map_Bucket_Iterator operator++ (int); /// Prefix reverse. ACE_Hash_Map_Bucket_Iterator &operator-- (void); /// Postfix reverse. ACE_Hash_Map_Bucket_Iterator operator-- (int); /// Returns a reference to the interal element is pointing to. ACE_Hash_Map_Entry& operator* (void) const; /// Returns reference the Hash_Map_Manager_Ex that is being iterated /// over. ACE_Hash_Map_Manager_Ex& map (void); /// Check if two iterators point to the same position int operator== (const ACE_Hash_Map_Bucket_Iterator &) const; int operator!= (const ACE_Hash_Map_Bucket_Iterator &) const; protected: /// Move forward by one element in the set. Returns 0 when there's /// no more item in the set after the current items, else 1. int forward_i (void); /// Move backward by one element in the set. Returns 0 when there's /// no more item in the set before the current item, else 1. int reverse_i (void); /// Map we are iterating over. ACE_Hash_Map_Manager_Ex *map_man_; /// Keeps track of how far we've advanced in the table. ssize_t index_; /// Keeps track of how far we've advanced in a linked list in each /// table slot. ACE_Hash_Map_Entry *next_; }; /** * @class ACE_Hash_Map_Reverse_Iterator_Ex * * @brief Reverse iterator for the . * * This class does not perform any internal locking of the * it is iterating upon since locking is * inherently inefficient and/or error-prone within an STL-style * iterator. If you require locking, you can explicitly use an * or on the 's * internal lock, which is accessible via its method. */ template class ACE_Hash_Map_Reverse_Iterator_Ex : public ACE_Hash_Map_Iterator_Base_Ex { public: // = Initialization method. ACE_Hash_Map_Reverse_Iterator_Ex (ACE_Hash_Map_Manager_Ex &mm, int head = 0); // = Iteration methods. /// Move forward by one element in the set. Returns 0 when all the /// items in the set have been seen, else 1. int advance (void); /// Dump the state of an object. void dump (void) const; // = STL styled iteration, compare, and reference functions. /// Prefix reverse. ACE_Hash_Map_Reverse_Iterator_Ex &operator++ (void); /// Postfix reverse. ACE_Hash_Map_Reverse_Iterator_Ex operator++ (int); /// Prefix advance. ACE_Hash_Map_Reverse_Iterator_Ex &operator-- (void); /// Postfix advance. ACE_Hash_Map_Reverse_Iterator_Ex operator-- (int); /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; }; /** * @class ACE_Hash_Map_Manager * * @brief Wrapper for backward compatibility. * * This implementation of a map uses a hash table. This class * expects that the contains a method called . * In addition, the must support . Both of * these constraints can be alleviated via template * specialization, as shown in the $ACE_ROOT/tests/Conn_Test.cpp * test. */ template class ACE_Hash_Map_Manager : public ACE_Hash_Map_Manager_Ex, ACE_Equal_To, ACE_LOCK> { public: /// Initialize a with default size. ACE_Hash_Map_Manager (ACE_Allocator *alloc = 0); /// Initialize a with size . ACE_Hash_Map_Manager (size_t size, ACE_Allocator *alloc = 0); // = The following two are necessary for template specialization of // ACE_Hash_Map_Manager to work. int equal (const EXT_ID &id1, const EXT_ID &id2); u_long hash (const EXT_ID &ext_id); }; /** * @class ACE_Hash_Map_Iterator * * @brief Wrapper for backward compatibility. */ template class ACE_Hash_Map_Iterator : public ACE_Hash_Map_Iterator_Ex, ACE_Equal_To, ACE_LOCK> { public: // = Initialization method. /// Construct from map ACE_Hash_Map_Iterator (ACE_Hash_Map_Manager &mm, int tail = 0); /// Construct from base ACE_Hash_Map_Iterator (const ACE_Hash_Map_Iterator_Ex, ACE_Equal_To, ACE_LOCK> &base); /// Assignment from base ACE_Hash_Map_Iterator & operator= (const ACE_Hash_Map_Iterator_Ex, ACE_Equal_To, ACE_LOCK> &base); }; /** * @class ACE_Hash_Map_Reverse_Iterator * * @brief Wrapper for backward compatibility. */ template class ACE_Hash_Map_Reverse_Iterator : public ACE_Hash_Map_Reverse_Iterator_Ex, ACE_Equal_To, ACE_LOCK> { public: // = Initialization method. ACE_Hash_Map_Reverse_Iterator (ACE_Hash_Map_Manager &mm, int head = 0); /// Construct from base ACE_Hash_Map_Reverse_Iterator (const ACE_Hash_Map_Reverse_Iterator_Ex, ACE_Equal_To, ACE_LOCK> &base); /// Assignment from base ACE_Hash_Map_Reverse_Iterator & operator= (const ACE_Hash_Map_Reverse_Iterator_Ex, ACE_Equal_To, ACE_LOCK> &base); }; #if defined (__ACE_INLINE__) // Include ace/Hash_Map_Manager_T.i on all platforms excluding SunCC. // This nonsense is necessary since SunCC (version 4.2) cannot inline // the code in ace/Hash_Map_Manager_T.i (with the fast option). # if !(defined (__SUNPRO_CC) && (__SUNPRO_CC == 0x420)) # include "ace/Hash_Map_Manager_T.i" # endif /* ! __SUNPRO_CC */ #endif /* __ACE_INLINE__ */ #if defined (ACE_TEMPLATES_REQUIRE_SOURCE) #include "ace/Hash_Map_Manager_T.cpp" #endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ #if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) #pragma implementation ("Hash_Map_Manager_T.cpp") #endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ #include "ace/post.h" #endif /* ACE_HASH_MAP_MANAGER_T_H */