# libxev **Repository Path**: mirrors_floatdrop/libxev ## Basic Information - **Project Name**: libxev - **Description**: libxev is a cross-platform, high-performance event loop that provides abstractions for non-blocking IO, timers, events, and more and works on Linux (io_uring or epoll), macOS (kqueue), and Wasm + WASI. Available as both a Zig and C API. - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-10-14 - **Last Updated**: 2026-05-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # libxev libxev is a cross-platform event loop. libxev provides a unified event loop abstraction for non-blocking IO, timers, signals, events, and more that works on macOS, Windows, Linux, and WebAssembly (browser and WASI). It is written in [Zig](https://ziglang.org/) but exports a C-compatible API (which further makes it compatible with any language out there that can communicate with C APIs). **Project Status: Stable for most use cases.** libxev is in daily use by large projects such as [Ghostty](https://ghostty.org), [zml](https://github.com/zml/zml), and more. For most use cases, libxev has been shown to be stable at scale. libxev has a broad featureset and there are likely less well-used corners of the library, but for most use cases libxev is already heavily used in production environments. **Why a new event loop library?** A few reasons. One, I think Zig lacks a generalized event loop comparable to libuv in features ("generalized" being a key word here). Two, I wanted to build a library like this around the design patterns of [io_uring](https://unixism.net/loti/what_is_io_uring.html), even mimicking its style on top of other OS primitives ( [credit to this awesome blog post](https://tigerbeetle.com/blog/a-friendly-abstraction-over-iouring-and-kqueue/)). Three, I wanted an event loop library that could build to WebAssembly (both WASI and freestanding) and that didn't really fit well into the goals of API style of existing libraries without bringing in something super heavy like Emscripten. The motivation for this library primarily though is scratching my own itch! ## Features **Cross-platform.** Linux (`io_uring` and `epoll`), macOS (`kqueue`), WebAssembly + WASI (`poll_oneoff`, threaded and non-threaded runtimes). (Windows support is planned and coming soon) **[Proactor API](https://en.wikipedia.org/wiki/Proactor_pattern).** Work is submitted to the libxev event loop and the caller is notified of work _completion_, as opposed to work _readiness_. **Zero runtime allocations.** This helps make runtime performance more predictable and makes libxev well suited for embedded environments. **Timers, TCP, UDP, Files, Processes.** High-level platform-agnostic APIs for interacting with timers, TCP/UDP sockets, files, processes, and more. For platforms that don't support async IO, the file operations are automatically scheduled to a thread pool. **Generic Thread Pool (Optional).** You can create a generic thread pool, configure its resource utilization, and use this to perform custom background tasks. The thread pool is used by some backends to do non-blocking tasks that don't have reliable non-blocking APIs (such as local file operations with `kqueue`). The thread pool can be shared across multiple threads and event loops to optimize resource utilization. **Low-level and High-Level API.** The high-level API is platform-agnostic but has some opinionated behavior and limited flexibility. The high-level API is recommended but the low-level API is always an available escape hatch. The low-level API is platform-specific and provides a mechanism for libxev users to squeeze out maximum performance. The low-level API is _just enough abstraction_ above the OS interface to make it easier to use without sacrificing noticable performance. **Tree Shaking (Zig).** This is a feature of Zig, but substantially benefits libraries such as libxev. Zig will only include function calls and features that you actually use. If you don't use a particular kind of high-level watcher (such as UDP sockets), then the functionality related to that abstraction is not compiled into your final binary at all. This lets libxev support optional "nice-to-have" functionality that may be considered "bloat" in some cases, but the end user doesn't have to pay for it. **Dependency-free.** libxev has no dependencies other than the built-in OS APIs at runtime. The C library depends on libc. This makes it very easy to cross-compile. ### Roadmap There are plenty of missing features that I still want to add: * Pipe high-level API * Signal handlers * Filesystem events * Windows backend * Freestanding WebAssembly support via an external event loop (i.e. the browser) And more... ### Performance There is plenty of room for performance improvements, and I want to be fully clear that I haven't done a lot of optimization work. Still, performance is looking good. I've tried to port many of [libuv benchmarks](https://github.com/libuv/libuv) to use the libxev API. I won't post specific benchmark results until I have a better environment to run them in. As a _very broad generalization_, you shouldn't notice a slowdown using libxev compared to other major event loops. This may differ on a feature-by-feature basis, and if you can show really poor performance in an issue I'm interested in resolving it! ## Example The example below shows an identical program written in Zig and in C that uses libxev to run a single 5s timer. This is almost silly how simple it is but is meant to just convey the overall feel of the library rather than a practical use case.
| Zig | C |
| ```zig const xev = @import("xev"); pub fn main() !void { var loop = try xev.Loop.init(.{}); defer loop.deinit(); const w = try xev.Timer.init(); defer w.deinit(); // 5s timer var c: xev.Completion = undefined; w.run(&loop, &c, 5000, void, null, &timerCallback); try loop.run(.until_done); } fn timerCallback( userdata: ?*void, loop: *xev.Loop, c: *xev.Completion, result: xev.Timer.RunError!void, ) xev.CallbackAction { _ = userdata; _ = loop; _ = c; _ = result catch unreachable; return .disarm; } ``` |
```c
#include |