当前位置: 首页 > news >正文

windows C++ Fiber (协程)

协程,也叫微线程,多个协程在逻辑上是并发的,实际并发由用户控件。
在windows上引入了纤程(fiber)。
WinBase.h 中函数原型

#if(_WIN32_WINNT >= 0x0400)//
// Fiber begin
//#pragma region Application Family or OneCore Family or Games Family
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES)#define FIBER_FLAG_FLOAT_SWITCH 0x1     // context switch floating pointWINBASEAPI
VOID
WINAPI
SwitchToFiber(_In_ LPVOID lpFiber);WINBASEAPI
VOID
WINAPI
DeleteFiber(_In_ LPVOID lpFiber);#if (_WIN32_WINNT >= 0x0501)WINBASEAPI
BOOL
WINAPI
ConvertFiberToThread(VOID);#endifWINBASEAPI
_Ret_maybenull_
LPVOID
WINAPI
CreateFiberEx(_In_     SIZE_T dwStackCommitSize,_In_     SIZE_T dwStackReserveSize,_In_     DWORD dwFlags,_In_     LPFIBER_START_ROUTINE lpStartAddress,_In_opt_ LPVOID lpParameter);WINBASEAPI
_Ret_maybenull_
LPVOID
WINAPI
ConvertThreadToFiberEx(_In_opt_ LPVOID lpParameter,_In_     DWORD dwFlags);#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) */
#pragma endregion#pragma region Desktop Family or OneCore Family or Games Family
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES)WINBASEAPI
_Ret_maybenull_
LPVOID
WINAPI
CreateFiber(_In_     SIZE_T dwStackSize,_In_     LPFIBER_START_ROUTINE lpStartAddress,_In_opt_ LPVOID lpParameter);WINBASEAPI
_Ret_maybenull_
LPVOID
WINAPI
ConvertThreadToFiber(_In_opt_ LPVOID lpParameter);#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) */
#pragma endregion//
// Fiber end
//

一个简单的例子

#include <iostream>
#include <Windows.h>LPVOID mainFiber,workFiber;int i;void fiberProc(LPVOID lpFiberParameter)
{for(i = 0;i < 10; ++i){SwitchToFiber(mainFiber);}
}int main(int argc,char** argv,char** env)
{mainFiber = ConvertThreadToFiber(NULL);workFiber = CreateFiber(1024,fiberProc,NULL);SwitchToFiber(workFiber);std::cout << i << std::endl;SwitchToFiber(workFiber);std::cout << i << std::endl;DeleteFiber(workFiber);ConvertFiberToThread();return 0;}

windows 上Fiber的调度需要用户自己控制
简单做一个协程调度

#include <iostream>
#include <Windows.h>
#include <list>
#include <functional>using co_proc = std::function<void(void*)>;void __co_proc(LPVOID lpParam);static int ids = 0;class scheduler;
class corountine
{
public:co_proc proc_;void* param_;corountine(co_proc proc,void* param):proc_(proc), param_(param),isfinished(false),id(++ids){this->fiber = CreateFiber(1024,__co_proc,this);}virtual ~corountine(){DeleteFiber(this->fiber);}LPVOID fiber;bool isfinished;int id;scheduler* sch;
};class scheduler
{std::list<corountine*> cos_;
public:scheduler(){mainFiber = ConvertThreadToFiber(NULL);}virtual ~scheduler(){ConvertFiberToThread();}void push_corountine(corountine* co){co->sch = this;cos_.push_back(co);}void run(){while(!cos_.empty()) {auto* co = cos_.front();cos_.erase(cos_.begin());if (!co->isfinished) {SwitchToFiber(co->fiber);}if (!co->isfinished) {cos_.push_back(co);} else {delete co;}}}void yield(){SwitchToFiber(mainFiber);}LPVOID mainFiber;};void __co_proc(LPVOID lpParam)
{corountine* co = (corountine*)lpParam;co->isfinished = false;co->proc_(co->param_);co->isfinished = true;SwitchToFiber(co->sch->mainFiber); // 一定要加上这句,不然主线程会结束
}int main(int argc,char** argv,char** env)
{scheduler sch;sch.push_corountine(new corountine([&](void* p){for (int i = 0;i < 7; ++i){std::cout << "i:"<<i<<std::endl;sch.yield();}},nullptr));sch.push_corountine(new corountine([&](void* p){for (int j = 0;j < 4; ++j){std::cout << "j:"<<j<<std::endl;sch.yield();}},nullptr));sch.run();return 0;}
http://www.lryc.cn/news/532559.html

相关文章:

  • 游戏引擎学习第89天
  • 2025新鲜出炉--前端面试题(一)
  • 教程 | i.MX RT1180 ECAT_digital_io DEMO 搭建(一)
  • Pyecharts系列课程04——折线图/面积图(Line)
  • 变压器-000000
  • 凝思60重置密码
  • linux——网络计算机{序列化及反序列化(JSON)(ifdef的用法)}
  • 【教程】docker升级镜像
  • 迅为RK3568开发板篇OpenHarmony实操HDF驱动控制LED-编写应用APP
  • python代码
  • React 打印插件 -- react-to-print
  • 探索C语言简易计算器程序的实现与优化
  • 深入了解 MySQL:从基础到高级特性
  • OSPF基础(1):工作过程、状态机、更新
  • 工业相机如何获得更好的图像色彩
  • 使用requestAnimationFrame减少浏览器重绘
  • Mac 终端命令大全
  • 如何使用deepseek开发一个翻译API
  • vue如何解决跨域
  • 红包雨项目前端部分
  • 新版AndroidStudio 修改 jdk版本
  • 【golang学习之旅】使用VScode安装配置Go开发环境
  • langchain教程-2.prompt
  • GGML、GGUF、GPTQ 都是啥?
  • C++ 原码、反码、补码和位操作符
  • idea中git版本回退
  • 【PostgreSQL内核学习 —— (WindowAgg(三))】
  • redis教程
  • Python aiortc API
  • Transaction rolled back because it has been marked as rollback-only问题解决