https:docs.microsoft.com/en-us/windows/win32/procthread/fibers
纤程也是一个执行上下文,比如各个寄存器的值
只不过纤程是由用户层面决定调度的
线程可以被转换为纤程,也就是创建纤程上下文,这样才能进行纤程之间的切换,也就是把当前上下文保存起来去执行另一个上下文
纤程只能由纤程去调度,也就是拥有纤程上下文的执行实体把当前纤程上下文保存,然后装上另一个纤程上下文执行
假如拥有执行实体的纤程自己删自己会导致执行实体退出
纤程上下文的起始方法退出,那么执行实体就会退出,但是该纤程上下文还有没有效不太清楚,按道理讲指令指针寄存器可能已经指向了非用户代码了,就跟main方法返回了差不多
拥有执行实体的纤程上下文自己调度自己的行为未定义
当你删除一个纤程上下文的时候,该纤程的栈会直接释放,假如你的栈中存在未析构的智能指针或者未析构的对象,那么会造成资源泄露
假如你要使用DeleteFiber函数删除纤程,那么纤程方法永远不会正常退出,它的生命结束于SwitchToFiber函数的调用永远不会再返回,意思就是你调用SwitchToFiber函数把上下文切换,执行实体换上另一个上下文,然后把原先的上下文也就是纤程删了,那被删除的上下文中的SwitchToFiber函数调用肯定永远不会返回。纤程方法指的是你创建纤程时传入的那个
示例开头的代码是用来本地化错误代码的,跟主体没有关系
主要逻辑在main方法中
我把本机接口简单包装了一下,所以是通过Fiber类来进行调用
#include <iostream> #include <windows.h> std::string GetWin32ErrorMessage(DWORD errorCode) { char buffer[4096]; auto length = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, errorCode, 0, buffer, sizeof(buffer), nullptr); return std::string{ buffer, length }; } void Exit(const std::string& message, DWORD errorCode) { std::cout << message << " " << GetWin32ErrorMessage(errorCode) << std::endl; exit(errorCode); } void Exit(const std::string& message) { Exit(message, GetLastError()); } void Print() { std::cout << std::endl; } template<typename T, typename ...TS> void Print(T value, TS ...values) { std::cout << value << " "; Print(values...); } class Fiber { public: static LPVOID ConvertToFiber() { auto handle = ::ConvertThreadToFiberEx(nullptr, FIBER_FLAG_FLOAT_SWITCH); if (handle == nullptr) { Exit("Convert To Fiber Error"); } return handle; } static void ConvertToThread() { if (::ConvertFiberToThread() == 0) { Exit("Convert To Thread Error"); } } static auto GetCurrentFiber() { return ::GetCurrentFiber(); } static LPVOID Create(LPFIBER_START_ROUTINE func) { auto handle = ::CreateFiberEx(0, 0, FIBER_FLAG_FLOAT_SWITCH, func, Fiber::GetCurrentFiber()); if (handle == nullptr) { Exit("Create Fiber Error"); } return handle; } static void Switch(LPVOID fiber) { if (fiber == Fiber::GetCurrentFiber()) { Exit("Switch Fiber error"); } ::SwitchToFiber(fiber); } static void Delete(LPVOID fiber) { ::DeleteFiber(fiber); } }; int main() { auto one_fiber = Fiber::ConvertToFiber(); auto tow_fiber = Fiber::Create([](auto create_fiber) { Print("子纤程运行"); Fiber::Delete(Fiber::GetCurrentFiber()); while (true) { Fiber::Switch(create_fiber); Print("子纤程运行"); } }); Print("已经创建了子纤程,但未运行"); Fiber::Switch(tow_fiber); Print("子纤程,调度回来啦"); Fiber::Switch(tow_fiber); Print("子纤程,调度回来啦"); Fiber::Switch(tow_fiber); Print("子纤程,调度回来啦"); Fiber::Delete(tow_fiber); Fiber::ConvertToThread(); }
利用纤程与io完成端口写的一个简单的文件服务器
https://github.com/LeiKaiFeng-GoodBoy/CppHttpFileServer
原文:https://www.cnblogs.com/leikaifeng/p/14665337.html