纤程(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; }