这篇文章讲讲简单上手libco,第一次使用感觉细节还是挺多的。
程序:实现两个协程对全局变量的交替 +1 操作。
(具体细节写在代码注释里面了)
#include <co_routine.h>
#include <stdlib.h>
#include <cstdio>
#include <queue>
#include <iostream>
#include <unistd.h>
using namespace std;
int id = 0;
void *fun1(void *arg)
{
stCoRoutine_t *co = static_cast<stCoRoutine_t *>(arg);
/*
注意逻辑:
这里我们需要while(true),为啥?
我们要始终牢记,协程是可以中断的函数,也就是在函数某个位置中断了,回来的话还是在这个位置;
所以如果没有while(true),通过co_yield_ct();切出去;
然后在切回来的时候就直接执行return nullptr;了,协程就直接结束了!
*/
while(true)
{
cout<<"协程1 对id+1:"<<(++id)<<'\n';
co_yield_ct(); //id+1之后,当前协程挂起,CPU切回到主函数
}
/*
co_yield_ct(); 这个是获取当前协程的"协程控制块",然后调用co_yield_env()挂起(切回去)
为什么不直接用co_yield_env()呢?
查看源码可以发现co_yield_env()并没有在<co_routine.h>中声明;
而是在<co_routine.cpp>中,co_yield_ct() 对其进行了封装。(不香吗?)
对于co_yield(co)也能将协程挂起,但是不知道为啥会段错误...有大佬知道的指点一下
*/
return nullptr;
}
void *fun2(void *arg)
{
stCoRoutine_t *co = static_cast<stCoRoutine_t *>(arg);
while(true)
{
cout<<"协程2 对id+1:"<<(++id)<<'\n';
co_yield_ct();
}
return nullptr;
}
int main()
{
//创建两个协程
stCoRoutine_t *co1,*co2;
/*
这里注意:
co_create 的第四个参数是函数fun1的参数,只有一个;
如果想要传多个参数怎么办?
我们可以把要传的参数封装成一个struct或者class;
然后传一个struct class的指针就行;
由于参数是void*类型的,所以在fun1函数中把arg用static_cast<>()转换一下就行。
*/
co_create(&co1, nullptr, fun1, co1);
co_create(&co2, nullptr, fun2, co2);
/*
注意逻辑:
这里需要while(true),
因为这个程序中我们并没有通过其他事情(比如上篇文章代码demo中的cond去"阻塞"和唤醒)去使得事件就绪;
所以如果不用while(true)的话,执行到协程co2切回主程序的时候,co_eventloop就会一直循环检测了;
而我们没有事件就绪,所以就卡在这了...
*/
while(true)
{
co_resume(co1);
sleep(1);
co_resume(co2);
sleep(1);
}
//创建eventloop,事件循环
co_eventloop(co_get_epoll_ct(), nullptr, nullptr);
return 0;
}
下面是运行结果: