tbox协程使用之切换与等待
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等接口
这里主要讲讲,基础的切换调度如何使用。。
yield切换
这个的使用非常简单,直接上代码吧,嘿嘿。。
static tb_void_t switchfunc(tb_cpointer_t priv)
{
// 获取传入的参数
tb_size_t count = (tb_size_t)priv;
while (count--)
{
// 打印当前协程id
tb_trace_i("[coroutine: %p]: %lu", tb_coroutine_self(), count);
// 让出当前协程,进行切换
tb_coroutine_yield();
}
}
tb_int_t main(tb_int_t argc, tb_char_t** argv)
{
// 初始化tbox
if (!tb_init(tb_null, tb_null)) return -1;
// 初始化一个调度器实例
tb_co_scheduler_ref_t scheduler = tb_co_scheduler_init();
if (scheduler)
{
// 开启一个协程,传递switchfunc切换函数和参数10,最后一个参数指定栈大小,传0使用默认值
tb_coroutine_start(scheduler, switchfunc, (tb_cpointer_t)10, 0);
// 开启协程,使用指定的栈大小:8192
tb_coroutine_start(scheduler, switchfunc, (tb_cpointer_t)10, 8192);
/* 运行调用,开始运行里面的所有协程
*
* 第二个参数指定是否启用独占模式,这个稍后细讲
*/
tb_co_scheduler_loop(scheduler, tb_true);
// 退出调度器
tb_co_scheduler_exit(scheduler);
}
// 退出tbox
tb_exit();
}
所有协程执行完后,就会从loop调用处返回,当然在协程函数内部也是可以嵌套开启新协程的
这个时候第一个参数就不需要显示指定scheduler了,传tb_null表示在当前调度器环境中开新协程,例如:
static tb_void_t switchfunc2(tb_cpointer_t priv)
{
// ..
}
static tb_void_t switchfunc(tb_cpointer_t priv)
{
// 在当前协程函数内,开启一个新协程
tb_coroutine_start(tb_null, switchfunc2, tb_null, 0);
// 获取传入的参数
tb_size_t count = (tb_size_t)priv;
while (count--)
{
// 让出当前协程,进行切换
tb_coroutine_yield();
}
}
独占模式
上面的代码中提到的独占模式,需要特殊说明下,一般情况下,传tb_false到loop()中,不启用此模式是最为稳妥的。
因为这样每个scheduler对应的线程都会在Tls中维护自己的scheduler引用,使得协程中所有操作,都回去访问当前线程tls对应的独立scheduler,互不干涉。
这个在存在多个scheduler的情况,尤为重要,当时这样多少会有些tls操作上的性能损耗,像server端一般只有一个scheduler的情况下,就没必要放到独立tls中去了
可以传入tb_true启用独占模式,告诉tb_co_scheduler_loop(),我当前不需要tls维护,只需要一个全局scheduler变量来维护就行了
这样的话,性能会提升一些,因此在只有一个scheduler存在的情况下,启用独占效率会高些。。
sleep等待
tbox的tb_sleep和tb_msleep()接口,是可以原生支持协程的,在协程外就是线程等待,在协程内就是协程等待。
当然也可以直接使用协程的接口:tb_coroutine_sleep()
例如:
static tb_void_t sleepfunc(tb_cpointer_t priv)
{
while (1)
{
// 等待10ms,切换到其他协程,直到10ms后才会切换回来继续执行
tb_msleep(10);
}
}
resume/suspend接口
挂起域恢复,跟yield的区别就是,被suspend挂起的协程,默认是不会被切换调度回来的,除非执行resume恢复它。
因此这两个接口是成对使用的,像sleep,lock和semaphore的内部实现,也是基于此套接口。
这两个接口还有个功能,就是可以在两个协程间,更加快速方便的传递一些参数数据,进行交互,而不需要channel支持。。
例如:
static tb_void_t resumefunc(tb_cpointer_t priv)
{
// 获取suspend协程引用
tb_coroutine_ref_t coroutine = (tb_coroutine_ref_t)priv;
/* 恢复suspend协程,传递参数"hello suspend!"给suspend()作为其返回值
*
* retval为suspend()中传入的参数:"hello resume!"
*/
tb_char_t const* retval = tb_coroutine_resume(coroutine, "hello suspend!");
}
static tb_void_t suspendfunc(tb_cpointer_t priv)
{
// 开启一个恢复协程,传入当前协程引用
tb_coroutine_start(tb_null, resumefunc, tb_coroutine_self(), 0);
/* 挂起当前协程,传递参数"hello resume!"给resume()作为其返回值
*
* retval为resume()中传入的参数:"hello suspend!"
*/
tb_char_t const* retval = tb_coroutine_suspend("hello resume!");
}
当然,如果不需要交互数据,那么只需要传tb_null就行了。。
个人主页:TBOOX开源工程
原文出处:http://tboox.org/cn/2016/10/29/coroutine-switch/
tbox协程使用之切换与等待的更多相关文章
- 并发异步编程之争:协程(asyncio)到底需不需要加锁?(线程/协程安全/挂起/主动切换)Python3
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_208 协程与线程向来焦孟不离,但事实上是,线程更被我们所熟知,在Python编程领域,单核同时间内只能有一个线程运行,这并不是什么 ...
- GJM : 进程、线程和协程的理解
感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创发表于 [请点击连接前往] ,未经 ...
- Queue、进程、线程、协程
参考博客地址 http://www.cnblogs.com/alex3714/articles/5230609.html 1.python GIL全局解释器锁 python调用的操作系统的原生线程,当 ...
- 写个百万级别full-stack小型协程库——原理介绍
其实说什么百万千万级别都是虚的,下面给出实现原理和测试结果,原理很简单,我就不上图了: 原理:为了简单明了,只支持单线程,每个协程共享一个4K的空间(你可以用堆,用匿名内存映射或者直接开个数组也都是可 ...
- Python 协程总结
Python 协程总结 理解 协程,又称为微线程,看上去像是子程序,但是它和子程序又不太一样,它在执行的过程中,可以在中断当前的子程序后去执行别的子程序,再返回来执行之前的子程序,但是它的相关信息还是 ...
- Python并发编程协程(Coroutine)之Gevent
Gevent官网文档地址:http://www.gevent.org/contents.html 基本概念 我们通常所说的协程Coroutine其实是corporate routine的缩写,直接翻译 ...
- 再议Python协程——从yield到asyncio
协程,英文名Coroutine.前面介绍Python的多线程,以及用多线程实现并发(参见这篇文章[浅析Python多线程]),今天介绍的协程也是常用的并发手段.本篇主要内容包含:协程的基本概念.协程库 ...
- Golang 之协程详解
转自:https://www.cnblogs.com/liang1101/p/7285955.html 一.Golang 线程和协程的区别 备注:需要区分进程.线程(内核级线程).协程(用户级线程)三 ...
- 协程与Epoll的配合
想快速了解协程与网络调用的原来么,那么请赶紧关闭本页,因为下面都是在扯淡. 这几天是端午假期,第一天大算照着网上一大堆基于ucontext来写协程的文章自己也写一个简单的协程实现.于是第一天我就开始动 ...
随机推荐
- ElasticSearch 7.x 默认不在支持指定索引类型
原文:ElasticSearch 7.x 默认不在支持指定索引类型 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://bl ...
- vue项目报错,解决Module build failed: Error: Cannot find module 'node-sass' 问题
1.报错问题 1 E:\WebStormFile\treehole-manage>npm run dev > xc-ui-pc-sysmanage@1.0.0 dev E:\WebStor ...
- java中的Excel导出功能
public void exportExcel(Long activityId, HttpServletResponse response) throws IOException { // 获取统计报 ...
- Centos 的防火墙(firewalld,iptables)
Centos系统防火墙介绍 概述: 1.Filewalld(动态防火墙)作为redhat7系统中变更对于netfilter内核模块的管理工具: 2.iptables service 管理防火墙规则的模 ...
- Map和Set的联系
Java中的集合 Java中的集合包括三大类,它们是Set.List和Map,它们都处于java.util包中,Set.List和Map都是接口,它们有各自的实现类.Set的实现类主要有HashSet ...
- Zabbix分布式监控系统实践 自定义配置
https://www.zabbix.com/wiki/templates/start 环境介绍OS: Ubuntu 10.10 Server 64-bitServers:zabbix-server: ...
- MAN VGEXTEND
VGEXTEND(8) VGEXTEND(8) NAME/名称 vgexten ...
- 运行 tensorboard
使用下面命令总是报错: tensorboard --logdir=mylogdir tensorboard --logdir='./mylogdir' 正确命令 tensorboard --logdi ...
- [洛谷P3205] HNOI2010 合唱队
问题描述 为了在即将到来的晚会上有更好的演出效果,作为AAA合唱队负责人的小A需要将合唱队的人根据他们的身高排出一个队形.假定合唱队一共N个人,第i个人的身高为Hi米(1000<=Hi<= ...
- Springboot ,1开启配置与2.扫描包(控制层,service层)二个注解@EnableAutoConfiguration,@ComponentScan 合并成一个注解@SpringBootApplication
//@EnableAutoConfiguration//@ComponentScan(value= {"com.foen.cloud.controller.*","com ...