diff options
-rw-r--r-- | ChangeLog-97a | 53 | ||||
-rw-r--r-- | README | 1 | ||||
-rw-r--r-- | ace/Map_Manager.h | 2 | ||||
-rw-r--r-- | ace/OS.h | 3 | ||||
-rw-r--r-- | ace/Proactor.cpp | 3 | ||||
-rw-r--r-- | ace/Proactor.h | 26 | ||||
-rw-r--r-- | ace/Reactor.cpp | 3 | ||||
-rw-r--r-- | ace/Reactor.h | 19 | ||||
-rw-r--r-- | ace/ReactorEx.cpp | 3 | ||||
-rw-r--r-- | ace/ReactorEx.h | 28 | ||||
-rw-r--r-- | ace/Timer_Heap.cpp | 204 | ||||
-rw-r--r-- | ace/Timer_Heap.h | 159 | ||||
-rw-r--r-- | ace/Timer_List.cpp | 244 | ||||
-rw-r--r-- | ace/Timer_List.h | 138 | ||||
-rw-r--r-- | ace/Timer_Queue.cpp | 298 | ||||
-rw-r--r-- | ace/Timer_Queue.h | 123 | ||||
-rw-r--r-- | ace/Timer_Queue.i | 12 | ||||
-rw-r--r-- | examples/Logger/Acceptor-server/server_loggerd.cpp | 9 | ||||
-rw-r--r-- | netsvcs/lib/Logging_Strategy.cpp | 4 | ||||
-rw-r--r-- | netsvcs/lib/Makefile | 144 | ||||
-rw-r--r-- | tests/Thread_Pool_Test.cpp | 2 | ||||
-rw-r--r-- | tests/Timer_Queue_Test.cpp | 130 |
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. @@ -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); @@ -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 ¤t_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 ¤t_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 ¤t_time); + virtual int expire (const ACE_Time_Value ¤t_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; } - |