zoukankan      html  css  js  c++  java
  • Ceph剖析:定时器safetimer的实现

    定时器的作用是在指定的时间执行指定的动作。SafeTimer通过multimap数据结构维护定时项,定时项是时间和事件的Pair,定时项在map中按照定时时间从小到大排列。此外,SafeTimer使用一个线程来轮询定时项,当到达定时项指定的时间时执行对应的事件。下面代码是这个线程的入口函数:

    void SafeTimer::timer_thread()
    {
       lock.Lock();
       while (!stopping) {
    	utime_t now = ceph_clock_now(cct); /// 获取当前时间
        
    	while (!schedule.empty()) {
    	  scheduled_map_t::iterator p = schedule.begin();
    
    	  /// 还没达到指定的定时时间
              /// 因为schedule中的定时项是已经排好顺序的,第1个元素就是最先要处理的事件,所以只要检查第1个元素就可以了
    	  if (p->first > now) { 
    		  break;
    	  }
    
    	  /// 处理指定的事件
    	  Context *callback = p->second;
    	  events.erase(callback);
    	  schedule.erase(p);
    	  
    	  if (!safe_callbacks){
               lock.Unlock();
    	  }
       
              /// 处理事件时,解锁。因为处理事件不会修改定时器本身的数据
    	  callback->complete(0);
    	  if (!safe_callbacks){
    		  lock.Lock();
    	  }
    	}
    
    	/// 当使用者向schedule插入新的定时项时,如果新的定时项的时间是最早的,那么它会唤醒该线程
    	if (schedule.empty()) {
    		cond.Wait(lock);
    	} else {
    		/// 等待指定的时间
    		cond.WaitUntil(lock, schedule.begin()->first);
            }
       }
      lock.Unlock();
    }
    

    定时器实现考虑以下几个因素:1) 定时项按照从早到晚排序,通过std::multimap实现;2) 修改定时器相关的数据时加锁,执行定时动作前解锁。这样就不会阻塞其它线程对定时器的操作,例如添加、删除定时项;3) 当新加入的定时项位于队列头部时,唤醒定时线程。


    -----------------------------------------------
    独学而无友,则孤陋而寡闻
    -----------------------------------------------
  • 相关阅读:
    BZOJ3144 [Hnoi2013]切糕 【最小割】
    BZOJ4196 [Noi2015]软件包管理器 【树剖】
    POJ3422:Kaka's Matrix Travels——题解
    POJ2195:Going Home——题解
    POJ3068:"Shortest" pair of paths——题解
    POJ3686:The Windy's——题解
    POJ2135:Farm Tour——题解
    POJ2987:Firing——题解
    POJ3469:Dual Core CPU——题解
    POJ3281:Dining——题解
  • 原文地址:https://www.cnblogs.com/shanno/p/3962884.html
Copyright © 2011-2022 走看看