// -*- C++ -*- //============================================================================= /** * @file Map_Manager.h * * @author Douglas C. Schmidt */ //============================================================================= #ifndef ACE_MAP_MANAGER_H #define ACE_MAP_MANAGER_H #include /**/ "ace/pre.h" #include /**/ "ace/config-all.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "ace/Basic_Types.h" #include "ace/Global_Macros.h" #include "ace/Default_Constants.h" ACE_BEGIN_VERSIONED_NAMESPACE_DECL // Forward declaration. class ACE_Allocator; /** * @class ACE_Map_Entry * * @brief An entry in the Map. */ template class ACE_Map_Entry { public: /// Initialize member variables. ACE_Map_Entry () = default; /// We need this destructor to keep some compilers from complaining. /// It's just a no-op, however. ~ACE_Map_Entry () = default; /// Key used to look up an entry. EXT_ID ext_id_ {}; /// The contents of the entry itself. INT_ID int_id_ {}; /// Dump the state of an object. void dump () const; /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; // = These are really private, but unfortunately template friends // are not portable. /// Get next entry. ACE_UINT32 next () const; /// Set next entry. void next (ACE_UINT32 n); /// Get prev entry. ACE_UINT32 prev () const; /// Set prev entry. void prev (ACE_UINT32 p); /// Keeps track of the next entry. ACE_UINT32 next_ {}; /// Keeps track of the previous entry. ACE_UINT32 prev_ {}; #if defined (ACE_HAS_LAZY_MAP_MANAGER) /// Is this entry free? bool free_ {true}; #endif /* ACE_HAS_LAZY_MAP_MANAGER */ }; // Forward decl. template class ACE_Map_Iterator_Base; // Forward decl. template class ACE_Map_Const_Iterator_Base; // Forward decl. template class ACE_Map_Iterator; // Forward decl. template class ACE_Map_Const_Iterator; // Forward decl. template class ACE_Map_Reverse_Iterator; /** * @class ACE_Map_Manager * * @brief * Define a map abstraction that associates EXT_IDs with * INT_IDs. * * The EXT_ID must support @c operator==. This constraint can * be alleviated via template specialization, as shown in the * $ACE_ROOT/tests/Conn_Test.cpp test. * This class uses an ACE_Allocator to allocate memory. The * user can make this a persistant class by providing an * ACE_Allocator with a persistable memory pool. * This implementation of a map uses an array, which is searched * linearly. For more efficient searching you should use the * ACE_Hash_Map_Manager. */ template class ACE_Map_Manager { public: friend class ACE_Map_Iterator_Base; friend class ACE_Map_Const_Iterator_Base; friend class ACE_Map_Iterator; friend class ACE_Map_Const_Iterator; friend class ACE_Map_Reverse_Iterator; // = Traits. typedef EXT_ID KEY; typedef INT_ID VALUE; typedef ACE_LOCK lock_type; typedef ACE_Map_Entry ENTRY; typedef ACE_Map_Iterator ITERATOR; typedef ACE_Map_Const_Iterator CONST_ITERATOR; typedef ACE_Map_Reverse_Iterator REVERSE_ITERATOR; typedef ACE_Map_Iterator iterator; typedef ACE_Map_Const_Iterator const_iterator; typedef ACE_Map_Reverse_Iterator reverse_iterator; /// Initialize a ACE_Map_Manager with the ACE_DEFAULT_MAP_SIZE. ACE_Map_Manager (ACE_Allocator *alloc = nullptr); /// Initialize a ACE_Map_Manager with @a size entries. ACE_Map_Manager (size_t size, ACE_Allocator *alloc = nullptr); /// Initialize a ACE_Map_Manager with size @a length. int open (size_t length = ACE_DEFAULT_MAP_SIZE, ACE_Allocator *alloc = nullptr); /// Close down a ACE_Map_Manager and release dynamically allocated /// resources. int close (); /// Close down a ACE_Map_Manager and release dynamically allocated /// resources. ~ACE_Map_Manager (); /** * Associate @a ext_id with @a int_id. If @a ext_id is already in the * map then the ACE_Map_Entry is not changed. * @retval 0 If a new entry is bound successfully. * @retval 1 If an attempt is made to bind an existing entry. * @retval -1 If failures occur. */ int bind (const EXT_ID &ext_id, const INT_ID &int_id); /** * Reassociate @a ext_id with @a int_id. If @a ext_id is not in the * map then behaves just like bind(). 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. * @retval 0 If a new entry is bound successfully. * @retval 1 If an existing entry was rebound. * @retval -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); /** * Reassociate @a ext_id with @a int_id. If @a ext_id is not in the * map then behaves just like bind(). Otherwise, store the old * values of @a int_id into the "out" parameter and rebind the new * parameters. * @retval 0 If a new entry is bound successfully. * @retval 1 If an existing entry was rebound. * @retval -1 If failures occur. */ int rebind (const EXT_ID &ext_id, const INT_ID &int_id, INT_ID &old_int_id); /// Reassociate @a ext_id with @a int_id. Old values in the map are /// ignored. int rebind (const EXT_ID &ext_id, const INT_ID &int_id); /** * Associate @a ext_id with @a int_id if and only if @a ext_id is not * in the map. If @a ext_id is already in the map then the @a int_id * parameter is overwritten with the existing value in the map * @retval 0 If a new entry is bound successfully. * @retval 1 If an attempt is made to bind an existing entry. * @retval -1 If failures occur. */ int trybind (const EXT_ID &ext_id, INT_ID &int_id); /** * Locate @a ext_id and pass out parameter via @a int_id. * @retval 0 If found. * @retval -1 If not found. */ int find (const EXT_ID &ext_id, INT_ID &int_id) const; /// Returns 0 if the @a ext_id is in the mapping, otherwise -1. int find (const EXT_ID &ext_id) const; /** * Unbind (remove) the @a ext_id from the map. Don't return the * @a int_id to the caller (this is useful for collections where the * @a int_ids are *not* dynamically allocated...) Returns 0 if * successful, else -1. */ 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. Returns 0 if * successful, else -1. */ int unbind (const EXT_ID &ext_id, INT_ID &int_id); /** * Unbind all entires. */ void unbind_all (); /// Return the current size of the map. size_t current_size () const; /// Return the total size of the map. size_t total_size () const; /** * Returns a reference to the underlying ACE_LOCK. 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 lock, 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. ACE_Map_Iterator begin (); ACE_Map_Iterator end (); /// Return reverse iterator. ACE_Map_Reverse_Iterator rbegin (); ACE_Map_Reverse_Iterator rend (); /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; protected: // = The following methods do the actual work. // These methods assume that the locks are held by the private // methods. /// Performs the binding of @a ext_id to @a int_id. Must be called /// with locks held. int bind_i (const EXT_ID &ext_id, const INT_ID &int_id); /// Bind an entry (without finding first). Must be called with locks /// held. int shared_bind (const EXT_ID &ext_id, const INT_ID &int_id); /// Performs a rebinding of to @a int_id. Also, recovers old /// values. 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 a rebinding of to @a int_id. Also, recovers old /// values. 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 a rebinding of to @a int_id. Must be called /// with locks held. int rebind_i (const EXT_ID &ext_id, const INT_ID &int_id); /// Performs a conditional bind of @a int_id using @a ext_id as the /// key. Must be called with locks held. int trybind_i (const EXT_ID &ext_id, INT_ID &int_id); /// Performs a find of @a int_id using @a ext_id 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 @a ext_id as the key. Must be called with /// locks held. int find_and_return_index (const EXT_ID &ext_id, ACE_UINT32 &slot); /// Performs an unbind of @a int_id using @a ext_id as the key. Must /// be called with locks held. int unbind_i (const EXT_ID &ext_id, INT_ID &int_id); /// Performs an unbind using @a ext_id as the key. Must be called /// with locks held. int unbind_i (const EXT_ID &ext_id); /// Performs an unbind using @a ext_id as the key. Must be called /// with locks held. int unbind_and_return_index (const EXT_ID &ext_id, ACE_UINT32 &slot); /// Unbind @a slot. void unbind_slot (ACE_UINT32 slot); /// Resize the map. Must be called with locks held. int resize_i (ACE_UINT32 size); /// Close down a . Must be called with locks held. int close_i (); /// 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); /// This function returns the new size of the Map Manager. This /// function is called when we run out of room and need to resize. ACE_UINT32 new_size (); /// Explicitly call the destructors and free up the /// . void free_search_structure (); /// Id of the free list sentinel. ACE_UINT32 free_list_id () const; /// Id of the occupied list sentinel. ACE_UINT32 occupied_list_id () const; /// Finds the next free slot. int next_free (ACE_UINT32 &slot); /// Move from free list to occupied list. void move_from_free_list_to_occupied_list (ACE_UINT32 slot); /// Move from occupied list to free list. void move_from_occupied_list_to_free_list (ACE_UINT32 slot); #if defined (ACE_HAS_LAZY_MAP_MANAGER) /** * In the case of lazy map managers, the movement of free slots from * the occupied list to the free list is delayed until we run out of * free slots in the free list. This function goes through the * entire occupied list, moving free slots to the free list. */ void move_all_free_slots_from_occupied_list (void); #endif /* ACE_HAS_LAZY_MAP_MANAGER */ /// Move helper. void shared_move (ACE_UINT32 slot, ACE_Map_Entry ¤t_list, ACE_UINT32 current_list_id, ACE_Map_Entry &new_list, ACE_UINT32 new_list_id); /// Pointer to a memory allocator. ACE_Allocator *allocator_; /// Synchronization variable for the MT_SAFE ACE_Map_Manager. mutable ACE_LOCK lock_; /// Implement the Map as a resizeable array of ACE_Map_Entry. ACE_Map_Entry *search_structure_; /// Total number of elements in this->search_structure_. ACE_UINT32 total_size_; /// Current size of the map. ACE_UINT32 cur_size_; /// Free list. ACE_Map_Entry free_list_; /// Occupied list. ACE_Map_Entry occupied_list_; enum { /// Grow map exponentially up to 64K MAX_EXPONENTIAL = 64 * 1024, /// Afterwards grow in chunks of 32K LINEAR_INCREASE = 32 * 1024 }; private: // = Disallow these operations. void operator= (const ACE_Map_Manager &) = delete; ACE_Map_Manager (const ACE_Map_Manager &) = delete; }; /** * @class ACE_Map_Iterator_Base * * @brief Iterator for the ACE_Map_Manager. * * This class factors out common code from its templatized * subclasses. */ template class ACE_Map_Iterator_Base { public: /// Constructor. If head != 0, the iterator constructed is positioned /// at the head of the map, it is positioned at the end otherwise. ACE_Map_Iterator_Base (ACE_Map_Manager &mm); // = 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_Map_Entry *&next_entry) const; /// Returns 1 when all items have been seen, else 0. int done () const; /// Returns a reference to the interal element @c this is pointing to. ACE_Map_Entry& operator* () const; /// Returns reference the Map_Manager that is being iterated /// over. ACE_Map_Manager& map (); /// Check if two iterators point to the same position bool operator== (const ACE_Map_Iterator_Base &) const; bool operator!= (const ACE_Map_Iterator_Base &) 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 (); /// Move backware 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 (); /// Dump the state of an object. void dump_i () const; /// Map we are iterating over. ACE_Map_Manager *map_man_; /// Keeps track of how far we've advanced... ACE_UINT32 next_; }; /** * @class ACE_Map_Const_Iterator_Base * * @brief Const iterator for the ACE_Map_Manager. * * This class factors out common code from its templatized * subclasses. */ template class ACE_Map_Const_Iterator_Base { public: /// Constructor. If head != 0, the iterator constructed is positioned /// at the head of the map, it is positioned at the end otherwise. ACE_Map_Const_Iterator_Base (const ACE_Map_Manager &mm); // = 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_Map_Entry *&next_entry) const; /// Returns 1 when all items have been seen, else 0. int done () const; /// Returns a reference to the interal element @c this is pointing to. ACE_Map_Entry& operator* () const; /// Returns reference the Map_Manager that is being iterated /// over. const ACE_Map_Manager& map () const; /// Check if two iterators point to the same position bool operator== (const ACE_Map_Const_Iterator_Base &) const; bool operator!= (const ACE_Map_Const_Iterator_Base &) 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 (); /// Move backware 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 (); /// Dump the state of an object. void dump_i () const; /// Map we are iterating over. const ACE_Map_Manager *map_man_; /// Keeps track of how far we've advanced... ACE_UINT32 next_; }; /** * @class ACE_Map_Iterator * * @brief Forward iterator for the ACE_Map_Manager. * * This class does not perform any internal locking of the * ACE_Map_Manager 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 * ACE_GUARD or ACE_READ_GUARD on the ACE_Map_Manager's * internal lock, which is accessible via its mutex() method. */ template class ACE_Map_Iterator : public ACE_Map_Iterator_Base { public: ACE_Map_Iterator (ACE_Map_Manager &mm, int pass_end = 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 (); /// Dump the state of an object. void dump () const; // = STL styled iteration, compare, and reference functions. /// Prefix advance. ACE_Map_Iterator &operator++ (); /// Postfix advance. ACE_Map_Iterator operator++ (int); /// Prefix reverse. ACE_Map_Iterator &operator-- (); /// Postfix reverse. ACE_Map_Iterator operator-- (int); /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; }; /** * @class ACE_Map_Const_Iterator * * @brief Forward const iterator for the ACE_Map_Manager. * * This class does not perform any internal locking of the * ACE_Map_Manager 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 * ACE_GUARD or ACE_READ_GUARD on the ACE_Map_Manager's * internal lock, which is accessible via its mutex() method. */ template class ACE_Map_Const_Iterator : public ACE_Map_Const_Iterator_Base { public: ACE_Map_Const_Iterator (const ACE_Map_Manager &mm, int pass_end = 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 (); /// Dump the state of an object. void dump () const; // = STL styled iteration, compare, and reference functions. /// Prefix advance. ACE_Map_Const_Iterator &operator++ (); /// Postfix advance. ACE_Map_Const_Iterator operator++ (int); /// Prefix reverse. ACE_Map_Const_Iterator &operator-- (); /// Postfix reverse. ACE_Map_Const_Iterator operator-- (int); /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; }; /** * @class ACE_Map_Reverse_Iterator * * @brief Reverse Iterator for the ACE_Map_Manager. * * This class does not perform any internal locking of the * ACE_Map_Manager 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 * ACE_GUARD or ACE_READ_GUARD on the ACE_Map_Manager's * internal lock, which is accessible via its mutex() method. */ template class ACE_Map_Reverse_Iterator : public ACE_Map_Iterator_Base { public: ACE_Map_Reverse_Iterator (ACE_Map_Manager &mm, int pass_end = 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 (); /// Dump the state of an object. void dump () const; // = STL styled iteration, compare, and reference functions. /// Prefix reverse. ACE_Map_Reverse_Iterator &operator++ (); /// Postfix reverse. ACE_Map_Reverse_Iterator operator++ (int); /// Prefix advance. ACE_Map_Reverse_Iterator &operator-- (); /// Postfix advance. ACE_Map_Reverse_Iterator operator-- (int); /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; }; ACE_END_VERSIONED_NAMESPACE_DECL #if defined (__ACE_INLINE__) #include "ace/Map_Manager.inl" #endif /* __ACE_INLINE__ */ #if defined (ACE_TEMPLATES_REQUIRE_SOURCE) #include "ace/Map_Manager.cpp" #endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ #if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) #pragma implementation ("Map_Manager.cpp") #endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ #include /**/ "ace/post.h" #endif /* ACE_MAP_MANAGER_H */