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)
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
20 // This constructor is required by ACE_Locked_Free_List::alloc.
29 Hash_Token
<TYPE
> *get_next ()
34 void set_next (Hash_Token
<TYPE
> *next
)
39 void set (const void *act
,
46 this->orig_id_
= orig_id
;
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 ()
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
)
78 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
> int
79 ACE_Timer_Hash_Upcall
<TYPE
, FUNCTOR
, ACE_LOCK
>::registration (
84 // Registration will be handled by the upcall functor of the timer
89 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
> int
90 ACE_Timer_Hash_Upcall
<TYPE
, FUNCTOR
, ACE_LOCK
>::preinvoke (TIMER_QUEUE
&,
94 const ACE_Time_Value
&,
97 // This method should never be invoked since we don't invoke
98 // expire() on the buckets.
103 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
> int
104 ACE_Timer_Hash_Upcall
<TYPE
, FUNCTOR
, ACE_LOCK
>::postinvoke (
109 const ACE_Time_Value
&,
112 // This method should never be invoked since we don't invoke
113 // expire() on the buckets.
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 (
125 const ACE_Time_Value
&)
127 // This method should never be invoked since we don't invoke
128 // expire() on the buckets.
133 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
> int
134 ACE_Timer_Hash_Upcall
<TYPE
, FUNCTOR
, ACE_LOCK
>::cancel_type (
140 // Cancellation will be handled by the upcall functor of the timer
145 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
> int
146 ACE_Timer_Hash_Upcall
<TYPE
, FUNCTOR
, ACE_LOCK
>::cancel_timer (
152 // Cancellation will be handled by the upcall functor of the timer
157 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
> int
158 ACE_Timer_Hash_Upcall
<TYPE
, FUNCTOR
, ACE_LOCK
>::deletion (
160 ACE_Event_Handler
*event_handler
,
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
));
169 this->timer_hash_
->upcall_functor ().
170 deletion (*this->timer_hash_
,
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
)
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 ()
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_
;
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 ();
213 // Positions the iterator at the next node in the bucket or goes to the next
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 ()
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_
;
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 ();
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 ()
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 (
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
),
283 table_size_ (table_size
),
284 table_functor_ (this),
285 earliest_position_ (0),
287 #if defined (ACE_WIN64)
289 #endif /* ACE_WIN64 */
292 ACE_TRACE ("ACE_Timer_Hash_T::ACE_Timer_Hash_T");
295 BUCKET
*[table_size
]);
301 ACE_NEW (this->table_
[i
],
302 BUCKET (&this->table_functor_
,
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
),
319 table_size_ (ACE_DEFAULT_TIMER_HASH_TABLE_SIZE
),
320 table_functor_ (this),
321 earliest_position_ (0)
322 #if defined (ACE_WIN64)
324 #endif /* ACE_WIN64 */
327 ACE_TRACE ("ACE_Timer_Hash_T::ACE_Timer_Hash_T");
330 BUCKET
*[ACE_DEFAULT_TIMER_HASH_TABLE_SIZE
]);
333 i
< this->table_size_
;
336 ACE_NEW (this->table_
[i
],
337 BUCKET (&this->table_functor_
,
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_
));
359 i
< this->table_size_
;
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,
383 // leave the rest to destructor
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
427 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, class BUCKET
, typename TIME_POLICY
>
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_
;
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
>
469 ACE_Timer_Hash_T
<TYPE
, FUNCTOR
, ACE_LOCK
, BUCKET
, TIME_POLICY
>::schedule_i (
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
);
489 this->table_
[position
]->schedule (type
,
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
;
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);
516 return reinterpret_cast<long> (h
);
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 (
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>.
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
);
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_
,
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
,
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>.
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
);
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_
,
595 // Call the close hooks.
598 // cancel_type() called once per <type>.
599 this->upcall_functor ().cancel_type (*this,
604 // cancel_timer() called once per <timer>.
605 this->upcall_functor ().cancel_timer (*this,
610 if (h
->pos_
== this->earliest_position_
)
611 this->find_new_earliest ();
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
);
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
,
634 ACE_TRACE ("ACE_Timer_Hash_T::cancel");
636 size_t i
; // loop variable.
638 Hash_Token
<TYPE
> **timer_ids
= 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_
],
648 i
< this->table_size_
;
651 ACE_Timer_Queue_Iterator_T
<TYPE
> & iter
=
652 this->table_
[i
]->iter ();
657 if (iter
.item ()->get_type () == type
)
659 reinterpret_cast<Hash_Token
<TYPE
> *> (
660 const_cast<void *> (iter
.item ()->get_act ()));
663 if (pos
> this->size_
)
666 for (i
= 0; i
< pos
; ++i
)
669 this->table_
[timer_ids
[i
]->pos_
]->cancel (timer_ids
[i
]->orig_id_
,
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
]);
684 this->find_new_earliest ();
686 // Call the close hooks.
689 // cancel_type() called once per <type>.
690 this->upcall_functor ().cancel_type (*this,
699 // cancel_timer() called once per <timer>.
700 this->upcall_functor ().cancel_timer (*this,
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 ())
717 ACE_Timer_Node_T
<TYPE
> *temp
=
718 this->table_
[this->earliest_position_
]->remove_first ();
720 this->find_new_earliest ();
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 ())
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
)
768 Base_Timer_Queue::dispatch_info_i (cur_time
, info
);
772 Hash_Token
<TYPE
> *h
=
773 reinterpret_cast<Hash_Token
<TYPE
> *> (const_cast<void *> (info
.act_
));
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
805 i
< this->table_size_
;
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 ();
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
825 this->recompute_next_abs_interval_time (expired
, cur_time
);
827 // Since this is an interval timer, we need to
829 this->reschedule (expired
);
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
);
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
);
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 */