Timer_Heap_T.cpp

Go to the documentation of this file.
00001 // $Id: Timer_Heap_T.cpp 80826 2008-03-04 14:51:23Z wotte $
00002 
00003 #ifndef ACE_TIMER_HEAP_T_CPP
00004 #define ACE_TIMER_HEAP_T_CPP
00005 
00006 #include "ace/Timer_Heap_T.h"
00007 #include "ace/Log_Msg.h"
00008 #include "ace/Guard_T.h"
00009 #include "ace/OS_NS_errno.h"
00010 #include "ace/OS_NS_string.h"
00011 #include "ace/Numeric_Limits.h"
00012 
00013 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00014 # pragma once
00015 #endif /* ACE_LACKS_PRAGMA_ONCE */
00016 
00017 /*
00018 ** The ACE_Timer_Heap::max_size_ and array loops, checks, etc. are all size_t.
00019 ** The timer IDs are long, and since they are indices into the heap, we need
00020 ** to be sure that the timer heap size can fit in a long. Hence, when size
00021 ** is (re)set, limit it to the maximum long value. We use the C++ standard
00022 ** limits if available.
00023 */
00024 
00025 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00026 
00027 // Define some simple inlined functions to clarify the code.
00028 inline size_t
00029 ACE_HEAP_PARENT (size_t X)
00030 {
00031   return (X == 0 ? 0 : ((X - 1) / 2));
00032 }
00033 
00034 inline size_t
00035 ACE_HEAP_LCHILD (size_t X)
00036 {
00037   return X + X + 1;
00038 }
00039 
00040 // Constructor that takes in an <ACE_Timer_Heap_T> to iterate over.
00041 
00042 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00043 ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Heap_Iterator_T (
00044   ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK> &heap)
00045   : timer_heap_ (heap)
00046 {
00047   ACE_TRACE ("ACE_Timer_Heap_Iterator_T::ACE_Timer_Heap_Iterator");
00048   this->first ();
00049 }
00050 
00051 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00052 ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::~ACE_Timer_Heap_Iterator_T (void)
00053 {
00054 }
00055 
00056 // Positions the iterator at the first node in the heap array
00057 
00058 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00059 void
00060 ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::first (void)
00061 {
00062   this->position_ = 0;
00063 }
00064 
00065 // Positions the iterator at the next node in the heap array
00066 
00067 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00068 void
00069 ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::next (void)
00070 {
00071   if (this->position_ != this->timer_heap_.cur_size_)
00072     ++this->position_;
00073 }
00074 
00075 // Returns true the <position_> is at the end of the heap array
00076 
00077 template <class TYPE, class FUNCTOR, class ACE_LOCK> bool
00078 ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::isdone (void) const
00079 {
00080   return this->position_ == this->timer_heap_.cur_size_;
00081 }
00082 
00083 // Returns the node at the current position in the heap or 0 if at the end
00084 
00085 template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
00086 ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::item (void)
00087 {
00088   if (this->position_ != this->timer_heap_.cur_size_)
00089     return this->timer_heap_.heap_[this->position_];
00090   return 0;
00091 }
00092 
00093 // Constructor
00094 // Note that timer_ids_curr_ and timer_ids_min_free_ both start at 0.
00095 // Since timer IDs are assigned by first incrementing the timer_ids_curr_
00096 // value, the first ID assigned will be 1 (just as in the previous design).
00097 // When it's time to wrap, the next ID given out will be 0.
00098 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00099 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Heap_T (
00100   size_t size,
00101   bool preallocated,
00102   FUNCTOR *upcall_functor,
00103   ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist)
00104   : ACE_Timer_Queue_T<TYPE,FUNCTOR,ACE_LOCK> (upcall_functor, freelist),
00105     max_size_ (size),
00106     cur_size_ (0),
00107     cur_limbo_ (0),
00108     timer_ids_curr_ (0),
00109     timer_ids_min_free_ (0),
00110     preallocated_nodes_ (0),
00111     preallocated_nodes_freelist_ (0)
00112 {
00113   ACE_TRACE ("ACE_Timer_Heap_T::ACE_Timer_Heap_T");
00114 
00115   // Possibly reduce size to fit in a long.
00116   if (size > static_cast<size_t> (ACE_Numeric_Limits<long>::max ()))
00117     {
00118       size = static_cast<size_t> (ACE_Numeric_Limits<long>::max ());
00119       this->max_size_ = size;
00120     }
00121 
00122   // Create the heap array.
00123   ACE_NEW (this->heap_,
00124            ACE_Timer_Node_T<TYPE> *[size]);
00125 
00126   // Create the parallel
00127   ACE_NEW (this->timer_ids_,
00128            ssize_t[size]);
00129 
00130   // Initialize the "freelist," which uses negative values to
00131   // distinguish freelist elements from "pointers" into the <heap_>
00132   // array.
00133   for (size_t i = 0; i < size; ++i)
00134     this->timer_ids_[i] = -1;
00135 
00136   if (preallocated)
00137     {
00138       ACE_NEW (this->preallocated_nodes_,
00139                ACE_Timer_Node_T<TYPE>[size]);
00140 
00141       // Add allocated array to set of such arrays for deletion on
00142       // cleanup.
00143       this->preallocated_node_set_.insert (this->preallocated_nodes_);
00144 
00145       // Form the freelist by linking the next_ pointers together.
00146       for (size_t j = 1; j < size; ++j)
00147         this->preallocated_nodes_[j - 1].set_next (&this->preallocated_nodes_[j]);
00148 
00149       // NULL-terminate the freelist.
00150       this->preallocated_nodes_[size - 1].set_next (0);
00151 
00152       // Assign the freelist pointer to the front of the list.
00153       this->preallocated_nodes_freelist_ =
00154         &this->preallocated_nodes_[0];
00155     }
00156 
00157   ACE_NEW (iterator_,
00158            HEAP_ITERATOR (*this));
00159 }
00160 
00161 // Note that timer_ids_curr_ and timer_ids_min_free_ both start at 0.
00162 // Since timer IDs are assigned by first incrementing the timer_ids_curr_
00163 // value, the first ID assigned will be 1 (just as in the previous design).
00164 // When it's time to wrap, the next ID given out will be 0.
00165 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00166 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Heap_T (
00167   FUNCTOR *upcall_functor,
00168   ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist)
00169   : ACE_Timer_Queue_T<TYPE,FUNCTOR,ACE_LOCK> (upcall_functor, freelist),
00170     max_size_ (ACE_DEFAULT_TIMERS),
00171     cur_size_ (0),
00172     cur_limbo_ (0),
00173     timer_ids_curr_ (0),
00174     timer_ids_min_free_ (0),
00175     preallocated_nodes_ (0),
00176     preallocated_nodes_freelist_ (0)
00177 {
00178   ACE_TRACE ("ACE_Timer_Heap_T::ACE_Timer_Heap_T");
00179 
00180   // Possibly reduce size to fit in a long.
00181   if (this->max_size_ > static_cast<size_t> (ACE_Numeric_Limits<long>::max ()))
00182     this->max_size_ = static_cast<size_t> (ACE_Numeric_Limits<long>::max ());
00183 
00184   // Create the heap array.
00185     ACE_NEW (this->heap_,
00186              ACE_Timer_Node_T<TYPE> *[this->max_size_]);
00187 
00188   // Create the parallel array.
00189   ACE_NEW (this->timer_ids_,
00190            ssize_t[this->max_size_]);
00191 
00192   // Initialize the "freelist," which uses negative values to
00193   // distinguish freelist elements from "pointers" into the <heap_>
00194   // array.
00195   for (size_t i = 0; i < this->max_size_; ++i)
00196     this->timer_ids_[i] = -1;
00197 
00198   ACE_NEW (iterator_,
00199            HEAP_ITERATOR (*this));
00200 }
00201 
00202 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00203 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::~ACE_Timer_Heap_T (void)
00204 {
00205   ACE_TRACE ("ACE_Timer_Heap_T::~ACE_Timer_Heap_T");
00206 
00207   delete iterator_;
00208 
00209   size_t current_size =
00210     this->cur_size_;
00211 
00212   // Clean up all the nodes still in the queue
00213   for (size_t i = 0; i < current_size; ++i)
00214     {
00215       // Grab the event_handler and act, then delete the node before calling
00216       // back to the handler. Prevents a handler from trying to cancel_timer()
00217       // inside handle_close(), ripping the current timer node out from
00218       // under us.
00219       TYPE eh = this->heap_[i]->get_type ();
00220       const void *act = this->heap_[i]->get_act ();
00221       this->free_node (this->heap_[i]);
00222       this->upcall_functor ().deletion (*this, eh, act);
00223     }
00224 
00225   delete [] this->heap_;
00226   delete [] this->timer_ids_;
00227 
00228   // clean up any preallocated timer nodes
00229   if (preallocated_nodes_ != 0)
00230     {
00231       ACE_Unbounded_Set_Iterator<ACE_Timer_Node_T<TYPE> *>
00232         set_iterator (this->preallocated_node_set_);
00233 
00234       for (ACE_Timer_Node_T<TYPE> **entry = 0;
00235            set_iterator.next (entry) !=0;
00236            set_iterator.advance ())
00237         delete [] *entry;
00238     }
00239 }
00240 
00241 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00242 long
00243 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::pop_freelist (void)
00244 {
00245   ACE_TRACE ("ACE_Timer_Heap_T::pop_freelist");
00246 
00247   // Scan for a free timer ID. Note that since this function is called
00248   // _after_ the check for a full timer heap, we are guaranteed to find
00249   // a free ID, even if we need to wrap around and start reusing freed IDs.
00250   // On entry, the curr_ index is at the previous ID given out; start
00251   // up where we left off last time.
00252   // NOTE - a timer_ids_ slot with -2 is out of the heap, but not freed.
00253   // It must be either freed (free_node) or rescheduled (reschedule).
00254   ++this->timer_ids_curr_;
00255   while (this->timer_ids_curr_ < this->max_size_ &&
00256          (this->timer_ids_[this->timer_ids_curr_] >= 0 ||
00257           this->timer_ids_[this->timer_ids_curr_] == -2  ))
00258     ++this->timer_ids_curr_;
00259   if (this->timer_ids_curr_ == this->max_size_)
00260     {
00261       ACE_ASSERT (this->timer_ids_min_free_ < this->max_size_);
00262       this->timer_ids_curr_ = this->timer_ids_min_free_;
00263       // We restarted the free search at min. Since min won't be
00264       // free anymore, and curr_ will just keep marching up the list
00265       // on each successive need for an ID, reset min_free_ to the
00266       // size of the list until an ID is freed that curr_ has already
00267       // gone past (see push_freelist).
00268       this->timer_ids_min_free_ = this->max_size_;
00269     }
00270 
00271   return static_cast<long> (this->timer_ids_curr_);
00272 }
00273 
00274 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00275 void
00276 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::push_freelist (long old_id)
00277 {
00278   ACE_TRACE ("ACE_Timer_Heap_T::push_freelist");
00279 
00280   // Since this ID has already been checked by one of the public
00281   // functions, it's safe to cast it here.
00282   size_t oldid = static_cast<size_t> (old_id);
00283 
00284   // The freelist values in the <timer_ids_> are negative, so set the
00285   // freed entry back to 'free'. If this is the new lowest value free
00286   // timer ID that curr_ won't see on it's normal march through the list,
00287   // remember it.
00288   ACE_ASSERT (this->timer_ids_[oldid] >= 0 || this->timer_ids_[oldid] == -2);
00289   if (this->timer_ids_[oldid] == -2)
00290     --this->cur_limbo_;
00291   else
00292     --this->cur_size_;
00293   this->timer_ids_[oldid] = -1;
00294   if (oldid < this->timer_ids_min_free_ && oldid <= this->timer_ids_curr_)
00295     this->timer_ids_min_free_ = oldid;
00296   return;
00297 }
00298 
00299 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00300 long
00301 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::timer_id (void)
00302 {
00303   ACE_TRACE ("ACE_Timer_Heap_T::timer_id");
00304 
00305   // Return the next item off the freelist and use it as the timer id.
00306   return this->pop_freelist ();
00307 }
00308 
00309 // Checks if queue is empty.
00310 
00311 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00312 bool
00313 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::is_empty (void) const
00314 {
00315   ACE_TRACE ("ACE_Timer_Heap_T::is_empty");
00316   return this->cur_size_ == 0;
00317 }
00318 
00319 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00320 ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> &
00321 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::iter (void)
00322 {
00323   this->iterator_->first ();
00324   return *this->iterator_;
00325 }
00326 
00327 // Returns earliest time in a non-empty queue.
00328 
00329 template <class TYPE, class FUNCTOR, class ACE_LOCK> const ACE_Time_Value &
00330 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::earliest_time (void) const
00331 {
00332   ACE_TRACE ("ACE_Timer_Heap_T::earliest_time");
00333   return this->heap_[0]->get_timer_value ();
00334 }
00335 
00336 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00337 void
00338 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::dump (void) const
00339 {
00340 #if defined (ACE_HAS_DUMP)
00341   ACE_TRACE ("ACE_Timer_Heap_T::dump");
00342   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00343 
00344   ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nmax_size_ = %d"), this->max_size_));
00345   ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ncur_size_ = %d"), this->cur_size_));
00346   ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ncur_limbo_= %d"), this->cur_limbo_));
00347   ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nids_curr_ = %d"),
00348               this->timer_ids_curr_));
00349   ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nmin_free_ = %d"),
00350               this->timer_ids_min_free_));
00351 
00352   ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nheap_ = \n")));
00353 
00354   for (size_t i = 0; i < this->cur_size_; ++i)
00355     {
00356       ACE_DEBUG ((LM_DEBUG,
00357                   ACE_TEXT ("%d\n"),
00358                   i));
00359       this->heap_[i]->dump ();
00360     }
00361 
00362   ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntimer_ids_ = \n")));
00363 
00364   for (size_t j = 0; j < this->max_size_; ++j)
00365     ACE_DEBUG ((LM_DEBUG,
00366                 ACE_TEXT ("%d\t%d\n"),
00367                 j,
00368                 this->timer_ids_[j]));
00369 
00370   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00371 #endif /* ACE_HAS_DUMP */
00372 }
00373 
00374 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00375 void
00376 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::copy (
00377   size_t slot,
00378   ACE_Timer_Node_T<TYPE> *moved_node)
00379 {
00380   // Insert <moved_node> into its new location in the heap.
00381   this->heap_[slot] = moved_node;
00382 
00383   ACE_ASSERT (moved_node->get_timer_id () >= 0
00384               && moved_node->get_timer_id () < (int) this->max_size_);
00385 
00386   // Update the corresponding slot in the parallel <timer_ids_> array.
00387   this->timer_ids_[moved_node->get_timer_id ()] = static_cast<ssize_t> (slot);
00388 }
00389 
00390 // Remove the slot'th timer node from the heap, but do not reclaim its
00391 // timer ID or change the size of this timer heap object. The caller of
00392 // this function must call either free_node (to reclaim the timer ID
00393 // and the timer node memory, as well as decrement the size of the queue)
00394 // or reschedule (to reinsert the node in the heap at a new time).
00395 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00396 ACE_Timer_Node_T<TYPE> *
00397 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::remove (size_t slot)
00398 {
00399   ACE_Timer_Node_T<TYPE> *removed_node =
00400     this->heap_[slot];
00401 
00402   // NOTE - the cur_size_ is being decremented since the queue has one
00403   // less active timer in it. However, this ACE_Timer_Node is not being
00404   // freed, and there is still a place for it in timer_ids_ (the timer ID
00405   // is not being relinquished). The node can still be rescheduled, or
00406   // it can be freed via free_node.
00407   --this->cur_size_;
00408 
00409   // Only try to reheapify if we're not deleting the last entry.
00410 
00411   if (slot < this->cur_size_)
00412     {
00413       ACE_Timer_Node_T<TYPE> *moved_node =
00414         this->heap_[this->cur_size_];
00415 
00416       // Move the end node to the location being removed and update
00417       // the corresponding slot in the parallel <timer_ids> array.
00418       this->copy (slot, moved_node);
00419 
00420       // If the <moved_node->time_value_> is great than or equal its
00421       // parent it needs be moved down the heap.
00422       size_t parent = ACE_HEAP_PARENT (slot);
00423 
00424       if (moved_node->get_timer_value ()
00425           >= this->heap_[parent]->get_timer_value ())
00426         this->reheap_down (moved_node,
00427                            slot,
00428                            ACE_HEAP_LCHILD (slot));
00429       else
00430         this->reheap_up (moved_node,
00431                          slot,
00432                          parent);
00433     }
00434 
00435   this->timer_ids_[removed_node->get_timer_id ()] = -2;
00436   ++this->cur_limbo_;
00437   return removed_node;
00438 }
00439 
00440 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00441 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::reheap_down (
00442   ACE_Timer_Node_T<TYPE> *moved_node,
00443   size_t slot,
00444   size_t child)
00445 {
00446   // Restore the heap property after a deletion.
00447 
00448   while (child < this->cur_size_)
00449     {
00450       // Choose the smaller of the two children.
00451       if (child + 1 < this->cur_size_
00452           && this->heap_[child + 1]->get_timer_value ()
00453           < this->heap_[child]->get_timer_value ())
00454         child++;
00455 
00456       // Perform a <copy> if the child has a larger timeout value than
00457       // the <moved_node>.
00458       if (this->heap_[child]->get_timer_value ()
00459           < moved_node->get_timer_value ())
00460         {
00461           this->copy (slot,
00462                       this->heap_[child]);
00463           slot = child;
00464           child = ACE_HEAP_LCHILD (child);
00465         }
00466       else
00467         // We've found our location in the heap.
00468         break;
00469     }
00470 
00471   this->copy (slot, moved_node);
00472 }
00473 
00474 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00475 void
00476 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::reheap_up (
00477   ACE_Timer_Node_T<TYPE> *moved_node,
00478   size_t slot,
00479   size_t parent)
00480 {
00481   // Restore the heap property after an insertion.
00482 
00483   while (slot > 0)
00484     {
00485       // If the parent node is greater than the <moved_node> we need
00486       // to copy it down.
00487       if (moved_node->get_timer_value ()
00488           < this->heap_[parent]->get_timer_value ())
00489         {
00490           this->copy (slot, this->heap_[parent]);
00491           slot = parent;
00492           parent = ACE_HEAP_PARENT (slot);
00493         }
00494       else
00495         break;
00496     }
00497 
00498   // Insert the new node into its proper resting place in the heap and
00499   // update the corresponding slot in the parallel <timer_ids> array.
00500   this->copy (slot,
00501               moved_node);
00502 }
00503 
00504 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00505 void
00506 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::insert (
00507   ACE_Timer_Node_T<TYPE> *new_node)
00508 {
00509   if (this->cur_size_ + this->cur_limbo_ + 2 >= this->max_size_)
00510     this->grow_heap ();
00511 
00512   this->reheap_up (new_node,
00513                    this->cur_size_,
00514                    ACE_HEAP_PARENT (this->cur_size_));
00515   this->cur_size_++;
00516 }
00517 
00518 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00519 void
00520 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::grow_heap (void)
00521 {
00522   // All the containers will double in size from max_size_.
00523   size_t new_size = this->max_size_ * 2;
00524 
00525 #if 0
00526   // Yikes - there's no way to flag a failure of going out of range of
00527   // a 'long' - this is a problem that should be addressed at some point.
00528   if (new_size > ACE_Numeric_Limits<long>::max ())
00529     new_size = ACE_Numeric_Limits<long>::max ();
00530 
00531   if (new_size <= this->max_size_)   // We are already at the limit
00532     {
00533       errno = ENOMEM;
00534       return -1;
00535     }
00536 #endif /* 0 */
00537 
00538    // First grow the heap itself.
00539 
00540   ACE_Timer_Node_T<TYPE> **new_heap = 0;
00541 
00542   ACE_NEW (new_heap,
00543            ACE_Timer_Node_T<TYPE> *[new_size]);
00544 
00545   ACE_OS::memcpy (new_heap,
00546                   this->heap_,
00547                   this->max_size_ * sizeof *new_heap);
00548   delete [] this->heap_;
00549   this->heap_ = new_heap;
00550 
00551   // Grow the array of timer ids.
00552 
00553   ssize_t *new_timer_ids = 0;
00554 
00555   ACE_NEW (new_timer_ids,
00556            ssize_t[new_size]);
00557 
00558   ACE_OS::memcpy (new_timer_ids,
00559                   this->timer_ids_,
00560                   this->max_size_ * sizeof (ssize_t));
00561 
00562   delete [] timer_ids_;
00563   this->timer_ids_ = new_timer_ids;
00564 
00565   // And add the new elements to the end of the "freelist".
00566   for (size_t i = this->max_size_; i < new_size; ++i)
00567     this->timer_ids_[i] = -(static_cast<ssize_t> (i) + 1);
00568 
00569    // Grow the preallocation array (if using preallocation)
00570   if (this->preallocated_nodes_ != 0)
00571     {
00572       // Create a new array with max_size elements to link in to
00573       // existing list.
00574       ACE_NEW (this->preallocated_nodes_,
00575                ACE_Timer_Node_T<TYPE>[this->max_size_]);
00576 
00577       // Add it to the set for later deletion
00578       this->preallocated_node_set_.insert (this->preallocated_nodes_);
00579 
00580       // Link new nodes together (as for original list).
00581       for (size_t k = 1; k < this->max_size_; ++k)
00582         this->preallocated_nodes_[k - 1].set_next (&this->preallocated_nodes_[k]);
00583 
00584       // NULL-terminate the new list.
00585       this->preallocated_nodes_[this->max_size_ - 1].set_next (0);
00586 
00587       // Link new array to the end of the existling list.
00588       if (this->preallocated_nodes_freelist_ == 0)
00589         this->preallocated_nodes_freelist_ =
00590           &preallocated_nodes_[0];
00591       else
00592         {
00593           ACE_Timer_Node_T<TYPE> *previous =
00594             this->preallocated_nodes_freelist_;
00595 
00596           for (ACE_Timer_Node_T<TYPE> *current = this->preallocated_nodes_freelist_->get_next ();
00597                current != 0;
00598                current = current->get_next ())
00599             previous = current;
00600 
00601           previous->set_next (&this->preallocated_nodes_[0]);
00602         }
00603     }
00604 
00605   this->max_size_ = new_size;
00606   // Force rescan of list from beginning for a free slot (I think...)
00607   // This fixed Bugzilla #2447.
00608   this->timer_ids_min_free_ = this->max_size_;
00609 }
00610 
00611 // Reschedule a periodic timer.  This function must be called with the
00612 // mutex lock held.
00613 
00614 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00615 void
00616 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::reschedule (
00617   ACE_Timer_Node_T<TYPE> *expired)
00618 {
00619   ACE_TRACE ("ACE_Timer_Heap_T::reschedule");
00620 
00621   // If we are rescheduling, then the most recent call was to
00622   // remove_first (). That called remove () to remove the node from the
00623   // heap, but did not free the timer ID. The ACE_Timer_Node still has
00624   // its assigned ID - just needs to be inserted at the new proper
00625   // place, and the heap restored properly.
00626   if (this->timer_ids_[expired->get_timer_id ()] == -2)
00627     --this->cur_limbo_;
00628   this->insert (expired);
00629 }
00630 
00631 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00632 ACE_Timer_Node_T<TYPE> *
00633 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::alloc_node (void)
00634 {
00635   ACE_Timer_Node_T<TYPE> *temp = 0;
00636 
00637   // Only allocate a node if we are *not* using the preallocated heap.
00638   if (this->preallocated_nodes_ == 0)
00639     ACE_NEW_RETURN (temp,
00640                     ACE_Timer_Node_T<TYPE>,
00641                     0);
00642   else
00643     {
00644       // check to see if the heap needs to grow
00645       if (this->preallocated_nodes_freelist_ == 0)
00646         this->grow_heap ();
00647 
00648       temp = this->preallocated_nodes_freelist_;
00649 
00650       // Remove the first element from the freelist.
00651       this->preallocated_nodes_freelist_ =
00652         this->preallocated_nodes_freelist_->get_next ();
00653     }
00654   return temp;
00655 }
00656 
00657 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00658 void
00659 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::free_node (
00660   ACE_Timer_Node_T<TYPE> *node)
00661 {
00662   // Return this timer id to the freelist.
00663   this->push_freelist (node->get_timer_id ());
00664 
00665   // Only free up a node if we are *not* using the preallocated heap.
00666   if (this->preallocated_nodes_ == 0)
00667     delete node;
00668   else
00669     {
00670       node->set_next (this->preallocated_nodes_freelist_);
00671       this->preallocated_nodes_freelist_ = node;
00672     }
00673 }
00674 
00675 // Insert a new timer that expires at time future_time; if interval is
00676 // > 0, the handler will be reinvoked periodically.
00677 
00678 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00679 long
00680 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::schedule_i (
00681   const TYPE &type,
00682   const void *act,
00683   const ACE_Time_Value &future_time,
00684   const ACE_Time_Value &interval)
00685 {
00686   ACE_TRACE ("ACE_Timer_Heap_T::schedule_i");
00687 
00688   if ((this->cur_size_ + this->cur_limbo_) < this->max_size_)
00689     {
00690       // Obtain the next unique sequence number.
00691       long timer_id = this->timer_id ();
00692 
00693       // Obtain the memory to the new node.
00694       ACE_Timer_Node_T<TYPE> *temp = 0;
00695 
00696       ACE_ALLOCATOR_RETURN (temp,
00697                             this->alloc_node (),
00698                             -1);
00699       temp->set (type,
00700                  act,
00701                  future_time,
00702                  interval,
00703                  0,
00704                  timer_id);
00705 
00706       this->insert (temp);
00707       return timer_id;
00708     }
00709   else
00710     return -1;
00711 }
00712 
00713 // Locate and remove the single timer with a value of @a timer_id from
00714 // the timer queue.
00715 
00716 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00717 int
00718 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (long timer_id,
00719                                                    const void **act,
00720                                                    int dont_call)
00721 {
00722   ACE_TRACE ("ACE_Timer_Heap_T::cancel");
00723   ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00724 
00725   // Locate the ACE_Timer_Node that corresponds to the timer_id.
00726 
00727   // Check to see if the timer_id is out of range
00728   if (timer_id < 0
00729       || (size_t) timer_id > this->max_size_)
00730     return 0;
00731 
00732   ssize_t timer_node_slot = this->timer_ids_[timer_id];
00733 
00734   // Check to see if timer_id is still valid.
00735   if (timer_node_slot < 0)
00736     return 0;
00737 
00738   if (timer_id != this->heap_[timer_node_slot]->get_timer_id ())
00739     {
00740       ACE_ASSERT (timer_id == this->heap_[timer_node_slot]->get_timer_id ());
00741       return 0;
00742     }
00743   else
00744     {
00745       ACE_Timer_Node_T<TYPE> *temp =
00746         this->remove (timer_node_slot);
00747 
00748       // Call the close hooks.
00749       int cookie = 0;
00750 
00751       // cancel_type() called once per <type>.
00752       this->upcall_functor ().cancel_type (*this,
00753                                            temp->get_type (),
00754                                            dont_call,
00755                                            cookie);
00756 
00757       // cancel_timer() called once per <timer>.
00758       this->upcall_functor ().cancel_timer (*this,
00759                                             temp->get_type (),
00760                                             dont_call,
00761                                             cookie);
00762 
00763       if (act != 0)
00764         *act = temp->get_act ();
00765 
00766       this->free_node (temp);
00767       return 1;
00768     }
00769 }
00770 
00771 // Locate and update the inteval on the timer_id
00772 
00773 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00774 int
00775 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::reset_interval (long timer_id,
00776                                                            const ACE_Time_Value &interval)
00777 {
00778   ACE_TRACE ("ACE_Timer_Heap_T::reset_interval");
00779   ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00780 
00781   // Locate the ACE_Timer_Node that corresponds to the timer_id.
00782 
00783   // Check to see if the timer_id is out of range
00784   if (timer_id < 0
00785       || (size_t) timer_id > this->max_size_)
00786     return -1;
00787 
00788   ssize_t timer_node_slot = this->timer_ids_[timer_id];
00789 
00790   // Check to see if timer_id is still valid.
00791   if (timer_node_slot < 0)
00792     return -1;
00793 
00794   if (timer_id != this->heap_[timer_node_slot]->get_timer_id ())
00795     {
00796       ACE_ASSERT (timer_id == this->heap_[timer_node_slot]->get_timer_id ());
00797       return -1;
00798     }
00799   else
00800     {
00801       // Reset the timer interval
00802       this->heap_[timer_node_slot]->set_interval (interval);
00803       return 0;
00804     }
00805 }
00806 
00807 // Locate and remove all values of @a type from the timer queue.
00808 
00809 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00810 int
00811 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (const TYPE &type,
00812                                                    int dont_call)
00813 {
00814   ACE_TRACE ("ACE_Timer_Heap_T::cancel");
00815 
00816   ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00817 
00818   int number_of_cancellations = 0;
00819 
00820   // Try to locate the ACE_Timer_Node that matches the timer_id.
00821 
00822   for (size_t i = 0; i < this->cur_size_; )
00823     {
00824       if (this->heap_[i]->get_type () == type)
00825         {
00826           ACE_Timer_Node_T<TYPE> *temp = this->remove (i);
00827 
00828           ++number_of_cancellations;
00829 
00830           this->free_node (temp);
00831 
00832           // We reset to zero so that we don't miss checking any nodes
00833           // if a reheapify occurs when a node is removed.  There
00834           // may be a better fix than this, however.
00835           i = 0;
00836         }
00837       else
00838         ++i;
00839     }
00840 
00841   // Call the close hooks.
00842   int cookie = 0;
00843 
00844   // cancel_type() called once per <type>.
00845   this->upcall_functor ().cancel_type (*this,
00846                                        type,
00847                                        dont_call,
00848                                        cookie);
00849 
00850   for (int j = 0;
00851        j < number_of_cancellations;
00852        ++j)
00853     {
00854       // cancel_timer() called once per <timer>.
00855       this->upcall_functor ().cancel_timer (*this,
00856                                             type,
00857                                             dont_call,
00858                                             cookie);
00859     }
00860 
00861   return number_of_cancellations;
00862 }
00863 
00864 // Returns the earliest node or returns 0 if the heap is empty.
00865 
00866 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00867 ACE_Timer_Node_T <TYPE> *
00868 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::remove_first (void)
00869 {
00870   ACE_TRACE ("ACE_Timer_Heap_T::remove_first");
00871 
00872   if (this->cur_size_ == 0)
00873     return 0;
00874 
00875   return this->remove (0);
00876 }
00877 
00878 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00879 ACE_Timer_Node_T <TYPE> *
00880 ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::get_first (void)
00881 {
00882   ACE_TRACE ("ACE_Timer_Heap_T::get_first");
00883 
00884   return this->cur_size_ == 0 ? 0 : this->heap_[0];
00885 }
00886 
00887 ACE_END_VERSIONED_NAMESPACE_DECL
00888 
00889 #endif /* ACE_TIMER_HEAP_T_CPP */

Generated on Tue Feb 2 17:18:43 2010 for ACE by  doxygen 1.4.7