summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorokellogg <okellogg@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2003-04-01 10:59:08 +0000
committerokellogg <okellogg@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2003-04-01 10:59:08 +0000
commit71636b8bab2396a4acd8071c759e6d34c9bdfe64 (patch)
tree87cf620ef93909fcb9e740c5c7856cb68d378bf1
parent79361a43bbc84aa3f17a27e502a759e4ec9c64d9 (diff)
downloadATCD-71636b8bab2396a4acd8071c759e6d34c9bdfe64.tar.gz
ChangeLogTag:Tue Apr 1 12:48:33 CEST 2003 Oliver Kellogg <oliver.kellogg@sysde.eads.net>
-rw-r--r--ace/Makefile.ace1
-rw-r--r--ace/Node.cpp9
-rw-r--r--ace/Node.h9
-rw-r--r--ace/Unbounded_Set_Ex.cpp620
-rw-r--r--ace/Unbounded_Set_Ex.h359
-rw-r--r--ace/Unbounded_Set_Ex.inl16
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..."
+}