Timer_Queue_Adapters.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 //=============================================================================
00004 /**
00005  *  @file    Timer_Queue_Adapters.h
00006  *
00007  *  Timer_Queue_Adapters.h,v 4.46 2006/04/28 15:28:05 shuston Exp
00008  *
00009  *  @author Douglas C. Schmidt <schmidt@cs.wustl.edu> and
00010  *          Carlos O'Ryan <coryan@uci.edu>
00011  */
00012 //=============================================================================
00013 
00014 #ifndef ACE_TIMER_QUEUE_ADAPTERS_H
00015 #define ACE_TIMER_QUEUE_ADAPTERS_H
00016 #include /**/ "ace/pre.h"
00017 
00018 #include "ace/Task.h"
00019 
00020 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00021 # pragma once
00022 #endif /* ACE_LACKS_PRAGMA_ONCE */
00023 
00024 #include "ace/Signal.h"
00025 #include "ace/Condition_Recursive_Thread_Mutex.h"
00026 
00027 #if defined (ACE_HAS_DEFERRED_TIMER_COMMANDS)
00028 #  include "ace/Unbounded_Queue.h"
00029 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00030 class ACE_Command_Base;
00031 ACE_END_VERSIONED_NAMESPACE_DECL
00032 #endif /* ACE_HAS_DEFERRED_TIMER_COMMANDS */
00033 
00034 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00035 
00036 /**
00037  * @class ACE_Async_Timer_Queue_Adapter
00038  *
00039  * @brief Adapts an ACE timer queue to be driven asynchronously using signals.
00040  *
00041  * This implementation uses the ACE_OS::ualarm call, to generate
00042  * the SIGARLM signal that is caught by this class.
00043  *
00044  * @note This adapter only works on platforms that support ualarm().
00045  * POSIX platforms generally do; Windows and some others do not.
00046  *
00047  * @todo This adapter does not automatically reschedule repeating timers.
00048  */
00049 template <class TQ>
00050 class ACE_Async_Timer_Queue_Adapter : public ACE_Event_Handler
00051 {
00052 public:
00053   typedef TQ TIMER_QUEUE;
00054 
00055   /// Constructor
00056   /**
00057    * Register the SIGALRM handler.  If @a mask == 0 then block all
00058    * signals when @c SIGALRM is run.  Otherwise, just block the signals
00059    * indicated in @a mask.
00060    */
00061   ACE_Async_Timer_Queue_Adapter (ACE_Sig_Set *mask = 0);
00062 
00063   /// Schedule the timer according to the semantics of the
00064   /// ACE_Timer_List.
00065   /**
00066    * This timer gets dispatched via a signal, rather than by a user
00067    * calling expire().  Note that interval timers are not implemented
00068    * yet.
00069    */
00070   long schedule (ACE_Event_Handler *type,
00071                  const void *act,
00072                  const ACE_Time_Value &future_time,
00073                  const ACE_Time_Value &interval = ACE_Time_Value::zero);
00074 
00075   /// Cancel the @a timer_id and pass back the @a act if an address is
00076   /// passed in.
00077   int cancel (long timer_id, const void **act = 0);
00078 
00079   /// Dispatch all timers with expiry time at or before the current time.
00080   /// Returns the number of timers expired.
00081   int expire (void);
00082 
00083   /// Return a reference to the underlying timer queue.
00084   TQ &timer_queue (void);
00085 
00086 private:
00087   /// Perform the logic to compute the new ualarm(2) setting.
00088   virtual int schedule_ualarm (void);
00089 
00090   /// Called back by @c SIGALRM handler.
00091   virtual int handle_signal (int signum, siginfo_t *, ucontext_t *);
00092 
00093   /// Handler for the @c SIGALRM signal, so that we can access our state
00094   /// without requiring any global variables.
00095   ACE_Sig_Handler sig_handler_;
00096 
00097   /// Implementation of the timer queue (e.g., ACE_Timer_List,
00098   /// ACE_Timer_Heap, etc.).
00099   TQ timer_queue_;
00100 
00101   /// Mask of signals to be blocked when we're servicing @c SIGALRM.
00102   ACE_Sig_Set mask_;
00103 };
00104 
00105 /**
00106  * @class ACE_Thread_Timer_Queue_Adapter
00107  *
00108  * @brief Adapts an ACE timer queue using a separate thread for dispatching.
00109  *
00110  * This implementation uses a separate thread to dispatch the timers.
00111  * The base queue need not be thread safe; this class takes all the
00112  * necessary locks.
00113  *
00114  * @note This is a case where template parameters will be useful, but
00115  * (IMHO) the effort and portability problems discourage their
00116  * use.
00117  *
00118  */
00119 template <class TQ>
00120 class ACE_Thread_Timer_Queue_Adapter : public ACE_Task_Base
00121 {
00122 public:
00123   /// Trait for the underlying queue type.
00124   typedef TQ TIMER_QUEUE;
00125 
00126 # if defined (ACE_HAS_DEFERRED_TIMER_COMMANDS)
00127 
00128   /// Typedef for the position at which to enqueue a deferred
00129   /// execution command.
00130   enum COMMAND_ENQUEUE_POSITION {HEAD, TAIL};
00131 
00132 # endif /* ACE_HAS_DEFERRED_TIMER_COMMANDS */
00133 
00134   /// Creates the timer queue.  Activation of the task is the user's
00135   /// responsibility. Optionally a pointer to a timer queue can be passed,
00136   /// when no pointer is passed, a TQ is dynamically created
00137   ACE_Thread_Timer_Queue_Adapter (ACE_Thread_Manager * = ACE_Thread_Manager::instance (),
00138                                   TQ* timer_queue = 0);
00139 
00140   /// Destructor.
00141   virtual ~ACE_Thread_Timer_Queue_Adapter (void);
00142 
00143   /// Schedule the timer according to the semantics of the <TQ>; wakes
00144   /// up the dispatching thread.
00145   long schedule (ACE_Event_Handler *handler,
00146                  const void *act,
00147                  const ACE_Time_Value &future_time,
00148                  const ACE_Time_Value &interval = ACE_Time_Value::zero);
00149 
00150   /// Cancel the @a timer_id and return the @a act parameter if an
00151   /// address is passed in. Also wakes up the dispatching thread.
00152   int cancel (long timer_id, const void **act = 0);
00153 
00154   /// Runs the dispatching thread.
00155   virtual int svc (void);
00156 
00157   /// Inform the dispatching thread that it should terminate.
00158   virtual void deactivate (void);
00159 
00160   /// Access the locking mechanism, useful for iteration.
00161   ACE_SYNCH_RECURSIVE_MUTEX &mutex (void);
00162 
00163   /// Set a user-specified timer queue.
00164   int timer_queue (TQ *tq);
00165 
00166   /// Return the current <TQ>.
00167   TQ *timer_queue (void) const;
00168 
00169   /// Return the thread id of our active object.
00170   ACE_thread_t thr_id (void) const;
00171 
00172   /**
00173    * We override the default activate() method so that we can ensure
00174    * that only a single thread is ever spawned.  Otherwise, too many
00175    * weird things can happen...
00176    */
00177   virtual int activate (long flags = THR_NEW_LWP | THR_JOINABLE,
00178                         int n_threads = 1,
00179                         int force_active = 0,
00180                         long priority = ACE_DEFAULT_THREAD_PRIORITY,
00181                         int grp_id = -1,
00182                         ACE_Task_Base *task = 0,
00183                         ACE_hthread_t thread_handles[] = 0,
00184                         void *stack[] = 0,
00185                         size_t stack_size[] = 0,
00186                         ACE_thread_t thread_names[] = 0);
00187 
00188 # if defined (ACE_HAS_DEFERRED_TIMER_COMMANDS)
00189 
00190   /**
00191    * Enqueues a command object for execution just before waiting on the next
00192    * timer event. This allows deferred execution of commands that cannot
00193    * be performed in the timer event handler context, such as registering
00194    * or cancelling timers on platforms where the timer queue mutex is not
00195    * recursive.
00196    */
00197   int enqueue_command (ACE_Command_Base *command_,
00198                        COMMAND_ENQUEUE_POSITION pos = TAIL);
00199 
00200 # endif /* ACE_HAS_DEFERRED_TIMER_COMMANDS */
00201 
00202 private:
00203 
00204 # if defined (ACE_HAS_DEFERRED_TIMER_COMMANDS)
00205   /// Dispatches all command objects enqueued in the most
00206   /// recent event handler context.
00207   int dispatch_commands (void);
00208 
00209   /// Queue of commands for deferred execution.
00210   ACE_Unbounded_Queue<ACE_Command_Base *> command_queue_;
00211 
00212   /// The mutual exclusion mechanism for the command queue.
00213   ACE_SYNCH_MUTEX command_mutex_;
00214 # endif /* ACE_HAS_DEFERRED_TIMER_COMMANDS */
00215 
00216   /// The underlying Timer_Queue.
00217   TQ* timer_queue_;
00218 
00219   /// Keeps track of whether we should delete the timer queue (if we
00220   /// didn't create it, then we don't delete it).
00221   int delete_timer_queue_;
00222 
00223   /// The mutual exclusion mechanism that is required to use the
00224   /// <condition_>.
00225   ACE_SYNCH_RECURSIVE_MUTEX mutex_;
00226 
00227   /**
00228    * The dispatching thread sleeps on this condition while waiting to
00229    * dispatch the next timer; it is used to wake it up if there is a
00230    * change on the timer queue.
00231    */
00232   ACE_SYNCH_RECURSIVE_CONDITION condition_;
00233 
00234   /// When deactivate is called this variable turns to false and the
00235   /// dispatching thread is signalled, to terminate its main loop.
00236   int active_;
00237 
00238   /// Thread id of our active object task.
00239   ACE_thread_t thr_id_;
00240 };
00241 
00242 ACE_END_VERSIONED_NAMESPACE_DECL
00243 
00244 #if defined (__ACE_INLINE__)
00245 # include "ace/Timer_Queue_Adapters.inl"
00246 #endif /* __ACE_INLINE__ */
00247 
00248 #if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
00249 # include "ace/Timer_Queue_Adapters.cpp"
00250 #endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
00251 
00252 #if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
00253 # pragma implementation ("Timer_Queue_Adapters.cpp")
00254 #endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
00255 
00256 #include /**/ "ace/post.h"
00257 #endif /* ACE_TIMER_QUEUE_ADAPTERS_H */

Generated on Thu Nov 9 09:42:07 2006 for ACE by doxygen 1.3.6