diff options
Diffstat (limited to 'ACE/ace/Unbounded_Queue.cpp')
-rw-r--r-- | ACE/ace/Unbounded_Queue.cpp | 434 |
1 files changed, 434 insertions, 0 deletions
diff --git a/ACE/ace/Unbounded_Queue.cpp b/ACE/ace/Unbounded_Queue.cpp new file mode 100644 index 00000000000..f88a45ee493 --- /dev/null +++ b/ACE/ace/Unbounded_Queue.cpp @@ -0,0 +1,434 @@ +// $Id$ + +#ifndef ACE_UNBOUNDED_QUEUE_CPP +#define ACE_UNBOUNDED_QUEUE_CPP + +#include "ace/Unbounded_Queue.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__ */ + +#include "ace/Malloc_Base.h" +#include "ace/Log_Msg.h" +#include "ace/os_include/os_errno.h" + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +ACE_ALLOC_HOOK_DEFINE(ACE_Unbounded_Queue) + +template <class T> +ACE_Unbounded_Queue<T>::ACE_Unbounded_Queue (ACE_Allocator *alloc) + : head_ (0), + cur_size_ (0), + allocator_ (alloc) +{ + // ACE_TRACE ("ACE_Unbounded_Queue<T>::ACE_Unbounded_Queue (void)"); + + if (this->allocator_ == 0) + this->allocator_ = ACE_Allocator::instance (); + + ACE_NEW_MALLOC (this->head_, + (ACE_Node<T> *) this->allocator_->malloc (sizeof (ACE_Node<T>)), + ACE_Node<T>); + // Make the list circular by pointing it back to itself. + this->head_->next_ = this->head_; +} + +template <class T> +ACE_Unbounded_Queue<T>::ACE_Unbounded_Queue (const ACE_Unbounded_Queue<T> &us) + : head_ (0), + cur_size_ (0), + allocator_ (us.allocator_) +{ + // ACE_TRACE ("ACE_Unbounded_Queue<T>::ACE_Unbounded_Queue"); + + if (this->allocator_ == 0) + this->allocator_ = ACE_Allocator::instance (); + + ACE_NEW_MALLOC (this->head_, + (ACE_Node<T> *) this->allocator_->malloc (sizeof (ACE_Node<T>)), + ACE_Node<T>); + this->head_->next_ = this->head_; + this->copy_nodes (us); +} + +template <class T> void +ACE_Unbounded_Queue<T>::operator= (const ACE_Unbounded_Queue<T> &us) +{ + // ACE_TRACE ("ACE_Unbounded_Queue<T>::operator="); + + if (this != &us) + { + this->delete_nodes (); + this->copy_nodes (us); + } +} + +template <class T> ACE_Unbounded_Queue_Iterator<T> +ACE_Unbounded_Queue<T>::begin (void) +{ + // ACE_TRACE ("ACE_Unbounded_Queue<T>::begin"); + return ACE_Unbounded_Queue_Iterator<T> (*this); +} + +template <class T> ACE_Unbounded_Queue_Iterator<T> +ACE_Unbounded_Queue<T>::end (void) +{ + // ACE_TRACE ("ACE_Unbounded_Queue<T>::end"); + return ACE_Unbounded_Queue_Iterator<T> (*this, 1); +} + +template <class T> void +ACE_Unbounded_Queue<T>::dump (void) const +{ +#if defined (ACE_HAS_DUMP) + // ACE_TRACE ("ACE_Unbounded_Queue<T>::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<T> iter (*(ACE_Unbounded_Queue<T> *) 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)); +#endif /* ACE_HAS_DUMP */ +} + +template <class T> void +ACE_Unbounded_Queue<T>::copy_nodes (const ACE_Unbounded_Queue<T> &us) +{ + for (ACE_Node<T> *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 <class T> void +ACE_Unbounded_Queue<T>::delete_nodes (void) +{ + for (ACE_Node<T> *curr = this->head_->next_; + // Keep looking until we've hit the dummy node. + curr != this->head_; + ) + { + ACE_Node<T> *temp = curr; + curr = curr->next_; + + ACE_DES_FREE_TEMPLATE (temp, + this->allocator_->free, + ACE_Node, + <T>); + --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 <class T> +ACE_Unbounded_Queue<T>::~ACE_Unbounded_Queue (void) +{ + // ACE_TRACE ("ACE_Unbounded_Queue<T>::~ACE_Unbounded_Queue (void)"); + + this->delete_nodes (); + ACE_DES_FREE_TEMPLATE (head_, + this->allocator_->free, + ACE_Node, + <T>); + this->head_ = 0; +} + +template <class T> int +ACE_Unbounded_Queue<T>::enqueue_head (const T &new_item) +{ + // ACE_TRACE ("ACE_Unbounded_Queue<T>::enqueue_head"); + + ACE_Node<T> *temp = 0; + + // Create a new node that points to the original head. + ACE_NEW_MALLOC_RETURN (temp, + static_cast<ACE_Node<T> *> (this->allocator_->malloc (sizeof (ACE_Node<T>))), + ACE_Node<T> (new_item, this->head_->next_), + -1); + // Link this pointer into the front of the list. Note that the + // "real" head of the queue is <head_->next_>, whereas <head_> is + // just a pointer to the dummy node. + this->head_->next_ = temp; + + ++this->cur_size_; + return 0; +} + +template <class T> int +ACE_Unbounded_Queue<T>::enqueue_tail (const T &new_item) +{ + // ACE_TRACE ("ACE_Unbounded_Queue<T>::enqueue_tail"); + + // Insert <item> 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; + + ACE_Node<T> *temp = 0; + + // Create a new dummy node. + ACE_NEW_MALLOC_RETURN (temp, + static_cast<ACE_Node<T> *> (this->allocator_->malloc (sizeof (ACE_Node<T>))), + ACE_Node<T> (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 <class T> int +ACE_Unbounded_Queue<T>::dequeue_head (T &item) +{ + // ACE_TRACE ("ACE_Unbounded_Queue<T>::dequeue_head"); + + // Check for empty queue. + if (this->is_empty ()) + return -1; + + ACE_Node<T> *temp = this->head_->next_; + + item = temp->item_; + this->head_->next_ = temp->next_; + ACE_DES_FREE_TEMPLATE (temp, + this->allocator_->free, + ACE_Node, + <T>); + --this->cur_size_; + return 0; +} + +template <class T> void +ACE_Unbounded_Queue<T>::reset (void) +{ + ACE_TRACE ("reset"); + + this->delete_nodes (); +} + +template <class T> int +ACE_Unbounded_Queue<T>::get (T *&item, size_t slot) const +{ + // ACE_TRACE ("ACE_Unbounded_Queue<T>::get"); + + ACE_Node<T> *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 <class T> int +ACE_Unbounded_Queue<T>::set (const T &item, + size_t slot) +{ + // ACE_TRACE ("ACE_Unbounded_Queue<T>::set"); + + ACE_Node<T> *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 const dummy = T (); + + // 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 <class T> void +ACE_Unbounded_Queue_Const_Iterator<T>::dump (void) const +{ +#if defined (ACE_HAS_DUMP) + // ACE_TRACE ("ACE_Unbounded_Queue_Const_Iterator<T>::dump"); +#endif /* ACE_HAS_DUMP */ +} + +template <class T> +ACE_Unbounded_Queue_Const_Iterator<T>::ACE_Unbounded_Queue_Const_Iterator (const ACE_Unbounded_Queue<T> &q, int end) + : current_ (end == 0 ? q.head_->next_ : q.head_ ), + queue_ (q) +{ + // ACE_TRACE ("ACE_Unbounded_Queue_Const_Iterator<T>::ACE_Unbounded_Queue_Const_Iterator"); +} + +template <class T> int +ACE_Unbounded_Queue_Const_Iterator<T>::advance (void) +{ + // ACE_TRACE ("ACE_Unbounded_Queue_Const_Iterator<T>::advance"); + this->current_ = this->current_->next_; + return this->current_ != this->queue_.head_; +} + +template <class T> int +ACE_Unbounded_Queue_Const_Iterator<T>::first (void) +{ + // ACE_TRACE ("ACE_Unbounded_Queue_Const_Iterator<T>::first"); + this->current_ = this->queue_.head_->next_; + return this->current_ != this->queue_.head_; +} + +template <class T> int +ACE_Unbounded_Queue_Const_Iterator<T>::done (void) const +{ + ACE_TRACE ("ACE_Unbounded_Queue_Const_Iterator<T>::done"); + + return this->current_ == this->queue_.head_; +} + +template <class T> int +ACE_Unbounded_Queue_Const_Iterator<T>::next (T *&item) +{ + // ACE_TRACE ("ACE_Unbounded_Queue_Const_Iterator<T>::next"); + if (this->current_ == this->queue_.head_) + return 0; + else + { + item = &this->current_->item_; + return 1; + } +} + +// **************************************************************** + +template <class T> void +ACE_Unbounded_Queue_Iterator<T>::dump (void) const +{ +#if defined (ACE_HAS_DUMP) + // ACE_TRACE ("ACE_Unbounded_Queue_Iterator<T>::dump"); +#endif /* ACE_HAS_DUMP */ +} + +template <class T> +ACE_Unbounded_Queue_Iterator<T>::ACE_Unbounded_Queue_Iterator (ACE_Unbounded_Queue<T> &q, int end) + : current_ (end == 0 ? q.head_->next_ : q.head_ ), + queue_ (q) +{ + // ACE_TRACE ("ACE_Unbounded_Queue_Iterator<T>::ACE_Unbounded_Queue_Iterator"); +} + +template <class T> int +ACE_Unbounded_Queue_Iterator<T>::advance (void) +{ + // ACE_TRACE ("ACE_Unbounded_Queue_Iterator<T>::advance"); + this->current_ = this->current_->next_; + return this->current_ != this->queue_.head_; +} + +template <class T> int +ACE_Unbounded_Queue_Iterator<T>::first (void) +{ + // ACE_TRACE ("ACE_Unbounded_Queue_Iterator<T>::first"); + this->current_ = this->queue_.head_->next_; + return this->current_ != this->queue_.head_; +} + +template <class T> int +ACE_Unbounded_Queue_Iterator<T>::done (void) const +{ + ACE_TRACE ("ACE_Unbounded_Queue_Iterator<T>::done"); + + return this->current_ == this->queue_.head_; +} + +template <class T> int +ACE_Unbounded_Queue_Iterator<T>::next (T *&item) +{ + // ACE_TRACE ("ACE_Unbounded_Queue_Iterator<T>::next"); + if (this->current_ == this->queue_.head_) + return 0; + else + { + item = &this->current_->item_; + return 1; + } +} + +ACE_END_VERSIONED_NAMESPACE_DECL + +#endif /* ACE_UNBOUNDED_QUEUE_CPP */ |