Use =default for skeleton copy constructor
[ACE_TAO.git] / ACE / ace / Timer_Queue_T.cpp
blob52ed9ad9c8086cc29dbac9f6a6c805bbc2198bbd
1 #ifndef ACE_TIMER_QUEUE_T_CPP
2 #define ACE_TIMER_QUEUE_T_CPP
4 #include "ace/config-all.h"
6 #if !defined (ACE_LACKS_PRAGMA_ONCE)
7 # pragma once
8 #endif /* ACE_LACKS_PRAGMA_ONCE */
10 #include "ace/Timer_Queue_T.h"
11 #include "ace/Guard_T.h"
12 #include "ace/Reverse_Lock_T.h"
13 #include "ace/Log_Category.h"
14 #include "ace/Null_Mutex.h"
15 #include "ace/OS_NS_sys_time.h"
16 #include "ace/Functor.h"
18 #if !defined (__ACE_INLINE__)
19 #include "ace/Timer_Queue_T.inl"
20 #endif /* __ACE_INLINE__ */
22 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
24 // This fudge factor can be overriden for timers that need it
25 // by defining the ACE_TIMER_SKEW symbol in the appropriate config
26 // header.
27 #if !defined (ACE_TIMER_SKEW)
28 # define ACE_TIMER_SKEW 0
29 #endif /* ACE_TIMER_SKEW */
31 template <class TYPE, class FUNCTOR> ACE_INLINE
32 ACE_Timer_Queue_Upcall_Base<TYPE, FUNCTOR>::ACE_Timer_Queue_Upcall_Base (FUNCTOR * upcall_functor)
33 : ACE_Abstract_Timer_Queue<TYPE>()
34 , ACE_Copy_Disabled()
35 , upcall_functor_(upcall_functor)
36 , delete_upcall_functor_ (upcall_functor == 0)
38 ACE_TRACE ("ACE_Timer_Queue_Upcall_Base::ACE_Timer_Queue_Upcall_Base");
40 if (upcall_functor != 0)
42 return;
45 ACE_NEW (upcall_functor_, FUNCTOR);
48 template <class TYPE, class FUNCTOR> ACE_INLINE
49 ACE_Timer_Queue_Upcall_Base<TYPE, FUNCTOR>::~ACE_Timer_Queue_Upcall_Base ()
51 ACE_TRACE ("ACE_Timer_Queue_Upcall_Base::~ACE_Timer_Queue_Upcall_Base");
52 if (this->delete_upcall_functor_)
54 delete this->upcall_functor_;
58 template <class TYPE, class FUNCTOR, class ACE_LOCK, typename TIME_POLICY> ACE_Time_Value
59 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK, TIME_POLICY>::gettimeofday()
61 return this->gettimeofday_static();
64 template <class TYPE, class FUNCTOR, class ACE_LOCK, typename TIME_POLICY> void
65 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK, TIME_POLICY>::gettimeofday (ACE_Time_Value (*gettimeofday)())
67 this->time_policy_.set_gettimeofday (gettimeofday);
70 template <class TYPE, class FUNCTOR, class ACE_LOCK, typename TIME_POLICY> ACE_Time_Value *
71 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK, TIME_POLICY>::calculate_timeout (ACE_Time_Value *max_wait_time)
73 ACE_TRACE ("ACE_Timer_Queue_T::calculate_timeout");
74 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, max_wait_time));
76 if (this->is_empty ())
77 // Nothing on the Timer_Queue, so use whatever the caller gave us.
78 return max_wait_time;
79 else
81 ACE_Time_Value const cur_time = this->gettimeofday_static ();
83 if (this->earliest_time () > cur_time)
85 // The earliest item on the Timer_Queue is still in the
86 // future. Therefore, use the smaller of (1) caller's wait
87 // time or (2) the delta time between now and the earliest
88 // time on the Timer_Queue.
90 this->timeout_ = this->earliest_time () - cur_time;
91 if (max_wait_time == 0 || *max_wait_time > timeout_)
92 return &this->timeout_;
93 else
94 return max_wait_time;
96 else
98 // The earliest item on the Timer_Queue is now in the past.
99 // Therefore, we've got to "poll" the Reactor, i.e., it must
100 // just check the descriptors and then dispatch timers, etc.
101 this->timeout_ = ACE_Time_Value::zero;
102 return &this->timeout_;
107 template <class TYPE, class FUNCTOR, class ACE_LOCK, typename TIME_POLICY> ACE_Time_Value *
108 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK, TIME_POLICY>::calculate_timeout (ACE_Time_Value *max_wait_time,
109 ACE_Time_Value *the_timeout)
111 ACE_TRACE ("ACE_Timer_Queue_T::calculate_timeout");
113 if (the_timeout == 0)
114 return 0;
116 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, max_wait_time));
118 if (this->is_empty ())
120 // Nothing on the Timer_Queue, so use whatever the caller gave us.
121 if (max_wait_time)
122 *the_timeout = *max_wait_time;
123 else
124 return 0;
126 else
128 ACE_Time_Value cur_time = this->gettimeofday_static ();
130 if (this->earliest_time () > cur_time)
132 // The earliest item on the Timer_Queue is still in the
133 // future. Therefore, use the smaller of (1) caller's wait
134 // time or (2) the delta time between now and the earliest
135 // time on the Timer_Queue.
137 *the_timeout = this->earliest_time () - cur_time;
138 if (!(max_wait_time == 0 || *max_wait_time > *the_timeout))
139 *the_timeout = *max_wait_time;
141 else
143 // The earliest item on the Timer_Queue is now in the past.
144 // Therefore, we've got to "poll" the Reactor, i.e., it must
145 // just check the descriptors and then dispatch timers, etc.
146 *the_timeout = ACE_Time_Value::zero;
149 return the_timeout;
152 template <class TYPE, class FUNCTOR, class ACE_LOCK, typename TIME_POLICY> ACE_Time_Value
153 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK, TIME_POLICY>::current_time()
155 ACE_Time_Value tv = this->gettimeofday_static ();
156 tv += this->timer_skew();
157 return tv;
160 template <class TYPE, class FUNCTOR, class ACE_LOCK, typename TIME_POLICY> void
161 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK, TIME_POLICY>::dump () const
163 #if defined (ACE_HAS_DUMP)
164 ACE_TRACE ("ACE_Timer_Queue_T::dump");
165 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
166 this->timeout_.dump ();
167 this->timer_skew_.dump ();
168 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
169 #endif /* ACE_HAS_DUMP */
172 template <class TYPE, class FUNCTOR, class ACE_LOCK, typename TIME_POLICY>
173 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK, TIME_POLICY>::ACE_Timer_Queue_T (FUNCTOR *upcall_functor,
174 ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist,
175 TIME_POLICY const & time_policy)
176 : ACE_Timer_Queue_Upcall_Base<TYPE,FUNCTOR>(upcall_functor),
177 time_policy_ (time_policy),
178 delete_free_list_ (freelist == 0),
179 timer_skew_ (0, ACE_TIMER_SKEW)
181 ACE_TRACE ("ACE_Timer_Queue_T::ACE_Timer_Queue_T");
183 if (!freelist)
184 ACE_NEW (free_list_,
185 (ACE_Locked_Free_List<ACE_Timer_Node_T<TYPE>,ACE_Null_Mutex>));
186 else
187 free_list_ = freelist;
190 template <class TYPE, class FUNCTOR, class ACE_LOCK, typename TIME_POLICY>
191 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK, TIME_POLICY>::~ACE_Timer_Queue_T ()
193 ACE_TRACE ("ACE_Timer_Queue_T::~ACE_Timer_Queue_T");
195 // Cleanup the free_list on the way out
196 if (this->delete_free_list_)
197 delete this->free_list_;
200 template <class TYPE, class FUNCTOR, class ACE_LOCK, typename TIME_POLICY> ACE_Timer_Node_T<TYPE> *
201 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK, TIME_POLICY>::alloc_node ()
203 return this->free_list_->remove ();
206 template <class TYPE, class FUNCTOR, class ACE_LOCK, typename TIME_POLICY> void
207 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK, TIME_POLICY>::free_node (ACE_Timer_Node_T<TYPE> *node)
209 this->free_list_->add (node);
212 template <class TYPE, class FUNCTOR, class ACE_LOCK, typename TIME_POLICY> ACE_LOCK &
213 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK, TIME_POLICY>::mutex ()
215 return this->mutex_;
218 template <class TYPE, class FUNCTOR, class ACE_LOCK, typename TIME_POLICY> long
219 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK, TIME_POLICY>::schedule (const TYPE &type,
220 const void *act,
221 const ACE_Time_Value &future_time,
222 const ACE_Time_Value &interval)
224 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
226 // Schedule the timer.
227 long const result =
228 this->schedule_i (type,
229 act,
230 future_time,
231 interval);
233 // Return on failure.
234 if (result == -1)
235 return result;
237 // Inform upcall functor of successful registration.
238 this->upcall_functor ().registration (*this,
239 type,
240 act);
242 // Return result;
243 return result;
246 template <class TYPE, class FUNCTOR, class ACE_LOCK, typename TIME_POLICY> int
247 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK, TIME_POLICY>::expire ()
249 // We can't check here is the timer queue is empty, in some
250 // implementations (like the timer heap) calling is_empty()
251 // would at that moment access member variables without having
252 // locked ourself for thread safety
253 return this->expire (this->gettimeofday_static () + timer_skew_);
256 // Run the <handle_timeout> method for all Timers whose values are <=
257 // <cur_time>.
258 template <class TYPE, class FUNCTOR, class ACE_LOCK, typename TIME_POLICY> int
259 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK, TIME_POLICY>::expire (const ACE_Time_Value &cur_time)
261 ACE_TRACE ("ACE_Timer_Queue_T::expire");
262 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
264 // Keep looping while there are timers remaining and the earliest
265 // timer is <= the <cur_time> passed in to the method.
267 if (this->is_empty ())
268 return 0;
270 int number_of_timers_expired = 0;
271 int result = 0;
273 ACE_Timer_Node_Dispatch_Info_T<TYPE> info;
275 while ((result = this->dispatch_info_i (cur_time, info)) != 0)
277 ACE_MT (ACE_Reverse_Lock<ACE_LOCK> rev_lk(this->mutex_));
278 ACE_MT (ACE_GUARD_RETURN (ACE_Reverse_Lock<ACE_LOCK>, rmon, rev_lk, -1));
280 const void *upcall_act = 0;
282 this->preinvoke (info, cur_time, upcall_act);
284 this->upcall (info, cur_time);
286 this->postinvoke (info, cur_time, upcall_act);
288 ++number_of_timers_expired;
291 ACE_UNUSED_ARG (result);
292 return number_of_timers_expired;
295 template <class TYPE, class FUNCTOR, class ACE_LOCK, typename TIME_POLICY> void
296 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK, TIME_POLICY>::recompute_next_abs_interval_time
297 (ACE_Timer_Node_T<TYPE> *expired,
298 const ACE_Time_Value &cur_time)
300 if ( expired->get_timer_value () <= cur_time )
303 * Somehow the current time is past when this time was
304 * supposed to expire (e.g., timer took too long,
305 * somebody changed system time, etc.). There used to
306 * be a simple loop here that skipped ahead one timer
307 * interval at a time, but that was horribly inefficient
308 * (an O(n) algorithm) when the timer duration was small
309 * relative to the amount of time skipped.
311 * So, we replace the loop with a simple computation,
312 * which also happens to be O(1). All times get
313 * normalized in the computation to microseconds.
315 * For reference, the loop looked like this:
317 * do
318 * expired->set_timer_value (expired->get_timer_value () +
319 * expired->get_interval ());
320 * while (expired->get_timer_value () <= cur_time);
324 // Compute the duration of the timer's interval
325 ACE_UINT64 interval_usec;
326 expired->get_interval ().to_usec (interval_usec);
328 // Compute the span between the current time and when
329 // the timer would have expired in the past (and
330 // normalize to microseconds).
331 ACE_Time_Value old_diff = cur_time - expired->get_timer_value ();
332 ACE_UINT64 old_diff_usec;
333 old_diff.to_usec (old_diff_usec);
335 // Compute the delta time in the future when the timer
336 // should fire as if it had advanced incrementally. The
337 // modulo arithmetic accomodates the likely case that
338 // the current time doesn't fall precisely on a timer
339 // firing interval.
340 ACE_UINT64 new_timer_usec =
341 interval_usec - (old_diff_usec % interval_usec);
343 // Compute the absolute time in the future when this
344 // interval timer should expire.
345 ACE_Time_Value new_timer_value
346 (cur_time.sec ()
347 + static_cast<time_t>(new_timer_usec / ACE_ONE_SECOND_IN_USECS),
348 cur_time.usec ()
349 + static_cast<suseconds_t>(new_timer_usec % ACE_ONE_SECOND_IN_USECS));
351 expired->set_timer_value (new_timer_value);
355 template <class TYPE, class FUNCTOR, class ACE_LOCK, typename TIME_POLICY> int
356 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK, TIME_POLICY>::expire_single (
357 ACE_Command_Base & pre_dispatch_command)
359 ACE_TRACE ("ACE_Timer_Queue_T::expire_single");
360 ACE_Timer_Node_Dispatch_Info_T<TYPE> info;
361 ACE_Time_Value cur_time;
363 // Create a scope for the lock ...
364 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
366 if (this->is_empty ())
367 return 0;
369 // Get the current time
370 cur_time = this->gettimeofday_static () + this->timer_skew ();
372 // Look for a node in the timer queue whose timer <= the present
373 // time.
374 if (!this->dispatch_info_i (cur_time, info))
376 return 0;
379 // We do not need the lock anymore, all these operations take place
380 // with local variables.
381 const void *upcall_act = 0;
383 // Preinvoke (handles refcount if needed, etc.)
384 this->preinvoke (info, cur_time, upcall_act);
386 // Release the token before expiration upcall.
387 pre_dispatch_command.execute();
389 // call the functor
390 this->upcall (info, cur_time);
392 // Postinvoke (undo refcount if needed, etc.)
393 this->postinvoke (info, cur_time, upcall_act);
395 // We have dispatched a timer
396 return 1;
399 template <class TYPE, class FUNCTOR, class ACE_LOCK, typename TIME_POLICY> int
400 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK, TIME_POLICY>::dispatch_info_i (const ACE_Time_Value &cur_time,
401 ACE_Timer_Node_Dispatch_Info_T<TYPE> &info)
403 ACE_TRACE ("ACE_Timer_Queue_T::dispatch_info_i");
405 if (this->is_empty ())
406 return 0;
408 if (this->earliest_time () <= cur_time)
410 ACE_Timer_Node_T<TYPE> *expired = this->remove_first ();
412 // Get the dispatch info
413 expired->get_dispatch_info (info);
415 // Check if this is an interval timer.
416 if (expired->get_interval () > ACE_Time_Value::zero)
418 // Make sure that we skip past values that have already
419 // "expired".
420 this->recompute_next_abs_interval_time (expired, cur_time);
422 // Since this is an interval timer, we need to reschedule
423 // it.
424 this->reschedule (expired);
426 else
428 // Call the factory method to free up the node.
429 this->free_node (expired);
432 return 1;
435 return 0;
438 template <class TYPE, class FUNCTOR, class ACE_LOCK, typename TIME_POLICY> void
439 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK, TIME_POLICY>::return_node (ACE_Timer_Node_T<TYPE> *node)
441 ACE_MT (ACE_GUARD (ACE_LOCK, ace_mon, this->mutex_));
442 this->free_node (node);
445 ACE_END_VERSIONED_NAMESPACE_DECL
447 #endif /* ACE_TIMER_QUEUE_T_CPP */