Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

Timer_Heap_T.cpp

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

Generated on Mon Jun 16 11:21:50 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002