diff options
author | Steve Huston <shuston@riverace.com> | 2018-06-26 18:01:38 -0400 |
---|---|---|
committer | Steve Huston <shuston@riverace.com> | 2018-06-26 18:01:38 -0400 |
commit | d3bb3163e9380bc55a4a8b7877949fdca5326571 (patch) | |
tree | 28fb8d730a9bc0ab8f5c4f26a19f399aa534a363 /ACE/ace/Timer_Wheel_T.cpp | |
parent | 515ec9ad5cb7d0361b499a31c13a7cb6c83f435a (diff) | |
download | ATCD-d3bb3163e9380bc55a4a8b7877949fdca5326571.tar.gz |
Fix memory leak in schedule; replace broken next-count logic in generate_timer_id
Diffstat (limited to 'ACE/ace/Timer_Wheel_T.cpp')
-rw-r--r-- | ACE/ace/Timer_Wheel_T.cpp | 63 |
1 files changed, 22 insertions, 41 deletions
diff --git a/ACE/ace/Timer_Wheel_T.cpp b/ACE/ace/Timer_Wheel_T.cpp index e9d4f294e97..7fd6f68f6bd 100644 --- a/ACE/ace/Timer_Wheel_T.cpp +++ b/ACE/ace/Timer_Wheel_T.cpp @@ -328,7 +328,14 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK, TIME_POLICY>::generate_timer_id (u_in // This field is used as a counter instead of a timer_id. long cnt = root->get_timer_id (); - if (cnt >= max_cnt && root == root->get_next ()) + if (cnt < max_cnt) + { + root->set_timer_id (cnt + 1); + return (cnt << this->spoke_bits_) | spoke; + } + + // Count has overflowed its range. + if (root == root->get_next ()) { // Special case when we overflow on an empty spoke. We can just // wrap the count around without searching for duplicates. We only @@ -337,50 +344,20 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK, TIME_POLICY>::generate_timer_id (u_in root->set_timer_id (1); return spoke; } - else if (cnt >= max_cnt) - { // overflow - cnt = 0; // try again starting at zero - } - else if (next_cnt == 0 || cnt < next_cnt) - { - root->set_timer_id (cnt + 1); - return (cnt << this->spoke_bits_) | spoke; - } + // Overflowed count, and the spoke is not empty. Search for an unused + // id value. //ACELIB_ERROR((LM_ERROR, "Timer id overflow. We have to search now.\n")); - - // We've run out of consecutive id numbers so now we have to search - // for a unique id. - // We'll try increasing numbers until we find one that is not in use, - // and we'll record the next highest number so that we can avoid this - // search as often as possible. - for (; cnt < max_cnt - 1; ++cnt) + for (cnt = 0; cnt < max_cnt - 1; ++cnt) { + // Look for an unused id. Yes, every new id on this spoke will result in a + // scan until all the spoke's timers get canceled/expired then the spoke will + // start over like new. So, when an empty spot is found, don't reset the + // root node's timer_id - it stays at max until the spoke clears out and + // starts over. long id = (cnt << this->spoke_bits_) | spoke; - ACE_Timer_Node_T<TYPE>* n = this->find_spoke_node (spoke, id); - if (n == 0) - { - root->set_timer_id (cnt + 1); - // Now we need to find the next highest cnt in use - next_cnt = 0; - for (; n != root; n = n->get_next ()) - { - long tmp = n->get_timer_id () >> this->spoke_bits_; - if (tmp > cnt && (tmp < next_cnt || next_cnt == 0)) - next_cnt = tmp; - } -#if defined (ACE_WIN64) - // The cast below is legit... we know we're storing a long in - // a pointer, but are only using it as a 'long' storage area. -# pragma warning(push) -# pragma warning(disable : 4312) -#endif /* ACE_WIN64 */ - root->set_act (reinterpret_cast<void*> (next_cnt)); -#if defined (ACE_WIN64) -# pragma warning(pop) -#endif /* ACE_WIN64 */ - return id; - } + if (0 == this->find_spoke_node (spoke, id)) + return id; } return -1; // We did our best, but the spoke is full. @@ -421,6 +398,10 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK, TIME_POLICY>::schedule_i (const TYPE& n->set (type, act, future_time, interval, 0, 0, id); this->schedule_i (n, spoke, future_time); } + else + { + this->free_node (n); + } return id; } |