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来写协程的文章自己也写一个简单的协程实现.于是第一天我就开始动 ...
随机推荐
- 在vsCode中用git命令合并分支
提交修改代码到本地仓库 $ git commit -m "修改的东西的描述"切换到master主分支上 $ git checkout master拉取主分支上面的代码 $ git ...
- Linux压缩、解压
gzip压缩: 归档,压缩,yourFloder文件夹生成yourName.tar.gz: - tar -zcvf yourName.tar.gz yourFloder 解压yourName.tar. ...
- C# ASP.NET发送电子邮件System.Net.Mail
1.补充知识 (1)POP3和SMTP服务器是什么? 简单点来说:POP3 用于接收电子邮件 ,SMTP 用于发送电子邮件. (1)POP3具体指什么? POP3(Post Office Protoc ...
- C# 获取系统环境数据
using System; using System.Data; using System.Text.RegularExpressions; using System.Threading; names ...
- ARM Cortex-M底层技术(3)—编译内核的原理及其应用
概述: 当前开发中,我使用的Keil开发工具较多(keil526),故以keil为例进行介绍,其他开发环境大同小异. 1. 编译链接的定义 不管我们编写的代码有多么简单,都必须经过「编译 --> ...
- css定位选择兄弟元素,nth-of-type
<span class="input-group-btn" the-id="num-change"> <button class=" ...
- 5.xml约束技术--------schema
1.schema约束 (1)dtd语法:<!ELEMENT 元素名称 约束> (2)schema符合xml的语法,xml语句 (3)一个xml文件中只能有一个dtd,但是可以有多个sche ...
- 【leetcode】1037. Valid Boomerang
题目如下: A boomerang is a set of 3 points that are all distinct and not in a straight line. Given a lis ...
- CSS基础知识总结二
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/html"> ...
- Reporting Services 配置工具
使用 Reporting Services 配置管理器可配置 Reporting Services 安装.如果使用“仅文件”选项安装报表服务器,则必须使用此工具来配置服务器,才能使用该服务器.如果使用 ...