summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog-97a53
-rw-r--r--README1
-rw-r--r--ace/Map_Manager.h2
-rw-r--r--ace/OS.h3
-rw-r--r--ace/Proactor.cpp3
-rw-r--r--ace/Proactor.h26
-rw-r--r--ace/Reactor.cpp3
-rw-r--r--ace/Reactor.h19
-rw-r--r--ace/ReactorEx.cpp3
-rw-r--r--ace/ReactorEx.h28
-rw-r--r--ace/Timer_Heap.cpp204
-rw-r--r--ace/Timer_Heap.h159
-rw-r--r--ace/Timer_List.cpp244
-rw-r--r--ace/Timer_List.h138
-rw-r--r--ace/Timer_Queue.cpp298
-rw-r--r--ace/Timer_Queue.h123
-rw-r--r--ace/Timer_Queue.i12
-rw-r--r--examples/Logger/Acceptor-server/server_loggerd.cpp9
-rw-r--r--netsvcs/lib/Logging_Strategy.cpp4
-rw-r--r--netsvcs/lib/Makefile144
-rw-r--r--tests/Thread_Pool_Test.cpp2
-rw-r--r--tests/Timer_Queue_Test.cpp130
22 files changed, 1251 insertions, 357 deletions
diff --git a/ChangeLog-97a b/ChangeLog-97a
index 44517e829e9..6a2006ca745 100644
--- a/ChangeLog-97a
+++ b/ChangeLog-97a
@@ -1,7 +1,58 @@
+Sun Jan 12 16:59:52 1997 Douglas C. Schmidt <schmidt@flamenco.cs.wustl.edu>
+
+ * ace/Timer_List.cpp (schedule): Cleanup the code so that (1)
+ timer_id never == -1 (in order to distinguish it from error
+ return values and (2) so that we avoid an unnecessary check for
+ operator new failure.
+
+ * ace/OS.h: Added a new #define called ACE_DEFAULT_MAX_TIMERS,
+ which specifies the maximum number of ACE_Event_Handlers
+ supported by ACE_Timer_Heap.
+
+ * ace/Proactor.cpp (ACE_Proactor): Updated the allocation of
+ ACE_Timer_Queue so that it really points to an ACE_Timer_List by
+ default. Naturally, this can be overridden by users.
+
+ * ace/ReactorEx.cpp (open): Updated the allocation of
+ ACE_Timer_Queue so that it really points to an ACE_Timer_List by
+ default. Naturally, this can be overridden by users.
+
+ * ace/Reactor.cpp (open): Updated the allocation of
+ ACE_Timer_Queue so that it really points to an ACE_Timer_List by
+ default. Naturally, this can be overridden by users.
+
+ * ace: Added two new classes called ACE_Timer_List and
+ ACE_Timer_Heap, which derive from ACE_Timer_Queue.
+ ACE_Timer_List is essentially the old behavior of
+ ACE_Timer_Queue, i.e., it uses an implementation of a linked
+ list of ACE_Timer_Nodes. ACE_Timer_Heap, on the other hand,
+ uses a heap-based callout queue, which is more appropriate for
+ certain real-time applications.
+
+ * ace/Timer_Queue: Revised the ACE_Timer_Queue implementation so
+ that it's now an abstract base class with most of the
+ implementation details pushed into the ACE_Timer_List and
+ ACE_Timer_Heap subclasses.
+
+ * ace/Timer_Queue.h: Made all the ACE_Timer_Queue methods public
+ so that we can override them in a subclass (e.g., the new
+ ACE_Timer_Heap).
+
+ * examples/Logger/Acceptor-server/server_loggerd.cpp: Fixed this
+ example application so that it only uses a single Reactor (the
+ REACTOR::instance()) rather than two Reactors. Thanks to Sandro
+ Doro <alex@aureus.sublink.org> for reporting this.
+
+ * netsvcs/lib/Logging_Strategy.cpp: Fixed the #include of
+ fstream.h and iostream.h to use the '<' '>' notation rather than
+ the '"' and '"' notation. This avoids problems with running
+ "make depend". Thanks to Rino Simioni <sir@necsy.it> for
+ reporting this fix.
+
Sun Jan 12 18:20:49 1997 David L. Levine <levine@cs.wustl.edu>
* ace/ACE.cpp (round_to_pagesize): fixed typo in reference to
- ACE::pagesize_
+ ACE::pagesize_.
* ace/ACE.cpp: initialize ACE::pagesize_ to 0.
diff --git a/README b/README
index d852d2d52e4..63a300dea17 100644
--- a/README
+++ b/README
@@ -464,6 +464,7 @@ Per Andersson <Per.Andersson@hfera.ericsson.se>
Anthony McConnell <Tonym@datel.demon.co.uk>
Mark Rabotnikov <mark@usp.elscintcorp.co.il>
John Bossom <John.Bossom@Cognos.COM>
+Rino Simioni <sir@necsy.it>
I would particularly like to thank Paul Stephenson, who worked with me
at Ericsson and is now at ObjectSpace. Paul devised the recursive
diff --git a/ace/Map_Manager.h b/ace/Map_Manager.h
index 4f089ade988..14b3bf18b98 100644
--- a/ace/Map_Manager.h
+++ b/ace/Map_Manager.h
@@ -237,7 +237,7 @@ public:
// = Iteration methods.
int next (ACE_Map_Entry<EXT_ID, INT_ID> *&next_entry);
- // Pass back the <entry> that hasn't been seen in the Set.
+ // Pass back the next <entry> that hasn't been seen in the Set.
// Returns 0 when all items have been seen, else 1.
int advance (void);
diff --git a/ace/OS.h b/ace/OS.h
index 183f5100bf8..7d635e6e2b2 100644
--- a/ace/OS.h
+++ b/ace/OS.h
@@ -93,6 +93,9 @@
// (does anyone know how to figure out the right values?!)
#define ACE_DEFAULT_MAX_SEGMENTS 6
+// Maximum number of <ACE_Event_Handler>s supported by <ACE_Timer_Heap>.
+#define ACE_DEFAULT_MAX_TIMERS 20000
+
// Used by the FIFO tests.
#define ACE_DEFAULT_RENDEZVOUS "/tmp/fifo.ace"
diff --git a/ace/Proactor.cpp b/ace/Proactor.cpp
index 06813981242..ac33079a690 100644
--- a/ace/Proactor.cpp
+++ b/ace/Proactor.cpp
@@ -3,6 +3,7 @@
#define ACE_BUILD_DLL
#include "ace/Proactor.h"
+#include "ace/Timer_List.h"
#if !defined (__ACE_INLINE__)
#include "ace/Proactor.i"
@@ -167,7 +168,7 @@ ACE_Proactor::ACE_Proactor (size_t number_of_threads, ACE_Timer_Queue *tq)
{
if (this->timer_queue_ == 0)
{
- ACE_NEW (this->timer_queue_, ACE_Timer_Queue);
+ ACE_NEW (this->timer_queue_, ACE_Timer_List);
this->delete_timer_queue_ = 1;
}
diff --git a/ace/Proactor.h b/ace/Proactor.h
index 4116c15713c..f34ca85f3f2 100644
--- a/ace/Proactor.h
+++ b/ace/Proactor.h
@@ -127,22 +127,23 @@ public:
const void *arg,
const ACE_Time_Value &delta,
const ACE_Time_Value &interval = ACE_Time_Value::zero);
- // Schedule an <Event_Handler> that will expire after <delay> amount
+ // Schedule an <event_handler> that will expire after <delay> amount
// of time. If it expires then <arg> is passed in as the value to
- // the <Event_Handler>'s <handle_timeout> callback method. If
+ // the <event_handler>'s <handle_timeout> callback method. If
// <interval> is != to <ACE_Time_Value::zero> then it is used to
- // reschedule the <Event_Handler> automatically. This method
- // returns a timer handle that uniquely identifies the
- // <Event_Handler> in an internal list. This timer handle can be
- // used to cancel an <Event_Handler> before it expires. The
- // cancellation ensures that timer_ids are unique up to values of
- // greater than 2 billion timers. As long as timers don't stay
- // around longer than this there should be no problems with
- // accidentally deleting the wrong timer.
+ // reschedule the <event_handler> automatically. This method
+ // returns a <timer_id> that uniquely identifies the <event_handler>
+ // in an internal list. This <timer_id> can be used to cancel an
+ // <event_handler> before it expires. The cancellation ensures that
+ // <timer_ids> are unique up to values of greater than 2 billion
+ // timers. As long as timers don't stay around longer than this
+ // there should be no problems with accidentally deleting the wrong
+ // timer. Returns -1 on failure (which is guaranteed never to be a
+ // valid <timer_id>.
virtual int cancel_timer (ACE_Event_Handler *handler);
// Cancel all <Event_Handlers> that match the address of
- // <Event_Handler>.
+ // <Event_Handler>. Returns number of handler's cancelled.
virtual int cancel_timer (int timer_id, const void **arg = 0);
// Cancel the single <ACE_Event_Handler> that matches the <timer_id>
@@ -150,6 +151,9 @@ public:
// non-NULL then it will be set to point to the ``magic cookie''
// argument passed in when the <Event_Handler> was registered. This
// makes it possible to free up the memory and avoid memory leaks.
+ // Returns 1 if cancellation succeeded and 0 if the <timer_id>
+ // wasn't found.
+
protected:
diff --git a/ace/Reactor.cpp b/ace/Reactor.cpp
index 814b82f35e7..e18dd4dc881 100644
--- a/ace/Reactor.cpp
+++ b/ace/Reactor.cpp
@@ -5,6 +5,7 @@
#include "ace/Synch_T.h"
#include "ace/SOCK_Acceptor.h"
#include "ace/SOCK_Connector.h"
+#include "ace/Timer_List.h"
#include "ace/Reactor.h"
#if !defined (__ACE_INLINE__)
@@ -858,7 +859,7 @@ ACE_Reactor::open (size_t size,
// quickly due to the use of sockets as a notification
// mechanism). At least this way the timer_queue_ isn't 0, so
// we can still use the Reactor as a timer...
- ACE_NEW_RETURN (this->timer_queue_, ACE_Timer_Queue, -1);
+ ACE_NEW_RETURN (this->timer_queue_, ACE_Timer_List, -1);
this->delete_timer_queue_ = 1;
}
diff --git a/ace/Reactor.h b/ace/Reactor.h
index 70f19a6972c..2c02bf4f8a1 100644
--- a/ace/Reactor.h
+++ b/ace/Reactor.h
@@ -452,17 +452,18 @@ public:
// the <event_handler>'s <handle_timeout> callback method. If
// <interval> is != to <ACE_Time_Value::zero> then it is used to
// reschedule the <event_handler> automatically. This method
- // returns a timer handle that uniquely identifies the
- // <event_handler> in an internal list. This timer handle can be
- // used to cancel an <event_handler> before it expires. The
- // cancellation ensures that timer_ids are unique up to values of
- // greater than 2 billion timers. As long as timers don't stay
- // around longer than this there should be no problems with
- // accidentally deleting the wrong timer.
+ // returns a <timer_id> that uniquely identifies the <event_handler>
+ // in an internal list. This <timer_id> can be used to cancel an
+ // <event_handler> before it expires. The cancellation ensures that
+ // <timer_ids> are unique up to values of greater than 2 billion
+ // timers. As long as timers don't stay around longer than this
+ // there should be no problems with accidentally deleting the wrong
+ // timer. Returns -1 on failure (which is guaranteed never to be a
+ // valid <timer_id>.
virtual int cancel_timer (ACE_Event_Handler *event_handler);
// Cancel all <event_handlers> that match the address of
- // <event_handler>.
+ // <event_handler>. Returns number of handler's cancelled.
virtual int cancel_timer (int timer_id, const void **arg = 0);
// Cancel the single <ACE_Event_Handler> that matches the <timer_id>
@@ -470,6 +471,8 @@ public:
// non-NULL then it will be set to point to the ``magic cookie''
// argument passed in when the <Event_Handler> was registered. This
// makes it possible to free up the memory and avoid memory leaks.
+ // Returns 1 if cancellation succeeded and 0 if the <timer_id>
+ // wasn't found.
// = High-level Event_Handler scheduling operations
diff --git a/ace/ReactorEx.cpp b/ace/ReactorEx.cpp
index dcffd36b986..5e79e04e85e 100644
--- a/ace/ReactorEx.cpp
+++ b/ace/ReactorEx.cpp
@@ -3,6 +3,7 @@
#define ACE_BUILD_DLL
#include "ace/ReactorEx.h"
+#include "ace/Timer_List.h"
#if defined (ACE_WIN32)
@@ -197,7 +198,7 @@ ACE_ReactorEx::open (size_t size,
if (this->timer_queue_ == 0)
{
- ACE_NEW_RETURN (this->timer_queue_, ACE_Timer_Queue, -1);
+ ACE_NEW_RETURN (this->timer_queue_, ACE_Timer_List, -1);
this->delete_timer_queue_ = 1;
}
diff --git a/ace/ReactorEx.h b/ace/ReactorEx.h
index 6b04f1eaf1a..9aacce36118 100644
--- a/ace/ReactorEx.h
+++ b/ace/ReactorEx.h
@@ -305,21 +305,23 @@ public:
const void *arg,
const ACE_Time_Value &delta,
const ACE_Time_Value &interval = ACE_Time_Value::zero);
- // Schedule an Event Handler <eh> that will expire after <delta>
- // amount of time. If it expires then <arg> is passed in as the
- // value to <handle_timeout> method call on <eh>. If <interval> is
- // != to ACE_Time_Value::zero then it is used to reschedule <eh>
- // automatically. This method returns a timer handle that uniquely
- // identifies the <eh> in an internal list. This timer handle can
- // be used to cancel an Event_Handler before it expires. The
- // cancellation ensures that timer_ids are unique up to values of
- // greater than 2 billion timers. As long as timers don't stay
- // around longer than this there should be no problems with
- // accidentally deleting the wrong timer.
+ // Schedule an <event_handler> that will expire after <delay> amount
+ // of time. If it expires then <arg> is passed in as the value to
+ // the <event_handler>'s <handle_timeout> callback method. If
+ // <interval> is != to <ACE_Time_Value::zero> then it is used to
+ // reschedule the <event_handler> automatically. This method
+ // returns a <timer_id> that uniquely identifies the <event_handler>
+ // in an internal list. This <timer_id> can be used to cancel an
+ // <event_handler> before it expires. The cancellation ensures that
+ // <timer_ids> are unique up to values of greater than 2 billion
+ // timers. As long as timers don't stay around longer than this
+ // there should be no problems with accidentally deleting the wrong
+ // timer. Returns -1 on failure (which is guaranteed never to be a
+ // valid <timer_id>.
virtual int cancel_timer (ACE_Event_Handler *event_handler);
// Cancel all Event_Handlers that match the address of
- // <event_handler>.
+ // <event_handler>. Returns number of handler's cancelled.
virtual int cancel_timer (int timer_id, const void **arg = 0);
// Cancel the single Event_Handler that matches the <timer_id> value
@@ -327,6 +329,8 @@ public:
// non-NULL then it will be set to point to the ``magic cookie''
// argument passed in when the Event_Handler was registered. This
// makes it possible to free up the memory and avoid memory leaks.
+ // Returns 1 if cancellation succeeded and 0 if the <timer_id>
+ // wasn't found.
// = Notification methods.
diff --git a/ace/Timer_Heap.cpp b/ace/Timer_Heap.cpp
new file mode 100644
index 00000000000..b69872928eb
--- /dev/null
+++ b/ace/Timer_Heap.cpp
@@ -0,0 +1,204 @@
+#include "ace/Timer_Heap.h"
+
+ACE_Timer_Heap_Iterator::ACE_Timer_Heap_Iterator (ACE_Timer_Heap &heap)
+ : timer_heap_ (heap)
+{
+}
+
+int
+ACE_Timer_Heap_Iterator::next (ACE_Timer_Node *&node,
+ const ACE_Time_Value &cur_time)
+{
+ if (this->timer_heap_.cur_size_ == 0
+ || this->timer_heap_.heap_[0]->timer_value_ > cur_time)
+ return 0;
+ else
+ {
+ node = this->timer_heap_.heap_[0];
+
+ // Transfer the last element in the heap to the front and
+ // restore the heap property.
+
+ this->timer_heap_.heap_[0] =
+ this->timer_heap_.heap_[--this->timer_heap_.cur_size_];
+
+ this->timer_heap_.reheap_down ();
+ return 1;
+ }
+}
+
+ACE_Timer_Heap::ACE_Timer_Heap (size_t size)
+ : max_size_ (size),
+ cur_size_ (0),
+ iterator_ (*this)
+{
+ ACE_NEW (this->heap_,
+ ACE_Timer_Node *[size]);
+}
+
+ACE_Timer_Heap::~ACE_Timer_Heap (void)
+{
+ delete [] this->heap_;
+}
+
+// Checks if queue is empty.
+
+int
+ACE_Timer_Heap::is_empty (void) const
+{
+ ACE_TRACE ("ACE_Timer_Heap::is_empty");
+ return this->cur_size_ == 0;
+}
+
+ACE_Timer_Queue_Iterator &
+ACE_Timer_Heap::iterator (void)
+{
+ return this->iterator_;
+}
+
+// Returns earliest time in a non-empty queue.
+
+const ACE_Time_Value &
+ACE_Timer_Heap::earliest_time (void) const
+{
+ ACE_TRACE ("ACE_Timer_Heap::earliest_time");
+ return this->heap_[0]->timer_value_;
+}
+
+void
+ACE_Timer_Heap::dump (void) const
+{
+ for (size_t index = 0; index < this->cur_size_; index++)
+ this->heap_[index]->dump ();
+}
+
+void
+ACE_Timer_Heap::reheap_down (void)
+{
+ int parent = 0;
+ int child = 1;
+ ACE_Timer_Node *temp = this->heap_[parent];
+
+ // Restore the heap property.
+
+ while (child < this->cur_size_)
+ {
+ if (child + 1 < this->cur_size_
+ && this->heap_[child + 1]->timer_value_ > this->heap_[child]->timer_value_)
+ child++;
+
+ if (this->heap_[child]->timer_value_ > temp->timer_value_)
+ {
+ this->heap_[parent] = this->heap_[child];
+ parent = child;
+ // Multiple child by 2 and add 1.
+ child += child + 1;
+ }
+ else
+ break;
+ }
+
+ this->heap_[parent] = temp;
+}
+
+void
+ACE_Timer_Heap::reheap_up (void)
+{
+ int parent;
+ int child = this->cur_size_ - 1;
+ ACE_Timer_Node *temp = this->heap_[child];
+
+ // Restore the heap property.
+
+ while (child > 0)
+ {
+ parent = (child - 1) / 2;
+
+ if (temp->timer_value_ < this->heap_[parent]->timer_value_)
+ {
+ this->heap_[child] = this->heap_[parent];
+ child = parent;
+ }
+ else
+ break;
+ }
+
+ this->heap_[child] = temp;
+}
+
+// Reschedule a periodic timer. This function must be called with the
+// mutex lock held.
+
+void
+ACE_Timer_Heap::reschedule (ACE_Timer_Node *expired)
+{
+ ACE_TRACE ("ACE_Timer_Heap::reschedule");
+
+ // Insert the <expired> node into the end of the heap and restore
+ // the heap property.
+ this->heap_[this->cur_size_++] = expired;
+ this->reheap_up ();
+}
+
+// Insert a new handler that expires at time future_time; if interval
+// is > 0, the handler will be reinvoked periodically.
+
+int
+ACE_Timer_Heap::schedule (ACE_Event_Handler *handler,
+ const void *arg,
+ const ACE_Time_Value &future_time,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_Timer_Heap::schedule");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ // Increment the sequence number (it will wrap around).
+ int timer_id = this->timer_id ();
+
+ if (this->cur_size_ >= this->max_size_)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ else
+ {
+ ACE_Timer_Node *temp;
+
+ ACE_NEW_RETURN (temp,
+ ACE_Timer_Node (handler,
+ arg,
+ future_time,
+ interval,
+ 0,
+ timer_id),
+ -1);
+
+ this->reheap_up (temp);
+ }
+
+ return timer_id;
+}
+
+// Locate and remove the single <ACE_Event_Handler> with a value of
+// <timer_id> from the timer queue.
+
+int
+ACE_Timer_Heap::cancel (int timer_id, const void **arg)
+{
+ ACE_TRACE ("ACE_Timer_Heap::cancel");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ return 0;
+}
+
+// Locate and remove all values of <handler> from the timer queue.
+
+int
+ACE_Timer_Heap::cancel (ACE_Event_Handler *handler)
+{
+ ACE_TRACE ("ACE_Timer_Heap::cancel");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ return 0;
+}
diff --git a/ace/Timer_Heap.h b/ace/Timer_Heap.h
new file mode 100644
index 00000000000..873b7985509
--- /dev/null
+++ b/ace/Timer_Heap.h
@@ -0,0 +1,159 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ace
+//
+// = FILENAME
+// Timer_Heap.h
+//
+// = AUTHOR
+// Doug Schmidt
+//
+// ============================================================================
+
+#if !defined (ACE_TIMER_HEAP_H)
+#define ACE_TIMER_HEAP_H
+
+#include "ace/Timer_Queue.h"
+
+// Forward declaration
+class ACE_Timer_Heap;
+
+class ACE_Export ACE_Timer_Heap_Iterator : public ACE_Timer_Queue_Iterator
+ // = TITLE
+ // Iterates over an <ACE_Timer_Queue>.
+ //
+ // = DESCRIPTION
+ // This is a special type of iterator that "advances" by moving
+ // the head of the timer queue up by one every time.
+{
+public:
+ ACE_Timer_Heap_Iterator (ACE_Timer_Heap &);
+ // Constructor.
+
+ virtual int next (ACE_Timer_Node *&timer_node,
+ const ACE_Time_Value &cur_time);
+ // Pass back the next <timer_node> that hasn't been seen yet, if its
+ // <time_value_> <= <cur_time>. In addition, moves the timer queue
+ // forward by one node. Returns 0 when all <timer_nodes> have been
+ // seen, else 1.
+
+protected:
+ ACE_Timer_Heap &timer_heap_;
+ // Pointer to the <ACE_Timer_Heap> that we are iterating over.
+};
+
+class ACE_Timer_Heap : public ACE_Timer_Queue
+ // = TITLE
+ // Provides an interface to timers.
+ //
+ // = DESCRIPTION
+ // This implementation uses a heap-based callout queue of
+ // absolute times. Therefore, in the average case, scheduling
+ // and expiring <ACE_Event_Handler> timers is O(log N) (where N
+ // is the total number of timers) and canceling timers is O(N)
+ // (since we need to perform linear search for the timer id).
+{
+ friend class ACE_Timer_Heap_Iterator;
+public:
+ // = Initialization and termination methods.
+ ACE_Timer_Heap (size_t size = ACE_DEFAULT_MAX_TIMERS);
+ // Constructor.
+
+ virtual ~ACE_Timer_Heap (void);
+ // Destructor.
+
+ virtual int is_empty (void) const;
+ // True if heap is empty, else false.
+
+ virtual const ACE_Time_Value &earliest_time (void) const;
+ // Returns the time of the earlier node in the Timer_Queue.
+
+ virtual int schedule (ACE_Event_Handler *event_handler,
+ const void *arg,
+ const ACE_Time_Value &delay,
+ const ACE_Time_Value &interval = ACE_Time_Value::zero);
+ // Schedule an <event_handler> that will expire after <delay> amount
+ // of time. If it expires then <arg> is passed in as the value to
+ // the <event_handler>'s <handle_timeout> callback method. If
+ // <interval> is != to <ACE_Time_Value::zero> then it is used to
+ // reschedule the <event_handler> automatically. This method
+ // returns a <timer_id> that uniquely identifies the <event_handler>
+ // in an internal list. This <timer_id> can be used to cancel an
+ // <event_handler> before it expires. The cancellation ensures that
+ // <timer_ids> are unique up to values of greater than 2 billion
+ // timers. As long as timers don't stay around longer than this
+ // there should be no problems with accidentally deleting the wrong
+ // timer. Returns -1 on failure (which is guaranteed never to be a
+ // valid <timer_id>.
+
+ virtual int cancel (ACE_Event_Handler *event_handler);
+ // Cancel all <event_handlers> that match the address of
+ // <event_handler>. Returns number of handler's cancelled.
+
+ virtual int cancel (int timer_id, const void **arg = 0);
+ // Cancel the single <ACE_Event_Handler> that matches the <timer_id>
+ // value (which was returned from the <schedule> method). If arg is
+ // non-NULL then it will be set to point to the ``magic cookie''
+ // argument passed in when the <Event_Handler> was registered. This
+ // makes it possible to free up the memory and avoid memory leaks.
+ // Returns 1 if cancellation succeeded and 0 if the <timer_id>
+ // wasn't found.
+
+ virtual int expire (const ACE_Time_Value &current_time);
+ // Run the <handle_timeout> method for all Timers whose values are
+ // <= <cur_time>. This does not account for <timer_skew>. Returns
+ // the number of <Event_Handler>s for which <handle_timeout> was
+ // called.
+
+ virtual int expire (void);
+ // Run the <handle_timeout> method for all Timers whose values are
+ // <= <ACE_OS::gettimeofday>. Also accounts for <timer_skew>.
+ // Returns the number of <Event_Handler>s for which <handle_timeout>
+ // was called.
+
+ virtual ACE_Time_Value *calculate_timeout (ACE_Time_Value *max);
+ // Determine the next event to timeout. Returns <max> if there are
+ // no pending timers or if all pending timers are longer than max.
+
+ virtual void dump (void) const;
+ // Dump the state of an object.
+
+protected:
+ virtual void reschedule (ACE_Timer_Node *);
+ // Reschedule an "interval" <ACE_Timer_Node>.
+
+ virtual ACE_Timer_Queue_Iterator &iterator (void);
+ // Returns a pointer to this <ACE_Timer_Queue>'s iterator.
+
+private:
+ void reheap_down (void);
+ // Called after a deletion to restore the heap property.
+
+ void reheap_up (void);
+ // Called after an insertion to restore the heap property.
+
+ size_t max_size_;
+ // Maximum size of the heap.
+
+ size_t cur_size_;
+ // Current size of the heap.
+
+ ACE_Timer_Heap_Iterator iterator_;
+ // Iterator used to expire timers.
+
+ ACE_Timer_Node **heap_;
+ // Current contents of the Heap, which is organized as a "heap" of
+ // <ACE_Timer_Node> *'s. In this context, a heap is a "partially
+ // ordered, almost complete" binary tree, which is stored in an
+ // array.
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/Timer_Heap.i"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_TIMER_HEAP_H */
diff --git a/ace/Timer_List.cpp b/ace/Timer_List.cpp
new file mode 100644
index 00000000000..5b0be11591a
--- /dev/null
+++ b/ace/Timer_List.cpp
@@ -0,0 +1,244 @@
+#include "ace/Timer_List.h"
+
+int
+ACE_Timer_List::expire (void)
+{
+ return this->ACE_Timer_Queue::expire ();
+}
+
+ACE_Timer_List_Iterator::ACE_Timer_List_Iterator (ACE_Timer_List &list)
+ : timer_list_ (list)
+{
+}
+
+int
+ACE_Timer_List_Iterator::next (ACE_Timer_Node *&node,
+ const ACE_Time_Value &cur_time)
+{
+ if (this->timer_list_.head_ == 0
+ || this->timer_list_.head_->timer_value_ > cur_time)
+ return 0;
+ else
+ {
+ node = this->timer_list_.head_;
+ this->timer_list_.head_ = this->timer_list_.head_->next_;
+ return 1;
+ }
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Timer_List)
+
+ACE_Timer_Queue_Iterator &
+ACE_Timer_List::iterator (void)
+{
+ return this->iterator_;
+}
+
+// Create an empty list.
+
+ACE_Timer_List::ACE_Timer_List (void)
+ : head_ (0),
+ iterator_ (*this)
+{
+ ACE_TRACE ("ACE_Timer_List::ACE_Timer_List");
+}
+
+// Checks if list is empty.
+
+int
+ACE_Timer_List::is_empty (void) const
+{
+ ACE_TRACE ("ACE_Timer_List::is_empty");
+ return this->head_ == 0;
+}
+
+// Returns earliest time in a non-empty list.
+
+const ACE_Time_Value &
+ACE_Timer_List::earliest_time (void) const
+{
+ ACE_TRACE ("ACE_Timer_List::earliest_time");
+ return this->head_->timer_value_;
+}
+
+// Remove all remaining items in the list.
+
+ACE_Timer_List::~ACE_Timer_List (void)
+{
+ ACE_TRACE ("ACE_Timer_List::~ACE_Timer_List");
+ ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_));
+
+ ACE_Timer_Node *curr = this->head_;
+
+ while (curr != 0)
+ {
+ ACE_Timer_Node *next = curr->next_;
+ delete curr;
+ curr = next;
+ }
+}
+
+// Reschedule a periodic timer. This function must be called with the
+// mutex lock held.
+
+void
+ACE_Timer_List::reschedule (ACE_Timer_Node *expired)
+{
+ ACE_TRACE ("ACE_Timer_List::reschedule");
+ if (this->is_empty ()
+ || expired->timer_value_ < this->earliest_time ())
+ {
+ expired->next_ = this->head_;
+ this->head_ = expired;
+ }
+ else
+ {
+ ACE_Timer_Node *prev = this->head_;
+ ACE_Timer_Node *after = this->head_->next_;
+
+ // Locate the proper position in the queue.
+
+ while (after != 0
+ && expired->timer_value_ > after->timer_value_)
+ {
+ prev = after;
+ after = after->next_;
+ }
+
+ expired->next_ = after;
+ prev->next_ = expired;
+ }
+}
+
+// Insert a new handler that expires at time future_time; if interval
+// is > 0, the handler will be reinvoked periodically.
+
+int
+ACE_Timer_List::schedule (ACE_Event_Handler *handler,
+ const void *arg,
+ const ACE_Time_Value &future_time,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_Timer_List::schedule");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ // Increment the sequence number (it will wrap around).
+ int timer_id = this->timer_id ();
+
+ if (this->is_empty () || future_time < this->earliest_time ())
+ {
+ // Place at the beginning of the list.
+ ACE_NEW_RETURN (this->head_,
+ ACE_Timer_Node (handler,
+ arg,
+ future_time,
+ interval,
+ this->head_,
+ timer_id),
+ -1);
+ return timer_id;
+ }
+
+ // Place in the middle of the list where it belongs (i.e., sorted in
+ // ascending order of absolute time to expire).
+ else
+ {
+ ACE_Timer_Node *prev = this->head_;
+ ACE_Timer_Node *after = this->head_->next_;
+
+ while (after != 0 && future_time > after->timer_value_)
+ {
+ prev = after;
+ after = after->next_;
+ }
+
+ ACE_NEW_RETURN (prev->next_,
+ ACE_Timer_Node (handler,
+ arg,
+ future_time,
+ interval,
+ after,
+ timer_id),
+ -1);
+ return timer_id;
+ }
+}
+
+// Locate and remove the single <ACE_Event_Handler> with a value of
+// <timer_id> from the timer queue.
+
+int
+ACE_Timer_List::cancel (int timer_id,
+ const void **arg)
+{
+ ACE_TRACE ("ACE_Timer_List::cancel");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ ACE_Timer_Node *prev = 0;
+ ACE_Timer_Node *curr = 0;
+
+ // Try to locate the ACE_Timer_Node that matches the timer_id.
+
+ for (curr = this->head_;
+ curr != 0 && curr->timer_id_ != timer_id;
+ curr = curr->next_)
+ prev = curr;
+
+ if (curr != 0)
+ {
+ if (prev == 0)
+ this->head_ = curr->next_;
+ else
+ prev->next_ = curr->next_;
+
+ if (arg != 0)
+ *arg = curr->arg_;
+
+ delete curr;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+// Locate and remove all values of <handler> from the timer queue.
+
+int
+ACE_Timer_List::cancel (ACE_Event_Handler *handler)
+{
+ ACE_TRACE ("ACE_Timer_List::cancel");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ ACE_Timer_Node *prev = 0;
+ ACE_Timer_Node *curr = this->head_;
+
+ int number_of_cancellations = 0;
+
+ while (curr != 0)
+ {
+ if (curr->handler_ == handler)
+ {
+ number_of_cancellations++;
+
+ if (prev == 0)
+ {
+ this->head_ = curr->next_;
+ delete curr;
+ curr = this->head_;
+ }
+ else
+ {
+ prev->next_ = curr->next_;
+ delete curr;
+ curr = prev->next_;
+ }
+ }
+ else
+ {
+ prev = curr;
+ curr = curr->next_;
+ }
+ }
+
+ return number_of_cancellations;
+}
diff --git a/ace/Timer_List.h b/ace/Timer_List.h
new file mode 100644
index 00000000000..14b4c38b6e6
--- /dev/null
+++ b/ace/Timer_List.h
@@ -0,0 +1,138 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ace
+//
+// = FILENAME
+// Timer_List.h
+//
+// = AUTHOR
+// Doug Schmidt
+//
+// ============================================================================
+
+#if !defined (ACE_TIMER_LIST_H)
+#define ACE_TIMER_LIST_H
+
+#include "ace/Timer_Queue.h"
+
+// Forward declaration
+class ACE_Timer_List;
+
+class ACE_Export ACE_Timer_List_Iterator : public ACE_Timer_Queue_Iterator
+ // = TITLE
+ // Iterates over an <ACE_Timer_Queue>.
+ //
+ // = DESCRIPTION
+ // This is a special type of iterator that "advances" by moving
+ // the head of the timer queue up by one every time.
+{
+public:
+ ACE_Timer_List_Iterator (ACE_Timer_List &);
+ // Constructor.
+
+ virtual int next (ACE_Timer_Node *&timer_node,
+ const ACE_Time_Value &cur_time);
+ // Pass back the next <timer_node> that hasn't been seen yet, if its
+ // <time_value_> <= <cur_time>. In addition, moves the timer queue
+ // forward by one node. Returns 0 when all <timer_nodes> have been
+ // seen, else 1.
+
+protected:
+ ACE_Timer_List &timer_list_;
+ // Pointer to the <ACE_Timer_List> that we are iterating over.
+};
+
+class ACE_Export ACE_Timer_List : public ACE_Timer_Queue
+ // = TITLE
+ // Provides an interface to timers.
+ //
+ // = DESCRIPTION
+ // This implementation uses a linked list of absolute times.
+ // Therefore, in the average case, scheduling and canceling
+ // <ACE_Event_Handler> timers is O(N) (where N is the total
+ // number of timers) and expiring timers is O(K) (where K is
+ // the total number of timers that are < the current time of
+ // day).
+ //
+ // More clever implementations could use a delta-list, a heap,
+ // or timing wheels, etc. For instance, <ACE_Timer_Heap>
+ // is a subclass of <ACE_Timer_List> that implements a
+ // heap-based callout queue.
+{
+ friend class ACE_Timer_List_Iterator;
+public:
+ // = Initialization and termination methods.
+ ACE_Timer_List (void);
+ // Default constructor.
+
+ virtual ~ACE_Timer_List (void);
+ // Destructor
+
+ virtual int is_empty (void) const;
+ // True if queue is empty, else false.
+
+ virtual const ACE_Time_Value &earliest_time (void) const;
+ // Returns the time of the earlier node in the <ACE_Timer_List>.
+
+ virtual int schedule (ACE_Event_Handler *event_handler,
+ const void *arg,
+ const ACE_Time_Value &delay,
+ const ACE_Time_Value &interval = ACE_Time_Value::zero);
+ // Schedule an <event_handler> that will expire after <delay> amount
+ // of time. If it expires then <arg> is passed in as the value to
+ // the <event_handler>'s <handle_timeout> callback method. If
+ // <interval> is != to <ACE_Time_Value::zero> then it is used to
+ // reschedule the <event_handler> automatically. This method
+ // returns a <timer_id> that uniquely identifies the <event_handler>
+ // in an internal list. This <timer_id> can be used to cancel an
+ // <event_handler> before it expires. The cancellation ensures that
+ // <timer_ids> are unique up to values of greater than 2 billion
+ // timers. As long as timers don't stay around longer than this
+ // there should be no problems with accidentally deleting the wrong
+ // timer. Returns -1 on failure (which is guaranteed never to be a
+ // valid <timer_id>.
+
+ virtual int cancel (ACE_Event_Handler *event_handler);
+ // Cancel all <event_handlers> that match the address of
+ // <event_handler>. Returns number of handler's cancelled.
+
+ virtual int cancel (int timer_id, const void **arg = 0);
+ // Cancel the single <ACE_Event_Handler> that matches the <timer_id>
+ // value (which was returned from the <schedule> method). If arg is
+ // non-NULL then it will be set to point to the ``magic cookie''
+ // argument passed in when the <Event_Handler> was registered. This
+ // makes it possible to free up the memory and avoid memory leaks.
+ // Returns 1 if cancellation succeeded and 0 if the <timer_id>
+ // wasn't found.
+
+ virtual int expire (const ACE_Time_Value &current_time);
+ // Run the <handle_timeout> method for all Timers whose values are
+ // <= <cur_time>. This does not account for <timer_skew>. Returns
+ // the number of <Event_Handler>s for which <handle_timeout> was
+ // called.
+
+ virtual int expire (void);
+ // Run the <handle_timeout> method for all Timers whose values are
+ // <= <ACE_OS::gettimeofday>. Also accounts for <timer_skew>.
+ // Returns the number of <Event_Handler>s for which <handle_timeout>
+ // was called.
+
+private:
+ virtual void reschedule (ACE_Timer_Node *);
+ // Reschedule an "interval" <ACE_Timer_Node>.
+
+ virtual ACE_Timer_Queue_Iterator &iterator (void);
+ // Returns a pointer to this <ACE_Timer_Queue>'s iterator.
+
+ ACE_Timer_Node *head_;
+ // Pointer to linked list of <ACE_Timer_Handles>.
+
+ ACE_Timer_List_Iterator iterator_;
+ // Iterator used to expire timers.
+};
+
+#endif /* ACE_TIMER_LIST_H */
diff --git a/ace/Timer_Queue.cpp b/ace/Timer_Queue.cpp
index e50ad82a7f8..5e9dd26e6ed 100644
--- a/ace/Timer_Queue.cpp
+++ b/ace/Timer_Queue.cpp
@@ -32,217 +32,68 @@ ACE_Timer_Node::ACE_Timer_Node (ACE_Event_Handler *h,
ACE_TRACE ("ACE_Timer_Node::ACE_Timer_Node");
}
-ACE_ALLOC_HOOK_DEFINE(ACE_Timer_Queue)
-
-void
-ACE_Timer_Queue::dump (void) const
-{
- ACE_TRACE ("ACE_Timer_Queue::dump");
- ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
- this->timer_skew_.dump ();
- ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
-}
-
-// Create an empty queue.
-
-ACE_Timer_Queue::ACE_Timer_Queue (void)
- : head_ (0),
- timer_id_ (0),
- timer_skew_ (0, ACE_TIMER_SKEW)
-{
- ACE_TRACE ("ACE_Timer_Queue::ACE_Timer_Queue");
-}
-
-// Checks if queue is empty.
-
-int
-ACE_Timer_Queue::is_empty (void) const
-{
- ACE_TRACE ("ACE_Timer_Queue::is_empty");
- return this->head_ == 0;
-}
-
-// Returns earliest time in a non-empty queue.
-
-const ACE_Time_Value &
-ACE_Timer_Queue::earliest_time (void) const
-{
- ACE_TRACE ("ACE_Timer_Queue::earliest_time");
- return this->head_->timer_value_;
-}
-
-// Remove all remaining items in the queue.
+// Determines the maximum amount of time that the Reactor must wait
+// before timing out. This is computed as the smaller of (1) the
+// amount the caller requested when calling handle_events() and (2)
+// the earliest time registered in the Timer Queue (if any). Must be
+// called with an external lock held since it returns a pointer to a
+// Time_Value object stored in the Timer_Queue object itself. If some
+// external lock isn't held we'll have reentrancy problems!
-ACE_Timer_Queue::~ACE_Timer_Queue (void)
+ACE_Time_Value *
+ACE_Timer_Queue::calculate_timeout (ACE_Time_Value *max_wait_time)
{
- ACE_TRACE ("ACE_Timer_Queue::~ACE_Timer_Queue");
- ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_));
-
- ACE_Timer_Node *curr = this->head_;
-
- while (curr != 0)
- {
- ACE_Timer_Node *next = curr->next_;
- delete curr;
- curr = next;
- }
-}
-
-// Reschedule a periodic timer. This function must be called with the
-// mutex lock held.
+ ACE_TRACE ("ACE_Timer_List::calculate_timeout");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, max_wait_time));
-void
-ACE_Timer_Queue::reschedule (ACE_Timer_Node *expired)
-{
- ACE_TRACE ("ACE_Timer_Queue::reschedule");
- if (this->is_empty () || expired->timer_value_ < this->earliest_time ())
- {
- expired->next_ = this->head_;
- this->head_ = expired;
- }
+ if (this->is_empty ())
+ // Nothing on the Timer_Queue, so use whatever the caller gave us.
+ return max_wait_time;
else
{
- ACE_Timer_Node *prev = this->head_;
- ACE_Timer_Node *after = this->head_->next_;
-
- // Locate the proper position in the queue.
+ ACE_Time_Value cur_time = ACE_OS::gettimeofday ();
- while (after != 0
- && expired->timer_value_ > after->timer_value_)
- {
- prev = after;
- after = after->next_;
- }
+ if (this->earliest_time () > cur_time)
+ {
+ // The earliest item on the Timer_Queue is still in the
+ // future. Therefore, use the smaller of (1) caller's wait
+ // time or (2) the delta time between now and the earliest
+ // time on the Timer_Queue.
- expired->next_ = after;
- prev->next_ = expired;
+ this->timeout_ = this->earliest_time () - cur_time;
+ if (max_wait_time == 0 || *max_wait_time > timeout_)
+ return &this->timeout_;
+ else
+ return max_wait_time;
+ }
+ else
+ {
+ // The earliest item on the Timer_Queue is now in the past.
+ // Therefore, we've got to "poll" the Reactor, i.e., it must
+ // just check the descriptors and then dispatch timers, etc.
+ this->timeout_ = ACE_Time_Value::zero;
+ return &this->timeout_;
+ }
}
}
-// Insert a new handler that expires at time future_time; if interval
-// is > 0, the handler will be reinvoked periodically.
-
-int
-ACE_Timer_Queue::schedule (ACE_Event_Handler *handler,
- const void *arg,
- const ACE_Time_Value &future_time,
- const ACE_Time_Value &interval)
+void
+ACE_Timer_Queue::dump (void) const
{
- ACE_TRACE ("ACE_Timer_Queue::schedule");
- ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
-
- // Increment the sequence number (it will wrap around).
- this->timer_id_++;
-
- if (this->is_empty () || future_time < this->earliest_time ())
- {
- // Place at the beginning of the list.
- ACE_NEW_RETURN (this->head_,
- ACE_Timer_Node (handler,
- arg,
- future_time,
- interval,
- this->head_,
- this->timer_id_),
- -1);
- return this->head_ ? this->timer_id_ : -1;
- }
- else // Place in the middle of the list somewhere.
- {
- ACE_Timer_Node *prev = this->head_;
- ACE_Timer_Node *after = this->head_->next_;
-
- while (after != 0 && future_time > after->timer_value_)
- {
- prev = after;
- after = after->next_;
- }
-
- ACE_NEW_RETURN (prev->next_,
- ACE_Timer_Node (handler,
- arg,
- future_time,
- interval,
- after,
- this->timer_id_),
- -1);
- return prev->next_ ? this->timer_id_ : -1;
- }
+ ACE_TRACE ("ACE_Timer_Queue::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->timer_skew_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
}
-// Locate and remove the single <ACE_Event_Handler> with a value of
-// <timer_id> from the timer queue.
+ACE_Timer_Queue::ACE_Timer_Queue (void)
+ : timer_id_ (0),
+ timer_skew_ (0, ACE_TIMER_SKEW)
-int
-ACE_Timer_Queue::cancel (int timer_id, const void **arg)
{
- ACE_TRACE ("ACE_Timer_Queue::cancel");
- ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
-
- ACE_Timer_Node *prev = 0;
- ACE_Timer_Node *curr = 0;
-
- // Try to locate the ACE_Timer_Node that matches the timer_id.
-
- for (curr = this->head_;
- curr != 0 && curr->timer_id_ != timer_id;
- curr = curr->next_)
- prev = curr;
-
- if (curr != 0)
- {
- if (prev == 0)
- this->head_ = curr->next_;
- else
- prev->next_ = curr->next_;
-
- if (arg != 0)
- *arg = curr->arg_;
-
- delete curr;
- return 0;
- }
- else
- return -1;
+ ACE_TRACE ("ACE_Timer_Queue::ACE_Timer_Queue");
}
-// Locate and remove all values of <handler> from the timer queue.
-
-int
-ACE_Timer_Queue::cancel (ACE_Event_Handler *handler)
-{
- ACE_TRACE ("ACE_Timer_Queue::cancel");
- ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
-
- ACE_Timer_Node *prev = 0;
- ACE_Timer_Node *curr = this->head_;
-
- while (curr != 0)
- {
- if (curr->handler_ == handler)
- {
- if (prev == 0)
- {
- this->head_ = curr->next_;
- delete curr;
- curr = this->head_;
- }
- else
- {
- prev->next_ = curr->next_;
- delete curr;
- curr = prev->next_;
- }
- }
- else
- {
- prev = curr;
- curr = curr->next_;
- }
- }
-
- return 0;
-}
// Run the <handle_timeout> method for all Timers whose values are <=
// <cur_time>.
@@ -250,26 +101,25 @@ ACE_Timer_Queue::cancel (ACE_Event_Handler *handler)
int
ACE_Timer_Queue::expire (const ACE_Time_Value &cur_time)
{
- ACE_TRACE ("ACE_Timer_Queue::expire");
+ ACE_TRACE ("ACE_Timer_List::expire");
ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
int number_of_timers_expired = 0;
+ ACE_Timer_Queue_Iterator &iterator (this->iterator ());
+
// Keep looping while there are timers remaining and the earliest
// timer is <= the <cur_time> passed in to the method.
- for (;
- this->is_empty () == 0 && this->earliest_time () <= cur_time;
- number_of_timers_expired++)
+ for (ACE_Timer_Node *expired;
+ iterator.next (expired, cur_time) != 0;
+ )
{
- ACE_Timer_Node *expired = this->head_;
ACE_Event_Handler *handler =
(ACE_Event_Handler *) expired->handler_;
const void *arg = expired->arg_;
int reclaim = 1;
- this->head_ = this->head_->next_;
-
// Check if this is an interval timer.
if (expired->interval_ > ACE_Time_Value::zero)
{
@@ -291,52 +141,10 @@ ACE_Timer_Queue::expire (const ACE_Time_Value &cur_time)
if (reclaim)
delete expired;
+
+ number_of_timers_expired++;
}
return number_of_timers_expired;
}
-// Determines the maximum amount of time that the Reactor must wait
-// before timing out. This is computed as the smaller of (1) the
-// amount the caller requested when calling handle_events() and (2)
-// the earliest time registered in the Timer Queue (if any). Must be
-// called with locks held since it returns a pointer to a Time_Value
-// object stored in the Timer_Queue object itself. If the lock isn't
-// held we'll have reentrancy problems!)
-
-ACE_Time_Value *
-ACE_Timer_Queue::calculate_timeout (ACE_Time_Value *max_wait_time)
-{
- ACE_TRACE ("ACE_Timer_Queue::calculate_timeout");
- ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, max_wait_time));
-
- if (this->is_empty ())
- // Nothing on the Timer_Queue, so use whatever the caller gave us.
- return max_wait_time;
- else
- {
- ACE_Time_Value cur_time = ACE_OS::gettimeofday ();
-
- if (this->earliest_time () > cur_time)
- {
- // The earliest item on the Timer_Queue is still in the
- // future. Therefore, use the smaller of (1) caller's wait
- // time or (2) the delta time between now and the earliest
- // time on the Timer_Queue.
-
- this->timeout_ = this->earliest_time () - cur_time;
- if (max_wait_time == 0 || *max_wait_time > timeout_)
- return &this->timeout_;
- else
- return max_wait_time;
- }
- else
- {
- // The earliest item on the Timer_Queue is now in the past.
- // Therefore, we've got to "poll" the Reactor, i.e., it must
- // just check the descriptors and then dispatch timers, etc.
- this->timeout_ = ACE_Time_Value::zero;
- return &this->timeout_;
- }
- }
-}
diff --git a/ace/Timer_Queue.h b/ace/Timer_Queue.h
index ea760dc8a8e..6c70cccd595 100644
--- a/ace/Timer_Queue.h
+++ b/ace/Timer_Queue.h
@@ -21,15 +21,24 @@
#include "ace/Time_Value.h"
#include "ace/Synch.h"
+// Forward declaration.
+class ACE_Timer_Queue;
+
// This should be nested within the ACE_Timer_Queue class but some C++
// compilers still don't like this...
-struct ACE_Timer_Node
+class ACE_Export ACE_Timer_Node
// = TITLE
// Maintains the state associated with a Timer entry.
{
-friend class ACE_Timer_Queue;
-private:
+ // = The use of friends should be replaced with accessors...
+ friend class ACE_Timer_Queue;
+ friend class ACE_Timer_List;
+ friend class ACE_Timer_List_Iterator;
+ friend class ACE_Timer_Heap;
+ friend class ACE_Timer_Heap_Iterator;
+
+ // = Initialization method.
ACE_Timer_Node (ACE_Event_Handler *h,
const void *a,
const ACE_Time_Value &t,
@@ -64,61 +73,84 @@ private:
// Dump the state of an object.
};
+class ACE_Export ACE_Timer_Queue_Iterator
+ // = TITLE
+ // Generic interfae for iterating over a subclass of
+ // <ACE_Timer_Queue>.
+ //
+ // = DESCRIPTION
+ // This is a special type of iterator that "advances" by moving
+ // the head of the timer queue up by one every time.
+{
+public:
+ virtual int next (ACE_Timer_Node *&timer_node,
+ const ACE_Time_Value &cur_time) = 0;
+ // Pass back the next <timer_node> that hasn't been seen yet, if its
+ // <time_value_> <= <cur_time>. In addition, moves the timer queue
+ // forward by one node. Returns 0 when all <timer_nodes> have been
+ // seen, else 1.
+};
+
class ACE_Export ACE_Timer_Queue
// = TITLE
// Provides an interface to timers.
//
// = DESCRIPTION
- // This is a simple implementation that uses a linked list of
- // absolute times. A more clever implementation would use a
- // delta-list, a heap, or timing wheels, etc.
+ // This implementation uses a linked list of absolute times.
+ // Therefore, in the average case, scheduling and canceling
+ // <ACE_Event_Handler> timers is O(N) (where N is the total
+ // number of timers) and expiring timers is O(K) (where K is
+ // the total number of timers that are < the current time of
+ // day).
+ //
+ // More clever implementations could use a delta-list, a heap,
+ // or timing wheels, etc. For instance, <ACE_Timer_Heap>
+ // is a subclass of <ACE_Timer_Queue> that implements a
+ // heap-based callout queue.
{
public:
// = Initialization and termination methods.
ACE_Timer_Queue (void);
// Default constructor.
- virtual ~ACE_Timer_Queue (void);
-
- int is_empty (void) const;
+ virtual int is_empty (void) const = 0;
// True if queue is empty, else false.
- const ACE_Time_Value &earliest_time (void) const;
+ virtual const ACE_Time_Value &earliest_time (void) const = 0;
// Returns the time of the earlier node in the Timer_Queue.
- // = Set/get the timer skew for the Timer_Queue.
- void timer_skew (const ACE_Time_Value &skew);
- const ACE_Time_Value &timer_skew (void) const;
-
virtual int schedule (ACE_Event_Handler *event_handler,
const void *arg,
const ACE_Time_Value &delay,
- const ACE_Time_Value &interval = ACE_Time_Value::zero);
+ const ACE_Time_Value &interval = ACE_Time_Value::zero) = 0;
// Schedule an <event_handler> that will expire after <delay> amount
// of time. If it expires then <arg> is passed in as the value to
// the <event_handler>'s <handle_timeout> callback method. If
// <interval> is != to <ACE_Time_Value::zero> then it is used to
// reschedule the <event_handler> automatically. This method
- // returns a timer handle that uniquely identifies the
- // <event_handler> in an internal list. This timer handle can be
- // used to cancel an <event_handler> before it expires. The
- // cancellation ensures that timer_ids are unique up to values of
- // greater than 2 billion timers. As long as timers don't stay
- // around longer than this there should be no problems with
- // accidentally deleting the wrong timer.
-
- virtual int cancel (ACE_Event_Handler *event_handler);
+ // returns a <timer_id> that uniquely identifies the <event_handler>
+ // in an internal list. This <timer_id> can be used to cancel an
+ // <event_handler> before it expires. The cancellation ensures that
+ // <timer_ids> are unique up to values of greater than 2 billion
+ // timers. As long as timers don't stay around longer than this
+ // there should be no problems with accidentally deleting the wrong
+ // timer. Returns -1 on failure (which is guaranteed never to be a
+ // valid <timer_id>.
+
+ virtual int cancel (ACE_Event_Handler *event_handler) = 0;
// Cancel all <event_handlers> that match the address of
- // <event_handler>.
+ // <event_handler>. Returns number of handler's cancelled.
- virtual int cancel (int timer_id, const void **arg = 0);
+ virtual int cancel (int timer_id, const void **arg = 0) = 0;
// Cancel the single <ACE_Event_Handler> that matches the <timer_id>
// value (which was returned from the <schedule> method). If arg is
// non-NULL then it will be set to point to the ``magic cookie''
// argument passed in when the <Event_Handler> was registered. This
// makes it possible to free up the memory and avoid memory leaks.
+ // Returns 1 if cancellation succeeded and 0 if the <timer_id>
+ // wasn't found.
- virtual int expire (const ACE_Time_Value &current_time);
+ virtual int expire (const ACE_Time_Value &current_time) = 0;
// Run the <handle_timeout> method for all Timers whose values are
// <= <cur_time>. This does not account for <timer_skew>. Returns
// the number of <Event_Handler>s for which <handle_timeout> was
@@ -134,34 +166,45 @@ public:
// Determine the next event to timeout. Returns <max> if there are
// no pending timers or if all pending timers are longer than max.
- void dump (void) const;
+ // = Set/get the timer skew for the Timer_Queue.
+ void timer_skew (const ACE_Time_Value &skew);
+ const ACE_Time_Value &timer_skew (void) const;
+
+ virtual void dump (void) const;
// Dump the state of an object.
ACE_ALLOC_HOOK_DECLARE;
// Declare the dynamic allocation hooks.
-private:
- ACE_Time_Value timeout_;
- // Returned by calculate_timeout.
+protected:
+ virtual void reschedule (ACE_Timer_Node *) = 0;
+ // Reschedule an "interval" <ACE_Timer_Node>.
+
+ virtual ACE_Timer_Queue_Iterator &iterator (void) = 0;
+ // Returns a pointer to this <ACE_Timer_Queue>'s iterator.
- virtual void reschedule (ACE_Timer_Node *);
- // Reschedule a "period" Timer_Node.
+ virtual int timer_id (void);
+ // Returns a timer id that uniquely identifies this timer. This id
+ // can be used to cancel a timer via the <cancel (int)> method. The
+ // timer id returned from this method will never == -1 to avoid
+ // conflicts with other failure return values.
- ACE_Timer_Node *head_;
- // Pointer to linked list of ACE_Timer_Handles.
+#if defined (ACE_MT_SAFE)
+ ACE_Recursive_Thread_Mutex lock_;
+ // Synchronization variable for the MT_SAFE ACE_Reactor
+#endif /* ACE_MT_SAFE */
+private:
int timer_id_;
// Keeps track of the timer id that uniquely identifies each timer.
// This id can be used to cancel a timer via the <cancel (int)>
// method.
+ ACE_Time_Value timeout_;
+ // Returned by <calculate_timeout>.
+
ACE_Time_Value timer_skew_;
// Adjusts for timer skew in various clocks.
-
-#if defined (ACE_MT_SAFE)
- ACE_Recursive_Thread_Mutex lock_;
- // Synchronization variable for the MT_SAFE ACE_Reactor
-#endif /* ACE_MT_SAFE */
};
#if defined (__ACE_INLINE__)
diff --git a/ace/Timer_Queue.i b/ace/Timer_Queue.i
index 480103b0062..7d344138d23 100644
--- a/ace/Timer_Queue.i
+++ b/ace/Timer_Queue.i
@@ -9,6 +9,18 @@ ACE_Timer_Queue::timer_skew (const ACE_Time_Value &skew)
timer_skew_ = skew;
}
+ACE_INLINE int
+ACE_Timer_Queue::timer_id (void)
+{
+ this->timer_id_++;
+
+ // Make sure this never == -1
+ if (this->timer_id_ == -1)
+ this->timer_id_ = 0;
+
+ return this->timer_id_;
+}
+
ACE_INLINE const ACE_Time_Value &
ACE_Timer_Queue::timer_skew (void) const
{
diff --git a/examples/Logger/Acceptor-server/server_loggerd.cpp b/examples/Logger/Acceptor-server/server_loggerd.cpp
index 89ed3a859a7..20b0bb3d0af 100644
--- a/examples/Logger/Acceptor-server/server_loggerd.cpp
+++ b/examples/Logger/Acceptor-server/server_loggerd.cpp
@@ -3,11 +3,10 @@
// This server daemon collects, formats, and displays logging
// information forwarded from client daemons running on other hosts in
// the network. In addition, this example illustrates how to use the
-// ACE_Reactor, ACE_Acceptor, ACE_Singleton, and ACE_Test_and_Set
+// ACE_Reactor, ACE_Acceptor, ACE_Singleton, and the ACE_Test_and_Set
// components.
#include "ace/Get_Opt.h"
-
#include "ace/Acceptor.h"
#include "ace/SOCK_Acceptor.h"
#include "ace/Synch.h"
@@ -237,8 +236,12 @@ main (int argc, char *argv[])
OPTIONS::instance ()->parse_args (argc, argv);
+ // We need to pass in REACTOR::instance() here so that we don't use
+ // the default ACE_Service_Config::reactor().
+
if (peer_acceptor.open
- (ACE_INET_Addr (OPTIONS::instance ()->port ())) == -1)
+ (ACE_INET_Addr (OPTIONS::instance ()->port ()),
+ REACTOR::instance ()) == -1)
ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open"), -1);
else if (REACTOR::instance ()->register_handler
diff --git a/netsvcs/lib/Logging_Strategy.cpp b/netsvcs/lib/Logging_Strategy.cpp
index 877feb8ead0..2243f01eacf 100644
--- a/netsvcs/lib/Logging_Strategy.cpp
+++ b/netsvcs/lib/Logging_Strategy.cpp
@@ -2,8 +2,8 @@
// $Id$
#define ACE_BUILD_SVC_DLL
-#include "iostream.h"
-#include "fstream.h"
+#include <iostream.h>
+#include <fstream.h>
#include "ace/Get_Opt.h"
#include "ace/Service_Object.h"
diff --git a/netsvcs/lib/Makefile b/netsvcs/lib/Makefile
index e2ca93d152d..b3582e23986 100644
--- a/netsvcs/lib/Makefile
+++ b/netsvcs/lib/Makefile
@@ -53,6 +53,8 @@ include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
$(WRAPPER_ROOT)/ace/Log_Record.i \
$(WRAPPER_ROOT)/ace/ACE.i \
$(WRAPPER_ROOT)/ace/Set.h \
+ $(WRAPPER_ROOT)/ace/Set.cpp \
+ $(WRAPPER_ROOT)/ace/Set.i \
$(WRAPPER_ROOT)/ace/Get_Opt.h \
$(WRAPPER_ROOT)/ace/Acceptor.h \
$(WRAPPER_ROOT)/ace/Service_Config.h \
@@ -67,6 +69,8 @@ include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
$(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \
$(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \
$(WRAPPER_ROOT)/ace/Synch_T.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.cpp \
+ $(WRAPPER_ROOT)/ace/Synch_T.i \
$(WRAPPER_ROOT)/ace/Signal.h \
$(WRAPPER_ROOT)/ace/Reactor.h \
$(WRAPPER_ROOT)/ace/Handle_Set.h \
@@ -84,11 +88,12 @@ include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
$(WRAPPER_ROOT)/ace/SOCK_IO.i \
$(WRAPPER_ROOT)/ace/INET_Addr.h \
$(WRAPPER_ROOT)/ace/SOCK_Stream.i \
- $(WRAPPER_ROOT)/ace/Reactor.i \
$(WRAPPER_ROOT)/ace/Proactor.h \
$(WRAPPER_ROOT)/ace/Message_Block.h \
$(WRAPPER_ROOT)/ace/Malloc.h \
$(WRAPPER_ROOT)/ace/Malloc_T.h \
+ $(WRAPPER_ROOT)/ace/Malloc_T.cpp \
+ $(WRAPPER_ROOT)/ace/Malloc_T.i \
$(WRAPPER_ROOT)/ace/Memory_Pool.h \
$(WRAPPER_ROOT)/ace/Mem_Map.h \
$(WRAPPER_ROOT)/ace/ReactorEx.h \
@@ -96,12 +101,27 @@ include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
$(WRAPPER_ROOT)/ace/IO_Cntl_Msg.h \
$(WRAPPER_ROOT)/ace/Strategies.h \
$(WRAPPER_ROOT)/ace/Strategies_T.h \
+ $(WRAPPER_ROOT)/ace/Strategies_T.cpp \
+ $(WRAPPER_ROOT)/ace/Message_Queue.cpp \
+ $(WRAPPER_ROOT)/ace/Message_Queue.i \
$(WRAPPER_ROOT)/ace/Svc_Conf_Tokens.h \
$(WRAPPER_ROOT)/ace/Svc_Handler.h \
$(WRAPPER_ROOT)/ace/Synch_Options.h \
$(WRAPPER_ROOT)/ace/Task.h \
$(WRAPPER_ROOT)/ace/Task_T.h \
+ $(WRAPPER_ROOT)/ace/Task_T.cpp \
+ $(WRAPPER_ROOT)/ace/Module.h \
+ $(WRAPPER_ROOT)/ace/Module.cpp \
+ $(WRAPPER_ROOT)/ace/Stream_Modules.h \
+ $(WRAPPER_ROOT)/ace/Stream_Modules.cpp \
+ $(WRAPPER_ROOT)/ace/Stream_Modules.i \
+ $(WRAPPER_ROOT)/ace/Module.i \
+ $(WRAPPER_ROOT)/ace/Task_T.i \
+ $(WRAPPER_ROOT)/ace/Svc_Handler.cpp \
+ $(WRAPPER_ROOT)/ace/Dynamic.h \
+ $(WRAPPER_ROOT)/ace/Svc_Handler.i \
$(WRAPPER_ROOT)/ace/Acceptor.i \
+ $(WRAPPER_ROOT)/ace/Acceptor.cpp \
$(WRAPPER_ROOT)/ace/SOCK_Acceptor.h \
$(WRAPPER_ROOT)/ace/Time_Request_Reply.h \
TS_Server_Handler.h
@@ -129,8 +149,12 @@ include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
$(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \
$(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \
$(WRAPPER_ROOT)/ace/Synch_T.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.cpp \
+ $(WRAPPER_ROOT)/ace/Synch_T.i \
$(WRAPPER_ROOT)/ace/Signal.h \
$(WRAPPER_ROOT)/ace/Set.h \
+ $(WRAPPER_ROOT)/ace/Set.cpp \
+ $(WRAPPER_ROOT)/ace/Set.i \
$(WRAPPER_ROOT)/ace/Reactor.h \
$(WRAPPER_ROOT)/ace/Handle_Set.h \
$(WRAPPER_ROOT)/ace/Timer_Queue.h \
@@ -147,11 +171,12 @@ include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
$(WRAPPER_ROOT)/ace/SOCK_IO.i \
$(WRAPPER_ROOT)/ace/INET_Addr.h \
$(WRAPPER_ROOT)/ace/SOCK_Stream.i \
- $(WRAPPER_ROOT)/ace/Reactor.i \
$(WRAPPER_ROOT)/ace/Proactor.h \
$(WRAPPER_ROOT)/ace/Message_Block.h \
$(WRAPPER_ROOT)/ace/Malloc.h \
$(WRAPPER_ROOT)/ace/Malloc_T.h \
+ $(WRAPPER_ROOT)/ace/Malloc_T.cpp \
+ $(WRAPPER_ROOT)/ace/Malloc_T.i \
$(WRAPPER_ROOT)/ace/Memory_Pool.h \
$(WRAPPER_ROOT)/ace/Mem_Map.h \
$(WRAPPER_ROOT)/ace/ReactorEx.h \
@@ -159,14 +184,31 @@ include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
$(WRAPPER_ROOT)/ace/IO_Cntl_Msg.h \
$(WRAPPER_ROOT)/ace/Strategies.h \
$(WRAPPER_ROOT)/ace/Strategies_T.h \
+ $(WRAPPER_ROOT)/ace/Strategies_T.cpp \
+ $(WRAPPER_ROOT)/ace/Message_Queue.cpp \
+ $(WRAPPER_ROOT)/ace/Message_Queue.i \
$(WRAPPER_ROOT)/ace/Svc_Conf_Tokens.h \
$(WRAPPER_ROOT)/ace/Connector.h \
$(WRAPPER_ROOT)/ace/Map_Manager.h \
+ $(WRAPPER_ROOT)/ace/Map_Manager.cpp \
+ $(WRAPPER_ROOT)/ace/Map_Manager.i \
$(WRAPPER_ROOT)/ace/Svc_Handler.h \
$(WRAPPER_ROOT)/ace/Synch_Options.h \
$(WRAPPER_ROOT)/ace/Task.h \
$(WRAPPER_ROOT)/ace/Task_T.h \
+ $(WRAPPER_ROOT)/ace/Task_T.cpp \
+ $(WRAPPER_ROOT)/ace/Module.h \
+ $(WRAPPER_ROOT)/ace/Module.cpp \
+ $(WRAPPER_ROOT)/ace/Stream_Modules.h \
+ $(WRAPPER_ROOT)/ace/Stream_Modules.cpp \
+ $(WRAPPER_ROOT)/ace/Stream_Modules.i \
+ $(WRAPPER_ROOT)/ace/Module.i \
+ $(WRAPPER_ROOT)/ace/Task_T.i \
+ $(WRAPPER_ROOT)/ace/Svc_Handler.cpp \
+ $(WRAPPER_ROOT)/ace/Dynamic.h \
+ $(WRAPPER_ROOT)/ace/Svc_Handler.i \
$(WRAPPER_ROOT)/ace/Connector.i \
+ $(WRAPPER_ROOT)/ace/Connector.cpp \
$(WRAPPER_ROOT)/ace/Get_Opt.h \
$(WRAPPER_ROOT)/ace/SOCK_Connector.h \
$(WRAPPER_ROOT)/ace/SOCK_Connector.i \
@@ -197,8 +239,12 @@ include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
$(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \
$(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \
$(WRAPPER_ROOT)/ace/Synch_T.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.cpp \
+ $(WRAPPER_ROOT)/ace/Synch_T.i \
$(WRAPPER_ROOT)/ace/Signal.h \
$(WRAPPER_ROOT)/ace/Set.h \
+ $(WRAPPER_ROOT)/ace/Set.cpp \
+ $(WRAPPER_ROOT)/ace/Set.i \
$(WRAPPER_ROOT)/ace/Reactor.h \
$(WRAPPER_ROOT)/ace/Handle_Set.h \
$(WRAPPER_ROOT)/ace/Timer_Queue.h \
@@ -215,11 +261,12 @@ include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
$(WRAPPER_ROOT)/ace/SOCK_IO.i \
$(WRAPPER_ROOT)/ace/INET_Addr.h \
$(WRAPPER_ROOT)/ace/SOCK_Stream.i \
- $(WRAPPER_ROOT)/ace/Reactor.i \
$(WRAPPER_ROOT)/ace/Proactor.h \
$(WRAPPER_ROOT)/ace/Message_Block.h \
$(WRAPPER_ROOT)/ace/Malloc.h \
$(WRAPPER_ROOT)/ace/Malloc_T.h \
+ $(WRAPPER_ROOT)/ace/Malloc_T.cpp \
+ $(WRAPPER_ROOT)/ace/Malloc_T.i \
$(WRAPPER_ROOT)/ace/Memory_Pool.h \
$(WRAPPER_ROOT)/ace/Mem_Map.h \
$(WRAPPER_ROOT)/ace/ReactorEx.h \
@@ -227,14 +274,31 @@ include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
$(WRAPPER_ROOT)/ace/IO_Cntl_Msg.h \
$(WRAPPER_ROOT)/ace/Strategies.h \
$(WRAPPER_ROOT)/ace/Strategies_T.h \
+ $(WRAPPER_ROOT)/ace/Strategies_T.cpp \
+ $(WRAPPER_ROOT)/ace/Message_Queue.cpp \
+ $(WRAPPER_ROOT)/ace/Message_Queue.i \
$(WRAPPER_ROOT)/ace/Svc_Conf_Tokens.h \
$(WRAPPER_ROOT)/ace/Connector.h \
$(WRAPPER_ROOT)/ace/Map_Manager.h \
+ $(WRAPPER_ROOT)/ace/Map_Manager.cpp \
+ $(WRAPPER_ROOT)/ace/Map_Manager.i \
$(WRAPPER_ROOT)/ace/Svc_Handler.h \
$(WRAPPER_ROOT)/ace/Synch_Options.h \
$(WRAPPER_ROOT)/ace/Task.h \
$(WRAPPER_ROOT)/ace/Task_T.h \
+ $(WRAPPER_ROOT)/ace/Task_T.cpp \
+ $(WRAPPER_ROOT)/ace/Module.h \
+ $(WRAPPER_ROOT)/ace/Module.cpp \
+ $(WRAPPER_ROOT)/ace/Stream_Modules.h \
+ $(WRAPPER_ROOT)/ace/Stream_Modules.cpp \
+ $(WRAPPER_ROOT)/ace/Stream_Modules.i \
+ $(WRAPPER_ROOT)/ace/Module.i \
+ $(WRAPPER_ROOT)/ace/Task_T.i \
+ $(WRAPPER_ROOT)/ace/Svc_Handler.cpp \
+ $(WRAPPER_ROOT)/ace/Dynamic.h \
+ $(WRAPPER_ROOT)/ace/Svc_Handler.i \
$(WRAPPER_ROOT)/ace/Connector.i \
+ $(WRAPPER_ROOT)/ace/Connector.cpp \
$(WRAPPER_ROOT)/ace/Get_Opt.h \
$(WRAPPER_ROOT)/ace/SOCK_Connector.h \
$(WRAPPER_ROOT)/ace/SOCK_Connector.i \
@@ -258,6 +322,8 @@ include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
$(WRAPPER_ROOT)/ace/Log_Record.i \
$(WRAPPER_ROOT)/ace/ACE.i \
$(WRAPPER_ROOT)/ace/Set.h \
+ $(WRAPPER_ROOT)/ace/Set.cpp \
+ $(WRAPPER_ROOT)/ace/Set.i \
$(WRAPPER_ROOT)/ace/Get_Opt.h \
$(WRAPPER_ROOT)/ace/Naming_Context.h \
$(WRAPPER_ROOT)/ace/Service_Object.h \
@@ -285,6 +351,8 @@ include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
$(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \
$(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \
$(WRAPPER_ROOT)/ace/Synch_T.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.cpp \
+ $(WRAPPER_ROOT)/ace/Synch_T.i \
$(WRAPPER_ROOT)/ace/Signal.h \
$(WRAPPER_ROOT)/ace/Reactor.h \
$(WRAPPER_ROOT)/ace/Handle_Set.h \
@@ -292,11 +360,12 @@ include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
$(WRAPPER_ROOT)/ace/Token.h \
$(WRAPPER_ROOT)/ace/Pipe.h \
$(WRAPPER_ROOT)/ace/Pipe.i \
- $(WRAPPER_ROOT)/ace/Reactor.i \
$(WRAPPER_ROOT)/ace/Proactor.h \
$(WRAPPER_ROOT)/ace/Message_Block.h \
$(WRAPPER_ROOT)/ace/Malloc.h \
$(WRAPPER_ROOT)/ace/Malloc_T.h \
+ $(WRAPPER_ROOT)/ace/Malloc_T.cpp \
+ $(WRAPPER_ROOT)/ace/Malloc_T.i \
$(WRAPPER_ROOT)/ace/Memory_Pool.h \
$(WRAPPER_ROOT)/ace/Mem_Map.h \
$(WRAPPER_ROOT)/ace/ReactorEx.h \
@@ -304,6 +373,9 @@ include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
$(WRAPPER_ROOT)/ace/IO_Cntl_Msg.h \
$(WRAPPER_ROOT)/ace/Strategies.h \
$(WRAPPER_ROOT)/ace/Strategies_T.h \
+ $(WRAPPER_ROOT)/ace/Strategies_T.cpp \
+ $(WRAPPER_ROOT)/ace/Message_Queue.cpp \
+ $(WRAPPER_ROOT)/ace/Message_Queue.i \
$(WRAPPER_ROOT)/ace/Svc_Conf_Tokens.h \
$(WRAPPER_ROOT)/ace/Synch_Options.h \
$(WRAPPER_ROOT)/ace/Name_Request_Reply.h \
@@ -312,7 +384,19 @@ include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
$(WRAPPER_ROOT)/ace/Svc_Handler.h \
$(WRAPPER_ROOT)/ace/Task.h \
$(WRAPPER_ROOT)/ace/Task_T.h \
+ $(WRAPPER_ROOT)/ace/Task_T.cpp \
+ $(WRAPPER_ROOT)/ace/Module.h \
+ $(WRAPPER_ROOT)/ace/Module.cpp \
+ $(WRAPPER_ROOT)/ace/Stream_Modules.h \
+ $(WRAPPER_ROOT)/ace/Stream_Modules.cpp \
+ $(WRAPPER_ROOT)/ace/Stream_Modules.i \
+ $(WRAPPER_ROOT)/ace/Module.i \
+ $(WRAPPER_ROOT)/ace/Task_T.i \
+ $(WRAPPER_ROOT)/ace/Svc_Handler.cpp \
+ $(WRAPPER_ROOT)/ace/Dynamic.h \
+ $(WRAPPER_ROOT)/ace/Svc_Handler.i \
$(WRAPPER_ROOT)/ace/Acceptor.i \
+ $(WRAPPER_ROOT)/ace/Acceptor.cpp \
$(WRAPPER_ROOT)/ace/SOCK_Acceptor.h \
Name_Handler.h
.obj/Server_Logging_Handler.o .shobj/Server_Logging_Handler.so: Server_Logging_Handler.cpp \
@@ -334,6 +418,9 @@ include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
$(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \
$(WRAPPER_ROOT)/ace/Synch_T.h \
$(WRAPPER_ROOT)/ace/Event_Handler.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.cpp \
+ $(WRAPPER_ROOT)/ace/Thread.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.i \
$(WRAPPER_ROOT)/ace/TLI_Acceptor.h \
$(WRAPPER_ROOT)/ace/TLI.h \
$(WRAPPER_ROOT)/ace/IPC_SAP.h \
@@ -357,20 +444,22 @@ include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
$(WRAPPER_ROOT)/ace/Service_Object.h \
$(WRAPPER_ROOT)/ace/Shared_Object.h \
$(WRAPPER_ROOT)/ace/Thread_Manager.h \
- $(WRAPPER_ROOT)/ace/Thread.h \
$(WRAPPER_ROOT)/ace/Signal.h \
$(WRAPPER_ROOT)/ace/Set.h \
+ $(WRAPPER_ROOT)/ace/Set.cpp \
+ $(WRAPPER_ROOT)/ace/Set.i \
$(WRAPPER_ROOT)/ace/Reactor.h \
$(WRAPPER_ROOT)/ace/Handle_Set.h \
$(WRAPPER_ROOT)/ace/Timer_Queue.h \
$(WRAPPER_ROOT)/ace/Token.h \
$(WRAPPER_ROOT)/ace/Pipe.h \
$(WRAPPER_ROOT)/ace/Pipe.i \
- $(WRAPPER_ROOT)/ace/Reactor.i \
$(WRAPPER_ROOT)/ace/Proactor.h \
$(WRAPPER_ROOT)/ace/Message_Block.h \
$(WRAPPER_ROOT)/ace/Malloc.h \
$(WRAPPER_ROOT)/ace/Malloc_T.h \
+ $(WRAPPER_ROOT)/ace/Malloc_T.cpp \
+ $(WRAPPER_ROOT)/ace/Malloc_T.i \
$(WRAPPER_ROOT)/ace/Memory_Pool.h \
$(WRAPPER_ROOT)/ace/Mem_Map.h \
$(WRAPPER_ROOT)/ace/ReactorEx.h \
@@ -378,12 +467,27 @@ include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
$(WRAPPER_ROOT)/ace/IO_Cntl_Msg.h \
$(WRAPPER_ROOT)/ace/Strategies.h \
$(WRAPPER_ROOT)/ace/Strategies_T.h \
+ $(WRAPPER_ROOT)/ace/Strategies_T.cpp \
+ $(WRAPPER_ROOT)/ace/Message_Queue.cpp \
+ $(WRAPPER_ROOT)/ace/Message_Queue.i \
$(WRAPPER_ROOT)/ace/Svc_Conf_Tokens.h \
$(WRAPPER_ROOT)/ace/Svc_Handler.h \
$(WRAPPER_ROOT)/ace/Synch_Options.h \
$(WRAPPER_ROOT)/ace/Task.h \
$(WRAPPER_ROOT)/ace/Task_T.h \
+ $(WRAPPER_ROOT)/ace/Task_T.cpp \
+ $(WRAPPER_ROOT)/ace/Module.h \
+ $(WRAPPER_ROOT)/ace/Module.cpp \
+ $(WRAPPER_ROOT)/ace/Stream_Modules.h \
+ $(WRAPPER_ROOT)/ace/Stream_Modules.cpp \
+ $(WRAPPER_ROOT)/ace/Stream_Modules.i \
+ $(WRAPPER_ROOT)/ace/Module.i \
+ $(WRAPPER_ROOT)/ace/Task_T.i \
+ $(WRAPPER_ROOT)/ace/Svc_Handler.cpp \
+ $(WRAPPER_ROOT)/ace/Dynamic.h \
+ $(WRAPPER_ROOT)/ace/Svc_Handler.i \
$(WRAPPER_ROOT)/ace/Acceptor.i \
+ $(WRAPPER_ROOT)/ace/Acceptor.cpp \
Server_Logging_Handler.h
.obj/Token_Handler.o .shobj/Token_Handler.so: Token_Handler.cpp \
$(WRAPPER_ROOT)/ace/Get_Opt.h \
@@ -411,8 +515,12 @@ include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
$(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \
$(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \
$(WRAPPER_ROOT)/ace/Synch_T.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.cpp \
+ $(WRAPPER_ROOT)/ace/Synch_T.i \
$(WRAPPER_ROOT)/ace/Signal.h \
$(WRAPPER_ROOT)/ace/Set.h \
+ $(WRAPPER_ROOT)/ace/Set.cpp \
+ $(WRAPPER_ROOT)/ace/Set.i \
$(WRAPPER_ROOT)/ace/Reactor.h \
$(WRAPPER_ROOT)/ace/Handle_Set.h \
$(WRAPPER_ROOT)/ace/Timer_Queue.h \
@@ -429,11 +537,12 @@ include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
$(WRAPPER_ROOT)/ace/SOCK_IO.i \
$(WRAPPER_ROOT)/ace/INET_Addr.h \
$(WRAPPER_ROOT)/ace/SOCK_Stream.i \
- $(WRAPPER_ROOT)/ace/Reactor.i \
$(WRAPPER_ROOT)/ace/Proactor.h \
$(WRAPPER_ROOT)/ace/Message_Block.h \
$(WRAPPER_ROOT)/ace/Malloc.h \
$(WRAPPER_ROOT)/ace/Malloc_T.h \
+ $(WRAPPER_ROOT)/ace/Malloc_T.cpp \
+ $(WRAPPER_ROOT)/ace/Malloc_T.i \
$(WRAPPER_ROOT)/ace/Memory_Pool.h \
$(WRAPPER_ROOT)/ace/Mem_Map.h \
$(WRAPPER_ROOT)/ace/ReactorEx.h \
@@ -441,23 +550,40 @@ include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
$(WRAPPER_ROOT)/ace/IO_Cntl_Msg.h \
$(WRAPPER_ROOT)/ace/Strategies.h \
$(WRAPPER_ROOT)/ace/Strategies_T.h \
+ $(WRAPPER_ROOT)/ace/Strategies_T.cpp \
+ $(WRAPPER_ROOT)/ace/Message_Queue.cpp \
+ $(WRAPPER_ROOT)/ace/Message_Queue.i \
$(WRAPPER_ROOT)/ace/Svc_Conf_Tokens.h \
$(WRAPPER_ROOT)/ace/Svc_Handler.h \
$(WRAPPER_ROOT)/ace/Synch_Options.h \
$(WRAPPER_ROOT)/ace/Task.h \
$(WRAPPER_ROOT)/ace/Task_T.h \
+ $(WRAPPER_ROOT)/ace/Task_T.cpp \
+ $(WRAPPER_ROOT)/ace/Module.h \
+ $(WRAPPER_ROOT)/ace/Module.cpp \
+ $(WRAPPER_ROOT)/ace/Stream_Modules.h \
+ $(WRAPPER_ROOT)/ace/Stream_Modules.cpp \
+ $(WRAPPER_ROOT)/ace/Stream_Modules.i \
+ $(WRAPPER_ROOT)/ace/Module.i \
+ $(WRAPPER_ROOT)/ace/Task_T.i \
+ $(WRAPPER_ROOT)/ace/Svc_Handler.cpp \
+ $(WRAPPER_ROOT)/ace/Dynamic.h \
+ $(WRAPPER_ROOT)/ace/Svc_Handler.i \
$(WRAPPER_ROOT)/ace/Acceptor.i \
+ $(WRAPPER_ROOT)/ace/Acceptor.cpp \
$(WRAPPER_ROOT)/ace/SOCK_Acceptor.h \
$(WRAPPER_ROOT)/ace/Token_Request_Reply.h \
$(WRAPPER_ROOT)/ace/Local_Tokens.h \
$(WRAPPER_ROOT)/ace/Stack.h \
+ $(WRAPPER_ROOT)/ace/Stack.cpp \
+ $(WRAPPER_ROOT)/ace/Stack.i \
$(WRAPPER_ROOT)/ace/Map_Manager.h \
+ $(WRAPPER_ROOT)/ace/Map_Manager.cpp \
+ $(WRAPPER_ROOT)/ace/Map_Manager.i \
$(WRAPPER_ROOT)/ace/Token_Collection.h \
$(WRAPPER_ROOT)/ace/SString.h \
Token_Handler.h
.obj/Logging_Strategy.o .shobj/Logging_Strategy.so: Logging_Strategy.cpp \
- /pkg/gnu/lib/g++-include/iostream.h \
- /pkg/gnu/lib/g++-include/fstream.h \
$(WRAPPER_ROOT)/ace/Get_Opt.h \
$(WRAPPER_ROOT)/ace/ACE.h \
$(WRAPPER_ROOT)/ace/OS.h \
diff --git a/tests/Thread_Pool_Test.cpp b/tests/Thread_Pool_Test.cpp
index 2a0a662914c..761479f9264 100644
--- a/tests/Thread_Pool_Test.cpp
+++ b/tests/Thread_Pool_Test.cpp
@@ -73,7 +73,7 @@ Thread_Pool::close (u_long)
Thread_Pool::Thread_Pool (int n_threads)
{
- // Create worker threads.
+ // Create a pool of worker threads.
if (this->activate (THR_NEW_LWP, n_threads) == -1)
ACE_ERROR ((LM_ERROR, "%p\n", "activate failed"));
}
diff --git a/tests/Timer_Queue_Test.cpp b/tests/Timer_Queue_Test.cpp
index f0ec1c90815..2ff194ba59f 100644
--- a/tests/Timer_Queue_Test.cpp
+++ b/tests/Timer_Queue_Test.cpp
@@ -1,6 +1,6 @@
-// ============================================================================
// $Id$
+// ============================================================================
//
// = LIBRARY
// tests
@@ -9,20 +9,23 @@
// Timer_Queue_Test.cpp
//
// = DESCRIPTION
-// This is a simple test of ACE_Timer_Queue. The test sets up a
-// bunch of timers and then adds them to a timer queue. The
-// functionality of the timer queue is then tested. No command line
-// arguments are needed to run the test.
+// This is a simple test of <ACE_Timer_Queue> and two of its
+// subclasses (<ACE_Timer_List> and <ACE_Timer_Heap>). The test
+// sets up a bunch of timers and then adds them to a timer
+// queue. The functionality of the timer queue is then tested. No
+// command line arguments are needed to run the test.
//
// = AUTHOR
// Prashant Jain
//
// ============================================================================
-
-#include "ace/Timer_Queue.h"
+#include "ace/Timer_List.h"
+#include "ace/Timer_Heap.h"
#include "test_config.h"
+const int MAX_ITERATIONS = ACE_DEFAULT_MAX_TIMERS - 1;
+
class Example_Handler : public ACE_Event_Handler
{
public:
@@ -34,12 +37,9 @@ public:
}
};
-int
-main (int, char *[])
+static void
+test_functionality (ACE_Timer_Queue *tq)
{
- ACE_START_TEST ("Timer_Queue_Test");
-
- ACE_Timer_Queue tq;
Example_Handler eh;
ACE_ASSERT (tq.is_empty ());
@@ -47,20 +47,108 @@ main (int, char *[])
int timer_id;
timer_id = tq.schedule (&eh, (const void *) 1, ACE_OS::gettimeofday ());
- tq.schedule (&eh, (const void *) 42, ACE_OS::gettimeofday ());
- tq.schedule (&eh, (const void *) 42, ACE_OS::gettimeofday ());
- tq.cancel (timer_id);
+ ACE_ASSERT (timer_id != -1);
+
+ ACE_ASSERT (tq.schedule (&eh, (const void *) 42,
+ ACE_OS::gettimeofday ()) != -1);
+ ACE_ASSERT (tq.schedule (&eh, (const void *) 42,
+ ACE_OS::gettimeofday ()) != -1);
+ ACE_ASSERT (tq.cancel (timer_id) == 1);
ACE_ASSERT (!tq.is_empty ());
- tq.expire (ACE_OS::gettimeofday ());
+ ACE_ASSERT (tq.expire (ACE_OS::gettimeofday () == 1));
- tq.schedule (&eh, (const void *) 4, ACE_OS::gettimeofday ());
- tq.schedule (&eh, (const void *) 5, ACE_OS::gettimeofday ());
- tq.cancel (&eh);
+ ACE_ASSERT (tq.schedule (&eh, (const void *) 4, ACE_OS::gettimeofday
+ ()) != -1);
+ ACE_ASSERT (tq.schedule (&eh, (const void *) 5, ACE_OS::gettimeofday
+ ()) != -1);
+ ACE_ASSERT (tq.cancel (&eh) == 2);
ACE_ASSERT (tq.is_empty ());
- tq.expire (ACE_OS::gettimeofday ());
+ ACE_ASSERT (tq.expire (ACE_OS::gettimeofday ()) == 0);
+}
+
+static void
+test_performance (ACE_Timer_Queue *tq,
+ const char *test_name)
+{
+ Example_Handler eh;
+ ACE_Profile_Timer timer;
+ int i;
+
+ ACE_ASSERT (tq->is_empty ());
+ ACE_ASSERT (ACE_Time_Value::zero == ACE_Time_Value (0));
+
+ timer.start ();
+
+ // Test the amount of time required to schedule all the timers.
+ for (i = 0; i < MAX_ITERATIONS; i++)
+ tq->schedule (&eh, (const void *) 42, ACE_OS::gettimeofday ());
+
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+
+ timer.elapsed_time (et);
+
+ ACE_DEBUG ((LM_DEBUG, "time to schedule %d timers for %s\n",
+ MAX_ITERATIONS, test_name));
+ ACE_DEBUG ((LM_DEBUG, "real time = %f secs, user time = %f secs, system time = %f secs\n",
+ et.real_time, et.user_time, et.system_time));
+ ACE_DEBUG ((LM_DEBUG, "time per call = %f usecs\n",
+ (et.real_time / double (MAX_ITERATIONS)) * 1000000));
+
+ timer.start ();
+
+ int timer_id = tq->schedule (&eh, (const void *) 42,
+ ACE_OS::gettimeofday ());
+
+ ACE_ASSERT (timer_id);
+
+ // Test the amount of time required to cancel all the timers (this
+ // takes advantage of the fact that <timer_ids> are always allocated
+ // contiguously starting at 0.
+ for (i = 0; i < MAX_ITERATIONS + 1; i++)
+ tq->cancel (timer_id--);
+
+ ACE_ASSERT (tq->is_empty ());
+
+ timer.elapsed_time (et);
+
+ ACE_DEBUG ((LM_DEBUG, "time to cancel %d timers for %s\n",
+ MAX_ITERATIONS, test_name));
+ ACE_DEBUG ((LM_DEBUG, "real time = %f secs, user time = %f secs, system time = %f secs\n",
+ et.real_time, et.user_time, et.system_time));
+ ACE_DEBUG ((LM_DEBUG, "time per call = %f usecs\n",
+ (et.real_time / double (MAX_ITERATIONS)) * 1000000));
+
+}
+
+struct Timer_Queues
+{
+ ACE_Timer_Queue *queue_;
+ // Pointer to the subclass of <ACE_Timer_Queue> that we're testing.
+
+ const char *name_;
+ // Name of the Queue that we're testing.
+};
+
+static Timer_Queues timer_queues[] =
+{
+ { new ACE_Timer_List, "ACE_Timer_List" },
+ { new ACE_Timer_Heap, "ACE_Timer_Queue" },
+ { 0, 0 };
+}
+
+int
+main (int, char *[])
+{
+ ACE_START_TEST ("Timer_Queue_Test");
+
+ for (int i = 0; timer_queues[i].name_ != 0; i++)
+ {
+ test_performance (timer_queues[i].queue_, timer_queues[i].name_);
+ test_functionality (timer_queues[i].queue_, timer_queues[i].name_);
+ delete timer_queues[i].queue_;
+ }
ACE_END_TEST;
return 0;
}
-