zoukankan      html  css  js  c++  java
  • 纤程

    纤程(fiber)是一种由应用程序自己调度的轻量级线程。纤程不能被线程自动调用。一个线程可以创建任意多个纤程。如果想使用纤程,可以使用createfiber()创建,但是其处于挂起状态。即纤程创建后不能马上执行。

    一旦创建了纤程,可以通过纤程的地址在纤程之间转换,纤程本身不能完成这项工作,需要SwitchToFiber()来自己完成转换工作!

    一个纤程在以下两种情况下将暂停:1.线程调用了其他纤程;2.该纤程所在的线程用完了系统分配的时间片。

    1.LPVOID WINAPI ConvertThreadToFiber( LPVOID lpParameter);

    //参数为指向传给纤程的数据,可以通过GetFiberData()宏来获得这些数据。

    //结果成功返回纤程地址,否则返回NULL。  GetLastError()可获取错误信息。

    2. LPVOID WINAPI CreateFiber(SIZE_T dwStackSize,LPFIBER_START_ROUTINE lpStartAddress,LPVOID lpParameter);

       //参数介绍(创建纤程的大小,默认为其线程的堆栈大小;用户定义的函数,表示纤程将要执行的函数的起始地址,该函数并不立即执行,而是在其他纤程调用SwitchToFiber()并且以其为参数时才执行;传给纤程的数据,可以通过GetFiberData()宏来获得这些数据)

    3. VOID WINAPI SwitchToFiber(LPVOID lpFiber); 参数为要调用纤程的地址。

    4. GetFiberData()宏。无参,返回当前纤程数据的指针。

    5. GetCurrentFiber()宏。无参,返回当前纤程的指针。

    6. VOID WINAPI DeleteFiber( LPVOID lpFiber); //参数(要删除的纤程地址)

       //如果当前正在运行的纤程执行此函数,则系统调用ExitThread()结束线程;

       //如果正在执行的纤程被其他纤程调用,则线程将可能会不正常的终止。

    线程通常采用自杀方式,纤程通常采用他杀方式!

    以下例子分别演示了纤程的一般使用方法和执行流程;纤程与同步。

    #include <iostream>
    #include <windows.h>
    using namespace std;
    
    struct fiberData
    {
        void * pfiber1;
        void * pfiber2;
        void * pfiber3;
    };
    
    void _stdcall fiber2(void*)
    {
        cout<<"come to fiber #2"<<endl;
        int result=0;
        fiberData* p=(fiberData*)::GetFiberData();//返回当前纤程数据的指针
    
        ::SwitchToFiber(p->pfiber3);
        cout<<"come back to fiber #2"<<endl;
    
        for(int i=0;i<=100;i++)
        {
            result+=i;
        }
        ::SwitchToFiber(p->pfiber3); //切换到纤程pfiber3
        cout<<"the sum from 1 to 100 is :"<<result<<endl;
        cout<<"switch to main fiber"<<endl;
        ::SwitchToFiber(p->pfiber1); //切换到纤程pfiber1
    }
    
    void _stdcall fiber3(void *)
    {
        fiberData* p=(fiberData*)::GetFiberData();//返回当前纤程数据的指针
        cout<<"come to fiber #3 for the first time"<<endl;
        ::SwitchToFiber(p->pfiber2); //切换到纤程pfiber2
    
        cout<<"come to fiber #2 again"<<endl;
        ::SwitchToFiber(p->pfiber2); //纤程pfiber2执行
    }
    
    int main()
    {
        fiberData fd;
        cout<<"convert thread to fiber"<<endl;
        fd.pfiber1=::ConvertThreadToFiber(&fd);
        cout<<"create fiber #2"<<endl;
        fd.pfiber2=::CreateFiber(0,fiber2,&fd);
        cout<<"create fiber #3"<<endl;
        fd.pfiber3=::CreateFiber(0,fiber3,&fd);
    
        cout<<"switch to fiber #2"<<endl;
        ::SwitchToFiber(fd.pfiber2);  //在此处才真正开始执行
        cout<<"come to main fiber again"<<endl;
        return 0;
    }
    //在纤程间切换的时候,可以发现每次是接着上次未完成的执行,不是重新开始新纤程。
    #include <iostream>
    #include <windows.h>
    #include <string>
    using namespace std;
    int pubData[10];
    int curPos=0;
    
    struct fiberData
    {
        void *pMain;
        void *pRead;
        void *pWrite;
    };
    
    //读纤程的实现函数
    void CALLBACK fiberRead(PVOID lpParameter)
    {
        fiberData* p=(fiberData*)lpParameter;
        while(curPos<10)
        {
            //读数据
            printf("read the %dth number:%d
    ",curPos+1,pubData[curPos]);
            ::Sleep(100);
            ::SwitchToFiber(p->pWrite);//转到写纤程
        }
    }
    
    //写纤程的实现函数
    void CALLBACK fiberWrite(PVOID lpParameter)
    {
        fiberData* p=(fiberData*)lpParameter;
        while(curPos<10)
        {
            //向公共存储区写数据
            pubData[curPos]=(curPos+1)*10;
            printf("write the %dth number:%d
    ",curPos+1,pubData[curPos]);
            //转到读纤程
            ::SwitchToFiber(p->pRead);
            curPos++;
        }
        ::SwitchToFiber(p->pMain);//返回主线程
    }
    
    DWORD WINAPI myThread(LPVOID lpParameter)
    {
        fiberData fd;
        fd.pMain =::ConvertThreadToFiber(&fd);//将线程转换为纤程
        fd.pWrite=::CreateFiber(0,fiberWrite,&fd);
        fd.pRead=::CreateFiber(0,fiberRead,&fd);
        ::SwitchToFiber(fd.pWrite);//转到写纤程  ,K
        ::DeleteFiber(fd.pWrite);//删除写纤程
        ::DeleteFiber(fd.pRead);//删除读纤程
        cout<<"over!";
        return 1;
    }
    
    DWORD WINAPI secondThread(LPVOID lpParameter)
    {
        for(int i=0;i<10;i++)
        {
            cout<<"come the second thread!"<<endl;
            cout<<"hello from the second thread!"<<endl;
            cout<<"go out the second thread"<<endl;
            ::Sleep (100);
        }
        return 1;
    }
    
    int main()
    {
        HANDLE handle1,handle2;
        DWORD dw1,dw2;
        handle1=::CreateThread(NULL,0,myThread,NULL,0,&dw1);
        handle2=::CreateThread(NULL,0,secondThread,NULL,0,&dw2);
        ::Sleep(1000);
        return 0;
    }
  • 相关阅读:
    hw笔试题-01
    tcp
    linux schedule
    arm架构学习
    skyeye
    RTOS
    systemdump相关
    sdio
    linux kernel 多线程
    linux内核同步
  • 原文地址:https://www.cnblogs.com/hometown/p/3399428.html
Copyright © 2011-2022 走看看