哪些绿色线程库可用于 C 语言,可以与 Haskell 绿色线程的性能和易用性相匹配?



我很习惯在Haskell中编程时依赖GHC的forkIO来实现可移植的轻量级线程。

C语言中有哪些同等的库可以提供同样的可伸缩性和易用性?

我特别需要至少下列两个函数的c -等价。

forkIO     :: IO () -> IO ThreadId
killThread ::             ThreadId -> IO ()

我假设对于我的应用程序,如果线程只切换阻塞操作而不是强制挂起就足够了,因为所有线程都频繁阻塞网络IO,并且我只使用splice系统调用来要求Linux内核在套接字之间推送数据。


文中有图表比较

    GNU甲状旁腺素
  • Protothreads
  • PM2包裹

的结果有利于原线程。由于我没有使用过任何库,而且可能还有其他库,我希望听到任何使用或开发过此类库的人的消息。

libMill可能是您正在搜索的:http://libmill.org/

它实现了Go-Lang通道风格的用户级线程。

它是由超级聪明的Martin Sústrik, ZeroMQ的创造者http://250bpm.com/开发的。所以一定很好☺

我不再有以下代码的注释,也没有任何示例-这是一个可移植的(伪)线程库,实现为预处理器宏

     typedef struct
     {
     unsigned int magic;
     unsigned short ctx;
     unsigned char is_destroyed;
     }
     _run;
     typedef struct
     {
     unsigned int magic;
     unsigned int cnt;
     }
     _sem;

     #define aa_RUNNER_WAITING             0
     #define aa_RUNNER_YIELDED             1
     #define aa_RUNNER_EXITED              2
     #define aa_RUNNER_ENDED               3
     #define aaRunnerCreate(rp)            (rp)->magic='runr'; (rp)->ctx=0; (rp)->is_destroyed=NO
     #define aaRunnerDestroy(rp)           (rp)->is_destroyed=YES
     #define aaRunnerThread(args)          C args
     #define aaRunnerBegin(rp)             { C yflag=YES; if(yflag) {}  switch((rp)->ctx) { case 0:
     #define aaRunnerEnd(rp)               } yflag=NO; if(yflag) {}  aaRunnerCreate(rp); return aa_RUNNER_ENDED; }
     #define aaRunnerWaitUntil(rp,condx)   do  { (rp)->ctx=__LINE__; case __LINE__: if(!(condx))  { return aa_RUNNER_WAITING;  }  } while(0)
     #define aaRunnerWaitWhile(rp,condi)   aaRunnerWaitUntil((rp),!(condi))
     #define aaRunnerWaitThread(rp,thr)    aaRunnerWaitWhile((rp),aaRunnerSchedule(thr))
     #define aaRunnerWaitSpawn(rp,chl,thr) do { aaRunnerCreate((chl));  aaRunnerWaitThread((rp),(thr)); } while(0)
     #define aaRunnerRestart(rp)           do { aaRunnerCreate(rp); return aa_RUNNER_WAITING; } while(0)
     #define aaRunnerExit(rp)              do { aaRunnerCreate(rp); (rp)->magic=0; return aa_RUNNER_EXITED;  } while(0)
     #define aaRunnerSchedule(f)           ((f)<aa_RUNNER_EXITED)
     #define aaRunnerYield(rp)             do { yflag=NO; (rp)->ctx=__LINE__; case __LINE__: if(!yflag||!((rp)->is_destroyed))  { return aa_RUNNER_YIELDED;  }  } while(0)
     #define aaRunnerYieldUntil(rp,condi)  do { yflag=NO; (rp)->ctx=__LINE__; case __LINE__: if(!yflag||!(condi)) { return aa_RUNNER_YIELDED;   }   } while(0)
     #define aaRunnerSemInit(sp,c)         (sp)->magic='runs'; (sp)->cnt=c
     #define aaRunnerSemWait(rp,sp)        do { aaRunnerWaitUntil(rp,(sp)->cnt>0); --(sp)->cnt;  } while(0)
     #define aaRunnerSemSignal(rp,sp)      ++(sp)->cnt

使用POSIX线程。它们在任何现代实现中都是"绿色的",不是在"绿色线程"的意义上,而是在轻量级和高效的意义上。没有一种可移植的方法可以在纯C或POSIX减线程之上滚动自己的线程。正如OP所提到的,有一些库以不可移植的方式实现绿色线程/协同例程(通常尽管声称可移植性)。

最接近可移植的方法是使用makecontext/swapcontext,不幸的是,这不能很好地执行,因为它必须在"线程"之间的每个开关上进行系统调用来保存/恢复信号掩码。这使得在"绿色"线程之间的切换比在"真正的"POSIX线程实现上的内核级线程之间的上下文切换更昂贵,并且基本上否定了所谓的"绿色线程"的任何好处。

不关心信号掩码的不可移植方法可以使用特定于机器的asm完全在用户空间中进行上下文切换,理论上比内核级线程性能更好,但是一旦引入IO,性能就会再次飞出窗口,因为即将执行IO的线程必须首先进行昂贵的测试来检查操作是否会阻塞,如果是,将控制权移交给另一个线程。

我坚持我的立场,"绿线"是一个早已过时的想法。这似乎也是Austin Group(负责POSIX)的立场,他们在POSIX 2008中删除了ucontext函数,并建议用POSIX线程替换(这现在是一个强制功能)。

相关内容

  • 没有找到相关文章

最新更新