// $Id$ // ============================================================================ // // = LIBRARY // ace // // = FILENAME // Hash_Map_Manager.cpp // // = AUTHOR // Doug Schmidt // // ============================================================================ #if !defined (ACE_HASH_MAP_MANAGER_C) #define ACE_HASH_MAP_MANAGER_C #include "ace/Hash_Map_Manager.h" #include "ace/Service_Config.h" #include "ace/Malloc.h" ACE_RCSID(ace, Hash_Map_Manager, "$Id$") template ACE_Hash_Map_Entry::ACE_Hash_Map_Entry (ACE_Hash_Map_Entry *next, ACE_Hash_Map_Entry *prev) : next_ (next), prev_ (prev) { } template ACE_Hash_Map_Entry::ACE_Hash_Map_Entry (const EXT_ID &ext_id, const INT_ID &int_id, ACE_Hash_Map_Entry *next, ACE_Hash_Map_Entry *prev) : ext_id_ (ext_id), int_id_ (int_id), next_ (next), prev_ (prev) { } # if ! defined (ACE_HAS_BROKEN_NOOP_DTORS) template ACE_Hash_Map_Entry::~ACE_Hash_Map_Entry (void) { } # endif /* ! defined (ACE_HAS_BROKEN_NOOP_DTORS) */ template void ACE_Hash_Map_Entry::dump (void) const { ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("next_ = %d"), this->next_)); ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("prev_ = %d"), this->prev_)); ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); } template void ACE_Hash_Map_Manager::dump (void) const { ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("total_size_ = %d"), this->total_size_)); ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("\ncur_size_ = %d"), this->cur_size_)); this->allocator_->dump (); this->lock_.dump (); ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); } template int ACE_Hash_Map_Manager::create_buckets (size_t size) { size_t bytes = size * sizeof (ACE_Hash_Map_Entry); void *ptr; ACE_ALLOCATOR_RETURN (ptr, this->allocator_->malloc (bytes), -1); this->table_ = (ACE_Hash_Map_Entry *) ptr; this->total_size_ = size; // Initialize each entry in the hash table to be a circular linked // list with the dummy node in the front serving as the anchor of // the list. for (size_t i = 0; i < size; i++) new (&this->table_[i]) ACE_Hash_Map_Entry (&this->table_[i], &this->table_[i]); return 0; } template int ACE_Hash_Map_Manager::open (size_t size, ACE_Allocator *alloc) { ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1); if (alloc == 0) alloc = ACE_Allocator::instance (); this->allocator_ = alloc; // This assertion is here to help track a situation that shouldn't // happen, but did with Sun C++ 4.1 (before a change to this class // was made: it used to have an enum that was supposed to be defined // to be ACE_DEFAULT_MAP_SIZE, but instead was defined to be 0). ACE_ASSERT (size != 0); // Calling this->close_i () to ensure we release previous allocated // memory before allocating new one. this->close_i (); return this->create_buckets (size); } template ACE_Hash_Map_Manager::ACE_Hash_Map_Manager (size_t size, ACE_Allocator *alloc) : allocator_ (alloc), table_ (0), total_size_ (0), cur_size_ (0) { if (this->open (size, alloc) == -1) ACE_ERROR ((LM_ERROR, ASYS_TEXT ("ACE_Hash_Map_Manager\n"))); } template ACE_Hash_Map_Manager::ACE_Hash_Map_Manager (ACE_Allocator *alloc) : allocator_ (alloc), table_ (0), total_size_ (0), cur_size_ (0) { if (this->open (ACE_DEFAULT_MAP_SIZE, alloc) == -1) ACE_ERROR ((LM_ERROR, ASYS_TEXT ("ACE_Hash_Map_Manager\n"))); } template int ACE_Hash_Map_Manager::close_i (void) { // Protect against "double-deletion" in case the destructor also // gets called. if (this->table_ != 0) { // Iterate through the entire map calling the destuctor of each // . for (size_t i = 0; i < this->total_size_; i++) { for (ACE_Hash_Map_Entry *temp_ptr = this->table_[i].next_; temp_ptr != &this->table_[i]; ) { ACE_Hash_Map_Entry *hold_ptr = temp_ptr; temp_ptr = temp_ptr->next_; // Explicitly call the destructor. ACE_DES_FREE_TEMPLATE2 (hold_ptr, this->allocator_->free, ACE_Hash_Map_Entry, EXT_ID, INT_ID); } // Destroy the dummy entry. ACE_Hash_Map_Entry *entry = &table_[i]; // The "if" second argument results in a no-op instead of // deallocation. ACE_DES_FREE_TEMPLATE2 (entry, ACE_NOOP, ACE_Hash_Map_Entry, EXT_ID, INT_ID); } // Free table memory. this->allocator_->free (this->table_); this->cur_size_ = 0; this->total_size_ = 0; // Should be done last... this->table_ = 0; } return 0; } template int ACE_Hash_Map_Manager::close (void) { ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1); return this->close_i (); } template ACE_Hash_Map_Manager::~ACE_Hash_Map_Manager (void) { this->close (); } template size_t ACE_Hash_Map_Manager::current_size (void) { return this->cur_size_; } template size_t ACE_Hash_Map_Manager::total_size (void) { return this->total_size_; } template ACE_LOCK & ACE_Hash_Map_Manager::mutex (void) { ACE_TRACE ("ACE_Hash_Map_Manager::mutex"); return this->lock_; } template u_long ACE_Hash_Map_Manager::hash (const EXT_ID &ext_id) { return ext_id.hash (); } template int ACE_Hash_Map_Manager::equal (const EXT_ID &id1, const EXT_ID &id2) { return id1 == id2; } template int ACE_Hash_Map_Manager::bind_i (const EXT_ID &ext_id, const INT_ID &int_id, ACE_Hash_Map_Entry *&entry) { u_long loc; int result = this->shared_find (ext_id, entry, loc); if (result == -1) { void *ptr; // Not found. ACE_ALLOCATOR_RETURN (ptr, this->allocator_->malloc (sizeof (ACE_Hash_Map_Entry)), -1); entry = new (ptr) ACE_Hash_Map_Entry (ext_id, int_id, this->table_[loc].next_, &this->table_[loc]); this->table_[loc].next_ = entry; entry->next_->prev_ = entry; this->cur_size_++; return 0; } else return 1; } template int ACE_Hash_Map_Manager::bind_i (const EXT_ID &ext_id, const INT_ID &int_id) { ACE_Hash_Map_Entry *temp; return this->bind_i (ext_id, int_id, temp); } template int ACE_Hash_Map_Manager::bind (const EXT_ID &ext_id, const INT_ID &int_id) { ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1); return this->bind_i (ext_id, int_id); } template int ACE_Hash_Map_Manager::bind (const EXT_ID &ext_id, const INT_ID &int_id, ACE_Hash_Map_Entry *&entry) { ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1); return this->bind_i (ext_id, int_id, entry); } template int ACE_Hash_Map_Manager::trybind_i (const EXT_ID &ext_id, INT_ID &int_id, ACE_Hash_Map_Entry *&entry) { u_long loc; int result = this->shared_find (ext_id, entry, loc); if (result == -1) { // Not found. void *ptr; ACE_ALLOCATOR_RETURN (ptr, this->allocator_->malloc (sizeof (ACE_Hash_Map_Entry)), -1); entry = new (ptr) ACE_Hash_Map_Entry (ext_id, int_id, this->table_[loc].next_, &this->table_[loc]); this->table_[loc].next_ = entry; entry->next_->prev_ = entry; this->cur_size_++; return 0; } else { entry->int_id_ = int_id; return 1; } } template int ACE_Hash_Map_Manager::trybind_i (const EXT_ID &ext_id, INT_ID &int_id) { ACE_Hash_Map_Entry *temp; return this->trybind_i (ext_id, int_id, temp); } template int ACE_Hash_Map_Manager::trybind (const EXT_ID &ext_id, INT_ID &int_id) { ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1); return this->trybind_i (ext_id, int_id); } template int ACE_Hash_Map_Manager::trybind (const EXT_ID &ext_id, INT_ID &int_id, ACE_Hash_Map_Entry *&entry) { ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1); return this->trybind_i (ext_id, int_id, entry); } template int ACE_Hash_Map_Manager::unbind_i (const EXT_ID &ext_id, INT_ID &int_id) { ACE_Hash_Map_Entry *temp; u_long loc; int result = this->shared_find (ext_id, temp, loc); if (result == -1) { errno = ENOENT; return -1; } int_id = temp->int_id_; return this->unbind_i (temp); } template int ACE_Hash_Map_Manager::unbind_i (ACE_Hash_Map_Entry *entry) { entry->next_->prev_ = entry->prev_; entry->prev_->next_ = entry->next_; // Explicitly call the destructor. ACE_DES_FREE_TEMPLATE2 (entry, this->allocator_->free, ACE_Hash_Map_Entry, EXT_ID, INT_ID); this->cur_size_--; return 0; } template int ACE_Hash_Map_Manager::unbind_i (const EXT_ID &ext_id) { INT_ID int_id; return this->unbind_i (ext_id, int_id); } template int ACE_Hash_Map_Manager::unbind (const EXT_ID &ext_id, INT_ID &int_id) { ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1); return this->unbind_i (ext_id, int_id); } template int ACE_Hash_Map_Manager::unbind (const EXT_ID &ext_id) { ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1); return this->unbind_i (ext_id) == -1 ? -1 : 0; } template int ACE_Hash_Map_Manager::unbind (ACE_Hash_Map_Entry *entry) { ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1); return this->unbind_i (entry) == -1 ? -1 : 0; } template int ACE_Hash_Map_Manager::shared_find (const EXT_ID &ext_id, ACE_Hash_Map_Entry *&entry, u_long &loc) { loc = this->hash (ext_id) % this->total_size_; ACE_Hash_Map_Entry *temp = this->table_[loc].next_; while (temp != &this->table_[loc] && this->equal (temp->ext_id_, ext_id) == 0) temp = temp->next_; if (temp == &this->table_[loc]) { errno = ENOENT; return -1; } else { entry = temp; return 0; } } template int ACE_Hash_Map_Manager::find_i (const EXT_ID &ext_id, INT_ID &int_id) { ACE_Hash_Map_Entry *entry; u_long dummy; if (this->shared_find (ext_id, entry, dummy) == -1) return -1; else { int_id = entry->int_id_; return 0; } } template int ACE_Hash_Map_Manager::find_i (const EXT_ID &ext_id) { ACE_Hash_Map_Entry *entry; u_long dummy; return this->shared_find (ext_id, entry, dummy); } template int ACE_Hash_Map_Manager::find (const EXT_ID &ext_id, INT_ID &int_id) { ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1); return this->find_i (ext_id, int_id); } template int ACE_Hash_Map_Manager::find (const EXT_ID &ext_id) { ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1); return this->find_i (ext_id); } template int ACE_Hash_Map_Manager::find_i (const EXT_ID &ext_id, ACE_Hash_Map_Entry *&entry) { u_long dummy; return this->shared_find (ext_id, entry, dummy); } template int ACE_Hash_Map_Manager::find (const EXT_ID &ext_id, ACE_Hash_Map_Entry *&entry) { ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1); return this->find_i (ext_id, entry); } template int ACE_Hash_Map_Manager::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) { u_long dummy; if (this->shared_find (ext_id, entry, dummy) == -1) return this->bind_i (ext_id, int_id); else { old_ext_id = entry->ext_id_; old_int_id = entry->int_id_; entry->ext_id_ = ext_id; entry->int_id_ = int_id; return 1; } } template int ACE_Hash_Map_Manager::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 *node; return this->rebind_i (ext_id, int_id, old_ext_id, old_int_id, node); } template int ACE_Hash_Map_Manager::rebind (const EXT_ID &ext_id, const INT_ID &int_id, EXT_ID &old_ext_id, INT_ID &old_int_id) { ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1); return this->rebind_i (ext_id, int_id, old_ext_id, old_int_id); } template int ACE_Hash_Map_Manager::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) { ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1); return this->rebind_i (ext_id, int_id, old_ext_id, old_int_id, entry); } // ------------------------------------------------------------ template ACE_Hash_Map_Iterator ACE_Hash_Map_Manager::begin (void) { return ACE_Hash_Map_Iterator (*this); } template ACE_Hash_Map_Iterator ACE_Hash_Map_Manager::end (void) { return ACE_Hash_Map_Iterator (*this, 1); } template ACE_Hash_Map_Reverse_Iterator ACE_Hash_Map_Manager::rbegin (void) { return ACE_Hash_Map_Reverse_Iterator (*this); } template ACE_Hash_Map_Reverse_Iterator ACE_Hash_Map_Manager::rend (void) { return ACE_Hash_Map_Reverse_Iterator (*this, 1); } ACE_ALLOC_HOOK_DEFINE(ACE_Hash_Map_Iterator_Base) template void ACE_Hash_Map_Iterator_Base::dump_i (void) const { ACE_TRACE ("ACE_Hash_Map_Iterator_Base::dump"); ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("index_ = %d "), this->index_)); ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("next_ = %x"), this->next_)); ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); } template ACE_Hash_Map_Iterator_Base::ACE_Hash_Map_Iterator_Base (ACE_Hash_Map_Manager &mm, int head) : map_man_ (&mm), index_ (head != 0 ? -1 : ACE_static_cast (ssize_t, mm.total_size_)), next_ (0) { ACE_TRACE ("ACE_Hash_Map_Iterator_Base::ACE_Hash_Map_Iterator_Base"); if (mm.table_ != 0) this->next_ = &mm.table_[head != 0 ? 0 : mm.total_size_ - 1]; } template int ACE_Hash_Map_Iterator_Base::next (ACE_Hash_Map_Entry *&entry) { ACE_TRACE ("ACE_Hash_Map_Iterator_Base::next"); if (this->map_man_->table_ != 0 && this->index_ < ACE_static_cast (ssize_t, this->map_man_->total_size_) && this->index_ >= 0 && this->next_ != &this->map_man_->table_[this->index_]) { entry = this->next_; return 1; } else return 0; } template int ACE_Hash_Map_Iterator_Base::done (void) const { ACE_TRACE ("ACE_Hash_Map_Iterator_Base::done"); return this->map_man_->table_ == 0 || this->index_ >= ACE_static_cast (ssize_t, this->map_man_->total_size_) || this->index_ < 0; } template int ACE_Hash_Map_Iterator_Base::forward_i (void) { ACE_TRACE ("ACE_Hash_Map_Iterator_Base::forward_i"); if (this->map_man_->table_ == 0) return -1; // Handle initial case specially. else if (this->index_ == -1) { this->index_++; return this->forward_i (); } else if (this->index_ >= ACE_static_cast (ssize_t, this->map_man_->total_size_)) return 0; this->next_ = this->next_->next_; if (this->next_ == &this->map_man_->table_[this->index_]) { while (++this->index_ < ACE_static_cast (ssize_t, this->map_man_->total_size_)) { this->next_ = this->map_man_->table_[this->index_].next_; if (this->next_ != &this->map_man_->table_[this->index_]) break; } } return this->index_ < ACE_static_cast (ssize_t, this->map_man_->total_size_); } template int ACE_Hash_Map_Iterator_Base::reverse_i (void) { ACE_TRACE ("ACE_Hash_Map_Iterator_Base::reverse_i"); if (this->map_man_->table_ == 0) return -1; else if (this->index_ == ACE_static_cast (ssize_t, this->map_man_->total_size_)) { this->index_--; return this->reverse_i (); } else if (this->index_ < 0) return 0; this->next_ = this->next_->prev_; if (this->next_ == &this->map_man_->table_[this->index_]) { while (--this->index_ >= 0) { this->next_ = this->map_man_->table_[this->index_].prev_; if (this->next_ != &this->map_man_->table_[this->index_]) break; } } return this->index_ >= 0; } template ACE_Hash_Map_Entry & ACE_Hash_Map_Iterator_Base::operator* (void) { ACE_TRACE ("ACE_Hash_Map_Iterator_Base::operator*"); ACE_Hash_Map_Entry *retv = 0; int result = this->next (retv); ACE_ASSERT (result != 0); return *retv; } // Returns the reference to the hash_map_manager that is being // iterated over. template ACE_Hash_Map_Manager& ACE_Hash_Map_Iterator_Base::map (void) { ACE_TRACE ("ACE_Hash_Map_Iterator_Base::map"); return *this->map_man_; } template int ACE_Hash_Map_Iterator_Base::operator== (const ACE_Hash_Map_Iterator_Base &rhs) const { ACE_TRACE ("ACE_Hash_Map_Iterator_Base::operator=="); return this->map_man_ == rhs.map_man_ && this->index_ == rhs.index_ && this->next_ == rhs.next_; } template int ACE_Hash_Map_Iterator_Base::operator!= (const ACE_Hash_Map_Iterator_Base &rhs) const { ACE_TRACE ("ACE_Hash_Map_Iterator_Base::operator!="); return this->next_ != rhs.next_ || this->index_ != rhs.index_ || this->map_man_ != rhs.map_man_; } ACE_ALLOC_HOOK_DEFINE(ACE_Hash_Map_Iterator) template void ACE_Hash_Map_Iterator::dump (void) const { ACE_TRACE ("ACE_Hash_Map_Iterator::dump"); this->dump_i (); } template ACE_Hash_Map_Iterator::ACE_Hash_Map_Iterator (ACE_Hash_Map_Manager &mm, int tail) : ACE_Hash_Map_Iterator_Base (mm, tail == 0 ? 1 : 0) { ACE_TRACE ("ACE_Hash_Map_Iterator::ACE_Hash_Map_Iterator"); if (tail == 0) this->forward_i (); } template int ACE_Hash_Map_Iterator::advance (void) { ACE_TRACE ("ACE_Hash_Map_Iterator::advance"); return this->forward_i (); } template ACE_Hash_Map_Iterator & ACE_Hash_Map_Iterator::operator++ (void) { ACE_TRACE ("ACE_Hash_Map_Iterator::operator++ (void)"); this->forward_i (); return *this; } template ACE_Hash_Map_Iterator ACE_Hash_Map_Iterator::operator++ (int) { ACE_TRACE ("ACE_Hash_Map_Iterator::operator++ (int)"); ACE_Hash_Map_Iterator retv (*this); this->forward_i (); return retv; } template ACE_Hash_Map_Iterator & ACE_Hash_Map_Iterator::operator-- (void) { ACE_TRACE ("ACE_Hash_Map_Iterator::operator-- (void)"); this->reverse_i (); return *this; } template ACE_Hash_Map_Iterator ACE_Hash_Map_Iterator::operator-- (int) { ACE_TRACE ("ACE_Hash_Map_Iterator::operator-- (int)"); ACE_Hash_Map_Iterator retv (*this); this->reverse_i (); return retv; } ACE_ALLOC_HOOK_DEFINE(ACE_Hash_Map_Reverse_Iterator) template void ACE_Hash_Map_Reverse_Iterator::dump (void) const { ACE_TRACE ("ACE_Hash_Map_Reverse_Iterator::dump"); this->dump_i (); } template ACE_Hash_Map_Reverse_Iterator::ACE_Hash_Map_Reverse_Iterator (ACE_Hash_Map_Manager &mm, int head) : ACE_Hash_Map_Iterator_Base (mm, head) { ACE_TRACE ("ACE_Hash_Map_Reverse_Iterator::ACE_Hash_Map_Reverse_Iterator"); if (head == 0) this->reverse_i (); } template int ACE_Hash_Map_Reverse_Iterator::advance (void) { ACE_TRACE ("ACE_Hash_Map_Reverse_Iterator::advance"); return this->reverse_i (); } template ACE_Hash_Map_Reverse_Iterator & ACE_Hash_Map_Reverse_Iterator::operator++ (void) { ACE_TRACE ("ACE_Hash_Map_Reverse_Iterator::operator++ (void)"); this->reverse_i (); return *this; } template ACE_Hash_Map_Reverse_Iterator ACE_Hash_Map_Reverse_Iterator::operator++ (int) { ACE_TRACE ("ACE_Hash_Map_Reverse_Iterator::operator++ (int)"); ACE_Hash_Map_Reverse_Iterator retv (*this); this->reverse_i (); return retv; } template ACE_Hash_Map_Reverse_Iterator & ACE_Hash_Map_Reverse_Iterator::operator-- (void) { ACE_TRACE ("ACE_Hash_Map_Reverse_Iterator::operator-- (void)"); this->forward_i (); return *this; } template ACE_Hash_Map_Reverse_Iterator ACE_Hash_Map_Reverse_Iterator::operator-- (int) { ACE_TRACE ("ACE_Hash_Map_Reverse_Iterator::operator-- (int)"); ACE_Hash_Map_Reverse_Iterator retv (*this); this->forward_i (); return retv; } #endif /* ACE_HASH_MAP_MANAGER_C */