纤程

纤程(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\n",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\n",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;
}

 

posted @ 2013-10-31 15:32  hometown  阅读(1518)  评论(0编辑  收藏  举报