Fixed typos
[ACE_TAO.git] / ACE / ace / Timer_Queue_Adapters.cpp
blob7f12d825813d6a0ce4c9dd6644314312f86a6ca8
1 #ifndef ACE_TIMER_QUEUE_ADAPTERS_CPP
2 #define ACE_TIMER_QUEUE_ADAPTERS_CPP
4 #include "ace/Timer_Queue_Adapters.h"
6 #if defined (ACE_HAS_DEFERRED_TIMER_COMMANDS)
7 #include "ace/Functor.h"
8 #endif /* ACE_HAS_DEFERRED_TIMER_COMMANDS */
10 #if !defined (ACE_LACKS_PRAGMA_ONCE)
11 # pragma once
12 #endif /* ACE_LACKS_PRAGMA_ONCE */
14 # if !defined (__ACE_INLINE__)
15 # include "ace/Timer_Queue_Adapters.inl"
16 # endif /* __ACE_INLINE__ */
18 #include "ace/Reverse_Lock_T.h"
19 #include "ace/Signal.h"
20 #include "ace/OS_NS_unistd.h"
21 #include "ace/OS_NS_sys_time.h"
23 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
25 template <class TQ, class TYPE> TQ &
26 ACE_Async_Timer_Queue_Adapter<TQ, TYPE>::timer_queue (void)
28 return this->timer_queue_;
31 template <class TQ, class TYPE> int
32 ACE_Async_Timer_Queue_Adapter<TQ, TYPE>::cancel (long timer_id,
33 const void **act)
35 // Block designated signals.
36 ACE_Sig_Guard sg (&this->mask_);
37 ACE_UNUSED_ARG (sg);
39 return this->timer_queue_.cancel (timer_id, act);
42 template <class TQ, class TYPE> int
43 ACE_Async_Timer_Queue_Adapter<TQ, TYPE>::expire (void)
45 // Block designated signals.
46 ACE_Sig_Guard sg (&this->mask_);
47 ACE_UNUSED_ARG (sg);
49 return this->timer_queue_.expire ();
52 template <class TQ, class TYPE> int
53 ACE_Async_Timer_Queue_Adapter<TQ, TYPE>::schedule_ualarm (void)
55 ACE_Time_Value tv = this->timer_queue_.earliest_time ()
56 - this->timer_queue_.gettimeofday ();
58 // Beware of negative times and zero times (which cause problems for
59 // <ualarm>).
60 if (tv < ACE_Time_Value::zero)
61 tv = ACE_Time_Value (0, 1);
63 // @@ This code should be clever enough to avoid updating the
64 // <ualarm> if we haven't actually changed the earliest time.
65 // Schedule a new timer.
66 ACE_OS::ualarm (tv);
67 return 0;
70 template <class TQ, class TYPE> long
71 ACE_Async_Timer_Queue_Adapter<TQ, TYPE>::schedule (TYPE eh,
72 const void *act,
73 const ACE_Time_Value &future_time,
74 const ACE_Time_Value &interval)
76 ACE_UNUSED_ARG (act);
77 ACE_UNUSED_ARG (interval);
79 // Block designated signals.
80 ACE_Sig_Guard sg (&this->mask_);
81 ACE_UNUSED_ARG (sg);
83 // @@ We still need to implement interval timers...
84 long tid = this->timer_queue_.schedule (eh, act, future_time);
86 if (tid == -1)
87 ACELIB_ERROR_RETURN ((LM_ERROR,
88 ACE_TEXT ("%p\n"),
89 ACE_TEXT ("schedule_timer")),
90 -1);
92 if (this->schedule_ualarm () == -1)
93 return 0;
95 return tid;
98 template <class TQ, class TYPE>
99 ACE_Async_Timer_Queue_Adapter<TQ, TYPE>::ACE_Async_Timer_Queue_Adapter (ACE_Sig_Set *mask)
100 // If <mask> == 0, block *all* signals when the SIGARLM handler is
101 // running, else just block those in the mask.
102 : mask_ (mask)
104 // The following code is necessary to selectively "block" certain
105 // signals when SIGALRM is running. Also, we always restart system
106 // calls that are interrupted by the signals.
108 ACE_Sig_Action sa ((ACE_SignalHandler) 0,
109 this->mask_,
110 SA_RESTART);
112 if (this->sig_handler_.register_handler (SIGALRM, this, &sa) == -1)
113 ACELIB_ERROR ((LM_ERROR,
114 ACE_TEXT ("%p\n"),
115 ACE_TEXT ("register_handler")));
118 // This is the signal handler function for the asynchronous timer
119 // list. It gets invoked asynchronously when the SIGALRM signal
120 // occurs.
122 template <class TQ, class TYPE> int
123 ACE_Async_Timer_Queue_Adapter<TQ, TYPE>::handle_signal (int signum,
124 siginfo_t *,
125 ucontext_t *)
127 switch (signum)
129 case SIGALRM:
131 // Expire the pending timers.
133 // @@ We need to figure out how to implement interval
134 // timers...
135 this->timer_queue_.expire ();
137 // Only schedule a new timer if there is one in the list.
139 // @@ This code should also become smarter to avoid
140 // unnecessary calls to ualarm().
141 if (this->timer_queue_.is_empty () == 0)
142 return this->schedule_ualarm ();
143 else
144 return 0;
145 /* NOTREACHED */
147 default:
148 ACELIB_ERROR_RETURN ((LM_ERROR,
149 "unexpected signal %S\n",
150 signum),
151 -1);
152 /* NOTREACHED */
156 template<class TQ, class TYPE>
157 ACE_Thread_Timer_Queue_Adapter<TQ, TYPE>::ACE_Thread_Timer_Queue_Adapter (ACE_Thread_Manager *tm,
158 TQ* timer_queue)
159 : ACE_Task_Base (tm),
160 timer_queue_(timer_queue),
161 delete_timer_queue_(false),
162 condition_ (mutex_, cond_attr_),
163 active_ (true), // Assume that we start in active mode.
164 thr_id_ (ACE_OS::NULL_thread)
166 if (timer_queue_ == 0)
168 ACE_NEW (this->timer_queue_,
169 TQ);
170 this->delete_timer_queue_ = true;
174 template<class TQ, class TYPE>
175 ACE_Thread_Timer_Queue_Adapter<TQ, TYPE>::~ACE_Thread_Timer_Queue_Adapter (void)
177 if (this->delete_timer_queue_)
179 delete this->timer_queue_;
180 this->timer_queue_ = 0;
181 this->delete_timer_queue_ = false;
183 else if (this->timer_queue_)
185 this->timer_queue_->close ();
186 this->timer_queue_ = 0;
190 template<class TQ, class TYPE> ACE_SYNCH_RECURSIVE_MUTEX &
191 ACE_Thread_Timer_Queue_Adapter<TQ, TYPE>::mutex (void)
193 return this->mutex_;
196 template<class TQ, class TYPE> long
197 ACE_Thread_Timer_Queue_Adapter<TQ, TYPE>::schedule
198 (TYPE handler,
199 const void *act,
200 const ACE_Time_Value &future_time,
201 const ACE_Time_Value &interval)
203 ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX, guard, this->mutex_, -1);
205 long result = this->timer_queue_->schedule (handler, act, future_time, interval);
206 this->condition_.signal ();
207 return result;
210 template<class TQ, class TYPE> int
211 ACE_Thread_Timer_Queue_Adapter<TQ, TYPE>::cancel (long timer_id,
212 const void **act)
214 ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX, guard, this->mutex_, -1);
216 int result = this->timer_queue_->cancel (timer_id, act);
217 condition_.signal ();
218 return result;
221 template<class TQ, class TYPE> void
222 ACE_Thread_Timer_Queue_Adapter<TQ, TYPE>::deactivate (void)
224 ACE_GUARD (ACE_SYNCH_RECURSIVE_MUTEX, guard, this->mutex_);
226 this->active_ = false;
227 this->condition_.signal ();
230 template<class TQ, class TYPE> int
231 ACE_Thread_Timer_Queue_Adapter<TQ, TYPE>::svc (void)
233 ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX, guard, this->mutex_, -1);
235 this->thr_id_ = ACE_Thread::self ();
237 // Thread cancellation point, if ACE supports it.
239 // Note: This call generates a warning under Solaris because the header
240 // file /usr/include/pthread.h redefines the routine argument. This
241 // is a bug in the Solaris header files and has nothing to do with
242 // ACE.
243 # if !defined (ACE_LACKS_PTHREAD_CANCEL)
244 ACE_PTHREAD_CLEANUP_PUSH (&this->condition_.mutex ().get_nesting_mutex ());
245 # endif /* ACE_LACKS_PTHREAD_CANCEL */
247 while (this->active_)
249 # if defined (ACE_HAS_DEFERRED_TIMER_COMMANDS)
250 // Temporarily suspend ownership of the timer queue mutex in
251 // order to dispatch deferred execution commands. These
252 // commands are to be treated as executing in a context
253 // "external" to the timer queue adapter, and thus must compete
254 // separately for this lock.
255 mutex_.release ();
256 this->dispatch_commands ();
258 // Re-acquire ownership of the timer queue mutex in order to
259 // restore the "internal" timer queue adapter context
260 mutex_.acquire ();
261 # endif /* ACE_HAS_DEFERRED_TIMER_COMMANDS */
263 // If the queue is empty, sleep until there is a change on it.
264 if (this->timer_queue_->is_empty ())
265 this->condition_.wait ();
266 else
268 // Compute the remaining time, being careful not to sleep
269 // for "negative" amounts of time.
270 ACE_Time_Value const tv_curr =
271 this->timer_queue_->gettimeofday ();
272 ACE_Time_Value const tv_earl =
273 this->timer_queue_->earliest_time ();
275 if (tv_earl > tv_curr)
277 // The earliest time on the Timer_Queue lies in future;
278 // convert the tv to an absolute time.
279 ACE_Time_Value const tv = this->timer_queue_->gettimeofday () + (tv_earl - tv_curr);
280 // ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("waiting until %u.%3.3u secs\n"),
281 // tv.sec(), tv.msec()));
282 this->condition_.wait (&tv);
286 // Expire timers anyway, at worst this is a no-op. Release the lock
287 // while dispatching; the timer queue has its own lock to protect
288 // itself.
290 ACE_Reverse_Lock<ACE_SYNCH_RECURSIVE_MUTEX> rel (this->mutex_);
291 ACE_GUARD_RETURN (ACE_Reverse_Lock<ACE_SYNCH_RECURSIVE_MUTEX>,
292 rmon, rel, -1);
293 this->timer_queue_->expire ();
297 // Thread cancellation point, if ACE supports it.
298 # if !defined (ACE_LACKS_PTHREAD_CANCEL)
299 ACE_PTHREAD_CLEANUP_POP (0);
300 # endif /* ACE_LACKS_PTHREAD_CANCEL */
302 return 0;
305 template<class TQ, class TYPE> int
306 ACE_Thread_Timer_Queue_Adapter<TQ, TYPE>::activate (long flags,
307 int ,
308 int ,
309 long priority,
310 int grp_id,
311 ACE_Task_Base *task,
312 ACE_hthread_t [],
313 void *stack[],
314 size_t stack_size[],
315 ACE_thread_t thread_ids[],
316 const char* thr_name[])
318 // Make sure to set this flag in case we were deactivated earlier.
319 this->active_ = true;
321 // Make sure that we only allow a single thread to be spawned for
322 // our adapter. Otherwise, too many weird things can happen.
323 return ACE_Task_Base::activate (flags, 1, 0, priority, grp_id, task, 0,
324 stack, stack_size, thread_ids, thr_name);
327 # if defined (ACE_HAS_DEFERRED_TIMER_COMMANDS)
329 // Enqueues a command object for execution just before waiting on the next
330 // timer event. This allows deferred execution of commands that cannot
331 // be performed in the timer event handler context, such as registering
332 // or cancelling timers on platforms where the timer queue mutex is not
333 // recursive.
335 template<class TQ, class TYPE> int
336 ACE_Thread_Timer_Queue_Adapter<TQ, TYPE>::enqueue_command (ACE_Command_Base *cmd,
337 COMMAND_ENQUEUE_POSITION pos)
339 // Serialize access to the command queue.
340 ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, guard, this->command_mutex_, -1);
342 if (pos == ACE_Thread_Timer_Queue_Adapter<TQ, TYPE>::TAIL)
343 return command_queue_.enqueue_tail (cmd);
344 else
345 return command_queue_.enqueue_head (cmd);
348 // Dispatches all command objects enqueued in the most recent event
349 // handler context.
351 template<class TQ, class TYPE> int
352 ACE_Thread_Timer_Queue_Adapter<TQ, TYPE>::dispatch_commands (void)
354 // Serialize access to the command queue.
355 ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, guard, this->command_mutex_, -1);
357 // loop through the enqueued commands
358 ACE_Command_Base *cmd = 0;
359 while (command_queue_.dequeue_head (cmd) == 0)
360 if (cmd)
362 cmd->execute ();
363 delete cmd;
366 return 0;
369 # endif /* ACE_HAS_DEFERRED_TIMER_COMMANDS */
371 ACE_END_VERSIONED_NAMESPACE_DECL
373 #endif /* ACE_TIMER_QUEUE_ADAPTERS_CPP */