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