mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2025-11-29 17:38:24 +08:00
432 lines
11 KiB
C++
432 lines
11 KiB
C++
#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_Category.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");
|
|
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nhead_ = %u"), this->head_));
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nhead_->next_ = %u"), this->head_->next_));
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_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 ())
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("count = %d\n"), count++));
|
|
|
|
ACELIB_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>);
|
|
}
|
|
|
|
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 */
|