基于windows fiber的协程(coroutine)实现
一个非常简单,但是实用的协程实现,使用Windows的*Fiber
函数族(linux可以稍微改一下用*context
函数族)。
fco.h
#ifndef _MSC_VER
#error "this fast coroutine library only supports MSVC building chain"
#endif#include <Windows.h>
#include <cstdint>
#include <map>namespace fco {
static constexpr int ERR_NOT_EXIST_CO = -1;enum Status {READY, // Set up to READY when fco::newco() calledAWAIT, // Set up to AWAIT when fco::yield() called
};struct Scheduler;
struct Coroutine;struct Coroutine {void (*task)(Scheduler*, void*);void* userData;char status;LPVOID winFiber;
};struct Scheduler {std::map<int, Coroutine*> coroutines;int currentIdx;LPVOID main;
};void __stdcall __entry(LPVOID lpParameter);Scheduler* initialize();void destroy(Scheduler* s);int newco(Scheduler* scheduler, void (*task)(Scheduler*, void*),void* userData);void resume(Scheduler* s, int coid);void yield(Scheduler* scheduler);int current(Scheduler* scheduler);} // namespace fco
fco.cpp
#include "fco.h"// Initialize fco library, return a global scheduler
fco::Scheduler* fco::initialize() {Scheduler* sched = new Scheduler;sched->currentIdx = ERR_NOT_EXIST_CO;sched->main = ConvertThreadToFiber(NULL);return sched;
}// Release all resources
void fco::destroy(Scheduler* s) {for (auto& c : s->coroutines) {DeleteFiber(c.second->winFiber);}delete s;
}// This is should NEVER BE called on user land
void __stdcall fco::__entry(LPVOID lpParameter) {// Execute the task of current coroutineScheduler* s = (Scheduler*)lpParameter;Coroutine* currentCo = s->coroutines[s->currentIdx];(currentCo->task)(s, currentCo->userData);// Clean up executed tasks->coroutines.erase(s->coroutines.find(s->currentIdx));s->currentIdx = ERR_NOT_EXIST_CO;currentCo->status = Status::READY;DeleteFiber(currentCo->winFiber);delete currentCo;// Switch to entry functionSwitchToFiber(s->main);
}// Create new coroutine and return an unique identity
int fco::newco(Scheduler* scheduler, void (*task)(fco::Scheduler*, void*),void* userData) {Coroutine* co = new Coroutine;co->task = task;co->userData = userData;co->winFiber = CreateFiber(0, __entry, scheduler);if (co->winFiber == NULL) {return ERR_NOT_EXIST_CO;}co->status = Status::READY;int newCoId =scheduler->coroutines.size() != 0? scheduler->coroutines.end().operator--().operator*().first + 1: 0;scheduler->coroutines.insert(std::make_pair(newCoId, co));return newCoId;
}// Resume suspended coroutine by given coid
void fco::resume(fco::Scheduler* scheduler, int coid) {if (coid < 0) {return;}Coroutine* co = scheduler->coroutines[coid];if (co->status == Status::READY || co->status == Status::AWAIT) {scheduler->currentIdx = coid;scheduler->coroutines[scheduler->currentIdx]->status = Status::AWAIT;co->status = Status::READY;SwitchToFiber(co->winFiber);}
}// Yield CPU time to main coroutine
void fco::yield(fco::Scheduler* scheduler) {Coroutine* co = scheduler->coroutines[scheduler->currentIdx];co->status = Status::AWAIT;scheduler->currentIdx = ERR_NOT_EXIST_CO;SwitchToFiber(scheduler->main);
}// Get current running coroutine identity
int fco::current(Scheduler* scheduler) { return scheduler->currentIdx; }
example
- hello world
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <vector>
#include "fco.h"void bar(fco::Scheduler* s, void* param) {for (int i = 0; i < 5; i++) {std::cout << "world\n";fco::yield(s);}
}int main() {fco::Scheduler* s = fco::initialize();int barFunc = fco::newco(s, bar, nullptr);for (int i = 0; i < 5; i++) {std::cout << "hello\n";fco::resume(s, barFunc);}fco::destroy(s);return 0;
}
- 生产者消费者模型
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <vector>
#include "fco.h"std::vector<int> vec;void producer(fco::Scheduler* s, void* param) {while (vec.size() < 10) {int resource = rand();std::cout << "Producing " << resource << "\n";vec.push_back(resource);}fco::resume(s, (int)param);fco::yield(s);
}void consumer(fco::Scheduler* s, void* param) {int producerCo = fco::newco(s, producer, (void*)fco::current(s));while (true) {while (!vec.empty()) {int resource = vec.back();vec.pop_back();std::cout << "Consuming " << resource << "\n";}fco::resume(s, producerCo);}
}void factory() {fco::Scheduler* s = fco::initialize();int consumerCo = fco::newco(s, consumer, nullptr);fco::resume(s, consumerCo);fco::destroy(s);
}int main() {srand((int)time(0));factory();system("pause");return 0;
}
转载于:https://www.cnblogs.com/ysherlock/p/10010106.html
基于windows fiber的协程(coroutine)实现相关推荐
- 并发编程协程(Coroutine)之Gevent
并发编程协程之Gevent Gevent官网文档地址:http://www.gevent.org/contents.html 基本概念 我们通常所说的协程Coroutine其实是corporate r ...
- qemu核心机制分析-协程coroutine
关于协程coroutine前面的文章已经介绍过了,本文总结对qemu中coroutine机制的分析,qemu 协程coroutine基于:setcontext函数族以及函数间跳转函数siglongjm ...
- c++ 协程_Python3 协程(coroutine)介绍
本文首发于 at7h 的个人博客. 目前 Python 语言的协程从实现来说可分为两类: 一种是基于传统生成器的协程,叫做 generator-based coroutines,通过包装 genera ...
- c++ 协程_理解Python协程(Coroutine)
由于GIL的存在,导致Python多线程性能甚至比单线程更糟. GIL: 全局解释器锁(英语:Global Interpreter Lock,缩写GIL),是计算机程序设计语言解释器用于同步线程的一种 ...
- Unity 协程Coroutine综合测试
Unity 协程Coroutine综合测试 1 using UnityEngine; 2 using System.Collections; 3 using System.Text; 4 5 publ ...
- U3D协程Coroutine之WWW与Update()的并行测试
U3D协程Coroutine之WWW与Update()的并行测试 using System.Collections; using UnityEditor; using UnityEngine; usi ...
- Lua协程Coroutine是什么
Lua协程Coroutine是什么 协程和线程不同: 同一时刻,一个多线程程序可以用多个线程同时执行:而协程只能有一个在执行 多线程是抢占式的:而协程是非抢占式的,只有协程显示被挂起,才会被挂起 协程 ...
- python3 协程 写法_理解Python的协程(Coroutine)
由于GIL的存在,导致Python多线程性能甚至比单线程更糟. GIL: 全局解释器锁(英语:Global Interpreter Lock,缩写GIL),是计算机程序设计语言解释器用于同步线程的一种 ...
- swoole mysql 协程_swoole-orm: 基于swoole的mysql协程连接池,简单封装。实现多个协程间共用同一个协程客户端。参考thinkphp-orm...
swoole-orm 基于swoole的mysql协程连接池,简单封装. 实现多个协程间共用同一个协程客户端 感谢完善 [1]:nowbe -> 新增数据返回insert_id 版本 v0.0. ...
- IMI 基于 Swoole 开发的协程 PHP 开发框架 常驻内存、协程异步非阻塞
介绍 IMI 是基于 Swoole 开发的协程 PHP 开发框架,拥有常驻内存.协程异步非阻塞IO等优点. IMI 框架文档丰富,上手容易,致力于让开发者跟使用传统 MVC 框架一样顺手. IMI 框 ...
最新文章
- 最常用的13条mysql语句
- 为什么我的索尼电视显示服务器异常,索尼液晶电视有哪些故障 索尼电视故障代码大全【详解】...
- pmp每日三题(2022年2月18日)
- Linux平台Oracle多个实例启动说明
- lora技术在无线抄表行业应用
- strspn php,php返回在字符串中包含 charlist 参数中指定的字符数目的函数strspn()
- 教你一招轻松入门python,不收藏等于错失了一个亿!
- linux 修改用户登录密码
- 【Vue.js 3.0】不使用根标签,Error:[vue/no-multiple-template-root] The template root requires exactly one ...
- [每日一题] OCP1z0-047 :2013-07-15 drop column
- HDU1871 无题【序列处理】
- 记录一次有意思的XSS过滤绕过
- Oracle的函数大全
- 中科大EPC课程爬取
- 【技术美术图形部分】2.1 色彩空间
- 部署在服务器上的行驶证识别api接口
- 【python安装】错误——“User installations are disabled via policy on the machine”
- 决策树可视化以及数据所要的处理(查漏补缺)
- uml的九种图例分析
- linux 查找文件是否含有某个字符串
热门文章
- bzoj1385 [Baltic2000]Division expression
- 深度学习之江湖~那些大神们
- jQuery实现文本框回车键转tab键
- 语句删除数据库表中有默认字段值的字段
- 实际应用中installshield的事件处理
- 理解Java - AQS
- ElasticSearch出现Cluster state has not been recovered yet, cannot write to the [null] index的解决办法
- 在Angularjs中使用directive自定义指令实现attribute的继承
- Sql Server2005 Transact-SQL
- Boost Asio socket 非阻塞/缓冲区大小等属性设置