Merge pull request #2301 from sonndinh/remove-dup-reactor-functions
[ACE_TAO.git] / ACE / ace / Timer_Hash_T.cpp
blob15e29a7ac932b5209f9ff1e54ed70dd9dbd89380
1 #ifndef ACE_TIMER_HASH_T_CPP
2 #define ACE_TIMER_HASH_T_CPP
4 #include "ace/Timer_Hash_T.h"
6 #if !defined (ACE_LACKS_PRAGMA_ONCE)
7 # pragma once
8 #endif /* ACE_LACKS_PRAGMA_ONCE */
10 #include "ace/OS_NS_sys_time.h"
11 #include "ace/Guard_T.h"
12 #include "ace/Log_Category.h"
14 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
16 template <class TYPE>
17 class Hash_Token
19 public:
20 // This constructor is required by ACE_Locked_Free_List::alloc.
21 Hash_Token () :
22 act_ (0),
23 pos_ (0),
24 orig_id_ (0),
25 next_ (0)
29 Hash_Token<TYPE> *get_next ()
31 return this->next_;
34 void set_next (Hash_Token<TYPE> *next)
36 this->next_ = next;
39 void set (const void *act,
40 size_t pos,
41 long orig_id,
42 const TYPE &type)
44 this->act_ = act;
45 this->pos_ = pos;
46 this->orig_id_ = orig_id;
47 this->type_ = type;
48 this->next_ = 0;
51 const void *act_;
52 size_t pos_;
53 long orig_id_;
54 TYPE type_;
55 /// Pointer to next token.
56 Hash_Token<TYPE> *next_;
59 // Default constructor
61 template <class TYPE, class FUNCTOR, class ACE_LOCK>
62 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Hash_Upcall ()
63 : timer_hash_ (0)
65 // Nothing
68 // Constructor that specifies a Timer_Hash to call up to
70 template <class TYPE, class FUNCTOR, class ACE_LOCK>
71 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Hash_Upcall (
72 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> *timer_hash)
73 : timer_hash_ (timer_hash)
75 // Nothing
78 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
79 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::registration (
80 TIMER_QUEUE &,
81 ACE_Event_Handler *,
82 const void *)
84 // Registration will be handled by the upcall functor of the timer
85 // hash.
86 return 0;
89 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
90 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::preinvoke (TIMER_QUEUE &,
91 ACE_Event_Handler *,
92 const void *,
93 int,
94 const ACE_Time_Value &,
95 const void *&)
97 // This method should never be invoked since we don't invoke
98 // expire() on the buckets.
99 ACE_ASSERT (0);
100 return 0;
103 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
104 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::postinvoke (
105 TIMER_QUEUE &,
106 ACE_Event_Handler *,
107 const void *,
108 int,
109 const ACE_Time_Value &,
110 const void *)
112 // This method should never be invoked since we don't invoke
113 // expire() on the buckets.
114 ACE_ASSERT (0);
115 return 0;
118 // Calls up to timer_hash's upcall functor
119 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
120 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::timeout (
121 TIMER_QUEUE &,
122 ACE_Event_Handler *,
123 const void *,
124 int,
125 const ACE_Time_Value &)
127 // This method should never be invoked since we don't invoke
128 // expire() on the buckets.
129 ACE_ASSERT (0);
130 return 0;
133 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
134 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::cancel_type (
135 TIMER_QUEUE &,
136 ACE_Event_Handler *,
137 int,
138 int &)
140 // Cancellation will be handled by the upcall functor of the timer
141 // hash.
142 return 0;
145 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
146 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::cancel_timer (
147 TIMER_QUEUE &,
148 ACE_Event_Handler *,
149 int,
150 int)
152 // Cancellation will be handled by the upcall functor of the timer
153 // hash.
154 return 0;
157 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
158 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::deletion (
159 TIMER_QUEUE &,
160 ACE_Event_Handler *event_handler,
161 const void *arg)
163 // Call up to the upcall functor of the timer hash since the timer
164 // hash does not invoke deletion() on its upcall functor directly.
165 Hash_Token<TYPE> *h =
166 reinterpret_cast<Hash_Token<TYPE> *> (const_cast<void *> (arg));
168 int result =
169 this->timer_hash_->upcall_functor ().
170 deletion (*this->timer_hash_,
171 event_handler,
172 h->act_);
174 return result;
177 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY>
178 ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::ACE_Timer_Hash_Iterator_T (Hash & hash)
179 : timer_hash_ (hash)
181 this->first ();
182 // Nothing
185 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY>
186 ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::~ACE_Timer_Hash_Iterator_T ()
188 // Nothing
191 // Positions the iterator at the first node in the timing hash table
193 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY> void
194 ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::first ()
196 for (this->position_ = 0;
197 this->position_ < this->timer_hash_.table_size_;
198 ++this->position_)
200 // Check for an empty entry
201 if (!this->timer_hash_.table_[this->position_]->is_empty ())
203 this->iter_ = &this->timer_hash_.table_[this->position_]->iter ();
204 this->iter_->first ();
205 return;
209 // Didn't find any
210 this->iter_ = 0;
213 // Positions the iterator at the next node in the bucket or goes to the next
214 // bucket
216 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY> void
217 ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::next ()
219 if (this->isdone ())
220 return;
222 // If there is no more in the current bucket, go to the next
223 if (this->iter_->isdone ())
225 for (++this->position_;
226 this->position_ < this->timer_hash_.table_size_;
227 ++this->position_)
229 // Check for an empty entry
230 if (!this->timer_hash_.table_[this->position_]->is_empty ())
232 this->iter_ = &this->timer_hash_.table_[this->position_]->iter ();
233 this->iter_->first ();
234 return;
238 // Didn't find any.
239 this->iter_ = 0;
241 else
242 this->iter_->next ();
245 // Returns true when we are at the end (when bucket_item_ == 0)
247 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY> bool
248 ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::isdone () const
250 return this->iter_ == 0;
253 // Returns the node at the current position in the sequence
255 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY>
256 ACE_Timer_Node_T<TYPE> *
257 ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::item ()
259 if (this->isdone ())
260 return 0;
262 return this->iter_->item ();
265 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY>
266 ACE_Timer_Queue_Iterator_T<TYPE> &
267 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::iter ()
269 this->iterator_->first ();
270 return *this->iterator_;
273 // Create an empty queue.
275 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY>
276 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::ACE_Timer_Hash_T (
277 size_t table_size,
278 FUNCTOR *upcall_functor,
279 ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist,
280 TIME_POLICY const & time_policy)
281 : Base_Timer_Queue (upcall_functor, freelist, time_policy),
282 size_ (0),
283 table_size_ (table_size),
284 table_functor_ (this),
285 earliest_position_ (0),
286 iterator_ (0)
287 #if defined (ACE_WIN64)
288 , pointer_base_ (0)
289 #endif /* ACE_WIN64 */
290 , token_list_ ()
292 ACE_TRACE ("ACE_Timer_Hash_T::ACE_Timer_Hash_T");
294 ACE_NEW (table_,
295 BUCKET *[table_size]);
297 for (size_t i = 0;
298 i < table_size;
299 ++i)
301 ACE_NEW (this->table_[i],
302 BUCKET (&this->table_functor_,
303 this->free_list_,
304 time_policy));
307 ACE_NEW (iterator_,
308 HASH_ITERATOR (*this));
312 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY>
313 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::ACE_Timer_Hash_T (
314 FUNCTOR *upcall_functor,
315 ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist,
316 TIME_POLICY const & time_policy)
317 : Base_Timer_Queue (upcall_functor, freelist, time_policy),
318 size_ (0),
319 table_size_ (ACE_DEFAULT_TIMER_HASH_TABLE_SIZE),
320 table_functor_ (this),
321 earliest_position_ (0)
322 #if defined (ACE_WIN64)
323 , pointer_base_ (0)
324 #endif /* ACE_WIN64 */
325 , token_list_ ()
327 ACE_TRACE ("ACE_Timer_Hash_T::ACE_Timer_Hash_T");
329 ACE_NEW (table_,
330 BUCKET *[ACE_DEFAULT_TIMER_HASH_TABLE_SIZE]);
332 for (size_t i = 0;
333 i < this->table_size_;
334 ++i)
336 ACE_NEW (this->table_[i],
337 BUCKET (&this->table_functor_,
338 this->free_list_,
339 time_policy));
342 ACE_NEW (iterator_,
343 HASH_ITERATOR (*this));
346 // Remove all remaining items in the Queue.
348 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY>
349 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::~ACE_Timer_Hash_T ()
351 ACE_TRACE ("ACE_Timer_Hash_T::~ACE_Timer_Hash_T");
352 ACE_MT (ACE_GUARD (ACE_LOCK, ace_mon, this->mutex_));
354 delete iterator_;
356 this->close ();
358 for (size_t i = 0;
359 i < this->table_size_;
360 ++i)
361 delete this->table_[i];
364 delete [] this->table_;
367 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY> int
368 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::close ()
370 ACE_TRACE ("ACE_Timer_Hash_T::close");
371 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
373 // Remove all remaining items from the queue.
374 while (!this->is_empty())
376 ACE_Timer_Node_T<TYPE>* n = this->remove_first();
377 this->upcall_functor ().deletion (*this,
378 n->get_type(),
379 n->get_act());
380 this->free_node (n);
383 // leave the rest to destructor
384 return 0;
387 // Checks if queue is empty.
389 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY> bool
390 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::is_empty () const
392 ACE_TRACE ("ACE_Timer_Hash_T::is_empty");
393 return this->table_[this->earliest_position_]->is_empty ();
396 // Returns earliest time in a non-empty bucket
398 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY>
399 const ACE_Time_Value &
400 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::earliest_time () const
402 ACE_TRACE ("ACE_Timer_Hash_T::earliest_time");
403 return this->table_[this->earliest_position_]->earliest_time ();
406 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY> void
407 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::dump () const
409 #if defined (ACE_HAS_DUMP)
410 ACE_TRACE ("ACE_Timer_Hash_T::dump");
411 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
412 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntable_size_ = %d"), this->table_size_));
413 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nearliest_position_ = %d"), this->earliest_position_));
415 for (size_t i = 0; i < this->table_size_; ++i)
416 if (!this->table_[i]->is_empty ())
417 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nBucket %d contains nodes"), i));
419 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
420 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
421 #endif /* ACE_HAS_DUMP */
424 // Reschedule a periodic timer. This function must be called with the
425 // mutex lock held.
427 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY>
428 void
429 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::reschedule (
430 ACE_Timer_Node_T<TYPE> *expired)
432 ACE_TRACE ("ACE_Timer_Hash_T::reschedule");
434 Hash_Token<TYPE> *h =
435 reinterpret_cast<Hash_Token<TYPE> *> (
436 const_cast<void *> (expired->get_act ()));
438 // Don't use ACE_Utils::truncate_cast<> here. A straight
439 // static_cast<> will provide more unique results when the number
440 // of seconds is greater than std::numeric_limits<size_t>::max().
441 size_t const secs_hash_input =
442 static_cast<size_t> (expired->get_timer_value ().sec ());
443 h->pos_ = secs_hash_input % this->table_size_;
445 h->orig_id_ =
446 this->table_[h->pos_]->schedule (expired->get_type (),
448 expired->get_timer_value (),
449 expired->get_interval ());
450 ACE_ASSERT (h->orig_id_ != -1);
452 // Since schedule() above will allocate a new node
453 // then here schedule <expired> for deletion. Don't call
454 // this->free_node() because that will invalidate <h>
455 // and that's what user have as timer_id.
456 Base_Timer_Queue::free_node (expired);
458 if (this->table_[this->earliest_position_]->is_empty ()
459 || this->table_[h->pos_]->earliest_time ()
460 < this->table_[this->earliest_position_]->earliest_time ())
461 this->earliest_position_ = h->pos_;
464 // Insert a new handler that expires at time future_time; if interval
465 // is > 0, the handler will be reinvoked periodically.
467 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY>
468 long
469 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::schedule_i (
470 const TYPE &type,
471 const void *act,
472 const ACE_Time_Value &future_time,
473 const ACE_Time_Value &interval)
475 ACE_TRACE ("ACE_Timer_Hash_T::schedule_i");
477 // Don't use ACE_Utils::truncate_cast<> here. A straight
478 // static_cast<> will provide more unique results when the number
479 // of seconds is greater than std::numeric_limits<size_t>::max().
480 size_t const secs_hash_input = static_cast<size_t> (future_time.sec ());
481 size_t const position = secs_hash_input % this->table_size_;
483 // Don't create Hash_Token directly. Instead we get one from Free_List
484 // and then set it properly.
485 Hash_Token<TYPE> *h = this->token_list_.remove ();
486 h->set (act, position, 0, type);
488 h->orig_id_ =
489 this->table_[position]->schedule (type,
491 future_time,
492 interval);
493 ACE_ASSERT (h->orig_id_ != -1);
495 if (this->table_[this->earliest_position_]->is_empty ()
496 || this->table_[position]->earliest_time ()
497 < this->table_[this->earliest_position_]->earliest_time ())
498 this->earliest_position_ = position;
500 ++this->size_;
502 #if defined (ACE_WIN64)
503 // This is a Win64 hack, necessary because of the original (bad) decision
504 // to use a pointer as the timer ID. This class doesn't follow the usual
505 // timer expiration rules (see comments in header file) and is probably
506 // not used much. The dynamic allocation of Hash_Tokens without
507 // recording them anywhere is a large problem for Win64 since the
508 // size of a pointer is 64 bits, but a long is 32. Since this class
509 // is not much used, I'm hacking this, at least for now. If it becomes
510 // an issue, I'll look at it again then.
511 intptr_t hi = reinterpret_cast<intptr_t> (h);
512 if (this->pointer_base_ == 0)
513 this->pointer_base_ = hi & 0xffffffff00000000;
514 return static_cast<long> (hi & 0xffffffff);
515 #else
516 return reinterpret_cast<long> (h);
517 #endif
520 // Locate and update the inteval on the timer_id
522 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY>
524 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::reset_interval (
525 long timer_id,
526 const ACE_Time_Value & interval)
528 ACE_TRACE ("ACE_Timer_Hash_T::reset_interval");
530 // Make sure we are getting a valid <timer_id>, not an error
531 // returned by <schedule>.
532 if (timer_id == -1)
533 return -1;
535 #if defined (ACE_WIN64)
536 unsigned long const timer_offset =
537 static_cast<unsigned long> (timer_id);
539 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
541 Hash_Token<TYPE> * const h =
542 reinterpret_cast<Hash_Token<TYPE> *> (this->pointer_base_ + timer_offset);
543 #else
544 Hash_Token<TYPE> * const h =
545 reinterpret_cast<Hash_Token<TYPE> *> (timer_id);
547 // Grab the lock before accessing the table. We don't need to do so
548 // before this point since no members are accessed until now.
549 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
550 #endif /* ACE_WIN64 */
552 return this->table_[h->pos_]->reset_interval (h->orig_id_,
553 interval);
556 // Locate and remove the single <ACE_Event_Handler> with a value of
557 // @a timer_id from the correct table timer queue.
559 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY>
561 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::cancel (long timer_id,
562 const void **act,
563 int dont_call)
565 ACE_TRACE ("ACE_Timer_Hash_T::cancel");
567 // Make sure we are getting a valid <timer_id>, not an error
568 // returned by <schedule>.
569 if (timer_id == -1)
570 return 0;
572 #if defined (ACE_WIN64)
573 unsigned long const timer_offset =
574 static_cast<unsigned long> (timer_id);
576 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
578 Hash_Token<TYPE> * const h =
579 reinterpret_cast<Hash_Token<TYPE> *> (this->pointer_base_ + timer_offset);
580 #else
581 Hash_Token<TYPE> * const h =
582 reinterpret_cast<Hash_Token<TYPE> *> (timer_id);
584 // Grab the lock before accessing the table. We don't need to do so
585 // before this point since no members are accessed until now.
586 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
587 #endif /* ACE_WIN64 */
589 int const result = this->table_[h->pos_]->cancel (h->orig_id_,
591 dont_call);
593 if (result == 1)
595 // Call the close hooks.
596 int cookie = 0;
598 // cancel_type() called once per <type>.
599 this->upcall_functor ().cancel_type (*this,
600 h->type_,
601 dont_call,
602 cookie);
604 // cancel_timer() called once per <timer>.
605 this->upcall_functor ().cancel_timer (*this,
606 h->type_,
607 dont_call,
608 cookie);
610 if (h->pos_ == this->earliest_position_)
611 this->find_new_earliest ();
613 if (act != 0)
614 *act = h->act_;
616 // We could destruct Hash_Token explicitly but we better
617 // schedule it for destruction. In this case next
618 // token_list_.remove () will use it.
619 this->token_list_.add (h);
621 --this->size_;
624 return result;
627 // Locate and remove all values of <type> from the timer queue.
629 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY>
631 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::cancel (const TYPE &type,
632 int dont_call)
634 ACE_TRACE ("ACE_Timer_Hash_T::cancel");
636 size_t i; // loop variable.
638 Hash_Token<TYPE> **timer_ids = 0;
639 size_t pos = 0;
641 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
643 ACE_NEW_RETURN (timer_ids,
644 Hash_Token<TYPE> *[this->size_],
645 -1);
647 for (i = 0;
648 i < this->table_size_;
649 ++i)
651 ACE_Timer_Queue_Iterator_T<TYPE> & iter =
652 this->table_[i]->iter ();
654 for (iter.first ();
655 !iter.isdone ();
656 iter.next ())
657 if (iter.item ()->get_type () == type)
658 timer_ids[pos++] =
659 reinterpret_cast<Hash_Token<TYPE> *> (
660 const_cast<void *> (iter.item ()->get_act ()));
663 if (pos > this->size_)
664 return -1;
666 for (i = 0; i < pos; ++i)
668 int const result =
669 this->table_[timer_ids[i]->pos_]->cancel (timer_ids[i]->orig_id_,
671 dont_call);
672 ACE_ASSERT (result == 1);
673 ACE_UNUSED_ARG (result);
675 // We could destruct Hash_Token explicitly but we better
676 // schedule it for destruction.
677 this->token_list_.add (timer_ids[i]);
679 --this->size_;
682 delete [] timer_ids;
684 this->find_new_earliest ();
686 // Call the close hooks.
687 int cookie = 0;
689 // cancel_type() called once per <type>.
690 this->upcall_functor ().cancel_type (*this,
691 type,
692 dont_call,
693 cookie);
695 for (i = 0;
696 i < pos;
697 ++i)
699 // cancel_timer() called once per <timer>.
700 this->upcall_functor ().cancel_timer (*this,
701 type,
702 dont_call,
703 cookie);
706 return static_cast<int> (pos);
709 // Removes the earliest node and finds the new earliest position
711 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY> ACE_Timer_Node_T<TYPE> *
712 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::remove_first ()
714 if (this->is_empty ())
715 return 0;
717 ACE_Timer_Node_T<TYPE> *temp =
718 this->table_[this->earliest_position_]->remove_first ();
720 this->find_new_earliest ();
722 --this->size_;
724 return temp;
727 // Finds a new earliest position
729 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY> void
730 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::find_new_earliest ()
732 for (size_t i = 0; i < this->table_size_; ++i)
733 if (!this->table_[i]->is_empty ())
734 if (this->table_[this->earliest_position_]->is_empty ()
735 || this->earliest_time () == ACE_Time_Value::zero
736 || this->table_[i]->earliest_time () <= this->earliest_time ())
737 this->earliest_position_ = i;
740 // Returns the earliest node without removing it
742 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY> ACE_Timer_Node_T<TYPE> *
743 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::get_first ()
745 ACE_TRACE ("ACE_Timer_Hash_T::get_first");
747 if (this->is_empty ())
748 return 0;
750 return this->table_[this->earliest_position_]->get_first ();
753 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY> void
754 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::free_node (ACE_Timer_Node_T<TYPE> *node)
756 Base_Timer_Queue::free_node (node);
758 Hash_Token<TYPE> *h =
759 reinterpret_cast<Hash_Token<TYPE> *> (const_cast<void *> (node->get_act ()));
760 this->token_list_.add (h);
763 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY> int
764 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::dispatch_info_i (const ACE_Time_Value &cur_time,
765 ACE_Timer_Node_Dispatch_Info_T<TYPE> &info)
767 int const result =
768 Base_Timer_Queue::dispatch_info_i (cur_time, info);
770 if (result == 1)
772 Hash_Token<TYPE> *h =
773 reinterpret_cast<Hash_Token<TYPE> *> (const_cast<void *> (info.act_));
775 info.act_ = h->act_;
778 return result;
781 // Dummy version of expire to get rid of warnings in Sun CC 4.2
783 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY> int
784 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::expire ()
786 return Base_Timer_Queue::expire();
789 // Specialized expire for Timer Hash
791 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET, typename TIME_POLICY> int
792 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET, TIME_POLICY>::expire (const ACE_Time_Value &cur_time)
794 ACE_TRACE ("ACE_Timer_Hash_T::expire");
796 int number_of_timers_expired = 0;
798 ACE_Timer_Node_T<TYPE> *expired = 0;
800 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
802 // Go through the table and expire anything that can be expired
804 for (size_t i = 0;
805 i < this->table_size_;
806 ++i)
808 while (!this->table_[i]->is_empty ()
809 && this->table_[i]->earliest_time () <= cur_time)
811 expired = this->table_[i]->remove_first ();
812 const void *act = expired->get_act ();
813 bool reclaim = true;
815 Hash_Token<TYPE> *h =
816 reinterpret_cast<Hash_Token<TYPE> *> (const_cast<void *> (act));
818 ACE_ASSERT (h->pos_ == i);
820 // Check if this is an interval timer.
821 if (expired->get_interval () > ACE_Time_Value::zero)
823 // Make sure that we skip past values that have already
824 // "expired".
825 this->recompute_next_abs_interval_time (expired, cur_time);
827 // Since this is an interval timer, we need to
828 // reschedule it.
829 this->reschedule (expired);
830 reclaim = false;
832 else
834 this->free_node (expired);
837 ACE_Timer_Node_Dispatch_Info_T<TYPE> info;
839 // Get the dispatch info
840 expired->get_dispatch_info (info);
842 info.act_ = h->act_;
844 const void *upcall_act = 0;
846 this->preinvoke (info, cur_time, upcall_act);
848 this->upcall (info, cur_time);
850 this->postinvoke (info, cur_time, upcall_act);
852 if (reclaim)
854 --this->size_;
857 ++number_of_timers_expired;
861 if (number_of_timers_expired > 0)
862 this->find_new_earliest ();
864 return number_of_timers_expired;
867 ACE_END_VERSIONED_NAMESPACE_DECL
869 #endif /* ACE_TIMER_HASH_T_CPP */