您现在的位置是:首页 >学无止境 >windows C++ Fiber (协程)网站首页学无止境

windows C++ Fiber (协程)

tadus_zeng 2025-02-10 10:02:31
简介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 point

WINBASEAPI
VOID
WINAPI
SwitchToFiber(
    _In_ LPVOID lpFiber
    );

WINBASEAPI
VOID
WINAPI
DeleteFiber(
    _In_ LPVOID lpFiber
    );

#if (_WIN32_WINNT >= 0x0501)

WINBASEAPI
BOOL
WINAPI
ConvertFiberToThread(
    VOID
    );

#endif

WINBASEAPI
_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;

}

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。