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.
42 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
43 ACE_Timer_Heap_Iterator_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::ACE_Timer_Heap_Iterator_T (
47 ACE_TRACE ("ACE_Timer_Heap_Iterator_T::ACE_Timer_Heap_Iterator");
51 // Positions the iterator at the first node in the heap array
52 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
54 ACE_Timer_Heap_Iterator_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::first ()
59 // Positions the iterator at the next node in the heap array
60 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
62 ACE_Timer_Heap_Iterator_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::next ()
64 if (this->position_
!= this->timer_heap_
.cur_size_
)
68 // Returns true the <position_> is at the end of the heap array
69 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
> bool
70 ACE_Timer_Heap_Iterator_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::isdone () const
72 return this->position_
== this->timer_heap_
.cur_size_
;
75 // Returns the node at the current position in the heap or 0 if at the end
76 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
> ACE_Timer_Node_T
<TYPE
> *
77 ACE_Timer_Heap_Iterator_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::item ()
79 if (this->position_
!= this->timer_heap_
.cur_size_
)
80 return this->timer_heap_
.heap_
[this->position_
];
85 // Note that timer_ids_curr_ and timer_ids_min_free_ both start at 0.
86 // Since timer IDs are assigned by first incrementing the timer_ids_curr_
87 // value, the first ID assigned will be 1 (just as in the previous design).
88 // When it's time to wrap, the next ID given out will be 0.
89 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
90 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::ACE_Timer_Heap_T (
93 FUNCTOR
*upcall_functor
,
94 ACE_Free_List
<ACE_Timer_Node_T
<TYPE
> > *freelist
,
95 TIME_POLICY
const & time_policy
)
96 : Base_Time_Policy (upcall_functor
,
104 timer_ids_min_free_ (0),
105 preallocated_nodes_ (0),
106 preallocated_nodes_freelist_ (0)
108 ACE_TRACE ("ACE_Timer_Heap_T::ACE_Timer_Heap_T");
110 // Possibly reduce size to fit in a long.
111 if (size
> static_cast<size_t> (ACE_Numeric_Limits
<long>::max ()))
113 size
= static_cast<size_t> (ACE_Numeric_Limits
<long>::max ());
114 this->max_size_
= size
;
117 // Create the heap array.
118 #if defined (ACE_HAS_ALLOC_HOOKS)
119 this->heap_
= reinterpret_cast<ACE_Timer_Node_T
<TYPE
> **>
120 (ACE_Allocator::instance ()->malloc (sizeof (ACE_Timer_Node_T
<TYPE
> *) * size
));
122 ACE_NEW (this->heap_
,
123 ACE_Timer_Node_T
<TYPE
> *[size
]);
124 #endif /* ACE_HAS_ALLOC_HOOKS */
126 // Create the parallel
127 ACE_NEW (this->timer_ids_
,
130 // Initialize the "freelist," which uses negative values to
131 // distinguish freelist elements from "pointers" into the <heap_>
133 for (size_t i
= 0; i
< size
; ++i
)
134 this->timer_ids_
[i
] = -1;
138 ACE_NEW (this->preallocated_nodes_
,
139 ACE_Timer_Node_T
<TYPE
>[size
]);
141 // Add allocated array to set of such arrays for deletion on
143 this->preallocated_node_set_
.insert (this->preallocated_nodes_
);
145 // Form the freelist by linking the next_ pointers together.
146 for (size_t j
= 1; j
< size
; ++j
)
147 this->preallocated_nodes_
[j
- 1].set_next (&this->preallocated_nodes_
[j
]);
149 // NULL-terminate the freelist.
150 this->preallocated_nodes_
[size
- 1].set_next (0);
152 // Assign the freelist pointer to the front of the list.
153 this->preallocated_nodes_freelist_
=
154 &this->preallocated_nodes_
[0];
158 HEAP_ITERATOR (*this));
161 // Note that timer_ids_curr_ and timer_ids_min_free_ both start at 0.
162 // Since timer IDs are assigned by first incrementing the timer_ids_curr_
163 // value, the first ID assigned will be 1 (just as in the previous design).
164 // When it's time to wrap, the next ID given out will be 0.
165 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
166 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::ACE_Timer_Heap_T (
167 FUNCTOR
*upcall_functor
,
168 ACE_Free_List
<ACE_Timer_Node_T
<TYPE
> > *freelist
,
169 TIME_POLICY
const & time_policy
)
170 : Base_Time_Policy (upcall_functor
,
173 max_size_ (ACE_DEFAULT_TIMERS
),
177 timer_ids_min_free_ (0),
178 preallocated_nodes_ (0),
179 preallocated_nodes_freelist_ (0)
181 ACE_TRACE ("ACE_Timer_Heap_T::ACE_Timer_Heap_T");
183 // Possibly reduce size to fit in a long.
184 if (this->max_size_
> static_cast<size_t> (ACE_Numeric_Limits
<long>::max ()))
185 this->max_size_
= static_cast<size_t> (ACE_Numeric_Limits
<long>::max ());
187 // Create the heap array.
188 #if defined (ACE_HAS_ALLOC_HOOKS)
189 this->heap_
= reinterpret_cast<ACE_Timer_Node_T
<TYPE
> **>
190 (ACE_Allocator::instance ()->malloc (sizeof (ACE_Timer_Node_T
<TYPE
> *) * this->max_size_
));
192 ACE_NEW (this->heap_
,
193 ACE_Timer_Node_T
<TYPE
> *[this->max_size_
]);
194 #endif /* ACE_HAS_ALLOC_HOOKS */
196 // Create the parallel array.
197 #if defined (ACE_HAS_ALLOC_HOOKS)
198 this->timer_ids_
= reinterpret_cast<ssize_t
*>
199 (ACE_Allocator::instance ()->malloc (sizeof (ssize_t
) * this->max_size_
));
201 ACE_NEW (this->timer_ids_
,
202 ssize_t
[this->max_size_
]);
203 #endif /* ACE_HAS_ALLOC_HOOKS */
205 // Initialize the "freelist," which uses negative values to
206 // distinguish freelist elements from "pointers" into the <heap_>
208 for (size_t i
= 0; i
< this->max_size_
; ++i
)
209 this->timer_ids_
[i
] = -1;
212 HEAP_ITERATOR (*this));
215 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
216 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::~ACE_Timer_Heap_T ()
218 ACE_TRACE ("ACE_Timer_Heap_T::~ACE_Timer_Heap_T");
224 #if defined (ACE_HAS_ALLOC_HOOKS)
226 (ACE_Allocator::instance ()->free (this->heap_
));
228 delete [] this->heap_
;
229 #endif /* ACE_HAS_ALLOC_HOOKS */
231 #if defined (ACE_HAS_ALLOC_HOOKS)
232 if (this->timer_ids_
)
233 (ACE_Allocator::instance ()->free (this->timer_ids_
));
235 delete [] this->timer_ids_
;
236 #endif /* ACE_HAS_ALLOC_HOOKS */
238 // clean up any preallocated timer nodes
239 if (preallocated_nodes_
!= 0)
241 ACE_Unbounded_Set_Iterator
<ACE_Timer_Node_T
<TYPE
> *>
242 set_iterator (this->preallocated_node_set_
);
244 for (ACE_Timer_Node_T
<TYPE
> **entry
= 0;
245 set_iterator
.next (entry
) !=0;
246 set_iterator
.advance ())
251 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
> int
252 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::close ()
254 ACE_TRACE ("ACE_Timer_Heap_T::close");
256 size_t current_size
=
259 // Clean up all the nodes still in the queue
260 for (size_t i
= 0; i
< current_size
; ++i
)
262 // Grab the event_handler and act, then delete the node before calling
263 // back to the handler. Prevents a handler from trying to cancel_timer()
264 // inside handle_close(), ripping the current timer node out from
266 TYPE eh
= this->heap_
[i
]->get_type ();
267 const void *act
= this->heap_
[i
]->get_act ();
268 this->free_node (this->heap_
[i
]);
269 this->upcall_functor ().deletion (*this, eh
, act
);
272 // leave the rest to the destructor
276 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
278 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::pop_freelist ()
280 ACE_TRACE ("ACE_Timer_Heap_T::pop_freelist");
282 // Scan for a free timer ID. Note that since this function is called
283 // _after_ the check for a full timer heap, we are guaranteed to find
284 // a free ID, even if we need to wrap around and start reusing freed IDs.
285 // On entry, the curr_ index is at the previous ID given out; start
286 // up where we left off last time.
287 // NOTE - a timer_ids_ slot with -2 is out of the heap, but not freed.
288 // It must be either freed (free_node) or rescheduled (reschedule).
289 ++this->timer_ids_curr_
;
290 while (this->timer_ids_curr_
< this->max_size_
&&
291 (this->timer_ids_
[this->timer_ids_curr_
] >= 0 ||
292 this->timer_ids_
[this->timer_ids_curr_
] == -2 ))
293 ++this->timer_ids_curr_
;
294 if (this->timer_ids_curr_
== this->max_size_
)
296 ACE_ASSERT (this->timer_ids_min_free_
< this->max_size_
);
297 this->timer_ids_curr_
= this->timer_ids_min_free_
;
298 // We restarted the free search at min. Since min won't be
299 // free anymore, and curr_ will just keep marching up the list
300 // on each successive need for an ID, reset min_free_ to the
301 // size of the list until an ID is freed that curr_ has already
302 // gone past (see push_freelist).
303 this->timer_ids_min_free_
= this->max_size_
;
306 return static_cast<long> (this->timer_ids_curr_
);
309 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
311 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::push_freelist (long old_id
)
313 ACE_TRACE ("ACE_Timer_Heap_T::push_freelist");
315 // Since this ID has already been checked by one of the public
316 // functions, it's safe to cast it here.
317 size_t oldid
= static_cast<size_t> (old_id
);
319 // The freelist values in the <timer_ids_> are negative, so set the
320 // freed entry back to 'free'. If this is the new lowest value free
321 // timer ID that curr_ won't see on it's normal march through the list,
323 ACE_ASSERT (this->timer_ids_
[oldid
] >= 0 || this->timer_ids_
[oldid
] == -2);
324 if (this->timer_ids_
[oldid
] == -2)
328 this->timer_ids_
[oldid
] = -1;
329 if (oldid
< this->timer_ids_min_free_
&& oldid
<= this->timer_ids_curr_
)
330 this->timer_ids_min_free_
= oldid
;
334 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
336 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::timer_id ()
338 ACE_TRACE ("ACE_Timer_Heap_T::timer_id");
340 // Return the next item off the freelist and use it as the timer id.
341 return this->pop_freelist ();
344 // Checks if queue is empty.
346 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
348 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::is_empty () const
350 ACE_TRACE ("ACE_Timer_Heap_T::is_empty");
352 return this->cur_size_
== 0;
355 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
356 ACE_Timer_Queue_Iterator_T
<TYPE
> &
357 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::iter ()
359 this->iterator_
->first ();
360 return *this->iterator_
;
363 // Returns earliest time in a non-empty queue.
365 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
> const ACE_Time_Value
&
366 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::earliest_time () const
368 ACE_TRACE ("ACE_Timer_Heap_T::earliest_time");
369 return this->heap_
[0]->get_timer_value ();
372 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
374 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::dump () const
376 #if defined (ACE_HAS_DUMP)
377 ACE_TRACE ("ACE_Timer_Heap_T::dump");
378 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
380 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("\nmax_size_ = %d"), this->max_size_
));
381 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("\ncur_size_ = %d"), this->cur_size_
));
382 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("\ncur_limbo_= %d"), this->cur_limbo_
));
383 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("\nids_curr_ = %d"),
384 this->timer_ids_curr_
));
385 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("\nmin_free_ = %d"),
386 this->timer_ids_min_free_
));
388 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("\nheap_ =\n")));
390 for (size_t i
= 0; i
< this->cur_size_
; ++i
)
392 ACELIB_DEBUG ((LM_DEBUG
,
395 this->heap_
[i
]->dump ();
398 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("\ntimer_ids_ =\n")));
400 for (size_t j
= 0; j
< this->max_size_
; ++j
)
401 ACELIB_DEBUG ((LM_DEBUG
,
402 ACE_TEXT ("%d\t%d\n"),
404 this->timer_ids_
[j
]));
406 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
407 #endif /* ACE_HAS_DUMP */
410 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
412 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::copy (
414 ACE_Timer_Node_T
<TYPE
> *moved_node
)
416 // Insert <moved_node> into its new location in the heap.
417 this->heap_
[slot
] = moved_node
;
419 ACE_ASSERT (moved_node
->get_timer_id () >= 0
420 && moved_node
->get_timer_id () < (int) this->max_size_
);
422 // Update the corresponding slot in the parallel <timer_ids_> array.
423 this->timer_ids_
[moved_node
->get_timer_id ()] = static_cast<ssize_t
> (slot
);
426 // Remove the slot'th timer node from the heap, but do not reclaim its
427 // timer ID or change the size of this timer heap object. The caller of
428 // this function must call either free_node (to reclaim the timer ID
429 // and the timer node memory, as well as decrement the size of the queue)
430 // or reschedule (to reinsert the node in the heap at a new time).
431 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
432 ACE_Timer_Node_T
<TYPE
> *
433 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::remove (size_t slot
)
435 ACE_Timer_Node_T
<TYPE
> *removed_node
=
438 // NOTE - the cur_size_ is being decremented since the queue has one
439 // less active timer in it. However, this ACE_Timer_Node is not being
440 // freed, and there is still a place for it in timer_ids_ (the timer ID
441 // is not being relinquished). The node can still be rescheduled, or
442 // it can be freed via free_node.
445 // Only try to reheapify if we're not deleting the last entry.
447 if (slot
< this->cur_size_
)
449 ACE_Timer_Node_T
<TYPE
> *moved_node
=
450 this->heap_
[this->cur_size_
];
452 // Move the end node to the location being removed and update
453 // the corresponding slot in the parallel <timer_ids> array.
454 this->copy (slot
, moved_node
);
456 // If the <moved_node->time_value_> is great than or equal its
457 // parent it needs be moved down the heap.
458 size_t parent
= ACE_HEAP_PARENT (slot
);
460 if (moved_node
->get_timer_value ()
461 >= this->heap_
[parent
]->get_timer_value ())
462 this->reheap_down (moved_node
,
464 ACE_HEAP_LCHILD (slot
));
466 this->reheap_up (moved_node
,
471 this->timer_ids_
[removed_node
->get_timer_id ()] = -2;
476 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
> void
477 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::reheap_down (
478 ACE_Timer_Node_T
<TYPE
> *moved_node
,
482 // Restore the heap property after a deletion.
484 while (child
< this->cur_size_
)
486 // Choose the smaller of the two children.
487 if (child
+ 1 < this->cur_size_
488 && this->heap_
[child
+ 1]->get_timer_value ()
489 < this->heap_
[child
]->get_timer_value ())
492 // Perform a <copy> if the child has a larger timeout value than
494 if (this->heap_
[child
]->get_timer_value ()
495 < moved_node
->get_timer_value ())
500 child
= ACE_HEAP_LCHILD (child
);
503 // We've found our location in the heap.
507 this->copy (slot
, moved_node
);
510 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
512 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::reheap_up (
513 ACE_Timer_Node_T
<TYPE
> *moved_node
,
517 // Restore the heap property after an insertion.
521 // If the parent node is greater than the <moved_node> we need
523 if (moved_node
->get_timer_value ()
524 < this->heap_
[parent
]->get_timer_value ())
526 this->copy (slot
, this->heap_
[parent
]);
528 parent
= ACE_HEAP_PARENT (slot
);
534 // Insert the new node into its proper resting place in the heap and
535 // update the corresponding slot in the parallel <timer_ids> array.
540 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
542 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::insert (
543 ACE_Timer_Node_T
<TYPE
> *new_node
)
545 if (this->cur_size_
+ this->cur_limbo_
+ 2 >= this->max_size_
)
548 this->reheap_up (new_node
,
550 ACE_HEAP_PARENT (this->cur_size_
));
554 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
556 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::grow_heap ()
558 // All the containers will double in size from max_size_.
559 size_t new_size
= this->max_size_
* 2;
561 // First grow the heap itself.
562 ACE_Timer_Node_T
<TYPE
> **new_heap
= 0;
564 #if defined (ACE_HAS_ALLOC_HOOKS)
565 new_heap
= reinterpret_cast<ACE_Timer_Node_T
<TYPE
> **>
566 (ACE_Allocator::instance ()->malloc (sizeof (ACE_Timer_Node_T
<TYPE
> *) * new_size
));
569 ACE_Timer_Node_T
<TYPE
> *[new_size
]);
570 #endif /* ACE_HAS_ALLOC_HOOKS */
572 ACE_OS::memcpy (new_heap
,
574 this->max_size_
* sizeof *new_heap
);
576 #if defined (ACE_HAS_ALLOC_HOOKS)
577 ACE_Allocator::instance ()->free (this->heap_
);
579 delete [] this->heap_
;
580 #endif /* ACE_HAS_ALLOC_HOOKS */
582 this->heap_
= new_heap
;
584 // Grow the array of timer ids.
586 ssize_t
*new_timer_ids
= 0;
588 #if defined (ACE_HAS_ALLOC_HOOKS)
589 new_timer_ids
= reinterpret_cast<ssize_t
*>
590 (ACE_Allocator::instance ()->malloc (sizeof (ssize_t
) * new_size
));
592 ACE_NEW (new_timer_ids
,
594 #endif /* ACE_HAS_ALLOC_HOOKS */
596 ACE_OS::memcpy (new_timer_ids
,
598 this->max_size_
* sizeof (ssize_t
));
600 #if defined (ACE_HAS_ALLOC_HOOKS)
601 if (this->timer_ids_
)
602 (ACE_Allocator::instance ()->free (this->timer_ids_
));
604 delete [] this->timer_ids_
;
605 #endif /* ACE_HAS_ALLOC_HOOKS */
606 this->timer_ids_
= new_timer_ids
;
608 // And add the new elements to the end of the "freelist".
609 for (size_t i
= this->max_size_
; i
< new_size
; ++i
)
610 this->timer_ids_
[i
] = -(static_cast<ssize_t
> (i
) + 1);
612 // Grow the preallocation array (if using preallocation)
613 if (this->preallocated_nodes_
!= 0)
615 // Create a new array with max_size elements to link in to
617 ACE_NEW (this->preallocated_nodes_
,
618 ACE_Timer_Node_T
<TYPE
>[this->max_size_
]);
620 // Add it to the set for later deletion
621 this->preallocated_node_set_
.insert (this->preallocated_nodes_
);
623 // Link new nodes together (as for original list).
624 for (size_t k
= 1; k
< this->max_size_
; ++k
)
625 this->preallocated_nodes_
[k
- 1].set_next (&this->preallocated_nodes_
[k
]);
627 // NULL-terminate the new list.
628 this->preallocated_nodes_
[this->max_size_
- 1].set_next (0);
630 // Link new array to the end of the existling list.
631 if (this->preallocated_nodes_freelist_
== 0)
632 this->preallocated_nodes_freelist_
=
633 &preallocated_nodes_
[0];
636 ACE_Timer_Node_T
<TYPE
> *previous
=
637 this->preallocated_nodes_freelist_
;
639 for (ACE_Timer_Node_T
<TYPE
> *current
= this->preallocated_nodes_freelist_
->get_next ();
641 current
= current
->get_next ())
644 previous
->set_next (&this->preallocated_nodes_
[0]);
648 this->max_size_
= new_size
;
649 // Force rescan of list from beginning for a free slot (I think...)
650 // This fixed Bugzilla #2447.
651 this->timer_ids_min_free_
= this->max_size_
;
654 // Reschedule a periodic timer. This function must be called with the
657 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
659 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::reschedule (
660 ACE_Timer_Node_T
<TYPE
> *expired
)
662 ACE_TRACE ("ACE_Timer_Heap_T::reschedule");
664 // If we are rescheduling, then the most recent call was to
665 // remove_first (). That called remove () to remove the node from the
666 // heap, but did not free the timer ID. The ACE_Timer_Node still has
667 // its assigned ID - just needs to be inserted at the new proper
668 // place, and the heap restored properly.
669 if (this->timer_ids_
[expired
->get_timer_id ()] == -2)
671 this->insert (expired
);
674 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
675 ACE_Timer_Node_T
<TYPE
> *
676 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::alloc_node ()
678 ACE_Timer_Node_T
<TYPE
> *temp
= 0;
680 // Only allocate a node if we are *not* using the preallocated heap.
681 if (this->preallocated_nodes_
== 0)
682 ACE_NEW_RETURN (temp
,
683 ACE_Timer_Node_T
<TYPE
>,
687 // check to see if the heap needs to grow
688 if (this->preallocated_nodes_freelist_
== 0)
691 temp
= this->preallocated_nodes_freelist_
;
693 if (this->preallocated_nodes_freelist_
)
695 // Remove the first element from the freelist.
696 this->preallocated_nodes_freelist_
=
697 this->preallocated_nodes_freelist_
->get_next ();
703 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
705 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::free_node (
706 ACE_Timer_Node_T
<TYPE
> *node
)
708 // Return this timer id to the freelist.
709 this->push_freelist (node
->get_timer_id ());
711 // Only free up a node if we are *not* using the preallocated heap.
712 if (this->preallocated_nodes_
== 0)
716 node
->set_next (this->preallocated_nodes_freelist_
);
717 this->preallocated_nodes_freelist_
= node
;
721 // Insert a new timer that expires at time future_time; if interval is
722 // > 0, the handler will be reinvoked periodically.
724 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
726 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::schedule_i (
729 const ACE_Time_Value
&future_time
,
730 const ACE_Time_Value
&interval
)
732 ACE_TRACE ("ACE_Timer_Heap_T::schedule_i");
734 if ((this->cur_size_
+ this->cur_limbo_
) < this->max_size_
)
736 // Obtain the next unique sequence number.
737 long const timer_id
= this->timer_id ();
739 // Obtain the memory to the new node.
740 ACE_Timer_Node_T
<TYPE
> *temp
= 0;
742 ACE_ALLOCATOR_RETURN (temp
,
759 // Locate and remove the single timer with a value of @a timer_id from
762 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
764 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::cancel (long timer_id
,
768 ACE_TRACE ("ACE_Timer_Heap_T::cancel");
769 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK
, ace_mon
, this->mutex_
, -1));
771 // Locate the ACE_Timer_Node that corresponds to the timer_id.
773 // Check to see if the timer_id is out of range
775 || (size_t) timer_id
> this->max_size_
)
778 ssize_t timer_node_slot
= this->timer_ids_
[timer_id
];
780 // Check to see if timer_id is still valid.
781 if (timer_node_slot
< 0)
784 if (timer_id
!= this->heap_
[timer_node_slot
]->get_timer_id ())
786 ACE_ASSERT (timer_id
== this->heap_
[timer_node_slot
]->get_timer_id ());
791 ACE_Timer_Node_T
<TYPE
> *temp
=
792 this->remove (timer_node_slot
);
794 // Call the close hooks.
797 // cancel_type() called once per <type>.
798 this->upcall_functor ().cancel_type (*this,
803 // cancel_timer() called once per <timer>.
804 this->upcall_functor ().cancel_timer (*this,
810 *act
= temp
->get_act ();
812 this->free_node (temp
);
817 // Locate and update the inteval on the timer_id
819 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
821 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::reset_interval (long timer_id
,
822 const ACE_Time_Value
&interval
)
824 ACE_TRACE ("ACE_Timer_Heap_T::reset_interval");
825 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK
, ace_mon
, this->mutex_
, -1));
827 // Locate the ACE_Timer_Node that corresponds to the timer_id.
829 // Check to see if the timer_id is out of range
831 || (size_t) timer_id
> this->max_size_
)
834 ssize_t timer_node_slot
= this->timer_ids_
[timer_id
];
836 // Check to see if timer_id is still valid.
837 if (timer_node_slot
< 0)
840 if (timer_id
!= this->heap_
[timer_node_slot
]->get_timer_id ())
842 ACE_ASSERT (timer_id
== this->heap_
[timer_node_slot
]->get_timer_id ());
847 // Reset the timer interval
848 this->heap_
[timer_node_slot
]->set_interval (interval
);
853 // Locate and remove all values of @a type from the timer queue.
855 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
857 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::cancel (const TYPE
&type
,
860 ACE_TRACE ("ACE_Timer_Heap_T::cancel");
862 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK
, ace_mon
, this->mutex_
, -1));
864 int number_of_cancellations
= 0;
866 // Try to locate the ACE_Timer_Node that matches the timer_id.
868 for (size_t i
= 0; i
< this->cur_size_
; )
870 if (this->heap_
[i
]->get_type () == type
)
872 ACE_Timer_Node_T
<TYPE
> *temp
= this->remove (i
);
874 ++number_of_cancellations
;
876 this->free_node (temp
);
878 // We reset to zero so that we don't miss checking any nodes
879 // if a reheapify occurs when a node is removed. There
880 // may be a better fix than this, however.
887 // Call the close hooks.
890 // cancel_type() called once per <type>.
891 this->upcall_functor ().cancel_type (*this,
897 j
< number_of_cancellations
;
900 // cancel_timer() called once per <timer>.
901 this->upcall_functor ().cancel_timer (*this,
907 return number_of_cancellations
;
910 // Returns the earliest node or returns 0 if the heap is empty.
912 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
913 ACE_Timer_Node_T
<TYPE
> *
914 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::remove_first ()
916 ACE_TRACE ("ACE_Timer_Heap_T::remove_first");
918 if (this->cur_size_
== 0)
921 return this->remove (0);
924 template <class TYPE
, class FUNCTOR
, class ACE_LOCK
, typename TIME_POLICY
>
925 ACE_Timer_Node_T
<TYPE
> *
926 ACE_Timer_Heap_T
<TYPE
, FUNCTOR
, ACE_LOCK
, TIME_POLICY
>::get_first ()
928 ACE_TRACE ("ACE_Timer_Heap_T::get_first");
930 return this->cur_size_
== 0 ? 0 : this->heap_
[0];
933 ACE_END_VERSIONED_NAMESPACE_DECL
935 #endif /* ACE_TIMER_HEAP_T_CPP */