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

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

什么是C的等效库,可以提供相同的可扩展性和易用性?

具体来说,我需要C等价物至少以下两个function。

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

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


更新

本文比较了数字和表格

  • GNU Pth
  • Protothreads
  • PM2包裹

结果有利于Protothreads。 由于我没有使用任何其他图书馆,我很乐意听到任何使用/开发此类图书馆的人。

libMill可能就是您要搜索的内容: http ://libmill.org/

它以Go-Lang通道样式实现用户级线程。

它由ZeroMQ的创建者http://250bpm.com/的超级聪明的MartinSústrik开发。 所以它必须是好的☺

我不再对以下代码进行评论,也没有任何示例 – 这是一个作为预处理器宏实现的可移植(伪)线程库

  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)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)的ucontext ,他在POSIX 2008中删除了ucontext函数,并建议用POSIX线程替换(现在是强制性function)。