// $Id$ #ifndef ACE_UNBOUNDED_QUEUE_C #define ACE_UNBOUNDED_QUEUE_C #include "ace/Unbounded_Queue.h" #include "ace/Malloc_Base.h" #include "ace/Log_Msg.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ #if !defined (__ACE_INLINE__) #include "ace/Unbounded_Queue.inl" #endif /* __ACE_INLINE__ */ ACE_RCSID(ace, Unbounded_Queue, "$Id$") ACE_ALLOC_HOOK_DEFINE(ACE_Unbounded_Queue) template ACE_Unbounded_Queue::ACE_Unbounded_Queue (ACE_Allocator *alloc) : head_ (0), cur_size_ (0), allocator_ (alloc) { // ACE_TRACE ("ACE_Unbounded_Queue::ACE_Unbounded_Queue (void)"); if (this->allocator_ == 0) this->allocator_ = ACE_Allocator::instance (); ACE_NEW_MALLOC (this->head_, (ACE_Node *) this->allocator_->malloc (sizeof (ACE_Node)), ACE_Node); // Make the list circular by pointing it back to itself. this->head_->next_ = this->head_; } template ACE_Unbounded_Queue::ACE_Unbounded_Queue (const ACE_Unbounded_Queue &us) : head_ (0), cur_size_ (0), allocator_ (us.allocator_) { // ACE_TRACE ("ACE_Unbounded_Queue::ACE_Unbounded_Queue"); if (this->allocator_ == 0) this->allocator_ = ACE_Allocator::instance (); ACE_NEW_MALLOC (this->head_, (ACE_Node *) this->allocator_->malloc (sizeof (ACE_Node)), ACE_Node); this->head_->next_ = this->head_; this->copy_nodes (us); } template void ACE_Unbounded_Queue::operator= (const ACE_Unbounded_Queue &us) { // ACE_TRACE ("ACE_Unbounded_Queue::operator="); if (this != &us) { this->delete_nodes (); this->copy_nodes (us); } } template ACE_Unbounded_Queue_Iterator ACE_Unbounded_Queue::begin (void) { // ACE_TRACE ("ACE_Unbounded_Queue::begin"); return ACE_Unbounded_Queue_Iterator (*this); } template ACE_Unbounded_Queue_Iterator ACE_Unbounded_Queue::end (void) { // ACE_TRACE ("ACE_Unbounded_Queue::end"); return ACE_Unbounded_Queue_Iterator (*this, 1); } template void ACE_Unbounded_Queue::dump (void) const { // ACE_TRACE ("ACE_Unbounded_Queue::dump"); ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nhead_ = %u"), this->head_)); ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nhead_->next_ = %u"), this->head_->next_)); ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ncur_size_ = %d\n"), this->cur_size_)); T *item = 0; #if !defined (ACE_NLOGGING) size_t count = 1; #endif /* ! ACE_NLOGGING */ for (ACE_Unbounded_Queue_Iterator iter (*(ACE_Unbounded_Queue *) this); iter.next (item) != 0; iter.advance ()) ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("count = %d\n"), count++)); ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); } template void ACE_Unbounded_Queue::copy_nodes (const ACE_Unbounded_Queue &us) { for (ACE_Node *curr = us.head_->next_; curr != us.head_; curr = curr->next_) if (this->enqueue_tail (curr->item_) == -1) // @@ What's the right thing to do here? this->delete_nodes (); } template void ACE_Unbounded_Queue::delete_nodes (void) { for (ACE_Node *curr = this->head_->next_; // Keep looking until we've hit the dummy node. curr != this->head_; ) { ACE_Node *temp = curr; curr = curr->next_; ACE_DES_FREE_TEMPLATE (temp, this->allocator_->free, ACE_Node, ); this->cur_size_--; // @@ Doesnt make sense to have this check since // this will always be true. // ACE_ASSERT (this->cur_size_ >= 0); } // Reset the list to be a circular list with just a dummy node. this->head_->next_ = this->head_; } template ACE_Unbounded_Queue::~ACE_Unbounded_Queue (void) { // ACE_TRACE ("ACE_Unbounded_Queue::~ACE_Unbounded_Queue (void)"); this->delete_nodes (); ACE_DES_FREE_TEMPLATE (head_, this->allocator_->free, ACE_Node, ); this->head_ = 0; } template int ACE_Unbounded_Queue::enqueue_head (const T &new_item) { // ACE_TRACE ("ACE_Unbounded_Queue::enqueue_head"); ACE_Node *temp; // Create a new node that points to the original head. ACE_NEW_MALLOC_RETURN (temp, (ACE_Node *) this->allocator_->malloc (sizeof (ACE_Node)), ACE_Node (new_item, this->head_->next_), -1); // Link this pointer into the front of the list. Note that the // "real" head of the queue is next_>, whereas is // just a pointer to the dummy node. this->head_->next_ = temp; this->cur_size_++; return 0; } template int ACE_Unbounded_Queue::enqueue_tail (const T &new_item) { // ACE_TRACE ("ACE_Unbounded_Queue::enqueue_tail"); ACE_Node *temp; // Insert into the old dummy node location. Note that this // isn't actually the "head" item in the queue, it's a dummy node at // the "tail" of the queue... this->head_->item_ = new_item; // Create a new dummy node. ACE_NEW_MALLOC_RETURN (temp, (ACE_Node *) this->allocator_->malloc (sizeof (ACE_Node)), ACE_Node (this->head_->next_), -1); // Link this dummy pointer into the list. this->head_->next_ = temp; // Point the head to the new dummy node. this->head_ = temp; this->cur_size_++; return 0; } template int ACE_Unbounded_Queue::dequeue_head (T &item) { // ACE_TRACE ("ACE_Unbounded_Queue::dequeue_head"); // Check for empty queue. if (this->is_empty ()) return -1; ACE_Node *temp = this->head_->next_; item = temp->item_; this->head_->next_ = temp->next_; ACE_DES_FREE_TEMPLATE (temp, this->allocator_->free, ACE_Node, ); --this->cur_size_; return 0; } template void ACE_Unbounded_Queue::reset (void) { ACE_TRACE ("reset"); this->delete_nodes (); } template int ACE_Unbounded_Queue::get (T *&item, size_t slot) const { // ACE_TRACE ("ACE_Unbounded_Queue::get"); ACE_Node *curr = this->head_->next_; size_t i; for (i = 0; i < this->cur_size_; i++) { if (i == slot) break; curr = curr->next_; } if (i < this->cur_size_) { item = &curr->item_; return 0; } else return -1; } template int ACE_Unbounded_Queue::set (const T &item, size_t slot) { // ACE_TRACE ("ACE_Unbounded_Queue::set"); ACE_Node *curr = this->head_->next_; size_t i; for (i = 0; i < slot && i < this->cur_size_; i++) curr = curr->next_; if (i < this->cur_size_) { // We're in range, so everything's cool. curr->item_ = item; return 0; } else { // We need to expand the list. // A common case will be increasing the set size by 1. // Therefore, we'll optimize for this case. if (i == slot) { // Try to expand the size of the set by 1. if (this->enqueue_tail (item) == -1) return -1; else return 0; } else { T dummy; // We need to expand the list by multiple (dummy) items. for (; i < slot; i++) { // This head points to the existing dummy node, which is // about to be overwritten when we add the new dummy // node. curr = this->head_; // Try to expand the size of the set by 1, but don't // store anything in the dummy node (yet). if (this->enqueue_tail (dummy) == -1) return -1; } curr->item_ = item; return 0; } } } // **************************************************************** template void ACE_Unbounded_Queue_Iterator::dump (void) const { // ACE_TRACE ("ACE_Unbounded_Queue_Iterator::dump"); } template ACE_Unbounded_Queue_Iterator::ACE_Unbounded_Queue_Iterator (ACE_Unbounded_Queue &q, int end) : current_ (end == 0 ? q.head_->next_ : q.head_ ), queue_ (q) { // ACE_TRACE ("ACE_Unbounded_Queue_Iterator::ACE_Unbounded_Queue_Iterator"); } template int ACE_Unbounded_Queue_Iterator::advance (void) { // ACE_TRACE ("ACE_Unbounded_Queue_Iterator::advance"); this->current_ = this->current_->next_; return this->current_ != this->queue_.head_; } template int ACE_Unbounded_Queue_Iterator::first (void) { // ACE_TRACE ("ACE_Unbounded_Queue_Iterator::first"); this->current_ = this->queue_.head_->next_; return this->current_ != this->queue_.head_; } template int ACE_Unbounded_Queue_Iterator::done (void) const { ACE_TRACE ("ACE_Unbounded_Queue_Iterator::done"); return this->current_ == this->queue_.head_; } template int ACE_Unbounded_Queue_Iterator::next (T *&item) { // ACE_TRACE ("ACE_Unbounded_Queue_Iterator::next"); if (this->current_ == this->queue_.head_) return 0; else { item = &this->current_->item_; return 1; } } #endif /* ACE_UNBOUNDED_QUEUE_C */