浅析libuv源码-获取精确时间

 在Timer模块中有提到,libuv控制着延迟事件的触发,那么必须想办法精确控制时间。

  如果是JS,获取当前时间可以直接通过Date.now()得到一个时间戳,然后将两段时间戳相减得到时间差。一般情况下当然没有问题,但是这个方法并不保险,因为本地计算机时间可以修改。

  libuv显然不会用这么愚蠢的办法来计算时间,C++内部有更为精妙的方法来处理这个事。

 

  首先在上一节中,一个简单的事件轮询代码如下:

复制代码
int main() {     uv_loop_t *loop = uv_default_loop();     uv_run(loop, UV_RUN_DEFAULT); }
复制代码

  这里的uv_default_loop会生成一个默认的静态对象,负责管理事件轮询,而这个对象有一个属性,则负责记录当前的时间,如下:

复制代码
  /* The current time according to the event loop. in msecs. */   uint64_t time; 
复制代码

  简单讲就是记录当前这一轮事件开始处理的时间,单位为毫秒。

  在初始化之后,就会执行uv_run来开始事件轮询了,因为这节只讲时间,所以省略无关代码,如下:

复制代码
int uv_run(uv_loop_t *loop, uv_run_mode mode) {     // ...     // 查询是否有未处理事件    r = uv__loop_alive(loop);     if (!r)         // 表示处理完一轮事件 更新时间        uv_update_time(loop);      // 如果有未处理事件    while (r != 0 && loop->stop_flag == 0) {         // 这里也会更新时间        uv_update_time(loop);         // ...    } }
复制代码

  可见,每次轮询时都会更新时间,方法就是那个uv_update_time,源码如下:

复制代码
void uv_update_time(uv_loop_t* loop) {     // 返回一个时间    uint64_t new_time = uv__hrtime(1000);     // 检测数据合法性并赋值    assert(new_time >= loop->time);     loop->time = new_time; }  uint64_t uv__hrtime(double scale) {     LARGE_INTEGER counter;      if (hrtime_interval_ == 0) {         return 0;     }      if (!QueryPerformanceCounter(&counter)) {         
                        
关键字:
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信