Baike.dev
All toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
N

neco

> 编程语言
Open source

Concurrency library for C (coroutines)

1.4K stars0 likes0 views
WebsiteGitHub

About

Concurrency library for C (coroutines)

Neco is a C library that provides concurrency using coroutines. It's small & fast, and intended to make concurrent I/O & network programming easy. ## Features - [Coroutines](docs/API.md#basic-operations): starting, sleeping, suspending, resuming, yielding, and joining. - [Synchronization](docs/API.md#channels): channels, generators, mutexes, condition variables, and waitgroups. - Support for [deadlines and cancelation](docs/API.md#deadlines-and-cancelation). - [Posix friendly](docs/API.md#posix-wrappers) interface using file descriptors. - Additional APIs for [networking](docs/API.md#networking-utilities), [signals](docs/API.md#signals), [random data](docs/API.md#random-number-generator), [streams](docs/API.md#streams-and-buffered-io), and [buffered I/O](docs/API.md#streams-and-buffered-io). - Lightweight runtime with a fair and deterministic [scheduler](#the-scheduler). - [Fast](#fast-context-switching) user-space context switching. Uses assembly in most cases. - Stackful coroutines that are nestable, with their life times fully managed by the scheduler. - Cross-platform. Linux, Mac, FreeBSD. _(Also WebAssembly and Windows with [some limitations](#platform-notes))_. - Single file amalgamation. No dependencies. - [Test suite](tests/README.md) with 100% coverage using sanitizers and [Valgrind](https://valgrind.org). For a deeper dive, check out the [API reference](docs/API.md). It may also be worthwhile to see the [Bluebox](https://github.com/tidwall/bluebox) project for a more complete example of using Neco, including benchmarks. ## Goals - Give C programs fast single-threaded concurrency. - To use a concurrency model that resembles the simplicity of pthreads or Go. - Provide an API for concurrent networking and I/O. - Make it easy to interop with existing Posix functions. It's a non-goal for Neco to provide a scalable multithreaded runtime, where the coroutine scheduler is shared among multiple cpu cores. Or to use other concurrency models like async/await. ## Using Just drop the "neco.c" and "neco.h" files into your project. Most modern C compilers should work. ```sh cc -c neco.c ``` ## Example 1 (Start a coroutine) A coroutine is started with the [`neco_start()`](docs/API.md#neco_start) function. When `neco_start()` is called for the first time it will initialize a Neco runtime and scheduler for the current thread, and then blocks until the coroutine and all child coroutines have terminated. ```c #include #include "neco.h" void coroutine(int argc, void *argv[]) { printf("main coroutine started\n"); } int main(int argc, char *argv[]) { neco_start(coroutine, 0); return 0; } ``` ## Example 2 (Use neco_main instead of main) Optionally, [`neco_main()`](docs/API.md#neco_main) can be used in place of the standard `main()`. This is for when the entirety of your program is intended to be run from only coroutines. It [adjusts the behavior](docs/API.md#neco_main) of the program slightly to make development and error checking easier. ```c #include #include "neco.h" int neco_main(int argc, char *argv[]) { printf("main coroutine started\n"); return 0; } ``` ## Example 3 (Multiple coroutines) Here we'll start two coroutines that continuously prints "tick" every one second and "tock" every two. ```c #include #include "neco.h" void ticker(int argc, void *argv[]) { while (1) { neco_sleep(NECO_SECOND); printf("tick\n"); } } void tocker(int argc, void *argv[]) { while (1) { neco_sleep(NECO_SECOND*2); printf("tock\n"); } } int neco_main(int argc, char *argv[]) { neco_start(ticker, 0); neco_start(tocker, 0); // Keep the program alive for an hour. neco_sleep(NECO_HOUR); return 0; } ``` ## Example 4 (Coroutine arguments) A coroutine is like its own little program that accepts any number of arguments. ```c void coroutine(int argc, void *argv[]) ``` The arguments are a series of pointers passed to the coroutine. All arguments are guaranteed to be in scope when the coroutine starts and until the first `neco_` function is called. This allows you an opportunity to validate and/or copy them. ``` … ``` ## Example 5 (Channels) A [channel](docs/API.md#channels) is a mechanism for communicating between two or more coroutines. Here we'll create a second coroutine that sends the message 'ping' to the first coroutine. ``` … ``` ## Example 6 (Generators) A [generator](docs/API.md#generators) is like channel but is stricly bound to a coroutine and is intended to treat the coroutine like an iterator. ``` … ``` ## Example 7 (Connect to server) Neco provides [`neco_dial()`](docs/API.md#neco_dial) for easily connecting to server. Here we'll performing a (very simple) HTTP request which prints the homepage of the http://example.com website. ``` … ``` ## Example 8 (Create a server) Use [`neco_serve()`](docs/API.md) to quickly bind and listen on an address. Here we'll run a tiny webserver at http://127.0.0.1:8080 ``` … ``` ## Example 9 (Echo server and client) Run server with: ```sh cc neco.c echo-server.c && ./a.out ``` Run client with: ```sh cc neco.c echo-client.c && ./a.out ``` **echo-server.c** ``` … ``` **echo-client.c** ``` … ``` ## Example 10 (Suspending and resuming a coroutine) Any coroutines can suspended itself indefinetly and then be resumed by other coroutines by using [`neco_suspend()`](docs/API.md#neco_suspend) and [`neco_resume()`](docs/API.md#neco_resume). ``` … ``` ### More examples You can find more [examples here](examples). ## Platform notes Linux, Mac, and FreeBSD supports all features. Windows and WebAssembly support the core coroutine features, but have some key limitiations, mostly with working with file descriptors and networking. This is primarly because the Neco event queue works with epoll and kqueue, which are only available on Linux and Mac/BSD respectively. This means that the `neco_wait()` (which allows for a coroutine to wait for a file descriptor to be readable or writeable) is not currently available on those platforms. Other limitations include: - Windows only supports amd64. - Windows and WebAssembly use smaller default stacks of 1MB. - Windows and WebAssembly do not support guards or gaps. - Windows and WebAssembly do not support NECO_CSPRNG (Cryptographically secure pseudorandom number generator) - Windows does not support stack unwinding. Other than that, Neco works great on those platforms. Any contributions towards making Windows and WebAssembly feature complete are welcome. ## The scheduler Neco uses [sco](https://github.com/tidwall/sco), which is a fair and deterministic scheduler. This means that no coroutine takes priority over another and that all concurrent operations will reproduce in an expected order. ### Fast context switching The coroutine context switching is powered by [llco](https://github.com/tidwall/llco) and uses assembly code in most cases. On my lab machine (AMD Ryzen 9 5950X) a context switch takes about 11 nanoseconds. ### Thread local runtime There can be no more than one scheduler per thread. When the first coroutine is started using `neco_start()`, a new Neco runtime is initialized in the current thread, and each runtime has its own scheduler. Communicating between coroutines that are running in different threads will require I/O mechanisms that do not block the current schedulers, such as `pipe()`, `eventfd()` or atomics. _Pthread utilties such as `pthread_mutex_t` and `pthread_cond_t` do not work very well in coroutines._ For example, here we'll create two threads, running their own Neco schedulers. Each using pipes to communicate with the other. ``` … ``` ## License Source code is available under the MIT [License](LICENSE).

Issues· 0 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

C

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言