## NAME

ACE_Map_Manager - Define a map abstraction that associates `EXT_ID`s with `INT_ID`s.

## SYNOPSIS

    #include <ace/Map_Manager.h>

    template<class EXT_ID, class INT_ID, class ACE_LOCK>
    class ACE_Map_Manager
    {
      public:
        friend class ACE_Map_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>;
        friend class ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK>;
        friend class ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK>;
        typedef EXT_ID KEY;
        typedef INT_ID VALUE;
        typedef ACE_Map_Entry<EXT_ID, INT_ID> ENTRY;
        typedef ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> ITERATOR;
            typedef ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> REVERSE_ITERATOR;

        typedef ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> iterator;
            typedef ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> reverse_iterator;

        ACE_Map_Manager (ACE_Allocator *alloc = 0);
        ACE_Map_Manager (size_t size, ACE_Allocator *alloc = 0);
        int open (
            size_t length = ACE_DEFAULT_MAP_SIZE,
            ACE_Allocator *alloc = 0
            );
        int close (void);
        ~ACE_Map_Manager (void);
        int bind (const EXT_ID &ext_id, const INT_ID &int_id);
        int rebind (
            const EXT_ID &ext_id,
            const INT_ID &int_id,
            EXT_ID &old_ext_id,
            INT_ID &old_int_id
            );
        int rebind (
            const EXT_ID &ext_id,
            const INT_ID &int_id,
            INT_ID &old_int_id
            );
        int rebind (const EXT_ID &ext_id, const INT_ID &int_id);
        int trybind (const EXT_ID &ext_id, INT_ID &int_id);
        int find (const EXT_ID &ext_id, INT_ID &int_id);
        int find (const EXT_ID &ext_id);
        int unbind (const EXT_ID &ext_id);
        int unbind (const EXT_ID &ext_id, INT_ID &int_id);
        size_t current_size (void) const;
        size_t total_size (void) const;
        ACE_LOCK &mutex (void);
        void dump (void) const;
        ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> begin (void);
        ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> end (void);
        ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> rbegin (void);
        ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> rend (void);
        ACE_ALLOC_HOOK_DECLARE;
      protected:
        int bind_i (const EXT_ID &ext_id, const INT_ID &int_id);
        int shared_bind (const EXT_ID &ext_id, const INT_ID &int_id);
        int rebind_i (
            const EXT_ID &ext_id,
            const INT_ID &int_id,
            EXT_ID &old_ext_id,
            INT_ID &old_int_id
            );
        int rebind_i (
            const EXT_ID &ext_id,
            const INT_ID &int_id,
            INT_ID &old_int_id
            );
        int rebind_i (const EXT_ID &ext_id, const INT_ID &int_id);
        int trybind_i (const EXT_ID &ext_id, INT_ID &int_id);
        int find_i (const EXT_ID &ext_id, INT_ID &int_id);
        int find_and_return_index (const EXT_ID &ext_id, size_t &slot);
        int unbind_i (const EXT_ID &ext_id, INT_ID &int_id);
        int unbind_i (const EXT_ID &ext_id);
        int unbind_and_return_index (const EXT_ID &ext_id, size_t &slot);
        int resize_i (size_t size);
        int close_i (void);
        int equal (const EXT_ID &id1, const EXT_ID &id2);
        size_t new_size (void);
        void free_search_structure (void);
        size_t free_list_id (void) const;
        size_t occupied_list_id (void) const;
        int next_free (size_t &slot);
        void move_from_free_list_to_occupied_list (size_t slot);
        void move_from_occupied_list_to_free_list (size_t slot);
        void shared_move (
            size_t slot,
            ACE_Map_Entry<EXT_ID, INT_ID> &current_list,
            size_t current_list_id,
            ACE_Map_Entry<EXT_ID, INT_ID> &new_list,
            size_t new_list_id
            );
        ACE_Allocator *allocator_;
        ACE_LOCK lock_;
        ACE_Map_Entry<EXT_ID, INT_ID> *search_structure_;
        size_t total_size_;
        size_t cur_size_;
        ACE_Map_Entry<EXT_ID, INT_ID> free_list_;
        ACE_Map_Entry<EXT_ID, INT_ID> occupied_list_;
        enum{ MAX_EXPONENTIAL = 64 * 1024, LINEAR_INCREASE = 32 * 1024 };
      private:
        inline ACE_UNIMPLEMENTED_FUNC (
            void operator= (const ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK> &)
            );
    };

## DESCRIPTION

The `EXT_ID` must support `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`.

## Traits.

    typedef EXT_ID KEY;

    typedef INT_ID VALUE;

    typedef ACE_Map_Entry<EXT_ID, INT_ID> ENTRY;

    typedef ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> ITERATOR;

        typedef ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> REVERSE_ITERATOR;

    typedef ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> iterator;

        typedef ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> reverse_iterator;

## Initialization and termination methods.

    ACE_Map_Manager (ACE_Allocator *alloc = 0);

Initialize a `Map_Manager` with the `ACE_DEFAULT_MAP_SIZE`.

    ACE_Map_Manager (size_t size, ACE_Allocator *alloc = 0);

Initialize a `Map_Manager` with `size` entries.

    int open (
        size_t length = ACE_DEFAULT_MAP_SIZE,
        ACE_Allocator *alloc = 0
        );

Initialize a `Map_Manager` with size `length`.

    int close (void);

Close down a `Map_Manager` and release dynamically allocated resources.

    ~ACE_Map_Manager (void);

