一.system_clock和steady_clock比较

下面一段摘录
system_clock:就类似Windows系统右下角那个时钟,是系统时间。明显那个时钟是可以乱设置的。明明是早上10点,却可以设置成下午3点。
steady_clock:则针对system_clock可以随意设置这个缺陷而提出来的,他表示时钟是不能设置的。
steady_clock的实现是使用monotonic时间,而monotonic时间一般是从boot启动后开始计数的。明显这不能获取日历时间(年月日时分秒)。
那么steady_clock有什么用途呢?时间比较!并且是不受用户调整系统时钟影响的时间比较。简单的例子如下:

auto begin = std::chrono::steady_clock::now();
for(int i = 0; i < 10000000; ++i)
{// 计算...
}
auto end = std::chrono::steady_clock::now();
auto diff = (end - begin).count(); //end-begin得到一个duration类型
std::cout<<diff<<std::endl;

二.定时管理器heap

phx使用了heap(小根堆)来管理超时,一般来说,heap能做的操作是top(), push(), pop()三个操作。但是这里的一些设计要求可以在任何合法的位置删除节点,所以仅仅有pop()是不够的。

看下面一段代码:

int UThreadPoll(UThreadSocket_t & socket, int events, int * revents, int timeout_ms) {int ret = -1;// 获得当前正在执行的协程,需要这个协程帮助做点事socket.uthread_id = socket.scheduler->GetCurrUThread();// 增加超时事件socket.event.events = events;socket.scheduler->AddTimer(&socket, timeout_ms);// 事件加入epoll// 理论上讲,AddTimer将这个超时事件加入额外管理的heap定时器管理器就OK了// 此处为什么还需要加入epoll中进行调度?// 原因在于,在超时事件还没到达的时候,可能就有事件触发了,使得下面这一轮提前结束!epoll_ctl(socket.epoll_fd, EPOLL_CTL_ADD, socket.socket, &socket.event);// 将当前的协程停止,转让CPU给主协程// 当主协程下次收到这个超时事件的时候会将执行权还给这个协程// 协程下次还是从当前位置开始执行socket.scheduler->YieldTask();// 当超时任务完成,协程继续从此处执行!// 完成后从epoll中删除定时器epoll_ctl(socket.epoll_fd, EPOLL_CTL_DEL, socket.socket, &socket.event);socket.scheduler->RemoveTimer(socket.timer_id);...
}

上面这段代码将socket加入超时事件中,同时epoll也会去监控这个socket。那么这就可能存在两种情况:
第一:如果谁正常超时事件达到,协程回到当前代码,那么下面的RemoveTimer就相当于是pop()操作,这个是很常规逻辑。
第二:如果在超时之前,epoll就监控到存在事件触发了,那么在超时之前就重新回到这个协程。这个时候节点并没有超时,所以节点可能不是小根堆的根节点。那么删除的是中间的某个节点。这时候之前的pop就不满足要求了,因为pop只能讲根节点弹出。
这里的根本问题不在删除哪个节点,而是我们怎么定位到那个节点,难道要扫描一遍?那样代价有点大。
phx在此处有一个很trick的做法,它将每个socket关联的定时器的index(在vector数组中的下标)保存在socket结构中!!!这样就可以做到O(1)定位。这个有点。。。只能说“6”。

看下具体的UThreadSocket结构:

typedef struct tagUThreadSocket {UThreadEpollScheduler * scheduler;int uthread_id;int epoll_fd;int socket;int connect_timeout_ms;int socket_timeout_ms;int waited_events;size_t timer_id;    // 保存这个socket的定时器在heap的数组中的位置(如果存在),方便在堆中的查找struct epoll_event event;void * args;
} UThreadSocket_t;

这个结构虽然很方便,但是总是觉得怪怪的。。。

OK,找到相应的节点后,那么删除操作就比较简单了。
看下具体的代码:

// 移除一个计时器
void Timer :: RemoveTimer(const size_t timer_id) {if (timer_id == 0) {return;}size_t now_idx = timer_id - 1;if (now_idx >= timer_heap_.size()) {return;}TimerObj obj = timer_heap_[now_idx];UThreadSocketSetTimerID(*obj.socket_, 0);// 当前与最后一个进行交换// 然后删除最后一个元素// 最后需要调整堆(up or down)std::swap(timer_heap_[timer_heap_.size() - 1], timer_heap_[now_idx]);timer_heap_.pop_back();if (timer_heap_.empty()) {return;}// 下面执行up 或者 down逻辑// 这里需要将移除的节点和最后的节点比较大小// 从而里判断是需要heap_up还是heap_downif (timer_heap_[now_idx] < obj) {heap_up(now_idx + 1);} else if (timer_heap_[now_idx] == obj) {UThreadSocketSetTimerID(*timer_heap_[now_idx].socket_, now_idx + 1);} else {heap_down(now_idx);}
}

在heap_up和heap_down函数中,有一行类似如下:

UThreadSocketSetTimerID(*timer_heap_[now_idx].socket_, now_idx + 1);

