前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一种定时器的实现

一种定时器的实现

作者头像
changan
发布2020-11-04 15:03:54
4830
发布2020-11-04 15:03:54
举报

概述

一个Timer的实现需要具备以下几个行为:

  • StartTimer(Interval, ExpiryAction)

注册一个时间间隔为 Interval 后执行 ExpiryAction 的定时器实例,其中,返回 TimerId 以区分在定时器系统中的其他定时器实例。

  • StopTimer(TimerId)

根据 TimerId 找到注册的定时器实例并执行 Stop 。

  • PerTickBookkeeping()

在一个 Tick 时间粒度内,定时器系统需要执行的动作,它最主要的行为,就是检查定时器系统中,是否有定时器实例已经到期。

具体的代码实现思路就是:在StartTimer的时候,把 当前时间 + Interval 作为key放入一个容器,然后在Loop的每次Tick里,从容器里面选出一个最小的key与当前时间比较,如果key小于当前时间,则这个key代表的timer就是expired,需要执行它的ExpiryAction(一般为回调)。

链表的实现

  • 精度是 1ms
  • 最长时间是10min,延长时间可以增加 slot数量,slot时间的间隔是 1ms
  • 通过继承Timer父类,在子类重写timeout实现 超时回调
  • 每次都需要遍历超过时间的所有链表,时间复杂度为O(n)

执行方式

每次从上次执行的时间,遍历每个链表上挂的timer是不是到期,如果到期了,就执行对应的超时函数,并移除定时器,把这个环拉直看就可以了:

image
image
int TimerMgr::TimeRun()
{
	Tick();
	int timeout_count = 0;
	int pass = currTime - lastRunTime;
	uint64_t time = lastRunTime + 1;

	for (int i = 0; i < pass; i++)
	{
		int index = time % timeLen;

		while(slot[index]->Size() > 0)
		{
			TimerNode* node = slot[index]->Serve();

			TimerNodeMap::iterator it;
			it = nodemap.find(node->t->getId());

			if (it != nodemap.end())
			{
				if (node == NULL)
				{

					ERROR("node == NULL");
					continue;
				}
				if (node->t == NULL)
				{
					ERROR("timer == NULL");
					continue;
				}
				DEBUG("time out %d", index);
				node->t->Timeout();
				nodemap.erase(node->t->getId());
				timeout_count++;
			}

			TimerPool.Free(reinterpret_cast<char*>(node->t));
			NodePool.Free(reinterpret_cast<char*>(node));
		}
		time++;
	}
	lastRunTime = currTime;
	return timeout_count;

}

example

子类:

template<class T>
class RobotTimer:public Timer
{
        typedef void (T::*Method)();
        public:
        RobotTimer(T * p, Method m):method(m),pRobot(p){}
        virtual void Timeout();
        private:
        Method method;
        T* pRobot;

};

template<class T>
void RobotTimer<T>::Timeout()
{
    (pRobot->*method)();
}


class BaseRobot
{
public:
    BaseRobot()
    {
        m_id = 0;
    }
    void RobotWait(int millseconds);
    void Resume()
    {
        cout<< "BaseRobot::Resume" << endl;

        TimerMgr::GetInst()->RemoveTimer(m_id);
        cout << "RemoveTimer"<< m_id << endl;
    }
    uint32_t m_id;
};

void BaseRobot::RobotWait(int millseconds)
{
    RobotTimer<BaseRobot>* t =  reinterpret_cast<RobotTimer<BaseRobot>*>(TimerMgr::GetInst()->TimerPool.Alloc());
    new (t) RobotTimer<BaseRobot>(this, &BaseRobot::Resume);
    t->SetTimer(millseconds);
    uint32_t tid = t->getId();
    TimerMgr::GetInst()->Insert(t);
    m_id = tid;
}

等待一段时间:

...
unsigned wait = NumberHelper::ARandRange(6, 60000);
BaseRobot* robot = new BaseRobot;
robot->RobotWait(1234);
...

code

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-12-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • 链表的实现
  • 执行方式
  • example
  • code
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档