特性:
非阻塞 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
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)