概念
协程,是一个程序组件,其功能其实就是执行一段可由用户随时中断或继续运行的代码,可与异步机制结合。一个线程中,可存在多个协程。
实现
windows平台下具有Fiber概念,其API提供了创建CreateFiberEx、删除DeleteFiber、切换SwitchToFiber的接口,Fiber可看作是协程在windows平台下的实现。
linux平台下我这里使用glibc提供的ucontext实现(感谢网友的贡献,让我抄一下代码),需手动实现保存运行环境的上下文。
我为了简化编程,使用了C++11新特性下的std::function、thread_local。使用thread_local可直接获得本线程的协程调度器,简便,且不用自己根据线程环境来获取到对应的协程调度器,但其局限性就是不可跨线程调度协程。本文只实现了linux、windows两个平台的环境。
其他具体的信息,这里就不说了,网上也挺多关于协程概念的描述。
提供的接口:
/*
* 开启当前线程的协程环境,只有开启后,才能对协程进行操作
* 只对调用者所在线程有效
*/
extern void OpenCoroutineEnv();
/*
* 关闭当前线程的协程环境,关闭后,当前线程的协程的所有操作将无效
* 只对调用者所在线程有效
*/
extern void CloseCoroutineEnv();
/*
* 在当前线程中创建协程
*/
extern Awaitable CreateCoroutine(Callable &&callable);
/*
* 在当前线程中创建协程,并立即运行
*/
extern Awaitable CreateAndStartCoroutine(Callable &&callable);
/*
* 唤醒协程,在该协程上一次跳出的地方继续运行
* 不可跨线程唤醒协程,只能对当前线程的协程操作,否则会得到意想不到的效果
*/
extern void ResumeCoroutine(Awaitable awaiter);
/*
* 跳出当前协程
*/
extern void YieldCoroutine();
/*
* 终止当前协程
*/
extern void EndCoroutine();
/*
* 获取协程的状态
*/
extern CoroutineStatus GetCoroutineStatus(Awaitable awaiter);
/*
* 获取当前正在运行的协程
*/
extern Awaitable GetCurrentCoroutine();
// 简化操作的命名
#define co_yield YieldCoroutine();
#define co_return EndCoroutine();
#define co_create(c) CreateCoroutine([&](){c;});
#define co_await(c) CreateAndStartCoroutine([&](){c;});
#define co_resume(c) ResumeCoroutine(c);
#define co_status GetCoroutineStatus(GetCurrentCoroutine());
#define co_running GetCurrentCoroutine();
源码
语言环境:C++11
头文件:Coroutine.h
#ifndef COROUTINE_H
#define COROUTINE_H
#include
enum class CoroutineStatus
{
DEAD, // 终止状态
RUNNABLE, // 就绪状态
RUNNING, // 运行状态
SUSPEND // 暂停状态
};
using Awaitable = long long;
using Callable = std::function;
/*
* 开启当前线程的协程环境
* 只对调用者所在线程有效
*/
extern void OpenCoroutineEnv();
/*
* 关闭当前线程的协程环境,关闭后,当前线程的协程的所有操作将无效
* 只对调用者所在线程有效
*/
extern void CloseCoroutineEnv();
/*
* 在当前线程中创建协程
*/
extern Awaitable CreateCoroutine(Callable &&callable);
/*
* 在当前线程中创建协程,并立即运行
*/
extern Awaitable CreateAndStartCoroutine(Callable &&callable);
/*
* 唤醒协程,在该协程上一次跳出的地方继续运行
* 不可跨线程唤醒协程,只能对当前线程的协程操作,否则会得到意想不到的效果
*/
extern void ResumeCoroutine(Awaitable awaiter);
/*
* 跳出当前协程
*/
extern void YieldCoroutine();
/*
* 终止当前协程
*/
extern void EndCoroutine();
/*
* 获取协程的状态
*/
extern CoroutineStatus GetCoroutineStatus(Awaitable awaiter);
/*
* 获取当前正在运行的协程
*/
extern Awaitable GetCurrentCoroutine();
// 操作命名
#define co_yield YieldCoroutine();
#define co_return EndCoroutine();
#define co_create(c) CreateCoroutine([&](){c;});
#define co_await(c) CreateAndStartCoroutine([&](){c;});
#define co_resume(c) ResumeCoroutine(c);
#define co_status GetCoroutineStatus(GetCurrentCoroutine());
#define co_running GetCurrentCoroutine();
#endif // COROUTINE_H
源文件:Coroutine.cpp
#include "Coroutine.h"
#include
测试代码
#include
#include "Coroutine.h"
static void func(int min, int max)
{
int c = 0;
for(int i = min; i <= max; ++i)
{
std::cout << i << std::endl;
if(++c % 5 == 0)
{
co_yield
}
if(c % 10 == 0)
{
co_return
}
}
}
static void func2(int min, int max)
{
int c = 0;
for(int i = min; i <= max; ++i)
{
std::cout << i << std::endl;
if(++c % 5 == 0)
{
co_yield
}
}
}
static void main_pro()
{
OpenCoroutineEnv();
Awaitable cid1 = co_await(func(10, 29));
Awaitable cid2 = co_await(func(30, 49));
Awaitable cid3 = co_await(func2(70, 100));
co_resume(cid1);
co_resume(cid2);
co_resume(cid3);
co_resume(cid1);
co_resume(cid2);
co_resume(cid3);
co_resume(cid1);
co_resume(cid2);
co_resume(cid3);
co_resume(cid1);
co_resume(cid2);
co_resume(cid3);
CloseCoroutineEnv();
}
int main()
{
main_pro();
return 0;
}
测试结果
如有问题,欢迎指出!