前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >libuv源码阅读(15)--ref-timer

libuv源码阅读(15)--ref-timer

原创
作者头像
wanyicheng
修改于 2021-03-14 09:03:17
修改于 2021-03-14 09:03:17
63800
代码可运行
举报
运行总次数:0
代码可运行
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <stdio.h>

#include <uv.h>

uv_loop_t *loop;
uv_timer_t gc_req;
uv_timer_t fake_job_req;

void gc(uv_timer_t *handle) {
    fprintf(stderr, "Freeing unused objects\n");
}

void fake_job(uv_timer_t *handle) {
    fprintf(stdout, "Fake job done\n");
}

int main() {
    loop = uv_default_loop();

    uv_timer_init(loop, &gc_req);
    // 垃圾回收信号函数 持续执行 解除引用 loop的运行是由下面那个定时器驱动的 所以在它结束后loop也会结束
    uv_unref((uv_handle_t*) &gc_req);
    // 重复执行参数设置
    uv_timer_start(&gc_req, gc, 0, 2000);

    // could actually be a TCP download or something
    // 虚假的任务执行 9秒后结束 只执行一次 它结束后由于loop没有保持引用的激活的timer了 就停止了
    uv_timer_init(loop, &fake_job_req);
    uv_timer_start(&fake_job_req, fake_job, 9000, 0);
    return uv_run(loop, UV_RUN_DEFAULT);
}

先看下结构体:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
struct uv_timer_s {
  UV_HANDLE_FIELDS
  UV_TIMER_PRIVATE_FIELDS
};

#define UV_HANDLE_FIELDS                                                      \
  /* public */                                                                \
  void* data;                                                                 \
  /* read-only */                                                             \
  uv_loop_t* loop;                                                            \
  uv_handle_type type;                                                        \
  /* private */                                                               \
  uv_close_cb close_cb;                                                       \
  void* handle_queue[2];                                                      \
  union {                                                                     \
    int fd;                                                                   \
    void* reserved[4];                                                        \
  } u;                                                                        \
  UV_HANDLE_PRIVATE_FIELDS                                                    \
  
#define UV_HANDLE_PRIVATE_FIELDS                                              \
  uv_handle_t* next_closing;                                                  \
  unsigned int flags;                                                         \
  
#define UV_TIMER_PRIVATE_FIELDS                                               \
  uv_timer_cb timer_cb;                                                       \
  void* heap_node[3];                                                         \
  uint64_t timeout;                                                           \
  uint64_t repeat;                                                            \
  uint64_t start_id;

主要包含 timercb 和用于最小时间堆节点字段heap_node等;它由一个基础hanlder类型和自身独有的属性构成

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) {
  // 同用handler的初始化
  uv__handle_init(loop, (uv_handle_t*)handle, UV_TIMER);
  handle->timer_cb = NULL;
  handle->timeout = 0;
  handle->repeat = 0;
  return 0;
}


int uv_timer_start(uv_timer_t* handle,
                   uv_timer_cb cb,
                   uint64_t timeout,
                   uint64_t repeat) {
  uint64_t clamped_timeout;

  if (uv__is_closing(handle) || cb == NULL)
    return UV_EINVAL;

  if (uv__is_active(handle))
    uv_timer_stop(handle);
  
  // 计算绝对时间超时值
  clamped_timeout = handle->loop->time + timeout;
  if (clamped_timeout < timeout)
    clamped_timeout = (uint64_t) -1;

  handle->timer_cb = cb;
  handle->timeout = clamped_timeout;
  handle->repeat = repeat;
  /* start_id is the second index to be compared in timer_less_than() */
  handle->start_id = handle->loop->timer_counter++;

  // 插入loop的最小时间堆中
  heap_insert(timer_heap(handle->loop),
              (struct heap_node*) &handle->heap_node,
              timer_less_than);
  // 激活handler
  uv__handle_start(handle);

  return 0;
}

int uv_timer_stop(uv_timer_t* handle) {
  if (!uv__is_active(handle))
    return 0;

  heap_remove(timer_heap(handle->loop),
              (struct heap_node*) &handle->heap_node,
              timer_less_than);
  uv__handle_stop(handle);

  return 0;
}

