• 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) 当新加入的定时项位于队列头部时,唤醒定时线程。


    -----------------------------------------------
    独学而无友,则孤陋而寡闻
    -----------------------------------------------
  • 相关阅读:
    vim /home/yuanyc/.bashrc export LC_ALL=zh_CN.UTF-8
    mongodb
    关于RegisterClass和CreateWindow
    c++中sqlite中文路径创建数据库失败的问题
    Layered Window 透明窗体的实现总结
    c++单列模式与线程安全
    Windows下API Hook 技术
    COM编程大致梳理
    关于c++多态
    几个多字节和UNICODE及UTF-8之间相互转化的函数
  • 原文地址:https://www.cnblogs.com/shanno/p/3962884.html
Copyright © 2020-2023  润新知