Restore build on FreeBSD.
[getmangos.git] / dep / ACE_wrappers / ace / Timer_Queue_Adapters.cpp
blobf6519ae9efccde859497094c544e560c3d527d26
1 // $Id: Timer_Queue_Adapters.cpp 80826 2008-03-04 14:51:23Z wotte $
3 #ifndef ACE_TIMER_QUEUE_ADAPTERS_CPP
4 #define ACE_TIMER_QUEUE_ADAPTERS_CPP
6 #include "ace/Timer_Queue_Adapters.h"
8 #if defined (ACE_HAS_DEFERRED_TIMER_COMMANDS)
9 #include "ace/Functor.h"
10 #endif /* ACE_HAS_DEFERRED_TIMER_COMMANDS */
12 #if !defined (ACE_LACKS_PRAGMA_ONCE)
13 # pragma once
14 #endif /* ACE_LACKS_PRAGMA_ONCE */
16 # if !defined (__ACE_INLINE__)
17 # include "ace/Timer_Queue_Adapters.inl"
18 # endif /* __ACE_INLINE__ */
20 #include "ace/Signal.h"
21 #include "ace/OS_NS_unistd.h"
22 #include "ace/OS_NS_sys_time.h"
24 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
26 template <class TQ> TQ &
27 ACE_Async_Timer_Queue_Adapter<TQ>::timer_queue (void)
29 return this->timer_queue_;
32 template <class TQ> int
33 ACE_Async_Timer_Queue_Adapter<TQ>::cancel (long timer_id,
34 const void **act)
36 // Block designated signals.
37 ACE_Sig_Guard sg (&this->mask_);
38 ACE_UNUSED_ARG (sg);
40 return this->timer_queue_.cancel (timer_id, act);
43 template <class TQ> int
44 ACE_Async_Timer_Queue_Adapter<TQ>::expire (void)
46 // Block designated signals.
47 ACE_Sig_Guard sg (&this->mask_);
48 ACE_UNUSED_ARG (sg);
50 return this->timer_queue_.expire ();
53 template <class TQ> int
54 ACE_Async_Timer_Queue_Adapter<TQ>::schedule_ualarm (void)
56 ACE_Time_Value tv = this->timer_queue_.earliest_time ()
57 - this->timer_queue_.gettimeofday ();
59 // Beware of negative times and zero times (which cause problems for
60 // <ualarm>).
61 if (tv < ACE_Time_Value::zero)
62 tv = ACE_Time_Value (0, 1);
64 // @@ This code should be clever enough to avoid updating the
65 // <ualarm> if we haven't actually changed the earliest time.
66 // Schedule a new timer.
67 ACE_OS::ualarm (tv);
68 return 0;
71 template <class TQ> long
72 ACE_Async_Timer_Queue_Adapter<TQ>::schedule (ACE_Event_Handler *eh,
73 const void *act,
74 const ACE_Time_Value &future_time,
75 const ACE_Time_Value &interval)
77 ACE_UNUSED_ARG (act);
78 ACE_UNUSED_ARG (interval);
80 // Block designated signals.
81 ACE_Sig_Guard sg (&this->mask_);
82 ACE_UNUSED_ARG (sg);
84 // @@ We still need to implement interval timers...
85 long tid = this->timer_queue_.schedule (eh, act, future_time);
87 if (tid == -1)
88 ACE_ERROR_RETURN ((LM_ERROR,
89 ACE_TEXT ("%p\n"),
90 ACE_TEXT ("schedule_timer")),
91 -1);
93 if (this->schedule_ualarm () == -1)
94 return 0;
96 return tid;
99 template <class TQ>
100 ACE_Async_Timer_Queue_Adapter<TQ>::ACE_Async_Timer_Queue_Adapter (ACE_Sig_Set *mask)
101 // If <mask> == 0, block *all* signals when the SIGARLM handler is
102 // running, else just block those in the mask.
103 : mask_ (mask)
105 // The following code is necessary to selectively "block" certain
106 // signals when SIGALRM is running. Also, we always restart system
107 // calls that are interrupted by the signals.
109 ACE_Sig_Action sa ((ACE_SignalHandler) 0,
110 this->mask_,
111 SA_RESTART);
113 if (this->sig_handler_.register_handler (SIGALRM, this, &sa) == -1)
114 ACE_ERROR ((LM_ERROR,
115 ACE_TEXT ("%p\n"),
116 ACE_TEXT ("register_handler")));
119 // This is the signal handler function for the asynchronous timer
120 // list. It gets invoked asynchronously when the SIGALRM signal
121 // occurs.
123 template <class TQ> int
124 ACE_Async_Timer_Queue_Adapter<TQ>::handle_signal (int signum,
125 siginfo_t *,
126 ucontext_t *)
128 switch (signum)
130 case SIGALRM:
132 // Expire the pending timers.
134 // @@ We need to figure out how to implement interval
135 // timers...
136 this->timer_queue_.expire ();
138 // Only schedule a new timer if there is one in the list.
140 // @@ This code should also become smarter to avoid
141 // unnecessary calls to ualarm().
142 if (this->timer_queue_.is_empty () == 0)
143 return this->schedule_ualarm ();
144 else
145 return 0;
146 /* NOTREACHED */
148 default:
149 ACE_ERROR_RETURN ((LM_ERROR,
150 "unexpected signal %S\n",
151 signum),
152 -1);
153 /* NOTREACHED */
157 template<class TQ>
158 ACE_Thread_Timer_Queue_Adapter<TQ>::ACE_Thread_Timer_Queue_Adapter (ACE_Thread_Manager *tm,
159 TQ* timer_queue)
160 : ACE_Task_Base (tm),
161 timer_queue_(timer_queue),
162 delete_timer_queue_(false),
163 condition_ (mutex_),
164 active_ (true), // Assume that we start in active mode.
165 thr_id_ (ACE_OS::NULL_thread)
167 if (timer_queue_ == 0)
169 ACE_NEW (this->timer_queue_,
170 TQ);
171 this->delete_timer_queue_ = true;
175 template<class TQ>
176 ACE_Thread_Timer_Queue_Adapter<TQ>::~ACE_Thread_Timer_Queue_Adapter (void)
178 if (this->delete_timer_queue_)
180 delete this->timer_queue_;
181 this->timer_queue_ = 0;
182 this->delete_timer_queue_ = false;
186 template<class TQ> ACE_SYNCH_RECURSIVE_MUTEX &
187 ACE_Thread_Timer_Queue_Adapter<TQ>::mutex (void)
189 return this->mutex_;
192 template<class TQ> long
193 ACE_Thread_Timer_Queue_Adapter<TQ>::schedule
194 (ACE_Event_Handler* handler,
195 const void *act,
196 const ACE_Time_Value &future_time,
197 const ACE_Time_Value &interval)
199 ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX, guard, this->mutex_, -1);
201 long result = this->timer_queue_->schedule (handler, act, future_time, interval);
202 this->condition_.signal ();
203 return result;
206 template<class TQ> int
207 ACE_Thread_Timer_Queue_Adapter<TQ>::cancel (long timer_id,
208 const void **act)
210 ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX, guard, this->mutex_, -1);
212 int result = this->timer_queue_->cancel (timer_id, act);
213 condition_.signal ();
214 return result;
217 template<class TQ> void
218 ACE_Thread_Timer_Queue_Adapter<TQ>::deactivate (void)
220 ACE_GUARD (ACE_SYNCH_RECURSIVE_MUTEX, guard, this->mutex_);
222 this->active_ = false;
223 this->condition_.signal ();
226 template<class TQ> int
227 ACE_Thread_Timer_Queue_Adapter<TQ>::svc (void)
229 ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX, guard, this->mutex_, -1);
231 this->thr_id_ = ACE_Thread::self ();
233 // Thread cancellation point, if ACE supports it.
235 // Note: This call generates a warning under Solaris because the header
236 // file /usr/include/pthread.h redefines the routine argument. This
237 // is a bug in the Solaris header files and has nothing to do with
238 // ACE.
239 # if !defined (ACE_LACKS_PTHREAD_CANCEL)
240 ACE_PTHREAD_CLEANUP_PUSH (&this->condition_.mutex ().get_nesting_mutex ());
241 # endif /* ACE_LACKS_PTHREAD_CANCEL */
243 while (this->active_)
245 # if defined (ACE_HAS_DEFERRED_TIMER_COMMANDS)
246 // Temporarily suspend ownership of the timer queue mutex in
247 // order to dispatch deferred execution commands. These
248 // commands are to be treated as executing in a context
249 // "external" to the timer queue adapter, and thus must compete
250 // separately for this lock.
251 mutex_.release ();
252 this->dispatch_commands ();
254 // Re-acquire ownership of the timer queue mutex in order to
255 // restore the "internal" timer queue adapter context
256 mutex_.acquire ();
257 # endif /* ACE_HAS_DEFERRED_TIMER_COMMANDS */
259 // If the queue is empty, sleep until there is a change on it.
260 if (this->timer_queue_->is_empty ())
261 this->condition_.wait ();
262 else
264 // Compute the remaining time, being careful not to sleep
265 // for "negative" amounts of time.
266 ACE_Time_Value const tv_curr = this->timer_queue_->gettimeofday ();
267 ACE_Time_Value const tv_earl = this->timer_queue_->earliest_time ();
269 if (tv_earl > tv_curr)
271 // The earliest time on the Timer_Queue is in future, so
272 // use ACE_OS::gettimeofday() to convert the tv to the
273 // absolute time.
274 ACE_Time_Value const tv = ACE_OS::gettimeofday () + (tv_earl - tv_curr);
275 // ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("waiting until %u.%3.3u secs\n"),
276 // tv.sec(), tv.msec()));
277 this->condition_.wait (&tv);
281 // Expire timers anyway, at worst this is a no-op.
282 this->timer_queue_->expire ();
285 // Thread cancellation point, if ACE supports it.
286 # if !defined (ACE_LACKS_PTHREAD_CANCEL)
287 ACE_PTHREAD_CLEANUP_POP (0);
288 # endif /* ACE_LACKS_PTHREAD_CANCEL */
290 return 0;
293 template<class TQ> int
294 ACE_Thread_Timer_Queue_Adapter<TQ>::activate (long flags,
295 int ,
296 int ,
297 long priority,
298 int grp_id,
299 ACE_Task_Base *task,
300 ACE_hthread_t [],
301 void *stack[],
302 size_t stack_size[],
303 ACE_thread_t thread_ids[],
304 const char* thr_name[])
306 // Make sure to set this flag in case we were deactivated earlier.
307 this->active_ = true;
309 // Make sure that we only allow a single thread to be spawned for
310 // our adapter. Otherwise, too many weird things can happen.
311 return ACE_Task_Base::activate (flags, 1, 0, priority, grp_id, task, 0,
312 stack, stack_size, thread_ids, thr_name);
315 # if defined (ACE_HAS_DEFERRED_TIMER_COMMANDS)
317 // Enqueues a command object for execution just before waiting on the next
318 // timer event. This allows deferred execution of commands that cannot
319 // be performed in the timer event handler context, such as registering
320 // or cancelling timers on platforms where the timer queue mutex is not
321 // recursive.
323 template<class TQ> int
324 ACE_Thread_Timer_Queue_Adapter<TQ>::enqueue_command (ACE_Command_Base *cmd,
325 COMMAND_ENQUEUE_POSITION pos)
327 // Serialize access to the command queue.
328 ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, guard, this->command_mutex_, -1);
330 if (pos == ACE_Thread_Timer_Queue_Adapter<TQ>::TAIL)
331 return command_queue_.enqueue_tail (cmd);
332 else
333 return command_queue_.enqueue_head (cmd);
336 // Dispatches all command objects enqueued in the most recent event
337 // handler context.
339 template<class TQ> int
340 ACE_Thread_Timer_Queue_Adapter<TQ>::dispatch_commands (void)
342 // Serialize access to the command queue.
343 ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, guard, this->command_mutex_, -1);
345 // loop through the enqueued commands
346 ACE_Command_Base *cmd = 0;
347 while (command_queue_.dequeue_head (cmd) == 0)
348 if (cmd)
350 cmd->execute ();
351 delete cmd;
354 return 0;
357 # endif /* ACE_HAS_DEFERRED_TIMER_COMMANDS */
359 ACE_END_VERSIONED_NAMESPACE_DECL
361 #endif /* ACE_TIMER_QUEUE_ADAPTERS_CPP */