fiber.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. #include "fiber.h"
  2. #include "fcontext.h"
  3. namespace bbFiber{
  4. const int MAX_FIBERS=1024;
  5. const size_t STACK_SIZE=65536; //woho
  6. const size_t STACK_BUF_SIZE=65536;
  7. struct Fiber{
  8. Fiber *succ;
  9. int id;
  10. unsigned char *stack;
  11. bbGCFiber *gcFiber;
  12. bbDBContext *dbContext;
  13. Entry entry;
  14. fcontext_t fcontext;
  15. fcontext_t fcontext2;
  16. };
  17. Fiber *fibers;
  18. Fiber *freeFibers;
  19. Fiber *mainFiber;
  20. Fiber *currFiber;
  21. unsigned char *stackBuf,*stackEnd;
  22. unsigned char *allocStack(){
  23. if( stackBuf==stackEnd ){
  24. stackBuf=alloc_fcontext_stack( STACK_BUF_SIZE,false );
  25. stackEnd=stackBuf+STACK_BUF_SIZE;
  26. }
  27. unsigned char *p=stackBuf;
  28. stackBuf+=STACK_SIZE;
  29. return p;
  30. }
  31. void init(){
  32. if( fibers ) return;
  33. fibers=new Fiber[MAX_FIBERS];
  34. bbGCFiber *gcFibers=new bbGCFiber[MAX_FIBERS];
  35. bbDBContext *dbContexts=new bbDBContext[MAX_FIBERS];
  36. for( int i=0;i<MAX_FIBERS;++i ){
  37. fibers[i].id=i;
  38. fibers[i].succ=&fibers[i+1];
  39. fibers[i].stack=nullptr;
  40. fibers[i].gcFiber=&gcFibers[i];
  41. fibers[i].dbContext=&dbContexts[i];
  42. fibers[i].fcontext=nullptr;
  43. fibers[i].fcontext2=nullptr;
  44. }
  45. fibers[MAX_FIBERS-1].succ=nullptr;
  46. freeFibers=&fibers[1];
  47. mainFiber=&fibers[0];
  48. mainFiber->gcFiber=bbGC::currentFiber;
  49. mainFiber->dbContext=bbDB::currentContext;
  50. currFiber=mainFiber;
  51. }
  52. Fiber *getFiber( int id ){
  53. if( !fibers ) return nullptr;
  54. Fiber *fiber=&fibers[id & (MAX_FIBERS-1)];
  55. if( fiber->id==id ) return fiber;
  56. return nullptr;
  57. }
  58. Fiber *allocFiber(){
  59. if( !fibers ) init();
  60. Fiber *fiber=freeFibers;
  61. if( !fiber ) return nullptr;
  62. if( !fiber->stack ) fiber->stack=allocStack();
  63. freeFibers=fiber->succ;
  64. fiber->id+=MAX_FIBERS;
  65. return fiber;
  66. }
  67. fcontext_t freeFiber( Fiber *fiber ){
  68. fcontext_t fcontext=fiber->fcontext2;
  69. fiber->id+=MAX_FIBERS;
  70. fiber->succ=freeFibers;
  71. freeFibers=fiber;
  72. return fcontext;
  73. }
  74. void setCurrFiber( Fiber *fiber ){
  75. bbGC::currentFiber=fiber->gcFiber;
  76. bbDB::currentContext=fiber->dbContext;
  77. currFiber=fiber;
  78. }
  79. void fiberEntry( transfer_t t ){
  80. Fiber *fiber=(Fiber*)t.data;
  81. fiber->fcontext2=t.fcontext;
  82. fiber->dbContext->init();
  83. fiber->gcFiber->link();
  84. setCurrFiber( fiber );
  85. fiber->entry();
  86. fiber->gcFiber->unlink();
  87. jump_fcontext( freeFiber( fiber ),nullptr );
  88. }
  89. // ***** API *****
  90. int createFiber( Entry entry ){
  91. Fiber *fiber=allocFiber();
  92. if( !fiber ) return 0;
  93. fiber->entry=entry;
  94. fiber->fcontext=make_fcontext( fiber->stack+STACK_SIZE,STACK_SIZE,fiberEntry );
  95. return fiber->id;
  96. }
  97. void resumeFiber( int id ){
  98. Fiber *fiber=getFiber( id );
  99. if( !fiber ){
  100. bbDB::error( "Invalid fiber id" );
  101. return;
  102. }
  103. Fiber *curr=currFiber;
  104. fiber->fcontext=jump_fcontext( fiber->fcontext,fiber ).fcontext;
  105. setCurrFiber( curr );
  106. }
  107. void suspendCurrentFiber(){
  108. if( currFiber==mainFiber ){
  109. bbDB::error( "Can't suspend main fiber" );
  110. return;
  111. }
  112. Fiber *fiber=currFiber;
  113. fiber->fcontext2=jump_fcontext( fiber->fcontext2,nullptr ).fcontext;
  114. setCurrFiber( fiber );
  115. }
  116. int startFiber( bbFunction<void()> entry ){
  117. int id=createFiber( entry );
  118. if( id ) resumeFiber( id );
  119. return id;
  120. }
  121. void terminateFiber( int id ){
  122. }
  123. int getCurrentFiber(){
  124. if( fibers ) return currFiber->id;
  125. return 0;
  126. }
  127. }