// 第一个定时器会重置执行 因为设置了repeat的重复时间
int uv_timer_again(uv_timer_t* handle) {
  if (handle->timer_cb == NULL)
    return UV_EINVAL;

  if (handle->repeat) {
    uv_timer_stop(handle);
    uv_timer_start(handle, handle->timer_cb, handle->repeat, handle->repeat);
  }

  return 0;
}

//  一次性定时器执行完回调后就会清除
void uv__run_timers(uv_loop_t* loop) {
  struct heap_node* heap_node;
  uv_timer_t* handle;

  for (;;) {
    heap_node = heap_min(timer_heap(loop));
    if (heap_node == NULL)
      break;

    handle = container_of(heap_node, uv_timer_t, heap_node);
    if (handle->timeout > loop->time)
      break;

    uv_timer_stop(handle);
    uv_timer_again(handle);
    handle->timer_cb(handle);
  }
}

总结:定时器就是指定时间:一次性或者重复执行的任务,但是由于loop自身循环过程中会有监听io事件等一系列逻辑,还要跑其他类型的任务如idle check等,所以这个定时时间并不完全精准。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

评论
登录后参与评论
暂无评论
推荐阅读
从实例看muduo网络库各模块交互过程
1、channel 2、Poller 和它的子类 EpollPoller 3、EventLoop 4、Thread、EventLoopThread、EventLoopThreadPool 5、Sock、Acceptor 6、Buffer 7、TcpServer、TCPConnection
看、未来
2021/10/09
4060
从实例看muduo网络库各模块交互过程
【C++仿Muduo库 #1】基本了解
仿muduo库One Thread One Loop式主从Reactor模型实现高并发服务器:
IsLand1314
2025/05/13
470
【C++仿Muduo库 #1】基本了解
(八)高性能服务器架构设计总结2——以flamigo服务器代码为例
说了这么多,我们来以flamingo的服务器程序的网络框架设计为例来验证上述介绍的理论。flamingo的网络框架是基于陈硕的muduo库,改成C++11的版本,并修改了一些bug。在此感谢原作者陈硕。flamingo的源码可以在这里下载:https://github.com/baloonwj/flamingo,打不开github的可以移步csdn:http://download.csdn.net/detail/analogous_love/9805797。
范蠡
2018/07/25
9870
muduo源码分析(一)-整体框架说明
muduo是chenshuo开源的一个基于reactor pattern的多线程网络库。同时他也写了一本关于此网络库的书《Linux多线程服务端编程:使用muduo C++网络库》,推荐阅读。
路小饭
2019/03/08
4.4K0
muduo源码分析(一)-整体框架说明
muduo源码分析(二)-Protobuf RPC流程
以源代码中muduo/examples/protobuf/rpc/为例,梳理pb rpc+muduo的处理流程。
路小饭
2019/03/09
3K0
muduo源码分析(二)-Protobuf RPC流程
muduo网络库学习之EventLoop(二):进程(线程)wait/notify 和 EventLoop::runInLoop
s1mba
2017/12/28
1.3K0
muduo网络库学习之EventLoop(二):进程(线程)wait/notify 和 EventLoop::runInLoop
关于muduo网络库的注解
http://blog.csdn.net/liuxuejiang158blog/article/details/17056537#comments
bear_fish
2018/09/19
7910
muduo网络库学习之EventLoop(三):Socket、Acceptor、TcpServer、TcpConnection(连接建立,接收消息)
s1mba
2017/12/28
1.3K0
muduo网络库学习之EventLoop(三):Socket、Acceptor、TcpServer、TcpConnection(连接建立,接收消息)
muduo网络编程库阅读
遵从Reactor模型,简单阅读了下。 来到目录examples/ace/loggin/server.cc server.cc main->LogServer->EventLoop和TcpServer
平凡的学生族
2021/01/07
5710
(八)高性能服务器架构设计总结2——以flamigo服务器代码为例
说了这么多,我们来以flamingo的服务器程序的网络框架设计为例来验证上述介绍的理论。flamingo的网络框架是基于陈硕的muduo库,改成C++11的版本,并修改了一些bug。在此感谢原作者陈硕。flamingo的源码可以在这里下载:https://github.com/baloonwj/flamingo,打不开github的可以移步csdn:http://download.csdn.net/detail/analogous_love/9805797。 上文介绍的核心线程函数的while循环位于eve
范蠡
2018/04/04
1.2K0
muduo网络库学习之EventLoop(六):TcpConnection::send()、shutdown()、handleRead()、handleWrite()
该文章是一篇技术博客,主要介绍了如何利用muduo库实现一个高性能的TCP服务端。文章首先介绍了muduo库的基本概念和特点,然后详细讲解了如何利用muduo库实现一个简单的TCP服务端。最后,文章通过一个实际的例子演示了如何利用muduo库解决实际问题。
s1mba
2017/12/28
1.6K0
muduo网络库学习之EventLoop(六):TcpConnection::send()、shutdown()、handleRead()、handleWrite()
缩略muduo库(4):事件循环 EventLoop
每一个线程都有一个EventLoop,每个loop里面都会有很多的channel,每个channel的任务都要在自己的线程中完成。 为了管理这些线程,设置了一份获取线程ID的代码,辅助管理。
看、未来
2021/10/09
2760
缩略muduo库(8):TcpConnection
最近VScode坏了,莫名其妙连不上虚拟机了,很难受。 已经判定不是Linux的问题,因为用cmd可以远程连接上。 所以这份就用VS先顶一下了,报了一堆的错也看不清楚。
看、未来
2021/10/09
3000
【项目日记】仿mudou的高并发服务器 --- 实现基础高并发服务器基础模块
实现高并发服务器的基础是实现基于事件触发的Reactor模型,通过Reactor模型对事件进行统一管理。对此我们需要设计:
叫我龙翔
2024/11/24
1330
【项目日记】仿mudou的高并发服务器 --- 实现基础高并发服务器基础模块
muduo网络库学习之EventLoop(五):TcpConnection生存期管理(连接关闭)
s1mba
2018/01/03
1.5K0
muduo网络库学习之EventLoop(五):TcpConnection生存期管理(连接关闭)
muduo网络库学习之EventLoop(四):EventLoopThread 类、EventLoopThreadPool 类
1、EventLoopThread(IO线程类) 任何一个线程,只要创建并运行了EventLoop,都称之为IO线程 IO线程不一定是主线程 muduo并发模型one loop per thread + threadpool(计算线程池) 为了方便今后使用,定义了EventLoopThread类,该类封装了IO线程 EventLoopThread创建了一个线程 在线程函数中创建了一个EvenLoop对象并调用EventLoop::loop 多个IO线程可以用IO线程池来管理,对应的类是EventLoo
s1mba
2018/01/15
1.6K0
muduo网络库学习之EventLoop(四):EventLoopThread 类、EventLoopThreadPool 类
缩略muduo库(9):TcpServer
准备讲解了,这里就直接放代码吧。 #pragma once #include "EventLoop.hpp" #include "Accept.hpp" #include "EventLoopThreadPool.hpp" #include "InetAddr.hpp" #include "nocopyable.hpp" #include "callback.hpp" #include <string> #include <functional> #include <atomic> #include <
看、未来
2021/10/09
3510
muduo TcpServer粗略过程
使用 \muduo\examples\asio\chat\server.cc 作例子
forxtz
2020/10/10
5750
【#2】介绍第三方库
🔥 JSONCPP 是一个开源的 C++ 库,用于解析和生成 JSON(JavaScript Object Notation)数据。它提供了简单易用的接口,支持 JSON 的序列化和反序列化操作,适用于处理配置文件、网络通信数据等场景。
IsLand1314
2025/03/26
1100
【#2】介绍第三方库
(三)一个服务器程序的架构介绍
本文将介绍我曾经做过的一个项目的服务器架构和服务器编程的一些重要细节。 一、程序运行环境 操作系统:centos 7.0 编译器:gcc/g++ 4.8.3 cmake 2.8.11 mysql数据库:5.5.47 项目代码管理工具:VS2013 一、程序结构 该程序总共有17个线程,其中分为9个数据库工作线程D和一个日志线程L,6个普通工作线程W,一个主线程M。(以下会用这些字母来代指这些线程) (一)、数据库工作线程的用途 9个数据库工作线程在线程启动之初,与mysql建立连接,也就是说每个线程都与my
范蠡
2018/04/04
1.1K0
推荐阅读
相关推荐
从实例看muduo网络库各模块交互过程
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档