summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog21
-rw-r--r--ChangeLogs/ChangeLog-02a21
-rw-r--r--ChangeLogs/ChangeLog-03a21
-rw-r--r--ace/Timer_Hash_T.cpp15
-rw-r--r--ace/Timer_Heap_T.cpp75
-rw-r--r--ace/Timer_Heap_T.h6
-rw-r--r--tests/Timer_Queue_Test.cpp1
7 files changed, 118 insertions, 42 deletions
diff --git a/ChangeLog b/ChangeLog
index f5fb8e81c65..27712d93c62 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,11 +1,28 @@
+Thu May 24 20:26:39 2001 Steve Huston <shuston@riverace.com>
+
+ * ace/Timer_Heap_T.{h cpp}: Fixed some problems in managing the
+ free timer ID list.
+
+ * ace/Timer_Hash_T.cpp (expire): Changed this to peek at the first
+ timer node from each table, do reschedule iterative timers, and
+ do the upcall, then _cancel_ the original, rather than try to
+ manage a remove_first()/reschedule-or-free sequence. The ID
+ assigned by the underlying table is not important, since its not
+ seen by the ACE_Timer_Hash_T caller anyway, and that's the main
+ impetus for using remove_first/reschedule (or free_node).
+
+ * tests/Timer_Queue_Test.cpp (test_functionality): Added a test
+ to verify empty timer queue after adding/removing two timers
+ right at the start.
+
Thu May 24 12:15:35 2001 Douglas C. Schmidt <schmidt@tango.doc.wustl.edu>
* ace/OS.h: Added #defines for RTLD_LAZY, RTLD_NOW, RTLD_GLOBAL.
Thanks to Kobi Cohen-Arazi <kobic@bvr.co.il> for suggesting
this.
- * ace/OS.h: Updated the ACE_Time_Value class to point out that the values
- are in secs and usecs. Thanks to Israel Illescas Gomez
+ * ace/OS.h: Updated the ACE_Time_Value class to point out that the
+ values are in secs and usecs. Thanks to Israel Illescas Gomez
<illescas@dycsa.es> for motivating this.
Thu May 24 18:08:27 2001 Steve Huston <shuston@riverace.com>
diff --git a/ChangeLogs/ChangeLog-02a b/ChangeLogs/ChangeLog-02a
index f5fb8e81c65..27712d93c62 100644
--- a/ChangeLogs/ChangeLog-02a
+++ b/ChangeLogs/ChangeLog-02a
@@ -1,11 +1,28 @@
+Thu May 24 20:26:39 2001 Steve Huston <shuston@riverace.com>
+
+ * ace/Timer_Heap_T.{h cpp}: Fixed some problems in managing the
+ free timer ID list.
+
+ * ace/Timer_Hash_T.cpp (expire): Changed this to peek at the first
+ timer node from each table, do reschedule iterative timers, and
+ do the upcall, then _cancel_ the original, rather than try to
+ manage a remove_first()/reschedule-or-free sequence. The ID
+ assigned by the underlying table is not important, since its not
+ seen by the ACE_Timer_Hash_T caller anyway, and that's the main
+ impetus for using remove_first/reschedule (or free_node).
+
+ * tests/Timer_Queue_Test.cpp (test_functionality): Added a test
+ to verify empty timer queue after adding/removing two timers
+ right at the start.
+
Thu May 24 12:15:35 2001 Douglas C. Schmidt <schmidt@tango.doc.wustl.edu>
* ace/OS.h: Added #defines for RTLD_LAZY, RTLD_NOW, RTLD_GLOBAL.
Thanks to Kobi Cohen-Arazi <kobic@bvr.co.il> for suggesting
this.
- * ace/OS.h: Updated the ACE_Time_Value class to point out that the values
- are in secs and usecs. Thanks to Israel Illescas Gomez
+ * ace/OS.h: Updated the ACE_Time_Value class to point out that the
+ values are in secs and usecs. Thanks to Israel Illescas Gomez
<illescas@dycsa.es> for motivating this.
Thu May 24 18:08:27 2001 Steve Huston <shuston@riverace.com>
diff --git a/ChangeLogs/ChangeLog-03a b/ChangeLogs/ChangeLog-03a
index f5fb8e81c65..27712d93c62 100644
--- a/ChangeLogs/ChangeLog-03a
+++ b/ChangeLogs/ChangeLog-03a
@@ -1,11 +1,28 @@
+Thu May 24 20:26:39 2001 Steve Huston <shuston@riverace.com>
+
+ * ace/Timer_Heap_T.{h cpp}: Fixed some problems in managing the
+ free timer ID list.
+
+ * ace/Timer_Hash_T.cpp (expire): Changed this to peek at the first
+ timer node from each table, do reschedule iterative timers, and
+ do the upcall, then _cancel_ the original, rather than try to
+ manage a remove_first()/reschedule-or-free sequence. The ID
+ assigned by the underlying table is not important, since its not
+ seen by the ACE_Timer_Hash_T caller anyway, and that's the main
+ impetus for using remove_first/reschedule (or free_node).
+
+ * tests/Timer_Queue_Test.cpp (test_functionality): Added a test
+ to verify empty timer queue after adding/removing two timers
+ right at the start.
+
Thu May 24 12:15:35 2001 Douglas C. Schmidt <schmidt@tango.doc.wustl.edu>
* ace/OS.h: Added #defines for RTLD_LAZY, RTLD_NOW, RTLD_GLOBAL.
Thanks to Kobi Cohen-Arazi <kobic@bvr.co.il> for suggesting
this.
- * ace/OS.h: Updated the ACE_Time_Value class to point out that the values
- are in secs and usecs. Thanks to Israel Illescas Gomez
+ * ace/OS.h: Updated the ACE_Time_Value class to point out that the
+ values are in secs and usecs. Thanks to Israel Illescas Gomez
<illescas@dycsa.es> for motivating this.
Thu May 24 18:08:27 2001 Steve Huston <shuston@riverace.com>
diff --git a/ace/Timer_Hash_T.cpp b/ace/Timer_Hash_T.cpp
index 07e65bb791a..16c6074c595 100644
--- a/ace/Timer_Hash_T.cpp
+++ b/ace/Timer_Hash_T.cpp
@@ -565,9 +565,8 @@ ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::expire (const ACE_Time_Value
while (!this->table_[i]->is_empty ()
&& this->table_[i]->earliest_time () <= cur_time)
{
- expired = this->table_[i]->remove_first ();
- --this->size_;
- TYPE &type = expired->get_type ();
+ expired = this->table_[i]->get_first ();
+ TYPE type = expired->get_type ();
const void *act = expired->get_act ();
int reclaim = 1;
@@ -587,6 +586,13 @@ ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::expire (const ACE_Time_Value
reclaim = 0;
}
+ // Now remove the timer from the original table... if
+ // it's a simple, non-recurring timer, it's got to be
+ // removed anyway. If it was rescheduled, it's been
+ // scheduled into the correct table (regardless of whether
+ // it's the same one or not) already.
+ this->table_[i]->cancel (expired->get_timer_id ());
+
Hash_Token *h = ACE_reinterpret_cast (Hash_Token *,
ACE_const_cast (void *,
act));
@@ -596,8 +602,7 @@ ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::expire (const ACE_Time_Value
cur_time);
if (reclaim)
{
- // Free up the node and the token
- this->free_node (expired);
+ --this->size_;
delete h;
}
number_of_timers_expired++;
diff --git a/ace/Timer_Heap_T.cpp b/ace/Timer_Heap_T.cpp
index f35380576d1..f86c7563776 100644
--- a/ace/Timer_Heap_T.cpp
+++ b/ace/Timer_Heap_T.cpp
@@ -67,7 +67,10 @@ ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::item (void)
}
// Constructor
-
+// Note that timer_ids_curr_ and timer_ids_min_free_ both start at 0.
+// Since timer IDs are assigned by first incrementing the timer_ids_curr_
+// value, the first ID assigned will be 1 (just as in the previous design).
+// When it's time to wrap, the next ID given out will be 0.
template <class TYPE, class FUNCTOR, class ACE_LOCK>
ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Heap_T (size_t size,
int preallocate,
@@ -76,8 +79,8 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Heap_T (size_t size,
: ACE_Timer_Queue_T<TYPE,FUNCTOR,ACE_LOCK> (upcall_functor, freelist),
max_size_ (size),
cur_size_ (0),
- timer_ids_next_ (0),
- timer_ids_min_free_ (size),
+ timer_ids_curr_ (0),
+ timer_ids_min_free_ (0),
preallocated_nodes_ (0),
preallocated_nodes_freelist_ (0)
{
@@ -122,14 +125,18 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Heap_T (size_t size,
HEAP_ITERATOR (*this));
}
+// Note that timer_ids_curr_ and timer_ids_min_free_ both start at 0.
+// Since timer IDs are assigned by first incrementing the timer_ids_curr_
+// value, the first ID assigned will be 1 (just as in the previous design).
+// When it's time to wrap, the next ID given out will be 0.
template <class TYPE, class FUNCTOR, class ACE_LOCK>
ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Heap_T (FUNCTOR *upcall_functor,
ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist)
: ACE_Timer_Queue_T<TYPE,FUNCTOR,ACE_LOCK> (upcall_functor, freelist),
max_size_ (ACE_DEFAULT_TIMERS),
cur_size_ (0),
- timer_ids_next_ (0),
- timer_ids_min_free_ (ACE_DEFAULT_TIMERS),
+ timer_ids_curr_ (0),
+ timer_ids_min_free_ (0),
preallocated_nodes_ (0),
preallocated_nodes_freelist_ (0)
{
@@ -197,28 +204,28 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::pop_freelist (void)
// Scan for a free timer ID. Note that since this function is called
// _after_ the check for a full timer heap, we are guaranteed to find
- // a free ID. The next_ index was left at the previous allocated ID
- // and we pick up where we left off last time.
- ++this->timer_ids_next_;
- if (this->timer_ids_next_ == this->max_size_)
+ // a free ID, even if we need to wrap around and start reusing freed IDs.
+ // On entry, the curr_ index is at the previous ID given out; start
+ // up where we left off last time.
+ ++this->timer_ids_curr_;
+ while (this->timer_ids_curr_ < this->max_size_ &&
+ this->timer_ids_[this->timer_ids_curr_] >= 0)
+ ++this->timer_ids_curr_;
+ if (this->timer_ids_curr_ == this->max_size_)
{
ACE_ASSERT (this->timer_ids_min_free_ < this->max_size_);
- this->timer_ids_next_ = this->timer_ids_min_free_;
+ this->timer_ids_curr_ = this->timer_ids_min_free_;
// We restarted the free search at min. Since min won't be
- // free anymore, find the next lowest free entry, recognizing
- // that there may not be any more; in that case, min_free_
- // gets left saying "none free" and will be reset next time
- // an entry is freed.
- while (++this->timer_ids_min_free_ < this->max_size_)
- if (this->timer_ids_[this->timer_ids_min_free_] < 0)
- break;
+ // free anymore, and curr_ will just keep marching up the list
+ // on each successive need for an ID, reset min_free_ to the
+ // size of the list until an ID is freed that curr_ has already
+ // gone past (see push_freelist).
+ this->timer_ids_min_free_ = this->max_size_;
}
- while (this->timer_ids_[this->timer_ids_next_] >= 0)
- ++this->timer_ids_next_;
// We need to truncate this to <int> for backwards compatibility.
int new_id = ACE_static_cast (int,
- this->timer_ids_next_);
+ this->timer_ids_curr_);
return new_id;
}
@@ -227,16 +234,18 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::push_freelist (int old_id)
{
ACE_TRACE ("ACE_Timer_Heap_T::push_freelist");
- // Since this ID has alreayd been checked by one of the public
+ // Since this ID has already been checked by one of the public
// functions, it's safe to cast it here.
size_t oldid = size_t (old_id);
// The freelist values in the <timer_ids_> are negative, so set the
// freed entry back to 'free'. If this is the new lowest value free
- // timer ID, remember it.
+ // timer ID that curr_ won't see on it's normal march through the list,
+ // remember it.
this->timer_ids_[oldid] = -1;
- if (oldid < this->timer_ids_min_free_)
+ if (oldid < this->timer_ids_min_free_ && oldid <= this->timer_ids_curr_)
this->timer_ids_min_free_ = oldid;
+ return;
}
template <class TYPE, class FUNCTOR, class ACE_LOCK> int
@@ -281,8 +290,8 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::dump (void) const
ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nmax_size_ = %d"), this->max_size_));
ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ncur_size_ = %d"), this->cur_size_));
- ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nids_next_ = %d"),
- this->timer_ids_next_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nids_curr_ = %d"),
+ this->timer_ids_curr_));
ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nmin_free_ = %d"),
this->timer_ids_min_free_));
@@ -321,15 +330,23 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::copy (int slot,
this->timer_ids_[moved_node->get_timer_id ()] = slot;
}
+// Remove the slot'th timer node from the heap, but do not reclaim its
+// timer ID or change the size of this timer heap object. The caller of
+// this function must call either free_node (to reclaim the timer ID
+// and the timer node memory, as well as decrement the size of the queue)
+// or reschedule (to reinsert the node in the heap at a new time).
template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::remove (size_t slot)
{
ACE_Timer_Node_T<TYPE> *removed_node =
this->heap_[slot];
- // Decrement the size of the heap by one since we're removing the
- // "slot"th node.
- this->cur_size_--;
+ // NOTE - this is a temporary decrement of cur_size_, since other
+ // member functions that will be called from here use it without
+ // wanting the removed node included. However, we will bump it back up
+ // before return to be sure that the removed node is still included in
+ // the size of this timer heap.
+ --this->cur_size_;
// Only try to reheapify if we're not deleting the last entry.
@@ -357,6 +374,7 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::remove (size_t slot)
parent);
}
+ ++this->cur_size_;
return removed_node;
}
@@ -565,6 +583,7 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::free_node (ACE_Timer_Node_T<TYPE> *no
// Return this timer id to the freelist.
this->push_freelist (node->get_timer_id ());
+ --this->cur_size_;
// Only free up a node if we are *not* using the preallocated heap.
if (this->preallocated_nodes_ == 0)
diff --git a/ace/Timer_Heap_T.h b/ace/Timer_Heap_T.h
index 0ad14588f98..20e3ce9e408 100644
--- a/ace/Timer_Heap_T.h
+++ b/ace/Timer_Heap_T.h
@@ -283,9 +283,9 @@ private:
*/
long *timer_ids_;
- /// "Pointer" to the next element in the <timer_ids_> array that will
- /// be checked for use when a new timer ID is needed.
- size_t timer_ids_next_;
+ /// "Pointer" to the element in the <timer_ids_> array that was
+ /// last given out as a timer ID.
+ size_t timer_ids_curr_;
/// Index representing the lowest timer ID that has been freed. When
/// the timer_ids_next_ value wraps around, it starts back at this
diff --git a/tests/Timer_Queue_Test.cpp b/tests/Timer_Queue_Test.cpp
index a9b03aadfd4..e37a0b1d2a9 100644
--- a/tests/Timer_Queue_Test.cpp
+++ b/tests/Timer_Queue_Test.cpp
@@ -115,6 +115,7 @@ test_functionality (ACE_Timer_Queue *tq)
tq->cancel (timer_id);
tq->cancel (timer_id2);
+ ACE_ASSERT (tq->is_empty () == 1);
timer_id = tq->schedule (&eh,
(const void *) 1,