diff options
author | okellogg <okellogg@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2003-04-01 10:59:08 +0000 |
---|---|---|
committer | okellogg <okellogg@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2003-04-01 10:59:08 +0000 |
commit | 71636b8bab2396a4acd8071c759e6d34c9bdfe64 (patch) | |
tree | 87cf620ef93909fcb9e740c5c7856cb68d378bf1 /ace | |
parent | 79361a43bbc84aa3f17a27e502a759e4ec9c64d9 (diff) | |
download | ATCD-71636b8bab2396a4acd8071c759e6d34c9bdfe64.tar.gz |
ChangeLogTag:Tue Apr 1 12:48:33 CEST 2003 Oliver Kellogg <oliver.kellogg@sysde.eads.net>
Diffstat (limited to 'ace')
-rw-r--r-- | ace/Makefile.ace | 1 | ||||
-rw-r--r-- | ace/Node.cpp | 9 | ||||
-rw-r--r-- | ace/Node.h | 9 | ||||
-rw-r--r-- | ace/Unbounded_Set_Ex.cpp | 620 | ||||
-rw-r--r-- | ace/Unbounded_Set_Ex.h | 359 | ||||
-rw-r--r-- | ace/Unbounded_Set_Ex.inl | 16 |
6 files changed, 1011 insertions, 3 deletions
diff --git a/ace/Makefile.ace b/ace/Makefile.ace index 339d3a86fdc..a20dc307cbc 100644 --- a/ace/Makefile.ace +++ b/ace/Makefile.ace @@ -259,6 +259,7 @@ TEMPLATE_FILES = \ Array_Base \ Node \ Unbounded_Set \ + Unbounded_Set_Ex \ Unbounded_Queue \ Asynch_Acceptor \ Asynch_Connector \ diff --git a/ace/Node.cpp b/ace/Node.cpp index 91e989d739b..f13b18cde86 100644 --- a/ace/Node.cpp +++ b/ace/Node.cpp @@ -23,14 +23,16 @@ ACE_Node<T>::~ACE_Node (void) template <class T> ACE_Node<T>::ACE_Node (const T &i, ACE_Node<T> *n) : next_ (n), - item_ (i) + item_ (i), + deleted_ (false) { // ACE_TRACE ("ACE_Node<T>::ACE_Node"); } template <class T> ACE_Node<T>::ACE_Node (ACE_Node<T> *n, int) - : next_ (n) + : next_ (n), + deleted_ (false) { // ACE_TRACE ("ACE_Node<T>::ACE_Node"); } @@ -38,7 +40,8 @@ ACE_Node<T>::ACE_Node (ACE_Node<T> *n, int) template <class T> ACE_Node<T>::ACE_Node (const ACE_Node<T> &s) : next_ (s.next_), - item_ (s.item_) + item_ (s.item_), + deleted_ (false) { // ACE_TRACE ("ACE_Node<T>::ACE_Node"); } diff --git a/ace/Node.h b/ace/Node.h index 3d69213bf26..932997fcd35 100644 --- a/ace/Node.h +++ b/ace/Node.h @@ -25,6 +25,9 @@ template <class T> class ACE_Unbounded_Set; template <class T> class ACE_Unbounded_Set_Iterator; template <class T> class ACE_Unbounded_Set_Const_Iterator; +template <class T> class ACE_Unbounded_Set_Ex; +template <class T> class ACE_Unbounded_Set_Ex_Iterator; +template <class T> class ACE_Unbounded_Set_Ex_Const_Iterator; template <class T> class ACE_Unbounded_Queue; template <class T> class ACE_Unbounded_Queue_Iterator; template <class T> class ACE_Unbounded_Stack; @@ -44,6 +47,9 @@ public: friend class ACE_Unbounded_Set<T>; friend class ACE_Unbounded_Set_Iterator<T>; friend class ACE_Unbounded_Set_Const_Iterator<T>; + friend class ACE_Unbounded_Set_Ex<T>; + friend class ACE_Unbounded_Set_Ex_Iterator<T>; + friend class ACE_Unbounded_Set_Ex_Const_Iterator<T>; friend class ACE_Unbounded_Stack<T>; friend class ACE_Unbounded_Stack_Iterator<T>; @@ -63,6 +69,9 @@ private: /// Current value of the item in this node. T item_; + + /// Flag that indicates whether this node is deleted. + int deleted_; }; #if defined (ACE_TEMPLATES_REQUIRE_SOURCE) diff --git a/ace/Unbounded_Set_Ex.cpp b/ace/Unbounded_Set_Ex.cpp new file mode 100644 index 00000000000..2dedd6a5537 --- /dev/null +++ b/ace/Unbounded_Set_Ex.cpp @@ -0,0 +1,620 @@ +// $Id$ + +#ifndef ACE_UNBOUNDED_SET_EX_C +#define ACE_UNBOUNDED_SET_EX_C + +#include "ace/Unbounded_Set_Ex.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_Set_Ex.inl" +#endif /* __ACE_INLINE__ */ + +ACE_RCSID(ace, Unbounded_Set_Ex, "$Id$") + +ACE_ALLOC_HOOK_DEFINE(ACE_Unbounded_Set_Ex) + +template <class T> size_t +ACE_Unbounded_Set_Ex<T>::size (void) const +{ + // ACE_TRACE ("ACE_Unbounded_Set_Ex<T>::size"); + return this->cur_size_; +} + +template <class T> int +ACE_Unbounded_Set_Ex<T>::insert_tail (const T &item) +{ + // ACE_TRACE ("ACE_Unbounded_Set_Ex<T>::insert_tail"); + ACE_Node<T> *temp; + + // Insert <item> into the old dummy node location. + this->head_->item_ = item; + + // Create a new dummy node. + ACE_NEW_MALLOC_RETURN (temp, + ACE_static_cast(ACE_Node<T>*, + this->allocator_->malloc (sizeof (ACE_Node<T>))), + ACE_Node<T> (this->head_->next_), + -1); + // Link this 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> void +ACE_Unbounded_Set_Ex<T>::reset (void) +{ + ACE_TRACE ("reset"); + + this->delete_nodes (); +} + +template <class T> void +ACE_Unbounded_Set_Ex<T>::dump (void) const +{ + ACE_TRACE ("ACE_Unbounded_Set_Ex<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_Set_Ex_Iterator<T> iter (*(ACE_Unbounded_Set_Ex<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)); +} + +template <class T> void +ACE_Unbounded_Set_Ex<T>::copy_nodes (const ACE_Unbounded_Set_Ex<T> &us) +{ + for (ACE_Node<T> *curr = us.head_->next_; + curr != us.head_; + curr = curr->next_) + { + if (!curr->deleted_) + this->insert_tail (curr->item_); + } +} + +template <class T> void +ACE_Unbounded_Set_Ex<T>::delete_nodes (void) +{ + ACE_Node<T> *curr = this->head_->next_; + ACE_ASSERT (number_of_iterators_ == 0); + // Keep looking until we've hit the dummy node. + + while (curr != this->head_) + { + ACE_Node<T> *temp = curr; + curr = curr->next_; + if (!temp->deleted_) + this->cur_size_--; + ACE_DES_FREE_TEMPLATE (temp, + this->allocator_->free, + ACE_Node, + <T>); + } + + // Reset the list to be a circular list with just a dummy node. + this->head_->next_ = this->head_; +} + +template <class T> void +ACE_Unbounded_Set_Ex<T>::cleanup () +{ + /// curr is the address of the chaining + ACE_Node<T> **curr = &(this->head_->next_); + ACE_ASSERT (number_of_iterators_ == 0); + + // Keep looking until we've hit the dummy node. + while (*curr != this->head_) + { + if ((*curr)->deleted_) + { + ACE_Node<T> *temp = *curr; + *curr = (*curr)->next_; // skip the deleted, curr is still the same + ACE_DES_FREE_TEMPLATE (temp, + this->allocator_->free, + ACE_Node, + <T>); + } + else + { + curr = &((*curr)->next_); + } + } +} + +template <class T> +ACE_Unbounded_Set_Ex<T>::~ACE_Unbounded_Set_Ex (void) +{ + // ACE_TRACE ("ACE_Unbounded_Set_Ex<T>::~ACE_Unbounded_Set_Ex"); + + this->delete_nodes (); + + // Delete the dummy node. + ACE_DES_FREE_TEMPLATE (head_, + this->allocator_->free, + ACE_Node, + <T>); + this->head_ = 0; +} + +template <class T> +ACE_Unbounded_Set_Ex<T>::ACE_Unbounded_Set_Ex (ACE_Allocator *alloc) + : head_ (0), + cur_size_ (0), + allocator_ (alloc), + number_of_iterators_ (0) +{ + // ACE_TRACE ("ACE_Unbounded_Set_Ex<T>::ACE_Unbounded_Set_Ex"); + + 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_Set_Ex<T>::ACE_Unbounded_Set_Ex (const ACE_Unbounded_Set_Ex<T> &us) + : head_ (0), + cur_size_ (0), + allocator_ (us.allocator_), + number_of_iterators_ (0) +{ + ACE_TRACE ("ACE_Unbounded_Set_Ex<T>::ACE_Unbounded_Set_Ex"); + + 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_Set_Ex<T>::operator= (const ACE_Unbounded_Set_Ex<T> &us) +{ + ACE_TRACE ("ACE_Unbounded_Set_Ex<T>::operator="); + + if (this != &us) + { + this->delete_nodes (); + this->copy_nodes (us); + } +} + +template <class T> int +ACE_Unbounded_Set_Ex<T>::find (const T &item) const +{ + // ACE_TRACE ("ACE_Unbounded_Set_Ex<T>::find"); + // Set <item> into the dummy node. + this->head_->item_ = item; + + ACE_Node<T> *temp = this->head_->next_; + + // Keep looping until we find the item. + while (!(temp->item_ == item && !temp->deleted_)) + temp = temp->next_; + + // If we found the dummy node then it's not really there, otherwise, + // it is there. + return temp == this->head_ ? -1 : 0; +} + +template <class T> int +ACE_Unbounded_Set_Ex<T>::insert (const T &item) +{ + // ACE_TRACE ("ACE_Unbounded_Set_Ex<T>::insert"); + if (this->find (item) == 0) + return 1; + else + return this->insert_tail (item); +} + +template <class T> int +ACE_Unbounded_Set_Ex<T>::remove (const T &item) +{ + // ACE_TRACE ("ACE_Unbounded_Set_Ex<T>::remove"); + + // Insert the item to be founded into the dummy node. + this->head_->item_ = item; + this->head_->deleted_ = false; + + ACE_Node<T> *curr = this->head_; + + while (!(curr->next_->item_ == item) || curr->next_->deleted_) + curr = curr->next_; + + if (curr->next_ == this->head_) + return -1; // Item was not found. + else + { + this->cur_size_--; + ACE_Node<T> *temp = curr->next_; + if (number_of_iterators_>0) + { + temp->deleted_=true; + } + else + { + // Skip over the node that we're deleting. + curr->next_ = temp->next_; + ACE_DES_FREE_TEMPLATE (temp, + this->allocator_->free, + ACE_Node, + <T>); + } + return 0; + } +} + +template <class T> ACE_Unbounded_Set_Ex_Iterator<T> +ACE_Unbounded_Set_Ex<T>::begin (void) +{ + // ACE_TRACE ("ACE_Unbounded_Set_Ex<T>::begin"); + return ACE_Unbounded_Set_Ex_Iterator<T> (*this); +} + +template <class T> ACE_Unbounded_Set_Ex_Iterator<T> +ACE_Unbounded_Set_Ex<T>::end (void) +{ + // ACE_TRACE ("ACE_Unbounded_Set_Ex<T>::end"); + return ACE_Unbounded_Set_Ex_Iterator<T> (*this, 1); +} + +template <class T> void +ACE_Unbounded_Set_Ex<T>::iterator_add (void) const +{ + number_of_iterators_++; +} + +template <class T> void +ACE_Unbounded_Set_Ex<T>::iterator_leave (void) +{ + ACE_ASSERT (number_of_iterators_ > 0); + number_of_iterators_--; + if (number_of_iterators_ == 0) + cleanup (); +} + +template <class T> void +ACE_Unbounded_Set_Ex<T>::const_iterator_leave (void) const +{ + ACE_ASSERT (number_of_iterators_ > 0); + number_of_iterators_--; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Unbounded_Set_Ex_Iterator) + +template <class T> void +ACE_Unbounded_Set_Ex_Iterator<T>::dump (void) const +{ + // ACE_TRACE ("ACE_Unbounded_Set_Ex_Iterator<T>::dump"); +} + +template <class T> +ACE_Unbounded_Set_Ex_Iterator<T>::ACE_Unbounded_Set_Ex_Iterator (ACE_Unbounded_Set_Ex<T> &s, int end) + : current_ (end == 0 ? s.head_->next_ : s.head_ ), set_ (&s) +{ + // ACE_TRACE ("ACE_Unbounded_Set_Ex_Iterator<T>::ACE_Unbounded_Set_Ex_Iterator"); + // the first one may be deleted + while (this->current_->deleted_ && this->current_ != this->set_->head_) + this->current_ = this->current_->next_; + registered_in_set_ = (!end && this->current_ != this->set_->head_); + if (registered_in_set_) + set_->iterator_add (); +} + +template <class T> +ACE_Unbounded_Set_Ex_Iterator<T>::ACE_Unbounded_Set_Ex_Iterator (const ACE_Unbounded_Set_Ex_Iterator<T> &o) + : current_ (o.current_), set_ (o.set_), + registered_in_set_ (o.registered_in_set_) +{ + if (registered_in_set_) + set_->iterator_add (); +} + +template <class T> void +ACE_Unbounded_Set_Ex_Iterator<T>::operator= (const ACE_Unbounded_Set_Ex_Iterator &o) +{ + if (this == &o) + return; + if (registered_in_set_) + set_->iterator_leave (); + this->set_ = o.set_; + this->current_ = o.current_; + this->registered_in_set_ = o.registered_in_set_; + if (registered_in_set_) + set_->iterator_add (); +} + + +template <class T> +ACE_Unbounded_Set_Ex_Iterator<T>::~ACE_Unbounded_Set_Ex_Iterator () +{ + if (registered_in_set_) + set_->iterator_leave (); +} + +template <class T> int +ACE_Unbounded_Set_Ex_Iterator<T>::advance (void) +{ + // ACE_TRACE ("ACE_Unbounded_Set_Ex_Iterator<T>::advance"); + this->current_ = this->current_->next_; + while (this->current_->deleted_ && this->current_ != this->set_->head_) + this->current_ = this->current_->next_; + int completed = (this->current_ == this->set_->head_); + if (completed && registered_in_set_) + { + set_->iterator_leave (); + registered_in_set_ = false; + } + return !completed; +} + +template <class T> int +ACE_Unbounded_Set_Ex_Iterator<T>::first (void) +{ + // ACE_TRACE ("ACE_Unbounded_Set_Ex_Iterator<T>::first"); + this->current_ = this->set_->head_->next_; + while (this->current_->deleted_ && this->current_ != this->set_->head_) + this->current_ = this->current_->next_; + int non_empty = (this->current_ != this->set_->head_); + if (non_empty && !registered_in_set_) + { + registered_in_set_ = true; + set_->iterator_add (); + } + return non_empty; +} + +template <class T> int +ACE_Unbounded_Set_Ex_Iterator<T>::done (void) const +{ + ACE_TRACE ("ACE_Unbounded_Set_Ex_Iterator<T>::done"); + + return this->current_ == this->set_->head_; +} + +template <class T> int +ACE_Unbounded_Set_Ex_Iterator<T>::next (T *&item) +{ + // ACE_TRACE ("ACE_Unbounded_Set_Ex_Iterator<T>::next"); + int completed = (this->current_ == this->set_->head_); + if (completed) + { + if (registered_in_set_) + { + set_->iterator_leave (); + registered_in_set_ = false; + } + return 0; + } + item = &this->current_->item_; + return 1; +} + +template <class T> ACE_Unbounded_Set_Ex_Iterator<T> +ACE_Unbounded_Set_Ex_Iterator<T>::operator++ (int) +{ + //ACE_TRACE ("ACE_Unbounded_Set_Ex_Iterator<T>::operator++ (int)"); + ACE_Unbounded_Set_Ex_Iterator<T> retv (*this); + + // postfix operator + + this->advance (); + return retv; +} + +template <class T> ACE_Unbounded_Set_Ex_Iterator<T>& +ACE_Unbounded_Set_Ex_Iterator<T>::operator++ (void) +{ + // ACE_TRACE ("ACE_Unbounded_Set_Ex_Iterator<T>::operator++ (void)"); + + // prefix operator + + this->advance (); + return *this; +} + +template <class T> T& +ACE_Unbounded_Set_Ex_Iterator<T>::operator* (void) +{ + //ACE_TRACE ("ACE_Unbounded_Set_Ex_Iterator<T>::operator*"); + T *retv = 0; + + int result = this->next (retv); + ACE_ASSERT (result != 0); + ACE_UNUSED_ARG (result); + + return *retv; +} + +template <class T> int +ACE_Unbounded_Set_Ex_Iterator<T>::operator== (const ACE_Unbounded_Set_Ex_Iterator<T> &rhs) const +{ + //ACE_TRACE ("ACE_Unbounded_Set_Ex_Iterator<T>::operator=="); + return (this->set_ == rhs.set_ && this->current_ == rhs.current_); +} + +template <class T> int +ACE_Unbounded_Set_Ex_Iterator<T>::operator!= (const ACE_Unbounded_Set_Ex_Iterator<T> &rhs) const +{ + //ACE_TRACE ("ACE_Unbounded_Set_Ex_Iterator<T>::operator!="); + return (this->set_ != rhs.set_ || this->current_ != rhs.current_); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Unbounded_Set_Ex_Const_Iterator) + +template <class T> void +ACE_Unbounded_Set_Ex_Const_Iterator<T>::dump (void) const +{ + // ACE_TRACE ("ACE_Unbounded_Set_Ex_Const_Iterator<T>::dump"); +} + +template <class T> +ACE_Unbounded_Set_Ex_Const_Iterator<T>::ACE_Unbounded_Set_Ex_Const_Iterator (const ACE_Unbounded_Set_Ex<T> &s, int end) + : current_ (end == 0 ? s.head_->next_ : s.head_ ), set_ (&s) +{ + // ACE_TRACE ("ACE_Unbounded_Set_Ex_Const_Iterator<T>::ACE_Unbounded_Set_Ex_Const_Iterator"); + // the first one may be deleted + while (this->current_->deleted_ && this->current_ != this->set_->head_) + this->current_ = this->current_->next_; + registered_in_set_ = (!end && this->current_ != this->set_->head_); + if (registered_in_set_) + set_->iterator_add (); +} + +template <class T> +ACE_Unbounded_Set_Ex_Const_Iterator<T>::ACE_Unbounded_Set_Ex_Const_Iterator + (const ACE_Unbounded_Set_Ex_Const_Iterator<T> &o) + : current_ (o.current_), + set_ (o.set_), + registered_in_set_ (o.registered_in_set_) +{ + if (registered_in_set_) + set_->iterator_add (); +} + +template <class T> +void ACE_Unbounded_Set_Ex_Const_Iterator<T>::operator= + (const ACE_Unbounded_Set_Ex_Const_Iterator& o) +{ + if (this == &o) + return; + if (registered_in_set_) + set_->const_iterator_leave (); + this->set_ = o.set_; + this->current_ = o.current_; + this->registered_in_set_ = o.registered_in_set_; + if (registered_in_set_) + set_->iterator_add (); +} + +template <class T> +ACE_Unbounded_Set_Ex_Const_Iterator<T>::~ACE_Unbounded_Set_Ex_Const_Iterator () +{ + if (registered_in_set_) + set_->const_iterator_leave (); +} + +template <class T> int +ACE_Unbounded_Set_Ex_Const_Iterator<T>::advance (void) +{ + // ACE_TRACE ("ACE_Unbounded_Set_Ex_Const_Iterator<T>::advance"); + this->current_ = this->current_->next_; + while (this->current_->deleted_ && this->current_ != this->set_->head_) + this->current_ = this->current_->next_; + int completed = (this->current_ == this->set_->head_); + if (completed && registered_in_set_) + { + set_->const_iterator_leave (); + registered_in_set_ = false; + } + return !completed; +} + +template <class T> int +ACE_Unbounded_Set_Ex_Const_Iterator<T>::first (void) +{ + // ACE_TRACE ("ACE_Unbounded_Set_Ex_Const_Iterator<T>::first"); + this->current_ = this->set_->head_->next_; + while (this->current_->deleted_ && this->current_ != this->set_->head_) + this->current_ = this->current_->next_; + int non_empty = (this->current_ != this->set_->head_); + if (non_empty && !registered_in_set_) + { + registered_in_set_ = true; + set_->iterator_add (); + } + return non_empty; +} + +template <class T> int +ACE_Unbounded_Set_Ex_Const_Iterator<T>::done (void) const +{ + ACE_TRACE ("ACE_Unbounded_Set_Ex_Const_Iterator<T>::done"); + + return this->current_ == this->set_->head_; +} + +template <class T> int +ACE_Unbounded_Set_Ex_Const_Iterator<T>::next (T *&item) +{ + // ACE_TRACE ("ACE_Unbounded_Set_Ex_Const_Iterator<T>::next"); + int completed = (this->current_ == this->set_->head_); + if (completed) + { + if (registered_in_set_) + { + set_->const_iterator_leave (); + registered_in_set_ = false; + } + return 0; + } + item = &this->current_->item_; + return 1; +} + +template <class T> ACE_Unbounded_Set_Ex_Const_Iterator<T> +ACE_Unbounded_Set_Ex_Const_Iterator<T>::operator++ (int) +{ + //ACE_TRACE ("ACE_Unbounded_Set_Ex_Const_Iterator<T>::operator++ (int)"); + ACE_Unbounded_Set_Ex_Const_Iterator<T> retv (*this); + + // postfix operator + + this->advance (); + return retv; +} + +template <class T> ACE_Unbounded_Set_Ex_Const_Iterator<T>& +ACE_Unbounded_Set_Ex_Const_Iterator<T>::operator++ (void) +{ + // ACE_TRACE ("ACE_Unbounded_Set_Ex_Const_Iterator<T>::operator++ (void)"); + + // prefix operator + + this->advance (); + return *this; +} + +template <class T> T& +ACE_Unbounded_Set_Ex_Const_Iterator<T>::operator* (void) +{ + //ACE_TRACE ("ACE_Unbounded_Set_Ex_Const_Iterator<T>::operator*"); + T *retv = 0; + + int result = this->next (retv); + ACE_ASSERT (result != 0); + ACE_UNUSED_ARG (result); + + return *retv; +} + +#endif /* ACE_UNBOUNDED_SET_EX_C */ diff --git a/ace/Unbounded_Set_Ex.h b/ace/Unbounded_Set_Ex.h new file mode 100644 index 00000000000..29811d19a15 --- /dev/null +++ b/ace/Unbounded_Set_Ex.h @@ -0,0 +1,359 @@ +/* -*- C++ -*- */ + +//============================================================================= +/** + * @file Unbounded_Set_Ex.h + * + * $Id$ + * + * @author Douglas C. Schmidt <schmidt@cs.wustl.edu> + * ACE_Unbounded_Set Extension by Rudolf Weber <rfweber@tesionmail.de> + * + * If iterators are working in an Unbounded_Set_Ex, the elements are not + * deleted physically, but marked as deleted. + * There is a bookkeeping of the iterators active in the set. + * It is an error if a set is reset() or destructed while iterators are + * still working on the set. + * + * CAUTION: Pay attention to the state of the iterators. + * Deleting a set, or an element in a set, is only feasible + * when no iterator is active. + * + */ +//============================================================================= + +#ifndef ACE_UNBOUNDED_SET_EX_H +#define ACE_UNBOUNDED_SET_EX_H +#include "ace/pre.h" + +#include "ace/Node.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +class ACE_Allocator; + +/** + * @class ACE_Unbounded_Set_Ex_Iterator + * + * @brief Implement an iterator over an unbounded set. + */ +template <class T> +class ACE_Unbounded_Set_Ex_Iterator +{ +public: + // = Initialization method. + ACE_Unbounded_Set_Ex_Iterator (ACE_Unbounded_Set_Ex<T> &s, int end = 0); + ACE_Unbounded_Set_Ex_Iterator (const ACE_Unbounded_Set_Ex_Iterator &o); + void operator= (const ACE_Unbounded_Set_Ex_Iterator &o); + ~ACE_Unbounded_Set_Ex_Iterator (); + + // = Iteration methods. + + /// Pass back the <next_item> that hasn't been seen in the Set. + /// Returns 0 when all items have been seen, else 1. + int next (T *&next_item); + + /// Move forward by one element in the set. Returns 0 when all the + /// items in the set have been seen, else 1. + int advance (void); + + /// Move to the first element in the set. Returns 0 if the + /// set is empty, else 1. + int first (void); + + /// Returns 1 when all items have been seen, else 0. + int done (void) const; + + /// Dump the state of an object. + void dump (void) const; + + // = STL styled iteration, compare, and reference functions. + + /// Postfix advance. + ACE_Unbounded_Set_Ex_Iterator<T> operator++ (int); + + /// Prefix advance. + ACE_Unbounded_Set_Ex_Iterator<T>& operator++ (void); + + /// Returns a reference to the internal element <this> is pointing to. + T& operator* (void); + + /// Check if two iterators point to the same position + int operator== (const ACE_Unbounded_Set_Ex_Iterator<T> &) const; + int operator!= (const ACE_Unbounded_Set_Ex_Iterator<T> &) const; + + /// Declare the dynamic allocation hooks. + ACE_ALLOC_HOOK_DECLARE; + +private: + + /// Pointer to the current node in the iteration. + ACE_Node<T> *current_; + + /// Pointer to the set we're iterating over. + ACE_Unbounded_Set_Ex<T> *set_; + + // Flag that indicates whether this iterator is registered at the set. + int registered_in_set_; +}; + +/** + * @class ACE_Unbounded_Set_Ex_Const_Iterator + * + * @brief Implement a const iterator over an unbounded set. + * + * The bookkeeping operations are regarded as const. (The member + * number_of_iterators_ in ACE_Unbounded_Set_Ex is `mutable'.) + * Some asynchronous activity may cause a deletion under a Const_Iterator + * so Const_Iterators are registered too. + * However, the cleanup operation isn't const at all, thus it is not + * called from const iterators. + * + */ +template <class T> +class ACE_Unbounded_Set_Ex_Const_Iterator +{ +public: + // = Initialization method. + ACE_Unbounded_Set_Ex_Const_Iterator (const ACE_Unbounded_Set_Ex<T> &s, int end = 0); + ACE_Unbounded_Set_Ex_Const_Iterator (const ACE_Unbounded_Set_Ex_Const_Iterator& o); + void operator= (const ACE_Unbounded_Set_Ex_Const_Iterator& o); + ~ACE_Unbounded_Set_Ex_Const_Iterator (); + + // = Iteration methods. + + /// Pass back the <next_item> that hasn't been seen in the Set. + /// Returns 0 when all items have been seen, else 1. + int next (T *&next_item); + + /// Move forward by one element in the set. Returns 0 when all the + /// items in the set have been seen, else 1. + int advance (void); + + /// Move to the first element in the set. Returns 0 if the + /// set is empty, else 1. + int first (void); + + /// Returns 1 when all items have been seen, else 0. + int done (void) const; + + /// Dump the state of an object. + void dump (void) const; + + // = STL styled iteration, compare, and reference functions. + + /// Postfix advance. + ACE_Unbounded_Set_Ex_Const_Iterator<T> operator++ (int); + + /// Prefix advance. + ACE_Unbounded_Set_Ex_Const_Iterator<T>& operator++ (void); + + /// Returns a reference to the internal element <this> is pointing to. + T& operator* (void); + + /// Check if two iterators point to the same position + int operator== (const ACE_Unbounded_Set_Ex_Const_Iterator<T> &) const; + int operator!= (const ACE_Unbounded_Set_Ex_Const_Iterator<T> &) const; + + /// Declare the dynamic allocation hooks. + ACE_ALLOC_HOOK_DECLARE; + +private: + + /// Pointer to the current node in the iteration. + ACE_Node<T> *current_; + + /// Pointer to the set we're iterating over. + const ACE_Unbounded_Set_Ex<T> *set_; + + // Flag that indicates whether this iterator is registered at the set. + int registered_in_set_; +}; + +/** + * @class ACE_Unbounded_Set_Ex + * + * @brief Implement a simple unordered set of <T> of unbounded size. + * + * This implementation of an unordered set uses a circular + * linked list with a dummy node. This implementation does not + * allow duplicates, but it maintains FIFO ordering of insertions. + * + * <b> Requirements and Performance Characteristics</b> + * - Internal Structure + * Circular linked list + * - Duplicates allowed? + * No + * - Random access allowed? + * No + * - Search speed + * Linear + * - Insert/replace speed + * Linear + * - Iterator still valid after change to container? + * Yes + * - Frees memory for removed elements? + * Yes + * - Items inserted by + * Value + * - Requirements for contained type + * -# Default constructor + * -# Copy constructor + * -# operator= + * -# operator== + * + */ +template <class T> +class ACE_Unbounded_Set_Ex +{ +public: + friend class ACE_Unbounded_Set_Ex_Iterator<T>; + friend class ACE_Unbounded_Set_Ex_Const_Iterator<T>; + + // Trait definition. + typedef ACE_Unbounded_Set_Ex_Iterator<T> ITERATOR; + typedef ACE_Unbounded_Set_Ex_Iterator<T> iterator; + typedef ACE_Unbounded_Set_Ex_Const_Iterator<T> CONST_ITERATOR; + typedef ACE_Unbounded_Set_Ex_Const_Iterator<T> const_iterator; + + // = Initialization and termination methods. + /// Constructor. Use user specified allocation strategy + /// if specified. + /** + * Initialize an empty set using the allocation strategy of the user if + * provided. + */ + ACE_Unbounded_Set_Ex (ACE_Allocator *alloc = 0); + + /// Copy constructor. + /** + * Initialize this set to be an exact copy of the set provided. + */ + ACE_Unbounded_Set_Ex (const ACE_Unbounded_Set_Ex<T> &); + + /// Assignment operator. + /** + * Perform a deep copy of the rhs into the lhs. + */ + void operator= (const ACE_Unbounded_Set_Ex<T> &); + + /// Destructor. + /** + * Destroy the nodes of the set. + */ + ~ACE_Unbounded_Set_Ex (void); + + // = Check boundary conditions. + + /// Returns 1 if the container is empty, otherwise returns 0. + /** + * Constant time is_empty check. + */ + int is_empty (void) const; + + /// Returns 0. + /** + * Always returns 0 since the set can never fill up. + */ + int is_full (void) const; + + // = Classic unordered set operations. + + ///Linear insertion of an item. + /** + * Insert <new_item> into the set (doesn't allow duplicates). + * Returns -1 if failures occur, 1 if item is already present, else + * 0. + */ + int insert (const T &new_item); + + /// Insert <item> at the tail of the set (doesn't check for + /// duplicates). + /** + * Constant time insert at the end of the set. + */ + int insert_tail (const T &item); + + ///Linear remove operation. + /** + * Remove first occurrence of <item> from the set. Returns 0 if + * it removes the item, -1 if it can't find the item, and -1 if a + * failure occurs. + */ + int remove (const T &item); + + /// Finds if <item> occurs in the set. Returns 0 if find succeeds, + /// else -1. + /** + * Performs a linear find operation. + */ + int find (const T &item) const; + + /// Size of the set. + /** + * Access the size of the set. + */ + size_t size (void) const; + + /// Dump the state of an object. + void dump (void) const; + + /// Reset the <ACE_Unbounded_Set_Ex> to be empty. + /** + * Delete the nodes of the set. + */ + void reset (void); + + // = STL-styled unidirectional iterator factory. + ACE_Unbounded_Set_Ex_Iterator<T> begin (void); + ACE_Unbounded_Set_Ex_Iterator<T> end (void); + + /// An Iterator has to register itself here. + void iterator_add () const; + /// A non-const Iterator has to unregister itself here. + void iterator_leave (); + /// A Const_Iterator has to unregister itself here. + void const_iterator_leave () const; + + /// Declare the dynamic allocation hooks. + ACE_ALLOC_HOOK_DECLARE; + +private: + /// Delete all the nodes in the Set. + void delete_nodes (void); + + /// Copy nodes into this set. + void copy_nodes (const ACE_Unbounded_Set_Ex<T> &); + + /// Really delete all nodes marked for deletion. + void cleanup (); + + /// Head of the linked list of Nodes. + ACE_Node<T> *head_; + + /// Current size of the set. + size_t cur_size_; + + /// Allocation strategy of the set. + ACE_Allocator *allocator_; + + /// Number of iterators working on this set. + mutable int number_of_iterators_; +}; + +#if defined (__ACE_INLINE__) +#include "ace/Unbounded_Set_Ex.inl" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Unbounded_Set_Ex.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Unbounded_Set_Ex.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#include "ace/post.h" +#endif /* ACE_UNBOUNDED_SET_EX_H */ diff --git a/ace/Unbounded_Set_Ex.inl b/ace/Unbounded_Set_Ex.inl new file mode 100644 index 00000000000..c6f38c7a9a0 --- /dev/null +++ b/ace/Unbounded_Set_Ex.inl @@ -0,0 +1,16 @@ +/* -*- C++ -*- */ +// $Id$ + +template <class T> ACE_INLINE int +ACE_Unbounded_Set_Ex<T>::is_empty (void) const +{ + ACE_TRACE ("ACE_Unbounded_Set_Ex<T>::is_empty"); + return this->head_ == this->head_->next_; +} + +template <class T> ACE_INLINE int +ACE_Unbounded_Set_Ex<T>::is_full (void) const +{ + ACE_TRACE ("ACE_Unbounded_Set_Ex<T>::is_full"); + return 0; // We should implement a "node of last resort for this..." +} |