如何采用libuv 构建 应用程序

如何采用libuv 构建 应用程序,第1张

libuv 是 Node 的新跨平台抽象层,用于抽象 Windows 的 IOCP 及 Unix 的 libev。作者打算在这个库的包含所有平台的差异性。

特性:

非阻塞 TCP 套接字

非阻塞命名管道

UDP

定时器

子进程生成

通过 uv_getaddrinfo 实现异步 DNS

异步文件系统 API:uv_fs_*

高分辨率时间:uv_hrtime

正在运行程序路径查找:uv_exepath

线程池调度:uv_queue_work

TTY控制的ANSI转义代码: uv_tty_t

文件系统事件现在支持 inotify, ReadDirectoryChangesW 和 kqueue。很快会支持事件端口:uv_fs_event_t

进程间的 IPC 与套接字共享:uv_write2

已受支持的平台:

Microsoft Windows *** 作系统,如 Windows XP SP2。使用 Visual Studio 或 MinGW 构建

Linux 2.6 使用 GCC 工具链

MacOS 使用 GCC 或 XCode 工具链

Solaris 121 或之后版本,使用 GCC 工具链

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

StartTimer(Interval, ExpiryAction)

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

StopTimer(TimerId)

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

PerTickBookkeeping()

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

具体的代码实现思路就是:

StartTimer的时候,把 当前时间 + Interval

作为key放入一个容器,然后在Loop的每次Tick里,从容器里面选出一个最小的key与当前时间比较,如果key小于当前时间,则这个key代表的

timer就是expired,需要执行它的ExpiryAction(一般为回调)。

这里有两个实现的细节:

获取当前时间

包含时间精度,使用系统时间还是CPU时间(asio里的deadline_timer和steady_timer的区别)

常用的API是:

Windows: QueryPerformanceFrequency() 和 QueryPerformanceCounter()

Linux: clock_gettime()

OSX: gettimeofday()或者mach_absolute_time()

当然在C++11里也可以偷懒使用chrono的high_resolution_clock std::chrono::high_resolution_clock

2.timer容器的选择

容器应该能够在很短的时间内找到MinValue

最小堆的find-min复杂度是O(1),所以蛮受人喜欢的

STL里提供有堆的API,make_heap, push_heap, pop_heap, sort_heap

3. PerTickBookkeeping是放在主循环线程还是另起线程

另起线程需要做好线程间通信,asio和skynet有单独的timer线程

一些代码实现:

这是boost.asio的实现的timer_queue,用的是最小堆

asio/timer_queue.hpp at master · chriskohlhoff/asio · GitHub

这是libuv的timer,采用的是红黑树实现(windows),linux下还是最小堆

libuv/timer.c at v1.x · libuv/libuv · GitHub

这是云风的skynet timer实现,采用链表实现

skynet/skynet_timer.c at master · cloudwu/skynet · GitHub


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/6165828.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-03-17
下一篇 2023-03-17

发表评论

登录后才能评论

评论列表(0条)

保存