这个就是每次调整完节点需要在socket结构中重新设置关联的timer在vector中的位置,Orz…

其他的正常的堆的操作就没什么好说的了。

微信后台 phxrpc (v0.8) 之 Timer(二)相关推荐

  1. 从无到有:微信后台系统的演进之路

    从无到有 2011.1.21 微信正式发布.这一天距离微信项目启动日约为2个月.就在这2个月里,微信从无到有,大家可能会好奇这期间微信后台做的最重要的事情是什么? 我想应该是以下三件事: 1. 确定了 ...

  2. 分享一套开源微信后台开发源码,简单配置就能使用(附源码)!

    项目源码 推荐 7 个牛哄哄 Spring Cloud 实战项目 推荐一个非常火爆的电商开源项目! 推荐两个项目! 重磅推荐:一套开源的网校系统,无论是自建网校还是接副业都很方便 推荐几个支付项目! ...

  3. 10年前腾讯微信后台第一天提交的代码曝光!

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:硬刚一周,3W字总结,一年的经验告诉你如何准备校招! 个人原创100W+访问量博客:点击前往,查看更多 编辑:卫 ...

  4. thinkphp 微信服务器验证代码_基于ThinkPHP5微信后台管理平台

    DIY分享秀 2019-10-08 22:28:57 ThinkAdmin V5 是一个基于 ThinkPHP 5.1 开发的后台管理系统. 我们致力于二次开发底层框架,提供完整的组件及API,基于此 ...

  5. 实现微信小程序和支付宝小程序二维码合并

    实现微信小程序和支付宝小程序二维码合并,这样用户就可以通过同一个二维码进入微信或者支付宝啦 1.需要准备可以通过公网访问的服务器 2.微信小程序 打开微信小程序后台->开发(左边)->开发 ...

  6. 从0到1:微信后台系统的演进之路(转自INFOQ)

    2个月的开发时间,微信后台系统经历了从0到1的过程.从小步慢跑到快速成长,经历了平台化到走出国门,微信交出的这份优异答卷,解题思路是怎样的?本文由张文瑞,微信后台团队出品. 从无到有 2011.1.2 ...

  7. 最新在线客服系统php代码微信软件公众号小程序app二维码聊天网站源码

    最新在线客服系统php代码微信软件公众号小程序app二维码聊天网站源码 管理界面 独家长期更新日志(欢迎反馈BUG) 1.添加手机端前后台声音提示 2.添加后台客户管理显示在线离线 3.添加清空当前对 ...

  8. 微信后台基于时间序的海量数据冷热分级架构设计实践

    写在前面 微信的后台数据存储随着微信产品特性的演进,经历了数次的架构改造,才形成如今成熟的大规模分布式存储系统,有条不紊的管理着由数千台异构机型组成的机器集群,得以支撑每天千万亿级的访问.键值以及 P ...

  9. 微信后台基于时间序的新一代海量数据存储架构的设计实践

    本文作者腾讯WXG后台开发工程师jeryyzhang,收录时有改动,感谢原作者的分享. 1.引言 大约3年前,微信技术团队分享了<微信后台基于时间序的海量数据冷热分级架构设计实践>一文,文 ...

最新文章

  1. Flutter开发之《闲鱼的探索与收获》笔记(51)
  2. 使用Leaflet创建地图拓扑图
  3. 《KAFKA官方文档》入门指南(二)
  4. 获取应用程序根目录物理路径(Web and Windows)
  5. STM32应用文件系统--W25Q256(RTT系统)
  6. JAVA流-File文件
  7. Android手机安装谷歌服务框架
  8. 前端面试题—2021年web前端开发面试题
  9. 顶级摄影师的磨皮美白利器Portraiture,支持搭配微设证件大师使用
  10. 如何使用Excel绘制图表?
  11. 计算机科学学院凤凰院徽,数学科学学院院徽、院训展示
  12. 计算机教学能力提升体会,学习《信息技术助力教学能力提高》感悟
  13. STM32F429_DWM物联网开发板
  14. python实现截取视频中特定帧进行保存功能
  15. 高度优先左高树(HBLT) - C语言
  16. 微信小程序联合视频播放器插件的使用
  17. 搜索c语言作业答案的软件,吉林大学软件学院C语言作业参考答案.doc
  18. stc15XX单片机的EPROM读写
  19. 史上最全的各类奖学金、各种称号、各种职位中英文对照
  20. 所谓“尽人事,听天命”

热门文章

  1. fabio 安装试用实际使用的几个问题
  2. 【云原生】AI云开发平台——AI Model Foundry介绍(开发者可免费体验AI训练模型)
  3. ibm aix_IBM AIX设备驱动程序开发
  4. Angular真有React开发人员讲得那么差劲?
  5. tensorflow的安装和求解泊松方程
  6. win10开机慢怎么解决_win10开机速度变慢的解决方法教程
  7. php开启sockets模块,wdlinux 增加php的sockets模块
  8. 控制JetsonNano风扇命令
  9. 深入 JavaScript 中的默认参数!
  10. MySQL - 5.7.31 - winx64 安装教程