tbox内部的所有io操作都是原生支持协程的,可以在线程和协程间任意切换,内置基于轮询的io调度器(epoll, kqueue等,后续还会支持iocp).
我们在socket操作的时候,只需要像平常顺序编程那样操作就可以实现异步并发收发数据。
这里先给个简答的文件服务器的例子,可参考下,代码非常简单:
这个文件服务器的功能很简单,就是不停的接收连接,然后开新协程,进行文件传输。
通过协程,从原始socket写起,也只需要不到100行代码,就可以实现一个高并发的文件服务器。
此处用到了tb_socket_sendf
直接对文件句柄操作,发送到socket,内部使用sendfile实现,不需要再上层开buffer读文件发送,因此效率会有明显提升。
而tb_socket_wait
内部会去将被等待的socket加入poll池,进行等待调度,直到事件到来才会继续执行。
并且协程的io调度器内部做了优化,不会去频繁得从轮询池里面添加删除socket,内部对epoll_ctl等操作会有个缓存,因此效率还是非常高的。
core/tools
目录以及msys工具链,在windows上使用xmake自编译core源码进行安装,优化xmake源码磁盘空间xmake/packages
,默认模板安装不再内置二进制packages,暂时需要手动放置,以后再做成自动包依赖下载编译-def:xxx.def
tbox的协程实现,是stackfull模式的,需要指定独立堆栈和协程函数,目前暂时还不能像golang那样实现堆栈的动态增长,之后会对其进行支持。
目前提供下面一些功能特性:
1. 提供yield切换调度支持,这个是必须的哈
2. 提供suspend(挂起)/resume(恢复)协程接口,不同于yield的是,被suspend后,如果不显示调用resume恢复它,是永远不会被调度到的
3. 提供sleep等待接口支持
4. 提供io调度支持,支持socket等io等待(内部使用epoll, poll, kqueue, select, poll等接口调度)
5. 原生支持stream,socket,http等模块的协程支持,可与线程进行无缝切换
6. 提供channel同道,进行协程间交互通信
7. 提供lock,semaphore等接口
协程现在已经不是个新东西了,很多语言都提供了原生支持,也有很多开源的库也提供了协程支持。
最近为了要给tbox增加协程,特地研究了下各大开源协程库的实现,例如:libtask, libmill, boost, libco, libgo等等。
他们都属于stackfull协程,每个协程有完整的私有堆栈,里面的核心就是上下文切换(context),而stackless的协程,比较出名的有protothreads,这个比较另类,有兴趣的同学可以去看下源码,这里就不多说了。
那么现有协程库,是怎么去实现context切换的呢,目前主要有以下几种方式:
各个协程协程库的切换效率的基准测试,可以参考:切换效率基准测试报告
要研究ucontext,其实只要看下libtask的实现就行了,非常经典,这套接口其实效率并不是很高,而且很多平台已经标记为废弃接口了(像macosx),目前主要是在linux下使用
libtask里面对不提供此接口的平台,进行了汇编实现,已达到跨平台的目的,
ucontext相关接口,主要有如下四个: