1 #ifndef ACE_TIMER_HEAP_T_CPP
2 #define ACE_TIMER_HEAP_T_CPP
4 #include "ace/Timer_Heap_T.h"
5 #include "ace/Log_Category.h"
6 #include "ace/Guard_T.h"
7 #include "ace/OS_NS_errno.h"
8 #include "ace/OS_NS_string.h"
9 #include "ace/Numeric_Limits.h"
11 #if !defined (ACE_LACKS_PRAGMA_ONCE)
13 #endif /* ACE_LACKS_PRAGMA_ONCE */
16 ** The ACE_Timer_Heap::max_size_ and array loops, checks, etc. are all size_t.
17 ** The timer IDs are long, and since they are indices into the heap, we need
18 ** to be sure that the timer heap size can fit in a long. Hence, when size
19 ** is (re)set, limit it to the maximum long value. We use the C++ standard
20 ** limits if available.
23 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
25 ACE_ALLOC_HOOK_DEFINE_Tccct(ACE_Timer_Heap_Iterator_T
)
26 ACE_ALLOC_HOOK_DEFINE_Tccct(ACE_Timer_Heap_T
)
28 // Define some simple inlined functions to clarify the code.
30 ACE_HEAP_PARENT (size_t X
)
32 return (X
== 0 ? 0 : ((X
- 1) / 2));
36 ACE_HEAP_LCHILD (size_t X
)
41 // Constructor that takes in an <ACE_Timer_Heap_T> to iterate over.
43 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
44 ACE_Timer_Heap_Iterator_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::ACE_Timer_Heap_Iterator_T (
48 ACE_TRACE ("ACE_Timer_Heap_Iterator_T::ACE_Timer_Heap_Iterator");
52 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
53 ACE_Timer_Heap_Iterator_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::~ACE_Timer_Heap_Iterator_T (void)
57 // Positions the iterator at the first node in the heap array
59 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
61 ACE_Timer_Heap_Iterator_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::first (void)
66 // Positions the iterator at the next node in the heap array
68 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
70 ACE_Timer_Heap_Iterator_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::next (void)
72 if (this->position_
!= this->timer_heap_
.cur_size_
)
76 // Returns true the <position_> is at the end of the heap array
78 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
> bool
79 ACE_Timer_Heap_Iterator_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::isdone (void) const
81 return this->position_
== this->timer_heap_
.cur_size_
;
84 // Returns the node at the current position in the heap or 0 if at the end
86 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
> ACE_Timer_Node_T
<TYPE
> *
87 ACE_Timer_Heap_Iterator_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::item (void)
89 if (this->position_
!= this->timer_heap_
.cur_size_
)
90 return this->timer_heap_
.heap_
[this->position_
];
95 // Note that timer_ids_curr_ and timer_ids_min_free_ both start at 0.
96 // Since timer IDs are assigned by first incrementing the timer_ids_curr_
97 // value, the first ID assigned will be 1 (just as in the previous design).
98 // When it's time to wrap, the next ID given out will be 0.
99 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
100 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::ACE_Timer_Heap_T (
103 FUNCTOR
*upcall_functor
,
104 ACE_Free_List
<ACE_Timer_Node_T
<TYPE
> > *freelist
,
105 TIME_POLICY
const & time_policy
)
106 : Base_Time_Policy (upcall_functor
,
113 timer_ids_min_free_ (0),
114 preallocated_nodes_ (0),
115 preallocated_nodes_freelist_ (0)
117 ACE_TRACE ("ACE_Timer_Heap_T::ACE_Timer_Heap_T");
119 // Possibly reduce size to fit in a long.
120 if (size
> static_cast<size_t> (ACE_Numeric_Limits
<long>::max ()))
122 size
= static_cast<size_t> (ACE_Numeric_Limits
<long>::max ());
123 this->max_size_
= size
;
126 // Create the heap array.
127 #if defined (ACE_HAS_ALLOC_HOOKS)
128 this->heap_
= reinterpret_cast<ACE_Timer_Node_T
<TYPE
> **>
129 (ACE_Allocator::instance ()->malloc (sizeof (ACE_Timer_Node_T
<TYPE
> *) * size
));
131 ACE_NEW (this->heap_
,
132 ACE_Timer_Node_T
<TYPE
> *[size
]);
133 #endif /* ACE_HAS_ALLOC_HOOKS */
135 // Create the parallel
136 ACE_NEW (this->timer_ids_
,
139 // Initialize the "freelist," which uses negative values to
140 // distinguish freelist elements from "pointers" into the <heap_>
142 for (size_t i
= 0; i
< size
; ++i
)
143 this->timer_ids_
[i
] = -1;
147 ACE_NEW (this->preallocated_nodes_
,
148 ACE_Timer_Node_T
<TYPE
>[size
]);
150 // Add allocated array to set of such arrays for deletion on
152 this->preallocated_node_set_
.insert (this->preallocated_nodes_
);
154 // Form the freelist by linking the next_ pointers together.
155 for (size_t j
= 1; j
< size
; ++j
)
156 this->preallocated_nodes_
[j
- 1].set_next (&this->preallocated_nodes_
[j
]);
158 // NULL-terminate the freelist.
159 this->preallocated_nodes_
[size
- 1].set_next (0);
161 // Assign the freelist pointer to the front of the list.
162 this->preallocated_nodes_freelist_
=
163 &this->preallocated_nodes_
[0];
167 HEAP_ITERATOR (*this));
170 // Note that timer_ids_curr_ and timer_ids_min_free_ both start at 0.
171 // Since timer IDs are assigned by first incrementing the timer_ids_curr_
172 // value, the first ID assigned will be 1 (just as in the previous design).
173 // When it's time to wrap, the next ID given out will be 0.
174 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
175 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::ACE_Timer_Heap_T (
176 FUNCTOR
*upcall_functor
,
177 ACE_Free_List
<ACE_Timer_Node_T
<TYPE
> > *freelist
,
178 TIME_POLICY
const & time_policy
)
179 : Base_Time_Policy (upcall_functor
,
182 max_size_ (ACE_DEFAULT_TIMERS
),
186 timer_ids_min_free_ (0),
187 preallocated_nodes_ (0),
188 preallocated_nodes_freelist_ (0)
190 ACE_TRACE ("ACE_Timer_Heap_T::ACE_Timer_Heap_T");
192 // Possibly reduce size to fit in a long.
193 if (this->max_size_
> static_cast<size_t> (ACE_Numeric_Limits
<long>::max ()))
194 this->max_size_
= static_cast<size_t> (ACE_Numeric_Limits
<long>::max ());
196 // Create the heap array.
197 #if defined (ACE_HAS_ALLOC_HOOKS)
198 this->heap_
= reinterpret_cast<ACE_Timer_Node_T
<TYPE
> **>
199 (ACE_Allocator::instance ()->malloc (sizeof (ACE_Timer_Node_T
<TYPE
> *) * this->max_size_
));
201 ACE_NEW (this->heap_
,
202 ACE_Timer_Node_T
<TYPE
> *[this->max_size_
]);
203 #endif /* ACE_HAS_ALLOC_HOOKS */
205 // Create the parallel array.
206 #if defined (ACE_HAS_ALLOC_HOOKS)
207 this->timer_ids_
= reinterpret_cast<ssize_t
*>
208 (ACE_Allocator::instance ()->malloc (sizeof (ssize_t
) * this->max_size_
));
210 ACE_NEW (this->timer_ids_
,
211 ssize_t
[this->max_size_
]);
212 #endif /* ACE_HAS_ALLOC_HOOKS */
214 // Initialize the "freelist," which uses negative values to
215 // distinguish freelist elements from "pointers" into the <heap_>
217 for (size_t i
= 0; i
< this->max_size_
; ++i
)
218 this->timer_ids_
[i
] = -1;
221 HEAP_ITERATOR (*this));
224 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
225 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::~ACE_Timer_Heap_T (void)
227 ACE_TRACE ("ACE_Timer_Heap_T::~ACE_Timer_Heap_T");
233 #if defined (ACE_HAS_ALLOC_HOOKS)
235 (ACE_Allocator::instance ()->free (this->heap_
));
237 delete [] this->heap_
;
238 #endif /* ACE_HAS_ALLOC_HOOKS */
240 #if defined (ACE_HAS_ALLOC_HOOKS)
241 if (this->timer_ids_
)
242 (ACE_Allocator::instance ()->free (this->timer_ids_
));
244 delete [] this->timer_ids_
;
245 #endif /* ACE_HAS_ALLOC_HOOKS */
247 // clean up any preallocated timer nodes
248 if (preallocated_nodes_
!= 0)
250 ACE_Unbounded_Set_Iterator
<ACE_Timer_Node_T
<TYPE
> *>
251 set_iterator (this->preallocated_node_set_
);
253 for (ACE_Timer_Node_T
<TYPE
> **entry
= 0;
254 set_iterator
.next (entry
) !=0;
255 set_iterator
.advance ())
260 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
> int
261 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::close (void)
263 ACE_TRACE ("ACE_Timer_Heap_T::close");
265 size_t current_size
=
268 // Clean up all the nodes still in the queue
269 for (size_t i
= 0; i
< current_size
; ++i
)
271 // Grab the event_handler and act, then delete the node before calling
272 // back to the handler. Prevents a handler from trying to cancel_timer()
273 // inside handle_close(), ripping the current timer node out from
275 TYPE eh
= this->heap_
[i
]->get_type ();
276 const void *act
= this->heap_
[i
]->get_act ();
277 this->free_node (this->heap_
[i
]);
278 this->upcall_functor ().deletion (*this, eh
, act
);
281 // leave the rest to the destructor
285 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
287 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::pop_freelist (void)
289 ACE_TRACE ("ACE_Timer_Heap_T::pop_freelist");
291 // Scan for a free timer ID. Note that since this function is called
292 // _after_ the check for a full timer heap, we are guaranteed to find
293 // a free ID, even if we need to wrap around and start reusing freed IDs.
294 // On entry, the curr_ index is at the previous ID given out; start
295 // up where we left off last time.
296 // NOTE - a timer_ids_ slot with -2 is out of the heap, but not freed.
297 // It must be either freed (free_node) or rescheduled (reschedule).
298 ++this->timer_ids_curr_
;
299 while (this->timer_ids_curr_
< this->max_size_
&&
300 (this->timer_ids_
[this->timer_ids_curr_
] >= 0 ||
301 this->timer_ids_
[this->timer_ids_curr_
] == -2 ))
302 ++this->timer_ids_curr_
;
303 if (this->timer_ids_curr_
== this->max_size_
)
305 ACE_ASSERT (this->timer_ids_min_free_
< this->max_size_
);
306 this->timer_ids_curr_
= this->timer_ids_min_free_
;
307 // We restarted the free search at min. Since min won't be
308 // free anymore, and curr_ will just keep marching up the list
309 // on each successive need for an ID, reset min_free_ to the
310 // size of the list until an ID is freed that curr_ has already
311 // gone past (see push_freelist).
312 this->timer_ids_min_free_
= this->max_size_
;
315 return static_cast<long> (this->timer_ids_curr_
);
318 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
320 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::push_freelist (long old_id
)
322 ACE_TRACE ("ACE_Timer_Heap_T::push_freelist");
324 // Since this ID has already been checked by one of the public
325 // functions, it's safe to cast it here.
326 size_t oldid
= static_cast<size_t> (old_id
);
328 // The freelist values in the <timer_ids_> are negative, so set the
329 // freed entry back to 'free'. If this is the new lowest value free
330 // timer ID that curr_ won't see on it's normal march through the list,
332 ACE_ASSERT (this->timer_ids_
[oldid
] >= 0 || this->timer_ids_
[oldid
] == -2);
333 if (this->timer_ids_
[oldid
] == -2)
337 this->timer_ids_
[oldid
] = -1;
338 if (oldid
< this->timer_ids_min_free_
&& oldid
<= this->timer_ids_curr_
)
339 this->timer_ids_min_free_
= oldid
;
343 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
345 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::timer_id (void)
347 ACE_TRACE ("ACE_Timer_Heap_T::timer_id");
349 // Return the next item off the freelist and use it as the timer id.
350 return this->pop_freelist ();
353 // Checks if queue is empty.
355 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
357 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::is_empty (void) const
359 ACE_TRACE ("ACE_Timer_Heap_T::is_empty");
361 return this->cur_size_
== 0;
364 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
365 ACE_Timer_Queue_Iterator_T
<TYPE
> &
366 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::iter (void)
368 this->iterator_
->first ();
369 return *this->iterator_
;
372 // Returns earliest time in a non-empty queue.
374 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
> const ACE_Time_Value
&
375 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::earliest_time (void) const
377 ACE_TRACE ("ACE_Timer_Heap_T::earliest_time");
378 return this->heap_
[0]->get_timer_value ();
381 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
383 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::dump (void) const
385 #if defined (ACE_HAS_DUMP)
386 ACE_TRACE ("ACE_Timer_Heap_T::dump");
387 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
389 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("\nmax_size_ = %d"), this->max_size_
));
390 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("\ncur_size_ = %d"), this->cur_size_
));
391 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("\ncur_limbo_= %d"), this->cur_limbo_
));
392 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("\nids_curr_ = %d"),
393 this->timer_ids_curr_
));
394 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("\nmin_free_ = %d"),
395 this->timer_ids_min_free_
));
397 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("\nheap_ =\n")));
399 for (size_t i
= 0; i
< this->cur_size_
; ++i
)
401 ACELIB_DEBUG ((LM_DEBUG
,
404 this->heap_
[i
]->dump ();
407 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("\ntimer_ids_ =\n")));
409 for (size_t j
= 0; j
< this->max_size_
; ++j
)
410 ACELIB_DEBUG ((LM_DEBUG
,
411 ACE_TEXT ("%d\t%d\n"),
413 this->timer_ids_
[j
]));
415 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
416 #endif /* ACE_HAS_DUMP */
419 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
421 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::copy (
423 ACE_Timer_Node_T
<TYPE
> *moved_node
)
425 // Insert <moved_node> into its new location in the heap.
426 this->heap_
[slot
] = moved_node
;
428 ACE_ASSERT (moved_node
->get_timer_id () >= 0
429 && moved_node
->get_timer_id () < (int) this->max_size_
);
431 // Update the corresponding slot in the parallel <timer_ids_> array.
432 this->timer_ids_
[moved_node
->get_timer_id ()] = static_cast<ssize_t
> (slot
);
435 // Remove the slot'th timer node from the heap, but do not reclaim its
436 // timer ID or change the size of this timer heap object. The caller of
437 // this function must call either free_node (to reclaim the timer ID
438 // and the timer node memory, as well as decrement the size of the queue)
439 // or reschedule (to reinsert the node in the heap at a new time).
440 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
441 ACE_Timer_Node_T
<TYPE
> *
442 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::remove (size_t slot
)
444 ACE_Timer_Node_T
<TYPE
> *removed_node
=
447 // NOTE - the cur_size_ is being decremented since the queue has one
448 // less active timer in it. However, this ACE_Timer_Node is not being
449 // freed, and there is still a place for it in timer_ids_ (the timer ID
450 // is not being relinquished). The node can still be rescheduled, or
451 // it can be freed via free_node.
454 // Only try to reheapify if we're not deleting the last entry.
456 if (slot
< this->cur_size_
)
458 ACE_Timer_Node_T
<TYPE
> *moved_node
=
459 this->heap_
[this->cur_size_
];
461 // Move the end node to the location being removed and update
462 // the corresponding slot in the parallel <timer_ids> array.
463 this->copy (slot
, moved_node
);
465 // If the <moved_node->time_value_> is great than or equal its
466 // parent it needs be moved down the heap.
467 size_t parent
= ACE_HEAP_PARENT (slot
);
469 if (moved_node
->get_timer_value ()
470 >= this->heap_
[parent
]->get_timer_value ())
471 this->reheap_down (moved_node
,
473 ACE_HEAP_LCHILD (slot
));
475 this->reheap_up (moved_node
,
480 this->timer_ids_
[removed_node
->get_timer_id ()] = -2;
485 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
> void
486 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::reheap_down (
487 ACE_Timer_Node_T
<TYPE
> *moved_node
,
491 // Restore the heap property after a deletion.
493 while (child
< this->cur_size_
)
495 // Choose the smaller of the two children.
496 if (child
+ 1 < this->cur_size_
497 && this->heap_
[child
+ 1]->get_timer_value ()
498 < this->heap_
[child
]->get_timer_value ())
501 // Perform a <copy> if the child has a larger timeout value than
503 if (this->heap_
[child
]->get_timer_value ()
504 < moved_node
->get_timer_value ())
509 child
= ACE_HEAP_LCHILD (child
);
512 // We've found our location in the heap.
516 this->copy (slot
, moved_node
);
519 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
521 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::reheap_up (
522 ACE_Timer_Node_T
<TYPE
> *moved_node
,
526 // Restore the heap property after an insertion.
530 // If the parent node is greater than the <moved_node> we need
532 if (moved_node
->get_timer_value ()
533 < this->heap_
[parent
]->get_timer_value ())
535 this->copy (slot
, this->heap_
[parent
]);
537 parent
= ACE_HEAP_PARENT (slot
);
543 // Insert the new node into its proper resting place in the heap and
544 // update the corresponding slot in the parallel <timer_ids> array.
549 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
551 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::insert (
552 ACE_Timer_Node_T
<TYPE
> *new_node
)
554 if (this->cur_size_
+ this->cur_limbo_
+ 2 >= this->max_size_
)
557 this->reheap_up (new_node
,
559 ACE_HEAP_PARENT (this->cur_size_
));
563 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
565 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::grow_heap (void)
567 // All the containers will double in size from max_size_.
568 size_t new_size
= this->max_size_
* 2;
570 // First grow the heap itself.
571 ACE_Timer_Node_T
<TYPE
> **new_heap
= 0;
573 #if defined (ACE_HAS_ALLOC_HOOKS)
574 new_heap
= reinterpret_cast<ACE_Timer_Node_T
<TYPE
> **>
575 (ACE_Allocator::instance ()->malloc (sizeof (ACE_Timer_Node_T
<TYPE
> *) * new_size
));
578 ACE_Timer_Node_T
<TYPE
> *[new_size
]);
579 #endif /* ACE_HAS_ALLOC_HOOKS */
581 ACE_OS::memcpy (new_heap
,
583 this->max_size_
* sizeof *new_heap
);
585 #if defined (ACE_HAS_ALLOC_HOOKS)
586 ACE_Allocator::instance ()->free (this->heap_
);
588 delete [] this->heap_
;
589 #endif /* ACE_HAS_ALLOC_HOOKS */
591 this->heap_
= new_heap
;
593 // Grow the array of timer ids.
595 ssize_t
*new_timer_ids
= 0;
597 #if defined (ACE_HAS_ALLOC_HOOKS)
598 new_timer_ids
= reinterpret_cast<ssize_t
*>
599 (ACE_Allocator::instance ()->malloc (sizeof (ssize_t
) * new_size
));
601 ACE_NEW (new_timer_ids
,
603 #endif /* ACE_HAS_ALLOC_HOOKS */
605 ACE_OS::memcpy (new_timer_ids
,
607 this->max_size_
* sizeof (ssize_t
));
609 #if defined (ACE_HAS_ALLOC_HOOKS)
610 if (this->timer_ids_
)
611 (ACE_Allocator::instance ()->free (this->timer_ids_
));
613 delete [] this->timer_ids_
;
614 #endif /* ACE_HAS_ALLOC_HOOKS */
615 this->timer_ids_
= new_timer_ids
;
617 // And add the new elements to the end of the "freelist".
618 for (size_t i
= this->max_size_
; i
< new_size
; ++i
)
619 this->timer_ids_
[i
] = -(static_cast<ssize_t
> (i
) + 1);
621 // Grow the preallocation array (if using preallocation)
622 if (this->preallocated_nodes_
!= 0)
624 // Create a new array with max_size elements to link in to
626 ACE_NEW (this->preallocated_nodes_
,
627 ACE_Timer_Node_T
<TYPE
>[this->max_size_
]);
629 // Add it to the set for later deletion
630 this->preallocated_node_set_
.insert (this->preallocated_nodes_
);
632 // Link new nodes together (as for original list).
633 for (size_t k
= 1; k
< this->max_size_
; ++k
)
634 this->preallocated_nodes_
[k
- 1].set_next (&this->preallocated_nodes_
[k
]);
636 // NULL-terminate the new list.
637 this->preallocated_nodes_
[this->max_size_
- 1].set_next (0);
639 // Link new array to the end of the existling list.
640 if (this->preallocated_nodes_freelist_
== 0)
641 this->preallocated_nodes_freelist_
=
642 &preallocated_nodes_
[0];
645 ACE_Timer_Node_T
<TYPE
> *previous
=
646 this->preallocated_nodes_freelist_
;
648 for (ACE_Timer_Node_T
<TYPE
> *current
= this->preallocated_nodes_freelist_
->get_next ();
650 current
= current
->get_next ())
653 previous
->set_next (&this->preallocated_nodes_
[0]);
657 this->max_size_
= new_size
;
658 // Force rescan of list from beginning for a free slot (I think...)
659 // This fixed Bugzilla #2447.
660 this->timer_ids_min_free_
= this->max_size_
;
663 // Reschedule a periodic timer. This function must be called with the
666 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
668 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::reschedule (
669 ACE_Timer_Node_T
<TYPE
> *expired
)
671 ACE_TRACE ("ACE_Timer_Heap_T::reschedule");
673 // If we are rescheduling, then the most recent call was to
674 // remove_first (). That called remove () to remove the node from the
675 // heap, but did not free the timer ID. The ACE_Timer_Node still has
676 // its assigned ID - just needs to be inserted at the new proper
677 // place, and the heap restored properly.
678 if (this->timer_ids_
[expired
->get_timer_id ()] == -2)
680 this->insert (expired
);
683 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
684 ACE_Timer_Node_T
<TYPE
> *
685 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::alloc_node (void)
687 ACE_Timer_Node_T
<TYPE
> *temp
= 0;
689 // Only allocate a node if we are *not* using the preallocated heap.
690 if (this->preallocated_nodes_
== 0)
691 ACE_NEW_RETURN (temp
,
692 ACE_Timer_Node_T
<TYPE
>,
696 // check to see if the heap needs to grow
697 if (this->preallocated_nodes_freelist_
== 0)
700 temp
= this->preallocated_nodes_freelist_
;
702 if (this->preallocated_nodes_freelist_
)
704 // Remove the first element from the freelist.
705 this->preallocated_nodes_freelist_
=
706 this->preallocated_nodes_freelist_
->get_next ();
712 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
714 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::free_node (
715 ACE_Timer_Node_T
<TYPE
> *node
)
717 // Return this timer id to the freelist.
718 this->push_freelist (node
->get_timer_id ());
720 // Only free up a node if we are *not* using the preallocated heap.
721 if (this->preallocated_nodes_
== 0)
725 node
->set_next (this->preallocated_nodes_freelist_
);
726 this->preallocated_nodes_freelist_
= node
;
730 // Insert a new timer that expires at time future_time; if interval is
731 // > 0, the handler will be reinvoked periodically.
733 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
735 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::schedule_i (
738 const ACE_Time_Value
&future_time
,
739 const ACE_Time_Value
&interval
)
741 ACE_TRACE ("ACE_Timer_Heap_T::schedule_i");
743 if ((this->cur_size_
+ this->cur_limbo_
) < this->max_size_
)
745 // Obtain the next unique sequence number.
746 long const timer_id
= this->timer_id ();
748 // Obtain the memory to the new node.
749 ACE_Timer_Node_T
<TYPE
> *temp
= 0;
751 ACE_ALLOCATOR_RETURN (temp
,
768 // Locate and remove the single timer with a value of @a timer_id from
771 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
773 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::cancel (long timer_id
,
777 ACE_TRACE ("ACE_Timer_Heap_T::cancel");
778 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK
, ace_mon
, this->mutex_
, -1));
780 // Locate the ACE_Timer_Node that corresponds to the timer_id.
782 // Check to see if the timer_id is out of range
784 || (size_t) timer_id
> this->max_size_
)
787 ssize_t timer_node_slot
= this->timer_ids_
[timer_id
];
789 // Check to see if timer_id is still valid.
790 if (timer_node_slot
< 0)
793 if (timer_id
!= this->heap_
[timer_node_slot
]->get_timer_id ())
795 ACE_ASSERT (timer_id
== this->heap_
[timer_node_slot
]->get_timer_id ());
800 ACE_Timer_Node_T
<TYPE
> *temp
=
801 this->remove (timer_node_slot
);
803 // Call the close hooks.
806 // cancel_type() called once per <type>.
807 this->upcall_functor ().cancel_type (*this,
812 // cancel_timer() called once per <timer>.
813 this->upcall_functor ().cancel_timer (*this,
819 *act
= temp
->get_act ();
821 this->free_node (temp
);
826 // Locate and update the inteval on the timer_id
828 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
830 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::reset_interval (long timer_id
,
831 const ACE_Time_Value
&interval
)
833 ACE_TRACE ("ACE_Timer_Heap_T::reset_interval");
834 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK
, ace_mon
, this->mutex_
, -1));
836 // Locate the ACE_Timer_Node that corresponds to the timer_id.
838 // Check to see if the timer_id is out of range
840 || (size_t) timer_id
> this->max_size_
)
843 ssize_t timer_node_slot
= this->timer_ids_
[timer_id
];
845 // Check to see if timer_id is still valid.
846 if (timer_node_slot
< 0)
849 if (timer_id
!= this->heap_
[timer_node_slot
]->get_timer_id ())
851 ACE_ASSERT (timer_id
== this->heap_
[timer_node_slot
]->get_timer_id ());
856 // Reset the timer interval
857 this->heap_
[timer_node_slot
]->set_interval (interval
);
862 // Locate and remove all values of @a type from the timer queue.
864 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
866 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::cancel (const TYPE
&type
,
869 ACE_TRACE ("ACE_Timer_Heap_T::cancel");
871 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK
, ace_mon
, this->mutex_
, -1));
873 int number_of_cancellations
= 0;
875 // Try to locate the ACE_Timer_Node that matches the timer_id.
877 for (size_t i
= 0; i
< this->cur_size_
; )
879 if (this->heap_
[i
]->get_type () == type
)
881 ACE_Timer_Node_T
<TYPE
> *temp
= this->remove (i
);
883 ++number_of_cancellations
;
885 this->free_node (temp
);
887 // We reset to zero so that we don't miss checking any nodes
888 // if a reheapify occurs when a node is removed. There
889 // may be a better fix than this, however.
896 // Call the close hooks.
899 // cancel_type() called once per <type>.
900 this->upcall_functor ().cancel_type (*this,
906 j
< number_of_cancellations
;
909 // cancel_timer() called once per <timer>.
910 this->upcall_functor ().cancel_timer (*this,
916 return number_of_cancellations
;
919 // Returns the earliest node or returns 0 if the heap is empty.
921 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
922 ACE_Timer_Node_T
<TYPE
> *
923 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::remove_first (void)
925 ACE_TRACE ("ACE_Timer_Heap_T::remove_first");
927 if (this->cur_size_
== 0)
930 return this->remove (0);
933 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
934 ACE_Timer_Node_T
<TYPE
> *
935 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::get_first (void)
937 ACE_TRACE ("ACE_Timer_Heap_T::get_first");
939 return this->cur_size_
== 0 ? 0 : this->heap_
[0];
942 ACE_END_VERSIONED_NAMESPACE_DECL
944 #endif /* ACE_TIMER_HEAP_T_CPP */