Which green threads libraries are available for C that can match the performance and ease of use of Haskell's green threads? [closed]

两盒软妹~` 提交于 2019-12-03 03:43:56

问题


I am well used to relying on GHC's forkIO for portable lightweight threads when programming in Haskell.

What are equivalent libraries for C that can provide the same scalibility and ease of use?

Specifically I need C-equivalents of at least the following two functions.

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

I assume for my application, it would be enough if threads only switched on blocking operations rather than being forcefully suspended because all threads block highly frequently for network IO and I only use the splice system call to ask the Linux kernel to push data around between sockets.


Update

This paper has figures and tables comparing

  • GNU Pth
  • Protothreads
  • PM2 Parcel

with results favoring Protothreads. As I have not used any and there may also be other libraries, I would love to hear from anyone who has used / developed such libraries.


回答1:


libMill is probably what you're searching for: http://libmill.org/

It implements user level threads in the Go-Lang channel style.

And it's being developed by the super smart Martin Sústrik, creator of ZeroMQ http://250bpm.com/. So it must be good ☺




回答2:


I no longer have the commenting for the following code, nor any examples - this is a portable ( pseudo ) thread library implemented as pre processor macros

     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



回答3:


Use POSIX threads. They are "green" on any modern implementation, not in the sense of "Green Threads", but in the sense of being lightweight and efficient. There is no portable way to roll your own threads on top of plain C or POSIX minus threads. As OP mentioned, there are some libraries implementing green-threads/co-routines in non-portable ways (often despite claiming portability).

The closest-to-portable approach is using makecontext/swapcontext, and unfortunately this cannot perform well because it has to make syscalls to save/restore the signal mask on each switch between "threads". This makes switching between "green" threads more expensive than a context switch between kernel-level threads on a "real" POSIX threads implementation, and basically negates any claimed benefit of "green threads".

Non-portable approaches that don't care about the signal mask could use machine-specific asm to do the context switches entirely in userspace, and in theory perform better than kernel-level threads, but performance would again fly out the window as soon as you introduce IO, since a thread that's about to perform IO would have to first do expensive tests to check if the operation will block, and if so, turn over control to a different thread.

I maintain my position that "green threads" are an idea whose time is long past. This also seems to be the position of the Austin Group (responsible for POSIX), who removed the ucontext functions in POSIX 2008 and recommended replacement with POSIX threads (which are now a mandatory feature).



来源:https://stackoverflow.com/questions/14368391/which-green-threads-libraries-are-available-for-c-that-can-match-the-performance

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!