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)
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 ()
28 return this->timer_queue_
;
31 template <class TQ
, class TYPE
> int
32 ACE_Async_Timer_Queue_Adapter
<TQ
, TYPE
>::cancel (long timer_id
,
35 // Block designated signals.
36 ACE_Sig_Guard
sg (&this->mask_
);
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 ()
45 // Block designated signals.
46 ACE_Sig_Guard
sg (&this->mask_
);
49 return this->timer_queue_
.expire ();
52 template <class TQ
, class TYPE
> int
53 ACE_Async_Timer_Queue_Adapter
<TQ
, TYPE
>::schedule_ualarm ()
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
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.
70 template <class TQ
, class TYPE
> long
71 ACE_Async_Timer_Queue_Adapter
<TQ
, TYPE
>::schedule (TYPE eh
,
73 const ACE_Time_Value
&future_time
,
74 const ACE_Time_Value
&interval
)
77 ACE_UNUSED_ARG (interval
);
79 // Block designated signals.
80 ACE_Sig_Guard
sg (&this->mask_
);
83 // @@ We still need to implement interval timers...
84 long tid
= this->timer_queue_
.schedule (eh
, act
, future_time
);
87 ACELIB_ERROR_RETURN ((LM_ERROR
,
89 ACE_TEXT ("schedule_timer")),
92 if (this->schedule_ualarm () == -1)
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.
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,
112 if (this->sig_handler_
.register_handler (SIGALRM
, this, &sa
) == -1)
113 ACELIB_ERROR ((LM_ERROR
,
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
122 template <class TQ
, class TYPE
> int
123 ACE_Async_Timer_Queue_Adapter
<TQ
, TYPE
>::handle_signal (int signum
, siginfo_t
*, ucontext_t
*)
129 // Expire the pending timers.
131 // @@ We need to figure out how to implement interval
133 this->timer_queue_
.expire ();
135 // Only schedule a new timer if there is one in the list.
137 // @@ This code should also become smarter to avoid
138 // unnecessary calls to ualarm().
139 if (this->timer_queue_
.is_empty () == 0)
140 return this->schedule_ualarm ();
146 ACELIB_ERROR_RETURN ((LM_ERROR
,
147 "unexpected signal %S\n",
154 template<class TQ
, class TYPE
>
155 ACE_Thread_Timer_Queue_Adapter
<TQ
, TYPE
>::ACE_Thread_Timer_Queue_Adapter (ACE_Thread_Manager
*tm
,
157 : ACE_Task_Base (tm
),
158 timer_queue_(timer_queue
),
159 delete_timer_queue_(false),
160 condition_ (mutex_
, cond_attr_
),
161 active_ (true), // Assume that we start in active mode.
162 thr_id_ (ACE_OS::NULL_thread
)
164 if (timer_queue_
== 0)
166 ACE_NEW (this->timer_queue_
,
168 this->delete_timer_queue_
= true;
172 template<class TQ
, class TYPE
>
173 ACE_Thread_Timer_Queue_Adapter
<TQ
, TYPE
>::~ACE_Thread_Timer_Queue_Adapter ()
175 if (this->delete_timer_queue_
)
177 delete this->timer_queue_
;
178 this->timer_queue_
= 0;
179 this->delete_timer_queue_
= false;
181 else if (this->timer_queue_
)
183 this->timer_queue_
->close ();
184 this->timer_queue_
= 0;
188 template<class TQ
, class TYPE
> ACE_SYNCH_RECURSIVE_MUTEX
&
189 ACE_Thread_Timer_Queue_Adapter
<TQ
, TYPE
>::mutex ()
194 template<class TQ
, class TYPE
> long
195 ACE_Thread_Timer_Queue_Adapter
<TQ
, TYPE
>::schedule
198 const ACE_Time_Value
&future_time
,
199 const ACE_Time_Value
&interval
)
201 ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX
, guard
, this->mutex_
, -1);
203 long result
= this->timer_queue_
->schedule (handler
, act
, future_time
, interval
);
204 this->condition_
.signal ();
208 template<class TQ
, class TYPE
> int
209 ACE_Thread_Timer_Queue_Adapter
<TQ
, TYPE
>::cancel (long timer_id
,
212 ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX
, guard
, this->mutex_
, -1);
214 int result
= this->timer_queue_
->cancel (timer_id
, act
);
215 condition_
.signal ();
219 template<class TQ
, class TYPE
> void
220 ACE_Thread_Timer_Queue_Adapter
<TQ
, TYPE
>::deactivate ()
222 ACE_GUARD (ACE_SYNCH_RECURSIVE_MUTEX
, guard
, this->mutex_
);
224 this->active_
= false;
225 this->condition_
.signal ();
228 template<class TQ
, class TYPE
> int
229 ACE_Thread_Timer_Queue_Adapter
<TQ
, TYPE
>::svc ()
231 ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX
, guard
, this->mutex_
, -1);
233 this->thr_id_
= ACE_Thread::self ();
235 // Thread cancellation point, if ACE supports it.
236 # if !defined (ACE_LACKS_PTHREAD_CANCEL)
237 ACE_PTHREAD_CLEANUP_PUSH (&this->condition_
.mutex ().get_nesting_mutex ());
238 # endif /* ACE_LACKS_PTHREAD_CANCEL */
240 while (this->active_
)
242 # if defined (ACE_HAS_DEFERRED_TIMER_COMMANDS)
243 // Temporarily suspend ownership of the timer queue mutex in
244 // order to dispatch deferred execution commands. These
245 // commands are to be treated as executing in a context
246 // "external" to the timer queue adapter, and thus must compete
247 // separately for this lock.
249 this->dispatch_commands ();
251 // Re-acquire ownership of the timer queue mutex in order to
252 // restore the "internal" timer queue adapter context
254 # endif /* ACE_HAS_DEFERRED_TIMER_COMMANDS */
256 // If the queue is empty, sleep until there is a change on it.
257 if (this->timer_queue_
->is_empty ())
258 this->condition_
.wait ();
261 // Compute the remaining time, being careful not to sleep
262 // for "negative" amounts of time.
263 ACE_Time_Value
const tv_curr
=
264 this->timer_queue_
->gettimeofday ();
265 ACE_Time_Value
const tv_earl
=
266 this->timer_queue_
->earliest_time ();
268 if (tv_earl
> tv_curr
)
270 // The earliest time on the Timer_Queue lies in future;
271 // convert the tv to an absolute time.
272 ACE_Time_Value
const tv
= this->timer_queue_
->gettimeofday () + (tv_earl
- tv_curr
);
273 // ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("waiting until %u.%3.3u secs\n"),
274 // tv.sec(), tv.msec()));
275 this->condition_
.wait (&tv
);
279 // Expire timers anyway, at worst this is a no-op. Release the lock
280 // while dispatching; the timer queue has its own lock to protect
283 ACE_Reverse_Lock
<ACE_SYNCH_RECURSIVE_MUTEX
> rel (this->mutex_
);
284 ACE_GUARD_RETURN (ACE_Reverse_Lock
<ACE_SYNCH_RECURSIVE_MUTEX
>,
286 this->timer_queue_
->expire ();
290 // Thread cancellation point, if ACE supports it.
291 # if !defined (ACE_LACKS_PTHREAD_CANCEL)
292 ACE_PTHREAD_CLEANUP_POP (0);
293 # endif /* ACE_LACKS_PTHREAD_CANCEL */
298 template<class TQ
, class TYPE
> int
299 ACE_Thread_Timer_Queue_Adapter
<TQ
, TYPE
>::activate (long flags
,
308 ACE_thread_t thread_ids
[],
309 const char* thr_name
[])
311 // Make sure to set this flag in case we were deactivated earlier.
312 this->active_
= true;
314 // Make sure that we only allow a single thread to be spawned for
315 // our adapter. Otherwise, too many weird things can happen.
316 return ACE_Task_Base::activate (flags
, 1, 0, priority
, grp_id
, task
, 0,
317 stack
, stack_size
, thread_ids
, thr_name
);
320 # if defined (ACE_HAS_DEFERRED_TIMER_COMMANDS)
322 // Enqueues a command object for execution just before waiting on the next
323 // timer event. This allows deferred execution of commands that cannot
324 // be performed in the timer event handler context, such as registering
325 // or cancelling timers on platforms where the timer queue mutex is not
328 template<class TQ
, class TYPE
> int
329 ACE_Thread_Timer_Queue_Adapter
<TQ
, TYPE
>::enqueue_command (ACE_Command_Base
*cmd
,
330 COMMAND_ENQUEUE_POSITION pos
)
332 // Serialize access to the command queue.
333 ACE_GUARD_RETURN (ACE_SYNCH_MUTEX
, guard
, this->command_mutex_
, -1);
335 if (pos
== ACE_Thread_Timer_Queue_Adapter
<TQ
, TYPE
>::TAIL
)
336 return command_queue_
.enqueue_tail (cmd
);
338 return command_queue_
.enqueue_head (cmd
);
341 // Dispatches all command objects enqueued in the most recent event
344 template<class TQ
, class TYPE
> int
345 ACE_Thread_Timer_Queue_Adapter
<TQ
, TYPE
>::dispatch_commands ()
347 // Serialize access to the command queue.
348 ACE_GUARD_RETURN (ACE_SYNCH_MUTEX
, guard
, this->command_mutex_
, -1);
350 // loop through the enqueued commands
351 ACE_Command_Base
*cmd
= 0;
352 while (command_queue_
.dequeue_head (cmd
) == 0)
362 # endif /* ACE_HAS_DEFERRED_TIMER_COMMANDS */
364 ACE_END_VERSIONED_NAMESPACE_DECL
366 #endif /* ACE_TIMER_QUEUE_ADAPTERS_CPP */