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 */