Timer_Queue_Adapters.h

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

Generated on Tue Feb 2 17:18:43 2010 for ACE by  doxygen 1.4.7