chenshuo / muduo

Event-driven network library for multi-threaded Linux server in C++11
https://github.com/chenshuo/muduo
Other
14.64k stars 5.14k forks source link

About TimerQueue's CancelInLoop #675

Closed russck closed 1 year ago

russck commented 1 year ago
void TimerQueue::cancelInLoop(TimerId timerId)
{
  loop_->assertInLoopThread();
  assert(timers_.size() == activeTimers_.size());
  ActiveTimer timer(timerId.timer_, timerId.sequence_);
  ActiveTimerSet::iterator it = activeTimers_.find(timer);
  if (it != activeTimers_.end())
  {
    size_t n = timers_.erase(Entry(it->first->expiration(), it->first));
    assert(n == 1); (void)n;
    delete it->first; // FIXME: no delete please
    activeTimers_.erase(it);
  }
  else if (callingExpiredTimers_)
  {
    cancelingTimers_.insert(timer);
  }
  assert(timers_.size() == activeTimers_.size());
}
void TimerQueue::handleRead()
{
  loop_->assertInLoopThread();
  Timestamp now(Timestamp::now());
  readTimerfd(timerfd_, now);

  std::vector<Entry> expired = getExpired(now);
//if canelInLoop() called in here, the target Timer is in expired, the cancel will not happen
  callingExpiredTimers_ = true;
//if canelInLoop() called in here, the cancelingTimers_ will clear soon before reset
  cancelingTimers_.clear();
  for (const Entry& it : expired)
  {
    it.second->run();
  }
  callingExpiredTimers_ = false;

  reset(expired, now);
}

What if cancelInLoop() called in annotation place?