Close down a `Map_Manager` and release dynamically allocated resources.

    int bind (const EXT_ID &ext_id, const INT_ID &int_id);

Associate `ext_id` with `int_id`. If `ext_id` is already in the map then the `Map_Entry` 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 rebind (
        const EXT_ID &ext_id,
        const INT_ID &int_id,
        EXT_ID &old_ext_id,
        INT_ID &old_int_id
        );

Reassociate `ext_id` with `int_id`. If `ext_id` is not in the map then behaves just like `bind`. Otherwise, store the old values of `ext_id` and `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 `Map_Entries` 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,
        INT_ID &old_int_id
        );

Reassociate `ext_id` with `int_id`. If `ext_id` is not in the map then behaves just like `bind`. Otherwise, store the old values of `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);

Reassociate `ext_id` with `int_id`. Old values in the map are ignored.

    int trybind (const EXT_ID &ext_id, INT_ID &int_id);

Associate `ext_id` with `int_id` if and only if `ext_id` is not in the map. If `ext_id` is already in the map then the `int_id` parameter is overwritten with 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 find (const EXT_ID &ext_id, INT_ID &int_id);

Locate `ext_id` and pass out parameter via `int_id`. If found, returns and non-negative integer; returns -1 if not found.

    int find (const EXT_ID &ext_id);

Returns a non-negative integer if the `ext_id` is in the mapping, otherwise -1.

    int unbind (const EXT_ID &ext_id);

Unbind (remove) the `ext_id` from the map. Don't return the `int_id` to the caller (this is useful for collections where the `int_id`s are *not* dynamically allocated...) Returns 0 if successful, else -1.

    int unbind (const EXT_ID &ext_id, INT_ID &int_id);

Break any association of `ext_id`. Returns the value of `int_id` in case the caller needs to deallocate memory. Returns 0 if successful, else -1.

    size_t current_size (void) const;

Return the current size of the map.

    size_t total_size (void) const;

Return the total size of the map.

    ACE_LOCK &mutex (void);

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!

    void dump (void) const;

Dump the state of an object.

## STL styled iterator factory functions.

    ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> begin (void);

    ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK> end (void);

Return forward iterator.

    ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> rbegin (void);

    ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK> rend (void);

Return reverse iterator.

    ACE_ALLOC_HOOK_DECLARE;

Declare the dynamic allocation hooks.

## The following methods do the actual work.

These methods assume that the locks are held by the private methods.

    int bind_i (const EXT_ID &ext_id, const INT_ID &int_id);

Performs the binding of `ext_id` to `int_id`. Must be called with locks held.

    int shared_bind (const EXT_ID &ext_id, const INT_ID &int_id);

Bind an entry (without finding first). 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 `ext_it` to `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 `ext_it` to `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);

Performs a rebinding of `ext_it` to `int_id`. Must be called with locks held.

    int trybind_i (const EXT_ID &ext_id, INT_ID &int_id);

Performs a conditional bind of `int_id` using `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 of `int_id` using `ext_id` as the key. Must be called with locks held.

    int find_and_return_index (const EXT_ID &ext_id, size_t &slot);

Performs a find using `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 of `int_id` using `ext_id` as the key. Must be called with locks held.

    int unbind_i (const EXT_ID &ext_id);

Performs an unbind using `ext_id` as the key. Must be called with locks held.

    int unbind_and_return_index (const EXT_ID &ext_id, size_t &slot);

Performs an unbind using `ext_id` as the key. Must be called with locks held.

    int resize_i (size_t size);

Resize the map. Must be called with locks held.

    int close_i (void);

Close down a `Map_Manager`. Must be called with locks held.

    int equal (const EXT_ID &id1, const EXT_ID &id2);

Returns 1 if `id1` == `id2`, else 0. This is defined as a separate method to facilitate template specialization.

    size_t new_size (void);

This function returns the new size of the Map Manager. This function is called when we run out of room and need to resize.

    void free_search_structure (void);

Explicitly call the destructors and free up the `search_structure_`.

    size_t free_list_id (void) const;

Id of the free list sentinel.

    size_t occupied_list_id (void) const;

Id of the occupied list sentinel.

    int next_free (size_t &slot);

Finds the next free slot.

    void move_from_free_list_to_occupied_list (size_t slot);

Move from free list to occupied list.

    void move_from_occupied_list_to_free_list (size_t slot);

Move from occupied list to free list.

    void shared_move (
        size_t slot,
        ACE_Map_Entry<EXT_ID, INT_ID> &current_list,
        size_t current_list_id,
        ACE_Map_Entry<EXT_ID, INT_ID> &new_list,
        size_t new_list_id
        );

Move helper.

    ACE_Allocator *allocator_;

Pointer to a memory allocator.

    ACE_LOCK lock_;

Synchronization variable for the MT_SAFE `ACE_Map_Manager`.

    ACE_Map_Entry<EXT_ID, INT_ID> *search_structure_;

Implementation of the Map (should use hashing instead of array...).

    size_t total_size_;

Total number of elements in this-search_structure_.

    size_t cur_size_;

Current size of the map.

    ACE_Map_Entry<EXT_ID, INT_ID> free_list_;

Free list.

    ACE_Map_Entry<EXT_ID, INT_ID> occupied_list_;

Occupied list.

## Disallow these operations.

    inline ACE_UNIMPLEMENTED_FUNC (
        void operator= (const ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK> &)
        );

## AUTHOR

Doug Schmidt

## LIBRARY

ace