diff options
author | coryan <coryan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2009-06-28 22:29:08 +0000 |
---|---|---|
committer | coryan <coryan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2009-06-28 22:29:08 +0000 |
commit | 525d59899aa78db156bda075e35c223ff6427853 (patch) | |
tree | 8b34e3d354b4c67e2824c8c4bc78c64d1f9a1da6 | |
parent | 44f9eeafaf8d997fdd3ad635d24bb7060d16f853 (diff) | |
download | ATCD-525d59899aa78db156bda075e35c223ff6427853.tar.gz |
Sun Jun 28 22:15:47 UTC 2009 Carlos O'Ryan <coryan@glamdring>
* ace/ace.mpc:
* ace/Abstract_Timer_Queue.h:
* ace/Abstract_Timer_Queue.cpp:
* ace/Timer_Queue_Iterator.h:
* ace/Timer_Queue_Iterator.inl:
* ace/Timer_Queue_Iterator.cpp:
* ace/Timer_Queuefwd.h:
* ace/Timer_Queue.h:
* ace/Timer_Queue_T.h:
* ace/Timer_Queue_T.inl:
* ace/Timer_Queue_T.cpp:
* ace/Timer_List_T.h:
* ace/Timer_List_T.cpp:
* ace/Timer_Wheel_T.h:
* ace/Timer_Wheel_T.cpp:
* ace/Timer_Hash_T.h:
* ace/Timer_Hash_T.cpp:
* ace/Timer_Heap_T.h:
* ace/Timer_Heap_T.cpp:
Heavy refactoring in ACE_Timer_Queue_T class and friends.
First, created a template base class (ACE_Abstract_Timer_Queue) that:
1) Only depends on the type held by the timer queue, not to lock
or upcall strategy.
2) It is a pure abstract class, i.e., none of its member
functions have any implementation.
3) Provides new pure virtual functions to encapsulates some
logic that was spread between tests, TP_Reactor and
Dev_Poll_Reactor.
Then I re-wrote all the standard timer queue objects in terms of
this class. In particular, the reactors use only the abstract
interface.
I also re-factored the Timer_Queue_Iterator to only depend on
the type of objects held by the timer queue. The rest of the
parameters where not used either.
Implement functionality that was spread in Dev_Poll_Reactor,
TP_Reactor and a test into expire_single.
* ace/Proactor.h:
* ace/TP_Reactor.cpp:
* ace/Dev_Poll_Reactor.cpp:
Both classes implemented the logic to dispatch a single timer
but release a mutex before the upcall. This was confusing as
well as required exposing too much detail about the Timer_Queue
classes.
The new mechanism is a single function in (expire_single)
ACE_Abstract_Timer_Queue<> (implemented in ACE_Timer_Queue_T<>)
which receives a command object to encapsulate the mutex release.
* ace/Functor.h:
* ace/Functor.cpp:
* ace/Functor_T.h:
* ace/Functor_T.inl:
Add helper ACE_Command_* objects. One is a no-op, for the test
below. The other is a callback that ignores the silly void*
argument in the ACE_Command_Base::execute() member function.
* tests/Timer_Queue_Reference_Counting_Test.cpp:
Re-factored test in terms of expire_single()
28 files changed, 870 insertions, 592 deletions
diff --git a/ACE/ChangeLog b/ACE/ChangeLog index 78965f2f08f..2ea189eab6e 100644 --- a/ACE/ChangeLog +++ b/ACE/ChangeLog @@ -1,3 +1,64 @@ +Sun Jun 28 22:15:47 UTC 2009 Carlos O'Ryan <coryan@glamdring> + + * ace/ace.mpc: + * ace/Abstract_Timer_Queue.h: + * ace/Abstract_Timer_Queue.cpp: + * ace/Timer_Queue_Iterator.h: + * ace/Timer_Queue_Iterator.inl: + * ace/Timer_Queue_Iterator.cpp: + * ace/Timer_Queuefwd.h: + * ace/Timer_Queue.h: + * ace/Timer_Queue_T.h: + * ace/Timer_Queue_T.inl: + * ace/Timer_Queue_T.cpp: + * ace/Timer_List_T.h: + * ace/Timer_List_T.cpp: + * ace/Timer_Wheel_T.h: + * ace/Timer_Wheel_T.cpp: + * ace/Timer_Hash_T.h: + * ace/Timer_Hash_T.cpp: + * ace/Timer_Heap_T.h: + * ace/Timer_Heap_T.cpp: + Heavy refactoring in ACE_Timer_Queue_T class and friends. + First, created a template base class (ACE_Abstract_Timer_Queue) that: + 1) Only depends on the type held by the timer queue, not to lock + or upcall strategy. + 2) It is a pure abstract class, i.e., none of its member + functions have any implementation. + 3) Provides new pure virtual functions to encapsulates some + logic that was spread between tests, TP_Reactor and + Dev_Poll_Reactor. + Then I re-wrote all the standard timer queue objects in terms of + this class. In particular, the reactors use only the abstract + interface. + I also re-factored the Timer_Queue_Iterator to only depend on + the type of objects held by the timer queue. The rest of the + parameters where not used either. + Implement functionality that was spread in Dev_Poll_Reactor, + TP_Reactor and a test into expire_single. + + * ace/Proactor.h: + * ace/TP_Reactor.cpp: + * ace/Dev_Poll_Reactor.cpp: + Both classes implemented the logic to dispatch a single timer + but release a mutex before the upcall. This was confusing as + well as required exposing too much detail about the Timer_Queue + classes. + The new mechanism is a single function in (expire_single) + ACE_Abstract_Timer_Queue<> (implemented in ACE_Timer_Queue_T<>) + which receives a command object to encapsulate the mutex release. + + * ace/Functor.h: + * ace/Functor.cpp: + * ace/Functor_T.h: + * ace/Functor_T.inl: + Add helper ACE_Command_* objects. One is a no-op, for the test + below. The other is a callback that ignores the silly void* + argument in the ACE_Command_Base::execute() member function. + + * tests/Timer_Queue_Reference_Counting_Test.cpp: + Re-factored test in terms of expire_single() + Sat Jun 27 00:55:10 UTC 2009 Johnny Willemsen <jwillemsen@remedy.nl> * rpmbuild/ace-tao-ciao.spec: diff --git a/ACE/ace/Abstract_Timer_Queue.cpp b/ACE/ace/Abstract_Timer_Queue.cpp new file mode 100644 index 00000000000..021c637fe6e --- /dev/null +++ b/ACE/ace/Abstract_Timer_Queue.cpp @@ -0,0 +1,24 @@ +#ifndef ACE_ABSTRACT_TIMER_QUEUE_CPP +#define ACE_ABSTRACT_TIMER_QUEUE_CPP +#include "ace/config-all.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Abstract_Timer_Queue.h" + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +// Even though the destructor is pure virtual you must provide an +// implementation. Most people know this, but sometimes we all +// forget, and we might be tempted to remove this code. +template<typename TYPE> +ACE_Abstract_Timer_Queue<TYPE>:: +~ACE_Abstract_Timer_Queue () +{ +} + +ACE_END_VERSIONED_NAMESPACE_DECL + +#endif /* ACE_ABSTRACT_TIMER_QUEUE_CPP */ diff --git a/ACE/ace/Abstract_Timer_Queue.h b/ACE/ace/Abstract_Timer_Queue.h new file mode 100644 index 00000000000..d7c08987ebf --- /dev/null +++ b/ACE/ace/Abstract_Timer_Queue.h @@ -0,0 +1,210 @@ +#ifndef ACE_ABSTRACT_TIMER_QUEUE_H +#define ACE_ABSTRACT_TIMER_QUEUE_H +#include /**/ "ace/pre.h" +/** + * @file Abstract_Timer_Queue.h + * + * @author Carlos O'Ryan <coryan@atdesk.com> + * + * Based on classes and files developed by Doug Schmidt, Darrell + * Brunsch, Irfan Pyarali and a cast of thousands. + */ + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +// Forward declares +class ACE_Time_Value; +class ACE_Command_Base; +template<typename TYPE> class ACE_Timer_Queue_Iterator_T; + +/** + * @class ACE_Abstract_Timer_Queue + * + * @brief Base class for all timer queues of a single type. + * + * This is a base class for all the timer queues, regardless of + * locking strategy, upcall mechanism, internal implementation, etc. + * The class was motivated by bug 3706: + * http://bugzilla.dre.vanderbilt.edu/show_bug.cgi?id=3706 + * In short, the Reactor (and potentially other classes) want to refer + * to timer queues regardless of the implementation internals. + */ +template<typename TYPE> +class ACE_Abstract_Timer_Queue +{ +public: + /// Destructor + virtual ~ACE_Abstract_Timer_Queue (void) = 0; + + /// True if queue is empty, else false. + virtual bool is_empty (void) const = 0; + + /// Returns the time of the earlier node in the Timer_Queue. Must + /// be called on a non-empty queue. + virtual const ACE_Time_Value &earliest_time (void) const = 0; + + /** + * Schedule @a type that will expire at @a future_time, which is + * specified in absolute time. If it expires then @a act is passed + * in as the value to the <functor>. If @a interval is != to + * ACE_Time_Value::zero then it is used to reschedule the @a type + * automatically, using relative time to the current <gettimeofday>. + * This method returns a <timer_id> that uniquely identifies the the + * @a type entry in an internal list. This <timer_id> can be used to + * cancel the timer 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 long schedule (const TYPE &type, + const void *act, + const ACE_Time_Value &future_time, + const ACE_Time_Value &interval = ACE_Time_Value::zero) = 0; + + /** + * Run the <functor> for all timers whose values are <= @a current_time. + * This does not account for <timer_skew>. Returns the number of + * timers canceled. + */ + virtual int expire (const ACE_Time_Value ¤t_time) = 0; + + /** + * Run the <functor> for all timers whose values are <= + * <ACE_OS::gettimeofday>. Also accounts for <timer_skew>. + * + * Depending on the resolution of the underlying OS the system calls + * like select()/poll() might return at time different than that is + * specified in the timeout. Suppose the OS guarantees a resolution of t ms. + * The timeline will look like + * + * A B + * | | + * V V + * |-------------|-------------|-------------|-------------| + * t t t t t + * + * + * If you specify a timeout value of A, then the timeout will not occur + * at A but at the next interval of the timer, which is later than + * that is expected. Similarly, if your timeout value is equal to B, + * then the timeout will occur at interval after B. Now depending upon the + * resolution of your timeouts and the accuracy of the timeouts + * needed for your application, you should set the value of + * <timer_skew>. In the above case, if you want the timeout A to fire + * no later than A, then you should specify your <timer_skew> to be + * A % t. + * + * The timeout value should be specified via the macro ACE_TIMER_SKEW + * in your config.h file. The default value is zero. + * + * Things get interesting if the t before the timeout value B is zero + * i.e your timeout is less than the interval. In that case, you are + * almost sure of not getting the desired timeout behaviour. Maybe you + * should look for a better OS :-) + * + * Returns the number of timers canceled. + */ + virtual int expire (void) = 0; + + /** + * A couple of classes using Timer_Queues need to dispatch a single + * event at a time. But before they dispatch the event they need to + * release a lock, signal other threads, etc. + * + * This member function should be used in that case. The additional + * operations to be called just before dispatching the event, and + * only if an event will be dispatched, are encapsulated in the + * ACE_Command_Base object. + */ + virtual int expire_single(ACE_Command_Base & pre_dispatch_command) = 0; + + /** + * Resets the interval of the timer represented by @a timer_id to + * @a interval, which is specified in relative time to the current + * <gettimeofday>. If @a interval is equal to + * ACE_Time_Value::zero, the timer will become a non-rescheduling + * timer. Returns 0 if successful, -1 if not. + */ + virtual int reset_interval (long timer_id, + const ACE_Time_Value &interval) = 0; + + /** + * Cancel all timer associated with @a type. If + * @a dont_call_handle_close is 0 then the <functor> will be invoked, + * which typically invokes the <handle_close> hook. Returns number + * of timers cancelled. + */ + virtual int cancel (const TYPE &type, + int dont_call_handle_close = 1) = 0; + + /** + * Cancel the single timer that matches the @a timer_id value (which + * was returned from the <schedule> method). If act is non-NULL + * then it will be set to point to the ``magic cookie'' argument + * passed in when the timer was registered. This makes it possible + * to free up the memory and avoid memory leaks. If + * @a dont_call_handle_close is 0 then the <functor> will be invoked, + * which typically calls the <handle_close> hook. Returns 1 if + * cancellation succeeded and 0 if the @a timer_id wasn't found. + */ + virtual int cancel (long timer_id, + const void **act = 0, + int dont_call_handle_close = 1) = 0; + + /** + * Returns the current time of day. This method allows different + * implementations of the timer queue to use special high resolution + * timers. + */ + virtual ACE_Time_Value gettimeofday (void) = 0; + + /** + * Allows applications to control how the timer queue gets the time of day. + */ + virtual void gettimeofday (ACE_Time_Value (*gettimeofday)(void)) = 0; + + /// Determine the next event to timeout. Returns @a max if there are + /// no pending timers or if all pending timers are longer than max. + /// This method acquires a lock internally since it modifies internal state. + virtual ACE_Time_Value *calculate_timeout (ACE_Time_Value *max) = 0; + + /** + * Determine the next event to timeout. Returns @a max if there are + * no pending timers or if all pending timers are longer than max. + * <the_timeout> should be a pointer to storage for the timeout value, + * and this value is also returned. This method does not acquire a + * lock internally since it doesn't modify internal state. If you + * need to call this method when the queue is being modified + * concurrently, however, you should make sure to acquire the <mutex()> + * externally before making the call. + */ + virtual ACE_Time_Value *calculate_timeout (ACE_Time_Value *max, + ACE_Time_Value *the_timeout) = 0; + + /** + * Return the current time, using the right time policy and any + * timer skew defined in derived classes. + */ + virtual ACE_Time_Value current_time() = 0; + + /// Type of Iterator. + typedef ACE_Timer_Queue_Iterator_T<TYPE> ITERATOR; + + /// Returns a pointer to this ACE_Timer_Queue's iterator. + virtual ITERATOR & iter (void) = 0; +}; + +ACE_END_VERSIONED_NAMESPACE_DECL + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Abstract_Timer_Queue.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Abstract_Timer_Queue.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#include /**/ "ace/post.h" +#endif /* ACE_ABSTRACT_TIMER_QUEUE_H */ diff --git a/ACE/ace/Dev_Poll_Reactor.cpp b/ACE/ace/Dev_Poll_Reactor.cpp index a49e9c40f4d..ae871efe74a 100644 --- a/ACE/ace/Dev_Poll_Reactor.cpp +++ b/ACE/ace/Dev_Poll_Reactor.cpp @@ -43,6 +43,7 @@ ACE_RCSID (ace, #include "ace/Guard_T.h" #include "ace/OS_NS_string.h" #include "ace/OS_NS_sys_time.h" +#include "ace/Functor_T.h" ACE_BEGIN_VERSIONED_NAMESPACE_DECL @@ -1084,37 +1085,10 @@ ACE_Dev_Poll_Reactor::dispatch (Token_Guard &guard) int ACE_Dev_Poll_Reactor::dispatch_timer_handler (Token_Guard &guard) { - if (this->timer_queue_->is_empty ()) - return 0; // Empty timer queue so cannot have any expired timers. + typedef ACE_Member_Function_Command<Token_Guard> Guard_Release; - // Get the current time - ACE_Time_Value cur_time (this->timer_queue_->gettimeofday () + - this->timer_queue_->timer_skew ()); - - // Look for a node in the timer queue whose timer <= the present - // time. - ACE_Timer_Node_Dispatch_Info info; - if (this->timer_queue_->dispatch_info (cur_time, info)) - { - const void *upcall_act = 0; - - // Preinvoke (handles refcount if needed, etc.) - this->timer_queue_->preinvoke (info, cur_time, upcall_act); - - // Release the token before expiration upcall. - guard.release_token (); - - // call the functor - this->timer_queue_->upcall (info, cur_time); - - // Postinvoke (undo refcount if needed, etc.) - this->timer_queue_->postinvoke (info, cur_time, upcall_act); - - // We have dispatched a timer - return 1; - } - - return 0; + Guard_Release release(guard, &Token_Guard::release_token); + return this->timer_queue_->expire_single(release); } #if 0 diff --git a/ACE/ace/Functor.cpp b/ACE/ace/Functor.cpp index 9fc3b3400c0..0d0d92fae8a 100644 --- a/ACE/ace/Functor.cpp +++ b/ACE/ace/Functor.cpp @@ -40,4 +40,14 @@ ACE_Command_Base::~ACE_Command_Base (void) { } +ACE_Noop_Command::ACE_Noop_Command() +{ +} + +int +ACE_Noop_Command::execute(void*) +{ + return 0; +} + ACE_END_VERSIONED_NAMESPACE_DECL diff --git a/ACE/ace/Functor.h b/ACE/ace/Functor.h index f303bc09c97..7edcae7174c 100644 --- a/ACE/ace/Functor.h +++ b/ACE/ace/Functor.h @@ -77,6 +77,23 @@ public: virtual int execute (void *arg = 0) = 0; }; +/** + * @class ACE_Noop_Command + * + * Implements a ACE_Command_Base with an empty execute() body. + */ + +class ACE_Export ACE_Noop_Command + : public ACE_Command_Base +{ +public: + /// Constructor + ACE_Noop_Command(); + + /// Implement the empty execute() member function + virtual int execute(void*); +}; + //////////////////////////////////////////////////////////// // STL-style Functor Classes and Template Specializations // //////////////////////////////////////////////////////////// diff --git a/ACE/ace/Functor_T.h b/ACE/ace/Functor_T.h index 554820e3c0b..3b148464308 100644 --- a/ACE/ace/Functor_T.h +++ b/ACE/ace/Functor_T.h @@ -78,6 +78,38 @@ private: ACTION action_; }; +/** + * @class ACE_Member_Function_Command + * + * @brief Defines a class template that allows us to invoke a member + * function using the GoF command style callback. + * + */ +template <class RECEIVER> +class ACE_Member_Function_Command : public ACE_Command_Base +{ +public: + typedef void (RECEIVER::*PTMF)(void); + + /// Con Constructor: sets the <receiver_> of the Command to recvr, and the + /// <action_> of the Command to <action>. + ACE_Member_Function_Command (RECEIVER &recvr, PTMF ptmf); + + /// Virtual destructor. + virtual ~ACE_Member_Function_Command (void); + + /// Invokes the method <action_> from the object <receiver_>. The + /// parameter is ignored + virtual int execute (void *); + +private: + /// Object where the method resides. + RECEIVER &receiver_; + + /// Method that is going to be invoked. + PTMF ptmf_; +}; + ///////////////////////////////// // STL-style Functor Templates // ///////////////////////////////// diff --git a/ACE/ace/Functor_T.inl b/ACE/ace/Functor_T.inl index 6441c091b76..d6cefade1bd 100644 --- a/ACE/ace/Functor_T.inl +++ b/ACE/ace/Functor_T.inl @@ -4,6 +4,27 @@ ACE_BEGIN_VERSIONED_NAMESPACE_DECL +template<class RECEIVER> ACE_INLINE +ACE_Member_Function_Command<RECEIVER>:: +ACE_Member_Function_Command (RECEIVER &recvr, PTMF ptmf) + : receiver_(recvr) + , ptmf_(ptmf) +{ +} + +template<class RECEIVER> ACE_INLINE +ACE_Member_Function_Command<RECEIVER>:: +~ACE_Member_Function_Command (void) +{ +} + +template<class RECEIVER> ACE_INLINE int +ACE_Member_Function_Command<RECEIVER>::execute (void *) +{ + (this->receiver_.*ptmf_)(); + return 0; +} + template <class TYPE> ACE_INLINE unsigned long ACE_Hash<TYPE>::operator () (const TYPE &t) const { diff --git a/ACE/ace/Proactor.h b/ACE/ace/Proactor.h index 704eef416ff..2db4ab9d39c 100644 --- a/ACE/ace/Proactor.h +++ b/ACE/ace/Proactor.h @@ -135,10 +135,8 @@ class ACE_Export ACE_Proactor { // = Here are the private typedefs that the ACE_Proactor uses. - typedef ACE_Timer_Queue_Iterator_T<ACE_Handler *, - ACE_Proactor_Handle_Timeout_Upcall, - ACE_SYNCH_RECURSIVE_MUTEX> - TIMER_QUEUE_ITERATOR; + typedef ACE_Timer_Queue_Iterator_T<ACE_Handler *> + TIMER_QUEUE_ITERATOR; typedef ACE_Timer_List_T<ACE_Handler *, ACE_Proactor_Handle_Timeout_Upcall, ACE_SYNCH_RECURSIVE_MUTEX> diff --git a/ACE/ace/TP_Reactor.cpp b/ACE/ace/TP_Reactor.cpp index ac9bbdada63..16eb60972dc 100644 --- a/ACE/ace/TP_Reactor.cpp +++ b/ACE/ace/TP_Reactor.cpp @@ -5,6 +5,7 @@ #include "ace/Timer_Queue.h" #include "ace/Sig_Handler.h" #include "ace/Log_Msg.h" +#include "ace/Functor_T.h" #include "ace/OS_NS_sys_time.h" #if !defined (__ACE_INLINE__) @@ -307,40 +308,10 @@ int ACE_TP_Reactor::handle_timer_events (int & /*event_count*/, ACE_TP_Token_Guard &guard) { - if (this->timer_queue_ == 0 || this->timer_queue_->is_empty()) - { // Empty timer queue so cannot have any expired timers. - return 0; - } - - // Get the current time - ACE_Time_Value cur_time (this->timer_queue_->gettimeofday () + - this->timer_queue_->timer_skew ()); - - // Look for a node in the timer queue whose timer <= the present - // time. - ACE_Timer_Node_Dispatch_Info info; - - if (this->timer_queue_->dispatch_info (cur_time, info)) - { - const void *upcall_act = 0; - - // Preinvoke. - this->timer_queue_->preinvoke (info, cur_time, upcall_act); + typedef ACE_Member_Function_Command<ACE_TP_Token_Guard> Guard_Release; - // Release the token before dispatching notifies... - guard.release_token (); - - // call the functor - this->timer_queue_->upcall (info, cur_time); - - // Postinvoke - this->timer_queue_->postinvoke (info, cur_time, upcall_act); - - // We have dispatched a timer - return 1; - } - - return 0; + Guard_Release release(guard, &ACE_TP_Token_Guard::release_token); + return this->timer_queue_->expire_single(release); } int diff --git a/ACE/ace/Timer_Hash_T.cpp b/ACE/ace/Timer_Hash_T.cpp index a2a81fc3773..15ff0b86334 100644 --- a/ACE/ace/Timer_Hash_T.cpp +++ b/ACE/ace/Timer_Hash_T.cpp @@ -258,7 +258,7 @@ ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::item (void) } template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> -ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> & +ACE_Timer_Queue_Iterator_T<TYPE> & ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::iter (void) { this->iterator_->first (); @@ -638,9 +638,7 @@ ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::cancel (const TYPE &type, i < this->table_size_; ++i) { - ACE_Timer_Queue_Iterator_T<TYPE, - ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>, - ACE_Null_Mutex> &iter = + ACE_Timer_Queue_Iterator_T<TYPE> & iter = this->table_[i]->iter (); for (iter.first (); diff --git a/ACE/ace/Timer_Hash_T.h b/ACE/ace/Timer_Hash_T.h index 53072ebd51c..cc3b6b786d3 100644 --- a/ACE/ace/Timer_Hash_T.h +++ b/ACE/ace/Timer_Hash_T.h @@ -119,7 +119,7 @@ private: * in the order of timeout values. */ template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> -class ACE_Timer_Hash_Iterator_T : public ACE_Timer_Queue_Iterator_T <TYPE, FUNCTOR, ACE_LOCK> +class ACE_Timer_Hash_Iterator_T : public ACE_Timer_Queue_Iterator_T <TYPE> { public: /// Constructor. @@ -145,7 +145,7 @@ protected: size_t position_; /// Current iterator used on <position>'s bucket - ACE_Timer_Queue_Iterator_T<TYPE, ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>, ACE_Null_Mutex> *iter_; + ACE_Timer_Queue_Iterator_T<TYPE> *iter_; }; /** @@ -252,7 +252,7 @@ public: virtual int expire (const ACE_Time_Value ¤t_time); /// Returns a pointer to this ACE_Timer_Queue's iterator. - virtual ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> &iter (void); + virtual ACE_Timer_Queue_Iterator_T<TYPE> &iter (void); /// Removes the earliest node from the queue and returns it virtual ACE_Timer_Node_T<TYPE> *remove_first (void); diff --git a/ACE/ace/Timer_Heap_T.cpp b/ACE/ace/Timer_Heap_T.cpp index c15597cf334..aef61388db2 100644 --- a/ACE/ace/Timer_Heap_T.cpp +++ b/ACE/ace/Timer_Heap_T.cpp @@ -317,7 +317,7 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::is_empty (void) const } template <class TYPE, class FUNCTOR, class ACE_LOCK> -ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> & +ACE_Timer_Queue_Iterator_T<TYPE> & ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::iter (void) { this->iterator_->first (); diff --git a/ACE/ace/Timer_Heap_T.h b/ACE/ace/Timer_Heap_T.h index 00c128b1aa9..e4bcdbefced 100644 --- a/ACE/ace/Timer_Heap_T.h +++ b/ACE/ace/Timer_Heap_T.h @@ -39,7 +39,7 @@ class ACE_Timer_Heap_T; * in the order of timeout values. */ template <class TYPE, class FUNCTOR, class ACE_LOCK> -class ACE_Timer_Heap_Iterator_T : public ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> +class ACE_Timer_Heap_Iterator_T : public ACE_Timer_Queue_Iterator_T<TYPE> { public: /// Constructor. @@ -163,7 +163,7 @@ public: int dont_call_handle_close = 1); /// Returns a pointer to this ACE_Timer_Queue's iterator. - virtual ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> &iter (void); + virtual ACE_Timer_Queue_Iterator_T<TYPE> &iter (void); /** * Removes the earliest node from the queue and returns it. Note that diff --git a/ACE/ace/Timer_List_T.cpp b/ACE/ace/Timer_List_T.cpp index e2313d0e002..c969b31ea64 100644 --- a/ACE/ace/Timer_List_T.cpp +++ b/ACE/ace/Timer_List_T.cpp @@ -70,7 +70,7 @@ ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::item (void) // Return our instance of the iterator -template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> & +template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Queue_Iterator_T<TYPE> & ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::iter (void) { this->iterator_->first (); diff --git a/ACE/ace/Timer_List_T.h b/ACE/ace/Timer_List_T.h index d4ec800340e..d4180172b8e 100644 --- a/ACE/ace/Timer_List_T.h +++ b/ACE/ace/Timer_List_T.h @@ -34,7 +34,7 @@ class ACE_Timer_List_T; */ template <class TYPE, class FUNCTOR, class ACE_LOCK> class ACE_Timer_List_Iterator_T -: public ACE_Timer_Queue_Iterator_T <TYPE, FUNCTOR, ACE_LOCK> +: public ACE_Timer_Queue_Iterator_T <TYPE> { public: typedef ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK> List; @@ -147,7 +147,7 @@ public: int dont_call_handle_close = 1); /// Returns a pointer to this ACE_Timer_Queue's iterator. - virtual ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>& iter (void); + virtual ACE_Timer_Queue_Iterator_T<TYPE>& iter (void); /// Removes the earliest node from the queue and returns it virtual ACE_Timer_Node_T<TYPE>* remove_first (void); diff --git a/ACE/ace/Timer_Queue.h b/ACE/ace/Timer_Queue.h index 36182f15f95..cee9f6bab84 100644 --- a/ACE/ace/Timer_Queue.h +++ b/ACE/ace/Timer_Queue.h @@ -40,9 +40,7 @@ typedef ACE_Timer_Node_Dispatch_Info_T<ACE_Event_Handler *> typedef ACE_Timer_Node_T<ACE_Event_Handler *> ACE_Timer_Node; -typedef ACE_Timer_Queue_Iterator_T<ACE_Event_Handler *, - ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>, - ACE_SYNCH_RECURSIVE_MUTEX> +typedef ACE_Timer_Queue_Iterator_T<ACE_Event_Handler *> ACE_Timer_Queue_Iterator; ACE_END_VERSIONED_NAMESPACE_DECL diff --git a/ACE/ace/Timer_Queue_Iterator.cpp b/ACE/ace/Timer_Queue_Iterator.cpp new file mode 100644 index 00000000000..d777396f489 --- /dev/null +++ b/ACE/ace/Timer_Queue_Iterator.cpp @@ -0,0 +1,56 @@ +#ifndef ACE_TIMER_QUEUE_ITERATOR_CPP +#define ACE_TIMER_QUEUE_ITERATOR_CPP + +#include "ace/config-all.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#if !defined (__ACE_INLINE__) +#include "ace/Timer_Queue_Iterator.inl" +#endif /* __ACE_INLINE__ */ + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +template <class TYPE> void +ACE_Timer_Node_T<TYPE>::dump (void) const +{ +#if defined (ACE_HAS_DUMP) + ACE_TRACE ("ACE_Timer_Node_T::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nact_ = %x"), this->act_)); + this->timer_value_.dump (); + this->interval_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nprev_ = %x"), this->prev_)); + ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nnext_ = %x"), this->next_)); + ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntimer_id_ = %d\n"), this->timer_id_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +#endif /* ACE_HAS_DUMP */ +} + +template <class TYPE> +ACE_Timer_Node_T<TYPE>::ACE_Timer_Node_T (void) +{ + ACE_TRACE ("ACE_Timer_Node_T::ACE_Timer_Node_T"); +} + +template <class TYPE> +ACE_Timer_Node_T<TYPE>::~ACE_Timer_Node_T (void) +{ + ACE_TRACE ("ACE_Timer_Node_T::~ACE_Timer_Node_T"); +} + +template <class TYPE> +ACE_Timer_Queue_Iterator_T<TYPE>::ACE_Timer_Queue_Iterator_T (void) +{ +} + +template <class TYPE> +ACE_Timer_Queue_Iterator_T<TYPE>::~ACE_Timer_Queue_Iterator_T (void) +{ +} + +ACE_END_VERSIONED_NAMESPACE_DECL + +#endif /* ACE_TIMER_QUEUE_ITERATOR_CPP */ diff --git a/ACE/ace/Timer_Queue_Iterator.h b/ACE/ace/Timer_Queue_Iterator.h new file mode 100644 index 00000000000..5e953dcfa1c --- /dev/null +++ b/ACE/ace/Timer_Queue_Iterator.h @@ -0,0 +1,196 @@ +#ifndef ACE_TIMER_QUEUE_ITERATOR_H +#define ACE_TIMER_QUEUE_ITERATOR_H +#include /**/ "ace/pre.h" +/** + * @file Timer_Queue_Iterator.h + * + * Re-factored from Timer_Queue_T.h + */ + +#include "ace/Time_Value.h" + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @class ACE_Timer_Node_Dispatch_Info_T + * + * @brief Maintains generated dispatch information for Timer nodes. + * + */ +template <class TYPE> +class ACE_Timer_Node_Dispatch_Info_T +{ +public: + /// The type of object held in the queue + TYPE type_; + + /// Asynchronous completion token associated with the timer. + const void *act_; + + /// Flag to check if the timer is recurring. + int recurring_timer_; +}; + +/** + * @class ACE_Timer_Node_T + * + * @brief Maintains the state associated with a Timer entry. + */ +template <class TYPE> +class ACE_Timer_Node_T +{ +public: + /// Default constructor + ACE_Timer_Node_T (void); + + /// Destructor + ~ACE_Timer_Node_T (void); + + /// Useful typedef .. + typedef ACE_Timer_Node_Dispatch_Info_T <TYPE> DISPATCH_INFO; + + /// Singly linked list + void set (const TYPE &type, + const void *a, + const ACE_Time_Value &t, + const ACE_Time_Value &i, + ACE_Timer_Node_T<TYPE> *n, + long timer_id); + + /// Doubly linked list version + void set (const TYPE &type, + const void *a, + const ACE_Time_Value &t, + const ACE_Time_Value &i, + ACE_Timer_Node_T<TYPE> *p, + ACE_Timer_Node_T<TYPE> *n, + long timer_id); + + // = Accessors + + /// Get the type. + TYPE &get_type (void); + + /// Set the type. + void set_type (TYPE &type); + + /// Get the asynchronous completion token. + const void *get_act (void); + + /// Set the asynchronous completion token. + void set_act (void *act); + + /// Get the timer value. + const ACE_Time_Value &get_timer_value (void) const; + + /// Set the timer value. + void set_timer_value (const ACE_Time_Value &timer_value); + + /// Get the timer interval. + const ACE_Time_Value &get_interval (void) const; + + /// Set the timer interval. + void set_interval (const ACE_Time_Value &interval); + + /// Get the previous pointer. + ACE_Timer_Node_T<TYPE> *get_prev (void); + + /// Set the previous pointer. + void set_prev (ACE_Timer_Node_T<TYPE> *prev); + + /// Get the next pointer. + ACE_Timer_Node_T<TYPE> *get_next (void); + + /// Set the next pointer. + void set_next (ACE_Timer_Node_T<TYPE> *next); + + /// Get the timer_id. + long get_timer_id (void) const; + + /// Set the timer_id. + void set_timer_id (long timer_id); + + /// Get the dispatch info. The dispatch information is got + /// through <info>. This form helps us in preventing allocation and + /// deleting data along the criticl path. + /// @@TODO: We may want to have a copying version too, so that our + /// interface will be complete.. + void get_dispatch_info (ACE_Timer_Node_Dispatch_Info_T <TYPE> &info); + + /// Dump the state of an TYPE. + void dump (void) const; + +private: + /// Type of object stored in the Queue + TYPE type_; + + /// Asynchronous completion token associated with the timer. + const void *act_; + + /// Time until the timer expires. + ACE_Time_Value timer_value_; + + /// If this is a periodic timer this holds the time until the next + /// timeout. + ACE_Time_Value interval_; + + /// Pointer to previous timer. + ACE_Timer_Node_T<TYPE> *prev_; + + /// Pointer to next timer. + ACE_Timer_Node_T<TYPE> *next_; + + /// Id of this timer (used to cancel timers before they expire). + long timer_id_; +}; + +/** + * @class ACE_Timer_Queue_Iterator_T + * + * @brief Generic interface for iterating over a subclass of + * ACE_Timer_Queue. + * + * This is a generic iterator that can be used to visit every + * node of a timer queue. Be aware that it isn't guaranteed + * that the transversal will be in order of timeout values. + */ +template <class TYPE> +class ACE_Timer_Queue_Iterator_T +{ +public: + // = Initialization and termination methods. + /// Constructor. + ACE_Timer_Queue_Iterator_T (void); + + /// Destructor. + virtual ~ACE_Timer_Queue_Iterator_T (void); + + /// Positions the iterator at the earliest node in the Timer Queue + virtual void first (void) = 0; + + /// Positions the iterator at the next node in the Timer Queue + virtual void next (void) = 0; + + /// Returns true when there are no more nodes in the sequence + virtual bool isdone (void) const = 0; + + /// Returns the node at the current position in the sequence + virtual ACE_Timer_Node_T<TYPE> *item (void) = 0; +}; + +ACE_END_VERSIONED_NAMESPACE_DECL + +#if defined (__ACE_INLINE__) +#include "ace/Timer_Queue_Iterator.inl" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Timer_Queue_Iterator.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Timer_Queue_Iterator.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#include /**/ "ace/post.h" +#endif /* ACE_TIMER_QUEUE_ITERATOR_H */ diff --git a/ACE/ace/Timer_Queue_Iterator.inl b/ACE/ace/Timer_Queue_Iterator.inl new file mode 100644 index 00000000000..353f98cf128 --- /dev/null +++ b/ACE/ace/Timer_Queue_Iterator.inl @@ -0,0 +1,135 @@ +// -*- C++ -*- +// +// $Id$ + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +template <class TYPE> ACE_INLINE void +ACE_Timer_Node_T<TYPE>::set (const TYPE &type, + const void *a, + const ACE_Time_Value &t, + const ACE_Time_Value &i, + ACE_Timer_Node_T<TYPE> *n, + long timer_id) +{ + this->type_ = type; + this->act_ = a; + this->timer_value_ = t; + this->interval_ = i; + this->next_ = n; + this->timer_id_ = timer_id; +} + +template <class TYPE> ACE_INLINE void +ACE_Timer_Node_T<TYPE>::set (const TYPE &type, + const void *a, + const ACE_Time_Value &t, + const ACE_Time_Value &i, + ACE_Timer_Node_T<TYPE> *p, + ACE_Timer_Node_T<TYPE> *n, + long timer_id) +{ + this->type_ = type; + this->act_ = a; + this->timer_value_ = t; + this->interval_ = i; + this->prev_ = p; + this->next_ = n; + this->timer_id_ = timer_id; +} + +template <class TYPE> ACE_INLINE TYPE & +ACE_Timer_Node_T<TYPE>::get_type (void) +{ + return this->type_; +} + +template <class TYPE> ACE_INLINE void +ACE_Timer_Node_T<TYPE>::set_type (TYPE &type) +{ + this->type_ = type; +} + +template <class TYPE> ACE_INLINE const void * +ACE_Timer_Node_T<TYPE>::get_act (void) +{ + return this->act_; +} + +template <class TYPE> ACE_INLINE void +ACE_Timer_Node_T<TYPE>::set_act (void *act) +{ + this->act_ = act; +} + +template <class TYPE> ACE_INLINE const ACE_Time_Value & +ACE_Timer_Node_T<TYPE>::get_timer_value (void) const +{ + return this->timer_value_; +} + +template <class TYPE> ACE_INLINE void +ACE_Timer_Node_T<TYPE>::set_timer_value (const ACE_Time_Value &timer_value) +{ + this->timer_value_ = timer_value; +} + +template <class TYPE> ACE_INLINE const ACE_Time_Value & +ACE_Timer_Node_T<TYPE>::get_interval (void) const +{ + return this->interval_; +} + +template <class TYPE> ACE_INLINE void +ACE_Timer_Node_T<TYPE>::set_interval (const ACE_Time_Value &interval) +{ + this->interval_ = interval; +} + +template <class TYPE> ACE_INLINE ACE_Timer_Node_T<TYPE> * +ACE_Timer_Node_T<TYPE>::get_prev (void) +{ + return this->prev_; +} + +template <class TYPE> ACE_INLINE void +ACE_Timer_Node_T<TYPE>::set_prev (ACE_Timer_Node_T<TYPE> *prev) +{ + this->prev_ = prev; +} + +template <class TYPE> ACE_INLINE ACE_Timer_Node_T<TYPE> * +ACE_Timer_Node_T<TYPE>::get_next (void) +{ + return this->next_; +} + +template <class TYPE> ACE_INLINE void +ACE_Timer_Node_T<TYPE>::set_next (ACE_Timer_Node_T<TYPE> *next) +{ + this->next_ = next; +} + +template <class TYPE> ACE_INLINE long +ACE_Timer_Node_T<TYPE>::get_timer_id (void) const +{ + return this->timer_id_; +} + +template <class TYPE> ACE_INLINE void +ACE_Timer_Node_T<TYPE>::set_timer_id (long timer_id) +{ + this->timer_id_ = timer_id; +} + +template <class TYPE> ACE_INLINE void +ACE_Timer_Node_T<TYPE>::get_dispatch_info (ACE_Timer_Node_Dispatch_Info_T<TYPE> &info) +{ + // Yes, do a copy + info.type_ = this->type_; + info.act_ = this->act_; + info.recurring_timer_ = + this->interval_ > ACE_Time_Value::zero; +} + +ACE_END_VERSIONED_NAMESPACE_DECL diff --git a/ACE/ace/Timer_Queue_T.cpp b/ACE/ace/Timer_Queue_T.cpp index 2ac9a29e9aa..07792ddb6a4 100644 --- a/ACE/ace/Timer_Queue_T.cpp +++ b/ACE/ace/Timer_Queue_T.cpp @@ -20,6 +20,7 @@ #include "ace/Reactor_Timer_Interface.h" #include "ace/Null_Mutex.h" #include "ace/OS_NS_sys_time.h" +#include "ace/Functor.h" #if !defined (__ACE_INLINE__) #include "ace/Timer_Queue_T.inl" @@ -34,44 +35,6 @@ ACE_BEGIN_VERSIONED_NAMESPACE_DECL # define ACE_TIMER_SKEW 0 #endif /* ACE_TIMER_SKEW */ -template <class TYPE> void -ACE_Timer_Node_T<TYPE>::dump (void) const -{ -#if defined (ACE_HAS_DUMP) - ACE_TRACE ("ACE_Timer_Node_T::dump"); - ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); - ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nact_ = %x"), this->act_)); - this->timer_value_.dump (); - this->interval_.dump (); - ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nprev_ = %x"), this->prev_)); - ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nnext_ = %x"), this->next_)); - ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntimer_id_ = %d\n"), this->timer_id_)); - ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); -#endif /* ACE_HAS_DUMP */ -} - -template <class TYPE> -ACE_Timer_Node_T<TYPE>::ACE_Timer_Node_T (void) -{ - ACE_TRACE ("ACE_Timer_Node_T::ACE_Timer_Node_T"); -} - -template <class TYPE> -ACE_Timer_Node_T<TYPE>::~ACE_Timer_Node_T (void) -{ - ACE_TRACE ("ACE_Timer_Node_T::~ACE_Timer_Node_T"); -} - -template <class TYPE, class FUNCTOR, class ACE_LOCK> -ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Queue_Iterator_T (void) -{ -} - -template <class TYPE, class FUNCTOR, class ACE_LOCK> -ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::~ACE_Timer_Queue_Iterator_T (void) -{ -} - template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Time_Value * ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::calculate_timeout (ACE_Time_Value *max_wait_time) { @@ -152,6 +115,14 @@ ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::calculate_timeout (ACE_Time_Value *m return the_timeout; } +template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Time_Value +ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::current_time() +{ + ACE_Time_Value tv = this->gettimeofday(); + tv += this->timer_skew(); + return tv; +} + template <class TYPE, class FUNCTOR, class ACE_LOCK> void ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::dump (void) const { @@ -283,6 +254,46 @@ ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::expire (const ACE_Time_Value &cur_ti return number_of_timers_expired; } +template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_INLINE int +ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::expire_single ( + ACE_Command_Base & pre_dispatch_command) +{ + ACE_TRACE ("ACE_Timer_Queue_T::expire_single"); + ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1)); + + if (this->is_empty ()) + return 0; + + // Get the current time + ACE_Time_Value cur_time (this->gettimeofday () + + this->timer_skew ()); + + // Look for a node in the timer queue whose timer <= the present + // time. + ACE_Timer_Node_Dispatch_Info_T<TYPE> info; + if (this->dispatch_info_i (cur_time, info)) + { + const void *upcall_act = 0; + + // Preinvoke (handles refcount if needed, etc.) + this->preinvoke (info, cur_time, upcall_act); + + // Release the token before expiration upcall. + pre_dispatch_command.execute(); + + // call the functor + this->upcall (info, cur_time); + + // Postinvoke (undo refcount if needed, etc.) + this->postinvoke (info, cur_time, upcall_act); + + // We have dispatched a timer + return 1; + } + + return 0; +} + template <class TYPE, class FUNCTOR, class ACE_LOCK> int ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::dispatch_info_i (const ACE_Time_Value &cur_time, ACE_Timer_Node_Dispatch_Info_T<TYPE> &info) diff --git a/ACE/ace/Timer_Queue_T.h b/ACE/ace/Timer_Queue_T.h index 8aef637579e..f796d9975df 100644 --- a/ACE/ace/Timer_Queue_T.h +++ b/ACE/ace/Timer_Queue_T.h @@ -16,185 +16,20 @@ #define ACE_TIMER_QUEUE_T_H #include /**/ "ace/pre.h" -#include "ace/Free_List.h" - #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ +#include "ace/Free_List.h" #include "ace/Event_Handler.h" #include "ace/Time_Value.h" +#include "ace/Abstract_Timer_Queue.h" +#include "ace/Timer_Queue_Iterator.h" +#include "ace/Copy_Disabled.h" ACE_BEGIN_VERSIONED_NAMESPACE_DECL /** - * @class ACE_Timer_Node_Dispatch_Info_T - * - * @brief Maintains generated dispatch information for Timer nodes. - * - */ -template <class TYPE> -class ACE_Timer_Node_Dispatch_Info_T -{ -public: - /// The type of object held in the queue - TYPE type_; - - /// Asynchronous completion token associated with the timer. - const void *act_; - - /// Flag to check if the timer is recurring. - int recurring_timer_; -}; - -/** - * @class ACE_Timer_Node_T - * - * @brief Maintains the state associated with a Timer entry. - */ -template <class TYPE> -class ACE_Timer_Node_T -{ -public: - /// Default constructor - ACE_Timer_Node_T (void); - - /// Destructor - ~ACE_Timer_Node_T (void); - - /// Useful typedef .. - typedef ACE_Timer_Node_Dispatch_Info_T <TYPE> DISPATCH_INFO; - - /// Singly linked list - void set (const TYPE &type, - const void *a, - const ACE_Time_Value &t, - const ACE_Time_Value &i, - ACE_Timer_Node_T<TYPE> *n, - long timer_id); - - /// Doubly linked list version - void set (const TYPE &type, - const void *a, - const ACE_Time_Value &t, - const ACE_Time_Value &i, - ACE_Timer_Node_T<TYPE> *p, - ACE_Timer_Node_T<TYPE> *n, - long timer_id); - - // = Accessors - - /// Get the type. - TYPE &get_type (void); - - /// Set the type. - void set_type (TYPE &type); - - /// Get the asynchronous completion token. - const void *get_act (void); - - /// Set the asynchronous completion token. - void set_act (void *act); - - /// Get the timer value. - const ACE_Time_Value &get_timer_value (void) const; - - /// Set the timer value. - void set_timer_value (const ACE_Time_Value &timer_value); - - /// Get the timer interval. - const ACE_Time_Value &get_interval (void) const; - - /// Set the timer interval. - void set_interval (const ACE_Time_Value &interval); - - /// Get the previous pointer. - ACE_Timer_Node_T<TYPE> *get_prev (void); - - /// Set the previous pointer. - void set_prev (ACE_Timer_Node_T<TYPE> *prev); - - /// Get the next pointer. - ACE_Timer_Node_T<TYPE> *get_next (void); - - /// Set the next pointer. - void set_next (ACE_Timer_Node_T<TYPE> *next); - - /// Get the timer_id. - long get_timer_id (void) const; - - /// Set the timer_id. - void set_timer_id (long timer_id); - - /// Get the dispatch info. The dispatch information is got - /// through <info>. This form helps us in preventing allocation and - /// deleting data along the criticl path. - /// @@TODO: We may want to have a copying version too, so that our - /// interface will be complete.. - void get_dispatch_info (ACE_Timer_Node_Dispatch_Info_T <TYPE> &info); - - /// Dump the state of an TYPE. - void dump (void) const; - -private: - /// Type of object stored in the Queue - TYPE type_; - - /// Asynchronous completion token associated with the timer. - const void *act_; - - /// Time until the timer expires. - ACE_Time_Value timer_value_; - - /// If this is a periodic timer this holds the time until the next - /// timeout. - ACE_Time_Value interval_; - - /// Pointer to previous timer. - ACE_Timer_Node_T<TYPE> *prev_; - - /// Pointer to next timer. - ACE_Timer_Node_T<TYPE> *next_; - - /// Id of this timer (used to cancel timers before they expire). - long timer_id_; -}; - -/** - * @class ACE_Timer_Queue_Iterator_T - * - * @brief Generic interface for iterating over a subclass of - * ACE_Timer_Queue. - * - * This is a generic iterator that can be used to visit every - * node of a timer queue. Be aware that it isn't guaranteed - * that the transversal will be in order of timeout values. - */ -template <class TYPE, class FUNCTOR, class ACE_LOCK> -class ACE_Timer_Queue_Iterator_T -{ -public: - // = Initialization and termination methods. - /// Constructor. - ACE_Timer_Queue_Iterator_T (void); - - /// Destructor. - virtual ~ACE_Timer_Queue_Iterator_T (void); - - /// Positions the iterator at the earliest node in the Timer Queue - virtual void first (void) = 0; - - /// Positions the iterator at the next node in the Timer Queue - virtual void next (void) = 0; - - /// Returns true when there are no more nodes in the sequence - virtual bool isdone (void) const = 0; - - /// Returns the node at the current position in the sequence - virtual ACE_Timer_Node_T<TYPE> *item (void) = 0; -}; - -/** * @class ACE_Timer_Queue_T * * @brief Provides an interface to timers. @@ -205,11 +40,10 @@ public: */ template <class TYPE, class FUNCTOR, class ACE_LOCK> class ACE_Timer_Queue_T + : public ACE_Abstract_Timer_Queue<TYPE> + , private ACE_Copy_Disabled { public: - /// Type of Iterator. - typedef ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> ITERATOR; - // = Initialization and termination methods. /** * Default constructor. @a upcall_functor is the instance of the @@ -224,72 +58,24 @@ public: /// classes. virtual ~ACE_Timer_Queue_T (void); - /// True if queue is empty, else false. - virtual bool is_empty (void) const = 0; - - /// Returns the time of the earlier node in the Timer_Queue. Must - /// be called on a non-empty queue. - virtual const ACE_Time_Value &earliest_time (void) const = 0; - /** - * Schedule @a type that will expire at @a future_time, which is - * specified in absolute time. If it expires then @a act is passed - * in as the value to the <functor>. If @a interval is != to - * ACE_Time_Value::zero then it is used to reschedule the @a type - * automatically, using relative time to the current <gettimeofday>. - * This method returns a <timer_id> that uniquely identifies the the - * @a type entry in an internal list. This <timer_id> can be used to - * cancel the timer 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>). + * Implement ACE_Abstract_Timer_Queue<TYPE>::schedule () with the right + * locking strategy. */ virtual long schedule (const TYPE &type, const void *act, const ACE_Time_Value &future_time, const ACE_Time_Value &interval = ACE_Time_Value::zero); + //@{ /** - * Resets the interval of the timer represented by @a timer_id to - * @a interval, which is specified in relative time to the current - * <gettimeofday>. If @a interval is equal to - * ACE_Time_Value::zero, the timer will become a non-rescheduling - * timer. Returns 0 if successful, -1 if not. - */ - virtual int reset_interval (long timer_id, - const ACE_Time_Value &interval) = 0; - - /** - * Cancel all timer associated with @a type. If - * @a dont_call_handle_close is 0 then the <functor> will be invoked, - * which typically invokes the <handle_close> hook. Returns number - * of timers cancelled. - */ - virtual int cancel (const TYPE &type, - int dont_call_handle_close = 1) = 0; - - /** - * Cancel the single timer that matches the @a timer_id value (which - * was returned from the <schedule> method). If act is non-NULL - * then it will be set to point to the ``magic cookie'' argument - * passed in when the timer was registered. This makes it possible - * to free up the memory and avoid memory leaks. If - * @a dont_call_handle_close is 0 then the <functor> will be invoked, - * which typically calls the <handle_close> hook. Returns 1 if - * cancellation succeeded and 0 if the @a timer_id wasn't found. - */ - virtual int cancel (long timer_id, - const void **act = 0, - int dont_call_handle_close = 1) = 0; - - /** - * Run the <functor> for all timers whose values are <= @a current_time. - * This does not account for <timer_skew>. Returns the number of - * timers canceled. + * Implement ACE_Abstract_Timer_Queue<TYPE>::expire () with the right + * locking strategy. */ virtual int expire (const ACE_Time_Value ¤t_time); + virtual int expire (void); + virtual int expire_single(ACE_Command_Base & pre_dispatch_command); + //@} /** * Get the dispatch information for a timer whose value is <= @a current_time. @@ -300,73 +86,25 @@ public: virtual int dispatch_info (const ACE_Time_Value ¤t_time, ACE_Timer_Node_Dispatch_Info_T<TYPE> &info); - /** - * Run the <functor> for all timers whose values are <= - * <ACE_OS::gettimeofday>. Also accounts for <timer_skew>. - * - * Depending on the resolution of the underlying OS the system calls - * like select()/poll() might return at time different than that is - * specified in the timeout. Suppose the OS guarantees a resolution of t ms. - * The timeline will look like - * - * A B - * | | - * V V - * |-------------|-------------|-------------|-------------| - * t t t t t - * - * - * If you specify a timeout value of A, then the timeout will not occur - * at A but at the next interval of the timer, which is later than - * that is expected. Similarly, if your timeout value is equal to B, - * then the timeout will occur at interval after B. Now depending upon the - * resolution of your timeouts and the accuracy of the timeouts - * needed for your application, you should set the value of - * <timer_skew>. In the above case, if you want the timeout A to fire - * no later than A, then you should specify your <timer_skew> to be - * A % t. - * - * The timeout value should be specified via the macro ACE_TIMER_SKEW - * in your config.h file. The default value is zero. - * - * Things get interesting if the t before the timeout value B is zero - * i.e your timeout is less than the interval. In that case, you are - * almost sure of not getting the desired timeout behaviour. Maybe you - * should look for a better OS :-) - * - * Returns the number of timers canceled. - */ - /* virtual */ int expire (void); + //@{ /** - * Returns the current time of day. This method allows different - * implementations of the timer queue to use special high resolution - * timers. + * Implement the gettimeofday() functions */ - /* virtual */ ACE_Time_Value gettimeofday (void); - - /// Allows applications to control how the timer queue gets the time - /// of day. - void gettimeofday (ACE_Time_Value (*gettimeofday)(void)); - - /// Determine the next event to timeout. Returns @a max if there are - /// no pending timers or if all pending timers are longer than max. - /// This method acquires a lock internally since it modifies internal state. - virtual ACE_Time_Value *calculate_timeout (ACE_Time_Value *max); + virtual ACE_Time_Value gettimeofday (void); + virtual void gettimeofday (ACE_Time_Value (*gettimeofday)(void)); + //@} + //@{ /** - * Determine the next event to timeout. Returns @a max if there are - * no pending timers or if all pending timers are longer than max. - * <the_timeout> should be a pointer to storage for the timeout value, - * and this value is also returned. This method does not acquire a - * lock internally since it doesn't modify internal state. If you - * need to call this method when the queue is being modified - * concurrently, however, you should make sure to acquire the <mutex()> - * externally before making the call. + * Implement calculate_timeout() using the right locking policy */ + virtual ACE_Time_Value *calculate_timeout (ACE_Time_Value *max); virtual ACE_Time_Value *calculate_timeout (ACE_Time_Value *max, ACE_Time_Value *the_timeout); + virtual ACE_Time_Value current_time(); + //@} /// Set the timer skew for the Timer_Queue. void timer_skew (const ACE_Time_Value &skew); @@ -380,15 +118,12 @@ public: /// Accessor to the upcall functor FUNCTOR &upcall_functor (void); - /// Returns a pointer to this ACE_Timer_Queue's iterator. - virtual ITERATOR &iter (void) = 0; + /// Dump the state of a object. + virtual void dump (void) const; /// Removes the earliest node from the queue and returns it virtual ACE_Timer_Node_T<TYPE> *remove_first (void) = 0; - /// Dump the state of a object. - virtual void dump (void) const; - /// Reads the earliest node from the queue and returns it. virtual ACE_Timer_Node_T<TYPE> *get_first (void) = 0; @@ -457,10 +192,6 @@ private: /// Adjusts for timer skew in various clocks. ACE_Time_Value timer_skew_; - - // = Don't allow these operations for now. - ACE_UNIMPLEMENTED_FUNC (ACE_Timer_Queue_T (const ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> &)) - ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> &)) }; /** @@ -473,6 +204,7 @@ private: */ template <class ACE_LOCK> class ACE_Event_Handler_Handle_Timeout_Upcall + : private ACE_Copy_Disabled { public: typedef ACE_Timer_Queue_T<ACE_Event_Handler *, @@ -538,10 +270,6 @@ private: /// Flag indicating that reference counting is required for this /// event handler upcall. int requires_reference_counting_; - - // = Don't allow these operations for now. - ACE_UNIMPLEMENTED_FUNC (ACE_Event_Handler_Handle_Timeout_Upcall (const ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK> &)) - ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK> &)) }; ACE_END_VERSIONED_NAMESPACE_DECL diff --git a/ACE/ace/Timer_Queue_T.inl b/ACE/ace/Timer_Queue_T.inl index 7275119e2e1..b282af01b7e 100644 --- a/ACE/ace/Timer_Queue_T.inl +++ b/ACE/ace/Timer_Queue_T.inl @@ -4,134 +4,6 @@ ACE_BEGIN_VERSIONED_NAMESPACE_DECL -template <class TYPE> ACE_INLINE void -ACE_Timer_Node_T<TYPE>::set (const TYPE &type, - const void *a, - const ACE_Time_Value &t, - const ACE_Time_Value &i, - ACE_Timer_Node_T<TYPE> *n, - long timer_id) -{ - this->type_ = type; - this->act_ = a; - this->timer_value_ = t; - this->interval_ = i; - this->next_ = n; - this->timer_id_ = timer_id; -} - -template <class TYPE> ACE_INLINE void -ACE_Timer_Node_T<TYPE>::set (const TYPE &type, - const void *a, - const ACE_Time_Value &t, - const ACE_Time_Value &i, - ACE_Timer_Node_T<TYPE> *p, - ACE_Timer_Node_T<TYPE> *n, - long timer_id) -{ - this->type_ = type; - this->act_ = a; - this->timer_value_ = t; - this->interval_ = i; - this->prev_ = p; - this->next_ = n; - this->timer_id_ = timer_id; -} - -template <class TYPE> ACE_INLINE TYPE & -ACE_Timer_Node_T<TYPE>::get_type (void) -{ - return this->type_; -} - -template <class TYPE> ACE_INLINE void -ACE_Timer_Node_T<TYPE>::set_type (TYPE &type) -{ - this->type_ = type; -} - -template <class TYPE> ACE_INLINE const void * -ACE_Timer_Node_T<TYPE>::get_act (void) -{ - return this->act_; -} - -template <class TYPE> ACE_INLINE void -ACE_Timer_Node_T<TYPE>::set_act (void *act) -{ - this->act_ = act; -} - -template <class TYPE> ACE_INLINE const ACE_Time_Value & -ACE_Timer_Node_T<TYPE>::get_timer_value (void) const -{ - return this->timer_value_; -} - -template <class TYPE> ACE_INLINE void -ACE_Timer_Node_T<TYPE>::set_timer_value (const ACE_Time_Value &timer_value) -{ - this->timer_value_ = timer_value; -} - -template <class TYPE> ACE_INLINE const ACE_Time_Value & -ACE_Timer_Node_T<TYPE>::get_interval (void) const -{ - return this->interval_; -} - -template <class TYPE> ACE_INLINE void -ACE_Timer_Node_T<TYPE>::set_interval (const ACE_Time_Value &interval) -{ - this->interval_ = interval; -} - -template <class TYPE> ACE_INLINE ACE_Timer_Node_T<TYPE> * -ACE_Timer_Node_T<TYPE>::get_prev (void) -{ - return this->prev_; -} - -template <class TYPE> ACE_INLINE void -ACE_Timer_Node_T<TYPE>::set_prev (ACE_Timer_Node_T<TYPE> *prev) -{ - this->prev_ = prev; -} - -template <class TYPE> ACE_INLINE ACE_Timer_Node_T<TYPE> * -ACE_Timer_Node_T<TYPE>::get_next (void) -{ - return this->next_; -} - -template <class TYPE> ACE_INLINE void -ACE_Timer_Node_T<TYPE>::set_next (ACE_Timer_Node_T<TYPE> *next) -{ - this->next_ = next; -} - -template <class TYPE> ACE_INLINE long -ACE_Timer_Node_T<TYPE>::get_timer_id (void) const -{ - return this->timer_id_; -} - -template <class TYPE> ACE_INLINE void -ACE_Timer_Node_T<TYPE>::set_timer_id (long timer_id) -{ - this->timer_id_ = timer_id; -} - -template <class TYPE> ACE_INLINE void -ACE_Timer_Node_T<TYPE>::get_dispatch_info (ACE_Timer_Node_Dispatch_Info_T<TYPE> &info) -{ - // Yes, do a copy - info.type_ = this->type_; - info.act_ = this->act_; - info.recurring_timer_ = - this->interval_ > ACE_Time_Value::zero; -} - template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_INLINE void ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::timer_skew (const ACE_Time_Value &skew) { diff --git a/ACE/ace/Timer_Queuefwd.h b/ACE/ace/Timer_Queuefwd.h index 6e03204bdde..af1b844d84d 100644 --- a/ACE/ace/Timer_Queuefwd.h +++ b/ACE/ace/Timer_Queuefwd.h @@ -17,19 +17,13 @@ #include /**/ "ace/pre.h" -#include "ace/Synch_Traits.h" +#include "ace/config-all.h" ACE_BEGIN_VERSIONED_NAMESPACE_DECL -template <class TYPE, class FUNCTOR, class ACE_LOCK> class ACE_Timer_Queue_T; -template <class ACE_LOCK> class ACE_Event_Handler_Handle_Timeout_Upcall; - class ACE_Event_Handler; - -typedef ACE_Timer_Queue_T<ACE_Event_Handler *, - ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>, - ACE_SYNCH_RECURSIVE_MUTEX> - ACE_Timer_Queue; +template <class TYPE> class ACE_Abstract_Timer_Queue; +typedef ACE_Abstract_Timer_Queue<ACE_Event_Handler*> ACE_Timer_Queue; ACE_END_VERSIONED_NAMESPACE_DECL diff --git a/ACE/ace/Timer_Wheel_T.cpp b/ACE/ace/Timer_Wheel_T.cpp index b860c1604dd..1392c63a5a7 100644 --- a/ACE/ace/Timer_Wheel_T.cpp +++ b/ACE/ace/Timer_Wheel_T.cpp @@ -783,7 +783,7 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::get_first_i (void) const * @return The iterator */ template <class TYPE, class FUNCTOR, class ACE_LOCK> -ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>& +ACE_Timer_Queue_Iterator_T<TYPE> & ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::iter (void) { this->iterator_->first (); diff --git a/ACE/ace/Timer_Wheel_T.h b/ACE/ace/Timer_Wheel_T.h index 40179f7a734..431944bb024 100644 --- a/ACE/ace/Timer_Wheel_T.h +++ b/ACE/ace/Timer_Wheel_T.h @@ -37,7 +37,7 @@ class ACE_Timer_Wheel_T; */ template <class TYPE, class FUNCTOR, class ACE_LOCK> class ACE_Timer_Wheel_Iterator_T - : public ACE_Timer_Queue_Iterator_T <TYPE, FUNCTOR, ACE_LOCK> + : public ACE_Timer_Queue_Iterator_T <TYPE> { public: typedef ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK> Wheel; @@ -150,7 +150,7 @@ public: int expire (const ACE_Time_Value& current_time); /// Returns a pointer to this <ACE_Timer_Queue_T>'s iterator. - virtual ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>& iter (void); + virtual ACE_Timer_Queue_Iterator_T<TYPE> & iter (void); /// Removes the earliest node from the queue and returns it virtual ACE_Timer_Node_T<TYPE>* remove_first (void); diff --git a/ACE/ace/ace.mpc b/ACE/ace/ace.mpc index fbc2424a2ed..859668c158d 100644 --- a/ACE/ace/ace.mpc +++ b/ACE/ace/ace.mpc @@ -282,6 +282,7 @@ project(ACE) : ace_output, acedefaults, install, other, codecs, token, svcconf, } Template_Files { + Abstract_Timer_Queue.cpp Acceptor.cpp Active_Map_Manager_T.cpp ARGV.cpp @@ -358,6 +359,7 @@ project(ACE) : ace_output, acedefaults, install, other, codecs, token, svcconf, Timer_Heap_T.cpp Timer_List_T.cpp Timer_Queue_Adapters.cpp + Timer_Queue_Iterator.cpp Timer_Queue_T.cpp Timer_Wheel_T.cpp Tokenizer_T.cpp diff --git a/ACE/tests/Timer_Queue_Reference_Counting_Test.cpp b/ACE/tests/Timer_Queue_Reference_Counting_Test.cpp index d0dcafff858..17abcf0827c 100644 --- a/ACE/tests/Timer_Queue_Reference_Counting_Test.cpp +++ b/ACE/tests/Timer_Queue_Reference_Counting_Test.cpp @@ -266,38 +266,8 @@ invoke_expire (ACE_Timer_Queue &timer_queue) int invoke_one_upcall (ACE_Timer_Queue &timer_queue) { - // Get the current time - ACE_Time_Value current_time (timer_queue.gettimeofday () + - timer_queue.timer_skew ()); - - // Look for a node in the timer queue whose timer <= the present - // time. - ACE_Timer_Node_Dispatch_Info dispatch_info; - - if (timer_queue.dispatch_info (current_time, - dispatch_info)) - { - const void *upcall_act = 0; - - // Preinvoke. - timer_queue.preinvoke (dispatch_info, - current_time, - upcall_act); - - // Call the functor - timer_queue.upcall (dispatch_info, - current_time); - - // Postinvoke - timer_queue.postinvoke (dispatch_info, - current_time, - upcall_act); - - // We have dispatched a timer - return 1; - } - - return 0; + ACE_Noop_Command command; + return timer_queue.expire_single(command); } void |