from Hacker News

Show HN: Neco – Coroutine Library for C

by tidwall on 4/8/24, 5:37 PM with 36 comments

  • by dkjaudyeqooe on 4/9/24, 10:53 PM

    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.

  • by plagiat0r on 4/8/24, 6:15 PM

    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.

  • by keepamovin on 4/8/24, 5:55 PM

    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?
  • by andrekandre on 4/9/24, 11:30 PM

      > neco_chan *messages = argv[0];
    
    neco_chan → neko chan → kitty cat (in japanese)... coincidence? ^_^
  • by dingdingdang on 4/9/24, 9:00 PM

    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.
  • by jonhohle on 4/10/24, 1:30 AM

    I’ve used libaco with a lot of success in the past (mixing uv, curl, and zlib in a way that made the zlib loop easier to manage (since it looked like a normal read, decompress loop with all context stack local).

    Any notes about why I would try Neco in the future?

  • by anfilt on 4/10/24, 9:52 AM

    It's a little lower level than what you have, but you may find somethings interesting here: https://github.com/Keith-Cancel/Bunki
  • by nialv7 on 4/9/24, 11:55 PM

    These are cooperatively scheduled green threads...

    I feel the word "coroutine" is slowly losing its original meaning, similar to what happened to "lambda".

  • by comex on 4/10/24, 3:58 AM

    How does it work on WebAssembly, where there's no native support for stack switching? Does it rely on Emscripten's Asyncify transformation?
  • by Karellen on 4/10/24, 8:45 AM

    In "Example 4", I don't understand where the "arg2" in `free(arg2)` is coming from?
  • by burntcaramel on 4/9/24, 11:24 PM

    Can someone explain how this works please? How does it prevent this from saturating the CPU?

        while (1) {
            neco_sleep(NECO_SECOND*2);
            printf("tock\n");
        }