一个非常简单,但是实用的协程实现,使用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)实现相关推荐

  1. 并发编程协程(Coroutine)之Gevent

    并发编程协程之Gevent Gevent官网文档地址:http://www.gevent.org/contents.html 基本概念 我们通常所说的协程Coroutine其实是corporate r ...

  2. qemu核心机制分析-协程coroutine

    关于协程coroutine前面的文章已经介绍过了,本文总结对qemu中coroutine机制的分析,qemu 协程coroutine基于:setcontext函数族以及函数间跳转函数siglongjm ...

  3. c++ 协程_Python3 协程(coroutine)介绍

    本文首发于 at7h 的个人博客. 目前 Python 语言的协程从实现来说可分为两类: 一种是基于传统生成器的协程,叫做 generator-based coroutines,通过包装 genera ...

  4. c++ 协程_理解Python协程(Coroutine)

    由于GIL的存在,导致Python多线程性能甚至比单线程更糟. GIL: 全局解释器锁(英语:Global Interpreter Lock,缩写GIL),是计算机程序设计语言解释器用于同步线程的一种 ...

  5. Unity 协程Coroutine综合测试

    Unity 协程Coroutine综合测试 1 using UnityEngine; 2 using System.Collections; 3 using System.Text; 4 5 publ ...

  6. U3D协程Coroutine之WWW与Update()的并行测试

    U3D协程Coroutine之WWW与Update()的并行测试 using System.Collections; using UnityEditor; using UnityEngine; usi ...

  7. Lua协程Coroutine是什么

    Lua协程Coroutine是什么 协程和线程不同: 同一时刻,一个多线程程序可以用多个线程同时执行:而协程只能有一个在执行 多线程是抢占式的:而协程是非抢占式的,只有协程显示被挂起,才会被挂起 协程 ...

  8. python3 协程 写法_理解Python的协程(Coroutine)

    由于GIL的存在,导致Python多线程性能甚至比单线程更糟. GIL: 全局解释器锁(英语:Global Interpreter Lock,缩写GIL),是计算机程序设计语言解释器用于同步线程的一种 ...

  9. swoole mysql 协程_swoole-orm: 基于swoole的mysql协程连接池,简单封装。实现多个协程间共用同一个协程客户端。参考thinkphp-orm...

    swoole-orm 基于swoole的mysql协程连接池,简单封装. 实现多个协程间共用同一个协程客户端 感谢完善 [1]:nowbe -> 新增数据返回insert_id 版本 v0.0. ...

  10. IMI 基于 Swoole 开发的协程 PHP 开发框架 常驻内存、协程异步非阻塞

    介绍 IMI 是基于 Swoole 开发的协程 PHP 开发框架,拥有常驻内存.协程异步非阻塞IO等优点. IMI 框架文档丰富,上手容易,致力于让开发者跟使用传统 MVC 框架一样顺手. IMI 框 ...

最新文章

  1. 最常用的13条mysql语句
  2. 为什么我的索尼电视显示服务器异常,索尼液晶电视有哪些故障 索尼电视故障代码大全【详解】...
  3. pmp每日三题(2022年2月18日)
  4. Linux平台Oracle多个实例启动说明
  5. lora技术在无线抄表行业应用
  6. strspn php,php返回在字符串中包含 charlist 参数中指定的字符数目的函数strspn()
  7. 教你一招轻松入门python,不收藏等于错失了一个亿!
  8. linux 修改用户登录密码
  9. 【Vue.js 3.0】不使用根标签,Error:[vue/no-multiple-template-root] The template root requires exactly one ...
  10. [每日一题] OCP1z0-047 :2013-07-15 drop column
  11. HDU1871 无题【序列处理】
  12. 记录一次有意思的XSS过滤绕过
  13. Oracle的函数大全
  14. 中科大EPC课程爬取
  15. 【技术美术图形部分】2.1 色彩空间
  16. 部署在服务器上的行驶证识别api接口
  17. 【python安装】错误——“User installations are disabled via policy on the machine”
  18. 决策树可视化以及数据所要的处理(查漏补缺)
  19. uml的九种图例分析
  20. linux 查找文件是否含有某个字符串

热门文章

  1. bzoj1385 [Baltic2000]Division expression
  2. 深度学习之江湖~那些大神们
  3. jQuery实现文本框回车键转tab键
  4. 语句删除数据库表中有默认字段值的字段
  5. 实际应用中installshield的事件处理
  6. 理解Java - AQS
  7. ElasticSearch出现Cluster state has not been recovered yet, cannot write to the [null] index的解决办法
  8. 在Angularjs中使用directive自定义指令实现attribute的继承
  9. Sql Server2005 Transact-SQL
  10. Boost Asio socket 非阻塞/缓冲区大小等属性设置