[HN Gopher] Show HN: Neco - Coroutine Library for C
       ___________________________________________________________________
        
       Show HN: Neco - Coroutine Library for C
        
       Author : tidwall
       Score  : 41 points
       Date   : 2024-04-08 17:37 UTC (1 days ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | keepamovin wrote:
       | I like how your examples become progressively more comprehensive.
       | What was your thinking going into this? How did you design this
       | library? i think you wanted something this beautiful and perfect
       | to exist, am i right? Or is it also an exercise to develop your
       | own understanding? I wouldn't know where to begin with C
       | gens/coroutines. Probably I would just fallback on kernel/sys
       | calls to suspend and hack from there: yay my function is stopped;
       | yay my code has been called again. Are you using setjmp/longjmp?
        
       | plagiat0r wrote:
       | I love how simple and elegant is this to use:
       | https://github.com/tidwall/neco/blob/main/examples/echo-serv...
       | 
       | I was going to actually implement an echo server for load
       | balancer health checks with minimal memory usage, but never
       | considered doing it in C but I might just use it! Thank you so
       | much.
        
       | dingdingdang wrote:
       | Can someone help elucidate why "It's a non-goal for Neco to
       | provide a scalable multithreaded runtime, where the coroutine
       | scheduler is shared among multiple cpu cores [...]" this library
       | even makes sense then? When I use coroutines in Go it is
       | invariably in order to make use of more CPU cores when extra
       | performance needs to be extracted.
        
         | trebecks wrote:
         | the scheduler is probably simpler if coroutines can't bounce
         | between cores. you can have a single thread per core that runs
         | the scheduler to multiplex a bunch of coroutines on the single
         | thread, which lines up with the example linked in the repo to a
         | redis clone. redis runs a single thread (i think technically it
         | has some multithreading stuff now but that was the model for a
         | while) but can concurrently process a bunch of requests like
         | when 1 or more requests are blocked on blpop, a pubsub thing,
         | xread with block arg given, etc. nginx does something similar
         | with forking a process per core that runs single threaded
         | (ignore the threading for stuff that reads from disk).
        
           | tidwall wrote:
           | Also it is possible to start multiple Neco schedulers in
           | different threads, there's an example in the readme.
        
             | trebecks wrote:
             | yeah i like this model. then you can use whatever
             | synchronization junk you prefer to share state between the
             | threads, if you have any.
             | 
             | your library looks well written and clean. thanks for
             | sharing.
             | 
             | if anyone else wants to go coroutine spelunking, these were
             | interesting to me:
             | 
             | https://github.com/higan-emu/libco/tree/master
             | 
             | https://github.com/Tencent/libco
             | 
             | https://github.com/hnes/libaco
             | 
             | https://kernel.googlesource.com/pub/scm/virt/kvm/qemu-
             | kvm/+/...
             | 
             | https://tia.mat.br/posts/2012/09/29/asynchronous_i_o_in_c_w
             | i...
             | 
             | https://www.cs.uml.edu/~bill/cs516/context_paper_rse-
             | pmt.pdf
        
         | LoganDark wrote:
         | Coroutines are still very useful for multitasking even if
         | you're not sharing tasks between CPU cores. Other coroutines
         | can just execute whenever something would normally block,
         | removing the need for multiple threads in the first place.
        
         | samatman wrote:
         | Goroutines aren't coroutines. This isn't a nitpick, it's pretty
         | essential to understanding the goals and non-goals of Neco.
         | 
         | Coroutines are a control-flow primitive which allows for a lot
         | of useful things, including advancing program state while a
         | coroutine waits on a syscall, generators, iterators, producer-
         | consumer patterns with channels, and combinations of these
         | things. They generalize function calls, or structure goto, if
         | you prefer.
         | 
         | Some of these applications are glossed as concurrent,
         | particularly their use to free the thread when execution
         | blocks, but all of them are single-threaded. Goroutines are
         | preemptively scheduled, and can be relocated between threads
         | transparently. That isn't really a coroutine, which is why they
         | have a different name.
         | 
         | The README has some notes on how to use Neco coroutines in a
         | multithreaded environment. It's basically how you'd run
         | execution paths of multiple function calls on several threads,
         | because coroutines are an orthogonal concern to threads.
        
       | dkjaudyeqooe wrote:
       | These are stackful coroutines, as opposed to stackless.
       | 
       | Stackful coroutines create a new stack for each coroutine thread
       | and save and restore the appropriate registers when switching.
       | Stackless coroutines are basically normal C functions that have
       | been hacked to save their local variables between calls and use
       | gotos (or, notoriously, a switch statement) to resume from where
       | they last yielded. Both are very useful in their own way.
       | 
       | This is a great project and I'll be trying it out in my current
       | work.
        
       ___________________________________________________________________
       (page generated 2024-04-09 23:00 UTC)